void USimpleConstructionScript::ValidateSceneRootNodes() { #if WITH_EDITOR UBlueprint* Blueprint = GetBlueprint(); if(DefaultSceneRootNode == nullptr) { // If applicable, create a default scene component node if(Blueprint != nullptr && FBlueprintEditorUtils::IsActorBased(Blueprint) && Blueprint->BlueprintType != BPTYPE_MacroLibrary) { DefaultSceneRootNode = CreateNode(USceneComponent::StaticClass(), USceneComponent::GetDefaultSceneRootVariableName()); CastChecked<USceneComponent>(DefaultSceneRootNode->ComponentTemplate)->bVisualizeComponent = true; } } if(DefaultSceneRootNode != nullptr) { // Get the current root component template const USceneComponent* RootComponentTemplate = GetSceneRootComponentTemplate(); // Add the default scene root back in if there are no other scene component nodes that can be used as root; otherwise, remove it if(RootComponentTemplate == nullptr && !RootNodes.Contains(DefaultSceneRootNode)) { RootNodes.Add(DefaultSceneRootNode); AllNodes.Add(DefaultSceneRootNode); } else if(RootComponentTemplate != nullptr && RootNodes.Contains(DefaultSceneRootNode)) { // If the default scene root has any child nodes, determine what they should parent to. USCS_Node* RootNode = nullptr; bool bIsParentComponentNative = false; FName ParentComponentOrVariableName = NAME_None; FName ParentComponentOwnerClassName = NAME_None; if(UBlueprintGeneratedClass* BPClass = Cast<UBlueprintGeneratedClass>(RootComponentTemplate->GetOuter())) { // The root scene component is an SCS node. if(BPClass->SimpleConstructionScript != nullptr) { const TArray<USCS_Node*> SCSRootNodes = BPClass->SimpleConstructionScript->GetRootNodes(); for(USCS_Node* SCSNode : SCSRootNodes) { if(SCSNode != nullptr && SCSNode->ComponentTemplate == RootComponentTemplate) { if(BPClass->SimpleConstructionScript != this) { // The root node is inherited from a parent BP class. ParentComponentOwnerClassName = BPClass->GetFName(); ParentComponentOrVariableName = SCSNode->VariableName; } else { // The root node belongs to the current BP class. RootNode = SCSNode; } break; } } } } else { // The root scene component is a native component. bIsParentComponentNative = true; ParentComponentOrVariableName = RootComponentTemplate->GetFName(); } // Reparent any child nodes within the current hierarchy. for(USCS_Node* ChildNode : DefaultSceneRootNode->ChildNodes) { if(RootNode != nullptr) { // We have an existing root node within the current BP class. RootNode->AddChildNode(ChildNode, false); } else { // The current root node is inherited from a parent class (may be BP or native). RootNodes.Add(ChildNode); ChildNode->bIsParentComponentNative = bIsParentComponentNative; ChildNode->ParentComponentOrVariableName = ParentComponentOrVariableName; ChildNode->ParentComponentOwnerClassName = ParentComponentOwnerClassName; } } // Remove the default scene root node from the current hierarchy. RootNodes.Remove(DefaultSceneRootNode); AllNodes.Remove(DefaultSceneRootNode); DefaultSceneRootNode->ChildNodes.Empty(); // These shouldn't be set, but just in case... DefaultSceneRootNode->bIsParentComponentNative = false; DefaultSceneRootNode->ParentComponentOrVariableName = NAME_None; DefaultSceneRootNode->ParentComponentOwnerClassName = NAME_None; } } #endif // WITH_EDITOR }
void USimpleConstructionScript::FixupSceneNodeHierarchy() { #if WITH_EDITOR // determine the scene's root component, this isn't necessarily a node owned // by this SCS; it could be from a super SCS, or (if SceneRootNode and // SceneRootComponentTemplate is not) it could be a native component USCS_Node* SceneRootNode = nullptr; USceneComponent* SceneRootComponentTemplate = GetSceneRootComponentTemplate(&SceneRootNode); // if there is no scene root (then there shouldn't be anything but the // default placeholder root). if (SceneRootComponentTemplate == nullptr) { return; } bool const bIsSceneRootNative = (SceneRootNode == nullptr); bool const bThisOwnsSceneRoot = !bIsSceneRootNative && RootNodes.Contains(SceneRootNode); // iterate backwards so that we can remove nodes from the array as we go for (int32 NodeIndex = RootNodes.Num() - 1; NodeIndex >= 0; --NodeIndex) { USCS_Node* Node = RootNodes[NodeIndex]; // we only care about the scene component hierarchy (non-scene components // can share root placement) if ((Node->ComponentTemplate == nullptr) || !Node->ComponentTemplate->IsA<USceneComponent>()) { continue; } // if this is the scene's root, then we shouldn't fix it up (instead we // need to be nesting others under this one) if (SceneRootComponentTemplate == Node->ComponentTemplate) { continue; } // if this node has a clear parent already defined, then ignore it (I // imagine that its attachment will be handled elsewhere) if (Node->ParentComponentOrVariableName != NAME_None) { continue; } if (bIsSceneRootNative) { // Parent to the native component template if not already attached Node->SetParent(SceneRootComponentTemplate); } else if (bThisOwnsSceneRoot) { // Reparent to this BP's root node if it's still in the root set RootNodes.Remove(Node); SceneRootNode->AddChildNode(Node, false); } else { // Parent to an inherited parent BP's node if not already attached Node->SetParent(SceneRootNode); } } #endif // #if WITH_EDITOR }