mirror of
https://github.com/Ed94/Cog.git
synced 2026-06-13 00:01:37 -07:00
Add behavior tree window
This commit is contained in:
Binary file not shown.
@@ -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();
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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<APawn>(Selection);
|
||||
if (Pawn == nullptr)
|
||||
{
|
||||
ImGui::TextDisabled("Not a pawn");
|
||||
return;
|
||||
}
|
||||
|
||||
AAIController* AIController = Cast<AAIController>(Pawn->Controller);
|
||||
if (AIController == nullptr)
|
||||
{
|
||||
ImGui::TextDisabled("No AIController");
|
||||
return;
|
||||
}
|
||||
|
||||
UBehaviorTreeComponent* BehaviorTreeComponent = Cast<UBehaviorTreeComponent>(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<UBTCompositeNode>(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<UBTTask_Wait>(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();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -50,35 +50,35 @@ void UCogAIWindow_Blackboard::RenderContent()
|
||||
APawn* Pawn = Cast<APawn>(Selection);
|
||||
if (Pawn == nullptr)
|
||||
{
|
||||
ImGui::TextDisabled("Selection is not a pawn");
|
||||
ImGui::TextDisabled("Not a pawn");
|
||||
return;
|
||||
}
|
||||
|
||||
AAIController* AIController = Cast<AAIController>(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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
@@ -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;
|
||||
|
||||
};
|
||||
|
||||
@@ -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<UCogAIDataAsset>();
|
||||
|
||||
UCogAIWindow_Blackboard* BlackboardWindow = CogWindowManager->CreateWindow<UCogAIWindow_Blackboard>("AI.Blackboard");
|
||||
//BlackboardWindow->SetAsset(InputAsset);
|
||||
CogWindowManager->CreateWindow<UCogAIWindow_BehaviorTree>("AI.Behavior Tree");
|
||||
CogWindowManager->CreateWindow<UCogAIWindow_Blackboard>("AI.Blackboard");
|
||||
|
||||
//---------------------------------------
|
||||
// Input
|
||||
|
||||
Reference in New Issue
Block a user