461bb77298
12 issues nuevos para implementacion paralela: text_editor, file_watcher, gl_texture_load, gl_compute+pingpong+DAG Compute, ImPlot3D, mesh_viewer, audio reactivo, animation curves, sql_workbench, http+ws inspector, scientific viz (5 charts), map_tiles, image_canvas + webcam_texture. Cada issue añade funciones al registry y un demo propio en primitives_gallery/demos_<feature>.cpp para minimizar conflictos en paralelo. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
5.9 KiB
5.9 KiB
0031 — C++ animation curves (timeline + bezier_editor + tween_curves)
APP Metadata
| Campo | Valor |
|---|---|
| ID | 0031 |
| Estado | pendiente |
| Prioridad | media |
| Tipo | feature — C++ core (cpp/functions/core) |
Dependencias
tokens_cpp_core. Independiente de los demas issues.
Desbloquea: animar uniforms en shaders_lab con keyframes; easing reusable en transiciones de UI; control fino sobre animaciones procedurales.
Objetivo
Tres primitivos:
tween_curves_cpp_core— set de funciones de easing puras (Penner): linear, ease_in/out_quad/cubic/expo, elastic, bounce. Header-only.bezier_editor_cpp_core— editor visual de una curva cubica Bezier (4 puntos de control), evaluacionf(t)para t∈[0,1]. Estado puro + render en ImGui canvas.timeline_cpp_core— widget tipo DAW: tracks horizontales con keyframes draggable, scrub, play/pause, evaluaciontrack_value_at(time)con interp lineal o curve por keyframe.
Demo en primitives_gallery con un slider animado por timeline + curva bezier para ease.
Contexto
shaders_lab tiene sliders manuales para uniforms. No hay forma de:
- Animar un uniform con curva temporal.
- Disenar transiciones suaves reusables.
Las funciones de easing son utiles tambien fuera de animacion (interpolacion de colores, rampas).
Arquitectura
cpp/functions/core/
├── tween_curves.h # NEW (header-only ok)
├── tween_curves.cpp # NEW (si hace falta .cpp)
├── tween_curves.md # NEW
├── bezier_editor.h # NEW
├── bezier_editor.cpp # NEW
├── bezier_editor.md # NEW
├── timeline.h # NEW
├── timeline.cpp # NEW
└── timeline.md # NEW
cpp/apps/primitives_gallery/
├── demos_animation.cpp # NEW
├── demos.h # MOD
├── main.cpp # MOD
└── CMakeLists.txt # MOD
API propuesta
namespace fn {
// --- tween_curves (puro, header-only ok) ---
namespace tween {
inline float linear(float t) { return t; }
inline float in_quad(float t) { return t*t; }
inline float out_quad(float t) { return 1 - (1-t)*(1-t); }
inline float in_out_cubic(float t) { /* Penner */ }
inline float in_expo(float t);
inline float out_expo(float t);
inline float in_elastic(float t);
inline float out_elastic(float t);
inline float out_bounce(float t);
// ... ~15 easing funcs
enum class Ease { Linear, InQuad, OutQuad, InOutQuad, InCubic, OutCubic, /*...*/ };
float apply(Ease e, float t);
}
// --- bezier_editor (puro estado) ---
struct BezierCurve { ImVec2 p0{0,0}, p1{0.25f,0.0f}, p2{0.75f,1.0f}, p3{1,1}; };
float bezier_eval(const BezierCurve&, float t); // y at x=t
bool bezier_editor(const char* id, BezierCurve&, ImVec2 size = {200, 200}); // returns true if changed
// --- timeline ---
struct Keyframe { float time; float value; tween::Ease ease = tween::Ease::Linear; };
struct Track { std::string name; std::vector<Keyframe> keys; };
struct TimelineState {
std::vector<Track> tracks;
float current_time = 0.0f;
float duration = 5.0f;
bool playing = false;
};
float track_value_at(const Track&, float t); // interp puro
void timeline_update(TimelineState&, float dt); // avanza si playing
bool timeline_widget(const char* id, TimelineState&, ImVec2 size = {-1, 200}); // returns true if changed
}
Tareas
Fase 1 — tween_curves
- 1.1 Implementar las funciones Penner (referencia: easings.net). Header-only inline para que el compilador inline en hot paths.
- 1.2
tween::apply(Ease, t)con switch. - 1.3 Tests: cada curva en t=0 y t=1 da 0 y 1 respectivamente (excepto elastic/bounce).
- 1.4
.md.
Fase 2 — bezier_editor
- 2.1
bezier_eval: De Casteljau o forma polinomial. Implementacion puramente algebraica. - 2.2
bezier_editor: canvas ImGui con 4 puntos draggable (p0/p3 fijos en {0,0}/{1,1} para easing). Dibuja la curva conAddBezierCubic. - 2.3 Tests para
bezier_eval. - 2.4
.md.
Fase 3 — timeline
- 3.1
track_value_at: encuentra el segmento (k_i, k_{i+1}), normaliza t, aplicatween::apply(ease). - 3.2
timeline_update: siplaying, avanzacurrent_time += dt; loop al llegar a duration. - 3.3
timeline_widget: barra con tracks horizontales, keyframes como diamantes draggable, scrub time con click en barra superior, botones play/pause. Estilo basado entokens. - 3.4 Tests para
track_value_at(linear). - 3.5
.md.
Fase 4 — Gallery demo
- 4.1
demos_animation.cpp:demo_tween(): dropdown de Ease + curva animandose contra el tiempo.demo_bezier_editor(): editor + plot de la curva resultante.demo_timeline(): timeline con 2 tracks ("hue", "amp") + slider que muestratrack_value_at(now)para cada uno.
- 4.2 Registrar en gallery (3 entradas).
Fase 5 — Tests + docs
- 5.1 Tests de easing y track_value_at.
- 5.2
./fn index+./fn showde los 3.
Ejemplo de uso
fn::TimelineState tl{};
tl.tracks.push_back({"hue", {{0, 0}, {2, 1}, {4, 0}}});
tl.duration = 4.0f;
tl.playing = true;
fn::run_app("anim", [&](float dt){
fn::timeline_update(tl, dt);
float h = fn::track_value_at(tl.tracks[0], tl.current_time);
ImGui::Text("hue = %.3f", h);
fn::timeline_widget("##tl", tl);
});
Decisiones de diseño
- Tween header-only: codigo pequeño, alto uso → inline.
- Bezier solo para easing (p0=0, p3=1) en MVP. Generalizable si hace falta.
- Timeline simple, no jerarquico: tracks planos. Si hace falta layering en el futuro, otro issue.
Riesgos
- UX del bezier_editor: precision de drag con mouse en canvas pequeño. Documentar tamaño minimo recomendado (180+).
- Timeline drag race: keyframe drag debe respetar orden temporal. Reordenar al soltar.