diff --git a/src/slic3r/CMakeLists.txt b/src/slic3r/CMakeLists.txt index 295ae683df..847ba6b962 100644 --- a/src/slic3r/CMakeLists.txt +++ b/src/slic3r/CMakeLists.txt @@ -241,6 +241,8 @@ set(SLIC3R_GUI_SOURCES GUI/Automation/AutomationServer.hpp GUI/Automation/AutomationRegistry.cpp GUI/Automation/AutomationRegistry.hpp + GUI/Automation/ImGuiItemTable.cpp + GUI/Automation/ImGuiItemTable.hpp GUI/I18N.cpp GUI/I18N.hpp GUI/DragDropPanel.cpp diff --git a/src/slic3r/GUI/Automation/ImGuiItemTable.cpp b/src/slic3r/GUI/Automation/ImGuiItemTable.cpp new file mode 100644 index 0000000000..61eba87a63 --- /dev/null +++ b/src/slic3r/GUI/Automation/ImGuiItemTable.cpp @@ -0,0 +1,31 @@ +#include "ImGuiItemTable.hpp" + +namespace Slic3r { namespace GUI { namespace Automation { + +ImGuiItemTable& ImGuiItemTable::instance() { + static ImGuiItemTable t; + return t; +} + +void ImGuiItemTable::record_item(ImGuiItemRecord rec) { + std::lock_guard lk(m_mutex); + m_back.items.push_back(std::move(rec)); +} + +void ImGuiItemTable::record_window(ImGuiWindowRecord rec) { + std::lock_guard lk(m_mutex); + m_back.windows.push_back(std::move(rec)); +} + +void ImGuiItemTable::swap_frame() { + std::lock_guard lk(m_mutex); + m_front = std::move(m_back); + m_back = ImGuiFrameRecord{}; +} + +ImGuiFrameRecord ImGuiItemTable::snapshot() const { + std::lock_guard lk(m_mutex); + return m_front; +} + +}}} // namespace diff --git a/src/slic3r/GUI/Automation/ImGuiItemTable.hpp b/src/slic3r/GUI/Automation/ImGuiItemTable.hpp new file mode 100644 index 0000000000..0557a56b49 --- /dev/null +++ b/src/slic3r/GUI/Automation/ImGuiItemTable.hpp @@ -0,0 +1,56 @@ +#pragma once +#include +#include +#include + +namespace Slic3r { namespace GUI { namespace Automation { + +// One recorded ImGui item. Rect is in ImGui display coords; WxUiBackend maps it +// to screen coords using the canvas client origin + DPI scale. +struct ImGuiItemRecord { + std::string window_name; + std::string label; // visible label / id + std::string type; // "button", "checkbox", "combo", "slider", "input", ... + float x = 0, y = 0, w = 0, h = 0; + bool enabled = true; + bool has_value = false; + std::string value; +}; + +// A complete recorded frame: items + window-level info. +struct ImGuiWindowRecord { + std::string name; + float x = 0, y = 0, w = 0, h = 0; + bool visible = true; +}; + +struct ImGuiFrameRecord { + std::vector items; + std::vector windows; +}; + +// Double-buffered recorder. The drawing code appends to the "back" frame; render() +// swaps it to "front" at frame end. Readers (GUI thread, after marshaling) read the +// front frame. All access is on the GUI thread, but we guard with a mutex anyway +// because the automation read may happen between frames. +class ImGuiItemTable { +public: + static ImGuiItemTable& instance(); + + // Called from ImGuiWrapper drawing hooks (GUI thread). No-op cheap append. + void record_item(ImGuiItemRecord rec); + void record_window(ImGuiWindowRecord rec); + + // Called at frame end (ImGuiWrapper::render). Promotes back -> front, clears back. + void swap_frame(); + + // Snapshot the latest complete frame for the backend to read. + ImGuiFrameRecord snapshot() const; + +private: + mutable std::mutex m_mutex; + ImGuiFrameRecord m_back; // accumulating + ImGuiFrameRecord m_front; // last complete +}; + +}}} // namespace