From 95d24ae76728e51b71f74b8def51868fcc072933 Mon Sep 17 00:00:00 2001 From: Arnaud Jamin Date: Mon, 16 Oct 2023 17:04:32 -0400 Subject: [PATCH] Add behavior tree window --- .../Characters/Creature1/BT_Creature1.uasset | Bin 10556 -> 19036 bytes .../Private/CogEngineWindow_Skeleton.cpp | 10 +- .../Public/CogEngineWindow_Skeleton.h | 2 +- .../Private/CogAIWindow_BehaviorTree.cpp | 227 ++++++++++++++++++ .../CogAI/Private/CogAIWindow_Blackboard.cpp | 16 +- .../CogAI/Public/CogAIWindow_BehaviorTree.h | 30 +++ .../CogAI/Public/CogAIWindow_Blackboard.h | 4 - Source/CogSample/CogSampleGameState.cpp | 7 +- 8 files changed, 275 insertions(+), 21 deletions(-) create mode 100644 Plugins/CogAI/Source/CogAI/Private/CogAIWindow_BehaviorTree.cpp create mode 100644 Plugins/CogAI/Source/CogAI/Public/CogAIWindow_BehaviorTree.h diff --git a/Content/Characters/Creature1/BT_Creature1.uasset b/Content/Characters/Creature1/BT_Creature1.uasset index bf2a7d4faa6353bf57b0709460b82854844f6295..1809239354c3ac8bde54a4b96e58ec98946b8f74 100644 GIT binary patch literal 19036 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 delta 2265 zcmZ`)ZA@Eb6uvLElv~O4BCNm){Zu>!EjGHkU6EP!5FEIAadL4zS6guF zbqYcTM-GQ%`}FW_;n}`Z&rEb@5fp^7$h}Gp9exf1BEWi)e{wAB?ck`gbs* zq8U|#te`BQeJk2*&9fKSmnJw>K03=RyUUmlRIv_@i;vDK))aI0^0*(zDzT#f*t$&Pgowo$ zn5YbvFkDB5%$f{@46a$rb+~9Nt%dxvYcee&vga-&$Ina4)^(BYb&(!IiYLp#&-S1} zD|Z;R#9i9BBM3Jf5xSV+kQd@rA;@|p`9WS#1+G8x{RUZc`G8!iY~C_7XK>I(Be(2* zIH8!`+)b4SQPtrLZBRzM8l06>c_*qS929++!^eHaB=eF4=c;Vt?;LW#TMyL1(W-hN z#4p*bFH;RDe+P^~au!Wg4DtTKgAar?mwBfu??N+K3BJl1h8qeDE>#{jz$sA3rpjubumn4~I9 zW>|?U&>d`MDJ^O`_&qa0E_6ktwvm)WvZa=YgbH{p;)bb+Ns`4w+s@4Wv*Y8b%X{BG zlWfy2#CMTKPEyktaZ!OO%jP5VyFS_e(XUTUzVh39ohBG;oD=o)UIBG;2)d&cHSNTX z5-u!);0M1o=o5Tg*YPeLZ--#-4w%0 zb4hB)(PWz0sR>Mgo}gl%!pCRy-pRBEX!9IKEw@lqBHoJgo#W7s##jIniw=}iZFT*wS^g;-;{@i4k>z& zt}Tk*UG3WIS4uawfxUAaj~njl!IYPJojBjzqJEgJgKxV0n0Xzb@*ZH!Oik_7?!MG- za_7Nqk&}EA{Yk8EvVVA$ ap_<+~W40|I`ju52qrM&p;tjq!@Y??mca}N; diff --git a/Plugins/Cog/Source/CogEngine/Private/CogEngineWindow_Skeleton.cpp b/Plugins/Cog/Source/CogEngine/Private/CogEngineWindow_Skeleton.cpp index a956dd7..780e4a8 100644 --- a/Plugins/Cog/Source/CogEngine/Private/CogEngineWindow_Skeleton.cpp +++ b/Plugins/Cog/Source/CogEngine/Private/CogEngineWindow_Skeleton.cpp @@ -114,13 +114,13 @@ void UCogEngineWindow_Skeleton::RenderContent() ImGui::PushStyleVar(ImGuiStyleVar_IndentSpacing, FCogWindowWidgets::GetFontWidth()); HoveredBoneIndex = INDEX_NONE; - DrawBoneEntry(0, false); + RenderBoneEntry(0, false); ImGui::PopStyleVar(); } //-------------------------------------------------------------------------------------------------------------------------- -void UCogEngineWindow_Skeleton::DrawBoneEntry(int32 BoneIndex, bool OpenAllChildren) +void UCogEngineWindow_Skeleton::RenderBoneEntry(int32 BoneIndex, bool OpenAllChildren) { if (BonesInfos.IsValidIndex(BoneIndex) == false) { @@ -202,6 +202,7 @@ void UCogEngineWindow_Skeleton::DrawBoneEntry(int32 BoneIndex, bool OpenAllChild // Checkbox //------------------------ ImGui::SameLine(); + FCogWindowWidgets::PushStyleCompact(); if (ImGui::Checkbox("##Visible", &BoneInfo.ShowBone)) { if (IsControlDown) @@ -217,6 +218,7 @@ void UCogEngineWindow_Skeleton::DrawBoneEntry(int32 BoneIndex, bool OpenAllChild BoneInfo.ShowTrajectory = false; } } + FCogWindowWidgets::PopStyleCompact(); const bool HasCustomVisiblity = BoneInfo.ShowName || BoneInfo.ShowAxes || BoneInfo.ShowLocalVelocity || BoneInfo.ShowTrajectory; if (HasCustomVisiblity) @@ -239,13 +241,13 @@ void UCogEngineWindow_Skeleton::DrawBoneEntry(int32 BoneIndex, bool OpenAllChild { for (int32 ChildIndex : BoneInfo.Children) { - DrawBoneEntry(ChildIndex, OpenAllChildren); + RenderBoneEntry(ChildIndex, OpenAllChildren); } } if (ShowNode) { - if (OpenChildren && ShowNode) + if (OpenChildren) { ImGui::TreePop(); } diff --git a/Plugins/Cog/Source/CogEngine/Public/CogEngineWindow_Skeleton.h b/Plugins/Cog/Source/CogEngine/Public/CogEngineWindow_Skeleton.h index 6f68065..fc2c214 100644 --- a/Plugins/Cog/Source/CogEngine/Public/CogEngineWindow_Skeleton.h +++ b/Plugins/Cog/Source/CogEngine/Public/CogEngineWindow_Skeleton.h @@ -42,7 +42,7 @@ protected: virtual void OnSelectionChanged(AActor* OldSelection, AActor* NewSelection) override; private: - void DrawBoneEntry(int32 BoneIndex, bool OpenAllChildren); + void RenderBoneEntry(int32 BoneIndex, bool OpenAllChildren); void SetChildrenVisibility(int32 BoneIndex, bool IsVisible); void DrawSkeleton(); void RefreshSkeleton(); diff --git a/Plugins/CogAI/Source/CogAI/Private/CogAIWindow_BehaviorTree.cpp b/Plugins/CogAI/Source/CogAI/Private/CogAIWindow_BehaviorTree.cpp new file mode 100644 index 0000000..899692a --- /dev/null +++ b/Plugins/CogAI/Source/CogAI/Private/CogAIWindow_BehaviorTree.cpp @@ -0,0 +1,227 @@ +#include "CogAIWindow_BehaviorTree.h" + +#include "AIController.h" +#include "BehaviorTree/BehaviorTree.h" +#include "BehaviorTree/BTCompositeNode.h" +#include "BehaviorTree/BTNode.h" +#include "BehaviorTree/Tasks/BTTask_Wait.h" +#include "BrainComponent.h" +#include "CogWindowWidgets.h" +#include "GameFramework/Pawn.h" +#include "imgui_internal.h" + +//-------------------------------------------------------------------------------------------------------------------------- +void UCogAIWindow_BehaviorTree::RenderHelp() +{ + ImGui::Text( + "This window displays the behavior tree of the selected actor. " + ); +} + +//-------------------------------------------------------------------------------------------------------------------------- +UCogAIWindow_BehaviorTree::UCogAIWindow_BehaviorTree() +{ + bHasMenu = true; +} + +//-------------------------------------------------------------------------------------------------------------------------- +void UCogAIWindow_BehaviorTree::RenderContent() +{ + Super::RenderContent(); + + + if (ImGui::BeginMenuBar()) + { + if (ImGui::BeginMenu("Options")) + { + ImGui::EndMenu(); + } + + FCogWindowWidgets::MenuSearchBar(Filter); + + ImGui::EndMenuBar(); + } + + AActor* Selection = GetSelection(); + if (Selection == nullptr) + { + ImGui::TextDisabled("No Selection"); + return; + } + + APawn* Pawn = Cast(Selection); + if (Pawn == nullptr) + { + ImGui::TextDisabled("Not a pawn"); + return; + } + + AAIController* AIController = Cast(Pawn->Controller); + if (AIController == nullptr) + { + ImGui::TextDisabled("No AIController"); + return; + } + + UBehaviorTreeComponent* BehaviorTreeComponent = Cast(AIController->GetBrainComponent()); + if (BehaviorTreeComponent == nullptr) + { + ImGui::TextDisabled("No BrainComponent"); + return; + } + + UBehaviorTree* CurrentTree = BehaviorTreeComponent->GetCurrentTree(); + if (CurrentTree == nullptr) + { + ImGui::TextDisabled("No Current Tree"); + return; + } + + //---------------------------------------------------------------------------------------- + // If we use the current tree root node it doesn't seem to be the one instanced. + // Not sure if there is a better way to access it, but we find the root node from + // the current active node. Then we will be able to check if the drawn nodes is + // parent of the active node to display it active. + //---------------------------------------------------------------------------------------- + const UBTNode* RootNodeInstanced = nullptr; + for (const UBTNode* ParentNode = BehaviorTreeComponent->GetActiveNode(); ParentNode != nullptr; ParentNode = ParentNode->GetParentNode()) + { + RootNodeInstanced = ParentNode; + } + + if (RootNodeInstanced != nullptr) + { + RenderNode(BehaviorTreeComponent, RootNodeInstanced, false); + } +} + +//-------------------------------------------------------------------------------------------------------------------------- +void UCogAIWindow_BehaviorTree::RenderNode(UBehaviorTreeComponent* BehaviorTreeComponent, const UBTNode* Node, bool OpenAllChildren) +{ + const char* NodeName = TCHAR_TO_ANSI(*Node->GetNodeName()); + const bool ShowNode = Filter.PassFilter(NodeName); + + const UBTCompositeNode* CompositeNode = Cast(Node); + + bool IsActive = false; + for (const UBTNode* ActiveParentNode = BehaviorTreeComponent->GetActiveNode(); ActiveParentNode != nullptr; ActiveParentNode = ActiveParentNode->GetParentNode()) + { + if (Node == ActiveParentNode) + { + IsActive = true; + break; + } + } + + bool OpenChildren = false; + + if (ShowNode) + { + ImGui::PushID(Node); + + if (OpenAllChildren) + { + ImGui::SetNextItemOpen(true, ImGuiCond_Always); + } + else + { + ImGui::SetNextItemOpen(true, ImGuiCond_Once); + } + + //------------------------ + // TreeNode + //------------------------ + const bool HasChildren = CompositeNode != nullptr && CompositeNode->GetChildrenNum() > 0; + if (HasChildren && Filter.IsActive() == false) + { + OpenChildren = ImGui::TreeNodeEx("##Node", ImGuiTreeNodeFlags_AllowItemOverlap | ImGuiTreeNodeFlags_SpanFullWidth); + } + else + { + ImGui::TreeNodeEx("##Node", ImGuiTreeNodeFlags_Leaf | ImGuiTreeNodeFlags_NoTreePushOnOpen | ImGuiTreeNodeFlags_AllowItemOverlap | ImGuiTreeNodeFlags_SpanFullWidth); + } + + const bool IsControlDown = ImGui::GetCurrentContext()->IO.KeyCtrl; + if (ImGui::IsItemClicked(ImGuiMouseButton_Left) && IsControlDown) + { + OpenAllChildren = true; + } + + //------------------------ + // ContextMenu + //------------------------ + if (ImGui::BeginPopupContextItem()) + { + ImGui::EndPopup(); + } + + //------------------------ + // Tooltip + //------------------------ + if (ImGui::IsItemHovered()) + { + ImGui::BeginTooltip(); + ImGui::BeginDisabled(); + ImGui::Text(TCHAR_TO_ANSI(*Node->GetStaticDescription())); + + if (const UBTTask_Wait* Wait = Cast(Node)) + { + ImGui::Text("Wait: %0.2fs", Wait->WaitTime); + } + + ImGui::EndDisabled(); + ImGui::EndTooltip(); + } + + //------------------------ + // Checkbox + //------------------------ + ImGui::SameLine(); + FCogWindowWidgets::PushStyleCompact(); + if (IsActive == false) + { + ImGui::BeginDisabled(); + } + bool DrawActive = IsActive; + ImGui::Checkbox("##Active", &DrawActive); + + if (IsActive == false) + { + ImGui::EndDisabled(); + } + FCogWindowWidgets::PopStyleCompact(); + + //------------------------ + // Name + //------------------------ + ImGui::SameLine(); + ImVec4 NameColor = IsActive ? ImVec4(0.0f, 1.0f, 0.0f, 1.0f) : ImVec4(1.0f, 1.0f, 1.0f, 0.6f); + ImGui::TextColored(NameColor, "%s", NodeName); + } + + //------------------------ + // Children + //------------------------ + if (OpenChildren || Filter.IsActive()) + { + if (CompositeNode != nullptr) + { + for (int32 i = 0; i < CompositeNode->GetChildrenNum(); ++i) + { + const UBTNode* ChildNode = CompositeNode->GetChildNode(i); + RenderNode(BehaviorTreeComponent, ChildNode, OpenAllChildren); + } + } + } + + if (ShowNode) + { + if (OpenChildren) + { + ImGui::TreePop(); + } + + ImGui::PopID(); + } +} + diff --git a/Plugins/CogAI/Source/CogAI/Private/CogAIWindow_Blackboard.cpp b/Plugins/CogAI/Source/CogAI/Private/CogAIWindow_Blackboard.cpp index 40301a8..4d960fe 100644 --- a/Plugins/CogAI/Source/CogAI/Private/CogAIWindow_Blackboard.cpp +++ b/Plugins/CogAI/Source/CogAI/Private/CogAIWindow_Blackboard.cpp @@ -50,35 +50,35 @@ void UCogAIWindow_Blackboard::RenderContent() APawn* Pawn = Cast(Selection); if (Pawn == nullptr) { - ImGui::TextDisabled("Selection is not a pawn"); + ImGui::TextDisabled("Not a pawn"); return; } AAIController* AIController = Cast(Pawn->Controller); if (AIController == nullptr) { - ImGui::TextDisabled("Selection has no AIController"); + ImGui::TextDisabled("No AIController"); return; } - UBrainComponent* Brain = AIController->GetBrainComponent(); - if (Brain == nullptr) + UBrainComponent* BehaviorTree = AIController->GetBrainComponent(); + if (BehaviorTree == nullptr) { - ImGui::TextDisabled("Selection controller has no BrainComponent"); + ImGui::TextDisabled("No BrainComponent"); return; } - UBlackboardComponent* Blackboard = Brain->GetBlackboardComponent(); + UBlackboardComponent* Blackboard = BehaviorTree->GetBlackboardComponent(); if (Blackboard == nullptr) { - ImGui::TextDisabled("Selection controller has no BlackboardComponent"); + ImGui::TextDisabled("No BlackboardComponent"); return; } UBlackboardData* BlackboardAsset = Blackboard->GetBlackboardAsset(); if (BlackboardAsset == nullptr) { - ImGui::TextDisabled("BlackboardComponent has no BlackboardAsset"); + ImGui::TextDisabled("No BlackboardAsset"); return; } diff --git a/Plugins/CogAI/Source/CogAI/Public/CogAIWindow_BehaviorTree.h b/Plugins/CogAI/Source/CogAI/Public/CogAIWindow_BehaviorTree.h new file mode 100644 index 0000000..a340255 --- /dev/null +++ b/Plugins/CogAI/Source/CogAI/Public/CogAIWindow_BehaviorTree.h @@ -0,0 +1,30 @@ +#pragma once + +#include "CoreMinimal.h" +#include "CogWindow.h" +#include "CogAIWindow_BehaviorTree.generated.h" + +class UBehaviorTreeComponent; +class UBTNode; + +UCLASS(Config = Cog) +class COGAI_API UCogAIWindow_BehaviorTree : public UCogWindow +{ + GENERATED_BODY() + +public: + + UCogAIWindow_BehaviorTree(); + +protected: + + void RenderHelp(); + + virtual void RenderContent() override; + + virtual void RenderNode(UBehaviorTreeComponent* BehaviorTreeComponent, const UBTNode* Node, bool OpenAllChildren); + +private: + + ImGuiTextFilter Filter; +}; diff --git a/Plugins/CogAI/Source/CogAI/Public/CogAIWindow_Blackboard.h b/Plugins/CogAI/Source/CogAI/Public/CogAIWindow_Blackboard.h index 2888046..a1e108b 100644 --- a/Plugins/CogAI/Source/CogAI/Public/CogAIWindow_Blackboard.h +++ b/Plugins/CogAI/Source/CogAI/Public/CogAIWindow_Blackboard.h @@ -4,9 +4,6 @@ #include "CogWindow.h" #include "CogAIWindow_Blackboard.generated.h" -namespace FBlackboard { typedef uint8 FKey; } -class UBlackboardData; - UCLASS(Config = Cog) class COGAI_API UCogAIWindow_Blackboard : public UCogWindow { @@ -28,5 +25,4 @@ private: bool bSortByName = true; ImGuiTextFilter Filter; - }; diff --git a/Source/CogSample/CogSampleGameState.cpp b/Source/CogSample/CogSampleGameState.cpp index 6cc6ff9..994c2db 100644 --- a/Source/CogSample/CogSampleGameState.cpp +++ b/Source/CogSample/CogSampleGameState.cpp @@ -18,6 +18,7 @@ #include "CogAbilityWindow_Pools.h" #include "CogAbilityWindow_Tags.h" #include "CogAbilityWindow_Tweaks.h" +#include "CogAIWindow_BehaviorTree.h" #include "CogAIWindow_Blackboard.h" #include "CogDebugDrawImGui.h" #include "CogDebugPlot.h" @@ -206,10 +207,8 @@ void ACogSampleGameState::InitializeCog() //--------------------------------------- // AI //--------------------------------------- - //const UCogAIDataAsset* InputAsset = GetFirstAssetByClass(); - - UCogAIWindow_Blackboard* BlackboardWindow = CogWindowManager->CreateWindow("AI.Blackboard"); - //BlackboardWindow->SetAsset(InputAsset); + CogWindowManager->CreateWindow("AI.Behavior Tree"); + CogWindowManager->CreateWindow("AI.Blackboard"); //--------------------------------------- // Input