void FDesktopPlatformWindows::GetRequiredRegistrySettings(TIndirectArray<FRegistryRootedKey> &RootedKeys) { // Get the path to VersionSelector.exe. If we're running from UnrealVersionSelector itself, try to stick with the current configuration. FString DefaultVersionSelectorName = FPlatformProcess::ExecutableName(false); if (!DefaultVersionSelectorName.StartsWith(TEXT("UnrealVersionSelector"))) { DefaultVersionSelectorName = TEXT("UnrealVersionSelector.exe"); } FString ExecutableFileName = FString(FPlatformProcess::BaseDir()) / DefaultVersionSelectorName; // Defer to UnrealVersionSelector.exe in a launcher installation if it's got the same version number or greater. FString InstallDir; if (FWindowsPlatformMisc::QueryRegKey(HKEY_LOCAL_MACHINE, TEXT("SOFTWARE\\EpicGames\\Unreal Engine"), TEXT("INSTALLDIR"), InstallDir) && (InstallDir.Len() > 0)) { FString NormalizedInstallDir = InstallDir; FPaths::NormalizeDirectoryName(NormalizedInstallDir); FString InstalledExecutableFileName = NormalizedInstallDir / FString("Launcher/Engine/Binaries/Win64/UnrealVersionSelector.exe"); if(GetShellIntegrationVersion(InstalledExecutableFileName) == GetShellIntegrationVersion(ExecutableFileName)) { ExecutableFileName = InstalledExecutableFileName; } } // Get the path to the executable FPaths::MakePlatformFilename(ExecutableFileName); FString QuotedExecutableFileName = FString(TEXT("\"")) + ExecutableFileName + FString(TEXT("\"")); // HKCU\SOFTWARE\Classes\.uproject FRegistryRootedKey *UserRootExtensionKey = new FRegistryRootedKey(HKEY_CURRENT_USER, TEXT("SOFTWARE\\Classes\\.uproject")); RootedKeys.Add(UserRootExtensionKey); // HKLM\SOFTWARE\Classes\.uproject FRegistryRootedKey *RootExtensionKey = new FRegistryRootedKey(HKEY_LOCAL_MACHINE, TEXT("SOFTWARE\\Classes\\.uproject")); RootExtensionKey->Key = new FRegistryKey(); RootExtensionKey->Key->SetValue(TEXT(""), TEXT("Unreal.ProjectFile")); RootedKeys.Add(RootExtensionKey); // HKLM\SOFTWARE\Classes\Unreal.ProjectFile FRegistryRootedKey *RootFileTypeKey = new FRegistryRootedKey(HKEY_LOCAL_MACHINE, TEXT("SOFTWARE\\Classes\\Unreal.ProjectFile")); RootFileTypeKey->Key = new FRegistryKey(); RootFileTypeKey->Key->SetValue(TEXT(""), TEXT("Unreal Engine Project File")); RootFileTypeKey->Key->FindOrAddKey(L"DefaultIcon")->SetValue(TEXT(""), QuotedExecutableFileName); RootedKeys.Add(RootFileTypeKey); // HKLM\SOFTWARE\Classes\Unreal.ProjectFile\shell FRegistryKey *ShellKey = RootFileTypeKey->Key->FindOrAddKey(TEXT("shell")); // HKLM\SOFTWARE\Classes\Unreal.ProjectFile\shell\open FRegistryKey *ShellOpenKey = ShellKey->FindOrAddKey(TEXT("open")); ShellOpenKey->SetValue(L"", L"Open"); ShellOpenKey->FindOrAddKey(L"command")->SetValue(L"", QuotedExecutableFileName + FString(TEXT(" /editor \"%1\""))); // HKLM\SOFTWARE\Classes\Unreal.ProjectFile\shell\run FRegistryKey *ShellRunKey = ShellKey->FindOrAddKey(TEXT("run")); ShellRunKey->SetValue(TEXT(""), TEXT("Launch game")); ShellRunKey->SetValue(TEXT("Icon"), QuotedExecutableFileName); ShellRunKey->FindOrAddKey(L"command")->SetValue(TEXT(""), QuotedExecutableFileName + FString(TEXT(" /game \"%1\""))); // HKLM\SOFTWARE\Classes\Unreal.ProjectFile\shell\rungenproj FRegistryKey *ShellProjectKey = ShellKey->FindOrAddKey(TEXT("rungenproj")); ShellProjectKey->SetValue(L"", L"Generate Visual Studio project files"); ShellProjectKey->SetValue(L"Icon", QuotedExecutableFileName); ShellProjectKey->FindOrAddKey(L"command")->SetValue(TEXT(""), QuotedExecutableFileName + FString(TEXT(" /projectfiles \"%1\""))); // HKLM\SOFTWARE\Classes\Unreal.ProjectFile\shell\switchversion FRegistryKey *ShellVersionKey = ShellKey->FindOrAddKey(TEXT("switchversion")); ShellVersionKey->SetValue(TEXT(""), TEXT("Switch Unreal Engine version...")); ShellVersionKey->SetValue(TEXT("Icon"), QuotedExecutableFileName); ShellVersionKey->FindOrAddKey(L"command")->SetValue(TEXT(""), QuotedExecutableFileName + FString(TEXT(" /switchversion \"%1\""))); // If the user has manually selected something other than our extension, we need to delete it. Explorer explicitly disables set access on that keys in that folder, but we can delete the whole thing. const TCHAR* UserChoicePath = TEXT("Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\FileExts\\.uproject\\UserChoice"); // Figure out whether we need to delete it. If it's already set to our own ProgId, leave it alone. bool bDeleteUserChoiceKey = true; HKEY hUserChoiceKey; if(RegOpenKeyEx(HKEY_CURRENT_USER, UserChoicePath, 0, KEY_READ, &hUserChoiceKey) == S_OK) { TCHAR ProgId[128]; ::DWORD ProgIdSize = sizeof(ProgId); ::DWORD ProgIdType = 0; if(RegQueryValueEx(hUserChoiceKey, TEXT("Progid"), NULL, &ProgIdType, (BYTE*)ProgId, &ProgIdSize) == ERROR_SUCCESS && ProgIdType == REG_SZ) { bDeleteUserChoiceKey = (FCString::Strcmp(ProgId, TEXT("Unreal.ProjectFile")) != 0); } RegCloseKey(hUserChoiceKey); } if(bDeleteUserChoiceKey) { RootedKeys.Add(new FRegistryRootedKey(HKEY_CURRENT_USER, UserChoicePath)); } }
/** * Executes all pending shadow-map encoding requests. * @param InWorld World in which the textures exist * @param bLightingSuccessful Whether the lighting build was successful or not. */ void FShadowMap2D::EncodeTextures(UWorld* InWorld , bool bLightingSuccessful) { if ( bLightingSuccessful ) { GWarn->BeginSlowTask( NSLOCTEXT("ShadowMap2D", "BeginEncodingShadowMapsTask", "Encoding shadow-maps"), false ); const int32 PackedLightAndShadowMapTextureSize = InWorld->GetWorldSettings()->PackedLightAndShadowMapTextureSize; // Reset the pending shadow-map size. PendingShadowMapSize = 0; Sort(PendingShadowMaps.GetData(), PendingShadowMaps.Num(), FCompareShadowMaps()); // Allocate texture space for each shadow-map. TIndirectArray<FShadowMapPendingTexture> PendingTextures; for (FShadowMapAllocationGroup& PendingGroup : PendingShadowMaps) { if (!ensure(PendingGroup.Allocations.Num() >= 1)) { continue; } int32 MaxWidth = 0; int32 MaxHeight = 0; for (auto& Allocation : PendingGroup.Allocations) { MaxWidth = FMath::Max(MaxWidth, Allocation->MappedRect.Width()); MaxHeight = FMath::Max(MaxHeight, Allocation->MappedRect.Height()); } FShadowMapPendingTexture* Texture = nullptr; // Find an existing texture which the shadow-map can be stored in. // Shadowmaps will always be 4-pixel aligned... for (FShadowMapPendingTexture& ExistingTexture : PendingTextures) { if (ExistingTexture.AddElement(PendingGroup)) { Texture = &ExistingTexture; break; } } if (!Texture) { int32 NewTextureSizeX = PackedLightAndShadowMapTextureSize; int32 NewTextureSizeY = PackedLightAndShadowMapTextureSize; // Assumes identically-sized allocations, fit into the smallest square const int32 AllocationCountX = FMath::CeilToInt(FMath::Sqrt(FMath::DivideAndRoundUp(PendingGroup.Allocations.Num() * MaxHeight, MaxWidth))); const int32 AllocationCountY = FMath::DivideAndRoundUp(PendingGroup.Allocations.Num(), AllocationCountX); const int32 AllocationSizeX = AllocationCountX * MaxWidth; const int32 AllocationSizeY = AllocationCountY * MaxHeight; if (AllocationSizeX > NewTextureSizeX || AllocationSizeY > NewTextureSizeY) { NewTextureSizeX = FMath::RoundUpToPowerOfTwo(AllocationSizeX); NewTextureSizeY = FMath::RoundUpToPowerOfTwo(AllocationSizeY); } // If there is no existing appropriate texture, create a new one. Texture = new FShadowMapPendingTexture(NewTextureSizeX, NewTextureSizeY); PendingTextures.Add(Texture); Texture->Outer = PendingGroup.TextureOuter; Texture->Bounds = PendingGroup.Bounds; Texture->ShadowmapFlags = PendingGroup.ShadowmapFlags; verify(Texture->AddElement(PendingGroup)); } // Give the texture ownership of the allocations for (auto& Allocation : PendingGroup.Allocations) { Texture->Allocations.Add(Allocation.Release()); } } PendingShadowMaps.Empty(); // Encode all the pending textures. for (int32 TextureIndex = 0; TextureIndex < PendingTextures.Num(); TextureIndex++) { if (bUpdateStatus && (TextureIndex % 20) == 0) { GWarn->UpdateProgress(TextureIndex, PendingTextures.Num()); } FShadowMapPendingTexture& PendingTexture = PendingTextures[TextureIndex]; PendingTexture.StartEncoding(InWorld); } PendingTextures.Empty(); GWarn->EndSlowTask(); } else { PendingShadowMaps.Empty(); } }