void UBTNode::InitializeInSubtree(UBehaviorTreeComponent& OwnerComp, uint8* NodeMemory, int32& NextInstancedIndex, EBTMemoryInit::Type InitType) const { if (bCreateNodeInstance) { // composite nodes can't be instanced! check(IsA(UBTCompositeNode::StaticClass()) == false); UBTNode* NodeInstance = OwnerComp.NodeInstances.IsValidIndex(NextInstancedIndex) ? OwnerComp.NodeInstances[NextInstancedIndex] : NULL; if (NodeInstance == NULL) { NodeInstance = NewObject<UBTNode>(&OwnerComp, GetClass(), GetFName(), RF_NoFlags, (UObject*)(this)); NodeInstance->InitializeNode(GetParentNode(), GetExecutionIndex(), GetMemoryOffset(), GetTreeDepth()); NodeInstance->bIsInstanced = true; OwnerComp.NodeInstances.Add(NodeInstance); } check(NodeInstance); NodeInstance->SetOwner(OwnerComp.GetOwner()); FBTInstancedNodeMemory* MyMemory = GetSpecialNodeMemory<FBTInstancedNodeMemory>(NodeMemory); MyMemory->NodeIdx = NextInstancedIndex; NodeInstance->OnInstanceCreated(OwnerComp); NextInstancedIndex++; } else { InitializeMemory(OwnerComp, NodeMemory, InitType); } }
void UBehaviorTreeGraphNode::PostEditImport() { ResetNodeOwner(); if (NodeInstance) { UBehaviorTree* BT = Cast<UBehaviorTree>(GetBehaviorTreeGraph()->GetOuter()); if (BT) { UBTNode* BTNode = (UBTNode*)NodeInstance; BTNode->InitializeFromAsset(*BT); BTNode->InitializeNode(NULL, MAX_uint16, 0, 0); } } }
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 UBehaviorTreeGraphNode::PostPlacedNewNode() { UClass* NodeClass = ClassData.GetClass(true); if (NodeClass) { UBehaviorTree* BT = Cast<UBehaviorTree>(GetBehaviorTreeGraph()->GetOuter()); if (BT) { NodeInstance = ConstructObject<UBTNode>(NodeClass, BT); UBTNode* BTNode = (UBTNode*)NodeInstance; BTNode->SetFlags(RF_Transactional); BTNode->InitializeFromAsset(*BT); BTNode->InitializeNode(NULL, MAX_uint16, 0, 0); } } }
void UBTNode::InitializeInSubtree(UBehaviorTreeComponent& OwnerComp, uint8* NodeMemory, int32& NextInstancedIndex, EBTMemoryInit::Type InitType) const { FBTInstancedNodeMemory* SpecialMemory = GetSpecialNodeMemory<FBTInstancedNodeMemory>(NodeMemory); if (SpecialMemory) { SpecialMemory->NodeIdx = INDEX_NONE; } if (bCreateNodeInstance) { // composite nodes can't be instanced! check(IsA(UBTCompositeNode::StaticClass()) == false); UBTNode* NodeInstance = OwnerComp.NodeInstances.IsValidIndex(NextInstancedIndex) ? OwnerComp.NodeInstances[NextInstancedIndex] : NULL; if (NodeInstance == NULL) { NodeInstance = (UBTNode*)StaticDuplicateObject(this, &OwnerComp); NodeInstance->InitializeNode(GetParentNode(), GetExecutionIndex(), GetMemoryOffset(), GetTreeDepth()); NodeInstance->bIsInstanced = true; OwnerComp.NodeInstances.Add(NodeInstance); } check(NodeInstance); check(SpecialMemory); SpecialMemory->NodeIdx = NextInstancedIndex; NodeInstance->SetOwner(OwnerComp.GetOwner()); NodeInstance->InitializeMemory(OwnerComp, NodeMemory, InitType); check(TreeAsset); NodeInstance->InitializeFromAsset(*TreeAsset); NodeInstance->OnInstanceCreated(OwnerComp); NextInstancedIndex++; } else { InitializeMemory(OwnerComp, NodeMemory, InitType); } }
void UBehaviorTreeGraph::UpdateAsset(EDebuggerFlags DebuggerFlags, bool bBumpVersion) { if (bLockUpdates) { return; } // initial cleanup & root node search UBehaviorTreeGraphNode_Root* RootNode = NULL; for (int32 Index = 0; Index < Nodes.Num(); ++Index) { UBehaviorTreeGraphNode* Node = Cast<UBehaviorTreeGraphNode>(Nodes[Index]); // debugger flags if (DebuggerFlags == ClearDebuggerFlags) { Node->ClearDebuggerState(); for (int32 iAux = 0; iAux < Node->Services.Num(); iAux++) { Node->Services[iAux]->ClearDebuggerState(); } for (int32 iAux = 0; iAux < Node->Decorators.Num(); iAux++) { Node->Decorators[iAux]->ClearDebuggerState(); } } // parent chain Node->ParentNode = NULL; for (int32 iAux = 0; iAux < Node->Services.Num(); iAux++) { Node->Services[iAux]->ParentNode = Node; } for (int32 iAux = 0; iAux < Node->Decorators.Num(); iAux++) { Node->Decorators[iAux]->ParentNode = Node; } // 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) { CreateBTFromGraph(Node); if (bBumpVersion) { GraphVersion++; } } } }
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); } } } }