diff --git a/Content/Characters/Creature1/BT_Creature1.uasset b/Content/Characters/Creature1/BT_Creature1.uasset index b409787..9a9370b 100644 Binary files a/Content/Characters/Creature1/BT_Creature1.uasset and b/Content/Characters/Creature1/BT_Creature1.uasset differ diff --git a/Plugins/CogAI/Source/CogAI/Private/CogAIWindow_BehaviorTree.cpp b/Plugins/CogAI/Source/CogAI/Private/CogAIWindow_BehaviorTree.cpp index fe1bb31..c1a7895 100644 --- a/Plugins/CogAI/Source/CogAI/Private/CogAIWindow_BehaviorTree.cpp +++ b/Plugins/CogAI/Source/CogAI/Private/CogAIWindow_BehaviorTree.cpp @@ -92,30 +92,20 @@ void UCogAIWindow_BehaviorTree::RenderContent() if (RootNodeInstanced != nullptr) { - RenderNode(BehaviorTreeComponent, RootNodeInstanced, false); + RenderNode(*BehaviorTreeComponent, const_cast(RootNodeInstanced), false); } } //-------------------------------------------------------------------------------------------------------------------------- -void UCogAIWindow_BehaviorTree::RenderNode(UBehaviorTreeComponent* BehaviorTreeComponent, const UBTNode* Node, bool OpenAllChildren) +void UCogAIWindow_BehaviorTree::RenderNode(UBehaviorTreeComponent& BehaviorTreeComponent, UBTNode* Node, bool OpenAllChildren) { - FString NodeNameStr; - if (const UBTTask_BlueprintBase* Wait = Cast(Node)) - { - NodeNameStr = Node->GetNodeName(); - } - else - { - NodeNameStr = Node->GetStaticDescription(); - } - - const char* NodeName = TCHAR_TO_ANSI(*NodeNameStr); + 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()) + for (const UBTNode* ActiveParentNode = BehaviorTreeComponent.GetActiveNode(); ActiveParentNode != nullptr; ActiveParentNode = ActiveParentNode->GetParentNode()) { if (Node == ActiveParentNode) { @@ -171,11 +161,66 @@ void UCogAIWindow_BehaviorTree::RenderNode(UBehaviorTreeComponent* BehaviorTreeC //------------------------ if (ImGui::IsItemHovered()) { - ImGui::BeginTooltip(); - ImGui::BeginDisabled(); - ImGui::Text(NodeName); - ImGui::EndDisabled(); - ImGui::EndTooltip(); + FCogWindowWidgets::BeginTableTooltip(); + + if (ImGui::BeginTable("Effect", 2, ImGuiTableFlags_Borders)) + { + ImGui::TableSetupColumn("Property"); + ImGui::TableSetupColumn("Value", ImGuiTableColumnFlags_WidthStretch); + + const ImVec4 TextColor(1.0f, 1.0f, 1.0f, 0.5f); + + //------------------------ + // Name + //------------------------ + ImGui::TableNextRow(); + ImGui::TableNextColumn(); + ImGui::TextColored(TextColor, "Name"); + ImGui::TableNextColumn(); + ImGui::Text("%s", NodeName); + + //------------------------ + // Static Description + //------------------------ + ImGui::TableNextRow(); + ImGui::TableNextColumn(); + ImGui::TextColored(TextColor, "Description"); + ImGui::TableNextColumn(); + ImGui::Text("%s", TCHAR_TO_ANSI(*Node->GetStaticDescription())); + + //------------------------ + // Runtime Values + //------------------------ + TArray RunTimeValues; + uint8* NodeMemory = BehaviorTreeComponent.GetNodeMemory(Node, BehaviorTreeComponent.GetActiveInstanceIdx()); + Node->DescribeRuntimeValues(BehaviorTreeComponent, NodeMemory, EBTDescriptionVerbosity::Detailed, RunTimeValues); + + for (const FString& RuntimeValue : RunTimeValues) + { + ImGui::TableNextRow(); + + FString Left, Right; + if (RuntimeValue.Split(TEXT(": "), &Left, &Right)) + { + ImGui::TableNextColumn(); + ImGui::TextColored(TextColor, TCHAR_TO_ANSI(*Left)); + + ImGui::TableNextColumn(); + ImGui::Text("%s", TCHAR_TO_ANSI(*Right)); + } + else + { + ImGui::TableNextColumn(); + ImGui::TextColored(TextColor, "Value"); + ImGui::TableNextColumn(); + ImGui::Text(TCHAR_TO_ANSI(*RuntimeValue)); + } + } + + ImGui::EndTable(); + } + + FCogWindowWidgets::EndTableTooltip(); } //------------------------ @@ -213,7 +258,7 @@ void UCogAIWindow_BehaviorTree::RenderNode(UBehaviorTreeComponent* BehaviorTreeC { for (int32 i = 0; i < CompositeNode->GetChildrenNum(); ++i) { - const UBTNode* ChildNode = CompositeNode->GetChildNode(i); + UBTNode* ChildNode = CompositeNode->GetChildNode(i); RenderNode(BehaviorTreeComponent, ChildNode, OpenAllChildren); } } diff --git a/Plugins/CogAI/Source/CogAI/Private/CogAIWindow_Blackboard.cpp b/Plugins/CogAI/Source/CogAI/Private/CogAIWindow_Blackboard.cpp index 4d960fe..700787a 100644 --- a/Plugins/CogAI/Source/CogAI/Private/CogAIWindow_Blackboard.cpp +++ b/Plugins/CogAI/Source/CogAI/Private/CogAIWindow_Blackboard.cpp @@ -82,6 +82,29 @@ void UCogAIWindow_Blackboard::RenderContent() return; } + TArray Keys; + uint8 Offset = 0; + for (UBlackboardData* It = BlackboardAsset; It; It = It->Parent) + { + for (int32 KeyID = 0; KeyID < It->Keys.Num(); KeyID++) + { + if (const FBlackboardEntry* Key = BlackboardAsset->GetKey(KeyID)) + { + Keys.Add(Key); + } + } + Offset += It->Keys.Num(); + } + + if (bSortByName) + { + Keys.Sort([](const FBlackboardEntry& Key1, const FBlackboardEntry& Key2) + { + return Key1.EntryName.Compare(Key1.EntryName) < 0; + }); + } + + if (ImGui::BeginTable("Blackboard", 3, ImGuiTableFlags_SizingFixedFit | ImGuiTableFlags_Resizable | ImGuiTableFlags_NoBordersInBodyUntilResize @@ -101,39 +124,43 @@ void UCogAIWindow_Blackboard::RenderContent() const FString CommonTypePrefix = UBlackboardKeyType::StaticClass()->GetName().AppendChar(TEXT('_')); - uint8 Offset = 0; - for (UBlackboardData* It = BlackboardAsset; It; It = It->Parent) + for (int32 KeyID = 0; KeyID < Keys.Num(); ++KeyID) { - for (int32 KeyID = 0; KeyID < It->Keys.Num(); KeyID++) + const FBlackboardEntry* Key = Keys[KeyID]; + if (Key == nullptr) { - const FBlackboardEntry* Key = BlackboardAsset->GetKey(KeyID); - if (Key == nullptr) - { - continue; - } - - const char* KeyName = TCHAR_TO_ANSI(*Key->EntryName.ToString()); - if (Filter.PassFilter(KeyName) == false) - { - continue; - } - - ImGui::TableNextRow(); - - ImGui::TableNextColumn(); - const FString FullKeyType = Key->KeyType ? GetNameSafe(Key->KeyType->GetClass()) : FString(); - const FString DescKeyType = FullKeyType.StartsWith(CommonTypePrefix) ? FullKeyType.RightChop(CommonTypePrefix.Len()) : FullKeyType; - ImGui::Text("%s", TCHAR_TO_ANSI(*DescKeyType)); - - ImGui::TableNextColumn(); - ImGui::Text("%s", KeyName); - - ImGui::TableNextColumn(); - const uint8* ValueData = Blackboard->GetKeyRawData(KeyID); - FString ValueDesc = Key->KeyType && ValueData ? *(Key->KeyType->WrappedDescribeValue(*Blackboard, ValueData)) : TEXT("Empty"); - ImGui::Text("%s", TCHAR_TO_ANSI(*ValueDesc)); + continue; } - Offset += It->Keys.Num(); + + const char* KeyName = TCHAR_TO_ANSI(*Key->EntryName.ToString()); + if (Filter.PassFilter(KeyName) == false) + { + continue; + } + + ImGui::TableNextRow(); + + //------------------------ + // Type + //------------------------ + ImGui::TableNextColumn(); + const FString FullKeyType = Key->KeyType ? GetNameSafe(Key->KeyType->GetClass()) : FString(); + const FString DescKeyType = FullKeyType.StartsWith(CommonTypePrefix) ? FullKeyType.RightChop(CommonTypePrefix.Len()) : FullKeyType; + ImGui::Text("%s", TCHAR_TO_ANSI(*DescKeyType)); + + //------------------------ + // Name + //------------------------ + ImGui::TableNextColumn(); + ImGui::Text("%s", KeyName); + + //------------------------ + // Value + //------------------------ + ImGui::TableNextColumn(); + const uint8* ValueData = Blackboard->GetKeyRawData(KeyID); + FString ValueDesc = Key->KeyType && ValueData ? *(Key->KeyType->WrappedDescribeValue(*Blackboard, ValueData)) : TEXT("Empty"); + ImGui::Text("%s", TCHAR_TO_ANSI(*ValueDesc)); } ImGui::EndTable(); diff --git a/Plugins/CogAI/Source/CogAI/Public/CogAIWindow_BehaviorTree.h b/Plugins/CogAI/Source/CogAI/Public/CogAIWindow_BehaviorTree.h index a340255..b541906 100644 --- a/Plugins/CogAI/Source/CogAI/Public/CogAIWindow_BehaviorTree.h +++ b/Plugins/CogAI/Source/CogAI/Public/CogAIWindow_BehaviorTree.h @@ -22,7 +22,7 @@ protected: virtual void RenderContent() override; - virtual void RenderNode(UBehaviorTreeComponent* BehaviorTreeComponent, const UBTNode* Node, bool OpenAllChildren); + virtual void RenderNode(UBehaviorTreeComponent& BehaviorTreeComponent, UBTNode* Node, bool OpenAllChildren); private: diff --git a/TODO.txt b/TODO.txt index 50b7e46..3332382 100644 --- a/TODO.txt +++ b/TODO.txt @@ -1,20 +1,15 @@ - CogImGui: Add a way to create and override CogImguiwidget - CogImGui: Try to find a global solution to prevent crash when breaking in a blueprint from an imgui action (reset the stack) -- CogDebug: Add log category description - - CogWindow: Add reset window position menu item or reset layout (window can get far away) - CogWindow: Try to remove CogWindow dependency to cogimgui. Should only depends on imgui (currently use setdpiscale of cogimgui) - CogWindow: Add reset window position menu item or reset layout (window can get far away) - - CogEngine: Save selection window settings (current actor and category) - CogEngine: More stats in the stats window - CogEngine: Overlay mode of stats. - CogEngine: Stat main menu widget could have a tooltip on each stat with a control to change set the emulation (FPS, Ping, Packetloss) - CogEngine: Skeleton window selectable have wrong height -- CogEngine: Property grid -- CogEngine: user settings - CogInput: Add multiple IMC on the input data asset. Maybe propose a current imc - CogInput: Add mouse over highlight on the buttons of the gamepad window @@ -24,5 +19,3 @@ - CogSample: Add a custom window in sample (changing the character faction) - CogSample: Create more abilities - CogSample: Add area of effects in the level - -- CogAI: Create a CogAI project with windows for BT and other AI tools \ No newline at end of file