コード例 #1
0
void FBlueprintCompileReinstancer::ReinstanceFast()
{
	UE_LOG(LogBlueprint, Log, TEXT("BlueprintCompileReinstancer: Doing a fast path refresh on class '%s'."), *GetPathNameSafe(ClassToReinstance));

	TArray<UObject*> ObjectsToReplace;
	GetObjectsOfClass(DuplicatedClass, ObjectsToReplace, /*bIncludeDerivedClasses=*/ false);

	const bool bIsActor = ClassToReinstance->IsChildOf<AActor>();
	const bool bIsAnimInstance = ClassToReinstance->IsChildOf<UAnimInstance>();
	const bool bIsComponent = ClassToReinstance->IsChildOf<UActorComponent>();
	for (auto Obj : ObjectsToReplace)
	{
		UE_LOG(LogBlueprint, Log, TEXT("  Fast path is refreshing (not replacing) %s"), *Obj->GetFullName());

		if ((!Obj->IsTemplate() || bIsComponent) && !Obj->IsPendingKill())
		{
			const bool bIsSelected = bIsActor ? Obj->IsSelected() : false;

			Obj->SetClass(ClassToReinstance);

			if (bIsActor)
			{
				auto Actor = CastChecked<AActor>(Obj);
				Actor->ReregisterAllComponents();
				Actor->RerunConstructionScripts();

				if (bIsSelected)
				{
					GEditor->SelectActor(Actor, /*bInSelected =*/true, /*bNotify =*/true, false, true);
				}
			}

			if (bIsAnimInstance)
			{
				// Initialising the anim instance isn't enough to correctly set up the skeletal mesh again in a
				// paused world, need to initialise the skeletal mesh component that contains the anim instance.
				if (USkeletalMeshComponent* SkelComponent = Cast<USkeletalMeshComponent>(Obj->GetOuter()))
				{
					SkelComponent->InitAnim(true);
				}
			}
		}
	}

	TArray<UObject*> SourceObjects;
	TMap<UObject*, UObject*> OldToNewInstanceMap;
	TMap<FStringAssetReference, UObject*> ReinstancedObjectsWeakReferenceMap;
	FReplaceReferenceHelper::IncludeCDO(DuplicatedClass, ClassToReinstance, OldToNewInstanceMap, SourceObjects, OriginalCDO);
	FReplaceReferenceHelper::FindAndReplaceReferences(SourceObjects, &ObjectsThatShouldUseOldStuff, ObjectsToReplace, OldToNewInstanceMap, ReinstancedObjectsWeakReferenceMap);
}
コード例 #2
0
void AActor::PostEditMove(bool bFinished)
{
	if ( ReregisterComponentsWhenModified() )
	{
		UBlueprint* Blueprint = Cast<UBlueprint>(GetClass()->ClassGeneratedBy);
		if(Blueprint && (Blueprint->bRunConstructionScriptOnDrag || bFinished) && !FLevelUtils::IsMovingLevel() )
		{
			FNavigationLockContext NavLock(GetWorld(), ENavigationLockReason::AllowUnregister);
			RerunConstructionScripts();
		}
	}

	if ( bFinished )
	{
		GetWorld()->bDoDelayedUpdateCullDistanceVolumes = true;
		GetWorld()->bAreConstraintsDirty = true;

		FEditorSupportDelegates::RefreshPropertyWindows.Broadcast();

		// Let other systems know that an actor was moved
		GEngine->BroadcastOnActorMoved( this );

		FEditorSupportDelegates::UpdateUI.Broadcast();
	}

	// If the root component was not just recreated by the construction script - call PostEditComponentMove on it
	if(RootComponent != NULL && !RootComponent->IsCreatedByConstructionScript())
	{
		// @TODO Should we call on ALL components?
		RootComponent->PostEditComponentMove(bFinished);
	}

	if (bFinished)
	{
		// update actor and all its components in navigation system after finishing move
		// USceneComponent::UpdateNavigationData works only in game world
		UNavigationSystem::UpdateNavOctreeBounds(this);

		TArray<AActor*> ParentedActors;
		GetAttachedActors(ParentedActors);
		for (int32 Idx = 0; Idx < ParentedActors.Num(); Idx++)
		{
			UNavigationSystem::UpdateNavOctreeBounds(ParentedActors[Idx]);
		}

		// not doing manual update of all attached actors since UpdateActorAndComponentsInNavOctree should take care of it
		UNavigationSystem::UpdateActorAndComponentsInNavOctree(*this);
	}
}
コード例 #3
0
void AActor::PostEditChangeProperty(FPropertyChangedEvent& PropertyChangedEvent)
{
	UProperty* PropertyThatChanged = PropertyChangedEvent.Property;
	FName PropertyName = PropertyThatChanged != NULL ? PropertyThatChanged->GetFName() : NAME_None;
	
	const bool bTransformationChanged = (PropertyName == Name_RelativeLocation || PropertyName == Name_RelativeRotation || PropertyName == Name_RelativeScale3D);

	// During SIE, allow components to reregistered and reconstructed in PostEditChangeProperty.
	// This is essential as construction is deferred during spawning / duplication when in SIE.
	if ((GEditor && GEditor->bIsSimulatingInEditor) || ReregisterComponentsWhenModified())
	{
		// In the Undo case we have an annotation storing information about constructed components and we do not want
		// to improperly apply out of date changes so we need to skip registration of all blueprint created components
		// and defer instance components attached to them until after rerun
		if (CurrentTransactionAnnotation.IsValid())
		{
			UnregisterAllComponents();

			TInlineComponentArray<UActorComponent*> Components;
			GetComponents(Components);

			Components.Sort([](UActorComponent& A, UActorComponent& B)
			{
				if (&B == B.GetOwner()->GetRootComponent())
				{
					return false;
				}
				if (USceneComponent* ASC = Cast<USceneComponent>(&A))
				{
					if (ASC->GetAttachParent() == &B)
					{
						return false;
					}
				}
				return true;
			});

			bool bRequiresReregister = false;
			for (UActorComponent* Component : Components)
			{
				if (Component->CreationMethod == EComponentCreationMethod::Native)
				{
					Component->RegisterComponent();
				}
				else if (Component->CreationMethod == EComponentCreationMethod::Instance)
				{
					USceneComponent* SC = Cast<USceneComponent>(Component);
					if (SC == nullptr || SC == RootComponent || (SC->GetAttachParent() && SC->GetAttachParent()->IsRegistered()))
					{
						Component->RegisterComponent();
					}
					else
					{
						bRequiresReregister = true;
					}
				}
				else
				{
					bRequiresReregister = true;
				}
			}

			RerunConstructionScripts();

			if (bRequiresReregister)
			{
				ReregisterAllComponents();
			}
		}
		else
		{
			UnregisterAllComponents();
			RerunConstructionScripts();
			ReregisterAllComponents();
		}
	}

	// Let other systems know that an actor was moved
	if (bTransformationChanged)
	{
		GEngine->BroadcastOnActorMoved( this );
	}

	if (GetWorld())
	{
		GetWorld()->bDoDelayedUpdateCullDistanceVolumes = true;
	}

	FEditorSupportDelegates::UpdateUI.Broadcast();
	Super::PostEditChangeProperty(PropertyChangedEvent);
}