#pragma once // timeline — widget tipo DAW: tracks horizontales con keyframes interpolados, // scrub y play/pause. Sirve para animar valores escalares (uniforms shader, // parametros UI, etc) a lo largo del tiempo. // // Estado puro (TimelineState) + funciones puras de interpolacion // (track_value_at) + render impuro (timeline_widget). // // Uso: // static fn::TimelineState tl; // tl.tracks.push_back({"hue", {{0,0}, {2,1}, {4,0}}}); // tl.duration = 4.0f; // // fn::timeline_update(tl, dt); // float h = fn::track_value_at(tl.tracks[0], tl.current_time); // fn::timeline_widget("##tl", tl); #include "core/tween_curves.h" #include #include #include namespace fn { struct Keyframe { float time; float value; tween::Ease ease = tween::Ease::Linear; }; struct Track { std::string name; std::vector keys; }; struct TimelineState { std::vector tracks; float current_time = 0.0f; float duration = 5.0f; bool playing = false; bool loop = true; }; // --- Pure ------------------------------------------------------------------- // Interpola el valor de `track` en el tiempo `t`. Asume keys ordenadas por // time. Si `t` cae antes del primer keyframe devuelve el value del primero; // si cae despues del ultimo, devuelve el value del ultimo. Entre keyframes // usa el ease de la SEGUNDA key (la "curva entrante" hasta esa key). float track_value_at(const Track& track, float t); // --- Update ----------------------------------------------------------------- // Avanza current_time si playing. Si loop=true hace wrap; si no, satura en // duration y pone playing=false al llegar. void timeline_update(TimelineState& s, float dt); // --- Render ----------------------------------------------------------------- // Widget completo: cabecera con play/pause + tiempo, ruler con scrub, y un // panel por track con keyframes draggable. Devuelve true si el usuario hizo // algun cambio (drag de keyframe, scrub, play/pause). bool timeline_widget(const char* id, TimelineState& s, ImVec2 size = ImVec2(-1, 200)); } // namespace fn