Commit Graph

77 Commits

Author SHA1 Message Date
egutierrez 5b73466bd4 chore(registry): notes en huerfanas usadas por framework/apps
Auditoria del issue 0044: anota en notes: el contexto de consumo de
huerfanos que no pueden registrarse en uses_functions porque sus
consumidores no son funciones del registry:
- consumido por cpp/framework/app_base.cpp (framework no indexado)
- consumido por cpp/apps/{shaders_lab,chart_demo,text_editor_smoke}/main.cpp
- scaffolding/demo en primitives_gallery

31 huerfanas anotadas. Las que quedan en uses_functions=[] tras esto
son hojas legitimas (no llaman a nada) o realmente sin uso (lista
DEAD reportada en el issue 0044).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-28 23:40:51 +02:00
egutierrez 7c95b36a5f chore(registry): añadir uses_functions a consumidores reales (viz)
Auditoria del issue 0044: 9 archivos .md de cpp/functions/viz/ con
uses_functions actualizado. Resuelve dependencias detectadas via
#include: plot_static (consumido por bar_chart, histogram, line_plot,
pie_chart, scatter_plot), gl_loader, gl_framebuffer, gl_shader,
graph_force_layout, graph_renderer, graph_spatial_hash, orbit_camera,
sparkline y tokens.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-28 23:40:37 +02:00
egutierrez 37ca9562c3 chore(registry): añadir uses_functions a consumidores reales (gfx)
Auditoria del issue 0044: 14 archivos .md de cpp/functions/gfx/ con
uses_functions actualizado. Resuelve dependencias detectadas via
#include: gl_loader (consumido por casi todo el dominio gfx),
dag_catalog (consumido por la familia dag_*), fullscreen_quad,
gl_framebuffer, gl_shader, mesh_obj_load, uniform_parser y
dag_node_previews.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-28 23:40:31 +02:00
egutierrez ee3c39ad25 chore(registry): añadir uses_functions a consumidores reales (core)
Auditoria del issue 0044: 17 archivos .md de cpp/functions/core/ con
uses_functions actualizado para reflejar las llamadas reales detectadas
mediante #include en sus .cpp/.h. Los huerfanos referenciados (tokens,
app_about, app_settings, layouts_menu, panel_menu, table_view,
text_editor, tween_curves, app_settings) ahora aparecen en el grafo de
dependencias del registry.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-28 23:40:22 +02:00
egutierrez ec81bf360d docs: ADR 0002 + CHANGELOG + reglas para dataforge/<name>+master
- docs/adr/0002-apps-analyses-as-dataforge-master.md: decision arquitectural
  con contexto, alternativas descartadas y cambios concretos del 2026-04-28.
- CHANGELOG.md: entrada 2026-04-28 con Added/Changed/Fixed.
- .claude/CLAUDE.md: nota sobre /full-git-push y dataforge/<name>+master.
- .claude/rules/apps_tbd.md: tronco unico master + init.defaultBranch.
- cpp/functions/core/app_menubar.md: notas del submenu Settings con About.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-28 22:41:55 +02:00
egutierrez 424e913566 feat(cpp,bash): app_about + Settings submenu, ensure_repo_synced pipeline
cpp/core: nuevo modulo app_about — ventana About con project/version/desc,
componible via about_window_set_info() en el init de la app y rendererizada
automaticamente por fn::run_app al final de cada frame.

app_menubar: el item top-level "Settings..." pasa a ser un BeginMenu
"Settings" con dos subitems: "Settings..." (existente) y "About..." (nuevo).

