/* 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 #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(); }