feat(automation): double-buffered ImGui item table

This commit is contained in:
SoftFever
2026-06-03 02:52:52 +08:00
parent 39a29cf865
commit c0d37bff3a
3 changed files with 89 additions and 0 deletions

View File

@@ -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

View File

@@ -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<std::mutex> lk(m_mutex);
m_back.items.push_back(std::move(rec));
}
void ImGuiItemTable::record_window(ImGuiWindowRecord rec) {
std::lock_guard<std::mutex> lk(m_mutex);
m_back.windows.push_back(std::move(rec));
}
void ImGuiItemTable::swap_frame() {
std::lock_guard<std::mutex> lk(m_mutex);
m_front = std::move(m_back);
m_back = ImGuiFrameRecord{};
}
ImGuiFrameRecord ImGuiItemTable::snapshot() const {
std::lock_guard<std::mutex> lk(m_mutex);
return m_front;
}
}}} // namespace

View File

@@ -0,0 +1,56 @@
#pragma once
#include <mutex>
#include <string>
#include <vector>
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<ImGuiItemRecord> items;
std::vector<ImGuiWindowRecord> 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