예제 #1
0
FString FMeshMergingTool::GetDefaultPackageName() const
{
	FString PackageName = FPackageName::FilenameToLongPackageName(FPaths::GameContentDir() + TEXT("SM_MERGED"));

	USelection* SelectedActors = GEditor->GetSelectedActors();
	// Iterate through selected actors and find first static mesh asset
	// Use this static mesh path as destination package name for a merged mesh
	for (FSelectionIterator Iter(*SelectedActors); Iter; ++Iter)
	{
		AActor* Actor = Cast<AActor>(*Iter);
		if (Actor)
		{
			FString ActorName = Actor->GetName();
			PackageName = FString::Printf(TEXT("%s_%s"), *PackageName, *ActorName);
			break;
		}
	}

	if (PackageName.IsEmpty())
	{
		PackageName = MakeUniqueObjectName(NULL, UPackage::StaticClass(), *PackageName).ToString();
	}

	return PackageName;
}
예제 #2
0
//* Destroys the constructed components.
void AActor::DestroyConstructedComponents()
{
	// Remove all existing components
	TInlineComponentArray<UActorComponent*> PreviouslyAttachedComponents;
	GetComponents(PreviouslyAttachedComponents);

	// We need the hierarchy to be torn down in attachment order, so do a quick sort
	PreviouslyAttachedComponents.Remove(nullptr);
	PreviouslyAttachedComponents.Sort([](UActorComponent& A, UActorComponent& B)
	{
		if (USceneComponent* BSC = Cast<USceneComponent>(&B))
		{
			if (BSC->AttachParent == &A)
			{
				return false;
			}
		}
		return true;
	});

	for (UActorComponent* Component : PreviouslyAttachedComponents)
	{
		if (Component)
		{
			bool bDestroyComponent = false;
			if (Component->IsCreatedByConstructionScript())
			{
				bDestroyComponent = true;
			}
			else
			{
				UActorComponent* OuterComponent = Component->GetTypedOuter<UActorComponent>();
				while (OuterComponent)
				{
					if (OuterComponent->IsCreatedByConstructionScript())
					{
						bDestroyComponent = true;
						break;
					}
					OuterComponent = OuterComponent->GetTypedOuter<UActorComponent>();
				}
			}

			if (bDestroyComponent)
			{
				if (Component == RootComponent)
				{
					RootComponent = NULL;
				}

				Component->DestroyComponent();

				// Rename component to avoid naming conflicts in the case where we rerun the SCS and name the new components the same way.
				FName const NewBaseName( *(FString::Printf(TEXT("TRASH_%s"), *Component->GetClass()->GetName())) );
				FName const NewObjectName = MakeUniqueObjectName(this, GetClass(), NewBaseName);
				Component->Rename(*NewObjectName.ToString(), this, REN_ForceNoResetLoaders|REN_DontCreateRedirectors|REN_NonTransactional);
			}
		}
	}
}
예제 #3
0
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;
}
	/**
	 * A helper that will take a blueprint and copy it into a new, temporary 
	 * package (intended for throwaway purposes).
	 * 
	 * @param  BlueprintToClone		The blueprint you wish to duplicate.
	 * @return A new temporary blueprint copy of what was passed in.
	 */
	static UBlueprint* DuplicateBlueprint(UBlueprint const* const BlueprintToClone)
	{
		UPackage* TempPackage = CreateTempPackage(BlueprintToClone->GetName());

		FString TempBlueprintName = MakeUniqueObjectName(TempPackage, UBlueprint::StaticClass(), BlueprintToClone->GetFName()).ToString();
		return Cast<UBlueprint>(StaticDuplicateObject(BlueprintToClone, TempPackage, *TempBlueprintName));
	}
예제 #5
0
파일: VObjec.cpp 프로젝트: xukunn1226/VRI3
VObject* VObject::StaticAllocateObject(const VClass* InClass, FName InName)
{
	if( !InClass )
	{
		debugf(TEXT("Invalid class for object %s"), InName.toString().c_str());
		return NULL;
	}

	VObject* Obj = NULL;
	if( InName == NAME_None )
	{
		InName = MakeUniqueObjectName(InClass);
	}
	else
	{
		Obj = StaticFindObject(InClass, InName);
	}

	if( Obj == NULL )
	{
		(*InClass->_ClassStaticConstructor)(&Obj);

		Obj->_Index = INDEX_NONE;
		Obj->_HashNext = NULL;
		Obj->_Name = InName;

		Obj->AddObject(INDEX_NONE);
	}

	return Obj;
}
	static void ReplaceStructWithTempDuplicate(
		UUserDefinedStruct* StructureToReinstance, 
		TSet<UBlueprint*>& BlueprintsToRecompile,
		TArray<UUserDefinedStruct*>& ChangedStructs)
	{
		if (StructureToReinstance)
		{
			UUserDefinedStruct* DuplicatedStruct = NULL;
			{
				const FString ReinstancedName = FString::Printf(TEXT("STRUCT_REINST_%s"), *StructureToReinstance->GetName());
				const FName UniqueName = MakeUniqueObjectName(GetTransientPackage(), UUserDefinedStruct::StaticClass(), FName(*ReinstancedName));

				TGuardValue<bool> IsDuplicatingClassForReinstancing(GIsDuplicatingClassForReinstancing, true);
				DuplicatedStruct = (UUserDefinedStruct*)StaticDuplicateObject(StructureToReinstance, GetTransientPackage(), *UniqueName.ToString(), ~RF_Transactional); 
			}

			DuplicatedStruct->Guid = StructureToReinstance->Guid;
			DuplicatedStruct->Bind();
			DuplicatedStruct->StaticLink(true);
			DuplicatedStruct->PrimaryStruct = StructureToReinstance;
			DuplicatedStruct->Status = EUserDefinedStructureStatus::UDSS_Duplicate;
			DuplicatedStruct->SetFlags(RF_Transient);
			DuplicatedStruct->AddToRoot();
			CastChecked<UUserDefinedStructEditorData>(DuplicatedStruct->EditorData)->RecreateDefaultInstance();

			for (auto StructProperty : TObjectRange<UStructProperty>(RF_ClassDefaultObject | RF_PendingKill))
			{
				if (StructProperty && (StructureToReinstance == StructProperty->Struct))
				{
					if (auto OwnerClass = Cast<UBlueprintGeneratedClass>(StructProperty->GetOwnerClass()))
					{
						if (UBlueprint* FoundBlueprint = Cast<UBlueprint>(OwnerClass->ClassGeneratedBy))
						{
							BlueprintsToRecompile.Add(FoundBlueprint);
							StructProperty->Struct = DuplicatedStruct;
						}
					}
					else if (auto OwnerStruct = Cast<UUserDefinedStruct>(StructProperty->GetOwnerStruct()))
					{
						check(OwnerStruct != DuplicatedStruct);
						const bool bValidStruct = (OwnerStruct->GetOutermost() != GetTransientPackage())
							&& !OwnerStruct->HasAnyFlags(RF_PendingKill)
							&& (EUserDefinedStructureStatus::UDSS_Duplicate != OwnerStruct->Status.GetValue());

						if (bValidStruct)
						{
							ChangedStructs.AddUnique(OwnerStruct);
							StructProperty->Struct = DuplicatedStruct;
						}
					}
					else
					{
						UE_LOG(LogK2Compiler, Error, TEXT("ReplaceStructWithTempDuplicate unknown owner"));
					}
				}
			}

			DuplicatedStruct->RemoveFromRoot();
		}
	}
