diff --git a/src/gui/debug_ui.cpp b/src/gui/debug_ui.cpp new file mode 100644 index 0000000..e0ddd8d --- /dev/null +++ b/src/gui/debug_ui.cpp @@ -0,0 +1,20 @@ +#include "gui_internal.hpp" + +bool show_demo_window = false; +bool show_metrics_window = false; + +void draw_debug_window(ImGuiIO& io, bool* main_loop_wait_for_input){ + ImGui::Begin("Debug Options"); + ImGui::ColorEdit3("clear_color", (float*)&clear_color); + ImGui::Checkbox("main_loop_wait_for_input", main_loop_wait_for_input); + ImGui::Text("Application average %.3f ms/frame (%.2f FPS)", 1000.0f / io.Framerate, io.Framerate); + ImGui::Checkbox("Demo Window", &show_demo_window); + ImGui::Checkbox("Metrics/Debug Window", &show_metrics_window); + ImGui::End(); + + if (show_demo_window) + ImGui::ShowDemoWindow(&show_demo_window); + + if (show_metrics_window) + ImGui::ShowMetricsWindow(&show_metrics_window); +} diff --git a/src/gui/demo_ui.cpp b/src/gui/demo_ui.cpp deleted file mode 100644 index a6100a1..0000000 --- a/src/gui/demo_ui.cpp +++ /dev/null @@ -1,34 +0,0 @@ -#include "gui_internal.hpp" - -bool show_demo_window = true; -bool show_metrics_window = true; - -void draw_demo_windows(ImGuiIO& io){ - if (show_demo_window) - ImGui::ShowDemoWindow(&show_demo_window); - - if (show_metrics_window) - ImGui::ShowMetricsWindow(&show_metrics_window); - - { - static float f = 0.0f; - static int counter = 0; - - ImGui::Begin("Hello, world!"); // Create a window called "Hello, world!" and append into it. - - ImGui::Text("This is some useful text."); // Display some text (you can use a format strings too) - ImGui::Checkbox("Demo Window", &show_demo_window); // Edit bools storing our window open/close state - ImGui::Checkbox("Metrics/Debug Window", &show_metrics_window); - - ImGui::SliderFloat("float", &f, 0.0f, 1.0f); // Edit 1 float using a slider from 0.0f to 1.0f - ImGui::ColorEdit3("clear color", (float*)&clear_color); // Edit 3 floats representing a color - - if (ImGui::Button("Button")) // Buttons return true when clicked (most widgets return true when edited/activated) - counter++; - ImGui::SameLine(); - ImGui::Text("counter = %d", counter); - - ImGui::Text("Application average %.3f ms/frame (%.1f FPS)", 1000.0f / io.Framerate, io.Framerate); - ImGui::End(); - } -} diff --git a/src/gui/gui_internal.hpp b/src/gui/gui_internal.hpp index 361eeeb..8793b5b 100644 --- a/src/gui/gui_internal.hpp +++ b/src/gui/gui_internal.hpp @@ -31,6 +31,7 @@ ImFont* _ImFont_LoadEmbedded(const void* data, int data_size, const char* font_n ////////////////////////////////////// // Variables and constants // ////////////////////////////////////// +const u8 frame_rate_min=30; // frames per second const u8 frame_rate_max=60; // frames per second extern ImVec4 clear_color; // background color for main window @@ -39,11 +40,11 @@ extern ImVec4 clear_color; // background color for main window ////////////////////////////////////// /// @brief frees all allocated resources void main_window_destroy(); -void draw_demo_windows(ImGuiIO&); +void draw_debug_window(ImGuiIO& io, bool* main_loop_wait_for_input); void draw_bg_window(); void node_editor_open(const char* title); -void node_editor_draw(); +void draw_node_editor(); void node_editor_close(); ////////////////////////////////////// @@ -56,3 +57,13 @@ void node_editor_close(); } #define SDL_TRY_ZERO(FUNC_CALL) if(FUNC_CALL != 0) SDL_ERROR_SAFETHROW(); #define SDL_TRY_ONE(FUNC_CALL) if(FUNC_CALL != 1) SDL_ERROR_SAFETHROW(); + + +////////////////////////////////////// +// ImGui extensions // +////////////////////////////////////// +namespace ImGui { + void SetWindowSizeMin(f32 window_width_min, f32 window_height_min); +} + +ImVec2 ImVec2Add(ImVec2 a, ImVec2 b); diff --git a/src/gui/imgui_extensions.cpp b/src/gui/imgui_extensions.cpp new file mode 100644 index 0000000..2b5562f --- /dev/null +++ b/src/gui/imgui_extensions.cpp @@ -0,0 +1,28 @@ +#include "gui_internal.hpp" + +namespace ImGui { + +void SetWindowSizeMin(f32 window_width_min, f32 window_height_min){ + ImVec2 window_size=ImGui::GetWindowSize(); + ImVec2 new_size=window_size; + bool changed=false; + if(window_size.xGetDebugName()); - io.Fonts->Build(); + ImFont_LoadEmbedded(font_Cousine_Regular, default_font_size); node_editor_open("node editor"); return MaybeNull; } // Wait, poll and handle events (inputs, window resize, etc.) -// You can read the io.WantCaptureMouse, io.WantCaptureKeyboard flags to tell if dear imgui wants to use your inputs. -// - When io.WantCaptureMouse is true, do not dispatch mouse input data to your main application, or clear/overwrite your copy of the mouse data. -// - When io.WantCaptureKeyboard is true, do not dispatch keyboard input data to your main application, or clear/overwrite your copy of the keyboard data. -// Generally you may always pass all inputs to dear imgui, and hide them from your application based on those two flags. -Maybe poll_events(bool& frame_needs_update, bool wait){ +Maybe poll_events(u16& frame_updates_requested, bool wait){ SDL_Event event; if(wait){ // waits for first event in cpu-efficient way @@ -92,7 +88,8 @@ Maybe poll_events(bool& frame_needs_update, bool wait){ return MaybeNull; do { - frame_needs_update|=ImGui_ImplSDL2_ProcessEvent(&event); + if(ImGui_ImplSDL2_ProcessEvent(&event)) + frame_updates_requested=2; switch(event.type){ case SDL_QUIT: { try_cpp(main_window_close(),_9914,;); @@ -118,8 +115,8 @@ Maybe draw_frame(){ // Draw UI draw_bg_window(); - draw_demo_windows(io); - node_editor_draw(); + draw_debug_window(io, &main_loop_wait_for_input); + draw_node_editor(); // Rendering ImGui::Render(); @@ -152,21 +149,36 @@ Maybe main_window_loop_start(){ // draw first frame try_cpp(draw_frame(),_2175,;); - // main loop + u16 frame_updates_requested=1; + u64 prev_update_time_ms=SDL_GetTicks64(); loop_running=true; + // main loop while(loop_running){ - bool frame_needs_update=false; // waits for events - try_cpp(poll_events(frame_needs_update, true),_55415,;); + try_cpp(poll_events(frame_updates_requested, main_loop_wait_for_input),_55415,;); - if(!frame_needs_update){ - // skips frame rendering if user didn't interacted with anything - u32 frame_delay_ms=1000/frame_rate_max; - SDL_Delay(frame_delay_ms); - continue; + if(frame_updates_requested==0) + { + u64 update_time_ms=SDL_GetTicks64(); + if(update_time_ms >= prev_update_time_ms + 1000/frame_rate_min){ + // if frame rate < frame_rate_min then requests frame draw + // works only if main_loop_wait_for_input = false + frame_updates_requested=1; + prev_update_time_ms=update_time_ms; + } + else { + // skips frame rendering and waits to limit fps + u32 frame_delay_ms=1000/frame_rate_max; + SDL_Delay(frame_delay_ms); + continue; + } } - - try_cpp(draw_frame(),_2175,;); + + // deaws requested number of frames + while(frame_updates_requested>0) { + try_cpp(draw_frame(),_2175,;); + frame_updates_requested--; + } } // Cleanup diff --git a/src/gui/node_editor.cpp b/src/gui/node_editor.cpp index ed329b9..7c68678 100644 --- a/src/gui/node_editor.cpp +++ b/src/gui/node_editor.cpp @@ -5,11 +5,15 @@ namespace NE = ax::NodeEditor; NE::EditorContext* editor_context=nullptr; const char* editor_title; +void draw_example_node(); + + void node_editor_open(const char* title){ NE::Config config; config.SettingsFile = "node_editor.json"; editor_context=NE::CreateEditor(&config); editor_title=title; + NE::Style& style=NE::GetStyle(); } void node_editor_close(){ @@ -17,27 +21,40 @@ void node_editor_close(){ editor_context=nullptr; } -void node_editor_draw(){ +u32 node_id_next; +u32 pin_id_next; +u32 link_id_next; + +void draw_node_editor(){ if(editor_context==nullptr) return; + node_id_next=0; + pin_id_next=0; + link_id_next=0; ImGui::Begin(editor_title); - NE::SetCurrentEditor(editor_context); - NE::Begin(editor_title, ImVec2(0.0, 0.0f)); - int uniqueId = 1; - // Start drawing nodes. - NE::BeginNode(uniqueId++); - ImGui::Text("Node A"); - NE::BeginPin(uniqueId++, NE::PinKind::Input); - ImGui::Text("-> In"); - NE::EndPin(); - ImGui::SameLine(); - NE::BeginPin(uniqueId++, NE::PinKind::Output); - ImGui::Text("Out ->"); - NE::EndPin(); - NE::EndNode(); - NE::End(); - NE::SetCurrentEditor(nullptr); + ImGui::SetWindowSizeMin(300,300); + NE::SetCurrentEditor(editor_context); + NE::Begin(editor_title); + // Start drawing nodes. + draw_example_node(); + ImVec2 node_pos=NE::GetNodePosition(node_id_next-1); + NE::SetNodePosition(node_id_next, ImVec2Add(node_pos, ImVec2(50, 20))); + draw_example_node(); + NE::End(); + NE::SetCurrentEditor(nullptr); ImGui::End(); } +void draw_example_node(){ + NE::BeginNode(node_id_next++); + ImGui::Text("Node A"); + NE::BeginPin(pin_id_next++, NE::PinKind::Input); + ImGui::Text("-> In"); + NE::EndPin(); + ImGui::SameLine(); + NE::BeginPin(pin_id_next++, NE::PinKind::Output); + ImGui::Text("Out ->"); + NE::EndPin(); + NE::EndNode(); +}