#pragma once #include #include struct GLFWwindow; // One row for the extensible right-hand stats list (oil temp, coolant // temp, etc.) — push more entries onto EngineStats::extra_stats as the // sim grows, no Gui changes needed. struct StatEntry { std::string label; double value; std::string unit; }; // Plain data the GUI reads each frame. The GUI knows nothing about // Engine/Transmission/Vehicle — main.cpp fills this in from Simulation. struct EngineStats { double rpm = 0.0; double redline_rpm = 6500.0; // tach gauge: start of red zone double max_rpm = 8000.0; // tach gauge: full scale double fuel_consumption_lph = 0.0; double crank_power_kw = 0.0; double output_heat_j = 0.0; std::vector extra_stats; }; // Which parasitic-load accessories are toggled on, via checkboxes drawn // in the left column by render(). Placeholders (Alternator, A/C, Power // Steering) until there's an actual load model behind them. struct AccessoryState { bool alternator = false; bool ac = false; bool power_steering = false; }; class Gui { public: bool init(); // create window + ImGui context bool begin_frame(); // returns false when the window should close void render(const EngineStats& stats); void end_frame(); // swap buffers void shutdown(); // Reflects the throttle lever as of the most recent render() call. // Spring-loaded: holds whatever value the drag left it at only // while the mouse is down, and snaps back to 0 the instant it's // released. Read it any time after render() this frame, or before // render() next frame, to feed it into the engine. double throttle() const { return static_cast(m_throttle_lever); } // Reflects the checkbox state as of the most recent render() call — // read it any time after render() this frame, or before render() // next frame, to feed accessory load into the engine. const AccessoryState& accessories() const { return m_accessories; } private: GLFWwindow* m_window = nullptr; float m_throttle_lever = 0.0f; AccessoryState m_accessories; };