Olympe Engine 2.0
2D Game Engine with ECS Architecture
Loading...
Searching...
No Matches
BTGraphLayoutEngine.h
Go to the documentation of this file.
1/**
2 * @file BTGraphLayoutEngine.h
3 * @brief Graph layout engine for behavior tree visualization
4 * @author Olympe Engine - Behavior Tree Debugger
5 * @date 2025
6 *
7 * @details
8 * Implements a 5-phase hierarchical graph layout algorithm:
9 * 1. Layering: Assign nodes to layers via BFS
10 * 2. Initial Ordering: Order nodes within layers
11 * 3. Crossing Reduction: Minimize edge crossings using barycenter heuristic
12 * 4. Buchheim-Walker Layout: Optimal parent centering in abstract unit space
13 * 5. Force-Directed Collision Resolution: Iterative overlap elimination
14 *
15 * The algorithm works in abstract unit space (each node = 1.0 unit) and converts
16 * to world coordinates at the end with adaptive spacing based on tree complexity.
17 */
18
19#pragma once
20
21#include "../vector.h"
22#include "../AI/BehaviorTree.h"
23#include <vector>
24#include <map>
25
26namespace Olympe
27{
28 /**
29 * @enum BTLayoutDirection
30 * @brief Layout direction for behavior tree visualization
31 */
33 {
34 TopToBottom, ///< Traditional top-down layout (vertical)
35 LeftToRight ///< Horizontal left-to-right layout
36 };
37
38 /**
39 * @struct BTNodeLayout
40 * @brief Layout information for a single behavior tree node
41 */
43 {
44 uint32_t nodeId = 0; ///< BT node ID
45 Vector position; ///< Final position (x, y)
46 int layer = 0; ///< Hierarchical layer (0 = root)
47 int orderInLayer = 0; ///< Order within the layer
48 float width = 200.0f; ///< Node visual width (increased for readability)
49 float height = 100.0f; ///< Node visual height (increased for readability)
50 };
51
52 /**
53 * @class BTGraphLayoutEngine
54 * @brief Computes clean hierarchical layouts for behavior trees
55 *
56 * Uses the Sugiyama algorithm to create readable, professional-looking
57 * node graphs without overlaps.
58 */
60 {
61 public:
64
65 /**
66 * @brief Set layout direction
67 * @param direction Layout direction (TopToBottom or LeftToRight)
68 */
70
71 /**
72 * @brief Get current layout direction
73 * @return Current layout direction
74 */
76
77 /**
78 * @brief Compute layout for a behavior tree
79 * @param tree The behavior tree asset to layout
80 * @param nodeSpacingX Horizontal spacing between nodes (default: 180px, reduced from 250px)
81 * @param nodeSpacingY Vertical spacing between layers (default: 120px, reduced from 180px)
82 * @param zoomFactor Zoom multiplier applied to final positions (default: 1.0)
83 * @return Vector of node layouts with computed positions
84 */
85 std::vector<BTNodeLayout> ComputeLayout(
87 float nodeSpacingX = 180.0f,
88 float nodeSpacingY = 120.0f,
89 float zoomFactor = 1.0f
90 );
91
92 /**
93 * @brief Get computed layout for a specific node
94 * @param nodeId The BT node ID
95 * @return Pointer to layout, or nullptr if not found
96 */
97 const BTNodeLayout* GetNodeLayout(uint32_t nodeId) const;
98
99 private:
100 // Phase 1: Assign nodes to layers via BFS from root
102
103 // Phase 2: Initial ordering of nodes within each layer
104 void InitialOrdering();
105
106 // Phase 3: Reduce edge crossings (barycenter heuristic)
108
109 // Phase 4: Buchheim-Walker optimal layout (in abstract unit space)
111
112 // Phase 5: Force-directed collision resolution (in abstract unit space)
114
115 // DEPRECATED: Old phases replaced by Buchheim-Walker
118
119 // Helper: Get children of a node
120 std::vector<uint32_t> GetChildren(const BTNode* node) const;
121
122 // Helper: Get parent nodes (reverse lookup)
124
125 // Helper: Calculate barycenter for a node
126 float CalculateBarycenter(uint32_t nodeId, const std::vector<BTNodeLayout*>& neighbors) const;
127
128 // NEW: Helper methods for Buchheim-Walker
129 void PlaceSubtree(uint32_t nodeId, const BehaviorTreeAsset* tree, int depth, float& nextAvailableX);
130 void ShiftSubtree(uint32_t nodeId, const BehaviorTreeAsset* tree, float offset);
131
132 // NEW: Helper methods for collision detection
133 bool DoNodesOverlap(const BTNodeLayout& a, const BTNodeLayout& b, float padding) const;
135
136 // NEW: Helper function to count edge crossings (for debugging)
137 int CountEdgeCrossings(const BehaviorTreeAsset* tree) const;
138
139 // Layout configuration
141
142 // Computed layouts
143 std::vector<BTNodeLayout> m_layouts;
144 std::map<uint32_t, size_t> m_nodeIdToIndex; // nodeId -> index in m_layouts
145
146 // Temporary data structures for algorithm
147 std::vector<std::vector<uint32_t>> m_layers; // layer -> [nodeIds]
148 std::map<uint32_t, std::vector<uint32_t>> m_parentMap; // nodeId -> [parentIds]
149 };
150}
ComponentTypeID GetComponentTypeID_Static()
Definition ECS_Entity.h:56
Computes clean hierarchical layouts for behavior trees.
bool DoNodesOverlap(const BTNodeLayout &a, const BTNodeLayout &b, float padding) const
void ShiftSubtree(uint32_t nodeId, const BehaviorTreeAsset *tree, float offset)
const BTNodeLayout * GetNodeLayout(uint32_t nodeId) const
Get computed layout for a specific node.
void PlaceSubtree(uint32_t nodeId, const BehaviorTreeAsset *tree, int depth, float &nextAvailableX)
void ResolveCollisions(float nodeSpacingX)
std::map< uint32_t, size_t > m_nodeIdToIndex
void ApplyBuchheimWalkerLayout(const BehaviorTreeAsset *tree)
std::vector< uint32_t > GetChildren(const BTNode *node) const
void BuildParentMap(const BehaviorTreeAsset *tree)
void SetLayoutDirection(BTLayoutDirection direction)
Set layout direction.
BTLayoutDirection GetLayoutDirection() const
Get current layout direction.
void AssignXCoordinates(float nodeSpacingX)
BTLayoutDirection m_layoutDirection
Default vertical.
std::map< uint32_t, std::vector< uint32_t > > m_parentMap
std::vector< BTNodeLayout > ComputeLayout(const BehaviorTreeAsset *tree, float nodeSpacingX=180.0f, float nodeSpacingY=120.0f, float zoomFactor=1.0f)
Compute layout for a behavior tree.
void ReduceCrossings(const BehaviorTreeAsset *tree)
void ResolveNodeCollisionsForceDirected(float nodePadding, int maxIterations)
void PushNodeApart(uint32_t nodeA, uint32_t nodeB, float minDistance)
int CountEdgeCrossings(const BehaviorTreeAsset *tree) const
float CalculateBarycenter(uint32_t nodeId, const std::vector< BTNodeLayout * > &neighbors) const
std::vector< BTNodeLayout > m_layouts
void AssignLayers(const BehaviorTreeAsset *tree)
std::vector< std::vector< uint32_t > > m_layers
BTLayoutDirection
Layout direction for behavior tree visualization.
@ LeftToRight
Horizontal left-to-right layout.
@ TopToBottom
Traditional top-down layout (vertical)
Represents a single node in a behavior tree.
Layout information for a single behavior tree node.
int orderInLayer
Order within the layer.
Vector position
Final position (x, y)
float height
Node visual height (increased for readability)
uint32_t nodeId
BT node ID.
int layer
Hierarchical layer (0 = root)
float width
Node visual width (increased for readability)