239 lines
7.7 KiB
Markdown
239 lines
7.7 KiB
Markdown
# BehaviorGraph Container-Based Architecture
|
|
|
|
|
|
**Core Principle:** All nodes, links, blocks exist within **containers**. Containers manage, run, and render their contents.
|
|
|
|
**Key Insight:** The app can have **multiple root containers**, each loaded from a separate file. Each root container represents a separate graph/document/workspace.
|
|
|
|
```
|
|
App
|
|
├── RootContainer1 (loaded from file1.json)
|
|
│ ├── Node A
|
|
│ ├── Node B
|
|
│ └── BehaviorGraph Container (Group 1)
|
|
│ ├── Node C
|
|
│ └── BehaviorGraph Container (Nested Group)
|
|
│ └── Node D
|
|
│
|
|
├── RootContainer2 (loaded from file2.json)
|
|
│ ├── Node E
|
|
│ └── Node F
|
|
│
|
|
└── RootContainer3 (loaded from file3.json)
|
|
└── BehaviorGraph Container (Group 2)
|
|
└── Node G
|
|
```
|
|
|
|
## Architecture Overview
|
|
|
|
### Container Hierarchy
|
|
- **App Level**
|
|
- Has **multiple root containers** (one per loaded file/graph)
|
|
- Each root container is a separate workspace/graph
|
|
- **Root Container** (one per file/graph)
|
|
- Contains top-level nodes for that graph
|
|
- Contains top-level groups for that graph
|
|
- Loaded from a single file
|
|
- **Group Containers** (BehaviorGraph instances)
|
|
- Contain inner nodes
|
|
- Can contain nested groups
|
|
- Have their own pin interface (for external connections)
|
|
|
|
### Key Benefits
|
|
1. **No Duplication**: Each node exists in exactly ONE container
|
|
2. **Clear Ownership**: Container owns its nodes/links
|
|
3. **Clean Separation**: Containers handle management, execution, rendering
|
|
4. **Natural Nesting**: Groups are just containers within containers
|
|
5. **Unified Interface**: Root and groups use same container interface
|
|
6. **State Management**: Containers have flags (hidden, active/disabled, running, error)
|
|
|
|
|
|
|
|
### App Structure Changes
|
|
|
|
### 2. Group Creation
|
|
|
|
|
|
**After:**
|
|
- Create BehaviorGraph container within **current active root container**
|
|
- Move selected nodes from active root container → group container
|
|
- Move links (internal links stay, external links need group pins)
|
|
- Group container owns these nodes now
|
|
- Groups belong to the root container they were created in
|
|
|
|
### 3. Rendering
|
|
|
|
- Render **active root container** (or all root containers if multi-view)
|
|
- Root container renders its nodes
|
|
- Root container renders its child containers (groups)
|
|
- Each container renders its own contents
|
|
- Different root containers can be in different tabs/views
|
|
|
|
### 4. Runtime Execution
|
|
|
|
|
|
**After:**
|
|
- **Active root container** runs (or all if running all graphs)
|
|
- Container iterates its nodes
|
|
- If node is a container (BehaviorGraph), call container->Run()
|
|
- Nested containers run recursively
|
|
- Each root container executes independently (or can be cross-container?)
|
|
|
|
### 5. Serialization
|
|
**Before:**
|
|
- Save all nodes
|
|
- Save groups with `m_ParentGroup` references
|
|
- Link up later
|
|
|
|
**After:**
|
|
- **Each root container saves to its own file**
|
|
- Save container hierarchy (root container + all nested groups)
|
|
- Each container saves its nodes/links
|
|
- Natural tree structure per file
|
|
- Multiple files = multiple root containers
|
|
|
|
|
|
|
|
### Introduces:
|
|
- ✅ Clean ownership model
|
|
- ✅ Natural nesting (containers in containers)
|
|
- ✅ Unified interface (root = container, groups = containers)
|
|
- ✅ Easier serialization (tree structure)
|
|
- ✅ Cleaner rendering (containers render themselves)
|
|
- ✅ State management (hidden, active/disabled, running, error flags)
|
|
|
|
|
|
### New Approach (Container)
|
|
```
|
|
App::m_RootContainers = [root1, root2]
|
|
RootContainer1::m_Nodes = [node1, node2]
|
|
RootContainer1::m_Children = [BehaviorGraphContainer1]
|
|
BehaviorGraphContainer1::m_Nodes = [node3, node4] // MOVED from root1
|
|
RootContainer2::m_Nodes = [node5, node6]
|
|
|
|
// Nodes exist in exactly ONE container
|
|
// No duplication, no parent tracking needed
|
|
// Each root container is independent (separate file/graph)
|
|
```
|
|
|
|
# Architecture Decision: Container-Based vs Node-Based
|
|
|
|
|
|
### Core Principle
|
|
**Everything lives in a container.** Containers own their contents (nodes, links, nested containers).
|
|
|
|
```
|
|
Root Container (implicit, always exists)
|
|
├── Node A
|
|
├── Node B
|
|
├── BehaviorGraph Container (Group 1)
|
|
│ ├── Node C
|
|
│ ├── Node D
|
|
│ └── BehaviorGraph Container (Nested Group)
|
|
│ └── Node E
|
|
└── Node F
|
|
```
|
|
|
|
### Key Concepts
|
|
|
|
1. **Single Ownership**: Each node/link exists in exactly ONE container
|
|
2. **Hierarchical**: Containers can contain other containers (natural nesting)
|
|
3. **Unified Interface**: Root and groups use the same container API
|
|
4. **Clean Separation**: Container handles management, execution, rendering
|
|
|
|
### Implementation Structure
|
|
|
|
```cpp
|
|
class Container
|
|
{
|
|
// Ownership
|
|
std::vector<Node*> m_Nodes; // Nodes in this container
|
|
std::vector<Link*> m_Links; // Links in this container
|
|
std::vector<Container*> m_Children; // Nested containers (groups)
|
|
|
|
// Interface (for groups only - root has no interface)
|
|
std::vector<GroupPin> m_InputFlowPins;
|
|
std::vector<GroupPin> m_OutputFlowPins;
|
|
std::vector<GroupPin> m_InputParamPins;
|
|
std::vector<GroupPin> m_OutputParamPins;
|
|
|
|
// Virtual connections (group pin → inner node pin)
|
|
std::map<ed::PinId, ed::PinId> m_GroupToInnerPins;
|
|
|
|
// Management
|
|
void AddNode(Node* node);
|
|
void RemoveNode(Node* node);
|
|
void AddLink(Link* link);
|
|
void RemoveLink(Link* link);
|
|
|
|
// Execution
|
|
void Run(App* app); // Execute container contents
|
|
|
|
// Rendering
|
|
void Render(App* app, Pin* newLinkPin);
|
|
|
|
// Query
|
|
Container* FindContainer(NodeId nodeId);
|
|
};
|
|
|
|
class BehaviorGraph : public Container, public ParameterizedBlock
|
|
{
|
|
// BehaviorGraph IS a container
|
|
// Also acts as a block (for runtime execution)
|
|
// Has group-specific UI (collapsed/expanded modes)
|
|
};
|
|
|
|
class App
|
|
{
|
|
Container* m_RootContainer; // Default container for top-level items
|
|
|
|
// Convenience methods
|
|
Container* GetRootContainer() { return m_RootContainer; }
|
|
Container* FindContainerForNode(NodeId nodeId);
|
|
|
|
// Backward compatibility (optional - can maintain flattened view)
|
|
std::vector<Node*> GetAllNodes(); // Recursive flattening
|
|
std::vector<Link*> GetAllLinks(); // Recursive flattening
|
|
};
|
|
```
|
|
|
|
## Migration Path
|
|
|
|
|
|
### Phase 2: Make BehaviorGraph a Container
|
|
1. BehaviorGraph inherits from Container
|
|
2. BehaviorGraph also inherits from ParameterizedBlock (block interface)
|
|
3. Group creation moves nodes from root → BehaviorGraph container
|
|
|
|
### Phase 3: Update All Systems
|
|
|
|
1. **Rendering**: Container-based (root renders self + children)
|
|
2. **Execution**: Container-based (root runs, nested containers run recursively)
|
|
3. **Serialization**: Container tree structure
|
|
4. **Queries**: Container-aware lookup methods
|
|
|
|
## Benefits Comparison
|
|
|
|
### Container-Based (New):
|
|
- ✅ Single ownership (node owned by exactly one container)
|
|
- ✅ No `m_ParentGroup` needed (container owns it)
|
|
- ✅ Unified patterns (all containers same interface)
|
|
- ✅ Natural serialization (save container tree)
|
|
- ✅ Clear ownership (container owns contents)
|
|
|
|
## Decision: Container-Based Architecture
|
|
|
|
|
|
**Alternative:** Can implement groups first with node-based approach, then refactor later (but creates technical debt).
|
|
|
|
## Next Steps
|
|
|
|
1. **Update Implementation Plan** - Reflect container architecture
|
|
2. **Design Container API** - Define exact interface
|
|
3. **Implement Root Container** - Move existing code
|
|
4. **Implement BehaviorGraph Container** - Group functionality
|
|
5. **Update All Systems** - Rendering, execution, serialization
|
|
|
|
See `docs/groups-container-architecture.md` for detailed container design.
|
|
|