deargui-vpl/docs-classes.md

19 KiB

Class Diagram Overview

Compact class diagram showing key classes and their relationships.

┌─────────────────────────────────────┐
│         Application                 │
│  (Base application lifecycle)       │
├─────────────────────────────────────┤
│ +OnStart()                           │
│ +OnStop()                            │
│ +OnFrame(deltaTime)                  │
│ +TakeScreenshot()                    │
└──────────────┬──────────────────────┘
               │ extends
               ▼
┌─────────────────────────────────────┐
│           App                        │
│  (Main application class)            │
├─────────────────────────────────────┤
│ -m_Nodes: vector<Node>              │
│ -m_Links: vector<Link>               │
│ -m_RootContainers: vector<...>       │
│ -m_ActiveRootContainer: RootContainer│
│ +GetNextId(): int                    │
│ +FindNode(id): Node*                 │
│ +FindLink(id): Link*                 │
│ +FindPin(id): Pin*                   │
│ +SpawnBlockNode(type): Node*         │
│ +SpawnParameterNode(type): Node*     │
│ +SaveGraph()                         │
│ +LoadGraph()                         │
│ +ExecuteRuntimeStep()               │
│ +RenderNodes()                       │
│ +RenderLinks()                       │
└─┬────────────┬───────────────┬──────┘
  │            │               │
  │ manages    │ owns            │ uses
  │            │               │
  ▼            ▼               ▼
┌──────────────────────┐  ┌─────────┐  ┌──────────────┐
│   RootContainer      │  │  Node   │  │ BlockRegistry│
│ (File-based graph)   │  │         │  │ (Factory)    │
├──────────────────────┤  └────┬────┘  ├──────────────┤
│ -m_Filename: string  │       │       │ +CreateBlock()│
│ -m_IsDirty: bool     │       │ has   │ +Register()  │
│ +GetFilename()       │       ▼       └──────────────┘
│ +SetDirty()          │  ┌─────────┐
└──────────┬───────────┘  │  Block  │◄───┐
           │ extends      │         │    │
           ▼              ├─────────┤    │
┌──────────────────────┐ │ +Build() │    │ extends
│      Container        │ │ +Render()│    │
│ (Hierarchical group)  │ │ +Run()   │    │
├──────────────────────┤ │ +Activate│    │
│ -m_NodeIds: vector    │ │   Output()│    │
│ -m_LinkIds: vector    │ │ +Activate│    │
│ -m_Children: vector   │ │   Input() │    │
│ +GetNextId(): int     │ └────┬────┘    │
│ +AddNode()            │       │        │
│ +RemoveNode()          │       │        │
│ +GetNodes(): vector   │       │        │
│ +GetLinks(): vector   │       │        │
│ +Run()                │       │        │
│ +Render()              │       │        │
└──────────────────────┘       │        │
                               │        │
                               │        │
                  ┌────────────┴──┐    │
                  │                │    │
                  ▼                ▼    │
         ┌──────────────────┐  ┌──────────────────┐
         │ ParameterizedBlock│  │  ParameterNode   │
         │  (Block + params) │  │ (Value nodes)    │
         ├──────────────────┤  ├──────────────────┤
         │ -m_InputParams   │  │ -m_ID: int       │
         │ -m_OutputParams   │  │ -m_Name: string  │
         │ -m_Inputs         │  │ -m_Type: PinType │
         │ -m_Outputs        │  │ -m_BoolValue     │
         │ +AddInputParam()  │  │ -m_IntValue      │
         │ +AddOutputParam()  │  │ -m_FloatValue    │
         │ +AddInput()       │  │ +GetBool()       │
         │ +AddOutput()      │  │ +SetBool()       │
         └──────────────────┘  │ +Run()           │
                                │ +Render()         │
                                │ +Build()          │
                                └──────────────────┘
                                         ▲
                                         │ creates
                                         │
                                ┌──────────────────┐
                                │ParameterRegistry │
                                │   (Factory)      │
                                ├──────────────────┤
                                │ +CreateParameter()│
                                └──────────────────┘


