#pragma once #include "imgui.h" #include struct GraphData; struct GraphRenderer; struct SpatialHash; // Callbacks opcionales del viewport. Se invocan dentro del frame ImGui — el // caller puede abrir popups (`ImGui::OpenPopup`) o cambiar estado de la app. // Cualquier puntero NULL se ignora. struct GraphViewportCallbacks { void (*on_context_menu)(int node_idx, ImVec2 screen_pos, void* user) = nullptr; void (*on_double_click)(int node_idx, void* user) = nullptr; void* user = nullptr; }; // Persistent state for graph_viewport widget. Create one per viewport and keep // alive across frames. struct GraphViewportState { // Camera float cam_x = 0.0f, cam_y = 0.0f; float zoom = 1.0f; float zoom_min = 0.01f, zoom_max = 50.0f; // Interaction result (read after calling graph_viewport each frame) int hovered_node = -1; // node index under cursor, -1 if none int selected_node = -1; // legacy: ultimo nodo clicado, -1 si ninguno bool is_dragging = false; // Multi-seleccion (issue 0049i). `selection` mantiene los indices de // todos los nodos seleccionados (orden de insercion). El flag NF_SELECTED // se mantiene sincronizado con esta lista. std::vector selection; // Lasso (issue 0049i). Activado durante Shift+Drag sobre area vacia. // Coordenadas en world space. bool lasso_active = false; ImVec2 lasso_start = ImVec2(0.0f, 0.0f); ImVec2 lasso_end = ImVec2(0.0f, 0.0f); // Layout bool layout_running = true; // animate force layout each frame float layout_energy = 0.0f; // kinetic energy from last step // Internal — managed by graph_viewport / graph_viewport_destroy GraphRenderer* renderer = nullptr; SpatialHash* spatial = nullptr; bool initialized = false; // Widget pixel dimensions tracked for resize detection int render_w = 0, render_h = 0; // Node being dragged (-1 = none). Si hay multi-seleccion, todos los // seleccionados se mueven solidariamente con el delta del raton. int drag_node = -1; // Posicion world del raton al iniciar el drag (issue 0049i). float drag_anchor_x = 0.0f; float drag_anchor_y = 0.0f; }; // Main viewport widget. Call every ImGui frame. // id: unique ImGui widget identifier // graph: mutable graph data (node positions updated on drag) // state: persistent state (camera, selection, GPU renderer); must outlive frames // size: widget size in pixels — ImVec2(0,0) uses all available space // cb: callbacks opcionales (right-click, double-click). Default = sin callbacks. // Returns true if any user interaction occurred (hover, click, drag, zoom). bool graph_viewport(const char* id, GraphData& graph, GraphViewportState& state, ImVec2 size = ImVec2(0.0f, 0.0f), const GraphViewportCallbacks& cb = GraphViewportCallbacks{}); // Release GPU resources. Call once when done with the viewport. void graph_viewport_destroy(GraphViewportState& state); // Fit camera to current graph bounds with 10% padding. void graph_viewport_fit(GraphData& graph, GraphViewportState& state); // Helpers de multi-seleccion (puros respecto al state). Mantienen // NF_SELECTED sincronizado. void graph_viewport_clear_selection(GraphData& graph, GraphViewportState& state); void graph_viewport_add_to_selection(GraphData& graph, GraphViewportState& state, int node_idx); void graph_viewport_toggle_selection(GraphData& graph, GraphViewportState& state, int node_idx); bool graph_viewport_is_selected(const GraphViewportState& state, int node_idx);