V2.0.0
This commit is contained in:
commit
9020ded6ce
95 files changed
+11394
No files matched your search
@@ -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; }
|
||||
@@ -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
|
||||
@@ -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();
|
||||
}
|
||||
Reference in new issue
Block a user