fix(shaders_lab): drop zone no longer eats node/slider input + inline tests

The previous InvisibleButton captured mouse events, so you could drag
from the Functions palette into the canvas, but node dragging and
slider interaction inside the canvas stopped working.

Fix: watch the global drag-drop payload without an explicit target. When
the mouse releases LMB over the DAG window with a "DAG_NODE_TYPE"
payload active, queue an add at that canvas position. No button, no
capture.

Tests (compiled standalone with preprocessor defines):
- dag_compile: 6/6 asserts (empty, single gen, op chain, multi-source
  blend, Output-driven fragColor, unconnected-Output fallback).
- dag_catalog: 8/8 asserts (uniqueness, per-kind input invariants,
  exactly one Output, body_glsl present & returns, control param
  indices valid).
Build with:
  g++ -std=c++17 -Icpp/functions -DDAG_COMPILE_TEST cpp/functions/gfx/dag_compile.cpp cpp/functions/gfx/dag_catalog.cpp -o /tmp/dag_compile_test
  g++ -std=c++17 -Icpp/functions -DDAG_CATALOG_TEST cpp/functions/gfx/dag_catalog.cpp -o /tmp/dag_catalog_test

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-04-24 22:24:39 +02:00
parent e828af3ac1
commit e3cfab3dc7
4 changed files with 169 additions and 13 deletions
+14 -13
View File
@@ -138,25 +138,26 @@ bool dag_node_editor(std::vector<DagStep>& pipeline) {
s_ctx = ed::CreateEditor(&cfg);
}
// Palette drop zone: accept dropped node types (from the Functions panel)
// and queue an add at the mouse canvas position (resolved after ed::Begin).
// Palette drop: detect without a capturing target (an InvisibleButton would
// steal clicks from the node editor). Observe the active drag-drop payload
// and, if the mouse is over this window and the user releases LMB, queue an
// add at that canvas position.
static std::string s_pending_add_name;
static ImVec2 s_pending_add_pos(0, 0);
static bool s_pending_add = false;
ImVec2 origin = ImGui::GetCursorScreenPos();
ImVec2 avail = ImGui::GetContentRegionAvail();
ImGui::InvisibleButton("##dag_drop_zone", avail,
ImGuiButtonFlags_MouseButtonLeft | ImGuiButtonFlags_MouseButtonRight);
if (ImGui::BeginDragDropTarget()) {
if (const ImGuiPayload* p = ImGui::AcceptDragDropPayload("DAG_NODE_TYPE")) {
s_pending_add_name.assign(static_cast<const char*>(p->Data), static_cast<size_t>(p->DataSize));
s_pending_add_pos = ImGui::GetMousePos();
s_pending_add = true;
const bool window_hovered = ImGui::IsWindowHovered(
ImGuiHoveredFlags_ChildWindows | ImGuiHoveredFlags_AllowWhenBlockedByActiveItem);
if (window_hovered) {
if (const ImGuiPayload* p = ImGui::GetDragDropPayload()) {
if (p->IsDataType("DAG_NODE_TYPE") && ImGui::IsMouseReleased(ImGuiMouseButton_Left)) {
s_pending_add_name.assign(static_cast<const char*>(p->Data),
static_cast<size_t>(p->DataSize));
s_pending_add_pos = ImGui::GetMousePos();
s_pending_add = true;
}
}
ImGui::EndDragDropTarget();
}
ImGui::SetCursorScreenPos(origin);
ed::SetCurrentEditor(s_ctx);
ed::Begin("dag_editor", ImVec2(0.0f, 0.0f));