#pragma once #include "FluidSim/ScenarioCatalog.hpp" #include "FluidSim/ScenarioSnapshot.hpp" #include #include namespace fluidsim::port::desktop { // Owns an editable design only. Simulation state is exchanged through snapshots // and explicit actions; mouse handlers never touch running components. class EngineEditor { public: void configure(const ScenarioExample& definition); bool handle_event(const sf::Event& event,sf::Vector2u size); void draw(sf::RenderWindow& window,const sf::Font* font,const ScenarioSnapshot& state) const; bool close(); bool visible() const { return visible_; } const EngineConfig& draft() const { return draft_; } std::optional take_live_update(); std::optional take_rebuild_request(); bool take_save_request(); void finish_rebuild(bool success,const std::string& message); void set_status(std::string message) { status_=std::move(message); } static sf::FloatRect bounds(sf::Vector2u size); static sf::FloatRect toggle_bounds(sf::Vector2u size); private: enum class Tab { Valves, Fuel, Pipes }; enum class Key { Mass,Spring,Damping,Preload,SoundArea,SoundDamping,Ignition,Idle,Pilot,Main,Needle,Stoich,Power,Length,Diameter }; struct Field { Key key;std::string label,unit;float value,minimum,maximum;int precision; }; bool supported_{},visible_{},exhaust_{},live_changed_{},rebuild_requested_{},save_requested_{},busy_{}; Tab tab_{Tab::Valves}; EngineConfig original_,draft_,rebuilding_; std::vector applied_pipes_; std::vector undo_,redo_; std::size_t pipe_{}; int dragging_field_{-1},dragging_point_{-1}; std::string status_{"Drag a cam point or slider. W/S controls the throttle."}; std::vector fields() const; void set_field(const Field& field,float value); void begin_edit(); void undo(); void redo(); void reset(); void drag(sf::Vector2f position,sf::Vector2u size); sf::FloatRect graph_bounds(sf::Vector2u size) const; sf::FloatRect field_bounds(sf::Vector2u size,std::size_t index) const; }; }