VRTowerDef/Plugins/MetaXR/Source/OculusXREditor/Private/OculusXREditorModule.cpp

599 lines
23 KiB
C++

// Copyright (c) Meta Platforms, Inc. and affiliates.
#include "OculusXREditorModule.h"
#include "AssetToolsModule.h"
#include "OculusXRToolStyle.h"
#include "OculusXRToolCommands.h"
#include "OculusXRPlatformToolWidget.h"
#include "OculusXRAssetDirectory.h"
#include "OculusXRHMDRuntimeSettings.h"
#include "IOculusXRProjectSetupModule.h"
#include "OculusXRHMDTypes.h"
#include "LevelEditor.h"
#include "Modules/ModuleManager.h"
#include "Widgets/Docking/SDockTab.h"
#include "Widgets/Input/SButton.h"
#include "PropertyEditorModule.h"
#include "DetailLayoutBuilder.h"
#include "DetailCategoryBuilder.h"
#include "DetailWidgetRow.h"
#include "GeneralProjectSettings.h"
#include "IAssetTools.h"
#include "Framework/MultiBox/MultiBoxBuilder.h"
#include "ISettingsModule.h"
#include "OculusXRPassthroughColorLutAsset.h"
#include "OculusXRHMDModule.h"
#include "OculusXRPrivacyNotification.h"
#include "OculusXRSettingsToggle.h"
#include "OculusXRTelemetryPrivacySettings.h"
#include "OculusXRTelemetry.h"
#include "OculusXRTelemetryEditorEvents.h"
#include "SExternalImageReference.h"
#include "AndroidRuntimeSettings.h"
#include "SourceControlHelpers.h"
#include "Framework/Notifications/NotificationManager.h"
#include "Widgets/Notifications/SNotificationList.h"
#include "Editor/EditorPerformanceSettings.h"
#define LOCTEXT_NAMESPACE "OculusXREditor"
const FName FOculusXREditorModule::OculusPlatToolTabName = FName("OculusXRPlaformTool");
void FOculusXREditorModule::PostLoadCallback()
{
FLevelEditorModule& LevelEditorModule = FModuleManager::LoadModuleChecked<FLevelEditorModule>("LevelEditor");
}
void FOculusXREditorModule::StartupModule()
{
bModuleValid = true;
RegisterSettings();
FOculusAssetDirectory::LoadForCook();
if (!IsRunningCommandlet())
{
FOculusToolStyle::Initialize();
FOculusToolStyle::ReloadTextures();
FOculusToolCommands::Register();
PluginCommands = MakeShareable(new FUICommandList);
PluginCommands->MapAction(
FOculusToolCommands::Get().OpenProjectSetupTool,
FExecuteAction::CreateRaw(this, &FOculusXREditorModule::PluginOpenSetupToolWindow),
FCanExecuteAction());
PluginCommands->MapAction(
FOculusToolCommands::Get().OpenPlatWindow,
FExecuteAction::CreateRaw(this, &FOculusXREditorModule::PluginOpenPlatWindow),
FCanExecuteAction());
PluginCommands->MapAction(
FOculusToolCommands::Get().ToggleDeploySo,
FExecuteAction::CreateLambda([=]() {
UOculusXRHMDRuntimeSettings* settings = GetMutableDefault<UOculusXRHMDRuntimeSettings>();
settings->bDeploySoToDevice = !settings->bDeploySoToDevice;
settings->Modify(true);
settings->UpdateSinglePropertyInConfigFile(settings->GetClass()->FindPropertyByName(GET_MEMBER_NAME_CHECKED(UOculusXRHMDRuntimeSettings, bDeploySoToDevice)), settings->GetDefaultConfigFilename());
}),
FCanExecuteAction(),
FIsActionChecked::CreateLambda([=]() {
return GetMutableDefault<UOculusXRHMDRuntimeSettings>()->bDeploySoToDevice;
}));
PluginCommands->MapAction(
FOculusToolCommands::Get().ToggleMetaXRSim,
FExecuteAction::CreateRaw(this, &FOculusXREditorModule::ToggleOpenXRRuntime),
FCanExecuteAction(),
FIsActionChecked::CreateLambda([=]() {
return FOculusXRHMDModule::IsSimulatorActivated();
}));
PluginCommands->MapAction(
FOculusToolCommands::Get().LaunchGameRoom,
FExecuteAction::CreateRaw(this, &FOculusXREditorModule::LaunchSESGameRoom),
FCanExecuteAction());
PluginCommands->MapAction(
FOculusToolCommands::Get().LaunchLivingRoom,
FExecuteAction::CreateRaw(this, &FOculusXREditorModule::LaunchSESLivingRoom),
FCanExecuteAction());
PluginCommands->MapAction(
FOculusToolCommands::Get().LaunchBedroom,
FExecuteAction::CreateRaw(this, &FOculusXREditorModule::LaunchSESBedroom),
FCanExecuteAction());
PluginCommands->MapAction(
FOculusToolCommands::Get().StopServer,
FExecuteAction::CreateRaw(this, &FOculusXREditorModule::StopSESServer),
FCanExecuteAction());
FLevelEditorModule& LevelEditorModule = FModuleManager::LoadModuleChecked<FLevelEditorModule>("LevelEditor");
// Adds an option to launch the tool to Window->Developer Tools.
TSharedPtr<FExtender> MenuExtender = MakeShareable(new FExtender());
MenuExtender->AddMenuExtension("Miscellaneous", EExtensionHook::After, PluginCommands, FMenuExtensionDelegate::CreateRaw(this, &FOculusXREditorModule::AddMenuExtension));
LevelEditorModule.GetMenuExtensibilityManager()->AddExtender(MenuExtender);
// We add the Oculus menu on the toolbar
TSharedPtr<FExtender> ToolbarExtender = MakeShareable(new FExtender);
ToolbarExtender->AddToolBarExtension("Play", EExtensionHook::After, PluginCommands, FToolBarExtensionDelegate::CreateRaw(this, &FOculusXREditorModule::AddToolbarExtension));
LevelEditorModule.GetToolBarExtensibilityManager()->AddExtender(ToolbarExtender);
FGlobalTabmanager::Get()->RegisterNomadTabSpawner(OculusPlatToolTabName, FOnSpawnTab::CreateRaw(this, &FOculusXREditorModule::OnSpawnPlatToolTab)).SetDisplayName(LOCTEXT("FOculusPlatfToolTabTitle", "Meta XR Platform Tool")).SetMenuType(ETabSpawnerMenuType::Hidden);
// Register asset types
IAssetTools& AssetTools = FModuleManager::LoadModuleChecked<FAssetToolsModule>("AssetTools").Get();
AssetTools.RegisterAssetTypeActions(MakeShareable(new FAssetTypeActions_OculusXRPassthroughColorLut));
OculusXRTelemetry::PropagateTelemetryConsent();
// If needed, open a notification here.
OculusXRTelemetry::SpawnNotification();
const UGeneralProjectSettings& ProjectSettings = *GetDefault<UGeneralProjectSettings>();
const FString ProjectIdString = ProjectSettings.ProjectID.ToString();
const OculusXRTelemetry::TScopedMarker<OculusXRTelemetry::Events::FEditorStart> StartEvent;
const auto& Annotated = StartEvent.AddAnnotation("project_hash", StringCast<ANSICHAR>(*ProjectIdString).Get());
UEditorPerformanceSettings* EditorPerformanceSettings = GetMutableDefault<UEditorPerformanceSettings>();
if (EditorPerformanceSettings->bOverrideMaxViewportRenderingResolution)
{
UE_LOG(LogTemp, Warning, TEXT("Existing value for UEditorPerformanceSettings::MaxViewportRenderingResolution will be overriden."));
}
UE_LOG(LogTemp, Log, TEXT("MetaXR ignores max viewport resolution in editor to support full HMD resolutions."));
EditorPerformanceSettings->bOverrideMaxViewportRenderingResolution = true;
EditorPerformanceSettings->MaxViewportRenderingResolution = 0;
FPropertyChangedEvent DisabledMaxResolutionEvent(EditorPerformanceSettings->GetClass()->FindPropertyByName(GET_MEMBER_NAME_CHECKED(UEditorPerformanceSettings, MaxViewportRenderingResolution)), EPropertyChangeType::ValueSet);
EditorPerformanceSettings->PostEditChangeProperty(DisabledMaxResolutionEvent);
}
}
void FOculusXREditorModule::ShutdownModule()
{
if (!bModuleValid)
{
return;
}
if (!IsRunningCommandlet())
{
FOculusToolStyle::Shutdown();
FOculusToolCommands::Unregister();
FGlobalTabmanager::Get()->UnregisterNomadTabSpawner(OculusPlatToolTabName);
}
FOculusAssetDirectory::ReleaseAll();
if (UObjectInitialized())
{
UnregisterSettings();
}
}
TSharedRef<SDockTab> FOculusXREditorModule::OnSpawnPlatToolTab(const FSpawnTabArgs& SpawnTabArgs)
{
/* clang-format off */
auto myTab = SNew(SDockTab)
.TabRole(ETabRole::NomadTab)
[
SNew(SOculusPlatformToolWidget)
];
/* clang-format on */
return myTab;
}
void FOculusXREditorModule::RegisterSettings()
{
if (ISettingsModule* SettingsModule = FModuleManager::GetModulePtr<ISettingsModule>("Settings"))
{
SettingsModule->RegisterSettings("Project", "Plugins", "OculusXR",
LOCTEXT("RuntimeSettingsName", "Meta XR"),
LOCTEXT("RuntimeSettingsDescription", "Configure the Meta XR plugin"),
GetMutableDefault<UOculusXRHMDRuntimeSettings>());
FPropertyEditorModule& PropertyModule = FModuleManager::GetModuleChecked<FPropertyEditorModule>("PropertyEditor");
PropertyModule.RegisterCustomClassLayout(UOculusXRHMDRuntimeSettings::StaticClass()->GetFName(), FOnGetDetailCustomizationInstance::CreateStatic(&FOculusXRHMDSettingsDetailsCustomization::MakeInstance));
SettingsModule->RegisterSettings("Editor", "Privacy", "OculusXR",
LOCTEXT("PrivacyTelemetrySettingsName", "MetaXR Usage Data"),
LOCTEXT("PrivacyTelemetrySettingsDescription", "Configure the way MetaXR usage information is handled."),
GetMutableDefault<UOculusXRTelemetryPrivacySettings>());
PropertyModule.RegisterCustomClassLayout(UOculusXRTelemetryPrivacySettings::StaticClass()->GetFName(), FOnGetDetailCustomizationInstance::CreateStatic(&FOculusXRSettingsToggle::MakeInstance));
}
}
void FOculusXREditorModule::UnregisterSettings()
{
if (ISettingsModule* SettingsModule = FModuleManager::GetModulePtr<ISettingsModule>("Settings"))
{
SettingsModule->UnregisterSettings("Project", "Plugins", "OculusXR");
SettingsModule->UnregisterSettings("Editor", "Privacy", "OculusXR");
}
}
FReply FOculusXREditorModule::PluginClickFn(bool text)
{
PluginOpenSetupToolWindow();
return FReply::Handled();
}
void FOculusXREditorModule::PluginOpenSetupToolWindow()
{
IOculusXRProjectSetupToolModule::Get().ShowProjectSetupTool("Meta Menu");
}
void FOculusXREditorModule::PluginOpenPlatWindow()
{
FGlobalTabmanager::Get()->TryInvokeTab(OculusPlatToolTabName);
}
void FOculusXREditorModule::ToggleOpenXRRuntime()
{
FOculusXRHMDModule::ToggleOpenXRRuntime();
}
void FOculusXREditorModule::LaunchSESGameRoom()
{
FOculusXRHMDModule::LaunchEnvironment("GameRoom");
}
void FOculusXREditorModule::LaunchSESLivingRoom()
{
FOculusXRHMDModule::LaunchEnvironment("LivingRoom");
}
void FOculusXREditorModule::LaunchSESBedroom()
{
FOculusXRHMDModule::LaunchEnvironment("Bedroom");
}
void FOculusXREditorModule::StopSESServer()
{
FOculusXRHMDModule::StopServer();
}
void FOculusXREditorModule::AddMenuExtension(FMenuBuilder& Builder)
{
bool v = false;
GConfig->GetBool(TEXT("/Script/OculusXREditor.OculusXREditorSettings"), TEXT("bAddMenuOption"), v, GEditorIni);
if (v)
{
Builder.AddMenuEntry(FOculusToolCommands::Get().OpenProjectSetupTool);
}
}
void FOculusXREditorModule::AddToolbarExtension(FToolBarBuilder& Builder)
{
Builder.SetLabelVisibility(EVisibility::All);
Builder.AddComboButton(
FUIAction(),
FOnGetContent::CreateRaw(this, &FOculusXREditorModule::CreateToolbarEntryMenu, PluginCommands),
LOCTEXT("OculusToolsToolBarCombo", "Meta XR Tools"),
LOCTEXT("OculusToolsToolBarComboTooltip", "Meta XR tools"),
TAttribute<FSlateIcon>::CreateLambda([]() {
return FSlateIcon(FOculusToolStyle::GetStyleSetName(), "OculusTool.MenuButton");
}),
false);
Builder.AddComboButton(
FUIAction(),
FOnGetContent::CreateRaw(this, &FOculusXREditorModule::CreateXrSimToolbarEntryMenu, PluginCommands),
LOCTEXT("MetaXRSimulatorCombo", "Meta XR Simulator"),
LOCTEXT("MetaXRSimulatorComboTooltip", "Meta XR Simulator"),
TAttribute<FSlateIcon>::CreateLambda([]() {
return FSlateIcon(FOculusToolStyle::GetStyleSetName(), "OculusTool.MenuButton");
}),
false);
}
// Add the entries to the OculusXR Tools toolbar menu button
TSharedRef<SWidget> FOculusXREditorModule::CreateToolbarEntryMenu(TSharedPtr<class FUICommandList> Commands)
{
FMenuBuilder MenuBuilder(true, Commands);
MenuBuilder.BeginSection("OculusXRBuilds", LOCTEXT("OculusXRBuilds", "Builds"));
MenuBuilder.AddMenuEntry(FOculusToolCommands::Get().ToggleDeploySo);
MenuBuilder.EndSection();
MenuBuilder.BeginSection("OculusXRTools", LOCTEXT("OculusXRTools", "Tools"));
MenuBuilder.AddMenuEntry(FOculusToolCommands::Get().OpenProjectSetupTool);
MenuBuilder.AddMenuEntry(FOculusToolCommands::Get().OpenPlatWindow);
MenuBuilder.EndSection();
return MenuBuilder.MakeWidget();
}
TSharedRef<SWidget> FOculusXREditorModule::CreateXrSimToolbarEntryMenu(TSharedPtr<class FUICommandList> Commands)
{
FMenuBuilder MenuBuilder(true, Commands);
MenuBuilder.BeginSection("MetaXRSimulator", LOCTEXT("MetaXRSimulator", "Toggle"));
MenuBuilder.AddMenuEntry(FOculusToolCommands::Get().ToggleMetaXRSim);
MenuBuilder.EndSection();
MenuBuilder.BeginSection("SES", LOCTEXT("SES", "SES"));
MenuBuilder.AddSubMenu(
LOCTEXT("Synthetic Environment Server", "Synthetic Environment Server"),
LOCTEXT("Synthetic Environment Server", "Synthetic Environment Server"),
FNewMenuDelegate::CreateRaw(this, &FOculusXREditorModule::CreateSESSubMenus));
MenuBuilder.EndSection();
return MenuBuilder.MakeWidget();
}
void FOculusXREditorModule::CreateSESSubMenus(FMenuBuilder& MenuBuilder)
{
MenuBuilder.BeginSection("Synthetic Environment Server", LOCTEXT("Synthetic Environment Server", "Synthetic Environment Server"));
MenuBuilder.AddMenuEntry(FOculusToolCommands::Get().LaunchGameRoom);
MenuBuilder.AddMenuEntry(FOculusToolCommands::Get().LaunchLivingRoom);
MenuBuilder.AddMenuEntry(FOculusToolCommands::Get().LaunchBedroom);
MenuBuilder.AddMenuEntry(FOculusToolCommands::Get().StopServer);
MenuBuilder.EndSection();
}
FOculusXRHMDSettingsDetailsCustomization::FOculusXRHMDSettingsDetailsCustomization()
: EngineAndroidPath(FPaths::EngineDir() + TEXT("Build/Android/Java"))
, GameAndroidPath(FPaths::ProjectDir() + TEXT("Build/Android"))
, LaunchImageLandscape(FPlatformIconInfo(TEXT("res/drawable/splashscreen_landscape.png"), LOCTEXT("SystemSplashImage", "System Splash Image"), FText::GetEmpty(), 640, 360, FPlatformIconInfo::Required))
, VRSplashPath(FPaths::ProjectDir() + TEXT("Build/Android/assets/vr_splash.png"))
{
}
TSharedRef<IDetailCustomization> FOculusXRHMDSettingsDetailsCustomization::MakeInstance()
{
return MakeShareable(new FOculusXRHMDSettingsDetailsCustomization);
}
FReply FOculusXRHMDSettingsDetailsCustomization::PluginClickPerfFn(bool text)
{
IOculusXRProjectSetupToolModule::Get().ShowProjectSetupTool("Settings");
return FReply::Handled();
}
FReply FOculusXRHMDSettingsDetailsCustomization::PluginClickPlatFn(bool text)
{
FGlobalTabmanager::Get()->TryInvokeTab(FOculusXREditorModule::OculusPlatToolTabName);
return FReply::Handled();
}
FReply FOculusXRHMDSettingsDetailsCustomization::DisableEngineSplash(bool text)
{
UOculusXRHMDRuntimeSettings* Settings = GetMutableDefault<UOculusXRHMDRuntimeSettings>();
Settings->bAutoEnabled = false;
Settings->SplashDescs.Empty();
Settings->TryUpdateDefaultConfigFile();
return FReply::Handled();
}
FReply FOculusXRHMDSettingsDetailsCustomization::AddSplashImage(bool text)
{
const FString AutomaticImagePath = EngineAndroidPath / LaunchImageLandscape.IconPath;
FText FailReason;
if (!SourceControlHelpers::CopyFileUnderSourceControl(VRSplashPath, AutomaticImagePath, LOCTEXT("ImageDescription", "image"), FailReason))
{
FNotificationInfo Info(FailReason);
Info.ExpireDuration = 3.0f;
FSlateNotificationManager::Get().AddNotification(Info);
return FReply::Unhandled();
}
return FReply::Handled();
}
void FOculusXRHMDSettingsDetailsCustomization::CustomizeDetails(IDetailLayoutBuilder& DetailLayout)
{
SavedLayoutBuilder = &DetailLayout;
// Labeled "General OculusXR" instead of "General" to enable searchability. The button "Launch Oculus Utilities Window" doesn't show up if you search for "Oculus"
IDetailCategoryBuilder& CategoryBuilder = DetailLayout.EditCategory("General Meta XR", FText::GetEmpty(), ECategoryPriority::Important);
/* clang-format off */
CategoryBuilder.AddCustomRow(LOCTEXT("General", "General"))
.WholeRowContent()
[
SNew(SVerticalBox)
+ SVerticalBox::Slot().AutoHeight().Padding(2)
[
SNew(SHorizontalBox)
+ SHorizontalBox::Slot().AutoWidth()
[
SNew(SButton)
.Text(LOCTEXT("LaunchTool", "Launch Meta XR Project Setup Tool"))
.OnClicked(this, &FOculusXRHMDSettingsDetailsCustomization::PluginClickPerfFn, true)
]
+ SHorizontalBox::Slot().FillWidth(8)
]
+ SVerticalBox::Slot().AutoHeight().Padding(2)
[
SNew(SHorizontalBox)
+ SHorizontalBox::Slot().AutoWidth()
[
SNew(SButton)
.Text(LOCTEXT("LaunchPlatTool", "Launch Meta XR Platform Window"))
.OnClicked(this, &FOculusXRHMDSettingsDetailsCustomization::PluginClickPlatFn, true)
]
+ SHorizontalBox::Slot().FillWidth(8)
]
];
IDetailCategoryBuilder& CTXPTCategoryBuilder = DetailLayout.EditCategory("System SplashScreen", FText::GetEmpty(), ECategoryPriority::Important);
static const FName WarningColorStyle("Colors.AccentYellow");
CTXPTCategoryBuilder.AddCustomRow(LOCTEXT("CTXPTWarning", "Contextual Passthrough Warning"))
.Visibility(TAttribute<EVisibility>(this, &FOculusXRHMDSettingsDetailsCustomization::GetContextualPassthroughWarningVisibility))
[
SNew(SVerticalBox)
+ SVerticalBox::Slot().FillHeight(1.f)
[
SNew(SHorizontalBox)
+ SHorizontalBox::Slot().FillWidth(1.f).VAlign(EVerticalAlignment::VAlign_Center)
[
SNew(STextBlock)
.Font(IDetailLayoutBuilder::GetDetailFont())
.AutoWrapText(true)
.Justification(ETextJustify::Center)
.Text(LOCTEXT("CTXPT_EngineSplashWarning", "Engine Splash Screen is enabled, this will result in an inconsistent experience."))
.ColorAndOpacity(FAppStyle::Get().GetSlateColor(WarningColorStyle))
]
+ SHorizontalBox::Slot().FillWidth(1.f).HAlign(EHorizontalAlignment::HAlign_Left)
[
SNew(SButton)
.VAlign(EVerticalAlignment::VAlign_Center)
.Text(LOCTEXT("DisableEngineSplashScreen", "Disable Engine Splash Screen"))
.OnClicked(this, &FOculusXRHMDSettingsDetailsCustomization::DisableEngineSplash, true)
]
]
];
// Duplicate "Show Launch Image" and "Launch Landscape" properties from Android Settings
CTXPTCategoryBuilder.AddCustomRow(LOCTEXT("ShowSystemSplashImageRow", "Show System Splash Image Row"))
.NameContent()
[
SNew(SHorizontalBox)
+ SHorizontalBox::Slot()
.Padding(FMargin(0, 1, 0, 1))
.FillWidth(1.0f)
[
SNew(STextBlock)
.Text(LOCTEXT("ShowSystemSplashImage", "Show System Splash Image"))
.Font(DetailLayout.GetDetailFont())
.ToolTipText(LOCTEXT("ShowSystemSplashImageToolTip", "Same as \"Show Launch Image\" setting in the \"Platform > Android > Launch Images\" section. If set, the image will be presented by the Operating System at launch time"))
]
]
.ValueContent()
.MaxDesiredWidth(400.0f)
.MinDesiredWidth(100.0f)
[
SNew(SHorizontalBox)
+ SHorizontalBox::Slot()
.FillWidth(1.0f)
.VAlign(VAlign_Center)
[
SNew(SCheckBox)
.IsChecked(TAttribute<ECheckBoxState>(this, &FOculusXRHMDSettingsDetailsCustomization::GetShowLaunchImageCheckBoxState))
.OnCheckStateChanged(this, &FOculusXRHMDSettingsDetailsCustomization::OnShowLaunchImageCheckStateChanged)
]
];
const FString AutomaticImagePath = EngineAndroidPath / LaunchImageLandscape.IconPath;
const FString TargetImagePath = GameAndroidPath / LaunchImageLandscape.IconPath;
const FVector2D LaunchImageMaxSize(150.0f, 150.0f);
CTXPTCategoryBuilder.AddCustomRow(LaunchImageLandscape.IconName)
.IsEnabled(TAttribute<bool>(this, &FOculusXRHMDSettingsDetailsCustomization::IsLaunchImageEnabled))
.NameContent()
[
SNew(SHorizontalBox)
+ SHorizontalBox::Slot()
.Padding(FMargin(0, 1, 0, 1))
.FillWidth(1.0f)
[
SNew(STextBlock)
.Text(LaunchImageLandscape.IconName)
.Font(DetailLayout.GetDetailFont())
.ToolTipText(LOCTEXT("SystemSplashImageToolTip", "Same as \"Launch Landscape\" setting in the \"Platform > Android > Launch Images\" section. This is the image that will be presented by the Operating System at launch time"))
]
]
.ValueContent()
.MaxDesiredWidth(400.0f)
.MinDesiredWidth(100.0f)
[
SNew(SHorizontalBox)
+ SHorizontalBox::Slot()
.FillWidth(1.0f)
.VAlign(VAlign_Center)
[
SNew(SExternalImageReference, AutomaticImagePath, TargetImagePath)
.FileDescription(LaunchImageLandscape.IconDescription)
.MaxDisplaySize(LaunchImageMaxSize)
.OnPostExternalImageCopy(FOnPostExternalImageCopy::CreateSP(this, &FOculusXRHMDSettingsDetailsCustomization::OnLaunchImageChanged))
]
];
CTXPTCategoryBuilder.AddCustomRow(LOCTEXT("SystemSplashImageWarning", "System Splash Image warning"))
.Visibility(TAttribute<EVisibility>(this, &FOculusXRHMDSettingsDetailsCustomization::GetSystemSplashImageWarningVisibility))
[
SNew(SVerticalBox)
+ SVerticalBox::Slot().FillHeight(1.f)
[
SNew(SHorizontalBox)
+ SHorizontalBox::Slot().FillWidth(1.f).VAlign(EVerticalAlignment::VAlign_Center)
[
SNew(STextBlock)
.Font(IDetailLayoutBuilder::GetDetailFont())
.AutoWrapText(true)
.Justification(ETextJustify::Center)
.Text(LOCTEXT("SystemSplashWarningText", "Splash Image is currently missing from project. Click button to add it."))
.ColorAndOpacity(FAppStyle::Get().GetSlateColor(WarningColorStyle))
]
+ SHorizontalBox::Slot().FillWidth(1.f).HAlign(EHorizontalAlignment::HAlign_Left)
[
SNew(SButton)
.VAlign(EVerticalAlignment::VAlign_Center)
.Text(LOCTEXT("DisableEngineSplashScreen", "Add Splash Image file to project"))
.OnClicked(this, &FOculusXRHMDSettingsDetailsCustomization::AddSplashImage, true)
]
]
];
/* clang-format on */
}
EVisibility FOculusXRHMDSettingsDetailsCustomization::GetContextualPassthroughWarningVisibility() const
{
UOculusXRHMDRuntimeSettings* OculusSettings = GetMutableDefault<UOculusXRHMDRuntimeSettings>();
return OculusSettings->SystemSplashBackground == ESystemSplashBackgroundType::Contextual && (OculusSettings->bAutoEnabled || !OculusSettings->SplashDescs.IsEmpty()) ? EVisibility::Visible : EVisibility::Collapsed;
}
ECheckBoxState FOculusXRHMDSettingsDetailsCustomization::GetShowLaunchImageCheckBoxState() const
{
UAndroidRuntimeSettings* AndroidSettings = GetMutableDefault<UAndroidRuntimeSettings>();
return AndroidSettings->bShowLaunchImage ? ECheckBoxState::Checked : ECheckBoxState::Unchecked;
}
bool FOculusXRHMDSettingsDetailsCustomization::IsLaunchImageEnabled() const
{
UAndroidRuntimeSettings* AndroidSettings = GetMutableDefault<UAndroidRuntimeSettings>();
return AndroidSettings->bShowLaunchImage;
}
void FOculusXRHMDSettingsDetailsCustomization::OnShowLaunchImageCheckStateChanged(const ECheckBoxState NewState)
{
UAndroidRuntimeSettings* AndroidSettings = GetMutableDefault<UAndroidRuntimeSettings>();
AndroidSettings->bShowLaunchImage = NewState == ECheckBoxState::Checked;
AndroidSettings->TryUpdateDefaultConfigFile();
}
bool FOculusXRHMDSettingsDetailsCustomization::OnLaunchImageChanged(const FString& InChosenImage)
{
// This will refresh the launch image located in android settings as well
SavedLayoutBuilder->ForceRefreshDetails();
FText FailReason;
if (!SourceControlHelpers::CopyFileUnderSourceControl(VRSplashPath, InChosenImage, LOCTEXT("ImageDescription", "image"), FailReason))
{
FNotificationInfo Info(FailReason);
Info.ExpireDuration = 3.0f;
FSlateNotificationManager::Get().AddNotification(Info);
return false;
}
return true;
}
EVisibility FOculusXRHMDSettingsDetailsCustomization::GetSystemSplashImageWarningVisibility() const
{
IFileManager& FileManager = IFileManager::Get();
return !FileManager.FileExists(*VRSplashPath) ? EVisibility::Visible : EVisibility::Collapsed;
}
//////////////////////////////////////////////////////////////////////////
IMPLEMENT_MODULE(FOculusXREditorModule, OculusXREditor);
//////////////////////////////////////////////////////////////////////////
#undef LOCTEXT_NAMESPACE