From 208eebdf89fe6eb7747bea4d1ffa86e3fc77f757 Mon Sep 17 00:00:00 2001 From: Wojtek Figat Date: Fri, 25 Sep 2026 00:30:24 +0200 Subject: [PATCH] Various fixes and improvements to BT --- Flax.sln.DotSettings | 1 + .../Editor/Surface/Archetypes/BehaviorTree.cs | 32 ++++++++++++------- Source/Engine/AI/BehaviorTreeNode.h | 2 +- Source/Engine/AI/BehaviorTreeNodes.cpp | 19 +++++++++-- Source/Engine/AI/BehaviorTreeNodes.h | 3 ++ 5 files changed, 42 insertions(+), 15 deletions(-) diff --git a/Flax.sln.DotSettings b/Flax.sln.DotSettings index 5a027a4d2..b5594c3f2 100644 --- a/Flax.sln.DotSettings +++ b/Flax.sln.DotSettings @@ -256,6 +256,7 @@ True True True + True True DisabledByUser True diff --git a/Source/Editor/Surface/Archetypes/BehaviorTree.cs b/Source/Editor/Surface/Archetypes/BehaviorTree.cs index 2ecb0f20c..dfd9f3d46 100644 --- a/Source/Editor/Surface/Archetypes/BehaviorTree.cs +++ b/Source/Editor/Surface/Archetypes/BehaviorTree.cs @@ -219,7 +219,7 @@ namespace FlaxEditor.Surface.Archetypes var headerColor = style.BackgroundHighlighted; if (_headerRect.Contains(ref _mousePosition) && !Surface.IsConnecting && !Surface.IsSelecting) headerColor *= 1.07f; - Render2D.FillRectangle(_headerRect, style.BackgroundHighlighted); + Render2D.FillRectangle(_headerRect, headerColor); Render2D.DrawText(style.FontLarge, Title, _headerTextRect, style.Foreground, TextAlignment.Near, TextAlignment.Center, TextWrapping.NoWrap, 1f, FlaxEditor.Surface.Constants.NodeHeaderTextScale); // Close button @@ -231,14 +231,6 @@ namespace FlaxEditor.Surface.Archetypes DrawChildren(); - // Selection outline - if (_isSelected) - { - var colorTop = Color.Orange; - var colorBottom = Color.OrangeRed; - Render2D.DrawRectangle(backgroundRect, colorTop, colorTop, colorBottom, colorBottom, 2.5f); - } - // Breakpoint dot if (Breakpoint.Set) { @@ -246,17 +238,31 @@ namespace FlaxEditor.Surface.Archetypes Render2D.DrawSprite(icon, new Rectangle(-7, -7, 16, 16), new Color(0.9f, 0.9f, 0.9f)); Render2D.DrawSprite(icon, new Rectangle(-6, -6, 14, 14), new Color(0.894117647f, 0.0784313725f, 0.0f)); } + } + protected virtual void DrawOverlays() + { + var style = Style.Current; if (highlightBox != null) Render2D.DrawRectangle(highlightBox.Bounds, style.BorderHighlighted, 2f); + // Selection outline + if (_isSelected) + { + var colorTop = Color.Orange; + var colorBottom = Color.OrangeRed; + var rect = new Rectangle(Float2.Zero, Size); + Render2D.DrawRectangle(rect, colorTop, colorTop, colorBottom, colorBottom, 2.5f); + } + // Debug relevancy outline if (_debugRelevant) { var colorTop = Color.LightYellow; var colorBottom = Color.Yellow; - backgroundRect = new Rectangle(Float2.One, Size - new Float2(2.0f)); - Render2D.DrawRectangle(backgroundRect, colorTop, colorTop, colorBottom, colorBottom); + var rect = new Rectangle(Float2.One, Size - new Float2(2.0f)); + //Render2D.DrawRectangle(backgroundRect, colorTop, colorTop, colorBottom, colorBottom); + Render2D.DrawRectangle(rect, style.ProgressNormal); } } @@ -555,6 +561,8 @@ namespace FlaxEditor.Surface.Archetypes Render2D.FillRectangle(new Rectangle(0, _headerRect.Bottom + 4, Width, Height - _headerRect.Bottom - 4), style.BackgroundHighlighted); Render2D.DrawText(style.FontSmall, _debugInfo, new Rectangle(4, _headerRect.Bottom + 7, _debugInfoSize), style.Foreground, scale: 0.8f); } + + DrawOverlays(); } public override void ResizeAuto() @@ -820,6 +828,8 @@ namespace FlaxEditor.Surface.Archetypes Render2D.DrawText(style.FontSmall, _debugInfo, new Rectangle(4, _headerRect.Bottom, _debugInfoSize), color, TextAlignment.Near, TextAlignment.Center, TextWrapping.NoWrap, 1, 0.8f); } + DrawOverlays(); + // Outline if (!_isSelected) { diff --git a/Source/Engine/AI/BehaviorTreeNode.h b/Source/Engine/AI/BehaviorTreeNode.h index 857b134f9..e1d2b40e7 100644 --- a/Source/Engine/AI/BehaviorTreeNode.h +++ b/Source/Engine/AI/BehaviorTreeNode.h @@ -31,7 +31,7 @@ private: public: /// - /// Node user name (eg. Follow Enemy, or Pick up Weapon). + /// Custom node name (eg. Follow Enemy, or Pick up Weapon). /// API_FIELD() String Name; diff --git a/Source/Engine/AI/BehaviorTreeNodes.cpp b/Source/Engine/AI/BehaviorTreeNodes.cpp index 710f99159..f69b10d19 100644 --- a/Source/Engine/AI/BehaviorTreeNodes.cpp +++ b/Source/Engine/AI/BehaviorTreeNodes.cpp @@ -380,6 +380,19 @@ BehaviorUpdateResult BehaviorTreeSubTreeNode::Update(const BehaviorUpdateContext return tree->Graph.Root->InvokeUpdate(subContext); } +#if USE_EDITOR + +String BehaviorTreeSubTreeNode::GetDebugInfo(const BehaviorUpdateContext& context) const +{ + if (Tree) + { + return StringUtils::GetFileNameWithoutExtension(Tree->GetPath()); + } + return String::Empty; +} + +#endif + BehaviorUpdateResult BehaviorTreeForceFinishNode::Update(const BehaviorUpdateContext& context) { context.Behavior->StopLogic(Result); @@ -401,7 +414,7 @@ void BehaviorTreeMoveToNode::GetAgentSize(Actor* agent, float& outRadius, float& { if (const auto* characterController = Cast(agent)) { - // Character Controller is an capsule + // Character Controller is a capsule outRadius = characterController->GetRadius(); outHeight = characterController->GetHeight() + 2 * outRadius; return; @@ -552,7 +565,7 @@ String BehaviorTreeMoveToNode::GetDebugInfo(const BehaviorUpdateContext& context Real distanceLeft = state->Path.Count() > state->TargetPathIndex ? Vector3::Distance(state->Path[state->TargetPathIndex], agentLocationOnPath) : 0; for (int32 i = state->TargetPathIndex; i < state->Path.Count(); i++) distanceLeft += Vector3::Distance(state->Path[i - 1], state->Path[i]); - return String::Format(TEXT("Agent: '{}'\nGoal: '{}'\nDistance: {}"), agent, goal, (int32)distanceLeft); + return String::Format(TEXT("Agent: '{}'\nGoal: '{}'\nDistance: {}"), agent, goal, distanceLeft); } } return String::Empty; @@ -770,7 +783,7 @@ String BehaviorTreeKnowledgeBooleanDecorator::GetDebugInfo(const BehaviorUpdateC { result = Value.ToString(); if (Invert) - result = TEXT("!") + result; + result = TEXT("Not ") + result; } return result; } diff --git a/Source/Engine/AI/BehaviorTreeNodes.h b/Source/Engine/AI/BehaviorTreeNodes.h index 154363dea..bcc2bce91 100644 --- a/Source/Engine/AI/BehaviorTreeNodes.h +++ b/Source/Engine/AI/BehaviorTreeNodes.h @@ -156,6 +156,9 @@ public: void InitState(const BehaviorUpdateContext& context) override; void ReleaseState(const BehaviorUpdateContext& context) override; BehaviorUpdateResult Update(const BehaviorUpdateContext& context) override; +#if USE_EDITOR + String GetDebugInfo(const BehaviorUpdateContext& context) const override; +#endif private: struct State