USCS_Node* USimpleConstructionScript::CreateNodeImpl(UActorComponent* NewComponentTemplate, FName ComponentVariableName)
{
	auto NewNode = NewObject<USCS_Node>(this, MakeUniqueObjectName(this, USCS_Node::StaticClass()));
	NewNode->SetFlags(RF_Transactional);
	NewNode->ComponentTemplate = NewComponentTemplate;
	NewNode->VariableName = ComponentVariableName;

	// Note: This should match up with UEdGraphSchema_K2::VR_DefaultCategory
	NewNode->CategoryName = NSLOCTEXT("SCS", "Default", "Default");
	NewNode->VariableGuid = FGuid::NewGuid();
	return NewNode;
}
예제 #8
0
UObject* FEditorObjectTracker::GetEditorObjectForClass( UClass* EdClass )
{
	UObject *Obj = (EditorObjMap.Contains(EdClass) ? *EditorObjMap.Find(EdClass) : NULL);
	if(Obj == NULL)
	{
		FString ObjName = MakeUniqueObjectName(GetTransientPackage(), EdClass).ToString();
		ObjName += "_EdObj";
		Obj = StaticConstructObject(EdClass, GetTransientPackage(), FName(*ObjName), RF_Public|RF_Standalone|RF_Transient);
		EditorObjMap.Add(EdClass,Obj);
	}
	return Obj;
}
	/** 
	 * Helper method to unload loaded blueprints. Use with caution.
	 *
	 * @param BlueprintObj	The blueprint to unload
	 * @param bForceFlush   If true, will force garbage collection on everything but native objects (defaults to false)
	 */
	static void UnloadBlueprint(UBlueprint* const BlueprintObj, bool bForceFlush = false)
	{
		// have to grab the blueprint's package before we move it to the transient package
		UPackage* const OldPackage = Cast<UPackage>(BlueprintObj->GetOutermost());

		UPackage* const TransientPackage = GetTransientPackage();
		if (OldPackage == TransientPackage)
		{
			UE_LOG(LogBlueprintAutomationTests, Log, TEXT("No need to unload '%s' from the transient package."), *BlueprintObj->GetName());
		}
		else if (OldPackage->HasAnyFlags(RF_RootSet) || BlueprintObj->HasAnyFlags(RF_RootSet))
		{
			UE_LOG(LogBlueprintAutomationTests, Error, TEXT("Cannot unload '%s' when its root is set (it will not be garbage collected, leaving it in an erroneous state)."), *OldPackage->GetName());
		}
		else if (OldPackage->IsDirty())
		{
			UE_LOG(LogBlueprintAutomationTests, Error, TEXT("Cannot unload '%s' when it has unsaved changes (save the asset and then try again)."), *OldPackage->GetName());
		}
		else 
		{
			// prevent users from modifying an open blueprint, after it has been unloaded
			CloseBlueprint(BlueprintObj);

			UPackage* NewPackage = TransientPackage;
			// move the blueprint to the transient package (to be picked up by garbage collection later)
			FName UnloadedName = MakeUniqueObjectName(NewPackage, UBlueprint::StaticClass(), BlueprintObj->GetFName());
			BlueprintObj->Rename(*UnloadedName.ToString(), NewPackage, REN_DontCreateRedirectors|REN_DoNotDirty);

			// make sure the blueprint is properly trashed so we can rerun tests on it
			BlueprintObj->SetFlags(RF_Transient);
			BlueprintObj->ClearFlags(RF_Standalone | RF_RootSet | RF_Transactional);
			BlueprintObj->RemoveFromRoot();
			BlueprintObj->MarkPendingKill();

			InvalidatePackage(OldPackage);
		}

		// because we just emptied out an existing package, we may want to clean 
		// up garbage so an attempted load doesn't stick us with an invalid asset
		if (bForceFlush)
		{
#if WITH_EDITOR
			// clear undo history to ensure that the transaction buffer isn't 
			// holding onto any references to the blueprints we want unloaded
			GEditor->Trans->Reset(NSLOCTEXT("BpAutomation", "BpAutomationTest", "Blueprint Automation Test"));
#endif // #if WITH_EDITOR
			CollectGarbage(RF_Native);
		}
	}
