--- name: graph_viewport_selection kind: function lang: cpp domain: viz version: "1.0.0" purity: pure signature: "void graph_viewport_clear_selection(GraphData& graph, GraphViewportState& state); bool graph_viewport_is_selected(const GraphViewportState& state, int node_idx); 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)" description: "Helpers puros (sin ImGui ni OpenGL) para gestionar la multi-seleccion del viewport: clear, add, toggle, is_selected. Mantienen sincronizados state.selection (vector de indices) y nodes[i].flags (NF_SELECTED bit), ademas de state.selected_node como ultimo focus." tags: [graph, viewport, selection, pure, multi-select, testable] uses_functions: [] uses_types: ["GraphData_cpp_viz"] returns: [] returns_optional: false error_type: "" imports: [] tested: true tests: ["selection add/clear/toggle/is_selected", "out-of-range indices ignored"] test_file_path: "cpp/tests/test_graph_viewport.cpp" file_path: "cpp/functions/viz/graph_viewport_selection.cpp" framework: imgui params: - name: graph desc: "GraphData. Se modifica para setear/limpiar el bit NF_SELECTED en nodes[i].flags." - name: state desc: "GraphViewportState. Se modifica state.selection (vector de indices) y state.selected_node." - name: node_idx desc: "Indice del nodo. Si esta fuera de rango (negativo o >= node_count) la funcion es no-op." output: "graph_viewport_is_selected: bool (true si el indice esta en state.selection). El resto: void. selected_node se actualiza al ultimo indice añadido, o al ultimo de la lista al togglear, o -1 si la lista queda vacia." notes: "Issue 0049i. TU separado de graph_viewport.cpp para que los tests unitarios cubran la maquinaria de seleccion sin abrir ventana ImGui. Operaciones idempotentes: añadir un indice ya seleccionado es no-op; togglear lo elimina. Las apps que necesiten seleccion programatica (ej: 'select all of type X') deben usar estas funciones en lugar de tocar state.selection a mano." --- # graph_viewport_selection Helpers puros para multi-seleccion en `graph_viewport`. Viven en su propio TU para que los tests unitarios puedan verificar invariantes (clear deja todo a NF_SELECTED=0, toggle es involutivo, etc.) sin abrir ventana ImGui. ## API ```cpp void graph_viewport_clear_selection (GraphData& graph, GraphViewportState& state); bool graph_viewport_is_selected (const GraphViewportState& state, int node_idx); 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); ``` ## Invariantes - `state.selection` y `nodes[i].flags & NF_SELECTED` siempre coherentes — no modificar uno sin el otro. Estas funciones lo garantizan. - `state.selected_node` es el "ultimo focus": el ultimo añadido o, al togglear fuera, el ultimo de la lista; `-1` si la lista esta vacia. - Indices fuera de rango son no-op (no escriben memoria, no añaden basura). ## Composabilidad `graph_viewport` los usa internamente al click/Ctrl+click/Esc. Apps externas los usan para seleccion programatica: ```cpp // Seleccionar todos los nodos de tipo Person graph_viewport_clear_selection(g, state); for (int i = 0; i < g.node_count; ++i) { if (g.nodes[i].type_id == person_type_id) { graph_viewport_add_to_selection(g, state, i); } } ``` ## Tests Cubiertos en `cpp/tests/test_graph_viewport.cpp` — cubren add/clear/toggle/ is_selected y out-of-range.