bash/infra: nueva pipeline ensure_repo_synced que compone gitea_create_repo
y gitea_push_directory para garantizar repo Gitea existente + sync de un
directorio local en una sola llamada idempotente.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-28 22:05:31 +02:00
egutierrez dda03b14cc merge: issue/0034 — scientific viz (treemap, sankey, chord, contour, voronoi)
# Conflicts:
#	cpp/apps/primitives_gallery/CMakeLists.txt
#	cpp/apps/primitives_gallery/demos.h
#	cpp/apps/primitives_gallery/main.cpp
2026-04-25 21:55:49 +02:00
egutierrez 2f6dea6ebd merge: issue/0032 — sql_workbench
# Conflicts:
#	cpp/apps/primitives_gallery/CMakeLists.txt
#	cpp/apps/primitives_gallery/demos.h
#	cpp/apps/primitives_gallery/main.cpp
2026-04-25 21:55:17 +02:00
egutierrez 25936dff79 merge: issue/0031 — animation curves (timeline + bezier_editor + tween_curves)
# Conflicts:
#	cpp/apps/primitives_gallery/CMakeLists.txt
2026-04-25 21:54:48 +02:00
egutierrez 55939cb60b merge: issue/0029 — mesh_viewer + obj loader + orbit_camera
# Conflicts:
#	cpp/apps/primitives_gallery/demos.h
#	cpp/apps/primitives_gallery/main.cpp
2026-04-25 21:54:27 +02:00
egutierrez fdf7c82bd7 feat(primitives_gallery): demos para los 5 charts cientificos (issue 0034)
Anade 5 entradas a la gallery (treemap, sankey, chord, contour, voronoi)
con datos sinteticos coherentes:
- treemap: 6 items 'gastos por categoria'
- sankey: 8 nodos clientes -> productos -> categorias (DAG)
- chord: matriz 6x6 simetrica de flujos entre paises
- contour: mezcla de 2 gaussianas 32x32 + 5 niveles
- voronoi: 30 seeds aleatorias + colores aleatorios

Wire-up additions only (demos.h, main.cpp k_demos[], CMakeLists.txt).
2026-04-25 21:53:01 +02:00
egutierrez d0bce11a40 feat(viz): voronoi diagram via raster brute-force (MVP)
Para cada tile 4x4 px del rect de render: encontrar seed mas cercano
(distancia Euclidea) y rellenar con su color. Suficiente para N<=200
seeds en region <=600x400.

voronoi_layout deja polygon vacio en MVP — solo rellena seed/color.
Para extraer poligonos analiticos seria necesario half-plane
intersections (Fortune) — diferido a otro issue.
2026-04-25 21:52:52 +02:00
egutierrez cda557286e feat(viz): contour plot via marching squares — layout puro + render
contour_compute implementa marching squares clasico (16 casos, casos
ambiguos 5 y 10 partidos en 2 segmentos). Para cada level devuelve un
ContourLine{pts, level} con segmentos en coords [0..nx-1]x[0..ny-1].

Verificado con gaussiana 32x32 + 4 niveles: todos los endpoints aparecen
>=2 veces (curvas cerradas, ningun endpoint huerfano).
2026-04-25 21:52:48 +02:00
egutierrez 75d4334e8c feat(viz): chord diagram — arcos circulares + cuerdas bezier
Para una matriz NxN: cada nodo ocupa un arco proporcional a sum(row).
Las cuerdas matrix[i,j] son bandas bezier cubico hacia el centro
conectando los arcos de i y j.

Limitacion: las cuerdas se dibujan con AddConvexPolyFilled aunque la
forma no sea estrictamente convexa — visualmente queda razonable.
2026-04-25 21:52:43 +02:00
egutierrez 636c7b8d05 feat(viz): sankey diagram — BFS topologico + bandas curvas (bezier cubico)
compute_levels asigna columnas via BFS, los nodos se apilan verticalmente
proporcional a max(in_total, out_total). Los links se renderizan como
bandas con bezier cubico, color del nodo origen + alpha bajo.

Asume DAG (sin ciclos). Si hay ciclos, los nodos del ciclo quedan en su
nivel parcial — no rompe pero puede solapar visualmente.
2026-04-25 21:52:37 +02:00
egutierrez 0487180ac2 feat(viz): treemap squarified (Bruls et al.) — layout puro + render DrawList
treemap_layout devuelve TreemapRect{min, max, item} con coords absolutas
dentro de la region. La suma de areas == area total (verificado via test
standalone, ratio=1.000000). El render usa AddRectFilled + AddText cuando
labels y valores caben dentro de la cell.

