static UProperty *GetPropertyByName( UClass *InClass, const FName &Name ) { if ( InClass == NULL ) return NULL; UProperty *Property = GetPropertyByNameRecurse( InClass, Name.ToString() ); if ( Property != NULL ) { return Property; } AActor *AsActor = Cast<AActor>(InClass->ClassDefaultObject); if ( AsActor != NULL ) { FString ComponentPropertyName = Name.ToString(); int32 SplitIndex = 0; if ( ComponentPropertyName.FindChar( '.', SplitIndex ) ) { //FString ComponentName = ComponentPropertyName.LeftChop(SplitIndex); ComponentPropertyName = ComponentPropertyName.RightChop(SplitIndex+1); TInlineComponentArray<UActorComponent*> ActorComponents; AsActor->GetComponents(ActorComponents); for ( auto ComponentIt = ActorComponents.CreateIterator(); ComponentIt; ++ComponentIt ) { UActorComponent *Component = *ComponentIt; check( Component != NULL ); /* if ( Component->GetName() != ComponentName ) { continue; } */ Property = GetPropertyByNameRecurse( Component->GetClass(), ComponentPropertyName ); if ( Property != NULL ) { return Property; } } } } return NULL; }
static UProperty *GetPropertyByName( UObject *Target, UStruct *InStruct, const FString &PropertyName, void ** hContainerPtr, int32 &OutArrayIndex ) { UProperty *Prop = GetPropertyByNameRecurse( Target->GetClass(), PropertyName, hContainerPtr, OutArrayIndex ); if ( Prop == NULL ) { AActor *AsActor = Cast<AActor>(Target); if ( AsActor != NULL ) { FString ComponentPropertyName = PropertyName; int32 SplitIndex = 0; if ( ComponentPropertyName.FindChar( '.', SplitIndex ) ) { //FString ComponentName = ComponentPropertyName.LeftChop(SplitIndex); ComponentPropertyName = ComponentPropertyName.RightChop(SplitIndex+1); TInlineComponentArray<UActorComponent*> ActorComponents; AsActor->GetComponents(ActorComponents); for ( auto ComponentIt = ActorComponents.CreateIterator(); ComponentIt && !Prop; ++ComponentIt ) { UActorComponent *Component = *ComponentIt; check( Component != NULL ); /* if ( Component->GetName() != ComponentName ) { continue; } */ *hContainerPtr = Component; Prop = GetPropertyByNameRecurse( Component->GetClass(), ComponentPropertyName, hContainerPtr, OutArrayIndex ); } } } } return Prop; }
/** * Removes the actor from its level's actor list and generally cleans up the engine's internal state. * What this function does not do, but is handled via garbage collection instead, is remove references * to this actor from all other actors, and kill the actor's resources. This function is set up so that * no problems occur even if the actor is being destroyed inside its recursion stack. * * @param ThisActor Actor to remove. * @param bNetForce [opt] Ignored unless called during play. Default is false. * @param bShouldModifyLevel [opt] If true, Modify() the level before removing the actor. Default is true. * @return true if destroy, false if actor couldn't be destroyed. */ bool UWorld::DestroyActor( AActor* ThisActor, bool bNetForce, bool bShouldModifyLevel ) { check(ThisActor); check(ThisActor->IsValidLowLevel()); //UE_LOG(LogSpawn, Log, "Destroy %s", *ThisActor->GetClass()->GetName() ); if (ThisActor->GetWorld() == NULL) { UE_LOG(LogSpawn, Warning, TEXT("Destroying %s, which doesn't have a valid world pointer"), *ThisActor->GetPathName()); } // If already on list to be deleted, pretend the call was successful. // We don't want recursive calls to trigger destruction notifications multiple times. if (ThisActor->IsPendingKillPending()) { return true; } // In-game deletion rules. if( IsGameWorld() ) { // Never destroy the world settings actor. This used to be enforced by bNoDelete and is actually needed for // seamless travel and network games. if (GetWorldSettings() == ThisActor) { return false; } // Can't kill if wrong role. if( ThisActor->Role!=ROLE_Authority && !bNetForce && !ThisActor->bNetTemporary ) { return false; } // Don't destroy player actors. APlayerController* PC = Cast<APlayerController>(ThisActor); if ( PC ) { UNetConnection* C = Cast<UNetConnection>(PC->Player); if( C ) { if( C->Channels[0] && C->State!=USOCK_Closed ) { C->bPendingDestroy = true; C->Channels[0]->Close(); } return false; } } } else { ThisActor->Modify(); } // Prevent recursion //FMarkActorIsBeingDestroyed MarkActorIsBeingDestroyed(ThisActor); // Notify the texture streaming manager about the destruction of this actor. IStreamingManager::Get().NotifyActorDestroyed( ThisActor ); // Tell this actor it's about to be destroyed. ThisActor->Destroyed(); // Detach this actor's children TArray<AActor*> AttachedActors; ThisActor->GetAttachedActors(AttachedActors); if (AttachedActors.Num() > 0) { TInlineComponentArray<USceneComponent*> SceneComponents; ThisActor->GetComponents(SceneComponents); for (TArray< AActor* >::TConstIterator AttachedActorIt(AttachedActors); AttachedActorIt; ++AttachedActorIt) { AActor* ChildActor = *AttachedActorIt; if (ChildActor != NULL) { for (auto SceneCompIter = SceneComponents.CreateIterator(); SceneCompIter; ++SceneCompIter) { ChildActor->DetachSceneComponentsFromParent(*SceneCompIter, true); } #if WITH_EDITOR if( GIsEditor ) { GEngine->BroadcastLevelActorDetached(ChildActor, ThisActor); } #endif } } } // Detach from anything we were attached to USceneComponent* RootComp = ThisActor->GetRootComponent(); if( RootComp != NULL && RootComp->AttachParent != NULL) { AActor* OldParentActor = RootComp->AttachParent->GetOwner(); if (OldParentActor) { OldParentActor->Modify(); } ThisActor->DetachRootComponentFromParent(); #if WITH_EDITOR if( GIsEditor ) { GEngine->BroadcastLevelActorDetached(ThisActor, OldParentActor); } #endif } ThisActor->ClearComponentOverlaps(); // If this actor has an owner, notify it that it has lost a child. if( ThisActor->GetOwner() ) { ThisActor->SetOwner(NULL); } // Notify net players that this guy has been destroyed. UNetDriver* ActorNetDriver = GEngine->FindNamedNetDriver(this, ThisActor->NetDriverName); if (ActorNetDriver) { ActorNetDriver->NotifyActorDestroyed(ThisActor); } if ( DemoNetDriver ) { DemoNetDriver->NotifyActorDestroyed( ThisActor ); } // Remove the actor from the actor list. RemoveActor( ThisActor, bShouldModifyLevel ); // Invalidate the lighting cache in the Editor. We need to check for GIsEditor as play has not begun in network game and objects get destroyed on switching levels if ( GIsEditor ) { ThisActor->InvalidateLightingCache(); #if WITH_EDITOR GEngine->BroadcastLevelActorDeleted(ThisActor); #endif } // Clean up the actor's components. ThisActor->UnregisterAllComponents(); // Mark the actor and its direct components as pending kill. ThisActor->MarkPendingKill(); ThisActor->MarkPackageDirty(); ThisActor->MarkComponentsAsPendingKill(); // Unregister the actor's tick function const bool bRegisterTickFunctions = false; const bool bIncludeComponents = true; ThisActor->RegisterAllActorTickFunctions(bRegisterTickFunctions, bIncludeComponents); // Return success. return true; }
USceneComponent* USCS_Node::GetParentComponentTemplate(UBlueprint* InBlueprint) const { USceneComponent* ParentComponentTemplate = NULL; if(ParentComponentOrVariableName != NAME_None) { check(InBlueprint != NULL && InBlueprint->GeneratedClass != NULL); // If the parent component template is found in the 'Components' array of the CDO (i.e. native) if(bIsParentComponentNative) { // Access the Blueprint CDO AActor* CDO = InBlueprint->GeneratedClass->GetDefaultObject<AActor>(); if(CDO != NULL) { // Find the component template in the CDO that matches the specified name TInlineComponentArray<USceneComponent*> Components; CDO->GetComponents(Components); for(auto CompIt = Components.CreateIterator(); CompIt; ++CompIt) { USceneComponent* CompTemplate = *CompIt; if(CompTemplate->GetFName() == ParentComponentOrVariableName) { // Found a match; this is our parent, we're done ParentComponentTemplate = CompTemplate; break; } } } } // Otherwise the parent component template is found in a parent Blueprint's SCS tree (i.e. non-native) else { // Get the Blueprint hierarchy TArray<UBlueprint*> ParentBPStack; UBlueprint::GetBlueprintHierarchyFromClass(InBlueprint->GeneratedClass, ParentBPStack); // Find the parent Blueprint in the hierarchy for(int32 StackIndex = ParentBPStack.Num() - 1; StackIndex > 0; --StackIndex) { UBlueprint* ParentBlueprint = ParentBPStack[StackIndex]; if(ParentBlueprint != NULL && ParentBlueprint->SimpleConstructionScript != NULL && ParentBlueprint->GeneratedClass->GetFName() == ParentComponentOwnerClassName) { // Find the SCS node with a variable name that matches the specified name TArray<USCS_Node*> ParentSCSNodes = ParentBlueprint->SimpleConstructionScript->GetAllNodes(); for(int32 ParentNodeIndex = 0; ParentNodeIndex < ParentSCSNodes.Num(); ++ParentNodeIndex) { USceneComponent* CompTemplate = Cast<USceneComponent>(ParentSCSNodes[ParentNodeIndex]->ComponentTemplate); if(CompTemplate != NULL && ParentSCSNodes[ParentNodeIndex]->VariableName == ParentComponentOrVariableName) { // Found a match; this is our parent, we're done ParentComponentTemplate = CompTemplate; break; } } } } } } return ParentComponentTemplate; }