feat(viz): graph_types modelo extendido + EntityType/RelationType + flags (issue 0049e)
Extiende el modelo agnostico de graph_types.h para soportar shapes/iconos/ filtros/labels/streaming sin acoplar a backend. Migra el unico consumer (demos_graph) en el mismo cambio. - GraphNode v2: type_id + shape_override/color_override/size_override + flags (NF_PINNED/VISIBLE/SELECTED/HOVERED) + label_idx + user_data. - GraphEdge v2: type_id + style_override + flags (EF_DIRECTED/VISIBLE). - EntityType / RelationType: tablas en GraphData (types, rel_types). - Helpers de resolucion (resolve_node_color/shape/size, resolve_edge_*) y constructores ergonomicos (graph_node, graph_edge, entity_type, relation_type) — sentinel-based para herencia automatica del tipo. - graph_renderer v1.4: lee NF_VISIBLE / EF_VISIBLE, resuelve apariencia via override → EntityType → fallback indexado por type_id. Skipea aristas con endpoints invisibles. Shapes siguen pintandose como circulo (0049f cableara el dispatch real). - graph_force_layout v1.2: pinned ahora vive en flags & NF_PINNED. - graph_viewport v1.1: hover/seleccion publican NF_HOVERED/SELECTED en el grafo (clear-then-set). Drag usa NF_PINNED. Tooltip muestra Type/ user_data en lugar de community/value/label. - demos_graph: 8 EntityType (paleta antigua) + 1 RelationType. type_id por cluster. user_data = indice numerico del nodo. Apariencia visual identica al pre-cambio. - test_graph_types.cpp: 12 casos cubriendo helpers, defaults, bitmask manipulation y resoluciones override-vs-EntityType. test_graph_edge_ static actualizado al nuevo modelo (ya no tiene .color directo). - 4 .md de tipos nuevos (graph_node, graph_edge, entity_type, relation_type) + GraphData v2.0 actualizado. Tests: 31/31 ctest verdes (incluye test_visual golden). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -13,19 +13,24 @@
|
||||
#include <algorithm>
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Community palette (ABGR packed, 10 colors)
|
||||
// Fallback palette (RGBA8 con R en LSB) — usada solo cuando GraphData::types
|
||||
// esta vacio. En el modelo extendido (issue 0049e) la apariencia de cada
|
||||
// nodo viene resuelta por `resolve_node_color()`, que mira primero el
|
||||
// override del nodo, luego el EntityType de la tabla, y finalmente este
|
||||
// fallback. Mantener 10 colores para nodos sin tipos sigue siendo util en
|
||||
// demos que aun no construyen tablas EntityType.
|
||||
// ---------------------------------------------------------------------------
|
||||
static const uint32_t k_palette[10] = {
|
||||
0xFF4CAF50, // green
|
||||
0xFFF44336, // red
|
||||
0xFF2196F3, // blue
|
||||
0xFFFF9800, // orange
|
||||
0xFF9C27B0, // purple
|
||||
0xFF00BCD4, // cyan
|
||||
0xFFFFEB3B, // yellow
|
||||
0xFFE91E63, // pink
|
||||
0xFF795548, // brown
|
||||
0xFF607D8B // blue-grey
|
||||
static const uint32_t k_fallback_palette[10] = {
|
||||
0xFF4CAF50u, // green
|
||||
0xFFF44336u, // red
|
||||
0xFF2196F3u, // blue
|
||||
0xFFFF9800u, // orange
|
||||
0xFF9C27B0u, // purple
|
||||
0xFF00BCD4u, // cyan
|
||||
0xFFFFEB3Bu, // yellow
|
||||
0xFFE91E63u, // pink
|
||||
0xFF795548u, // brown
|
||||
0xFF607D8Bu, // blue-grey
|
||||
};
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
@@ -562,8 +567,17 @@ unsigned int graph_renderer_draw(GraphRenderer* r, const GraphData& graph,
|
||||
const GraphEdge& e = graph.edges[i];
|
||||
if (e.source >= (uint32_t)graph.node_count) continue;
|
||||
if (e.target >= (uint32_t)graph.node_count) continue;
|
||||
uint32_t col = e.color != 0 ? e.color
|
||||
: pack_rgba8(0x88, 0x88, 0x88, 0xFF);
|
||||
if (!(e.flags & EF_VISIBLE)) continue;
|
||||
// Saltamos aristas cuyos endpoints no estan visibles —
|
||||
// el shader las pintaria igualmente (las posiciones siguen
|
||||
// en el TBO) pero la aristas tendrian apariencia conectando
|
||||
// "vacios" si los nodos estan ocultos por NF_VISIBLE off.
|
||||
if (!(graph.nodes[e.source].flags & NF_VISIBLE)) continue;
|
||||
if (!(graph.nodes[e.target].flags & NF_VISIBLE)) continue;
|
||||
|
||||
uint32_t col = resolve_edge_color(e, graph.rel_types,
|
||||
graph.rel_type_count);
|
||||
if (col == 0u) col = pack_rgba8(0x88, 0x88, 0x88, 0xFF);
|
||||
r->edge_static_staging[out++] = { e.source, e.target, col, 0u };
|
||||
}
|
||||
if (out > 0) {
|
||||
@@ -625,13 +639,27 @@ unsigned int graph_renderer_draw(GraphRenderer* r, const GraphData& graph,
|
||||
size_t visible = 0;
|
||||
for (int i = 0; i < graph.node_count; ++i) {
|
||||
const GraphNode& n = graph.nodes[i];
|
||||
float sz = n.size > 0.0f ? n.size : 4.0f;
|
||||
if (!(n.flags & NF_VISIBLE)) continue;
|
||||
|
||||
float sz = resolve_node_size(n, graph.types, graph.type_count);
|
||||
if (sz <= 0.0f) sz = 4.0f;
|
||||
float half = sz * 0.5f;
|
||||
// AABB del nodo: centro ± half. Skip si fuera del viewport.
|
||||
if (n.x + half < vx0 || n.x - half > vx1) continue;
|
||||
if (n.y + half < vy0 || n.y - half > vy1) continue;
|
||||
|
||||
uint32_t ncol = n.color != 0 ? n.color : k_palette[n.community % 10];
|
||||
// Apariencia: 1) override del nodo, 2) EntityType, 3) fallback
|
||||
// indexado por type_id (paleta de 10 — sustituye al community
|
||||
// del modelo v1).
|
||||
uint32_t ncol;
|
||||
if (n.color_override != 0u) {
|
||||
ncol = n.color_override;
|
||||
} else if (graph.types && n.type_id < (uint16_t)graph.type_count) {
|
||||
ncol = graph.types[n.type_id].color;
|
||||
} else {
|
||||
ncol = k_fallback_palette[n.type_id % 10];
|
||||
}
|
||||
// 0049f anadira el dispatch de shape; por ahora todos circulos.
|
||||
r->node_staging[visible++] = { n.x, n.y, sz, ncol };
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user