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; }
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); } }
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); } } }
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); }
//---------------------------------------------------------------------------- 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()); }); }
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); } } } } }