diff --git a/src/gui/node_editor.h b/src/gui/node_editor.h new file mode 100644 index 0000000..33437d9 --- /dev/null +++ b/src/gui/node_editor.h @@ -0,0 +1,112 @@ +#pragma once + +#include +#include + +#define IMGUI_DEFINE_MATH_OPERATORS +#include +#include + +#include "../geom.h" + +class GuiNode { +public: + GuiNode(std::string name, Rect bbox) + : name(name), bbox(bbox) + {} + +protected: + friend class NodeEditor; + + std::string name; + + Rect bbox; +}; + +class NodeEditor { +public: + NodeEditor() { + nodeList.emplace_back("hi", Rect(10, 10, 60, 60)); + nodeList.emplace_back("hi2", Rect(10, 80, 60, 60)); + } + + void draw_window(const char *title, bool *opened) { + ImGui::SetNextWindowSize(ImVec2(700,600), ImGuiSetCond_FirstUseEver); + if (ImGui::Begin(title, opened)) { + // -- Create child canvas + ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(1,1)); + ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(0,0)); + ImGui::PushStyleColor(ImGuiCol_ChildWindowBg, ImColor(60,60,70,200)); + ImGui::BeginChild("nodes_region", ImVec2(0, 0), true, ImGuiWindowFlags_NoScrollbar|ImGuiWindowFlags_NoMove); + + // -- Prepare to draw + // Get the draw list for this canvas + ImDrawList* draw_list = ImGui::GetWindowDrawList(); + draw_list->ChannelsSplit(2); + + // this gets the offset to the upper-right corner of the child canvas. + // Note: here, cursor means "draw cursor", not "mouse pointing cursor". + ImVec2 canvas_pos = ImGui::GetCursorScreenPos(); + ImVec2 canvas_size = ImGui::GetWindowSize(); + + ImVec2 offset = canvas_pos - scrolling; // TODO: add scrolling + + // -- Draw the grid + if (show_grid) { + ImVec2 local_offset = ImGui::GetCursorPos() - scrolling; + + float spacing = 32.0f; ImU32 color = IM_COL32(200, 200, 200, 40); + + for (float x = fmodf(local_offset.x, spacing); x < canvas_size.x; x += spacing) + draw_list->AddLine(ImVec2(x, 0.0f)+canvas_pos, + ImVec2(x, canvas_size.y)+canvas_pos, color); + for (float y = fmodf(local_offset.y, spacing); y < canvas_size.y; y += spacing) + draw_list->AddLine(ImVec2(0.0f, y)+canvas_pos, + ImVec2(canvas_size.x, y)+canvas_pos, color); + } + + Rect viewportRect = Rect(scrolling, canvas_size); + + for (const auto &node : nodeList) { + bool visible = viewportRect.intersects(node.bbox); + if (visible) { + // -- Draw the node boxes + draw_list->ChannelsSetCurrent(0); // Switch to the background layer + + ImVec2 upper_left = offset + node.bbox.pos; + ImVec2 lower_right = upper_left + node.bbox.size; + + draw_list->AddRectFilled(upper_left, lower_right, ImColor(60, 60, 60), 4.0f); + draw_list->AddRect(upper_left, lower_right, ImColor(100, 100, 100), 4.0f); + + // for (int i=0; iAddCircleFilled(offset + position, 4.0f, ImColor(150, 150, 150, 150)); + // } + } + } + + // -- merge channels back together + draw_list->ChannelsMerge(); + + // -- scrolling! + // [ pointer over neditor ] [ not interacting ctrls ] [ middle mouse dragging ] + if (ImGui::IsWindowHovered() && !ImGui::IsAnyItemActive() && ImGui::IsMouseDragging(2, 0.0f)) + scrolling = scrolling - ImGui::GetIO().MouseDelta; + + // -- clean up + ImGui::EndChild(); // end :nodes_region + ImGui::PopStyleColor(); // pop ChildWindowBg + ImGui::PopStyleVar(2); // pop FramePadding, WindowPadding + } + ImGui::End(); + } + +private: + std::vector nodeList; + + ImVec2 scrolling = ImVec2(0.0f, 0.0f); + bool show_grid = true; +};