void RebuildExecutionOrder(UBehaviorTreeGraphNode* RootEdNode, UBTCompositeNode* RootNode, uint16* ExecutionIndex, uint8 TreeDepth) { if (RootEdNode == NULL || RootEdNode == NULL) { return; } // collect services if (RootEdNode->Services.Num()) { for (int32 i = 0; i < RootEdNode->Services.Num(); i++) { UBTService* ServiceInstance = RootEdNode->Services[i] ? Cast<UBTService>(RootEdNode->Services[i]->NodeInstance) : NULL; if (ServiceInstance) { ServiceInstance->InitializeNode(RootNode, *ExecutionIndex, 0, TreeDepth); *ExecutionIndex += 1; } } } // gather all nodes int32 ChildIdx = 0; for (int32 PinIdx = 0; PinIdx < RootEdNode->Pins.Num(); PinIdx++) { UEdGraphPin* Pin = RootEdNode->Pins[PinIdx]; if (Pin->Direction != EGPD_Output) { continue; } // sort connections so that they're organized the same as user can see in the editor TArray<UEdGraphPin*> SortedPins = Pin->LinkedTo; SortedPins.Sort(FCompareNodeXLocation()); for (int32 Index = 0; Index < SortedPins.Num(); ++Index) { UBehaviorTreeGraphNode* GraphNode = Cast<UBehaviorTreeGraphNode>(SortedPins[Index]->GetOwningNode()); if (GraphNode == NULL) { continue; } UBTTaskNode* TaskInstance = Cast<UBTTaskNode>(GraphNode->NodeInstance); UBTCompositeNode* CompositeInstance = Cast<UBTCompositeNode>(GraphNode->NodeInstance); UBTNode* ChildNode = CompositeInstance ? (UBTNode*)CompositeInstance : (UBTNode*)TaskInstance; if (ChildNode == NULL) { continue; } // collect decorators TArray<UBTDecorator*> DecoratorInstances; TArray<FBTDecoratorLogic> DecoratorOperations; CollectDecorators(NULL, GraphNode, DecoratorInstances, DecoratorOperations, true, RootNode, ExecutionIndex, TreeDepth, ChildIdx); InitializeInjectedNodes(GraphNode, RootNode, *ExecutionIndex, TreeDepth, ChildIdx); // special case: subtrees UBTTask_RunBehavior* SubtreeTask = Cast<UBTTask_RunBehavior>(TaskInstance); if (SubtreeTask) { *ExecutionIndex += SubtreeTask->GetInjectedNodesCount(); } ChildNode->InitializeNode(RootNode, *ExecutionIndex, 0, TreeDepth); *ExecutionIndex += 1; ChildIdx++; if (CompositeInstance) { RebuildExecutionOrder(GraphNode, CompositeInstance, ExecutionIndex, TreeDepth + 1); CompositeInstance->InitializeComposite((*ExecutionIndex) - 1); } } } }
void CreateChildren(UBehaviorTree* BTAsset, UBTCompositeNode* RootNode, const UBehaviorTreeGraphNode* RootEdNode, uint16* ExecutionIndex, uint8 TreeDepth) { if (RootEdNode == NULL) { return; } RootNode->Children.Reset(); RootNode->Services.Reset(); // collect services if (RootEdNode->Services.Num()) { for (int32 i = 0; i < RootEdNode->Services.Num(); i++) { UBTService* ServiceInstance = RootEdNode->Services[i] ? Cast<UBTService>(RootEdNode->Services[i]->NodeInstance) : NULL; if (ServiceInstance) { if (Cast<UBehaviorTree>(ServiceInstance->GetOuter()) == NULL) { ServiceInstance->Rename(NULL, BTAsset); } ServiceInstance->InitializeNode(RootNode, *ExecutionIndex, 0, TreeDepth); *ExecutionIndex += 1; RootNode->Services.Add(ServiceInstance); } } } // gather all nodes int32 ChildIdx = 0; for (int32 PinIdx = 0; PinIdx < RootEdNode->Pins.Num(); PinIdx++) { UEdGraphPin* Pin = RootEdNode->Pins[PinIdx]; if (Pin->Direction != EGPD_Output) { continue; } // sort connections so that they're organized the same as user can see in the editor Pin->LinkedTo.Sort(FCompareNodeXLocation()); for (int32 Index = 0; Index < Pin->LinkedTo.Num(); ++Index) { UBehaviorTreeGraphNode* GraphNode = Cast<UBehaviorTreeGraphNode>(Pin->LinkedTo[Index]->GetOwningNode()); if (GraphNode == NULL) { continue; } UBTTaskNode* TaskInstance = Cast<UBTTaskNode>(GraphNode->NodeInstance); if (TaskInstance && Cast<UBehaviorTree>(TaskInstance->GetOuter()) == NULL) { TaskInstance->Rename(NULL, BTAsset); } UBTCompositeNode* CompositeInstance = Cast<UBTCompositeNode>(GraphNode->NodeInstance); if (CompositeInstance && Cast<UBehaviorTree>(CompositeInstance->GetOuter()) == NULL) { CompositeInstance->Rename(NULL, BTAsset); } if (TaskInstance == NULL && CompositeInstance == NULL) { continue; } // collect decorators TArray<UBTDecorator*> DecoratorInstances; TArray<FBTDecoratorLogic> DecoratorOperations; CollectDecorators(BTAsset, GraphNode, DecoratorInstances, DecoratorOperations, true, RootNode, ExecutionIndex, TreeDepth, ChildIdx); // store child data RootNode->Children.AddZeroed(); FBTCompositeChild& ChildInfo = RootNode->Children[ChildIdx]; ChildInfo.ChildComposite = CompositeInstance; ChildInfo.ChildTask = TaskInstance; ChildInfo.Decorators = DecoratorInstances; ChildInfo.DecoratorOps = DecoratorOperations; ChildIdx++; UBTNode* ChildNode = CompositeInstance ? (UBTNode*)CompositeInstance : (UBTNode*)TaskInstance; if (ChildNode && Cast<UBehaviorTree>(ChildNode->GetOuter()) == NULL) { ChildNode->Rename(NULL, BTAsset); } InitializeInjectedNodes(GraphNode, RootNode, *ExecutionIndex, TreeDepth, ChildIdx); // special case: subtrees UBTTask_RunBehavior* SubtreeTask = Cast<UBTTask_RunBehavior>(TaskInstance); if (SubtreeTask) { *ExecutionIndex += SubtreeTask->GetInjectedNodesCount(); } ChildNode->InitializeNode(RootNode, *ExecutionIndex, 0, TreeDepth); *ExecutionIndex += 1; VerifyDecorators(GraphNode); if (CompositeInstance) { CreateChildren(BTAsset, CompositeInstance, GraphNode, ExecutionIndex, TreeDepth + 1); CompositeInstance->InitializeComposite((*ExecutionIndex) - 1); } } } }
void UEnvironmentQueryGraph::UpdateAsset() { if (bLockUpdates) { return; } //let's find root node UEnvironmentQueryGraphNode_Root* RootNode = NULL; for (int32 Index = 0; Index < Nodes.Num(); ++Index) { RootNode = Cast<UEnvironmentQueryGraphNode_Root>(Nodes[Index]); if (RootNode != NULL) { break; } } UEnvQuery* Query = Cast<UEnvQuery>(GetOuter()); Query->Options.Reset(); if (RootNode && RootNode->Pins.Num() > 0 && RootNode->Pins[0]->LinkedTo.Num() > 0) { UEdGraphPin* MyPin = RootNode->Pins[0]; // sort connections so that they're organized the same as user can see in the editor MyPin->LinkedTo.Sort(FCompareNodeXLocation()); for (int32 Index=0; Index < MyPin->LinkedTo.Num(); ++Index) { UEnvironmentQueryGraphNode_Option* OptionNode = Cast<UEnvironmentQueryGraphNode_Option>(MyPin->LinkedTo[Index]->GetOwningNode()); if (OptionNode) { UEnvQueryOption* OptionInstance = Cast<UEnvQueryOption>(OptionNode->NodeInstance); if (OptionInstance != NULL) { OptionInstance->Tests.Reset(); for (int32 iTest = 0; iTest < OptionNode->Tests.Num(); iTest++) { UEnvironmentQueryGraphNode_Test* TestNode = OptionNode->Tests[iTest]; if (TestNode && TestNode->bTestEnabled) { UEnvQueryTest* TestInstance = Cast<UEnvQueryTest>(TestNode->NodeInstance); if (TestInstance) { OptionInstance->Tests.Add(TestInstance); } } } Query->Options.Add(OptionInstance); } } } } RemoveOrphanedNodes(); #if USE_EQS_DEBUGGER UEnvQueryManager::NotifyAssetUpdate(Query); #endif }
void UEnvironmentQueryGraph::UpdateAsset(int32 UpdateFlags) { if (IsLocked()) { return; } // let's find root node UEnvironmentQueryGraphNode_Root* RootNode = NULL; for (int32 Idx = 0; Idx < Nodes.Num(); Idx++) { RootNode = Cast<UEnvironmentQueryGraphNode_Root>(Nodes[Idx]); if (RootNode != NULL) { break; } } UEnvQuery* Query = Cast<UEnvQuery>(GetOuter()); Query->GetOptionsMutable().Reset(); if (RootNode && RootNode->Pins.Num() > 0 && RootNode->Pins[0]->LinkedTo.Num() > 0) { UEdGraphPin* MyPin = RootNode->Pins[0]; // sort connections so that they're organized the same as user can see in the editor MyPin->LinkedTo.Sort(FCompareNodeXLocation()); for (int32 Idx = 0; Idx < MyPin->LinkedTo.Num(); Idx++) { UEnvironmentQueryGraphNode_Option* OptionNode = Cast<UEnvironmentQueryGraphNode_Option>(MyPin->LinkedTo[Idx]->GetOwningNode()); if (OptionNode) { OptionNode->UpdateNodeData(); UEnvQueryOption* OptionInstance = Cast<UEnvQueryOption>(OptionNode->NodeInstance); if (OptionInstance && OptionInstance->Generator) { OptionInstance->Tests.Reset(); for (int32 TestIdx = 0; TestIdx < OptionNode->SubNodes.Num(); TestIdx++) { UAIGraphNode* SubNode = OptionNode->SubNodes[TestIdx]; if (SubNode == nullptr) { continue; } SubNode->ParentNode = OptionNode; UEnvironmentQueryGraphNode_Test* TestNode = Cast<UEnvironmentQueryGraphNode_Test>(SubNode); if (TestNode && TestNode->bTestEnabled) { UEnvQueryTest* TestInstance = Cast<UEnvQueryTest>(TestNode->NodeInstance); if (TestInstance) { OptionInstance->Tests.Add(TestInstance); } } } Query->GetOptionsMutable().Add(OptionInstance); } // FORT-16508 tracking BEGIN: log invalid option if (OptionInstance && OptionInstance->Generator == nullptr) { FString DebugMessage = FString::Printf(TEXT("[%s] UpdateAsset found option instance [pin:%d] without a generator! tests:%d"), FPlatformTime::StrTimestamp(), Idx, OptionNode->SubNodes.Num()); RootNode->LogDebugMessage(DebugMessage); } else if (OptionInstance == nullptr) { FString DebugMessage = FString::Printf(TEXT("[%s] UpdateAsset found option node [pin:%d] without an instance! tests:%d"), FPlatformTime::StrTimestamp(), Idx, OptionNode->SubNodes.Num()); RootNode->LogDebugMessage(DebugMessage); } // FORT-16508 tracking END } } } RemoveOrphanedNodes(); // FORT-16508 tracking BEGIN: find corrupted options if (RootNode) { for (int32 Idx = 0; Idx < Nodes.Num(); Idx++) { UEnvironmentQueryGraphNode_Option* OptionNode = Cast<UEnvironmentQueryGraphNode_Option>(Nodes[Idx]); if (OptionNode) { UEnvQueryOption* OptionInstance = Cast<UEnvQueryOption>(OptionNode->NodeInstance); if (OptionNode->NodeInstance == nullptr || OptionInstance == nullptr || OptionInstance->HasAnyFlags(RF_Transient)) { FString DebugMessage = FString::Printf(TEXT("[%s] found corrupted node after RemoveOrphanedNodes! type:instance option:%s instance:%d transient:%d tests:%d"), FPlatformTime::StrTimestamp(), *GetNameSafe(OptionNode), OptionNode->NodeInstance ? (OptionInstance ? 1 : -1) : 0, OptionNode->NodeInstance ? (OptionNode->HasAnyFlags(RF_Transient) ? 1 : 0) : -1, OptionNode->SubNodes.Num()); RootNode->LogDebugError(DebugMessage); } if (OptionInstance && (OptionInstance->Generator == nullptr || OptionInstance->Generator->HasAnyFlags(RF_Transient))) { FString DebugMessage = FString::Printf(TEXT("[%s] found corrupted node after RemoveOrphanedNodes! type:generator option:%s instance:%d transient:%d tests:%d"), FPlatformTime::StrTimestamp(), *GetNameSafe(OptionNode), OptionNode->NodeInstance ? 1 : 0, OptionNode->NodeInstance ? (OptionNode->HasAnyFlags(RF_Transient) ? 1 : 0) : -1, OptionNode->SubNodes.Num()); RootNode->LogDebugError(DebugMessage); } } } } // FORT-16508 tracking END #if USE_EQS_DEBUGGER UEnvQueryManager::NotifyAssetUpdate(Query); #endif }
void UEnvironmentQueryGraph::UpdateAsset(int32 UpdateFlags) { if (IsLocked()) { return; } // let's find root node UEnvironmentQueryGraphNode_Root* RootNode = NULL; for (int32 Idx = 0; Idx < Nodes.Num(); Idx++) { RootNode = Cast<UEnvironmentQueryGraphNode_Root>(Nodes[Idx]); if (RootNode != NULL) { break; } } UEnvQuery* Query = Cast<UEnvQuery>(GetOuter()); Query->Options.Reset(); if (RootNode && RootNode->Pins.Num() > 0 && RootNode->Pins[0]->LinkedTo.Num() > 0) { UEdGraphPin* MyPin = RootNode->Pins[0]; // sort connections so that they're organized the same as user can see in the editor MyPin->LinkedTo.Sort(FCompareNodeXLocation()); for (int32 Idx = 0; Idx < MyPin->LinkedTo.Num(); Idx++) { UEnvironmentQueryGraphNode_Option* OptionNode = Cast<UEnvironmentQueryGraphNode_Option>(MyPin->LinkedTo[Idx]->GetOwningNode()); if (OptionNode) { OptionNode->UpdateNodeData(); UEnvQueryOption* OptionInstance = Cast<UEnvQueryOption>(OptionNode->NodeInstance); if (OptionInstance && OptionInstance->Generator) { OptionInstance->Tests.Reset(); for (int32 TestIdx = 0; TestIdx < OptionNode->SubNodes.Num(); TestIdx++) { UAIGraphNode* SubNode = OptionNode->SubNodes[TestIdx]; if (SubNode == nullptr) { continue; } SubNode->ParentNode = OptionNode; UEnvironmentQueryGraphNode_Test* TestNode = Cast<UEnvironmentQueryGraphNode_Test>(SubNode); if (TestNode && TestNode->bTestEnabled) { UEnvQueryTest* TestInstance = Cast<UEnvQueryTest>(TestNode->NodeInstance); if (TestInstance) { OptionInstance->Tests.Add(TestInstance); } } } Query->Options.Add(OptionInstance); } } } } RemoveOrphanedNodes(); #if USE_EQS_DEBUGGER UEnvQueryManager::NotifyAssetUpdate(Query); #endif }