//----------------------------------------------------------------------// // FBehaviorTreeInstance //----------------------------------------------------------------------// void FBehaviorTreeInstance::Initialize(UBehaviorTreeComponent& OwnerComp, UBTCompositeNode& Node, int32& InstancedIndex, EBTMemoryInit::Type InitType) { for (int32 ServiceIndex = 0; ServiceIndex < Node.Services.Num(); ServiceIndex++) { Node.Services[ServiceIndex]->InitializeInSubtree(OwnerComp, Node.Services[ServiceIndex]->GetNodeMemory<uint8>(*this), InstancedIndex, InitType); } uint8* NodeMemory = Node.GetNodeMemory<uint8>(*this); Node.InitializeInSubtree(OwnerComp, NodeMemory, InstancedIndex, InitType); UBTCompositeNode* InstancedComposite = Cast<UBTCompositeNode>(Node.GetNodeInstance(OwnerComp, NodeMemory)); if (InstancedComposite) { InstancedComposite->InitializeComposite(Node.GetLastExecutionIndex()); } for (int32 ChildIndex = 0; ChildIndex < Node.Children.Num(); ChildIndex++) { FBTCompositeChild& ChildInfo = Node.Children[ChildIndex]; for (int32 DecoratorIndex = 0; DecoratorIndex < ChildInfo.Decorators.Num(); DecoratorIndex++) { UBTDecorator* DecoratorOb = ChildInfo.Decorators[DecoratorIndex]; uint8* DecoratorMemory = DecoratorOb->GetNodeMemory<uint8>(*this); DecoratorOb->InitializeInSubtree(OwnerComp, DecoratorMemory, InstancedIndex, InitType); UBTDecorator* InstancedDecoratorOb = Cast<UBTDecorator>(DecoratorOb->GetNodeInstance(OwnerComp, DecoratorMemory)); if (InstancedDecoratorOb) { InstancedDecoratorOb->InitializeParentLink(DecoratorOb->GetChildIndex()); } } if (ChildInfo.ChildComposite) { Initialize(OwnerComp, *(ChildInfo.ChildComposite), InstancedIndex, InitType); } else if (ChildInfo.ChildTask) { for (int32 ServiceIndex = 0; ServiceIndex < ChildInfo.ChildTask->Services.Num(); ServiceIndex++) { UBTService* ServiceOb = ChildInfo.ChildTask->Services[ServiceIndex]; uint8* ServiceMemory = ServiceOb->GetNodeMemory<uint8>(*this); ServiceOb->InitializeInSubtree(OwnerComp, ServiceMemory, InstancedIndex, InitType); UBTService* InstancedServiceOb = Cast<UBTService>(ServiceOb->GetNodeInstance(OwnerComp, ServiceMemory)); if (InstancedServiceOb) { InstancedServiceOb->InitializeParentLink(ServiceOb->GetChildIndex()); } } ChildInfo.ChildTask->InitializeInSubtree(OwnerComp, ChildInfo.ChildTask->GetNodeMemory<uint8>(*this), InstancedIndex, InitType); } } }
void UBehaviorTreeGraph::RebuildExecutionOrder() { // initial cleanup & root node search UBehaviorTreeGraphNode_Root* RootNode = NULL; for (int32 Index = 0; Index < Nodes.Num(); ++Index) { UBehaviorTreeGraphNode* Node = Cast<UBehaviorTreeGraphNode>(Nodes[Index]); // prepare node instance UBTNode* NodeInstance = Cast<UBTNode>(Node->NodeInstance); if (NodeInstance) { // mark all nodes as disconnected first, path from root will replace it with valid values later NodeInstance->InitializeNode(NULL, MAX_uint16, 0, 0); } // cache root if (RootNode == NULL) { RootNode = Cast<UBehaviorTreeGraphNode_Root>(Nodes[Index]); } UBehaviorTreeGraphNode_CompositeDecorator* CompositeDecorator = Cast<UBehaviorTreeGraphNode_CompositeDecorator>(Nodes[Index]); if (CompositeDecorator) { CompositeDecorator->ResetExecutionRange(); } } if (RootNode && RootNode->Pins.Num() > 0 && RootNode->Pins[0]->LinkedTo.Num() > 0) { UBehaviorTreeGraphNode* Node = Cast<UBehaviorTreeGraphNode>(RootNode->Pins[0]->LinkedTo[0]->GetOwningNode()); if (Node) { UBTCompositeNode* BTNode = Cast<UBTCompositeNode>(Node->NodeInstance); if (BTNode) { uint16 ExecutionIndex = 0; uint8 TreeDepth = 0; BTNode->InitializeNode(NULL, ExecutionIndex, 0, TreeDepth); ExecutionIndex++; BTGraphHelpers::RebuildExecutionOrder(Node, BTNode, &ExecutionIndex, TreeDepth); } } } }
void FBehaviorTreeInstance::CleanupNodes(UBehaviorTreeComponent& OwnerComp, UBTCompositeNode& Node, EBTMemoryClear::Type CleanupType) { for (int32 ServiceIndex = 0; ServiceIndex < Node.Services.Num(); ServiceIndex++) { Node.Services[ServiceIndex]->CleanupInSubtree(OwnerComp, Node.Services[ServiceIndex]->GetNodeMemory<uint8>(*this), CleanupType); } Node.CleanupInSubtree(OwnerComp, Node.GetNodeMemory<uint8>(*this), CleanupType); for (int32 ChildIndex = 0; ChildIndex < Node.Children.Num(); ChildIndex++) { FBTCompositeChild& ChildInfo = Node.Children[ChildIndex]; for (int32 DecoratorIndex = 0; DecoratorIndex < ChildInfo.Decorators.Num(); DecoratorIndex++) { ChildInfo.Decorators[DecoratorIndex]->CleanupInSubtree(OwnerComp, ChildInfo.Decorators[DecoratorIndex]->GetNodeMemory<uint8>(*this), CleanupType); } if (ChildInfo.ChildComposite) { CleanupNodes(OwnerComp, *(ChildInfo.ChildComposite), CleanupType); } else if (ChildInfo.ChildTask) { for (int32 ServiceIndex = 0; ServiceIndex < ChildInfo.ChildTask->Services.Num(); ServiceIndex++) { ChildInfo.ChildTask->Services[ServiceIndex]->CleanupInSubtree(OwnerComp, ChildInfo.ChildTask->Services[ServiceIndex]->GetNodeMemory<uint8>(*this), CleanupType); } ChildInfo.ChildTask->CleanupInSubtree(OwnerComp, ChildInfo.ChildTask->GetNodeMemory<uint8>(*this), CleanupType); } } }
END_SLATE_FUNCTION_BUILD_OPTIMIZATION void FBehaviorDecoratorDetails::UpdateAllowedAbortModes() { ModeValues.Reset(); UBTDecorator* MyDecorator = Cast<UBTDecorator>(MyNode); UBTCompositeNode* MyParentNode = MyDecorator ? MyDecorator->GetParentNode() : NULL; const bool bAllowAbortNone = MyDecorator == NULL || MyDecorator->bAllowAbortNone; const bool bAllowAbortSelf = (MyDecorator == NULL || MyDecorator->bAllowAbortChildNodes) && (MyParentNode == NULL || MyParentNode->CanAbortSelf()); const bool bAllowAbortLowerPriority = (MyDecorator == NULL || MyDecorator->bAllowAbortLowerPri) && (MyParentNode == NULL || MyParentNode->CanAbortLowerPriority()); const bool AbortCondition[] = { bAllowAbortNone, bAllowAbortSelf, bAllowAbortLowerPriority, bAllowAbortSelf && bAllowAbortLowerPriority }; EBTFlowAbortMode::Type AbortValues[] = { EBTFlowAbortMode::None, EBTFlowAbortMode::Self, EBTFlowAbortMode::LowerPriority, EBTFlowAbortMode::Both }; for (int32 i = 0; i < 4; i++) { if (AbortCondition[i]) { FStringIntPair ModeDesc; ModeDesc.Int = AbortValues[i]; ModeDesc.Str = UBehaviorTreeTypes::DescribeFlowAbortMode(AbortValues[i]); ModeValues.Add(ModeDesc); } } bIsModeEnabled = MyDecorator && ModeValues.Num(); bShowMode = ModeValues.Num() > 0; }
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); } } } }
static void InitializeNodeHelper(UBTCompositeNode* ParentNode, UBTNode* NodeOb, uint8 TreeDepth, uint16& ExecutionIndex, TArray<FNodeInitializationData>& InitList, UBehaviorTree& TreeAsset, UObject* NodeOuter) { // special case: subtrees UBTTask_RunBehavior* SubtreeTask = Cast<UBTTask_RunBehavior>(NodeOb); if (SubtreeTask) { ExecutionIndex += SubtreeTask->GetInjectedNodesCount(); } InitList.Add(FNodeInitializationData(NodeOb, ParentNode, ExecutionIndex, TreeDepth, NodeOb->GetInstanceMemorySize(), NodeOb->GetSpecialMemorySize())); NodeOb->InitializeFromAsset(TreeAsset); ExecutionIndex++; UBTCompositeNode* CompositeOb = Cast<UBTCompositeNode>(NodeOb); if (CompositeOb) { for (int32 ServiceIndex = 0; ServiceIndex < CompositeOb->Services.Num(); ServiceIndex++) { if (CompositeOb->Services[ServiceIndex] == NULL) { UE_LOG(LogBehaviorTree, Warning, TEXT("%s has missing service node! (parent: %s)"), *TreeAsset.GetName(), *UBehaviorTreeTypes::DescribeNodeHelper(CompositeOb)); CompositeOb->Services.RemoveAt(ServiceIndex, 1, false); ServiceIndex--; continue; } UBTService* Service = Cast<UBTService>(StaticDuplicateObject(CompositeOb->Services[ServiceIndex], NodeOuter, TEXT("None")));; CompositeOb->Services[ServiceIndex] = Service; InitList.Add(FNodeInitializationData(Service, CompositeOb, ExecutionIndex, TreeDepth, Service->GetInstanceMemorySize(), Service->GetSpecialMemorySize())); Service->InitializeFromAsset(TreeAsset); ExecutionIndex++; } for (int32 ChildIndex = 0; ChildIndex < CompositeOb->Children.Num(); ChildIndex++) { FBTCompositeChild& ChildInfo = CompositeOb->Children[ChildIndex]; for (int32 DecoratorIndex = 0; DecoratorIndex < ChildInfo.Decorators.Num(); DecoratorIndex++) { if (ChildInfo.Decorators[DecoratorIndex] == NULL) { UE_LOG(LogBehaviorTree, Warning, TEXT("%s has missing decorator node! (parent: %s, branch: %d)"), *TreeAsset.GetName(), *UBehaviorTreeTypes::DescribeNodeHelper(CompositeOb), ChildIndex); ChildInfo.Decorators.RemoveAt(DecoratorIndex, 1, false); DecoratorIndex--; continue; } UBTDecorator* Decorator = Cast<UBTDecorator>(StaticDuplicateObject(ChildInfo.Decorators[DecoratorIndex], NodeOuter, TEXT("None"))); ChildInfo.Decorators[DecoratorIndex] = Decorator; InitList.Add(FNodeInitializationData(Decorator, CompositeOb, ExecutionIndex, TreeDepth, Decorator->GetInstanceMemorySize(), Decorator->GetSpecialMemorySize())); Decorator->InitializeFromAsset(TreeAsset); Decorator->InitializeDecorator(ChildIndex); ExecutionIndex++; } UBTNode* ChildNode = NULL; if (ChildInfo.ChildComposite) { ChildInfo.ChildComposite = Cast<UBTCompositeNode>(StaticDuplicateObject(ChildInfo.ChildComposite, NodeOuter, TEXT("None"))); ChildNode = ChildInfo.ChildComposite; } else if (ChildInfo.ChildTask) { ChildInfo.ChildTask = Cast<UBTTaskNode>(StaticDuplicateObject(ChildInfo.ChildTask, NodeOuter, TEXT("None"))); ChildNode = ChildInfo.ChildTask; } if (ChildNode) { InitializeNodeHelper(CompositeOb, ChildNode, TreeDepth + 1, ExecutionIndex, InitList, TreeAsset, NodeOuter); } } CompositeOb->InitializeComposite(ExecutionIndex - 1); } }