diff --git a/apps/shaders_lab/shaders_lab.exe b/apps/shaders_lab/shaders_lab.exe index dbf0fa62..2c1d905a 100755 Binary files a/apps/shaders_lab/shaders_lab.exe and b/apps/shaders_lab/shaders_lab.exe differ diff --git a/cpp/functions/gfx/dag_node_editor.cpp b/cpp/functions/gfx/dag_node_editor.cpp index 2685d02b..0c7538c4 100644 --- a/cpp/functions/gfx/dag_node_editor.cpp +++ b/cpp/functions/gfx/dag_node_editor.cpp @@ -117,6 +117,14 @@ static bool topo_sort(std::vector& pipeline) { std::vector sorted; sorted.reserve(static_cast(n)); for (int idx : order) sorted.push_back(pipeline[static_cast(idx)]); + + // Force Output nodes to the back so all their dependencies live at smaller + // indices (compiler and cycle validator search strictly before the target). + std::stable_partition(sorted.begin(), sorted.end(), [](const DagStep& s) { + const DagNodeDef* d = dag_find(s.name); + return !(d && d->kind == DagKind::Output); + }); + pipeline = std::move(sorted); return true; } @@ -174,7 +182,15 @@ bool dag_node_editor(std::vector& pipeline) { ImVec2 canvas_pos = ed::ScreenToCanvas(s_pending_add_pos); step.editor_pos_x = canvas_pos.x; step.editor_pos_y = canvas_pos.y; - pipeline.push_back(step); + // Insert before the Output node so the Output stays at the back; + // otherwise new nodes can never be wired into it (compiler and + // cycle check only search indices strictly before the target). + auto insert_it = pipeline.end(); + for (auto it = pipeline.begin(); it != pipeline.end(); ++it) { + const DagNodeDef* d = dag_find(it->name); + if (d && d->kind == DagKind::Output) { insert_it = it; break; } + } + pipeline.insert(insert_it, step); changed = true; } s_pending_add = false; @@ -246,7 +262,15 @@ bool dag_node_editor(std::vector& pipeline) { } else if (ctrl.kind == DagControl::Kind::Color) { int pr = ctrl.param_idx[0]; if (pr >= 0 && pr + 2 < 4) { - ImGui::ColorEdit3(uid_lbl, &step.params[static_cast(pr)]); + // Suspend the node editor while the color picker popup is + // open so its clicks don't reach the canvas (and so the + // popup isn't clipped to the node bounds). + ed::Suspend(); + ImGui::ColorEdit3(uid_lbl, &step.params[static_cast(pr)], + ImGuiColorEditFlags_NoInputs | + ImGuiColorEditFlags_NoLabel | + ImGuiColorEditFlags_AlphaBar); + ed::Resume(); } } }