AActor* UVREditorMode::SpawnTransientSceneActor(TSubclassOf<AActor> ActorClass, const FString& ActorName, const bool bWithSceneComponent) const { const bool bWasWorldPackageDirty = GetWorld()->GetOutermost()->IsDirty(); // @todo vreditor: Needs respawn if world changes (map load, etc.) Will that always restart the editor mode anyway? FActorSpawnParameters ActorSpawnParameters; ActorSpawnParameters.Name = MakeUniqueObjectName( GetWorld(), ActorClass, *ActorName ); // @todo vreditor: Without this, SpawnActor() can return us an existing PendingKill actor of the same name! WTF? ActorSpawnParameters.SpawnCollisionHandlingOverride = ESpawnActorCollisionHandlingMethod::AlwaysSpawn; ActorSpawnParameters.ObjectFlags = EObjectFlags::RF_Transient; check( ActorClass != nullptr ); AActor* NewActor = GetWorld()->SpawnActor< AActor >( ActorClass, ActorSpawnParameters ); NewActor->SetActorLabel( ActorName ); if( bWithSceneComponent ) { // Give the new actor a root scene component, so we can attach multiple sibling components to it USceneComponent* SceneComponent = NewObject<USceneComponent>( NewActor ); NewActor->AddOwnedComponent( SceneComponent ); NewActor->SetRootComponent( SceneComponent ); SceneComponent->RegisterComponent(); } // Don't dirty the level file after spawning a transient actor if( !bWasWorldPackageDirty ) { GetWorld()->GetOutermost()->SetDirtyFlag( false ); } return NewActor; }
void FDeferRegisterStaticComponents::RegisterComponents(AActor* Actor) { TArray<FDeferredComponentInfo>* ActorComponentsToRegister = ComponentsToRegister.Find(Actor); if (ActorComponentsToRegister) { for (int32 ComponentIndex = 0; ComponentIndex < ActorComponentsToRegister->Num(); ++ComponentIndex) { const FDeferredComponentInfo& SavedInfo = (*ActorComponentsToRegister)[ComponentIndex]; USceneComponent* Component = SavedInfo.Component; // Restore saved mobility just before registering this component. Component->Mobility = SavedInfo.SavedMobility; Component->RegisterComponent(); } ComponentsToRegister.Remove(Actor); } }
PyObject *py_ue_add_actor_root_component(ue_PyUObject * self, PyObject * args) { ue_py_check(self); PyObject *obj; char *name; if (!PyArg_ParseTuple(args, "Os:add_actor_root_component", &obj, &name)) { return NULL; } if (!self->ue_object->IsA<AActor>()) { return PyErr_Format(PyExc_Exception, "uobject is not an AActor"); } AActor *actor = (AActor *)self->ue_object; if (!ue_is_pyuobject(obj)) { return PyErr_Format(PyExc_Exception, "argument is not a UObject"); } ue_PyUObject *py_obj = (ue_PyUObject *)obj; if (!py_obj->ue_object->IsA<UClass>()) { return PyErr_Format(PyExc_Exception, "argument is not a class"); } USceneComponent *component = NewObject<USceneComponent>(actor, (UClass *)py_obj->ue_object, FName(UTF8_TO_TCHAR(name)), RF_Public); if (!component) return PyErr_Format(PyExc_Exception, "unable to create component"); actor->SetRootComponent(component); if (actor->GetWorld() && !component->IsRegistered()) { component->RegisterComponent(); } if (component->bWantsInitializeComponent && !component->HasBeenInitialized() && component->IsRegistered()) component->InitializeComponent(); Py_RETURN_UOBJECT(component); }
PyObject *py_ue_add_actor_root_component(ue_PyUObject * self, PyObject * args) { ue_py_check(self); PyObject *obj; char *name; if (!PyArg_ParseTuple(args, "Os:add_actor_root_component", &obj, &name)) { return NULL; } if (!self->ue_object->IsA<AActor>()) { return PyErr_Format(PyExc_Exception, "uobject is not an AActor"); } AActor *actor = (AActor *)self->ue_object; if (!ue_is_pyuobject(obj)) { return PyErr_Format(PyExc_Exception, "argument is not a UObject"); } ue_PyUObject *py_obj = (ue_PyUObject *)obj; if (!py_obj->ue_object->IsA<UClass>()) { return PyErr_Format(PyExc_Exception, "argument is not a class"); } USceneComponent *component = NewObject<USceneComponent>(actor, (UClass *)py_obj->ue_object, FName(UTF8_TO_TCHAR(name))); if (!component) return PyErr_Format(PyExc_Exception, "unable to create component"); actor->SetRootComponent(component); if (actor->GetWorld()) { component->RegisterComponent(); } PyObject *ret = (PyObject *)ue_get_python_wrapper(component); if (!ret) return PyErr_Format(PyExc_Exception, "uobject is in invalid state"); Py_INCREF(ret); return ret; }
void USimpleConstructionScript::ExecuteScriptOnActor(AActor* Actor, const FTransform& RootTransform, bool bIsDefaultTransform) { if(RootNodes.Num() > 0) { TSet<UActorComponent*> AllComponentsCreatedBySCS; TInlineComponentArray<UActorComponent*> InstancedComponents; for(auto NodeIt = RootNodes.CreateIterator(); NodeIt; ++NodeIt) { USCS_Node* RootNode = *NodeIt; if(RootNode != nullptr) { // Get all native scene components TInlineComponentArray<USceneComponent*> Components; Actor->GetComponents(Components); for (int32 Index = Components.Num()-1; Index >= 0; --Index) { USceneComponent* SceneComponent = Components[Index]; if (SceneComponent->CreationMethod == EComponentCreationMethod::Instance) { Components.RemoveAt(Index); } else { // Handle the native sub-component of an instance component case USceneComponent* ParentSceneComponent = SceneComponent->GetTypedOuter<USceneComponent>(); if (ParentSceneComponent && ParentSceneComponent->CreationMethod == EComponentCreationMethod::Instance) { Components.RemoveAt(Index); } } } // Get the native root component; if it's not set, the first native scene component will be used as root. This matches what's done in the SCS editor. USceneComponent* RootComponent = Actor->GetRootComponent(); if(RootComponent == nullptr && Components.Num() > 0) { RootComponent = Components[0]; } // If the root node specifies that it has a parent USceneComponent* ParentComponent = nullptr; if(RootNode->ParentComponentOrVariableName != NAME_None) { // Get the Actor class object UClass* ActorClass = Actor->GetClass(); check(ActorClass != nullptr); // If the root node is parented to a "native" component (i.e. in the 'Components' array) if(RootNode->bIsParentComponentNative) { for(int32 CompIndex = 0; CompIndex < Components.Num(); ++CompIndex) { // If we found a match, remember the index if(Components[CompIndex]->GetFName() == RootNode->ParentComponentOrVariableName) { ParentComponent = Components[CompIndex]; break; } } } else { // In the non-native case, the SCS node's variable name property is used as the parent identifier UObjectPropertyBase* Property = FindField<UObjectPropertyBase>(ActorClass, RootNode->ParentComponentOrVariableName); if(Property != nullptr) { // If we found a matching property, grab its value and use that as the parent for this node ParentComponent = Cast<USceneComponent>(Property->GetObjectPropertyValue_InContainer(Actor)); } } } // Create the new component instance and any child components it may have UActorComponent* InstancedComponent = RootNode->ExecuteNodeOnActor(Actor, ParentComponent != nullptr ? ParentComponent : RootComponent, &RootTransform, bIsDefaultTransform); if(InstancedComponent != nullptr) { InstancedComponents.Add(InstancedComponent); } // get list of every component SCS created, in case some of them aren't in the attachment hierarchy any more (e.g. rigid bodies) TInlineComponentArray<USceneComponent*> ComponentsAfterSCS; Actor->GetComponents(ComponentsAfterSCS); for (USceneComponent* C : ComponentsAfterSCS) { if (Components.Contains(C) == false) { AllComponentsCreatedBySCS.Add(C); } } } } // Register all instanced SCS components once SCS execution has finished; sorted in order to register the scene component hierarchy first, followed by the remaining actor components (in case they happen to depend on something in the scene hierarchy) InstancedComponents.Sort([](const UActorComponent& A, const UActorComponent& B) { return A.IsA<USceneComponent>(); }); for(auto InstancedComponent : InstancedComponents) { RegisterInstancedComponent(InstancedComponent); } // now that the instanced components in the attachment hierarchy are registered, register any other components that SCS made but aren't in the attachment hierarchy for whatever reason. for (auto C : AllComponentsCreatedBySCS) { if (C->IsRegistered() == false) { C->RegisterComponent(); } } } else if(Actor->GetRootComponent() == NULL) // Must have a root component at the end of SCS, so if we don't have one already (from base class), create a SceneComponent now { USceneComponent* SceneComp = NewObject<USceneComponent>(Actor); SceneComp->SetFlags(RF_Transactional); SceneComp->CreationMethod = EComponentCreationMethod::SimpleConstructionScript; SceneComp->SetWorldTransform(RootTransform); Actor->SetRootComponent(SceneComp); SceneComp->RegisterComponent(); } }