Add initial FnixLib development implementation
This commit is contained in:
commit
84742ae38e
33 files changed
+3340
No files matched your search
@@ -0,0 +1,45 @@
|
||||
/*
|
||||
* FnixLib - lienzo (búfer de píxeles en memoria).
|
||||
*
|
||||
* Un FnixCanvas es la superficie sobre la que dibuja el renderizador 2D por
|
||||
* software. Cada ventana tiene uno (fnix_window_canvas), pero también se
|
||||
* pueden crear lienzos independientes, por ejemplo para pruebas sin pantalla.
|
||||
*
|
||||
* Formato de píxel: uint32_t 0x00RRGGBB, filas consecutivas sin relleno,
|
||||
* origen (0,0) arriba a la izquierda.
|
||||
*/
|
||||
#ifndef FNIX_CANVAS_H
|
||||
#define FNIX_CANVAS_H
|
||||
|
||||
#include "fnix/types.h"
|
||||
|
||||
FNIX_BEGIN_DECLS
|
||||
|
||||
/* Lado máximo de un lienzo, en píxeles. */
|
||||
#define FNIX_CANVAS_MAX_SIZE 16384
|
||||
|
||||
/* Crea un lienzo negro de width x height. Devuelve NULL si el tamaño no está
|
||||
* entre 1 y FNIX_CANVAS_MAX_SIZE o si falta memoria (ver fnix_last_error). */
|
||||
FnixCanvas *fnix_canvas_create(int width, int height);
|
||||
|
||||
/* Libera el lienzo. Acepta NULL. Si era el destino de dibujo del hilo actual,
|
||||
* el destino pasa a ser NULL. */
|
||||
void fnix_canvas_destroy(FnixCanvas *canvas);
|
||||
|
||||
int fnix_canvas_width(const FnixCanvas *canvas);
|
||||
int fnix_canvas_height(const FnixCanvas *canvas);
|
||||
|
||||
/* Acceso de solo lectura a los píxeles (0x00RRGGBB). NULL si canvas es NULL. */
|
||||
const uint32_t *fnix_canvas_pixels(const FnixCanvas *canvas);
|
||||
|
||||
/* Color del píxel (x, y) con alfa 255. Fuera del lienzo devuelve FNIX_TRANSPARENT. */
|
||||
FnixColor fnix_canvas_get_pixel(const FnixCanvas *canvas, int x, int y);
|
||||
|
||||
/* Lienzo sobre el que dibujan las funciones fnix_draw_*. Es un valor por hilo.
|
||||
* fnix_begin_frame() lo establece al lienzo de la ventana. */
|
||||
void fnix_set_target(FnixCanvas *canvas);
|
||||
FnixCanvas *fnix_get_target(void);
|
||||
|
||||
FNIX_END_DECLS
|
||||
|
||||
#endif /* FNIX_CANVAS_H */
|
||||
@@ -0,0 +1,47 @@
|
||||
/*
|
||||
* FnixLib - dibujo 2D por software.
|
||||
*
|
||||
* Todas las funciones dibujan sobre el lienzo de destino (fnix_get_target()).
|
||||
* Sin destino no hacen nada y dejan un error en fnix_last_error().
|
||||
*
|
||||
* Reglas comunes:
|
||||
* - Se recorta al lienzo: dibujar parcial o totalmente fuera es seguro.
|
||||
* - Color con alfa 255 reemplaza el píxel; alfa 0 no dibuja; los valores
|
||||
* intermedios se mezclan con el fondo (alfa "source-over").
|
||||
* - Cada píxel se modifica como máximo una vez por llamada, así que la mezcla
|
||||
* con alfa nunca se aplica dos veces sobre el mismo píxel.
|
||||
* - Coordenadas, anchos, altos y radios deben estar en [-2^28, 2^28]; fuera
|
||||
* de ese rango no se dibuja nada y se registra un error.
|
||||
*/
|
||||
#ifndef FNIX_DRAW2D_H
|
||||
#define FNIX_DRAW2D_H
|
||||
|
||||
#include "fnix/types.h"
|
||||
|
||||
FNIX_BEGIN_DECLS
|
||||
|
||||
/* Rellena todo el lienzo. Ignora el alfa del color (escribe color opaco). */
|
||||
void fnix_clear(FnixColor color);
|
||||
|
||||
void fnix_draw_pixel(int x, int y, FnixColor color);
|
||||
|
||||
/* Línea de 1 píxel de grosor; incluye ambos extremos. */
|
||||
void fnix_draw_line(int x_start, int y_start, int x_end, int y_end,
|
||||
FnixColor color);
|
||||
|
||||
/* Rectángulo con esquina superior izquierda (x, y). width o height <= 0
|
||||
* no dibujan nada. */
|
||||
void fnix_draw_rect(int x, int y, int width, int height, FnixColor color);
|
||||
void fnix_draw_rect_outline(int x, int y, int width, int height,
|
||||
FnixColor color);
|
||||
|
||||
/* Círculo de centro (cx, cy). Un píxel (dx, dy) pertenece al disco si
|
||||
* dx*dx + dy*dy <= radius*radius + radius. radius 0 dibuja un píxel;
|
||||
* radius < 0 no dibuja nada. El contorno es el disco de radio `radius`
|
||||
* menos el de radio `radius - 1` (1 píxel de grosor). */
|
||||
void fnix_draw_circle(int cx, int cy, int radius, FnixColor color);
|
||||
void fnix_draw_circle_outline(int cx, int cy, int radius, FnixColor color);
|
||||
|
||||
FNIX_END_DECLS
|
||||
|
||||
#endif /* FNIX_DRAW2D_H */
|
||||
@@ -0,0 +1,42 @@
|
||||
/*
|
||||
* FnixLib - manejo de errores.
|
||||
*
|
||||
* Convención general de la API:
|
||||
* - Las funciones que crean un objeto devuelven un puntero; NULL indica fallo.
|
||||
* - Las funciones de consulta no fallan: con un puntero NULL o un argumento
|
||||
* fuera de rango devuelven 0 / false.
|
||||
* - Cuando algo falla, FnixLib guarda un código y un mensaje legibles
|
||||
* (por hilo), que se consultan con fnix_last_error_code() y
|
||||
* fnix_last_error(). Un éxito NO borra el último error (como errno).
|
||||
*/
|
||||
#ifndef FNIX_ERRORS_H
|
||||
#define FNIX_ERRORS_H
|
||||
|
||||
#include "fnix/types.h"
|
||||
|
||||
FNIX_BEGIN_DECLS
|
||||
|
||||
typedef enum FnixError {
|
||||
FNIX_OK = 0,
|
||||
FNIX_ERROR_INVALID_ARGUMENT, /* argumento nulo o fuera de rango */
|
||||
FNIX_ERROR_OUT_OF_MEMORY, /* no se pudo reservar memoria */
|
||||
FNIX_ERROR_PLATFORM, /* fallo del sistema (pantalla, ventana) */
|
||||
FNIX_ERROR_UNSUPPORTED /* el sistema no ofrece lo que se necesita */
|
||||
} FnixError;
|
||||
|
||||
/* Descripción corta y fija de un código. Nunca devuelve NULL. */
|
||||
const char *fnix_error_string(FnixError error);
|
||||
|
||||
/* Código del último error ocurrido en este hilo (FNIX_OK si no hubo ninguno). */
|
||||
FnixError fnix_last_error_code(void);
|
||||
|
||||
/* Mensaje detallado del último error. Nunca devuelve NULL; es "" si no hubo
|
||||
* errores. El puntero es válido hasta el siguiente error en este hilo. */
|
||||
const char *fnix_last_error(void);
|
||||
|
||||
/* Olvida el último error de este hilo. */
|
||||
void fnix_clear_error(void);
|
||||
|
||||
FNIX_END_DECLS
|
||||
|
||||
#endif /* FNIX_ERRORS_H */
|
||||
@@ -0,0 +1,45 @@
|
||||
/*
|
||||
* FnixLib - cola de eventos.
|
||||
*
|
||||
* Además de las consultas de estado de input.h, cada ventana guarda los
|
||||
* eventos recibidos en una cola que el programa puede vaciar con
|
||||
* fnix_window_poll_event(). La cola conserva como máximo los 256 eventos más
|
||||
* recientes: si el programa no la consulta, los más antiguos se descartan.
|
||||
*/
|
||||
#ifndef FNIX_EVENTS_H
|
||||
#define FNIX_EVENTS_H
|
||||
|
||||
#include "fnix/input.h"
|
||||
#include "fnix/types.h"
|
||||
|
||||
FNIX_BEGIN_DECLS
|
||||
|
||||
typedef enum FnixEventType {
|
||||
FNIX_EVENT_NONE = 0,
|
||||
FNIX_EVENT_WINDOW_CLOSE, /* el usuario pidió cerrar la ventana */
|
||||
FNIX_EVENT_FOCUS_GAINED,
|
||||
FNIX_EVENT_FOCUS_LOST,
|
||||
FNIX_EVENT_KEY_DOWN, /* usa key y repeat */
|
||||
FNIX_EVENT_KEY_UP, /* usa key */
|
||||
FNIX_EVENT_MOUSE_BUTTON_DOWN, /* usa button, x, y */
|
||||
FNIX_EVENT_MOUSE_BUTTON_UP, /* usa button, x, y */
|
||||
FNIX_EVENT_MOUSE_MOVE, /* usa x, y */
|
||||
FNIX_EVENT_MOUSE_WHEEL /* usa wheel, x, y */
|
||||
} FnixEventType;
|
||||
|
||||
/* Solo son significativos los campos indicados para cada tipo; el resto vale 0. */
|
||||
typedef struct FnixEvent {
|
||||
FnixEventType type;
|
||||
FnixKey key;
|
||||
bool repeat; /* KEY_DOWN generado por autorepeat */
|
||||
FnixMouseButton button;
|
||||
int x, y;
|
||||
int wheel; /* +1 arriba, -1 abajo */
|
||||
} FnixEvent;
|
||||
|
||||
/* Saca el evento más antiguo de la cola. Devuelve false si está vacía. */
|
||||
bool fnix_window_poll_event(FnixWindow *window, FnixEvent *event);
|
||||
|
||||
FNIX_END_DECLS
|
||||
|
||||
#endif /* FNIX_EVENTS_H */
|
||||
@@ -0,0 +1,21 @@
|
||||
/*
|
||||
* FnixLib - cabecera general: incluye toda la API pública.
|
||||
*/
|
||||
#ifndef FNIX_FNIX_H
|
||||
#define FNIX_FNIX_H
|
||||
|
||||
#define FNIX_VERSION_MAJOR 0
|
||||
#define FNIX_VERSION_MINOR 1
|
||||
#define FNIX_VERSION_PATCH 0
|
||||
#define FNIX_VERSION_STRING "0.1.0"
|
||||
|
||||
#include "fnix/canvas.h"
|
||||
#include "fnix/draw2d.h"
|
||||
#include "fnix/errors.h"
|
||||
#include "fnix/events.h"
|
||||
#include "fnix/input.h"
|
||||
#include "fnix/time.h"
|
||||
#include "fnix/types.h"
|
||||
#include "fnix/window.h"
|
||||
|
||||
#endif /* FNIX_FNIX_H */
|
||||
@@ -0,0 +1,72 @@
|
||||
/*
|
||||
* FnixLib - estado del teclado y del ratón.
|
||||
*
|
||||
* Las consultas se refieren al estado tras el último fnix_begin_frame():
|
||||
* - down: la tecla/botón está mantenida ahora mismo.
|
||||
* - pressed: pasó de suelta a pulsada en este fotograma (el autorepeat del
|
||||
* teclado NO la vuelve a activar).
|
||||
* - released: pasó de pulsada a suelta en este fotograma. También se activa
|
||||
* para todo lo que estaba pulsado cuando la ventana pierde el foco.
|
||||
*
|
||||
* Las teclas se identifican por el símbolo que produce cada una SIN modificadores
|
||||
* en la distribución de teclado activa: con una distribución no QWERTY, la tecla
|
||||
* física que antes era "A" puede cambiar de identificador.
|
||||
*
|
||||
* Todas las funciones aceptan window == NULL o valores inválidos y devuelven 0/false.
|
||||
*/
|
||||
#ifndef FNIX_INPUT_H
|
||||
#define FNIX_INPUT_H
|
||||
|
||||
#include "fnix/types.h"
|
||||
|
||||
FNIX_BEGIN_DECLS
|
||||
|
||||
typedef enum FnixKey {
|
||||
FNIX_KEY_UNKNOWN = 0,
|
||||
/* Las letras, los dígitos y F1..F12 son contiguos: no reordenar. */
|
||||
FNIX_KEY_A, FNIX_KEY_B, FNIX_KEY_C, FNIX_KEY_D, FNIX_KEY_E, FNIX_KEY_F,
|
||||
FNIX_KEY_G, FNIX_KEY_H, FNIX_KEY_I, FNIX_KEY_J, FNIX_KEY_K, FNIX_KEY_L,
|
||||
FNIX_KEY_M, FNIX_KEY_N, FNIX_KEY_O, FNIX_KEY_P, FNIX_KEY_Q, FNIX_KEY_R,
|
||||
FNIX_KEY_S, FNIX_KEY_T, FNIX_KEY_U, FNIX_KEY_V, FNIX_KEY_W, FNIX_KEY_X,
|
||||
FNIX_KEY_Y, FNIX_KEY_Z,
|
||||
FNIX_KEY_0, FNIX_KEY_1, FNIX_KEY_2, FNIX_KEY_3, FNIX_KEY_4,
|
||||
FNIX_KEY_5, FNIX_KEY_6, FNIX_KEY_7, FNIX_KEY_8, FNIX_KEY_9,
|
||||
FNIX_KEY_F1, FNIX_KEY_F2, FNIX_KEY_F3, FNIX_KEY_F4, FNIX_KEY_F5,
|
||||
FNIX_KEY_F6, FNIX_KEY_F7, FNIX_KEY_F8, FNIX_KEY_F9, FNIX_KEY_F10,
|
||||
FNIX_KEY_F11, FNIX_KEY_F12,
|
||||
FNIX_KEY_SPACE, FNIX_KEY_ENTER, FNIX_KEY_ESCAPE, FNIX_KEY_TAB,
|
||||
FNIX_KEY_BACKSPACE,
|
||||
FNIX_KEY_LEFT, FNIX_KEY_RIGHT, FNIX_KEY_UP, FNIX_KEY_DOWN,
|
||||
FNIX_KEY_LEFT_SHIFT, FNIX_KEY_RIGHT_SHIFT,
|
||||
FNIX_KEY_LEFT_CTRL, FNIX_KEY_RIGHT_CTRL,
|
||||
FNIX_KEY_LEFT_ALT, FNIX_KEY_RIGHT_ALT,
|
||||
FNIX_KEY_COUNT
|
||||
} FnixKey;
|
||||
|
||||
typedef enum FnixMouseButton {
|
||||
FNIX_MOUSE_LEFT = 0,
|
||||
FNIX_MOUSE_MIDDLE,
|
||||
FNIX_MOUSE_RIGHT,
|
||||
FNIX_MOUSE_BUTTON_COUNT
|
||||
} FnixMouseButton;
|
||||
|
||||
bool fnix_key_down(const FnixWindow *window, FnixKey key);
|
||||
bool fnix_key_pressed(const FnixWindow *window, FnixKey key);
|
||||
bool fnix_key_released(const FnixWindow *window, FnixKey key);
|
||||
|
||||
bool fnix_mouse_down(const FnixWindow *window, FnixMouseButton button);
|
||||
bool fnix_mouse_pressed(const FnixWindow *window, FnixMouseButton button);
|
||||
bool fnix_mouse_released(const FnixWindow *window, FnixMouseButton button);
|
||||
|
||||
/* Posición del cursor en píxeles de la ventana (origen arriba a la izquierda).
|
||||
* Puede quedar fuera de la ventana mientras se arrastra con un botón pulsado. */
|
||||
int fnix_mouse_x(const FnixWindow *window);
|
||||
int fnix_mouse_y(const FnixWindow *window);
|
||||
|
||||
/* Desplazamiento de la rueda acumulado en este fotograma: positivo hacia
|
||||
* arriba (alejándose del usuario), negativo hacia abajo. */
|
||||
int fnix_mouse_wheel(const FnixWindow *window);
|
||||
|
||||
FNIX_END_DECLS
|
||||
|
||||
#endif /* FNIX_INPUT_H */
|
||||
@@ -0,0 +1,20 @@
|
||||
/*
|
||||
* FnixLib - tiempo.
|
||||
*/
|
||||
#ifndef FNIX_TIME_H
|
||||
#define FNIX_TIME_H
|
||||
|
||||
#include "fnix/types.h"
|
||||
|
||||
FNIX_BEGIN_DECLS
|
||||
|
||||
/* Segundos desde un origen arbitrario, con un reloj monótono (nunca retrocede).
|
||||
* Sirve para medir intervalos, no para conocer la hora del día. */
|
||||
double fnix_time_now(void);
|
||||
|
||||
/* Duerme el hilo actual al menos `seconds` segundos. Valores <= 0 no hacen nada. */
|
||||
void fnix_time_sleep(double seconds);
|
||||
|
||||
FNIX_END_DECLS
|
||||
|
||||
#endif /* FNIX_TIME_H */
|
||||
@@ -0,0 +1,47 @@
|
||||
/*
|
||||
* FnixLib - tipos públicos comunes.
|
||||
*/
|
||||
#ifndef FNIX_TYPES_H
|
||||
#define FNIX_TYPES_H
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
#define FNIX_BEGIN_DECLS extern "C" {
|
||||
#define FNIX_END_DECLS }
|
||||
#else
|
||||
#define FNIX_BEGIN_DECLS
|
||||
#define FNIX_END_DECLS
|
||||
#endif
|
||||
|
||||
FNIX_BEGIN_DECLS
|
||||
|
||||
/* Tipos opacos: su contenido es privado y puede cambiar entre versiones. */
|
||||
typedef struct FnixWindow FnixWindow;
|
||||
typedef struct FnixCanvas FnixCanvas;
|
||||
|
||||
/* Color RGBA con 8 bits por canal. a = 255 es opaco, a = 0 es invisible. */
|
||||
typedef struct FnixColor {
|
||||
uint8_t r, g, b, a;
|
||||
} FnixColor;
|
||||
|
||||
#define FNIX_RGBA(red, green, blue, alpha) \
|
||||
((FnixColor){(red), (green), (blue), (alpha)})
|
||||
#define FNIX_RGB(red, green, blue) FNIX_RGBA((red), (green), (blue), 255)
|
||||
|
||||
#define FNIX_BLACK FNIX_RGB(0, 0, 0)
|
||||
#define FNIX_WHITE FNIX_RGB(255, 255, 255)
|
||||
#define FNIX_RED FNIX_RGB(255, 0, 0)
|
||||
#define FNIX_GREEN FNIX_RGB(0, 255, 0)
|
||||
#define FNIX_BLUE FNIX_RGB(0, 0, 255)
|
||||
#define FNIX_YELLOW FNIX_RGB(255, 255, 0)
|
||||
#define FNIX_CYAN FNIX_RGB(0, 255, 255)
|
||||
#define FNIX_MAGENTA FNIX_RGB(255, 0, 255)
|
||||
#define FNIX_GRAY FNIX_RGB(128, 128, 128)
|
||||
#define FNIX_TRANSPARENT FNIX_RGBA(0, 0, 0, 0)
|
||||
|
||||
FNIX_END_DECLS
|
||||
|
||||
#endif /* FNIX_TYPES_H */
|
||||
@@ -0,0 +1,65 @@
|
||||
/*
|
||||
* FnixLib - ventanas.
|
||||
*
|
||||
* Uso típico:
|
||||
*
|
||||
* FnixWindow *window = fnix_window_create("Mi juego", 800, 600);
|
||||
* while (!fnix_window_should_close(window)) {
|
||||
* fnix_begin_frame(window); // lee eventos, fija el destino
|
||||
* fnix_clear(FNIX_BLACK);
|
||||
* fnix_draw_circle(400, 300, 50, FNIX_RED);
|
||||
* fnix_end_frame(window); // muestra y limita los FPS
|
||||
* }
|
||||
* fnix_window_destroy(window);
|
||||
*
|
||||
* Limitaciones de la versión 0.1.0: la ventana tiene tamaño fijo y solo existe
|
||||
* la implementación para Linux/X11 (ver README.md).
|
||||
*
|
||||
* Todas las funciones aceptan window == NULL (no hacen nada o devuelven 0).
|
||||
*/
|
||||
#ifndef FNIX_WINDOW_H
|
||||
#define FNIX_WINDOW_H
|
||||
|
||||
#include "fnix/types.h"
|
||||
|
||||
FNIX_BEGIN_DECLS
|
||||
|
||||
/* Crea y muestra una ventana de width x height píxeles (cada lado entre 1 y
|
||||
* FNIX_CANVAS_MAX_SIZE) y su lienzo. Devuelve NULL si falla; el motivo está
|
||||
* en fnix_last_error(). Límite inicial de FPS: 60. */
|
||||
FnixWindow *fnix_window_create(const char *title, int width, int height);
|
||||
|
||||
/* Cierra la ventana y libera todos sus recursos. Acepta NULL. */
|
||||
void fnix_window_destroy(FnixWindow *window);
|
||||
|
||||
/* true cuando el usuario cerró la ventana o se llamó a fnix_window_request_close. */
|
||||
bool fnix_window_should_close(const FnixWindow *window);
|
||||
void fnix_window_request_close(FnixWindow *window);
|
||||
|
||||
int fnix_window_width(const FnixWindow *window);
|
||||
int fnix_window_height(const FnixWindow *window);
|
||||
|
||||
/* Lienzo de la ventana; lo que se dibuje en él se muestra en fnix_end_frame().
|
||||
* Pertenece a la ventana: no se debe destruir por separado. */
|
||||
FnixCanvas *fnix_window_canvas(FnixWindow *window);
|
||||
|
||||
/* Limita los fotogramas por segundo durmiendo en fnix_end_frame().
|
||||
* 0 desactiva el límite (el bucle usará toda la CPU). Valores negativos = 0. */
|
||||
void fnix_window_set_target_fps(FnixWindow *window, int fps);
|
||||
|
||||
/* Segundos entre el inicio del fotograma anterior y el del actual (medidos en
|
||||
* fnix_begin_frame). Vale 0 en el primer fotograma. */
|
||||
double fnix_window_delta_time(const FnixWindow *window);
|
||||
|
||||
/* Inicio de fotograma: borra los "pressed/released" y la rueda del fotograma
|
||||
* anterior, procesa los eventos pendientes del sistema, calcula el delta time
|
||||
* y fija el lienzo de la ventana como destino de dibujo. NO borra el lienzo. */
|
||||
void fnix_begin_frame(FnixWindow *window);
|
||||
|
||||
/* Fin de fotograma: muestra el lienzo en la ventana y espera lo necesario para
|
||||
* respetar el límite de FPS. */
|
||||
void fnix_end_frame(FnixWindow *window);
|
||||
|
||||
FNIX_END_DECLS
|
||||
|
||||
#endif /* FNIX_WINDOW_H */
|
||||
Reference in new issue
Block a user