From 81cbc240645f80ba4cee0b2e17c860da0bc3208b Mon Sep 17 00:00:00 2001 From: "Zed A. Shaw" Date: Sat, 17 Jan 2026 23:43:44 -0500 Subject: [PATCH] Have the start of an animation dev tool. --- meson.build | 7 +++ tests/animation.cpp | 10 +++-- tools/animator.cpp | 103 ++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 116 insertions(+), 4 deletions(-) create mode 100644 tools/animator.cpp diff --git a/meson.build b/meson.build index 5f04b44..d99771f 100644 --- a/meson.build +++ b/meson.build @@ -183,6 +183,13 @@ executable('arena', override_options: exe_defaults, dependencies: dependencies) +executable('animator', + sources + [ 'tools/animator.cpp' ], + cpp_args: cpp_args, + link_args: link_args, + override_options: exe_defaults, + dependencies: dependencies) + executable('storyboard', sources + [ 'tools/storyboard.cpp' ], cpp_args: cpp_args, diff --git a/tests/animation.cpp b/tests/animation.cpp index 2ce30be..a7ae0ba 100644 --- a/tests/animation.cpp +++ b/tests/animation.cpp @@ -160,7 +160,7 @@ TEST_CASE("new animation system", "[animation-new]") { PLAY_TEST(anim); bool onLoop_ran = false; - anim.onLoop = [&](auto& seq, auto &tr) -> bool { + anim.onLoop = [&](auto& seq, auto& tr) -> bool { seq.current = 0; onLoop_ran = true; return tr.looped; @@ -170,7 +170,7 @@ TEST_CASE("new animation system", "[animation-new]") { REQUIRE(onLoop_ran == true); // only runs twice - anim.onLoop = [](auto &seq, auto &tr) -> bool { + anim.onLoop = [](auto& seq, auto& tr) -> bool { if(seq.loop_count == 2) { seq.current = 0; return false; @@ -184,7 +184,7 @@ TEST_CASE("new animation system", "[animation-new]") { REQUIRE(anim.$sequence.loop_count == 2); // stops at end - anim.onLoop = [](auto &seq, auto &tr) -> bool { + anim.onLoop = [](auto& seq, auto& tr) -> bool { if(seq.loop_count == 1) { seq.current = seq.frame_count - 1; return false; @@ -194,7 +194,9 @@ TEST_CASE("new animation system", "[animation-new]") { }; } - +TEST_CASE("easing functions in animate2", "[animation-new]") { + auto anim = crafter(); +} TEST_CASE("animation easing tests", "[animation]") { Animation anim; diff --git a/tools/animator.cpp b/tools/animator.cpp new file mode 100644 index 0000000..f493b29 --- /dev/null +++ b/tools/animator.cpp @@ -0,0 +1,103 @@ +#include "sound.hpp" +#include "ai.hpp" +#include "animation.hpp" +#include +#include "shaders.hpp" +#include "backend.hpp" +#include "events.hpp" +#include "constants.hpp" +#include "gui/event_router.hpp" +#include "constants.hpp" +#include +#include "gui/event_router.hpp" +#include +#include + +using namespace std::chrono_literals; + +struct UI { + guecs::UI $ui; + + void init(const std::string& sprite_name) { + $ui.position(0,0, SCREEN_WIDTH, SCREEN_HEIGHT); + $ui.layout( + "[*%(100,200)data|*%=(300,200)viewer|_|_]" + "[_|_|_|_]"); + + for(auto& [name, cell] : $ui.cells()) { + auto comp = $ui.entity(name); + if(name == "viewer") { + $ui.set(comp, { + sprite_name, 0, false}); + } else { + $ui.set(comp, {}); + $ui.set(comp, {guecs::to_wstring(name)}); + $ui.set(comp, {}); + } + } + + $ui.init(); + } + + void render(sf::RenderWindow& window) { + $ui.render(window); + } + + bool mouse(float x, float y, guecs::Modifiers mods) { + return $ui.mouse(x, y, mods); + } +}; + +int main(int argc, char* argv[]) { + shaders::init(); + components::init(); + sfml::Backend backend; + guecs::init(&backend); + ai::init("ai"); + animation::init(); + + dbc::check(argc == 2, "USAGE: animator "); + std::string sprite_name{argv[1]}; + + sf::RenderWindow window(sf::VideoMode({SCREEN_WIDTH, SCREEN_HEIGHT}), "Animation Crafting Tool"); + window.setVerticalSyncEnabled(VSYNC); + + if(FRAME_LIMIT) window.setFramerateLimit(FRAME_LIMIT); + window.setPosition({0,0}); + + sound::mute(true); + sound::play("ambient_1", true); + + UI main{}; + main.init(sprite_name); + gui::routing::Router router; + + while(true) { + while(const auto ev = window.pollEvent()) { + using enum game::Event; + auto gui_ev = router.process_event(ev); + auto mouse_pos = window.mapPixelToCoords(router.position); + + switch(gui_ev) { + case MOUSE_CLICK: + main.mouse(mouse_pos.x, mouse_pos.y, guecs::NO_MODS); + break; + case MOUSE_MOVE: + main.mouse(mouse_pos.x, mouse_pos.y, {1 << guecs::ModBit::hover}); + break; + case QUIT: + return 0; + default: + break; // ignored + } + + window.clear(); + main.render(window); + window.display(); + } + + std::this_thread::sleep_for(10ms); + } + + return 0; +}