Limitaciones MVP: jerarquia plana (no recursivo), sin interaccion.
2026-04-25 21:52:33 +02:00
egutierrez c1a3d72e59 feat(primitives_gallery): demo de mesh_viewer (cubo procedural + .obj loader)
Genera cubo procedural in-line (mesh_obj_parse de string), permite
cargar .obj desde un text input absoluto. Botones: Reload cube,
Wireframe toggle, Load .obj. Status line con tris count y
instrucciones (drag to orbit, wheel to zoom).

issue 0029
2026-04-25 21:51:27 +02:00
egutierrez b557433388 feat(viz): mesh_viewer — componente 3D con FBO + Lambert headlight
Compila/cachea por id un programa GLSL (vertex+fragment) con
iluminacion Lambert (luz=camara), gestiona Framebuffer cacheado por
id, dibuja MeshGpu con orbit camera, muestra via ImGui::Image y
maneja drag (mouse) + wheel (zoom). Wireframe opcional via
glPolygonMode.

gl_loader: añade glUniformMatrix4fv (proc requerido en Windows para
subir las matrices view/proj del mesh_viewer).

issue 0029
2026-04-25 21:51:22 +02:00
egutierrez 4e19583a22 feat(core): orbit_camera — camara orbital pura (matrices view/proj + drag)
State minimal (azimuth, elevation, distance, fov, aspect, near/far).
orbit_camera_matrices: lookAt+perspective row-major float[16] (subir a
GL con transpose=GL_TRUE). orbit_camera_handle_drag: dx→azimuth,
dy→elevation (clamp ±π/2-eps), wheel→distance (clamp >0.1). Sin glm,
solo <cmath>.

issue 0029
2026-04-25 21:51:15 +02:00
egutierrez c5dc63699a feat(gfx): mesh_gpu — VAO/VBO/EBO upload para Mesh
mesh_gpu_upload sube positions+normals interleaved (stride 6 floats,
location 0=a_pos, location 1=a_normal) + EBO uint32. mesh_gpu_destroy
libera todo. GL_STATIC_DRAW (mesh inmutable post-upload).

issue 0029
2026-04-25 21:51:10 +02:00
egutierrez 10ac4c74db feat(gfx): mesh_obj_load — minimal Wavefront .obj parser
mesh_obj_parse (pure) + mesh_obj_load (impure file helper).
Soporta v / vn / f (tris y quads). Genera normales per-face si
faltan (flat shading). Quads se parten en 2 tris; n-gons (>4) se
descartan silenciosamente. Indices 1-based positivos y negativos.

issue 0029
2026-04-25 21:51:05 +02:00
egutierrez 4ed27a58d1 feat(primitives_gallery): demos for tween_curves + bezier_editor + timeline
Adds three new demos to the Core section of primitives_gallery:

- demo_tween: dropdown of all 16 Ease modes + animated plot showing the
  curve and a moving marker that traverses t=0..1 in a loop.
- demo_bezier_editor: live editor with reset + ease-out / ease-in-out
  presets, current control points displayed, slider over t showing
  bezier_eval(curve, t).
- demo_timeline: 2 tracks (hue, amp) with mixed eases, live progress bars
  showing track_value_at(current_time) updating each frame.

Wires the three demos into k_demos[] in main.cpp and adds the new sources
(plus the three function .cpp files) to CMakeLists.txt.
2026-04-25 21:50:44 +02:00
egutierrez 448765fa15 feat(core): add timeline — DAW-style keyframe widget
Timeline widget with:
- Header: play/pause + reset + duration drag + loop checkbox
- Ruler: 0.5s ticks, scrub via click+drag
- Tracks: horizontal rows with diamond-shaped draggable keyframes
- Playhead: vertical primary_light line + ruler triangle marker

State and types:
- Keyframe { time, value, ease }
- Track { name, vector<Keyframe> }
- TimelineState { tracks, current_time, duration, playing, loop }

Pure functions:
- track_value_at(track, t): interp between keys, ease applied via the
  destination keyframe (Maya/AfterEffects convention)
- timeline_update(state, dt): advance current_time, wrap or saturate

