fix(fn-run): propagar stdout/stderr de bash functions library-style #1
Binary file not shown.
@@ -70,19 +70,19 @@ static ImVec4 kind_color(DagKind kind) {
|
||||
return ImVec4(1, 1, 1, 1);
|
||||
}
|
||||
|
||||
static constexpr float PIN_RADIUS = 7.0f;
|
||||
static constexpr float PIN_RADIUS = 9.0f;
|
||||
static constexpr float PIN_DIAMETER = PIN_RADIUS * 2.0f;
|
||||
static const ImVec4 PIN_COLOR = ImVec4(0.78f, 0.78f, 0.82f, 1.0f);
|
||||
static const ImVec4 PIN_BORDER = ImVec4(0.20f, 0.20f, 0.22f, 1.0f);
|
||||
|
||||
// Draws a filled circle of `color` and reserves a 14x14 dummy item so the
|
||||
// node editor can compute the pin's hit rect from the surrounding BeginPin.
|
||||
// Adds an outline in a slightly darker tone for visibility.
|
||||
static void draw_pin_circle(ImVec4 color) {
|
||||
// Draws a filled circle and reserves a (PIN_DIAMETER × PIN_DIAMETER) item.
|
||||
// All pins use the same neutral color since the data type is uniform (vec4).
|
||||
static void draw_pin_circle() {
|
||||
ImVec2 cursor = ImGui::GetCursorScreenPos();
|
||||
ImVec2 center = ImVec2(cursor.x + PIN_RADIUS, cursor.y + PIN_RADIUS);
|
||||
ImDrawList* dl = ImGui::GetWindowDrawList();
|
||||
dl->AddCircleFilled(center, PIN_RADIUS, ImGui::ColorConvertFloat4ToU32(color));
|
||||
ImVec4 border(color.x * 0.4f, color.y * 0.4f, color.z * 0.4f, 1.0f);
|
||||
dl->AddCircle(center, PIN_RADIUS, ImGui::ColorConvertFloat4ToU32(border), 0, 1.5f);
|
||||
dl->AddCircleFilled(center, PIN_RADIUS, ImGui::ColorConvertFloat4ToU32(PIN_COLOR));
|
||||
dl->AddCircle(center, PIN_RADIUS, ImGui::ColorConvertFloat4ToU32(PIN_BORDER), 0, 1.5f);
|
||||
ImGui::Dummy(ImVec2(PIN_DIAMETER, PIN_DIAMETER));
|
||||
}
|
||||
|
||||
@@ -233,19 +233,24 @@ bool dag_node_editor(std::vector<DagStep>& pipeline) {
|
||||
s_positioned.insert(step.editor_uid);
|
||||
}
|
||||
|
||||
// Zero lateral padding so the input/output pin circles sit flush
|
||||
// with the node's left and right edges.
|
||||
ed::PushStyleVar(ed::StyleVar_NodePadding, ImVec4(0, 8, 0, 8));
|
||||
ed::BeginNode(ed::NodeId(node_id(step.editor_uid)));
|
||||
|
||||
// Header
|
||||
// Header (with horizontal padding so the title doesn't touch the edge)
|
||||
ImGui::Dummy(ImVec2(8, 0));
|
||||
ImGui::SameLine(0, 0);
|
||||
ImGui::PushStyleColor(ImGuiCol_Text, col);
|
||||
ImGui::TextUnformatted(def->label.c_str());
|
||||
ImGui::PopStyleColor();
|
||||
ImGui::Dummy(ImVec2(0, 2));
|
||||
ImGui::Dummy(ImVec2(0, 4));
|
||||
|
||||
int ni = def->num_inputs;
|
||||
bool has_output_pin = (def->kind != DagKind::Output);
|
||||
|
||||
// ── Three-column layout: inputs · controls · output ──────────
|
||||
ImGui::BeginGroup(); // inputs column
|
||||
ImGui::BeginGroup(); // inputs column (left edge)
|
||||
if (ni == 0) {
|
||||
ImGui::Dummy(ImVec2(PIN_DIAMETER, PIN_DIAMETER));
|
||||
}
|
||||
@@ -253,14 +258,14 @@ bool dag_node_editor(std::vector<DagStep>& pipeline) {
|
||||
ed::BeginPin(ed::PinId(input_pin_id(step.editor_uid, k)), ed::PinKind::Input);
|
||||
ed::PinPivotAlignment(ImVec2(0.0f, 0.5f));
|
||||
ed::PinPivotSize(ImVec2(0, 0));
|
||||
draw_pin_circle(col);
|
||||
draw_pin_circle();
|
||||
ed::EndPin();
|
||||
}
|
||||
ImGui::EndGroup();
|
||||
|
||||
ImGui::SameLine();
|
||||
ImGui::SameLine(0, 8); // gap between pin column and controls
|
||||
|
||||
ImGui::BeginGroup(); // controls column
|
||||
ImGui::BeginGroup(); // controls column (centre, with internal padding)
|
||||
ImGui::PushID(static_cast<int>(step.editor_uid));
|
||||
if (def->controls.empty() && def->kind != DagKind::Output) {
|
||||
ImGui::Dummy(ImVec2(60, PIN_DIAMETER));
|
||||
@@ -295,14 +300,14 @@ bool dag_node_editor(std::vector<DagStep>& pipeline) {
|
||||
ImGui::PopID();
|
||||
ImGui::EndGroup();
|
||||
|
||||
ImGui::SameLine();
|
||||
ImGui::SameLine(0, 8); // gap between controls and output pin
|
||||
|
||||
ImGui::BeginGroup(); // output column
|
||||
ImGui::BeginGroup(); // output column (right edge)
|
||||
if (has_output_pin) {
|
||||
ed::BeginPin(ed::PinId(output_pin_id(step.editor_uid)), ed::PinKind::Output);
|
||||
ed::PinPivotAlignment(ImVec2(1.0f, 0.5f));
|
||||
ed::PinPivotSize(ImVec2(0, 0));
|
||||
draw_pin_circle(col);
|
||||
draw_pin_circle();
|
||||
ed::EndPin();
|
||||
} else {
|
||||
ImGui::Dummy(ImVec2(PIN_DIAMETER, PIN_DIAMETER));
|
||||
@@ -310,6 +315,7 @@ bool dag_node_editor(std::vector<DagStep>& pipeline) {
|
||||
ImGui::EndGroup();
|
||||
|
||||
ed::EndNode();
|
||||
ed::PopStyleVar();
|
||||
}
|
||||
|
||||
// ── Draw existing links ──────────────────────────────────────────────────
|
||||
@@ -323,12 +329,10 @@ bool dag_node_editor(std::vector<DagStep>& pipeline) {
|
||||
int src_idx = find_by_id(pipeline, sid);
|
||||
if (src_idx < 0) continue;
|
||||
const DagStep& src_step = pipeline[static_cast<size_t>(src_idx)];
|
||||
const DagNodeDef* src_def = dag_find(src_step.name);
|
||||
ImVec4 link_col = src_def ? kind_color(src_def->kind) : ImVec4(0.7f, 0.7f, 0.7f, 1.0f);
|
||||
ed::Link(ed::LinkId(link_id(src_step.editor_uid, step.editor_uid, k)),
|
||||
ed::PinId(output_pin_id(src_step.editor_uid)),
|
||||
ed::PinId(input_pin_id(step.editor_uid, k)),
|
||||
link_col, 2.5f);
|
||||
PIN_COLOR, 2.5f);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -349,6 +353,37 @@ bool dag_node_editor(std::vector<DagStep>& pipeline) {
|
||||
ed::Resume();
|
||||
}
|
||||
|
||||
// ── Right-click on a pin clears all connections of that pin ────────────
|
||||
{
|
||||
ed::Suspend();
|
||||
ed::PinId ctx_pid;
|
||||
if (ed::ShowPinContextMenu(&ctx_pid)) {
|
||||
uintptr_t raw = ctx_pid.Get();
|
||||
uint32_t uid = uid_from_pin(raw);
|
||||
if (is_output_pin(raw)) {
|
||||
// Output pin: clear every source_ids entry pointing to this node
|
||||
int idx = find_by_uid(pipeline, uid);
|
||||
if (idx >= 0) {
|
||||
const std::string source_id = pipeline[static_cast<size_t>(idx)].id;
|
||||
for (auto& s : pipeline) {
|
||||
for (auto& sid : s.source_ids) {
|
||||
if (sid == source_id) { sid.clear(); changed = true; }
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// Input pin: clear that single slot
|
||||
int slot = slot_from_input_pin(raw);
|
||||
int idx = find_by_uid(pipeline, uid);
|
||||
if (idx >= 0 && slot >= 0 && slot < 4) {
|
||||
auto& sid = pipeline[static_cast<size_t>(idx)].source_ids[static_cast<size_t>(slot)];
|
||||
if (!sid.empty()) { sid.clear(); changed = true; }
|
||||
}
|
||||
}
|
||||
}
|
||||
ed::Resume();
|
||||
}
|
||||
|
||||
// ── Handle link creation ─────────────────────────────────────────────────
|
||||
if (ed::BeginCreate()) {
|
||||
ed::PinId start_pin, end_pin;
|
||||
|
||||
Reference in New Issue
Block a user