Пример #1
1
bool FMergeActorsModule::UnregisterMergeActorsTool(IMergeActorsTool* Tool)
{
	if (Tool != nullptr)
	{
		if (MergeActorsTools.RemoveAll([=](const TUniquePtr<IMergeActorsTool>& Ptr) { return Ptr.Get() == Tool; }) > 0)
		{
			TSharedPtr<SMergeActorsToolbar> MergeActorsToolbar = MergeActorsToolbarPtr.Pin();
			if (MergeActorsToolbar.IsValid())
			{
				MergeActorsToolbar->RemoveTool(Tool);
			}

			return true;
		}
	}
	return false;
}
Пример #2
0
void SKeySelector::GetSearchTokens(const FString& SearchString, TArray<FString>& OutTokens) const
{
	if (SearchString.Contains("\"") && SearchString.ParseIntoArray(OutTokens, TEXT("\""), true) > 0)
	{
		for (auto &TokenIt : OutTokens)
		{
			// we have the token, we don't need the quotes anymore, they'll just confused the comparison later on
			TokenIt = TokenIt.TrimQuotes();
			// We remove the spaces as all later comparison strings will also be de-spaced
			TokenIt = TokenIt.Replace(TEXT(" "), TEXT(""));
		}

		// due to being able to handle multiple quoted blocks like ("Make Epic" "Game Now") we can end up with
		// and empty string between (" ") blocks so this simply removes them
		struct FRemoveMatchingStrings
		{
			bool operator()(const FString& RemovalCandidate) const
			{
				return RemovalCandidate.IsEmpty();
			}
		};
		OutTokens.RemoveAll(FRemoveMatchingStrings());
	}
	else
	{
		// unquoted search equivalent to a match-any-of search
		SearchString.ParseIntoArray(OutTokens, TEXT(" "), true);
	}
}
void SFindInMaterial::InitiateSearch()
{
	TArray<FString> Tokens;
	if (SearchValue.Contains("\"") && SearchValue.ParseIntoArray(Tokens, TEXT("\""), true) > 0)
	{
		for (auto &TokenIt : Tokens)
		{
			// we have the token, we don't need the quotes anymore, they'll just confused the comparison later on
			TokenIt = TokenIt.TrimQuotes();
			// We remove the spaces as all later comparison strings will also be de-spaced
			TokenIt = TokenIt.Replace(TEXT(" "), TEXT(""));
		}

		// due to being able to handle multiple quoted blocks like ("Make Epic" "Game Now") we can end up with
		// and empty string between (" ") blocks so this simply removes them
		struct FRemoveMatchingStrings
		{
			bool operator()(const FString& RemovalCandidate) const
			{
				return RemovalCandidate.IsEmpty();
			}
		};
		Tokens.RemoveAll(FRemoveMatchingStrings());
	}
	else
	{
		// unquoted search equivalent to a match-any-of search
		SearchValue.ParseIntoArray(Tokens, TEXT(" "), true);
	}

	for (auto It(ItemsFound.CreateIterator()); It; ++It)
	{
		TreeView->SetItemExpansion(*It, false);
	}
	ItemsFound.Empty();
	if (Tokens.Num() > 0)
	{
		HighlightText = FText::FromString(SearchValue);
		MatchTokens(Tokens);
	}

	// Insert a fake result to inform user if none found
	if (ItemsFound.Num() == 0)
	{
		ItemsFound.Add(FSearchResult(new FFindInMaterialResult(LOCTEXT("MaterialSearchNoResults", "No Results found").ToString())));
	}

	TreeView->RequestTreeRefresh();

	for (auto It(ItemsFound.CreateIterator()); It; ++It)
	{
		TreeView->SetItemExpansion(*It, true);
	}
}
void FOnlineNotificationHandler::RemoveSystemNotificationBinding(FString NotificationType, FDelegateHandle RemoveHandle)
{
	TArray<FOnlineNotificationBinding>* FoundBindings = SystemBindingMap.Find(NotificationType);

	int32 BindingsRemoved = 0;
	if (FoundBindings)
	{
		BindingsRemoved = FoundBindings->RemoveAll([=](const FOnlineNotificationBinding& Binding) { return Binding.NotificationDelegate.GetHandle() == RemoveHandle; });
	}

	if (BindingsRemoved == 0)
	{
		UE_LOG_ONLINE(Error, TEXT("Attempted to remove binding that could not be found for type %s"), *NotificationType);
	}
}
Пример #5
0
void FAssetDeleteModel::DiscoverSourceFileReferences(FPendingDelete& PendingDelete)
{
	if (!GetDefault<UEditorLoadingSavingSettings>()->bMonitorContentDirectories)
	{
		return;
	}
	
	// Start by extracting the files from the object
	TArray<FString> SourceContentFiles;
	Utils::ExtractSourceFilePaths(PendingDelete.GetObject(), SourceContentFiles);

	auto MonitoredDirectories = GUnrealEd->AutoReimportManager->GetMonitoredDirectories();

	// Remove anything that's not under a monitored, mounted path, or doesn't exist
	SourceContentFiles.RemoveAll([&](const FString& InFilename){
		for (const auto& Dir : MonitoredDirectories)
		{
			if (!Dir.MountPoint.IsEmpty() && InFilename.StartsWith(Dir.Path))
			{
				if (FPaths::FileExists(InFilename))
				{
					return false;
				}
				else
				{
					return true;
				}
			}
		}
		return true;
	});

	// Now accumulate references to the same source content file. We only offer to delete a file if it is only referenced by the deleted object(s)
	IAssetRegistry& AssetRegistry = FModuleManager::LoadModuleChecked<FAssetRegistryModule>(TEXT("AssetRegistry")).Get();
	for (const FString& SourcePath : SourceContentFiles)
	{
		int32* NumReferences = SourceFileToAssetCount.Find(SourcePath);
		if (NumReferences)
		{
			(*NumReferences)--;
		}
		else
		{
			const int32 NumReferencingAssets = Utils::FindAssetsPertainingToFile(AssetRegistry, SourcePath).Num();
			SourceFileToAssetCount.Add(SourcePath, NumReferencingAssets - 1);
		}
	}
}
Пример #6
0
bool FHierarchicalLODBuilder::ShouldGenerateCluster(AActor* Actor)
{
	if (!Actor)
	{
		return false;
	}

	if (!Actor->bEnableAutoLODGeneration)
	{
		return false;
	}

	FVector Origin, Extent;
	Actor->GetActorBounds(false, Origin, Extent);
	if (Extent.SizeSquared() <= 0.1)
	{
		return false;
	}

	// for now only consider staticmesh - I don't think skel mesh would work with simplygon merge right now @fixme
	TArray<UStaticMeshComponent*> Components;
	Actor->GetComponents<UStaticMeshComponent>(Components);
	// TODO: support instanced static meshes
	Components.RemoveAll([](UStaticMeshComponent* Val){ return Val->IsA(UInstancedStaticMeshComponent::StaticClass()); });

	int32 ValidComponentCount = 0;
	// now make sure you check parent primitive, so that we don't build for the actor that already has built. 
	if (Components.Num() > 0)
	{
		for (auto& ComponentIter : Components)
		{
			if (ComponentIter->GetLODParentPrimitive())
			{
				return false;
			}

			// see if we should generate it
			if (ComponentIter->ShouldGenerateAutoLOD())
			{
				++ValidComponentCount;
				break;
			}
		}
	}

	return (ValidComponentCount > 0);
}
Пример #7
0
//----------------------------------------------------------------------------
void Node::UpdateStateRenderObject(States* pStates, Lights* pLights)
{
	if (!mspRenderObject)
	{
		return;
	}

	// update global state
	StatePtr* rStates = mspRenderObject->GetStates();
	for (UInt i = 0; i < State::MAX_STATE_TYPE; i++)
	{
		TArray<State*>& rState = pStates[i];
		rStates[i] = rState[rState.GetQuantity()-1];
	}

	// update light state
	TArray<LightPtr>* pRenderObjectLights = mspRenderObject->GetLights();
	if (!pRenderObjectLights)
	{
		pRenderObjectLights = WIRE_NEW TArray<LightPtr>;
	}

	pRenderObjectLights->RemoveAll();
	pRenderObjectLights->SetMaxQuantity(pLights->GetQuantity());
	for (UInt i = 0; i < pLights->GetQuantity(); i++)
	{
		if (((*pLights)[i]->LayerMask & mLayerMask) != 0)
		{
			pRenderObjectLights->Append((*pLights)[i]);
		}
	}

	enum
	{
		STATEKEYBITS = 12,
		LIGHTKEYBITS = 12,
	};

	UInt stateKey = State::GetSetID(mspRenderObject->GetStates());
	WIRE_ASSERT(stateKey < (1 << STATEKEYBITS));

	UInt lightKey = Light::GetSetID(mspRenderObject->GetLights());
	WIRE_ASSERT(stateKey < (1 << LIGHTKEYBITS));

	UInt key = (lightKey << STATEKEYBITS) | stateKey;
	mspRenderObject->SetStateSetID(key);
}
FActorPositionTraceResult FActorPositioning::TraceWorldForPosition(const UWorld& InWorld, const FSceneView& InSceneView, const FVector& RayStart, const FVector& RayEnd, const TArray<AActor*>* IgnoreActors)
{
	TArray<FHitResult> Hits;

	FCollisionQueryParams Param(TEXT("DragDropTrace"), true);
	Param.bTraceAsyncScene = true;
	
	if (IgnoreActors)
	{
		Param.AddIgnoredActors(*IgnoreActors);
	}

	FActorPositionTraceResult Results;
	if ( InWorld.LineTraceMultiByObjectType(Hits, RayStart, RayEnd, FCollisionObjectQueryParams(FCollisionObjectQueryParams::InitType::AllObjects), Param) )
	{
		{
			// Filter out anything that should be ignored
			FSuspendRenderingThread SuspendRendering(false);
			Hits.RemoveAll([&](const FHitResult& Hit){
				return IsHitIgnored(Hit, InSceneView);
			});
		}

		// Go through all hits and find closest
		float ClosestHitDistanceSqr = TNumericLimits<float>::Max();

		for (const auto& Hit : Hits)
		{
			const float DistanceToHitSqr = (Hit.ImpactPoint - RayStart).SizeSquared();
			if (DistanceToHitSqr < ClosestHitDistanceSqr)
			{
				ClosestHitDistanceSqr = DistanceToHitSqr;
				Results.Location = Hit.Location;
				Results.SurfaceNormal = Hit.Normal.GetSafeNormal();
				Results.State = FActorPositionTraceResult::HitSuccess;
				Results.HitActor = Hit.Actor;
			}
		}
	}

	return Results;
}
/** Remove the player notification handler for a type */
void FOnlineNotificationHandler::RemovePlayerNotificationBinding(const FUniqueNetId& PlayerId, FString NotificationType, FDelegateHandle RemoveHandle)
{
	int32 BindingsRemoved = 0;

	NotificationTypeBindingsMap* FoundPlayerBindings = PlayerBindingMap.Find(PlayerId.ToString());

	if (FoundPlayerBindings)
	{
		TArray<FOnlineNotificationBinding>* FoundPlayerTypeBindings = FoundPlayerBindings->Find(NotificationType);

		if (FoundPlayerTypeBindings)
		{
			BindingsRemoved = FoundPlayerTypeBindings->RemoveAll([=](const FOnlineNotificationBinding& Binding) { return Binding.NotificationDelegate.GetHandle() == RemoveHandle; });
		}
	}

	if (BindingsRemoved == 0)
	{
		UE_LOG_ONLINE(Error, TEXT("Attempted to remove binding that could not be found for player %s type %s"), *PlayerId.ToDebugString(), *NotificationType);
	}
}
bool FHierarchicalLODUtilities::BuildStaticMeshForLODActor(ALODActor* LODActor, UPackage* AssetsOuter, const FHierarchicalSimplification& LODSetup, const uint32 LODIndex)
{
	if (AssetsOuter && LODActor)
	{
		if (!LODActor->IsDirty())
		{
			return false;
		}

		const FScopedTransaction Transaction(LOCTEXT("UndoAction_BuildProxyMesh", "Building Proxy Mesh for Cluster"));
		LODActor->Modify();		

		// Delete actor assets before generating new ones
		FHierarchicalLODUtilities::DestroyClusterData(LODActor);	
		
		TArray<UStaticMeshComponent*> AllComponents;
		{
			FScopedSlowTask SlowTask(LODActor->SubActors.Num(), (LOCTEXT("HierarchicalLODUtils_CollectStaticMeshes", "Collecting Static Meshes for Cluster")));
			SlowTask.MakeDialog();
			for (auto& Actor : LODActor->SubActors)
			{
				TArray<UStaticMeshComponent*> Components;

				if (Actor->IsA<ALODActor>())
				{
					ExtractStaticMeshComponentsFromLODActor(Actor, Components);
				}
				else
				{
					Actor->GetComponents<UStaticMeshComponent>(Components);
				}

				// TODO: support instanced static meshes
				Components.RemoveAll([](UStaticMeshComponent* Val){ return Val->IsA(UInstancedStaticMeshComponent::StaticClass()); });

				AllComponents.Append(Components);
				SlowTask.EnterProgressFrame(1);
			}
		}

		// it shouldn't even have come here if it didn't have any staticmesh
		if (ensure(AllComponents.Num() > 0))
		{
			FScopedSlowTask SlowTask(LODActor->SubActors.Num(), (LOCTEXT("HierarchicalLODUtils_MergingMeshes", "Merging Static Meshes and creating LODActor")));
			SlowTask.MakeDialog();

			// In case we don't have outer generated assets should have same path as LOD level
			const FString AssetsPath = AssetsOuter->GetName() + TEXT("/");
			AActor* FirstActor = LODActor->SubActors[0];

			TArray<UObject*> OutAssets;
			FVector OutProxyLocation = FVector::ZeroVector;
			UStaticMesh* MainMesh = nullptr;

			// Generate proxy mesh and proxy material assets
			IMeshUtilities& MeshUtilities = FModuleManager::Get().LoadModuleChecked<IMeshUtilities>("MeshUtilities");
			// should give unique name, so use level + actor name
			const FString PackageName = FString::Printf(TEXT("LOD_%s"), *FirstActor->GetName());
			if (MeshUtilities.GetMeshMergingInterface() && LODSetup.bSimplifyMesh)
			{
				TArray<AActor*> Actors;
				ExtractSubActorsFromLODActor(LODActor, Actors);

				FHierarchicalLODUtilities& Module = FModuleManager::LoadModuleChecked<FHierarchicalLODUtilities>("HierarchicalLODUtilities");
				FHierarchicalLODProxyProcessor* Processor = Module.GetProxyProcessor();

				FHierarchicalSimplification OverrideLODSetup = LODSetup;

				FMeshProxySettings ProxySettings = LODSetup.ProxySetting;
				if (LODActor->bOverrideMaterialMergeSettings)
				{
					ProxySettings.MaterialSettings = LODActor->MaterialSettings;
				}

				if (LODActor->bOverrideScreenSize)
				{
					ProxySettings.ScreenSize = LODActor->ScreenSize;
				}

				if (LODActor->bOverrideTransitionScreenSize)
				{
					OverrideLODSetup.TransitionScreenSize = LODActor->TransitionScreenSize;
				}

				FGuid JobID = Processor->AddProxyJob(LODActor, OverrideLODSetup);
				MeshUtilities.CreateProxyMesh(Actors, ProxySettings, AssetsOuter, PackageName, JobID, Processor->GetCallbackDelegate(), true, OverrideLODSetup.TransitionScreenSize);
				return true;
			}
			else
			{
				FMeshMergingSettings MergeSettings = LODSetup.MergeSetting;
				if (LODActor->bOverrideMaterialMergeSettings)
				{
					MergeSettings.MaterialSettings = LODActor->MaterialSettings;
				}

				MeshUtilities.MergeStaticMeshComponents(AllComponents, FirstActor->GetWorld(), MergeSettings, AssetsOuter, PackageName, LODIndex, OutAssets, OutProxyLocation, LODSetup.TransitionScreenSize, true);
				
				// set staticmesh
				for (auto& Asset : OutAssets)
				{
					UStaticMesh* StaticMesh = Cast<UStaticMesh>(Asset);

					if (StaticMesh)
					{
						MainMesh = StaticMesh;
					}
				}

				LODActor->SetStaticMesh(MainMesh);
				LODActor->SetActorLocation(OutProxyLocation);
				LODActor->SubObjects = OutAssets;

				// At the moment this assumes a fixed field of view of 90 degrees (horizontal and vertical axi)
				static const float FOVRad = 90.0f * (float)PI / 360.0f;
				static const FMatrix ProjectionMatrix = FPerspectiveMatrix(FOVRad, 1920, 1080, 0.01f);
				FBoxSphereBounds Bounds = LODActor->GetStaticMeshComponent()->CalcBounds(FTransform());
				LODActor->LODDrawDistance = FHierarchicalLODUtilities::CalculateDrawDistanceFromScreenSize(Bounds.SphereRadius, LODSetup.TransitionScreenSize, ProjectionMatrix);
				LODActor->UpdateSubActorLODParents();

				// Freshly build so mark not dirty
				LODActor->SetIsDirty(false);

				return true;
			}
		}
	}
	return false;
}
void FInternationalization::GetCulturesWithAvailableLocalization(const TArray<FString>& InLocalizationPaths, TArray< FCultureRef >& OutAvailableCultures, const bool bIncludeDerivedCultures)
{
	OutAvailableCultures.Reset();

	TArray<FString> AllLocalizationFolders;
	IFileManager& FileManager = IFileManager::Get();
	for(const auto& LocalizationPath : InLocalizationPaths)
	{
		/* Visitor class used to enumerate directories of culture */
		class FCultureEnumeratorVistor : public IPlatformFile::FDirectoryVisitor
		{
		public:
			FCultureEnumeratorVistor( TArray<FString>& OutLocalizationFolders )
				: LocalizationFolders(OutLocalizationFolders)
			{
			}

			virtual bool Visit(const TCHAR* FilenameOrDirectory, bool bIsDirectory) override
			{
				if(bIsDirectory)
				{
					// UE localization resource folders use "en-US" style while ICU uses "en_US"
					const FString LocalizationFolder = FPaths::GetCleanFilename(FilenameOrDirectory);
					const FString CanonicalName = FCulture::GetCanonicalName(LocalizationFolder);
					LocalizationFolders.AddUnique(CanonicalName);
				}

				return true;
			}

			/** Array to fill with the names of the UE localization folders available at the given path */
			TArray<FString>& LocalizationFolders;
		};

		FCultureEnumeratorVistor CultureEnumeratorVistor(AllLocalizationFolders);
		FileManager.IterateDirectory(*LocalizationPath, CultureEnumeratorVistor);
	}

	// Find any cultures that are a partial match for those we have translations for.
	if(bIncludeDerivedCultures)
	{
		TArray<FString> CultureNames;
		GetCultureNames(CultureNames);
		for(const FString& CultureName : CultureNames)
		{
			FCulturePtr Culture = GetCulture(CultureName);
			if (Culture.IsValid())
			{
				TArray<FString> PrioritizedParentCultureNames = Culture->GetPrioritizedParentCultureNames();

				for (const FString& PrioritizedParentCultureName : PrioritizedParentCultureNames)
				{
					if(AllLocalizationFolders.Contains(PrioritizedParentCultureName))
					{
						OutAvailableCultures.AddUnique(Culture.ToSharedRef());
						break;
					}
				}
			}
		}
	}
	// Find any cultures that are a complete match for those we have translations for.
	else
	{
		for(const FString& LocalizationFolder : AllLocalizationFolders)
		{
			FCulturePtr Culture = GetCulture(LocalizationFolder);
			if(Culture.IsValid())
			{
				OutAvailableCultures.AddUnique(Culture.ToSharedRef());
			}
		}
	}

	// Remove any cultures that were explicitly disabled
	OutAvailableCultures.RemoveAll([&](const FCultureRef& InCulture) -> bool
	{
		return Implementation->IsCultureDisabled(InCulture->GetName());
	});
}
Пример #12
0
void FLODCluster::BuildActor(ULevel* InLevel, const int32 LODIdx, const bool bCreateMeshes)
{
	FColor Colours[8] = { FColor::Cyan, FColor::Red, FColor::Green, FColor::Blue, FColor::Yellow, FColor::Magenta, FColor::White, FColor::Black };
	// do big size
	if (InLevel && InLevel->GetWorld())
	{
		// create asset using Actors
		const FHierarchicalSimplification& LODSetup = InLevel->GetWorld()->GetWorldSettings()->HierarchicalLODSetup[LODIdx];

		// Retrieve draw distance for current and next LOD level
		const float DrawDistance = LODSetup.DrawDistance;		
		const int32 LODCount = InLevel->GetWorld()->GetWorldSettings()->HierarchicalLODSetup.Num();
		const float NextDrawDistance = (LODIdx < (LODCount - 1)) ? InLevel->GetWorld()->GetWorldSettings()->HierarchicalLODSetup[LODIdx + 1].DrawDistance : 0.0f;

		// Where generated assets will be stored
		UPackage* AssetsOuter = InLevel->GetOutermost(); // this asset is going to save with map, this means, I'll have to delete with it
		if (AssetsOuter)
		{
			TArray<UStaticMeshComponent*> AllComponents;

			for (auto& Actor: Actors)
			{
				TArray<UStaticMeshComponent*> Components;
				
				if (Actor->IsA<ALODActor>())
				{
					HierarchicalLODUtils::ExtractStaticMeshComponentsFromLODActor(Actor, Components);
				}
				else
				{
					Actor->GetComponents<UStaticMeshComponent>(Components);
				}

				// TODO: support instanced static meshes
				Components.RemoveAll([](UStaticMeshComponent* Val){ return Val->IsA(UInstancedStaticMeshComponent::StaticClass()); });

				AllComponents.Append(Components);
			}

			// it shouldn't even have come here if it didn't have any staticmesh
			if (ensure(AllComponents.Num() > 0))
			{
				// In case we don't have outer generated assets should have same path as LOD level

				const FString AssetsPath = AssetsOuter->GetName() + TEXT("/");
				AActor* FirstActor = Actors[0];

				TArray<UObject*> OutAssets;
				FVector OutProxyLocation = FVector::ZeroVector;
				UStaticMesh* MainMesh = nullptr;
				if (bCreateMeshes)
				{
					// Generate proxy mesh and proxy material assets
					IMeshUtilities& MeshUtilities = FModuleManager::Get().LoadModuleChecked<IMeshUtilities>("MeshUtilities");
					// should give unique name, so use level + actor name
					const FString PackageName = FString::Printf(TEXT("LOD_%s"), *FirstActor->GetName());
					if (MeshUtilities.GetMeshMergingInterface() && LODSetup.bSimplifyMesh)
					{
						MeshUtilities.CreateProxyMesh(Actors, LODSetup.ProxySetting, AssetsOuter, PackageName, OutAssets, OutProxyLocation);
					}
					else
					{						
						MeshUtilities.MergeStaticMeshComponents(AllComponents, FirstActor->GetWorld(), LODSetup.MergeSetting, AssetsOuter, PackageName, LODIdx, OutAssets, OutProxyLocation, LODSetup.DrawDistance, true);
					}

					// we make it private, so it can't be used by outside of map since it's useless, and then remove standalone
					for (auto& AssetIter : OutAssets)
					{
						AssetIter->ClearFlags(RF_Public | RF_Standalone);
					}

					
					// set staticmesh
					for (auto& Asset : OutAssets)
					{
						UStaticMesh* StaticMesh = Cast<UStaticMesh>(Asset);

						if (StaticMesh)
						{
							MainMesh = StaticMesh;
						}
					}
				}
							

				if (MainMesh || !bCreateMeshes)
				{
					UWorld* LevelWorld = Cast<UWorld>(InLevel->GetOuter());

					check (LevelWorld);

					FTransform Transform;
					Transform.SetLocation(OutProxyLocation);					
										
					// create LODActors using the current Actors
					ALODActor* NewActor = nullptr;
										
					NewActor = LevelWorld->SpawnActor<ALODActor>(ALODActor::StaticClass(), Transform);				
					NewActor->SubObjects = OutAssets;
					NewActor->LODLevel = LODIdx+1;
					NewActor->LODDrawDistance = DrawDistance;
					NewActor->SetStaticMesh( MainMesh );
					// now set as parent
					for(auto& Actor : Actors)
					{
						NewActor->AddSubActor(Actor);
					}

					// Mark dirty according to whether or not this is a preview build
					NewActor->SetIsDirty(!bCreateMeshes);
				}
			}
		}
	}
}