예제 #10
0
bool UModel::Rename( const TCHAR* InName, UObject* NewOuter, ERenameFlags Flags )
{
#if WITH_EDITOR
	// Also rename the UPolys.
	if (NewOuter && Polys && Polys->GetOuter() == GetOuter())
	{
		if (Polys->Rename(*MakeUniqueObjectName(NewOuter, Polys->GetClass()).ToString(), NewOuter, Flags) == false)
		{
			return false;
		}
	}
#endif // WITH_EDITOR

	return Super::Rename( InName, NewOuter, Flags );
}
예제 #11
0
UWidget* FWidgetTemplateClass::CreateNamed(class UWidgetTree* Tree, FName NameOverride)
{
	if (NameOverride != NAME_None)
	{
		UObject* ExistingObject = StaticFindObject(UObject::StaticClass(), Tree, *NameOverride.ToString());
		if (ExistingObject != nullptr)
		{
			NameOverride = MakeUniqueObjectName(Tree, WidgetClass.Get(), NameOverride);
		}
	}

	UWidget* NewWidget = Tree->ConstructWidget<UWidget>(WidgetClass.Get(), NameOverride);
	NewWidget->OnCreationFromPalette();

	return NewWidget;
}
void UChildActorComponent::DestroyChildActor(const bool bRequiresRename)
{
	// If we own an Actor, kill it now
	if(ChildActor != nullptr && !GExitPurge)
	{
		// if still alive, destroy, otherwise just clear the pointer
		if (!ChildActor->IsPendingKillOrUnreachable())
		{
#if WITH_EDITOR
			if (CachedInstanceData)
			{
				delete CachedInstanceData;
				CachedInstanceData = nullptr;
			}
#else
			check(!CachedInstanceData);
#endif
			// If we're already tearing down we won't be needing this
			if (!HasAnyFlags(RF_BeginDestroyed))
			{
				CachedInstanceData = new FChildActorComponentInstanceData(this);
			}

			UWorld* World = ChildActor->GetWorld();
			// World may be nullptr during shutdown
			if(World != nullptr)
			{
				UClass* ChildClass = ChildActor->GetClass();

				// We would like to make certain that our name is not going to accidentally get taken from us while we're destroyed
				// so we increment ClassUnique beyond our index to be certain of it.  This is ... a bit hacky.
				ChildClass->ClassUnique = FMath::Max(ChildClass->ClassUnique, ChildActor->GetFName().GetNumber());

				if (bRequiresRename)
				{
					const FString ObjectBaseName = FString::Printf(TEXT("DESTROYED_%s_CHILDACTOR"), *ChildClass->GetName());
					const ERenameFlags RenameFlags = ((GetWorld()->IsGameWorld() || IsLoading()) ? REN_DoNotDirty | REN_ForceNoResetLoaders : REN_DoNotDirty);
					ChildActor->Rename(*MakeUniqueObjectName(ChildActor->GetOuter(), ChildClass, *ObjectBaseName).ToString(), nullptr, RenameFlags);
				}
				World->DestroyActor(ChildActor);
			}
		}

		ChildActor = nullptr;
	}
}
void UWidgetBlueprint::PostLoad()
{
	Super::PostLoad();

	WidgetTree->ForEachWidget([&] (UWidget* Widget) {
		Widget->ConnectEditorData();
	});

	if( GetLinkerUE4Version() < VER_UE4_FIXUP_WIDGET_ANIMATION_CLASS )
	{
		// Fixup widget animiations.
		for( auto& OldAnim : AnimationData_DEPRECATED )
		{
			FName AnimName = OldAnim.MovieScene->GetFName();

			// Rename the old movie scene so we can reuse the name
			OldAnim.MovieScene->Rename( *MakeUniqueObjectName( this, UMovieScene::StaticClass(), "MovieScene").ToString(), nullptr, REN_ForceNoResetLoaders | REN_DontCreateRedirectors | REN_DoNotDirty | REN_NonTransactional);

			UWidgetAnimation* NewAnimation = NewObject<UWidgetAnimation>(this, AnimName, RF_Transactional);

			OldAnim.MovieScene->Rename(*AnimName.ToString(), NewAnimation, REN_ForceNoResetLoaders | REN_DontCreateRedirectors | REN_DoNotDirty | REN_NonTransactional );

			NewAnimation->MovieScene = OldAnim.MovieScene;
			NewAnimation->AnimationBindings = OldAnim.AnimationBindings;
			
			Animations.Add( NewAnimation );
		}	

		AnimationData_DEPRECATED.Empty();
	}

	if ( GetLinkerUE4Version() < VER_UE4_RENAME_WIDGET_VISIBILITY )
	{
		static const FName Visiblity(TEXT("Visiblity"));
		static const FName Visibility(TEXT("Visibility"));

		for ( FDelegateEditorBinding& Binding : Bindings )
		{
			if ( Binding.PropertyName == Visiblity )
			{
				Binding.PropertyName = Visibility;
			}
		}
	}
}
void UMovieSceneShotTrack::AddNewShot(FGuid CameraHandle, UMovieScene& ShotMovieScene, const TRange<float>& TimeRange, const FText& ShotName, int32 ShotNumber )
{
	Modify();

	FName UniqueShotName = MakeUniqueObjectName( this, UMovieSceneShotSection::StaticClass(), *ShotName.ToString() );

	UMovieSceneShotSection* NewSection = NewObject<UMovieSceneShotSection>( this, UniqueShotName, RF_Transactional );
	NewSection->SetMovieScene( &ShotMovieScene );
	NewSection->SetStartTime( TimeRange.GetLowerBoundValue() );
	NewSection->SetEndTime( TimeRange.GetUpperBoundValue() );
	NewSection->SetCameraGuid( CameraHandle );
	NewSection->SetShotNameAndNumber( ShotName , ShotNumber );

	SubMovieSceneSections.Add( NewSection );
	
	// When a new shot is added, sort all shots to ensure they are in the correct order
	SortShots();
}
예제 #15
0
void ULevelSequence::PostLoad()
{
	Super::PostLoad();

#if WITH_EDITOR
	TSet<FGuid> InvalidSpawnables;

	for (int32 Index = 0; Index < MovieScene->GetSpawnableCount(); ++Index)
	{
		FMovieSceneSpawnable& Spawnable = MovieScene->GetSpawnable(Index);
		if (!Spawnable.GetObjectTemplate())
		{
			if (Spawnable.GeneratedClass_DEPRECATED && Spawnable.GeneratedClass_DEPRECATED->ClassGeneratedBy)
			{
				const FName TemplateName = MakeUniqueObjectName(MovieScene, UObject::StaticClass(), Spawnable.GeneratedClass_DEPRECATED->ClassGeneratedBy->GetFName());

				UObject* NewTemplate = NewObject<UObject>(MovieScene, Spawnable.GeneratedClass_DEPRECATED, TemplateName);
				if (NewTemplate)
				{
					Spawnable.CopyObjectTemplate(*NewTemplate, *this);
				}
			}
		}

		if (!Spawnable.GetObjectTemplate())
		{
			InvalidSpawnables.Add(Spawnable.GetGuid());
			UE_LOG(LogLevelSequence, Warning, TEXT("Discarding spawnable with ID '%s' since its generated class could not produce to a template actor"), *Spawnable.GetGuid().ToString());
		}
	}

	for (FGuid& ID : InvalidSpawnables)
	{
		MovieScene->RemoveSpawnable(ID);
	}
#endif

	if ( MovieScene->GetFixedFrameInterval() == 0 )
	{
		MovieScene->SetFixedFrameInterval( 1 / 30.0f );
	}
}
	static void CleanAndSanitizeStruct(UBlueprintGeneratedStruct* StructToClean)
	{
		check(StructToClean);

		const FString TransientString = FString::Printf(TEXT("TRASHSTRUCT_%s"), *StructToClean->GetName());
		const FName TransientName = MakeUniqueObjectName(GetTransientPackage(), UBlueprintGeneratedStruct::StaticClass(), FName(*TransientString));
		UBlueprintGeneratedStruct* TransientStruct = NewNamedObject<UBlueprintGeneratedStruct>(GetTransientPackage(), TransientName, RF_Public|RF_Transient);

		const bool bRecompilingOnLoad = StructToClean->StructGeneratedBy ? StructToClean->StructGeneratedBy->bIsRegeneratingOnLoad : false;
		const ERenameFlags RenFlags = REN_DontCreateRedirectors | (bRecompilingOnLoad ? REN_ForceNoResetLoaders : 0);

		TArray<UObject*> SubObjects;
		GetObjectsWithOuter(StructToClean, SubObjects, true);
		for( auto SubObjIt = SubObjects.CreateIterator(); SubObjIt; ++SubObjIt )
		{
			UObject* CurrSubObj = *SubObjIt;
			CurrSubObj->Rename(NULL, TransientStruct, RenFlags);
			if( UProperty* Prop = Cast<UProperty>(CurrSubObj) )
			{
				FKismetCompilerUtilities::InvalidatePropertyExport(Prop);
			}
			else
			{
				ULinkerLoad::InvalidateExport(CurrSubObj);
			}
		}

		if(!bRecompilingOnLoad)
		{
			StructToClean->RemoveMetaData(TEXT("BlueprintType"));
		}

		StructToClean->SetSuperStruct(NULL);
		StructToClean->Children = NULL;
		StructToClean->Script.Empty();
		StructToClean->MinAlignment = 0;
		StructToClean->RefLink = NULL;
		StructToClean->PropertyLink = NULL;
		StructToClean->DestructorLink = NULL;
		StructToClean->ScriptObjectReferences.Empty();
		StructToClean->PropertyLink = NULL;
	}
	static void CleanAndSanitizeStruct(UUserDefinedStruct* StructToClean)
	{
		check(StructToClean);

		if (auto EditorData = Cast<UUserDefinedStructEditorData>(StructToClean->EditorData))
		{
			EditorData->CleanDefaultInstance();
		}

		const FString TransientString = FString::Printf(TEXT("TRASHSTRUCT_%s"), *StructToClean->GetName());
		const FName TransientName = MakeUniqueObjectName(GetTransientPackage(), UUserDefinedStruct::StaticClass(), FName(*TransientString));
		UUserDefinedStruct* TransientStruct = NewObject<UUserDefinedStruct>(GetTransientPackage(), TransientName, RF_Public | RF_Transient);

		TArray<UObject*> SubObjects;
		GetObjectsWithOuter(StructToClean, SubObjects, true);
		SubObjects.Remove(StructToClean->EditorData);
		for( auto SubObjIt = SubObjects.CreateIterator(); SubObjIt; ++SubObjIt )
		{
			UObject* CurrSubObj = *SubObjIt;
			CurrSubObj->Rename(NULL, TransientStruct, REN_DontCreateRedirectors);
			if( UProperty* Prop = Cast<UProperty>(CurrSubObj) )
			{
				FKismetCompilerUtilities::InvalidatePropertyExport(Prop);
			}
			else
			{
				FLinkerLoad::InvalidateExport(CurrSubObj);
			}
		}

		StructToClean->SetSuperStruct(NULL);
		StructToClean->Children = NULL;
		StructToClean->Script.Empty();
		StructToClean->MinAlignment = 0;
		StructToClean->RefLink = NULL;
		StructToClean->PropertyLink = NULL;
		StructToClean->DestructorLink = NULL;
		StructToClean->ScriptObjectReferences.Empty();
		StructToClean->PropertyLink = NULL;
		StructToClean->ErrorMessage.Empty();
	}
