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;
	}
Exemplo n.º 3
0
/**
 * 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;
}
Exemplo n.º 4
0
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;
}