┌──────────────────────────────────────┐
│        EditorContext                  │
│   (Core editor & rendering)          │
├──────────────────────────────────────┤
│ -m_Links: vector<Link*>               │
│ -m_Nodes: vector<Node*>               │
│ -m_GuidedLinks: map<LinkId, ...>     │
│ +CreateLink(id): Link*                │
│ +DrawNodes()                          │
│ +DrawLinks()                           │
│ +HandleControlPointDragging()         │
│ +HandleGuidedLinkInteractions()       │
│ +ExecuteRuntime()                     │
└───────┬────────────┬──────────────────┘
        │ manages    │ manages
        │            │
        ▼            ▼
   ┌─────────┐  ┌──────────────────┐
   │  Link   │  │   GuidedLink     │
   │         │  │ (Waypoint routing)│
   └─────────┘  ├──────────────────┤
                │ +ID: LinkId      │
                │ +Mode: LinkMode  │
                │ +ControlPoints  │
                │ +AddControlPoint() │
                │ +RemoveControlP()│
                │ +GetCurveSegm()  │
                └────┬─────────────┘
                     │ contains
                     ▼
              ┌──────────────────┐
              │  ControlPoint    │
              │ (Waypoint)       │
              ├──────────────────┤
              │ +Position: ImVec2│
              │ +IsManual: bool  │
              └──────────────────┘
                     ▲
                     │ persists
                     │
              ┌──────────────────┐
              │  LinkSettings    │
              │ (Persistence)    │
              ├──────────────────┤
              │ +m_ID: LinkId    │
              │ +m_Mode: LinkMode│
              │ +m_ControlPoints │
              │ +Serialize(): json│
              └──────────────────┘


Relationship Legend:
  ───►  = manages/owns (composition)
  ──..► = uses/creates (dependency)
  ──┬── = extends (inheritance)
  ──o── = has (aggregation)

Key Components

Application Layer

  • App: Main application class managing nodes, links, containers, and runtime execution
  • Extends Application base class for windowing and rendering

Block System

  • Block: Abstract base class for executable nodes
  • ParameterizedBlock: Block with input/output parameters and flow control
  • BlockRegistry: Factory pattern for creating block instances

Parameter System

Container System

  • Container: Hierarchical node/link grouping with ID management
  • RootContainer: Top-level container tied to a graph file

Editor System

Source Files Reference