예제 #18
0
FString FMeshProxyTool::GetDefaultPackageName() const
{
	FString PackageName;

	USelection* SelectedActors = GEditor->GetSelectedActors();

	// Iterate through selected actors and find first static mesh asset
	// Use this static mesh path as destination package name for a merged mesh
	for (FSelectionIterator Iter(*SelectedActors); Iter; ++Iter)
	{
		AActor* Actor = Cast<AActor>(*Iter);
		if (Actor)
		{
			TInlineComponentArray<UStaticMeshComponent*> SMComponets;
			Actor->GetComponents<UStaticMeshComponent>(SMComponets);
			for (UStaticMeshComponent* Component : SMComponets)
			{
				if (Component->StaticMesh)
				{
					PackageName = FPackageName::GetLongPackagePath(Component->StaticMesh->GetOutermost()->GetName());
					PackageName += FString(TEXT("/PROXY_")) + Component->StaticMesh->GetName();
					break;
				}
			}
		}

		if (!PackageName.IsEmpty())
		{
			break;
		}
	}

	if (PackageName.IsEmpty())
	{
		PackageName = FPackageName::FilenameToLongPackageName(FPaths::GameContentDir() + TEXT("PROXY"));
		PackageName = MakeUniqueObjectName(NULL, UPackage::StaticClass(), *PackageName).ToString();
	}

	return PackageName;
}
예제 #19
0
void USceneCapturer::InitCaptureComponent( USceneCaptureComponent2D* CaptureComponent, float HFov, float VFov, EStereoscopicPass InStereoPass )
{
	CaptureComponent->SetVisibility( true );
	CaptureComponent->SetHiddenInGame( false );

    CaptureComponent->CaptureStereoPass = InStereoPass;
    CaptureComponent->FOVAngle = FMath::Max( HFov, VFov );
    CaptureComponent->bCaptureEveryFrame = false;
    CaptureComponent->CaptureSource = ESceneCaptureSource::SCS_FinalColorLDR;

	const FName TargetName = MakeUniqueObjectName(this, UTextureRenderTarget2D::StaticClass(), TEXT("SceneCaptureTextureTarget"));
    CaptureComponent->TextureTarget = NewObject<UTextureRenderTarget2D>(this, TargetName);
    //TODO: ikrimae: Not sure why the render target needs to be float to avoid banding. Seems like captures to this RT and then applies PP
    //               on top of it which causes degredation.
    CaptureComponent->TextureTarget->InitCustomFormat(CaptureWidth, CaptureHeight, PF_A16B16G16R16, false);
	CaptureComponent->TextureTarget->ClearColor = FLinearColor::Red;

	CaptureComponent->RegisterComponentWithWorld( GWorld );

	// UE4 cannot serialize an array of subobject pointers, so add these objects to the root
	CaptureComponent->AddToRoot();
}
예제 #20
0
void UMovieSceneShotTrack::AddNewShot(FGuid CameraHandle, UMovieSceneSequence& ShotMovieSceneSequence, float StartTime, const FText& ShotName, int32 ShotNumber )
{
	Modify();

	FName UniqueShotName = MakeUniqueObjectName( this, UMovieSceneShotSection::StaticClass(), *ShotName.ToString() );

	UMovieSceneShotSection* NewSection = NewObject<UMovieSceneShotSection>( this, UniqueShotName, RF_Transactional );
	NewSection->SetMovieSceneAnimation( &ShotMovieSceneSequence );
	NewSection->SetStartTime( StartTime );
	NewSection->SetEndTime( FindEndTimeForShot( StartTime ) );
	NewSection->SetCameraGuid( CameraHandle );
	NewSection->SetShotNameAndNumber( ShotName , ShotNumber );

	SubMovieSceneSections.Add( NewSection );

	// When a new shot is added, sort all shots to ensure they are in the correct order
	SortShots();



	// Once shots are sorted fixup the surrounding shots to fix any gaps
	FixupSurroundingShots( *NewSection, false );
}
예제 #21
0
void UChildActorComponent::DestroyChildActor()
{
    // If we own an Actor, kill it now
    if(ChildActor != nullptr && !GExitPurge)
    {
        // if still alive, destroy, otherwise just clear the pointer
        if(!ChildActor->IsPendingKill())
        {
#if WITH_EDITOR
            if (CachedInstanceData)
            {
                delete CachedInstanceData;
            }
#else
            check(!CachedInstanceData);
#endif
            CachedInstanceData = new FChildActorComponentInstanceData(this);

            UWorld* World = ChildActor->GetWorld();
            // World may be nullptr during shutdown
            if(World != nullptr)
            {
                UClass* ChildClass = ChildActor->GetClass();

                // We would like to make certain that our name is not going to accidentally get taken from us while we're destroyed
                // so we increment ClassUnique beyond our index to be certain of it.  This is ... a bit hacky.
                ChildClass->ClassUnique = FMath::Max(ChildClass->ClassUnique, ChildActor->GetFName().GetNumber());

                const FString ObjectBaseName = FString::Printf(TEXT("DESTROYED_%s_CHILDACTOR"), *ChildClass->GetName());
                ChildActor->Rename(*MakeUniqueObjectName(ChildActor->GetOuter(), ChildClass, *ObjectBaseName).ToString(), nullptr, REN_DoNotDirty);
                World->DestroyActor(ChildActor);
            }
        }

        ChildActor = nullptr;
    }
}
예제 #22
0
//* Destroys the constructed components.
void AActor::DestroyConstructedComponents()
{
	// Remove all existing components
	TArray<UActorComponent*> PreviouslyAttachedComponents;
	GetComponents(PreviouslyAttachedComponents);
	for (int32 i = 0; i < PreviouslyAttachedComponents.Num(); i++)
	{
		UActorComponent*& Component = PreviouslyAttachedComponents[i];
		if (Component && Component->bCreatedByConstructionScript)
		{
			if (Component == RootComponent)
			{
				RootComponent = NULL;
			}

			Component->DestroyComponent();

			// Rename component to avoid naming conflicts in the case where we rerun the SCS and name the new components the same way.
			FName const NewBaseName( *(FString::Printf(TEXT("TRASH_%s"), *Component->GetClass()->GetName())) );
			FName const NewObjectName = MakeUniqueObjectName(this, GetClass(), NewBaseName);
			Component->Rename(*NewObjectName.ToString(), this, REN_ForceNoResetLoaders);
		}
	}
}
	static void ReplaceStructWithTempDuplicate(
		UBlueprintGeneratedStruct* StructureToReinstance, 
		TSet<UBlueprint*>& BlueprintsToRecompile,
		TArray<UBlueprintGeneratedStruct*>& ChangedStructs)
	{
		if (StructureToReinstance)
		{
			UBlueprintGeneratedStruct* DuplicatedStruct = NULL;
			{
				const FString ReinstancedName = FString::Printf(TEXT("STRUCT_REINST_%s"), *StructureToReinstance->GetName());
				const FName UniqueName = MakeUniqueObjectName(GetTransientPackage(), UBlueprintGeneratedStruct::StaticClass(), FName(*ReinstancedName));

				const bool OldIsDuplicatingClassForReinstancing = GIsDuplicatingClassForReinstancing;
				GIsDuplicatingClassForReinstancing = true;
				DuplicatedStruct = (UBlueprintGeneratedStruct*)StaticDuplicateObject(StructureToReinstance, GetTransientPackage(), *UniqueName.ToString(), ~RF_Transactional); 
				GIsDuplicatingClassForReinstancing = OldIsDuplicatingClassForReinstancing;
			}
			DuplicatedStruct->Status = EBlueprintStructureStatus::BSS_Duplicate;
			DuplicatedStruct->SetFlags(RF_Transient);
			DuplicatedStruct->AddToRoot();

			for (TObjectIterator<UStructProperty> PropertyIter(RF_ClassDefaultObject|RF_PendingKill); PropertyIter; ++PropertyIter)
			{
				UStructProperty* StructProperty = *PropertyIter;
				if (StructProperty && (StructureToReinstance == StructProperty->Struct))
				{
					UBlueprint* FoundBlueprint = NULL;
					if (auto OwnerClass = Cast<UBlueprintGeneratedClass>(StructProperty->GetOwnerClass()))
					{
						FoundBlueprint = Cast<UBlueprint>(OwnerClass->ClassGeneratedBy);
					}
					else if (auto OwnerStruct = Cast<UBlueprintGeneratedStruct>(StructProperty->GetOwnerStruct()))
					{
						check(OwnerStruct != DuplicatedStruct);
						const bool bValidStruct = (OwnerStruct->GetOutermost() != GetTransientPackage())
							&& !OwnerStruct->HasAnyFlags(RF_PendingKill)
							&& (EBlueprintStructureStatus::BSS_Duplicate != OwnerStruct->Status.GetValue());

						if (bValidStruct)
						{
							FoundBlueprint = OwnerStruct->StructGeneratedBy;
							ChangedStructs.AddUnique(OwnerStruct);
						}
						
					}
					else
					{
						UE_LOG(LogK2Compiler, Warning, TEXT("ReplaceStructWithTempDuplicate unknown owner"));
					}

					if (NULL != FoundBlueprint)
					{
						StructProperty->Struct = DuplicatedStruct;
						BlueprintsToRecompile.Add(FoundBlueprint);
					}
				}
			}

			DuplicatedStruct->RemoveFromRoot();
		}
	}
