#define FSM_DEBUG 1 #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 "gui/guecstra.hpp" #include "animate2.hpp" bool YES_SYNC=true; namespace animator { struct UI { guecs::UI $ui; void init(const std::string& sprite_name) { $ui.position(0,0, SCREEN_WIDTH, SCREEN_HEIGHT); $ui.layout( "[play|*%=(300,400)viewer|_|_]" "[stop|_|_|_]" "[next|_|_|_]" "[prev|_|_|_]"); 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.set(comp, {[](auto){ fmt::println("I don't know what to do here."); }}); } } $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); } }; enum class State { START=__LINE__, ANIMATE=__LINE__, END=__LINE__, }; struct FSM : public DeadSimpleFSM { UI $ui; gui::routing::Router $router; sf::RenderWindow $window{sf::VideoMode({SCREEN_WIDTH, SCREEN_HEIGHT}), "Animation Crafting Tool"}; void init(const std::string &sprite_name) { $ui.init(sprite_name); if(YES_SYNC) { $window.setVerticalSyncEnabled(VSYNC); if(FRAME_LIMIT) $window.setFramerateLimit(FRAME_LIMIT); } $window.setPosition({0,0}); } void event(game::Event ev, std::any data={}) { switch($state) { FSM_STATE(State, START, ev); FSM_STATE(State, ANIMATE, ev); FSM_STATE(State, END, ev); } } void START(game::Event ev) { switch(ev) { case game::Event::TICK: state(State::ANIMATE); break; default: state(State::START); } } void ANIMATE(game::Event ev) { switch(ev) { case game::Event::TICK: // stuff break; default: state(State::START); } } void END(game::Event ev) { } void handle_keyboard_mouse() { 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: $ui.mouse(mouse_pos.x, mouse_pos.y, guecs::NO_MODS); break; case MOUSE_MOVE: $ui.mouse(mouse_pos.x, mouse_pos.y, {1 << guecs::ModBit::hover}); break; case QUIT: state(State::END); default: break; // ignored } } } void render() { $window.clear(); $ui.render($window); $window.display(); } bool active() { return !in_state(State::END); } }; } 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]}; sound::mute(true); sound::play("ambient_1", true); animator::FSM main; main.init(argv[1]); animate2::Timer timer; timer.start(); while(main.active()) { timer.begin(); main.render(); auto [ticks, alpha] = timer.commit(); fmt::println("TICK: {}, alpha: {}", ticks, alpha); for(int i = 0; i < ticks; i++) { main.event(game::Event::TICK, {}); } // do something with alpha.... main.handle_keyboard_mouse(); } return 0; }