This commit is contained in:
Clinv committed 2026-10-24 11:52:16 -03:00
commit 9020ded6ce
95 files changed
+11394

No files matched your search

+113
View File
@@ -0,0 +1,113 @@
/* Implementación FALSA de las funciones de raylib que usa Tahgibu: no abre ventanas ni dibuja,
* pero reproduce un guion de ratón/teclado para ejercitar el bucle real de src/ui. */
#include <stdlib.h>
#include <string.h>
#include "raylib.h"
#include "mock_raylib.h"
static const mock_event *g_events;
static int g_nevents, g_next, g_last_frame, g_frame;
static Vector2 g_mouse;
static bool g_down[3], g_pressed[3], g_released[3];
static bool g_key_down[512], g_key_pressed[512];
static int g_chars[256], g_nchars, g_char_head;
static float g_wheel;
static int g_tex_updates, g_draw_calls;
void mock_script(const mock_event *events, int count, int last_frame) {
g_events = events; g_nevents = count; g_last_frame = last_frame; g_next = 0; g_frame = 0;
}
int mock_frames_run(void) { return g_frame; }
int mock_texture_updates(void) { return g_tex_updates; }
int mock_draw_calls(void) { return g_draw_calls; }
void SetConfigFlags(unsigned int flags) { (void)flags; }
void InitWindow(int width, int height, const char *title) { (void)width; (void)height; (void)title; }
void CloseWindow(void) {}
void SetWindowMinSize(int w, int h) { (void)w; (void)h; }
void SetTargetFPS(int fps) { (void)fps; }
void SetExitKey(int key) { (void)key; }
int GetScreenWidth(void) { return 1280; }
int GetScreenHeight(void) { return 800; }
float GetFrameTime(void) { return 1.0f / 60.0f; }
double GetTime(void) { return 1000.0 + (double)g_frame / 60.0; }
/* Se llama una vez por vuelta del bucle: avanza el guion. */
bool WindowShouldClose(void) {
g_frame++;
memset(g_pressed, 0, sizeof g_pressed);
memset(g_released, 0, sizeof g_released);
memset(g_key_pressed, 0, sizeof g_key_pressed);
g_wheel = 0;
while (g_next < g_nevents && g_events[g_next].frame <= g_frame) {
const mock_event *e = &g_events[g_next++];
int k = (int)e->a;
switch (e->type) {
case EV_MOVE: g_mouse.x = e->a; g_mouse.y = e->b; break;
case EV_DOWN: g_down[k] = true; g_pressed[k] = true; break;
case EV_UP: g_down[k] = false; g_released[k] = true; break;
case EV_KEY: if (k >= 0 && k < 512) g_key_pressed[k] = true; break;
case EV_KEYDOWN: if (k >= 0 && k < 512) g_key_down[k] = true; break;
case EV_KEYUP: if (k >= 0 && k < 512) g_key_down[k] = false; break;
case EV_CHAR: if (g_nchars < 256) g_chars[g_nchars++] = k; break;
case EV_WHEEL: g_wheel = e->a; break;
}
}
return g_frame > g_last_frame;
}
void BeginDrawing(void) {}
void EndDrawing(void) {}
void ClearBackground(Color c) { (void)c; g_draw_calls++; }
void BeginScissorMode(int x, int y, int w, int h) { (void)x; (void)y; (void)w; (void)h; }
void EndScissorMode(void) {}
void DrawRectangle(int x, int y, int w, int h, Color c) { (void)x; (void)y; (void)w; (void)h; (void)c; g_draw_calls++; }
void DrawRectangleRec(Rectangle r, Color c) { (void)r; (void)c; g_draw_calls++; }
void DrawRectangleLines(int x, int y, int w, int h, Color c) { (void)x; (void)y; (void)w; (void)h; (void)c; g_draw_calls++; }
void DrawRectangleLinesEx(Rectangle r, float t, Color c) { (void)r; (void)t; (void)c; g_draw_calls++; }
void DrawCircleLines(int x, int y, float r, Color c) { (void)x; (void)y; (void)r; (void)c; g_draw_calls++; }
void DrawText(const char *t, int x, int y, int s, Color c) { (void)t; (void)x; (void)y; (void)s; (void)c; g_draw_calls++; }
int MeasureText(const char *t, int size) { return (int)strlen(t) * size / 2; }
Font GetFontDefault(void) {
Font f;
memset(&f, 0, sizeof f);
f.baseSize = 10;
f.texture.id = 1;
f.texture.width = 1;
f.texture.height = 1;
return f;
}
Font LoadFontEx(const char *path, int size, int *codepoints, int count) {
(void)path; (void)codepoints; (void)count;
Font f = GetFontDefault();
f.baseSize = size;
f.texture.id = 2;
return f;
}
void UnloadFont(Font f) { (void)f; }
void DrawTextEx(Font f, const char *t, Vector2 p, float size, float spacing, Color c) {
(void)f; (void)t; (void)p; (void)size; (void)spacing; (void)c; g_draw_calls++;
}
Vector2 MeasureTextEx(Font f, const char *t, float size, float spacing) {
(void)f;
float n = (float)strlen(t);
return (Vector2){n * size * 0.52f + (n > 0.0f ? (n - 1.0f) * spacing : 0.0f), size};
}
Texture2D LoadTextureFromImage(Image img) { Texture2D t = {1, img.width, img.height, 1, img.format}; return t; }
void UpdateTexture(Texture2D t, const void *pixels) { (void)t; if (pixels) g_tex_updates++; }
void UnloadTexture(Texture2D t) { (void)t; }
void SetTextureFilter(Texture2D t, int f) { (void)t; (void)f; }
void DrawTexturePro(Texture2D t, Rectangle s, Rectangle d, Vector2 o, float r, Color c) { (void)t; (void)s; (void)d; (void)o; (void)r; (void)c; g_draw_calls++; }
Vector2 GetMousePosition(void) { return g_mouse; }
bool IsMouseButtonPressed(int b) { return g_pressed[b]; }
bool IsMouseButtonDown(int b) { return g_down[b]; }
bool IsMouseButtonReleased(int b) { return g_released[b]; }
float GetMouseWheelMove(void) { return g_wheel; }
bool IsKeyPressed(int k) { return k >= 0 && k < 512 && g_key_pressed[k]; }
bool IsKeyPressedRepeat(int k) { (void)k; return false; }
bool IsKeyDown(int k) { return k >= 0 && k < 512 && g_key_down[k]; }
int GetCharPressed(void) { return g_char_head < g_nchars ? g_chars[g_char_head++] : 0; }
const char *GetClipboardText(void) { return ""; }
bool CheckCollisionPointRec(Vector2 p, Rectangle r) { return p.x >= r.x && p.x < r.x + r.width && p.y >= r.y && p.y < r.y + r.height; }
+14
View File
@@ -0,0 +1,14 @@
/* Control del "raylib falso" que usa la prueba de humo de la interfaz (sin ventana ni GPU). */
#ifndef MOCK_RAYLIB_H
#define MOCK_RAYLIB_H
typedef enum { EV_MOVE, EV_DOWN, EV_UP, EV_KEY, EV_KEYDOWN, EV_KEYUP, EV_CHAR, EV_WHEEL } mock_ev_type;
typedef struct { int frame; mock_ev_type type; float a, b; } mock_event;
/* Programa un guion de eventos (ordenado por frame) y el último frame; luego tgb_ui_run lo consume. */
void mock_script(const mock_event *events, int count, int last_frame);
int mock_frames_run(void);
int mock_texture_updates(void);
int mock_draw_calls(void);
#endif
+85
View File
@@ -0,0 +1,85 @@
/* Prueba de humo de la interfaz: ejecuta el bucle REAL de src/ui con un raylib falso y un guion de
* ratón/teclado, y comprueba el resultado en el archivo .tgb guardado. NO prueba la compatibilidad
* con raylib real: solo la lógica de la interfaz y su integración con el núcleo. */
#include <stdio.h>
#include "../tgb_test.h"
#include "mock_raylib.h"
#include "../../src/ui/ui_run.h"
#include "../../src/ui/ui_app.h"
static tgb_context *g_ctx;
static char g_root[200];
static mock_event mk(int f, mock_ev_type t, float a, float b) { mock_event e = {f, t, a, b}; return e; }
#define CTRL_DOWN(f) mk(f, EV_KEYDOWN, 341, 0)
#define CTRL_UP(f) mk(f, EV_KEYUP, 341, 0)
#define KEY(f, k) mk(f, EV_KEY, (float)(k), 0)
#define MOVE(f, x, y) mk(f, EV_MOVE, x, y)
#define DOWN(f) mk(f, EV_DOWN, 0, 0)
#define UP(f) mk(f, EV_UP, 0, 0)
int main(void) {
/* El texto truncado nunca debe romper una secuencia UTF-8. */
char clipped[64];
ui_fit_text(clipped, sizeof clipped, "Rectángulo selección ñ", 100.0f, 14.0f);
CHECK(strncmp(clipped, "Rect", 4) == 0);
CHECK(strstr(clipped, "...") != NULL || strcmp(clipped, "Rectángulo selección ñ") == 0);
g_ctx = tgb_test_context(g_root, sizeof g_root);
tgb_recovery *rec = NULL;
CHECK_OK(tgb_recovery_open(g_ctx, &rec));
tgb_plugin_manager *pm = NULL;
CHECK_OK(tgb_plugin_manager_create(g_ctx, &pm));
char out[300]; snprintf(out, sizeof out, "%s/humo.tgb", g_root);
/* guion (ventana falsa de 1280x800: lienzo en x 0..980, y 104..606; "Nuevo" de la línea de tiempo en (45,625)) */
static mock_event ev[400];
int n = 0;
#define E(x) (ev[n++] = (x))
/* 1) trazo con el lápiz en el fotograma 1 */
E(MOVE(5, 300, 300)); E(DOWN(6));
for (int i = 0; i < 10; i++) E(MOVE(7 + i, 300 + 20 * (float)i, 300 + 5 * (float)i));
E(UP(18));
/* 2) deshacer y rehacer con atajos */
E(CTRL_DOWN(20)); E(KEY(20, 90)); E(CTRL_UP(21)); /* Ctrl+Z */
E(CTRL_DOWN(24)); E(KEY(24, 89)); E(CTRL_UP(25)); /* Ctrl+Y */
/* 3) rectángulo con la tecla R, arrastrando */
E(KEY(28, 82)); E(MOVE(29, 600, 200)); E(DOWN(30)); E(MOVE(31, 650, 250)); E(MOVE(32, 700, 300)); E(UP(33));
/* 4) nuevo fotograma (botón "Nuevo" de la línea de tiempo) y un trazo en él */
E(MOVE(36, 45, 625)); E(DOWN(37)); E(UP(38));
E(KEY(40, 80)); /* P: lápiz */
E(MOVE(41, 350, 350)); E(DOWN(42)); E(MOVE(43, 420, 380)); E(MOVE(44, 480, 360)); E(UP(45));
/* 5) reproducir un rato (Enter) y pausar */
E(KEY(50, 257)); E(KEY(120, 257));
/* 6) abrir "Guardar como" (Ctrl+Shift+S), borrar el texto por defecto, escribir la ruta, aceptar */
E(CTRL_DOWN(130)); E(mk(130, EV_KEYDOWN, 340, 0)); E(KEY(130, 83)); E(CTRL_UP(131)); E(mk(131, EV_KEYUP, 340, 0));
for (int i = 0; i < 40; i++) E(KEY(135 + i, 259)); /* Backspace */
for (const char *p = out; *p; p++) E(mk(180, EV_CHAR, (float)(unsigned char)*p, 0));
E(KEY(185, 257)); /* Enter */
#undef E
mock_script(ev, n, 260);
int rc = tgb_ui_run(g_ctx, rec, pm, NULL);
CHECK_EQ(rc, 0);
CHECK(mock_frames_run() > 250);
CHECK(mock_texture_updates() > 10); /* la vista se refrescó muchas veces */
CHECK(mock_draw_calls() > 5000);
/* el archivo guardado desde la interfaz contiene lo dibujado */
tgb_document *d = NULL;
CHECK_OK(tgb_document_load(g_ctx, out, &d));
if (d) {
CHECK_EQ(tgb_frame_count(d), 2);
CHECK(tgb_canvas_width(tgb_frame_cel(d, 0, 0)) == 960);
size_t f0 = count_alpha(tgb_frame_cel(d, 0, 0)), f1 = count_alpha(tgb_frame_cel(d, 1, 0));
printf(" (pixeles dibujados: fotograma 1 = %zu, fotograma 2 = %zu)\n", f0, f1);
CHECK(f0 > 150); /* trazo + rectángulo */
CHECK(f1 > 50);
CHECK(!tgb_document_dirty(d));
tgb_document_destroy(d);
}
tgb_plugin_manager_destroy(pm);
tgb_recovery_close(rec, true);
tgb_context_destroy(g_ctx);
tgb_test_rmtree(g_root);
TEST_SUMMARY();
}