예제 #24
0
void AActor::SetActorLabelInternal( const FString& NewActorLabelDirty, bool bMakeGloballyUniqueFName, bool bMarkDirty )
{
	// Clean up the incoming string a bit
	FString NewActorLabel = NewActorLabelDirty;
	NewActorLabel.Trim();
	NewActorLabel.TrimTrailing();


	// First, update the actor label
	{
		// Has anything changed?
		if( FCString::Strcmp( *NewActorLabel, *GetActorLabel() ) != 0 )
		{
			// Store new label
			Modify( bMarkDirty );
			ActorLabel = NewActorLabel;
		}
	}


	// Next, update the actor's name
	{
		// Generate an object name for the actor's label
		const FName OldActorName = GetFName();
		FName NewActorName = MakeObjectNameFromDisplayLabel( GetActorLabel(), OldActorName );

		// Has anything changed?
		if( OldActorName != NewActorName )
		{
			// Try to rename the object
			UObject* NewOuter = NULL;		// Outer won't be changing
			ERenameFlags RenFlags = bMakeGloballyUniqueFName ? (REN_DontCreateRedirectors | REN_ForceGlobalUnique) : REN_DontCreateRedirectors;
			bool bCanRename = Rename( *NewActorName.ToString(), NewOuter, REN_Test | REN_DoNotDirty | REN_NonTransactional | RenFlags );
			if( bCanRename )
			{
				// NOTE: Will assert internally if rename fails
				const bool bWasRenamed = Rename( *NewActorName.ToString(), NewOuter, RenFlags );
			}
			else
			{
				// Unable to rename the object.  Use a unique object name variant.
				NewActorName = MakeUniqueObjectName( bMakeGloballyUniqueFName ? ANY_PACKAGE : GetOuter(), GetClass(), NewActorName );

				bCanRename = Rename( *NewActorName.ToString(), NewOuter, REN_Test | REN_DoNotDirty | REN_NonTransactional | RenFlags );
				if( bCanRename )
				{
					// NOTE: Will assert internally if rename fails
					const bool bWasRenamed = Rename( *NewActorName.ToString(), NewOuter, RenFlags );
				}
				else
				{
					// Unable to rename the object.  Oh well, not a big deal.
				}
			}
		}
	}

	FPropertyChangedEvent PropertyEvent( FindField<UProperty>( AActor::StaticClass(), "ActorLabel" ) );
	PostEditChangeProperty(PropertyEvent);

	FCoreDelegates::OnActorLabelChanged.Broadcast(this);
}
예제 #25
0
void FHotReloadClassReinstancer::RecreateCDOAndSetupOldClassReinstancing(UClass* InOldClass)
{
	// Set base class members to valid values
	ClassToReinstance = InOldClass;
	DuplicatedClass = InOldClass;
	OriginalCDO = InOldClass->GetDefaultObject();
	bHasReinstanced = false;
	bSkipGarbageCollection = false;
	bNeedsReinstancing = false;
	NewClass = InOldClass; // The class doesn't change in this case

	// Collect the original property values
	SerializeCDOProperties(InOldClass->GetDefaultObject(), OriginalCDOProperties);

	// Remember all the basic info about the object before we rename it
	EObjectFlags CDOFlags = OriginalCDO->GetFlags();
	UObject* CDOOuter = OriginalCDO->GetOuter();
	FName CDOName = OriginalCDO->GetFName();

	// Rename original CDO, so we can store this one as OverridenArchetypeForCDO
	// and create new one with the same name and outer.
	OriginalCDO->Rename(
		*MakeUniqueObjectName(
			GetTransientPackage(),
			OriginalCDO->GetClass(),
			*FString::Printf(TEXT("BPGC_ARCH_FOR_CDO_%s"), *InOldClass->GetName())
		).ToString(),
		GetTransientPackage(),
		REN_DoNotDirty | REN_DontCreateRedirectors | REN_NonTransactional | REN_SkipGeneratedClasses | REN_ForceNoResetLoaders);
	
	// Re-create the CDO, re-running its constructor
	ReconstructClassDefaultObject(InOldClass, CDOOuter, CDOName, CDOFlags);

	ReconstructedCDOsMap.Add(OriginalCDO, InOldClass->GetDefaultObject());

	// Collect the property values after re-constructing the CDO
	SerializeCDOProperties(InOldClass->GetDefaultObject(), ReconstructedCDOProperties);

	// We only want to re-instance the old class if its CDO's values have changed or any of its DSOs' property values have changed
	if (DefaultPropertiesHaveChanged())
	{
		bNeedsReinstancing = true;
		SaveClassFieldMapping(InOldClass);

		TArray<UClass*> ChildrenOfClass;
		GetDerivedClasses(InOldClass, ChildrenOfClass);
		for (auto ClassIt = ChildrenOfClass.CreateConstIterator(); ClassIt; ++ClassIt)
		{
			UClass* ChildClass = *ClassIt;
			UBlueprint* ChildBP = Cast<UBlueprint>(ChildClass->ClassGeneratedBy);
			if (ChildBP && !ChildBP->HasAnyFlags(RF_BeingRegenerated))
			{
				if (!ChildBP->HasAnyFlags(RF_NeedLoad))
				{
					Children.AddUnique(ChildBP);
					auto BPGC = Cast<UBlueprintGeneratedClass>(ChildBP->GeneratedClass);
					auto CurrentCDO = BPGC ? BPGC->GetDefaultObject(false) : nullptr;
					if (CurrentCDO && (OriginalCDO == CurrentCDO->GetArchetype()))
					{
						BPGC->OverridenArchetypeForCDO = OriginalCDO;
					}
				}
			}
		}
	}
}
예제 #26
0
파일: Sequencer.cpp 프로젝트: johndpope/UE4
FGuid FSequencer::AddSpawnableForAssetOrClass( UObject* Object, UObject* CounterpartGamePreviewObject )
{
	FGuid NewSpawnableGuid;
	
	if( ObjectBindingManager->AllowsSpawnableObjects() )
	{
		// Grab the MovieScene that is currently focused.  We'll add our Blueprint as an inner of the
		// MovieScene asset.
		UMovieScene* OwnerMovieScene = GetFocusedMovieScene();

		// @todo sequencer: Undo doesn't seem to be working at all
		const FScopedTransaction Transaction( LOCTEXT("UndoAddingObject", "Add Object to MovieScene") );

		// Use the class as the spawnable's name if this is an actor class, otherwise just use the object name (asset)
		const bool bIsActorClass = Object->IsA( AActor::StaticClass() ) && !Object->HasAnyFlags( RF_ArchetypeObject );
		const FName AssetName = bIsActorClass ? Object->GetClass()->GetFName() : Object->GetFName();

		// Inner objects don't need a name (it will be auto-generated by the UObject system), but we want one in this case
		// because the class of any actors that are created from this Blueprint may end up being user-facing.
		const FName BlueprintName = MakeUniqueObjectName( OwnerMovieScene, UBlueprint::StaticClass(), AssetName );

		// Use the asset name as the initial spawnable name
		const FString NewSpawnableName = AssetName.ToString();		// @todo sequencer: Need UI to allow user to rename these slots

		// Create our new blueprint!
		UBlueprint* NewBlueprint = NULL;
		{
			// @todo sequencer: Add support for forcing specific factories for an asset
			UActorFactory* FactoryToUse = NULL;
			if( bIsActorClass )
			{
				// Placing an actor class directly::
				FactoryToUse = GEditor->FindActorFactoryForActorClass( Object->GetClass() );
			}
			else
			{
				// Placing an asset
				FactoryToUse = FActorFactoryAssetProxy::GetFactoryForAssetObject( Object );
			}

			if( FactoryToUse != NULL )
			{
				// Create the blueprint
				NewBlueprint = FactoryToUse->CreateBlueprint( Object, OwnerMovieScene, BlueprintName );
			}
			else if( bIsActorClass )
			{
				// We don't have a factory, but we can still try to create a blueprint for this actor class
				NewBlueprint = FKismetEditorUtilities::CreateBlueprint( Object->GetClass(), OwnerMovieScene, BlueprintName, EBlueprintType::BPTYPE_Normal, UBlueprint::StaticClass(), UBlueprintGeneratedClass::StaticClass() );
			}
		}

		if( ensure( NewBlueprint != NULL ) )
		{
			if( NewBlueprint->GeneratedClass != NULL && FBlueprintEditorUtils::IsActorBased( NewBlueprint ) )
			{
				AActor* ActorCDO = CastChecked< AActor >( NewBlueprint->GeneratedClass->ClassDefaultObject );

				// If we have a counterpart object, then copy the properties from that object back into our blueprint's CDO
				// @todo sequencer livecapture: This isn't really good enough to handle complex actors.  The dynamically-spawned actor could have components that
				// were created in its construction script or via straight-up C++ code.  Instead what we should probably do is duplicate the PIE actor and generate
				// our CDO from that duplicate.  It could get pretty complex though.
				if( CounterpartGamePreviewObject != NULL )
				{
					AActor* CounterpartGamePreviewActor = CastChecked< AActor >( CounterpartGamePreviewObject );
					CopyActorProperties( CounterpartGamePreviewActor, ActorCDO );
				}
				else
				{
					// Place the new spawnable in front of the camera (unless we were automatically created from a PIE actor)
					PlaceActorInFrontOfCamera( ActorCDO );
				}
			}

			NewSpawnableGuid = OwnerMovieScene->AddSpawnable( NewSpawnableName, NewBlueprint, CounterpartGamePreviewObject );

			if (IsShotFilteringOn())
			{
				AddUnfilterableObject(NewSpawnableGuid);
			}
		}
	
	}

	return NewSpawnableGuid;
}
예제 #27
0
FBlueprintCompileReinstancer::FBlueprintCompileReinstancer(UClass* InClassToReinstance, bool bIsBytecodeOnly, bool bSkipGC)
	: ClassToReinstance(InClassToReinstance)
	, DuplicatedClass(NULL)
	, OriginalCDO(NULL)
	, bHasReinstanced(false)
	, bSkipGarbageCollection(bSkipGC)
	, ClassToReinstanceDefaultValuesCRC(0)
{
	if( InClassToReinstance != NULL )
	{
		bIsReinstancingSkeleton = FKismetEditorUtilities::IsClassABlueprintSkeleton(ClassToReinstance);

		SaveClassFieldMapping(InClassToReinstance);

		// Remember the initial CDO for the class being resinstanced
		OriginalCDO = ClassToReinstance->GetDefaultObject();

		// Duplicate the class we're reinstancing into the transient package.  We'll re-class all objects we find to point to this new class
		GIsDuplicatingClassForReinstancing = true;
		ClassToReinstance->ClassFlags |= CLASS_NewerVersionExists;
		const FName RenistanceName = MakeUniqueObjectName(GetTransientPackage(), ClassToReinstance->GetClass(), *FString::Printf(TEXT("REINST_%s"), *ClassToReinstance->GetName()));
		DuplicatedClass = (UClass*)StaticDuplicateObject(ClassToReinstance, GetTransientPackage(), *RenistanceName.ToString(), ~RF_Transactional); 

		ClassToReinstance->ClassFlags &= ~CLASS_NewerVersionExists;
		GIsDuplicatingClassForReinstancing = false;

		auto BPGDuplicatedClass = Cast<UBlueprintGeneratedClass>(DuplicatedClass);
		auto DuplicatedClassUberGraphFunction = BPGDuplicatedClass ? BPGDuplicatedClass->UberGraphFunction : nullptr;
		if (DuplicatedClassUberGraphFunction)
		{
			DuplicatedClassUberGraphFunction->Bind();
			DuplicatedClassUberGraphFunction->StaticLink(true);
		}

		// Bind and link the duplicate class, so that it has the proper duplicate property offsets
		DuplicatedClass->Bind();
		DuplicatedClass->StaticLink(true);

		// Copy over the ComponentNametoDefaultObjectMap, which tells CopyPropertiesForUnrelatedObjects which components are instanced and which aren't

		GIsDuplicatingClassForReinstancing = true;
		UObject* OldCDO = ClassToReinstance->GetDefaultObject();
		DuplicatedClass->ClassDefaultObject = (UObject*)StaticDuplicateObject(OldCDO, GetTransientPackage(), *DuplicatedClass->GetDefaultObjectName().ToString());
		GIsDuplicatingClassForReinstancing = false;

		DuplicatedClass->ClassDefaultObject->SetFlags(RF_ClassDefaultObject);
		DuplicatedClass->ClassDefaultObject->SetClass(DuplicatedClass);

		OldCDO->SetClass(DuplicatedClass);
		ObjectsThatShouldUseOldStuff.Add(DuplicatedClass); //CDO of REINST_ class can be used as archetype

		if( !bIsBytecodeOnly )
		{
			TArray<UObject*> ObjectsToChange;
			const bool bIncludeDerivedClasses = false;
			GetObjectsOfClass(ClassToReinstance, ObjectsToChange, bIncludeDerivedClasses);
			for (auto ObjIt = ObjectsToChange.CreateConstIterator(); ObjIt; ++ObjIt)
			{
				(*ObjIt)->SetClass(DuplicatedClass);
			}

			TArray<UClass*> ChildrenOfClass;
			GetDerivedClasses(ClassToReinstance, ChildrenOfClass);
			for ( auto ClassIt = ChildrenOfClass.CreateConstIterator(); ClassIt; ++ClassIt )
			{
				UClass* ChildClass = *ClassIt;
				UBlueprint* ChildBP = Cast<UBlueprint>(ChildClass->ClassGeneratedBy);
				if (ChildBP)
				{
					const bool bClassIsDirectlyGeneratedByTheBlueprint = (ChildBP->GeneratedClass == ChildClass)
						|| (ChildBP->SkeletonGeneratedClass == ChildClass);

					if (ChildBP->HasAnyFlags(RF_BeingRegenerated) || !bClassIsDirectlyGeneratedByTheBlueprint)
					{
						if (ChildClass->GetSuperClass() == ClassToReinstance)
						{
							ReparentChild(ChildClass);
						}

						//TODO: some stronger condition would be nice
						if (!bClassIsDirectlyGeneratedByTheBlueprint)
						{
							ObjectsThatShouldUseOldStuff.Add(ChildClass);
						}
					}
					// If this is a direct child, change the parent and relink so the property chain is valid for reinstancing
					else if( !ChildBP->HasAnyFlags(RF_NeedLoad) )
					{
						if( ChildClass->GetSuperClass() == ClassToReinstance )
						{
							ReparentChild(ChildBP);
						}

						Children.AddUnique(ChildBP);
					}
					else
					{
						// If this is a child that caused the load of their parent, relink to the REINST class so that we can still serialize in the CDO, but do not add to later processing
						ReparentChild(ChildClass);
					}
				}
			}
		}

		// Pull the blueprint that generated this reinstance target, and gather the blueprints that are dependent on it
		UBlueprint* GeneratingBP = Cast<UBlueprint>(ClassToReinstance->ClassGeneratedBy);
		check(GeneratingBP || GIsAutomationTesting);
		if(GeneratingBP)
		{
			ClassToReinstanceDefaultValuesCRC = GeneratingBP->CrcPreviousCompiledCDO;
			FBlueprintEditorUtils::GetDependentBlueprints(GeneratingBP, Dependencies);
		}
	}
}
예제 #28
0
void FAmbientSoundDetails::CreateNewSoundCue( ESoundCueLayouts Layout )
{

	if( AmbientSound.IsValid() )
	{
		OnStopSoundClicked();

		AAmbientSound* AS = CastChecked<AAmbientSound>(AmbientSound.Get());

		// First if the existing SoundCue is a child of the AmbientSound rename it off to oblivion so we can have a good name
		USoundCue* SoundCue = Cast<USoundCue>(AmbientSound->GetAudioComponent()->Sound);
		if (SoundCue && SoundCue->GetOuter() == AS)
		{
			SoundCue->Rename(*MakeUniqueObjectName( GetTransientPackage(), USoundCue::StaticClass() ).ToString(), GetTransientPackage(), REN_DontCreateRedirectors);
		}

		int32 NodeColumn = 0;
		USoundNode* PrevNode = NULL;

		SoundCue = NewObject<USoundCue>(AS, FName(*AS->GetInternalSoundCueName()));
		AS->GetAudioComponent()->Sound = SoundCue;
		AS->GetAudioComponent()->PostEditChange();

		if (Layout == SOUNDCUE_LAYOUT_RANDOM_LOOP || Layout == SOUNDCUE_LAYOUT_RANDOM_LOOP_WITH_DELAY)
		{
			USoundNodeLooping* LoopingNode = SoundCue->ConstructSoundNode<USoundNodeLooping>();
			LoopingNode->CreateStartingConnectors();
			LoopingNode->PlaceNode(NodeColumn++, 0, 1);
			
			if (!PrevNode)
			{
				SoundCue->FirstNode = LoopingNode;
			}
			else
			{
				check(PrevNode->ChildNodes.Num() > 0);
				PrevNode->ChildNodes[0] = LoopingNode;
			}
			PrevNode = LoopingNode;

			if (Layout == SOUNDCUE_LAYOUT_RANDOM_LOOP_WITH_DELAY)
			{
				USoundNodeDelay* DelayNode = SoundCue->ConstructSoundNode<USoundNodeDelay>();
				DelayNode->CreateStartingConnectors();
				DelayNode->PlaceNode(NodeColumn++,0,1);

				if (!PrevNode)
				{
					SoundCue->FirstNode = DelayNode;
				}
				else
				{
					check(PrevNode->ChildNodes.Num() > 0);
					PrevNode->ChildNodes[0] = DelayNode;
				}
				PrevNode = DelayNode;
			}

			USoundNodeRandom* RandomNode = SoundCue->ConstructSoundNode<USoundNodeRandom>();
			RandomNode->CreateStartingConnectors();
			RandomNode->PlaceNode(NodeColumn++,0,1);

			if (!PrevNode)
			{
				SoundCue->FirstNode = RandomNode;
			}
			else
			{
				check(PrevNode->ChildNodes.Num() > 0);
				PrevNode->ChildNodes[0] = RandomNode;
			}
			PrevNode = RandomNode;
		}
		else if (Layout == SOUNDCUE_LAYOUT_MIXER)
		{
			USoundNodeMixer* MixerNode = SoundCue->ConstructSoundNode<USoundNodeMixer>();
			MixerNode->CreateStartingConnectors();
			MixerNode->PlaceNode(NodeColumn++,0,1);

			if (!PrevNode)
			{
				SoundCue->FirstNode = MixerNode;
			}
			else
			{
				check(PrevNode->ChildNodes.Num() > 0);
				PrevNode->ChildNodes[0] = MixerNode;
			}
			PrevNode = MixerNode;
		}

		if (PrevNode)
		{
			const int32 ChildCount = PrevNode->ChildNodes.Num();
			for (int32 ChildIndex = 0; ChildIndex < ChildCount; ++ChildIndex)
			{
				USoundNodeWavePlayer* PlayerNode = SoundCue->ConstructSoundNode<USoundNodeWavePlayer>();
				PlayerNode->PlaceNode(NodeColumn,ChildIndex,ChildCount);

				if (Layout == SOUNDCUE_LAYOUT_MIXER)
				{
					PlayerNode->bLooping = true;
				}

				PrevNode->ChildNodes[ChildIndex] = PlayerNode;
			}
		}

		SoundCue->LinkGraphNodesFromSoundNodes();

		FAssetEditorManager::Get().OpenEditorForAsset(SoundCue);
	}
}
void UChildActorComponent::DestroyChildActor()
{
	// If we own an Actor, kill it now unless we don't have authority on it, for that we rely on the server
	// If the level that the child actor is being removed then don't destory the child actor so re-adding it doesn't
	// need to create a new actor
	if (ChildActor && ChildActor->HasAuthority() && !GetOwner()->GetLevel()->bIsBeingRemoved)
	{
		if (!GExitPurge)
		{
			// if still alive, destroy, otherwise just clear the pointer
			if (!ChildActor->IsPendingKillOrUnreachable())
			{
#if WITH_EDITOR
				if (CachedInstanceData)
				{
					delete CachedInstanceData;
					CachedInstanceData = nullptr;
				}
#else
				check(!CachedInstanceData);
#endif
				// If we're already tearing down we won't be needing this
				if (!HasAnyFlags(RF_BeginDestroyed) && !IsUnreachable())
				{
					CachedInstanceData = new FChildActorComponentInstanceData(this);
				}

				UWorld* World = ChildActor->GetWorld();
				// World may be nullptr during shutdown
				if (World != nullptr)
				{
					UClass* ChildClass = ChildActor->GetClass();

					// We would like to make certain that our name is not going to accidentally get taken from us while we're destroyed
					// so we increment ClassUnique beyond our index to be certain of it.  This is ... a bit hacky.
					int32& ClassUnique = ChildActor->GetOutermost()->ClassUniqueNameIndexMap.FindOrAdd(ChildClass->GetFName());
					ClassUnique = FMath::Max(ClassUnique, ChildActor->GetFName().GetNumber());

					// If we are getting here due to garbage collection we can't rename, so we'll have to abandon this child actor name and pick up a new one
					if (!IsGarbageCollecting())
					{
						const FString ObjectBaseName = FString::Printf(TEXT("DESTROYED_%s_CHILDACTOR"), *ChildClass->GetName());
						const ERenameFlags RenameFlags = ((GetWorld()->IsGameWorld() || IsLoading()) ? REN_DoNotDirty | REN_ForceNoResetLoaders : REN_DoNotDirty);
						ChildActor->Rename(*MakeUniqueObjectName(ChildActor->GetOuter(), ChildClass, *ObjectBaseName).ToString(), nullptr, RenameFlags);
					}
					else
					{
						ChildActorName = NAME_None;
						if (CachedInstanceData)
						{
							CachedInstanceData->ChildActorName = NAME_None;
						}
					}
					World->DestroyActor(ChildActor);
				}
			}
		}

		ChildActor = nullptr;
	}
}
예제 #30
0
AActor* UWorld::SpawnActor( UClass* Class, FTransform const* Transform, const FActorSpawnParameters& SpawnParameters )
{
	SCOPE_CYCLE_COUNTER(STAT_SpawnActorTime);
	check( CurrentLevel ); 	
	check(GIsEditor || (CurrentLevel == PersistentLevel));

	// Make sure this class is spawnable.
	if( !Class )
	{
		UE_LOG(LogSpawn, Warning, TEXT("SpawnActor failed because no class was specified") );
		return NULL;
	}
	if( Class->HasAnyClassFlags(CLASS_Deprecated) )
	{
		UE_LOG(LogSpawn, Warning, TEXT("SpawnActor failed because class %s is deprecated"), *Class->GetName() );
		return NULL;
	}
	if( Class->HasAnyClassFlags(CLASS_Abstract) )
	{
		UE_LOG(LogSpawn, Warning, TEXT("SpawnActor failed because class %s is abstract"), *Class->GetName() );
		return NULL;
	}
	else if( !Class->IsChildOf(AActor::StaticClass()) )
	{
		UE_LOG(LogSpawn, Warning, TEXT("SpawnActor failed because %s is not an actor class"), *Class->GetName() );
		return NULL;
	}
	else if (SpawnParameters.Template != NULL && SpawnParameters.Template->GetClass() != Class)
	{
		UE_LOG(LogSpawn, Warning, TEXT("SpawnActor failed because template class (%s) does not match spawn class (%s)"), *SpawnParameters.Template->GetClass()->GetName(), *Class->GetName());
		if (!SpawnParameters.bNoFail)
		{
			return NULL;
		}
	}
	else if (bIsRunningConstructionScript && !SpawnParameters.bAllowDuringConstructionScript)
	{
		UE_LOG(LogSpawn, Warning, TEXT("SpawnActor failed because we are running a ConstructionScript (%s)"), *Class->GetName() );
		return NULL;
	}
	else if (bIsTearingDown)
	{
		UE_LOG(LogSpawn, Warning, TEXT("SpawnActor failed because we are in the process of tearing down the world"));
		return NULL;
	}
	else if (Transform && Transform->ContainsNaN())
	{
		UE_LOG(LogSpawn, Warning, TEXT("SpawnActor failed because the given transform (%s) is invalid"), *Transform->ToString());
		return NULL;
	}

	ULevel* LevelToSpawnIn = SpawnParameters.OverrideLevel;
	if (LevelToSpawnIn == NULL)
	{
		// Spawn in the same level as the owner if we have one. @warning: this relies on the outer of an actor being the level.
		LevelToSpawnIn = (SpawnParameters.Owner != NULL) ? CastChecked<ULevel>(SpawnParameters.Owner->GetOuter()) : CurrentLevel;
	}

	FName NewActorName = SpawnParameters.Name;
	AActor* Template = SpawnParameters.Template;
	// Use class's default actor as a template.
	if( !Template )
	{
		Template = Class->GetDefaultObject<AActor>();
	}
	else if (NewActorName.IsNone() && !Template->HasAnyFlags(RF_ClassDefaultObject))
	{
		NewActorName = MakeUniqueObjectName(LevelToSpawnIn, Template->GetClass(), *Template->GetFName().GetPlainNameString());
	}
	check(Template!=NULL);

	// See if we can spawn on ded.server/client only etc (check NeedsLoadForClient & NeedsLoadForServer)
	if(!CanCreateInCurrentContext(Template))
	{
		UE_LOG(LogSpawn, Warning, TEXT("Unable to spawn class '%s' due to client/server context."), *Class->GetName() );
		return NULL;
	}

	FVector NewLocation = Transform ? Transform->GetLocation() : (Template->GetRootComponent() ? Template->GetRootComponent()->RelativeLocation : FVector::ZeroVector);
	FRotator NewRotation = Transform ? Transform->GetRotation().Rotator() :	(Template->GetRootComponent() ? Template->GetRootComponent()->RelativeRotation : FRotator::ZeroRotator);
	FVector NewScale = Transform ? Transform->GetScale3D() :	(Template->GetRootComponent() ? Template->GetRootComponent()->RelativeScale3D : FVector(1.f) );

	PRAGMA_DISABLE_DEPRECATION_WARNINGS;
	// handle existing (but deprecated) uses of bNoCollisionFail where user set it to true
	ESpawnActorCollisionHandlingMethod CollisionHandlingOverride = SpawnParameters.SpawnCollisionHandlingOverride;
	if ((CollisionHandlingOverride == ESpawnActorCollisionHandlingMethod::Undefined) && SpawnParameters.bNoCollisionFail)
	{
		CollisionHandlingOverride = ESpawnActorCollisionHandlingMethod::AlwaysSpawn;
	}
	PRAGMA_ENABLE_DEPRECATION_WARNINGS;

	// "no fail" take preedence over collision handling settings that include fails
	if (SpawnParameters.bNoFail)
	{
		// maybe upgrade to disallow fail
		if (CollisionHandlingOverride == ESpawnActorCollisionHandlingMethod::AdjustIfPossibleButDontSpawnIfColliding)
		{
			CollisionHandlingOverride = ESpawnActorCollisionHandlingMethod::AdjustIfPossibleButAlwaysSpawn;
		}
		else if (CollisionHandlingOverride == ESpawnActorCollisionHandlingMethod::DontSpawnIfColliding)
		{
			CollisionHandlingOverride = ESpawnActorCollisionHandlingMethod::AlwaysSpawn;
		}
	}

	// use override if set, else fall back to actor's preference
	ESpawnActorCollisionHandlingMethod const CollisionHandlingMethod = (CollisionHandlingOverride == ESpawnActorCollisionHandlingMethod::Undefined) ? Template->SpawnCollisionHandlingMethod : CollisionHandlingOverride;

	// see if we can avoid spawning altogether by checking native components
	// note: we can't handle all cases here, since we don't know the full component hierarchy until after the actor is spawned
	if (CollisionHandlingMethod == ESpawnActorCollisionHandlingMethod::DontSpawnIfColliding)
	{
		if (EncroachingBlockingGeometry(Template, NewLocation, NewRotation))
		{
			// a native component is colliding, that's enough to reject spawning
			UE_LOG(LogSpawn, Warning, TEXT("SpawnActor failed because of collision at the spawn location [%s] for [%s]"), *NewLocation.ToString(), *Class->GetName());
			return nullptr;
		}
	}

	// actually make the actor object
	AActor* const Actor = NewObject<AActor>(LevelToSpawnIn, Class, NewActorName, SpawnParameters.ObjectFlags, Template);
	check(Actor);

#if WITH_EDITOR
	Actor->ClearActorLabel(); // Clear label on newly spawned actors
#endif // WITH_EDITOR

	if ( GUndo )
	{
		ModifyLevel( LevelToSpawnIn );
	}
	LevelToSpawnIn->Actors.Add( Actor );

	// Add this newly spawned actor to the network actor list
	AddNetworkActor( Actor );

#if PERF_SHOW_MULTI_PAWN_SPAWN_FRAMES
	if( Cast<APawn>(Actor) )
	{
		FString PawnName = FString::Printf(TEXT("%d: %s"), ThisFramePawnSpawns.Num(), *Actor->GetPathName());
		ThisFramePawnSpawns.Add(PawnName);
	}
#endif

	// tell the actor what method to use, in case it was overridden
	Actor->SpawnCollisionHandlingMethod = CollisionHandlingMethod;

	Actor->PostSpawnInitialize(FTransform(NewRotation, NewLocation, NewScale), SpawnParameters.Owner, SpawnParameters.Instigator, SpawnParameters.bRemoteOwned, SpawnParameters.bNoFail, SpawnParameters.bDeferConstruction);

	if (Actor->IsPendingKill() && !SpawnParameters.bNoFail)
	{
		UE_LOG(LogSpawn, Warning, TEXT("SpawnActor failed because the spawned actor IsPendingKill"));
		return NULL;
	}
// 
// 	// actor should have all of its components now, do any collision checking and handling that we need to do
// 	switch (CollisionHandlingMethod)
// 	{
// 	case ESpawnActorCollisionHandlingMethod::AdjustIfPossibleButAlwaysSpawn:
// 	 	// Try to find a spawn position
// 		{
// 			FVector AdjustedLocation = NewLocation;
// 			FRotator AdjustedRotation = NewRotation;
// 			if (FindTeleportSpot(Actor, AdjustedLocation, AdjustedRotation))
// 			{
// 				Actor->SetActorLocationAndRotation(AdjustedLocation, AdjustedRotation);
// 			}
// 		}
// 	 	break;
// 	case ESpawnActorCollisionHandlingMethod::AdjustIfPossibleButDontSpawnIfColliding:
// 	 	// Try to find a spawn position
// 		{
// 			FVector AdjustedLocation = NewLocation;
// 			FRotator AdjustedRotation = NewRotation;
// 			if (FindTeleportSpot(Actor, AdjustedLocation, AdjustedRotation))
// 			{
// 				Actor->SetActorLocationAndRotation(AdjustedLocation, AdjustedRotation);
// 			}
// 			else
// 			{
// 				UE_LOG(LogSpawn, Warning, TEXT("SpawnActor failed because of collision at the spawn location [%s] for [%s]"), *NewLocation.ToString(), *Class->GetName());
// 				DestroyActor(Actor);
// 				return nullptr;
// 			}
// 		}
// 	 	break;
// 	case ESpawnActorCollisionHandlingMethod::DontSpawnIfColliding:
// 		// #todo: don't recheck components checked above?
// 		if (EncroachingBlockingGeometry(Actor, NewLocation, NewRotation))
// 	 	{
// 	 		UE_LOG(LogSpawn, Warning, TEXT("SpawnActor failed because of collision at the spawn location [%s] for [%s]"), *NewLocation.ToString(), *Class->GetName());
// 			DestroyActor(Actor);
// 			return nullptr;
// 	 	}
// 	 	break;
// 	// note we use "always spawn" as default, so treat undefined as that
// 	case ESpawnActorCollisionHandlingMethod::Undefined:
// 	case ESpawnActorCollisionHandlingMethod::AlwaysSpawn:
// 	default:
// 	 	// nothing to do, just proceed as normal
// 	 	break;
// 	}

	Actor->CheckDefaultSubobjects();

	// Broadcast notification of spawn
	OnActorSpawned.Broadcast(Actor);

#if WITH_EDITOR
	if (GIsEditor)
	{
		GEngine->BroadcastLevelActorAdded(Actor);
	}
#endif

	return Actor;
}