Render with fn_tokens for visual coherence with the rest of the design
system. Keys are sorted by time on every changed frame to keep order
consistent during drag.
2026-04-25 21:50:35 +02:00
egutierrez a8e153b73f feat(core): add bezier_editor — visual cubic Bezier curve editor
ImGui canvas with 4 draggable control points (p0/p3 locked at (0,0)/(1,1)
by default for use as easing curves). Pure evaluation via De Casteljau
(bezier_point) plus sampling-based y(x) lookup (bezier_eval).

Render uses fn_tokens for visual coherence: bg, border, primary curve,
text_dim diagonal reference, text_muted handle tangents.

p1.x and p2.x clamped to [0,1] to keep the curve usable as easing; Y
values are free to allow deliberate overshoot.
2026-04-25 21:50:29 +02:00
egutierrez 384bfecf3a feat(core): add tween_curves — Penner easing functions
16 easing curves (linear, quad, cubic, expo, elastic, bounce in/out/inOut)
header-mostly so the compiler inlines on hot paths. Pure, no I/O, no state.

Includes:
- tween::apply(Ease, t) dispatcher for data-driven uses (timeline keyframe.ease,
  dropdown selection)
- tween::name(Ease) for UI labels
- tween::ease_count for iteration

Tested values documented in tween_curves.md.
2026-04-25 21:50:21 +02:00
egutierrez 4d53ee6380 feat(primitives_gallery): demo de sql_workbench contra registry.db readonly
Demo nuevo en demos_sql.cpp: abre registry.db en SQLITE_OPEN_READONLY
(resolviendo via FN_REGISTRY_ROOT o cwd ascendente), monta
fn::SqlWorkbenchState con readonly=true y query inicial sobre la tabla
functions. Wire-up: entry en k_demos[] tras process_runner; declaracion
en demos.h; sources sql_workbench.cpp + demos_sql.cpp + link
SQLite::SQLite3 en CMakeLists.txt.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-25 21:49:09 +02:00
egutierrez 0cf04c37df feat(primitives_gallery): demos para surface_plot_3d + scatter_3d
- demos_3d.cpp con dos demos:
  * demo_surface_plot_3d: malla 64x64 de A*sin(fx*x)*cos(fy*y) con
    sliders fx/fy/amp en tiempo real.
  * demo_scatter_3d: 3 clusters gaussianos (N=500) coloreados por
    cluster, semilla fija para reproducibilidad.
- demos.h: declara las dos demos en la seccion Viz.
- main.cpp: dos entradas nuevas en k_demos[] (Viz, tras heatmap /
  table_view).
- CMakeLists.txt: anade demos_3d.cpp + surface_plot_3d.cpp +
  scatter_3d.cpp al target.

Issue 0028.
2026-04-25 21:48:51 +02:00
egutierrez e24d16db59 feat(core): sql_workbench component (issue 0032)
ImGui SQL workbench: editor (text_editor + CodeLang::SQL), schema sidebar
desde sqlite_master, tabla resultado (table_view), historial. Backend
sql_workbench_run_query separado de UI; readonly opt-in (rechaza non-SELECT/
PRAGMA/EXPLAIN/WITH); cap de filas (truncated_at, default 10000); last_ms
medido con steady_clock.

API: sql_workbench(id, sqlite3*, SqlWorkbenchState&, size). DB caller-owned.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-25 21:48:50 +02:00
egutierrez cebf87cb4e feat(viz): surface_plot_3d real (ImPlot3D) + scatter_3d nuevo
surface_plot_3d (v2.0.0): quita el STUB. API basada en
SurfacePlot3DConfig (z[nx*ny] row-major + ranges X/Y) que delega en
ImPlot3D::PlotSurface. Las coordenadas X/Y por vertice se generan
internamente desde [x_min, x_max] x [y_min, y_max].

scatter_3d (v1.0.0): nuevo primitivo. Scatter 3D con tamano y color
opcionales por punto via ImPlot3DSpec::MarkerSizes / MarkerFillColors.
Util para PCA / clustering / nubes de puntos sinteticas.

Ambos namespace fn::, kind component, purity pure. Orbit / zoom / pan
los aporta ImPlot3D nativo.