Class Description Header File Implementation Files
Application Base application class for windowing, rendering, and lifecycle management examples/application/include/application.h -
App Main application class managing nodes, links, containers, graph persistence, and runtime execution examples/blueprints-example/app.h app-logic.cpp, app-render.cpp, app-runtime.cpp
Block Abstract base class for executable nodes with Build/Render/Run interface and activation API examples/blueprints-example/blocks/block.h blocks/*.cpp
ParameterizedBlock Block with input/output parameters and flow control pins examples/blueprints-example/blocks/block.h blocks/*.cpp
BlockRegistry Factory pattern registry for creating block instances by type name examples/blueprints-example/blocks/block.h -
ParameterNode Standalone value nodes (Bool/Int/Float/String) with editable display modes examples/blueprints-example/blocks/parameter_node.h blocks/parameter_node.cpp
ParameterRegistry Factory for creating parameter nodes by type examples/blueprints-example/blocks/parameter_node.h -
Container Hierarchical container for grouping nodes/links with ID management and safe pointer resolution examples/blueprints-example/containers/container.h containers/container.cpp
RootContainer Top-level container tied to a graph file, manages root-level nodes and links examples/blueprints-example/containers/root_container.h containers/root_container.cpp
EditorContext Core editor managing rendering, interactions, link management, and guided link editing imgui_node_editor_internal.h imgui_node_editor_render.cpp, imgui_node_editor_links.cpp
GuidedLink User-controllable waypoints for custom link routing with control point management links-guided.h imgui_node_editor_links.cpp
ControlPoint Individual waypoint on a guided link with manual/auto placement flags links-guided.h -
LinkSettings Persistence structure for guided link configuration (mode, control points, snap settings) links-guided.h -

Key Methods

App Core Operations

  • SaveGraph() / LoadGraph(): Graph persistence
  • ExecuteRuntimeStep(): Process activated blocks
  • RenderNodes() / RenderLinks(): Visual rendering
  • FindNode() / FindLink() / FindPin(): ID-based lookups

Block Execution

  • Block::Run(): Execute block logic
  • Block::ActivateOutput() / ActivateInput(): Flow control
  • Block::Build(): Create node structure with pins
  • Block::Render(): Custom rendering per block

Container Management

  • Container::GetNodes() / GetLinks(): Safe ID-to-pointer resolution
  • Container::GetNextId(): Unique ID generation
  • Container::Run(): Execute container contents

Editor Rendering

  • EditorContext::DrawNodes() / DrawLinks(): Core rendering
  • EditorContext::HandleGuidedLinkInteractions(): Waypoint editing
  • EditorContext::ExecuteRuntime(): Runtime integration point

Simplification Suggestions

Core API Requirements

The imgui_node_editor.h API only requires:

  • NodeId, LinkId, PinId: Type-safe IDs (already used correctly)
  • BeginNode()/EndNode(): Node creation blocks
  • BeginPin()/EndPin(): Pin creation blocks
  • Link(): Create link between two PinIds
  • QueryNewLink/QueryNewNode: Creation callbacks
  • QueryDeletedNode/QueryDeletedLink: Deletion callbacks
  • GetNodePosition/SetNodePosition: Position management

The editor does NOT require:

  • Container/grouping hierarchy
  • Complex inheritance chains
  • Registry/factory patterns
  • Duplicate storage systems

🗑️ Candidates for Removal/Simplification

1. Container System Redundancy ⚠️ HIGH IMPACT

Problem: App stores nodes/links in both m_Nodes/m_Links AND RootContainer::m_NodeIds/m_LinkIds

  • Core API works with IDs directly - doesn't need containers
  • Double storage = sync complexity + pointer invalidation risks
  • GetNodes()/GetLinks() converts IDs→pointers unnecessarily

Suggestion:

  • Remove Container/RootContainer entirely OR
  • Make Container just a grouping/visual feature (nodes still in App's flat list)
  • Use std::map<NodeId, Node*> for O(1) lookups instead of ID vectors

Files affected: containers/container.h, containers/root_container.h, app-logic.cpp (GetNodes/GetLinks calls)


2. Registry Pattern Overhead ⚠️ MEDIUM IMPACT

Problem: BlockRegistry and ParameterRegistry are singleton factories that just map strings to constructors

  • Adds indirection for simple "create by type name" operations
  • Could be simple function tables or even switch statements

Suggestion:

  • Replace with std::function<Block*(int)> map directly in App
  • OR use simple switch(typeName) if block types are finite
  • Keep factories only if you need dynamic plugin loading

Files affected: blocks/block.h (registry), app-logic.cpp (CreateBlock calls)


3. Block vs ParameterizedBlock Inheritance ⚠️ MEDIUM IMPACT

Problem: Two-level inheritance when most/all blocks need parameters anyway

  • Base Block is abstract but has minimal functionality
  • ParameterizedBlock adds params, but could just be the base class

Suggestion:

  • Merge Block and ParameterizedBlock into single Block class
  • OR make ParameterizedBlock the base, drop abstract Block if unused
  • Check if any blocks actually use base Block without parameters

Files affected: blocks/block.h, all block implementations


Problem: LinkSettings (for persistence) and GuidedLink (for runtime) store same data

  • Two structures for same concept = sync complexity

Suggestion:

  • Merge into single structure with Serialize() method
  • OR make GuidedLink contain LinkSettings directly
  • Eliminates conversion between formats

Files affected: links-guided.h, save/load code


5. Node Instance Union Pattern ⚠️ LOW IMPACT

Problem: Node stores either BlockInstance* OR ParameterInstance* (mutually exclusive)

  • Requires runtime type checking (IsBlockBased(), GetBlockInstance(), etc.)
  • Could use std::variant<Block*, ParameterNode*> or simpler approach

Suggestion:

  • Use std::variant for type safety OR
  • Separate BlockNode and ParameterNode completely (no shared base)
  • Current pattern works but adds complexity

Files affected: types.h (Node struct), rendering/runtime code


Problem: Container stores IDs in vectors, then converts to pointers via App::FindNode()

  • Adds indirection layer, performance overhead (though minimal)
  • Pointer invalidation risks when vectors resize

Suggestion:

  • Store pointers directly if Container system is kept
  • OR use std::unordered_map<NodeId, Node*> for O(1) lookup
  • Current ID-based storage is safer but adds complexity

Files affected: containers/container.cpp (GetNodes/GetLinks implementations)


What to Keep

  • Block abstraction: Good separation of concerns (Build/Render/Run)
  • Activation API: Useful for flow control in runtime
  • Guided Links: Core feature, keep but simplify persistence
  • ID-based lookups: Type safety is valuable, but consider maps vs vectors

📊 Impact Summary

Simplification Impact Effort Priority
Remove Container system HIGH HIGH
Simplify Registry MEDIUM LOW
Merge Block inheritance MEDIUM MEDIUM
Merge LinkSettings LOW LOW
Simplify Node instances LOW MEDIUM

Before removing anything, verify:

  1. Are containers used for anything beyond tracking node/link ownership? (groups? nesting?)
  2. Do any blocks actually inherit from Block directly without parameters?
  3. Can we prove Container system adds value beyond App's flat storage?
  4. What percentage of code deals with Container vs direct Node/Link access?

Core Insight: The editor API works with IDs. Your abstractions should minimize conversion between IDs ↔ pointers ↔ containers.