Issue 0028.
2026-04-25 21:48:43 +02:00
egutierrez b3e55f7abe feat(framework): inicializar contexto ImPlot3D en app_base
ImPlot3D::CreateContext() / DestroyContext() acoplado al ciclo de
vida de ImPlot. Cualquier app que use fn::run_app obtiene el contexto
3D listo sin codigo extra.

Issue 0028.
2026-04-25 21:48:34 +02:00
egutierrez 4bf6f37e97 chore(vendor): vendorear ImPlot3D v0.4 como submodulo + target CMake
- submodule cpp/vendor/implot3d -> github.com/brenocq/implot3d, pinned
  commit 41ae3e447c0de20ecab95d38a4b4dc0835a3efc2 (v0.4).
- target CMake `implot3d` parejo a `implot` (3 sources: implot3d.cpp,
  implot3d_items.cpp, implot3d_meshes.cpp).
- fn_framework linkea implot3d para que cualquier app pueda usar las
  funciones viz/*_3d sin configurar nada extra.
- VENDORING.md externo (no tocamos el README upstream).

Issue 0028.
2026-04-25 21:48:29 +02:00
egutierrez 6d7b802199 feat(primitives_gallery): demos individuales para wave 1 + 5 primitivos viz/core
Cobertura del catalogo visual:
- text_editor (Wave 1, 0025): demo solo del editor con dropdown GLSL/SQL/Cpp/Generic.
- file_watcher (Wave 1, 0025): demo solo del watcher con boton touch + log.
- gl_texture_load (Wave 1, 0026): ya tenia demo (Gfx).
- process_runner: tarea simulada en background con spinner.
- candlestick: 30 dias OHLC sintetico.
- gauge: 3 indicadores con sliders (CPU/MEM/GPU).
- heatmap: gaussiana 12x12.
- table_view: 6 funciones del registry como muestra.

El demo combinado anterior (text_editor + watcher) se separa en dos para
que cada entry del sidebar exhiba un solo primitivo. Mas claro y mas
indexable.

Total entries en gallery: 26 (antes 23).
2026-04-25 21:40:44 +02:00
egutierrez ab27e4e5fa build(cpp): primitives_gallery activa por defecto
Tras commitear los deps (button, toolbar, modal_dialog, app_settings, etc.)
todos los sources del gallery estan tracked. Quita el gate FN_BUILD_GALLERY
y deja el subdirectorio como add_subdirectory incondicional (igual que
chart_demo y shaders_lab).

Build verificado: cmake --build cpp/build construye chart_demo, shaders_lab,
text_editor_smoke, primitives_gallery y registry_dashboard.
2026-04-25 21:28:24 +02:00
egutierrez 0db9242692 docs(cpp): añadir DESIGN_SYSTEM.md
Documenta el sistema de design tokens del registry C++:
- Identidad visual unica (Mantine v9 dark + indigo) compartida entre apps
- Como se aplican los tokens via fn::run_app
- Convenciones de uso (cuando usar tokens.colors.surface vs accent, etc.)

Es la fuente de verdad cuando se crean nuevas primitivas o apps fn_ui.
2026-04-25 21:26:09 +02:00
egutierrez a9045d45a0 feat(cpp/gfx): code_to_generator + shaderlab_db
Dos primitivas del pipeline de shaders_lab que ya estaban en uso pero sin
indexar al registry:

- code_to_generator_cpp_gfx (function, pure)
  Traduce un fragment shader GLSL escrito a mano (modo Code, con void main()
  + fragColor = ...) en un body de DAG Gen + DagControl[]. Cada uniform
  anotado se convierte en un control; el body usa el parametro uv y reemplaza
  fragColor= por return. Empaqueta uniforms en vec4 (4 x n_uniforms).

- shaderlab_db_cpp_gfx (function, impure)
  CRUD persistente para generators custom de shaders_lab via sqlite3.
  Guarda el GLSL original, el body traducido para el DAG, los DagControl y
  los param_defaults en una BD local (shaders_lab.db). Soporta open(:memory:)
  para tests.

Ambas se indexan ahora en registry.db y son reusables fuera de shaders_lab
si en el futuro hay otra app que componga DAGs de shaders.
2026-04-25 21:26:03 +02:00
egutierrez 8d28faf3e8 feat(cpp/core): app framework UI (settings, menubar, layouts)
5 primitivas que componen el chrome de una app fn_ui completa:

- app_settings_cpp_core         (function, impure)  ventana flotante de
  settings globales (Display + Typography + secciones extra registrables) con
  persistencia automatica en app_settings.ini junto al ejecutable.
- app_menubar_cpp_core          (component, pure)   MainMenuBar unificada
  con menu View (toggles de paneles) y Layouts. Punto de entrada de la
  menubar de cualquier app fn_ui.
- layouts_menu_cpp_core         (component, pure)   menu para guardar/aplicar/
  borrar/reset layouts de ImGui via callbacks (no I/O propio).
- panel_menu_cpp_core           (component, pure)   menu checkable para
  abrir/cerrar paneles, composable dentro de la MainMenuBar.
- layout_storage_sqlite_cpp_core (function, impure) primitivas CRUD de bajo
  nivel para persistir blobs INI de ImGui en sqlite (ui_layouts table).

Permiten que apps como shaders_lab y registry_dashboard ofrezcan: panel
toggles, layouts persistentes en BD, ventana de settings con preview en
vivo. Todas usan tokens_cpp_core para el styling.
2026-04-25 21:25:51 +02:00
egutierrez dff0d735c1 feat(cpp/core): primitivas UI estilo Mantine
Anade 9 primitivas reutilizables al registry C++ que replican el comportamiento
de los componentes correspondientes de @fn_library / Mantine v9, todas
estilizadas con tokens_cpp_core (colores Mantine dark + indigo):

- button_cpp_core         (component, pure)  variantes primary/secondary/subtle/danger + sm/md/lg
- icon_button_cpp_core    (component, pure)  cuadrado 28x28 con glyph centrado + tooltip
- toolbar_cpp_core        (component, pure)  grupo horizontal de acciones con separadores
- modal_dialog_cpp_core   (component, pure)  popup modal centrada + close con Escape
- text_input_cpp_core     (component, impure) InputText con label muted + placeholder
- select_cpp_core         (component, impure) dropdown con label + opcion '(none)' opcional
- toast_cpp_core          (component, impure) notificaciones efimeras + inbox con badge
- tree_view_cpp_core      (component, impure) jerarquia low-level con tree_node_clicked helper
- process_runner_cpp_core (component, impure) tarea en std::thread + spinner inline

Cada primitiva tiene su .md con frontmatter completo (params/output) y se
indexa via fn index. Son la base del primitives_gallery y de cualquier
app fn_ui futura.
2026-04-25 21:25:39 +02:00
egutierrez 79591daef2 feat(cpp/core): icon_font + icons_tabler
icon_font_cpp_core (impure): carga Karla-Regular como texto vectorial y
mergea Tabler Icons al mismo tamano en el atlas de ImGui. Tras el call,
los TI_* renderizan inline con el texto.

icons_tabler.h: header con macros TI_<NAME> que apuntan a los codepoints
del set Tabler (UTF-8 escapado). Generado a partir del CSS del vendor con
cpp/vendor/tabler-icons/gen_header.py — re-ejecutable si se actualiza el
set sin tocar a mano los ~5500 codepoints.

Justifica la regla cpp_icons.md: todas las apps C++ usan TI_* en lugar de
emoji o hex inline.
2026-04-25 21:25:25 +02:00
egutierrez 6e57818f14 chore(cpp/vendor): vendor Tabler Icons v3.41.1 (TTF + generador)
Vendorea el set de iconos Tabler (~5500 iconos, MIT) para usar en apps
ImGui via icon_font_cpp_core. Incluye:

- tabler-icons.ttf       — atlas TTF para mergear en ImGui
- tabler-icons.css       — referencia de codepoints (no se compila)
- gen_header.py          — script que regenera cpp/functions/core/icons_tabler.h
                           con macros TI_<NAME> a partir del CSS
- LICENSE / README.md    — atribucion MIT

Versionar el TTF (~700 KB) evita depender de descargas en build. Las apps
usan TI_* en strings y el atlas se carga con icon_font_cpp_core::load().
2026-04-25 21:25:17 +02:00
egutierrez 53402d84d5 docs(issues): marcar 0025 y 0026 como completados + WIP master
Wave 1 de parallel-fix-issues integrada a master:
- 0025: text_editor_cpp_core + file_watcher_cpp_core
- 0026: gl_texture_load_cpp_gfx (vendor: stb_image v2.30)

Ademas se commitea WIP previo de master que estaba sin commitear (cambios
en shaders_lab, dag_*, framework, tokens, kpi_card, gl_loader.md, etc.)
para dejar HEAD buildable.

Notas:
- Algunos deps del gallery (button.cpp, toolbar.cpp, modal_dialog.cpp...)
  siguen UNTRACKED — gating con FN_BUILD_GALLERY=ON (default OFF) para
  que master build (sin flag) no los necesite.
- Build OK con y sin flag. fn index registra 904 functions.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-25 21:14:15 +02:00
egutierrez 37e8139c5b feat(primitives_gallery): wire gl_texture_load demo
Tras integrar 0025 (que trajo la app entera) y 0026 (que solo añadio
demos_gl_texture.cpp + assets/sample.png + cpp/functions/gfx/gl_texture_load.*),
falta wire-up de la entrada nueva en los archivos compartidos del gallery.

- demos.h: declarar gallery::demo_gl_texture()
- main.cpp: entrada en k_demos[] con id "gl_texture", category "Gfx"
- CMakeLists.txt: añadir demos_gl_texture.cpp, gl_texture_load.cpp,
  stb_image_impl.cpp, e include dir vendor/stb

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-25 21:05:45 +02:00
egutierrez 5e94dd5087 merge: issue/0026 — gl_texture_load (stb_image)
# Conflicts:
#	cpp/CMakeLists.txt
2026-04-25 21:05:11 +02:00
egutierrez ed1ffd07b5 feat(primitives_gallery): wire text_editor + file_watcher demo
- demos_text_editor.cpp: split horizontal con editor GLSL precargado a la
  izquierda (boton Save to /tmp/fn_demo.glsl + dirty indicator) y panel de
  eventos a la derecha (path, active flag, lista scrollable, boton clear).
  Watcher activo sobre /tmp/fn_demo.glsl; reintenta el add() tras el primer
  Save si el archivo no existia al iniciar.
- demos.h: declaracion de gallery::demo_text_editor()
- main.cpp: entry "text_editor"/"text_editor + watcher" en categoria Core
- CMakeLists.txt: anade demos_text_editor.cpp + sources de text_editor,
  file_watcher y vendor TextEditor.cpp + include path de imgui_text_edit

Nota: la primitives_gallery NO se construye en este branch (sus deps —
button.cpp, toolbar.cpp, etc. — son untracked en master). El subdirectorio
se anade pero protegido por FN_BUILD_GALLERY=OFF para no romper builds.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-25 21:00:55 +02:00
egutierrez dc079a815b test(cpp): add text_editor_smoke build gate for issue 0025
App minima (no abre ventana ImGui) que crea/settea/lee text_editor y registra
un watch sobre /tmp/fn_smoke_test.txt para confirmar que TextEditor.cpp del
vendor + text_editor.cpp + file_watcher.cpp enlazan correctamente. Activada
por defecto si la carpeta existe (no requiere la primitives_gallery).

Tambien anade flag FN_BUILD_GALLERY (OFF default) para no romper el build
cuando la primitives_gallery no esta presente — sus deps (button.cpp,
toolbar.cpp...) son sources untracked en algunas branches.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-25 21:00:47 +02:00
egutierrez b43be6a308 feat(cpp/core): add file_watcher_cpp_core (inotify Linux / RDCW Win)
Watcher de archivos no bloqueante con backend nativo por plataforma:

- Linux: inotify_init1(IN_NONBLOCK | IN_CLOEXEC), inotify_add_watch con
  mascara MODIFY|CREATE|DELETE|CLOSE_WRITE|MOVED_*. Drain en cada poll().
- Windows: ReadDirectoryChangesW overlapped + GetOverlappedResult no
  bloqueante. Para vigilar un archivo, registra el directorio padre y filtra
  por nombre exacto en el poll().
- Otros: stub — poll() devuelve vacio y last_error() reporta no soportado.

API en namespace fn:: con tipos opacos (FileWatcher PIMPL). Errores via
last_error() en vez de excepciones. Documentadas las limitaciones (limite de
inotify watches en Linux, granularidad directorio-level en Windows, no
recursividad).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-25 21:00:38 +02:00
egutierrez 3ad63f79dc feat(cpp/core): add text_editor_cpp_core component (PIMPL)
Wrapper en namespace fn:: sobre ImGuiColorTextEdit. La API publica solo expone
TextEditorState como tipo opaco; el TextEditor del vendor vive dentro del .cpp.

Soporta CodeLang::{Generic, GLSL, SQL, Cpp} (highlighting via las
LanguageDefinition del vendor). text_editor_render() devuelve true en el frame
en que el contenido cambia; flag dirty manejado independientemente para casos
"editado pero aun no guardado".

text_editor_get_text() cachea el resultado en un std::string del state para
mantener el const char* valido entre llamadas (el GetText() del vendor devuelve
std::string por valor).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-25 21:00:31 +02:00
egutierrez 7cccaec5dd feat(cpp/vendor): vendor ImGuiColorTextEdit (MIT) for text_editor primitive
Pinneado al commit 0a88824f del upstream. Patches locales aplicados a
TextEditor.cpp para compilar contra ImGui 1.91+ (GetKeyIndex eliminado,
PushAllowKeyboardFocus/PopAllowKeyboardFocus removidos). Documentado en
cpp/vendor/imgui_text_edit/README.md.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-25 21:00:22 +02:00
egutierrez f33d55485e feat(primitives_gallery): demo de gl_texture_load + asset PNG
Añade demos_gl_texture.cpp (carga assets/sample.png con la nueva
funcion gl_texture_load_cpp_gfx, muestra w/h/channels y sliders de
tint RGB + zoom UV via ImGui::ImageWithBg) y un PNG damero 256x256
generado para la demo.

Tambien registra apps/primitives_gallery como subdirectorio en
cpp/CMakeLists.txt (la app vive como WIP en master; aqui solo se
añade el hook de build).

Para integrarse, demos.h, main.cpp y CMakeLists.txt de la gallery
deben anadir respectivamente la declaracion gallery::demo_gl_texture(),
la entrada {"gl_texture", "gl_texture_load", "Gfx", &gallery::demo_gl_texture}
en k_demos[], y demos_gl_texture.cpp + cpp/functions/gfx/gl_texture_load.cpp +
cpp/vendor/stb/stb_image_impl.cpp + include de cpp/vendor/stb a sus sources.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-25 20:58:50 +02:00
egutierrez cb0591ff91 feat(gfx): añadir gl_texture_load_cpp_gfx
Funcion impura del registry que carga PNG/JPG/BMP/TGA/HDR a una textura
OpenGL lista para sampler2D. Composable con gl_loader, gl_shader,
shader_canvas. Genera mipmaps, soporta sRGB y HDR (RGBA16F).

API:
  GlTexture gl_texture_load(path, flip_y=true, srgb=false)
  GlTexture gl_texture_load_from_memory(data, size, ...)
  void      gl_texture_destroy(tex)
  const char* gl_texture_last_error()  // thread-local
  void      gl_texture_bind_uniform(prog, name, tex, unit)

Errores via thread_local string accesible por gl_texture_last_error().

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-25 20:58:14 +02:00
egutierrez fcbda2af2e feat(gl_loader): añadir glActiveTexture y glGenerateMipmap
Necesarios para que gl_texture_load (cpp/functions/gfx/) funcione en
Windows tras wglGetProcAddress. En Linux son simbolos directos via
GL_GLEXT_PROTOTYPES, no afecta.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-25 20:58:07 +02:00