Android build settings + metaxr
This commit is contained in:
56
Plugins/MetaXR/Source/OculusXREditor/OculusXREditor.Build.cs
Normal file
56
Plugins/MetaXR/Source/OculusXREditor/OculusXREditor.Build.cs
Normal file
@@ -0,0 +1,56 @@
|
||||
// @lint-ignore-every LICENSELINT
|
||||
// Copyright Epic Games, Inc. All Rights Reserved.
|
||||
|
||||
using UnrealBuildTool;
|
||||
|
||||
public class OculusXREditor : ModuleRules
|
||||
{
|
||||
public OculusXREditor(ReadOnlyTargetRules Target) : base(Target)
|
||||
{
|
||||
bUseUnity = true;
|
||||
|
||||
PrivateDependencyModuleNames.AddRange(
|
||||
new string[] {
|
||||
"Projects",
|
||||
"InputCore",
|
||||
"UnrealEd",
|
||||
"LevelEditor",
|
||||
"PropertyEditor",
|
||||
"CoreUObject",
|
||||
"Engine",
|
||||
"EngineSettings",
|
||||
"AndroidRuntimeSettings",
|
||||
"Slate",
|
||||
"SlateCore",
|
||||
"EditorStyle",
|
||||
"Core",
|
||||
"OculusXRHMD",
|
||||
"OculusXRMovement",
|
||||
"OculusXRPassthrough",
|
||||
"OVRPluginXR",
|
||||
"OculusXRProjectSetupTool",
|
||||
"HTTP",
|
||||
"DesktopPlatform",
|
||||
"LauncherServices",
|
||||
"GameProjectGeneration",
|
||||
"SharedSettingsWidgets",
|
||||
"RHI",
|
||||
"SourceControl",
|
||||
}
|
||||
);
|
||||
|
||||
PrivateIncludePaths.AddRange(
|
||||
new string[] {
|
||||
// Relative to Engine\Plugins\Runtime\Oculus\OculusVR\Source
|
||||
"OculusXREditor/Private",
|
||||
"OculusXRHMD/Private",
|
||||
"OculusXRProjectSetupTool/Private"
|
||||
});
|
||||
|
||||
PrivateIncludePathModuleNames.AddRange(
|
||||
new string[] {
|
||||
"Settings",
|
||||
"OculusXRProjectSetupTool"
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,328 @@
|
||||
// @lint-ignore-every LICENSELINT
|
||||
// Copyright Epic Games, Inc. All Rights Reserved.
|
||||
|
||||
#include "OculusXRBuildAnalytics.h"
|
||||
#include "GameProjectGenerationModule.h"
|
||||
#include "OculusXRHMDModule.h"
|
||||
#include "OculusXRHMDRuntimeSettings.h"
|
||||
#include "OculusXRTelemetryPrivacySettings.h"
|
||||
#include "Runtime/Core/Public/HAL/FileManager.h"
|
||||
|
||||
FOculusBuildAnalytics* FOculusBuildAnalytics::instance = 0;
|
||||
|
||||
FOculusBuildAnalytics* FOculusBuildAnalytics::GetInstance()
|
||||
{
|
||||
if (IOculusXRHMDModule::IsAvailable())
|
||||
{
|
||||
if (instance == nullptr)
|
||||
{
|
||||
instance = new FOculusBuildAnalytics();
|
||||
}
|
||||
}
|
||||
|
||||
return instance;
|
||||
}
|
||||
|
||||
bool FOculusBuildAnalytics::IsOculusXRHMDAvailable()
|
||||
{
|
||||
return IOculusXRHMDModule::IsAvailable() && FOculusXRHMDModule::Get().PreInit();
|
||||
}
|
||||
|
||||
void FOculusBuildAnalytics::Shutdown()
|
||||
{
|
||||
}
|
||||
|
||||
FOculusBuildAnalytics::FOculusBuildAnalytics()
|
||||
{
|
||||
bool TelemetryEnabled = false;
|
||||
if (const auto EditorPrivacySettings = GetDefault<UOculusXRTelemetryPrivacySettings>())
|
||||
{
|
||||
TelemetryEnabled = EditorPrivacySettings->bIsEnabled;
|
||||
}
|
||||
|
||||
if (TelemetryEnabled)
|
||||
{
|
||||
RegisterLauncherCallback();
|
||||
}
|
||||
}
|
||||
|
||||
void FOculusBuildAnalytics::OnTelemetryToggled(bool Enabled)
|
||||
{
|
||||
if (Enabled)
|
||||
{
|
||||
RegisterLauncherCallback();
|
||||
}
|
||||
else
|
||||
{
|
||||
if (LauncherCallbackHandle.IsValid())
|
||||
{
|
||||
ILauncherServicesModule& ProjectLauncherServicesModule = FModuleManager::LoadModuleChecked<ILauncherServicesModule>("LauncherServices");
|
||||
ProjectLauncherServicesModule.OnCreateLauncherDelegate.Remove(LauncherCallbackHandle);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void FOculusBuildAnalytics::RegisterLauncherCallback()
|
||||
{
|
||||
ILauncherServicesModule& ProjectLauncherServicesModule = FModuleManager::LoadModuleChecked<ILauncherServicesModule>("LauncherServices");
|
||||
LauncherCallbackHandle = ProjectLauncherServicesModule.OnCreateLauncherDelegate.AddRaw(this, &FOculusBuildAnalytics::OnLauncherCreated);
|
||||
}
|
||||
|
||||
void FOculusBuildAnalytics::OnLauncherCreated(ILauncherRef Launcher)
|
||||
{
|
||||
// Add callback for when launcher worker is started
|
||||
Launcher->FLauncherWorkerStartedDelegate.AddRaw(this, &FOculusBuildAnalytics::OnLauncherWorkerStarted);
|
||||
}
|
||||
|
||||
void FOculusBuildAnalytics::OnLauncherWorkerStarted(ILauncherWorkerPtr LauncherWorker, ILauncherProfileRef Profile)
|
||||
{
|
||||
bool isUsingIterativeCotf = GetMutableDefault<UOculusXRHMDRuntimeSettings>()->bIterativeCookOnTheFly;
|
||||
FOculusXRHMDModule::GetPluginWrapper().SetDeveloperMode(true);
|
||||
FOculusXRHMDModule::GetPluginWrapper().SendEvent2(
|
||||
"build_start_is_iterative_cotf", isUsingIterativeCotf ? "1" : "0", "ovrbuild");
|
||||
|
||||
TArray<FString> Platforms = Profile.Get().GetCookedPlatforms();
|
||||
if (Platforms.Num() == 1)
|
||||
{
|
||||
if (Platforms[0].Equals("Android_ASTC") || Platforms[0].Contains("Windows"))
|
||||
{
|
||||
CurrentBuildStage = UNDEFINED_STAGE;
|
||||
AndroidPackageTime = 0;
|
||||
UATLaunched = false;
|
||||
BuildCompleted = false;
|
||||
CurrentBuildPlatform = Platforms[0];
|
||||
TotalBuildTime = 0;
|
||||
BuildStepCount = 0;
|
||||
OutputDirectory = Profile.Get().GetPackageDirectory();
|
||||
|
||||
// Assign callbacks for stages
|
||||
LauncherWorker.Get()->OnStageCompleted().AddRaw(this, &FOculusBuildAnalytics::OnStageCompleted);
|
||||
LauncherWorker.Get()->OnOutputReceived().AddRaw(this, &FOculusBuildAnalytics::OnBuildOutputReceived);
|
||||
LauncherWorker.Get()->OnStageStarted().AddRaw(this, &FOculusBuildAnalytics::OnStageStarted);
|
||||
LauncherWorker.Get()->OnCompleted().AddRaw(this, &FOculusBuildAnalytics::OnCompleted);
|
||||
|
||||
// Get information on what oculus platform we are building for and also the OS platform
|
||||
FString OculusPlatform;
|
||||
if (CurrentBuildPlatform.Equals("Android_ASTC"))
|
||||
{
|
||||
UEnum* OculusMobileDevices = StaticEnum<EOculusMobileDevice::Type>();
|
||||
UAndroidRuntimeSettings* Settings = GetMutableDefault<UAndroidRuntimeSettings>();
|
||||
TArray<TEnumAsByte<EOculusMobileDevice::Type>> TargetOculusDevices = Settings->PackageForOculusMobile;
|
||||
TArray<FString> Devices;
|
||||
|
||||
if (TargetOculusDevices.Contains(EOculusMobileDevice::Quest2))
|
||||
{
|
||||
Devices.Add("quest2");
|
||||
}
|
||||
OculusPlatform = FString::Join(Devices, TEXT("_"));
|
||||
}
|
||||
else if (CurrentBuildPlatform.Contains("Windows"))
|
||||
{
|
||||
CurrentBuildPlatform = "Windows";
|
||||
OculusPlatform = "rift";
|
||||
}
|
||||
|
||||
// Count user asset files
|
||||
UserAssetCount = 0;
|
||||
TArray<FString> FileNames;
|
||||
IFileManager::Get().FindFilesRecursive(FileNames, *FPaths::ProjectContentDir(), TEXT("*.*"), true, false, false);
|
||||
UserAssetCount = FileNames.Num();
|
||||
|
||||
// Count user script files
|
||||
FGameProjectGenerationModule& GameProjectModule = FModuleManager::LoadModuleChecked<FGameProjectGenerationModule>(TEXT("GameProjectGeneration"));
|
||||
SourceFileCount = 0;
|
||||
SourceFileDirectorySize = 0;
|
||||
GameProjectModule.Get().GetProjectSourceDirectoryInfo(SourceFileCount, SourceFileDirectorySize);
|
||||
|
||||
// Generate build GUID
|
||||
FGuid guid = FGuid::NewGuid();
|
||||
FOculusXRHMDModule::GetPluginWrapper().AddCustomMetadata("build_guid", TCHAR_TO_ANSI(*guid.ToString()));
|
||||
|
||||
// Send build start event with corresponding metadata
|
||||
FOculusXRHMDModule::GetPluginWrapper().AddCustomMetadata("asset_count", TCHAR_TO_ANSI(*FString::FromInt(UserAssetCount)));
|
||||
FOculusXRHMDModule::GetPluginWrapper().AddCustomMetadata("script_count", TCHAR_TO_ANSI(*FString::FromInt(SourceFileCount)));
|
||||
|
||||
FOculusXRHMDModule::GetPluginWrapper().AddCustomMetadata("target_platform", TCHAR_TO_ANSI(*CurrentBuildPlatform));
|
||||
FOculusXRHMDModule::GetPluginWrapper().AddCustomMetadata("target_oculus_platform", TCHAR_TO_ANSI(*OculusPlatform));
|
||||
|
||||
TArray<ILauncherTaskPtr> TaskList;
|
||||
LauncherWorker->GetTasks(TaskList);
|
||||
BuildStepCount = TaskList.Num();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void FOculusBuildAnalytics::OnCompleted(bool Succeeded, double TotalTime, int32 ErrorCode)
|
||||
{
|
||||
if (!BuildCompleted && Succeeded)
|
||||
{
|
||||
SendBuildCompleteEvent(TotalTime);
|
||||
}
|
||||
}
|
||||
|
||||
void FOculusBuildAnalytics::OnStageCompleted(const FString& StageName, double Time)
|
||||
{
|
||||
if (CurrentBuildStage != UNDEFINED_STAGE)
|
||||
{
|
||||
FString TaskName;
|
||||
switch (CurrentBuildStage)
|
||||
{
|
||||
case COOK_IN_EDITOR_STAGE:
|
||||
TaskName = "build_step_editor_cook";
|
||||
break;
|
||||
case LAUNCH_UAT_STAGE:
|
||||
TaskName = "build_step_launch_uat";
|
||||
break;
|
||||
case COMPILE_STAGE:
|
||||
TaskName = "build_step_compile";
|
||||
break;
|
||||
case COOK_STAGE:
|
||||
TaskName = "build_step_cook";
|
||||
break;
|
||||
case DEPLOY_STAGE:
|
||||
TaskName = "build_step_deploy";
|
||||
break;
|
||||
case PACKAGE_STAGE:
|
||||
TaskName = "build_step_package";
|
||||
break;
|
||||
case RUN_STAGE:
|
||||
return;
|
||||
default:
|
||||
TaskName = "build_step_undefined";
|
||||
break;
|
||||
}
|
||||
|
||||
if (AndroidPackageTime > 0)
|
||||
{
|
||||
Time -= AndroidPackageTime;
|
||||
}
|
||||
|
||||
TotalBuildTime += Time;
|
||||
FOculusXRHMDModule::GetPluginWrapper().SendEvent2(TCHAR_TO_ANSI(*TaskName), TCHAR_TO_ANSI(*FString::SanitizeFloat(Time)), "ovrbuild");
|
||||
}
|
||||
}
|
||||
|
||||
void FOculusBuildAnalytics::OnStageStarted(const FString& StageName)
|
||||
{
|
||||
if (StageName.Equals("Cooking in the editor"))
|
||||
{
|
||||
CurrentBuildStage = COOK_IN_EDITOR_STAGE;
|
||||
}
|
||||
else if (StageName.Equals("Build Task") && CurrentBuildStage == LAUNCH_UAT_STAGE)
|
||||
{
|
||||
CurrentBuildStage = COMPILE_STAGE;
|
||||
}
|
||||
else if (StageName.Equals("Build Task"))
|
||||
{
|
||||
CurrentBuildStage = LAUNCH_UAT_STAGE;
|
||||
}
|
||||
else if (StageName.Equals("Cook Task"))
|
||||
{
|
||||
CurrentBuildStage = COOK_STAGE;
|
||||
}
|
||||
else if (StageName.Equals("Package Task"))
|
||||
{
|
||||
CurrentBuildStage = PACKAGE_STAGE;
|
||||
}
|
||||
else if (StageName.Equals("Deploy Task"))
|
||||
{
|
||||
CurrentBuildStage = DEPLOY_STAGE;
|
||||
}
|
||||
else if (StageName.Equals("Run Task"))
|
||||
{
|
||||
CurrentBuildStage = RUN_STAGE;
|
||||
SendBuildCompleteEvent(TotalBuildTime);
|
||||
BuildCompleted = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
CurrentBuildStage = UNDEFINED_STAGE;
|
||||
}
|
||||
}
|
||||
|
||||
void FOculusBuildAnalytics::OnBuildOutputReceived(const FString& Message)
|
||||
{
|
||||
if (CurrentBuildPlatform.Equals("Android_ASTC") && (CurrentBuildStage == DEPLOY_STAGE || CurrentBuildStage == PACKAGE_STAGE))
|
||||
{
|
||||
if (Message.Contains("BUILD SUCCESSFUL"))
|
||||
{
|
||||
FString Text, Time;
|
||||
Message.Split("in", &Text, &Time);
|
||||
|
||||
if (!Time.IsEmpty())
|
||||
{
|
||||
FString SMinutes, SSeconds;
|
||||
if (Time.Contains("m"))
|
||||
{
|
||||
Time.Split("m", &SMinutes, &SSeconds);
|
||||
}
|
||||
else
|
||||
{
|
||||
SSeconds = Time;
|
||||
}
|
||||
|
||||
int Minutes = FCString::Atoi(*SMinutes);
|
||||
int Seconds = FCString::Atoi(*SSeconds);
|
||||
|
||||
AndroidPackageTime = Minutes * 60 + Seconds;
|
||||
|
||||
FOculusXRHMDModule::GetPluginWrapper().SendEvent2("build_step_gradle_build", TCHAR_TO_ANSI(*FString::SanitizeFloat(AndroidPackageTime)), "ovrbuild");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void FOculusBuildAnalytics::SendBuildCompleteEvent(float TotalTime)
|
||||
{
|
||||
if (CurrentBuildPlatform.Equals("Android_ASTC"))
|
||||
{
|
||||
int64 APKTotalSize = 0;
|
||||
TArray<FString> FoundAPKs;
|
||||
OutputDirectory = FPaths::ProjectDir() + "Binaries/Android";
|
||||
OutputDirectory = FPaths::ConvertRelativePathToFull(OutputDirectory);
|
||||
IFileManager::Get().FindFiles(FoundAPKs, *FPaths::Combine(OutputDirectory, TEXT("*.apk")), true, false);
|
||||
|
||||
FDateTime LatestTime = FDateTime(0);
|
||||
FString LatestAPK;
|
||||
for (int i = 0; i < FoundAPKs.Num(); i++)
|
||||
{
|
||||
FDateTime APKCreationTime = IFileManager::Get().GetTimeStamp(*FPaths::Combine(OutputDirectory, FoundAPKs[i]));
|
||||
if (APKCreationTime > LatestTime)
|
||||
{
|
||||
LatestTime = APKCreationTime;
|
||||
LatestAPK = FoundAPKs[i];
|
||||
}
|
||||
}
|
||||
|
||||
TArray<FString> FoundOBBs;
|
||||
LatestTime = FDateTime(0);
|
||||
FString LatestOBB;
|
||||
IFileManager::Get().FindFiles(FoundOBBs, *FPaths::Combine(OutputDirectory, TEXT("*.obb")), true, false);
|
||||
for (int i = 0; i < FoundOBBs.Num(); i++)
|
||||
{
|
||||
FDateTime OBBCreationTime = IFileManager::Get().GetTimeStamp(*FPaths::Combine(OutputDirectory, FoundOBBs[i]));
|
||||
if (OBBCreationTime > LatestTime)
|
||||
{
|
||||
LatestTime = OBBCreationTime;
|
||||
LatestOBB = FoundOBBs[i];
|
||||
}
|
||||
}
|
||||
|
||||
if (!LatestAPK.IsEmpty())
|
||||
{
|
||||
APKTotalSize += IFileManager::Get().FileSize(*FPaths::Combine(OutputDirectory, LatestAPK));
|
||||
}
|
||||
if (!LatestOBB.IsEmpty())
|
||||
{
|
||||
APKTotalSize += IFileManager::Get().FileSize(*FPaths::Combine(OutputDirectory, LatestOBB));
|
||||
}
|
||||
|
||||
if (APKTotalSize > 0)
|
||||
{
|
||||
FOculusXRHMDModule::GetPluginWrapper().AddCustomMetadata("build_output_size", TCHAR_TO_ANSI(*FString::FromInt(APKTotalSize)));
|
||||
}
|
||||
}
|
||||
|
||||
FOculusXRHMDModule::GetPluginWrapper().AddCustomMetadata("build_step_count", TCHAR_TO_ANSI(*FString::FromInt(BuildStepCount)));
|
||||
FOculusXRHMDModule::GetPluginWrapper().SendEvent2("build_complete", TCHAR_TO_ANSI(*FString::SanitizeFloat(TotalTime)), "ovrbuild");
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
// @lint-ignore-every LICENSELINT
|
||||
// Copyright Epic Games, Inc. All Rights Reserved.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "ILauncherServicesModule.h"
|
||||
#include "ILauncher.h"
|
||||
#include "Modules/ModuleManager.h"
|
||||
#include "UObject/Class.h"
|
||||
#include "AndroidRuntimeSettings.h"
|
||||
#include "OculusXRPluginWrapper.h"
|
||||
|
||||
enum EBuildStage
|
||||
{
|
||||
UNDEFINED_STAGE,
|
||||
COOK_IN_EDITOR_STAGE,
|
||||
COOK_STAGE,
|
||||
LAUNCH_UAT_STAGE,
|
||||
COMPILE_STAGE,
|
||||
PACKAGE_STAGE,
|
||||
DEPLOY_STAGE,
|
||||
RUN_STAGE,
|
||||
};
|
||||
|
||||
class FOculusBuildAnalytics
|
||||
{
|
||||
public:
|
||||
static FOculusBuildAnalytics* GetInstance();
|
||||
static void Shutdown();
|
||||
static bool IsOculusXRHMDAvailable();
|
||||
|
||||
void RegisterLauncherCallback();
|
||||
void OnTelemetryToggled(bool Enabled);
|
||||
|
||||
void OnLauncherCreated(ILauncherRef Launcher);
|
||||
void OnLauncherWorkerStarted(ILauncherWorkerPtr LauncherWorker, ILauncherProfileRef Profile);
|
||||
void OnStageCompleted(const FString& StageName, double Time);
|
||||
void OnStageStarted(const FString& StageName);
|
||||
void OnBuildOutputReceived(const FString& Message);
|
||||
void OnCompleted(bool Succeeded, double TotalTime, int32 ErrorCode);
|
||||
void SendBuildCompleteEvent(float TotalTime);
|
||||
|
||||
private:
|
||||
FOculusBuildAnalytics();
|
||||
|
||||
static FOculusBuildAnalytics* instance;
|
||||
|
||||
FDelegateHandle LauncherCallbackHandle;
|
||||
|
||||
float TotalBuildTime;
|
||||
float AndroidPackageTime;
|
||||
bool BuildCompleted;
|
||||
bool UATLaunched;
|
||||
int UserAssetCount;
|
||||
int BuildStepCount;
|
||||
int32 SourceFileCount;
|
||||
int64 SourceFileDirectorySize;
|
||||
|
||||
EBuildStage CurrentBuildStage;
|
||||
FString CurrentBuildPlatform;
|
||||
FString OutputDirectory;
|
||||
};
|
||||
@@ -0,0 +1,624 @@
|
||||
// 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 "IDetailPropertyRow.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 "OculusXRBuildAnalytics.h"
|
||||
#include "OculusXRPTLayerComponentDetailsCustomization.h"
|
||||
#include "OculusXRPassthroughLayerComponent.h"
|
||||
#include "SExternalImageReference.h"
|
||||
#include "AndroidRuntimeSettings.h"
|
||||
#include "SourceControlHelpers.h"
|
||||
#include "Framework/Notifications/NotificationManager.h"
|
||||
#include "Interfaces/IProjectManager.h"
|
||||
#include "Widgets/Notifications/SNotificationList.h"
|
||||
#include "Editor/EditorPerformanceSettings.h"
|
||||
#include "HAL/FileManager.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();
|
||||
|
||||
FPropertyEditorModule& PropertyModule = FModuleManager::LoadModuleChecked<FPropertyEditorModule>("PropertyEditor");
|
||||
PropertyModule.RegisterCustomClassLayout(UOculusXRPassthroughLayerComponent::StaticClass()->GetFName(), FOnGetDetailCustomizationInstance::CreateStatic(&FOculusXRPTLayerComponentDetailsCustomization::MakeInstance));
|
||||
|
||||
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().ToggleIterativeCookOnTheFly,
|
||||
FExecuteAction::CreateLambda([=]() {
|
||||
UOculusXRHMDRuntimeSettings* settings = GetMutableDefault<UOculusXRHMDRuntimeSettings>();
|
||||
settings->bIterativeCookOnTheFly = !settings->bIterativeCookOnTheFly;
|
||||
settings->Modify(true);
|
||||
settings->UpdateSinglePropertyInConfigFile(settings->GetClass()->FindPropertyByName(GET_MEMBER_NAME_CHECKED(UOculusXRHMDRuntimeSettings, bIterativeCookOnTheFly)), settings->GetDefaultConfigFilename());
|
||||
}),
|
||||
|
||||
FCanExecuteAction(),
|
||||
FIsActionChecked::CreateLambda([=]() {
|
||||
return GetMutableDefault<UOculusXRHMDRuntimeSettings>()->bIterativeCookOnTheFly;
|
||||
}));
|
||||
PluginCommands->MapAction(
|
||||
FOculusToolCommands::Get().ToggleMetaXRSim,
|
||||
FExecuteAction::CreateRaw(this, &FOculusXREditorModule::ToggleOpenXRRuntime),
|
||||
FCanExecuteAction(),
|
||||
FIsActionChecked::CreateLambda([=]() {
|
||||
return FOculusXRHMDModule::IsSimulatorActivated();
|
||||
}));
|
||||
|
||||
int32 numRooms = FOculusToolCommands::Get().RoomCommands.Num();
|
||||
for (int ii = 0; ii < numRooms; ++ii)
|
||||
{
|
||||
PluginCommands->MapAction(
|
||||
FOculusToolCommands::Get().RoomCommands[ii],
|
||||
FExecuteAction::CreateLambda([this, ii]() {
|
||||
FOculusXREditorModule::LaunchRoom(ii);
|
||||
}));
|
||||
}
|
||||
|
||||
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::MaybeSpawnTelemetryConsent();
|
||||
|
||||
FOculusBuildAnalytics::GetInstance();
|
||||
|
||||
const OculusXRTelemetry::TScopedMarker<OculusXRTelemetry::Events::FEditorStart> StartEvent;
|
||||
bool bProjectCreatedFromMRTemplate = false;
|
||||
FProjectStatus ProjectStatus;
|
||||
if (IProjectManager::Get().QueryStatusForCurrentProject(ProjectStatus))
|
||||
{
|
||||
bProjectCreatedFromMRTemplate = ProjectStatus.Category == "MetaMRTemplate";
|
||||
}
|
||||
const auto& Annotated = StartEvent.AddAnnotation("created_from_mr_template", bProjectCreatedFromMRTemplate ? "true" : "false");
|
||||
|
||||
// OVRPlugin may not be initialized, we need to check if it is initialized before sending the event.
|
||||
if (FOculusXRHMDModule::GetPluginWrapper().IsInitialized())
|
||||
{
|
||||
FOculusXRHMDModule::GetPluginWrapper().SendEvent2("editor_start", bProjectCreatedFromMRTemplate ? "created_from_mr_template" : "", "integration");
|
||||
}
|
||||
|
||||
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);
|
||||
FOculusBuildAnalytics::Shutdown();
|
||||
}
|
||||
|
||||
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::LaunchRoom(int32 index)
|
||||
{
|
||||
FOculusXRHMDModule::LaunchEnvironment(index);
|
||||
}
|
||||
|
||||
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.AddMenuEntry(FOculusToolCommands::Get().ToggleIterativeCookOnTheFly);
|
||||
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"));
|
||||
for (auto room : FOculusToolCommands::Get().RoomCommands)
|
||||
{
|
||||
MenuBuilder.AddMenuEntry(room);
|
||||
}
|
||||
MenuBuilder.AddMenuEntry(FOculusToolCommands::Get().StopServer);
|
||||
MenuBuilder.EndSection();
|
||||
}
|
||||
|
||||
FOculusXRHMDSettingsDetailsCustomization::FOculusXRHMDSettingsDetailsCustomization()
|
||||
: LaunchImageLandscape(FPlatformIconInfo(TEXT("res/drawable/splashscreen_landscape.png"), LOCTEXT("SystemSplashImage", "System Splash Image"), FText::GetEmpty(), 640, 360, FPlatformIconInfo::Required))
|
||||
, EngineAndroidPath(FPaths::EngineDir() + TEXT("Build/Android/Java"))
|
||||
, GameAndroidPath(FPaths::ProjectDir() + TEXT("Build/Android"))
|
||||
, 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)
|
||||
{
|
||||
static const FName WarningColorStyle("Colors.AccentYellow");
|
||||
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);
|
||||
|
||||
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
|
||||
@@ -0,0 +1,98 @@
|
||||
// Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "IOculusXREditorModule.h"
|
||||
#include "Modules/ModuleInterface.h"
|
||||
#include "IDetailCustomization.h"
|
||||
#include "PlatformIconInfo.h"
|
||||
#include "Input/Reply.h"
|
||||
#include "Layout/Visibility.h"
|
||||
|
||||
class FToolBarBuilder;
|
||||
class FMenuBuilder;
|
||||
|
||||
#define OCULUS_EDITOR_MODULE_NAME "OculusXREditor"
|
||||
|
||||
enum class ECheckBoxState : uint8;
|
||||
|
||||
class FOculusXREditorModule : public IOculusXREditorModule
|
||||
{
|
||||
public:
|
||||
FOculusXREditorModule()
|
||||
: bModuleValid(false){};
|
||||
|
||||
/** IModuleInterface implementation */
|
||||
virtual void StartupModule() override;
|
||||
virtual void ShutdownModule() override;
|
||||
virtual void PostLoadCallback() override;
|
||||
|
||||
void RegisterSettings();
|
||||
void UnregisterSettings();
|
||||
|
||||
void PluginOpenSetupToolWindow();
|
||||
FReply PluginClickFn(bool text);
|
||||
|
||||
void PluginOpenPlatWindow();
|
||||
|
||||
void ToggleOpenXRRuntime();
|
||||
|
||||
void CreateSESSubMenus(FMenuBuilder& MenuBuilder);
|
||||
void StopSESServer();
|
||||
|
||||
void LaunchRoom(int32 roomIndex);
|
||||
|
||||
public:
|
||||
static const FName OculusPlatToolTabName;
|
||||
|
||||
private:
|
||||
void AddToolbarExtension(FToolBarBuilder& Builder);
|
||||
TSharedRef<SWidget> CreateToolbarEntryMenu(TSharedPtr<class FUICommandList> Commands);
|
||||
TSharedRef<SWidget> CreateXrSimToolbarEntryMenu(TSharedPtr<class FUICommandList> Commands);
|
||||
void AddMenuExtension(FMenuBuilder& Builder);
|
||||
|
||||
TSharedRef<class SDockTab> OnSpawnPlatToolTab(const class FSpawnTabArgs& SpawnTabArgs);
|
||||
|
||||
private:
|
||||
TSharedPtr<class FUICommandList> PluginCommands;
|
||||
bool bModuleValid;
|
||||
};
|
||||
|
||||
class IDetailLayoutBuilder;
|
||||
|
||||
class FOculusXRHMDSettingsDetailsCustomization : public IDetailCustomization
|
||||
{
|
||||
private:
|
||||
FOculusXRHMDSettingsDetailsCustomization();
|
||||
|
||||
FPlatformIconInfo LaunchImageLandscape;
|
||||
|
||||
const FString EngineAndroidPath;
|
||||
const FString GameAndroidPath;
|
||||
const FString VRSplashPath;
|
||||
|
||||
IDetailLayoutBuilder* SavedLayoutBuilder;
|
||||
|
||||
public:
|
||||
/** Makes a new instance of this detail layout class for a specific detail view requesting it */
|
||||
static TSharedRef<IDetailCustomization> MakeInstance();
|
||||
|
||||
// IDetailCustomization interface
|
||||
virtual void CustomizeDetails(IDetailLayoutBuilder& DetailLayout) override;
|
||||
// End of IDetailCustomization interface
|
||||
|
||||
EVisibility GetContextualPassthroughWarningVisibility() const;
|
||||
ECheckBoxState GetShowLaunchImageCheckBoxState() const;
|
||||
bool IsLaunchImageEnabled() const;
|
||||
|
||||
void OnShowLaunchImageCheckStateChanged(const ECheckBoxState NewState);
|
||||
bool OnLaunchImageChanged(const FString& InChosenImage);
|
||||
|
||||
EVisibility GetSystemSplashImageWarningVisibility() const;
|
||||
|
||||
FReply PluginClickPerfFn(bool text);
|
||||
FReply PluginClickPlatFn(bool text);
|
||||
FReply DisableEngineSplash(bool text);
|
||||
FReply AddSplashImage(bool text);
|
||||
};
|
||||
@@ -0,0 +1,9 @@
|
||||
// @lint-ignore-every LICENSELINT
|
||||
// Copyright Epic Games, Inc. All Rights Reserved.
|
||||
|
||||
#include "OculusXREditorSettings.h"
|
||||
|
||||
UOculusXREditorSettings::UOculusXREditorSettings()
|
||||
: PerfToolTargetPlatform(EOculusXRPlatform::PC)
|
||||
{
|
||||
}
|
||||
@@ -0,0 +1,380 @@
|
||||
// Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
|
||||
#include "OculusXRMovementAssetsFactories.h"
|
||||
|
||||
#include "AssetToolsModule.h"
|
||||
#include "IAssetTools.h"
|
||||
#include "Kismet2/KismetEditorUtilities.h"
|
||||
|
||||
#include "OculusXRLiveLinkRetargetFaceAsset.h"
|
||||
#include "OculusXRLiveLinkRetargetFaceVisemesAsset.h"
|
||||
#include "OculusXRLiveLinkRetargetBodyAsset.h"
|
||||
|
||||
#define LOCTEXT_NAMESPACE "OculusXRMovementAssetsFactories"
|
||||
|
||||
UOculusXRMetahumanRetargetAssetFactory::UOculusXRMetahumanRetargetAssetFactory(const FObjectInitializer& ObjectInitializer)
|
||||
: Super(ObjectInitializer)
|
||||
{
|
||||
SupportedClass = UBlueprint::StaticClass();
|
||||
|
||||
bCreateNew = true;
|
||||
bEditAfterNew = true;
|
||||
}
|
||||
|
||||
bool UOculusXRMetahumanRetargetAssetFactory::ConfigureProperties()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
uint32 UOculusXRMetahumanRetargetAssetFactory::GetMenuCategories() const
|
||||
{
|
||||
IAssetTools& AssetTools = FModuleManager::LoadModuleChecked<FAssetToolsModule>("AssetTools").Get();
|
||||
return AssetTools.RegisterAdvancedAssetCategory("LiveLink", LOCTEXT("AssetCategoryName", "Live Link"));
|
||||
}
|
||||
|
||||
UObject* UOculusXRMetahumanRetargetAssetFactory::FactoryCreateNew(UClass* Class, UObject* InParent, FName Name, EObjectFlags Flags, UObject* Context, FFeedbackContext* Warn, FName CallingContext)
|
||||
{
|
||||
UBlueprint* RetargetBlueprint = FKismetEditorUtilities::CreateBlueprint(ParentClass, InParent, Name, BlueprintType, UBlueprint::StaticClass(), UBlueprintGeneratedClass::StaticClass(), CallingContext);
|
||||
|
||||
if (const TSubclassOf<UObject> GeneratedClass = RetargetBlueprint->GeneratedClass)
|
||||
{
|
||||
SetDefaults(GeneratedClass);
|
||||
}
|
||||
|
||||
return RetargetBlueprint;
|
||||
}
|
||||
|
||||
UOculusXRMetahumanFaceRetargetAssetFactory::UOculusXRMetahumanFaceRetargetAssetFactory(const FObjectInitializer& ObjectInitializer)
|
||||
: Super(ObjectInitializer)
|
||||
{
|
||||
ParentClass = UOculusXRLiveLinkRetargetFaceAsset::StaticClass();
|
||||
}
|
||||
|
||||
FText UOculusXRMetahumanFaceRetargetAssetFactory::GetDisplayName() const
|
||||
{
|
||||
return LOCTEXT("DisplayNameMetahumanFace", "Face retarget asset for OculusXRMovement and Metahuman");
|
||||
}
|
||||
|
||||
void UOculusXRMetahumanFaceRetargetAssetFactory::SetDefaults(const TSubclassOf<UObject> GeneratedClass) const
|
||||
{
|
||||
if (UOculusXRLiveLinkRetargetFaceAsset* Retargeting = GeneratedClass->GetDefaultObject<UOculusXRLiveLinkRetargetFaceAsset>())
|
||||
{
|
||||
Retargeting->CurveRemapping.Emplace(EOculusXRFaceExpression::BrowLowererL, { "CTRL_expressions_BrowDownL", "CTRL_expressions_BrowLateralL" });
|
||||
Retargeting->CurveRemapping.Emplace(EOculusXRFaceExpression::BrowLowererR, { "CTRL_expressions_BrowDownR", "CTRL_expressions_BrowLateralR" });
|
||||
Retargeting->CurveRemapping.Emplace(EOculusXRFaceExpression::CheekPuffL, { "CTRL_expressions_mouthCheekBlowL" });
|
||||
Retargeting->CurveRemapping.Emplace(EOculusXRFaceExpression::CheekPuffR, { "CTRL_expressions_mouthCheekBlowR" });
|
||||
Retargeting->CurveRemapping.Emplace(EOculusXRFaceExpression::CheekRaiserL, { "CTRL_expressions_eyeCheekRaiseL" });
|
||||
Retargeting->CurveRemapping.Emplace(EOculusXRFaceExpression::CheekRaiserR, { "CTRL_expressions_eyeCheekRaiseR" });
|
||||
Retargeting->CurveRemapping.Emplace(EOculusXRFaceExpression::CheekSuckL, { "CTRL_expressions_mouthCheekSuckL" });
|
||||
Retargeting->CurveRemapping.Emplace(EOculusXRFaceExpression::CheekSuckR, { "CTRL_expressions_mouthCheekSuckR" });
|
||||
Retargeting->CurveRemapping.Emplace(EOculusXRFaceExpression::ChinRaiserB, { "CTRL_expressions_jawChinRaiseDL", "CTRL_expressions_jawChinRaiseDR" });
|
||||
Retargeting->CurveRemapping.Emplace(EOculusXRFaceExpression::ChinRaiserT, { "CTRL_expressions_jawChinRaiseUL", "CTRL_expressions_jawChinRaiseUR" });
|
||||
Retargeting->CurveRemapping.Emplace(EOculusXRFaceExpression::DimplerL, { "CTRL_expressions_mouthDimpleL" });
|
||||
Retargeting->CurveRemapping.Emplace(EOculusXRFaceExpression::DimplerR, { "CTRL_expressions_mouthDimpleR" });
|
||||
Retargeting->CurveRemapping.Emplace(EOculusXRFaceExpression::EyesClosedL, { "CTRL_expressions_eyeBlinkL" });
|
||||
Retargeting->CurveRemapping.Emplace(EOculusXRFaceExpression::EyesClosedR, { "CTRL_expressions_eyeBlinkR" });
|
||||
Retargeting->CurveRemapping.Emplace(EOculusXRFaceExpression::EyesLookDownL, { "CTRL_expressions_eyeLookDownL" });
|
||||
Retargeting->CurveRemapping.Emplace(EOculusXRFaceExpression::EyesLookDownR, { "CTRL_expressions_eyeLookDownR" });
|
||||
Retargeting->CurveRemapping.Emplace(EOculusXRFaceExpression::EyesLookLeftL, { "CTRL_expressions_eyeLookLeftL" });
|
||||
Retargeting->CurveRemapping.Emplace(EOculusXRFaceExpression::EyesLookLeftR, { "CTRL_expressions_eyeLookLeftR" });
|
||||
Retargeting->CurveRemapping.Emplace(EOculusXRFaceExpression::EyesLookRightL, { "CTRL_expressions_eyeLookRightL" });
|
||||
Retargeting->CurveRemapping.Emplace(EOculusXRFaceExpression::EyesLookRightR, { "CTRL_expressions_eyeLookRightR" });
|
||||
Retargeting->CurveRemapping.Emplace(EOculusXRFaceExpression::EyesLookUpL, { "CTRL_expressions_eyeLookUpL" });
|
||||
Retargeting->CurveRemapping.Emplace(EOculusXRFaceExpression::EyesLookUpR, { "CTRL_expressions_eyeLookUpR" });
|
||||
Retargeting->CurveRemapping.Emplace(EOculusXRFaceExpression::InnerBrowRaiserL, { "CTRL_expressions_browRaiseInL" });
|
||||
Retargeting->CurveRemapping.Emplace(EOculusXRFaceExpression::InnerBrowRaiserR, { "CTRL_expressions_browRaiseInR" });
|
||||
Retargeting->CurveRemapping.Emplace(EOculusXRFaceExpression::JawDrop, { "CTRL_expressions_jawOpen" });
|
||||
Retargeting->CurveRemapping.Emplace(EOculusXRFaceExpression::JawSidewaysLeft, { "CTRL_expressions_jawLeft" });
|
||||
Retargeting->CurveRemapping.Emplace(EOculusXRFaceExpression::JawSidewaysRight, { "CTRL_expressions_jawRight" });
|
||||
Retargeting->CurveRemapping.Emplace(EOculusXRFaceExpression::JawThrust, { "CTRL_expressions_jawFwd", "CTRL_expressions_jawBack" });
|
||||
Retargeting->CurveRemapping.Emplace(EOculusXRFaceExpression::LidTightenerL, { "CTRL_expressions_eyeSquintInnerL" });
|
||||
Retargeting->CurveRemapping.Emplace(EOculusXRFaceExpression::LidTightenerR, { "CTRL_expressions_eyeSquintInnerR" });
|
||||
Retargeting->CurveRemapping.Emplace(EOculusXRFaceExpression::LipCornerDepressorL, { "CTRL_expressions_mouthCornerDepressL" });
|
||||
Retargeting->CurveRemapping.Emplace(EOculusXRFaceExpression::LipCornerDepressorR, { "CTRL_expressions_mouthCornerDepressR" });
|
||||
Retargeting->CurveRemapping.Emplace(EOculusXRFaceExpression::LipCornerPullerL, { "CTRL_expressions_mouthCornerPullL" });
|
||||
Retargeting->CurveRemapping.Emplace(EOculusXRFaceExpression::LipCornerPullerR, { "CTRL_expressions_mouthCornerPullR" });
|
||||
Retargeting->CurveRemapping.Emplace(EOculusXRFaceExpression::LipFunnelerLB, { "CTRL_expressions_mouthFunnelDL" });
|
||||
Retargeting->CurveRemapping.Emplace(EOculusXRFaceExpression::LipFunnelerLT, { "CTRL_expressions_mouthFunnelUL" });
|
||||
Retargeting->CurveRemapping.Emplace(EOculusXRFaceExpression::LipFunnelerRB, { "CTRL_expressions_mouthFunnelDR" });
|
||||
Retargeting->CurveRemapping.Emplace(EOculusXRFaceExpression::LipFunnelerRT, { "CTRL_expressions_mouthFunnelUR" });
|
||||
Retargeting->CurveRemapping.Emplace(EOculusXRFaceExpression::LipPressorL, { "CTRL_expressions_mouthLipsPressL" });
|
||||
Retargeting->CurveRemapping.Emplace(EOculusXRFaceExpression::LipPressorR, { "CTRL_expressions_mouthLipsPressR" });
|
||||
Retargeting->CurveRemapping.Emplace(EOculusXRFaceExpression::LipPuckerL, { "CTRL_expressions_mouthLipsPurseDL", "CTRL_expressions_mouthLipsPurseUL" });
|
||||
Retargeting->CurveRemapping.Emplace(EOculusXRFaceExpression::LipPuckerR, { "CTRL_expressions_mouthLipsPurseDR", "CTRL_expressions_mouthLipsPurseUR" });
|
||||
Retargeting->CurveRemapping.Emplace(EOculusXRFaceExpression::LipStretcherL, { "CTRL_expressions_mouthStretchL" });
|
||||
Retargeting->CurveRemapping.Emplace(EOculusXRFaceExpression::LipStretcherR, { "CTRL_expressions_mouthStretchR" });
|
||||
Retargeting->CurveRemapping.Emplace(EOculusXRFaceExpression::LipSuckLB, { "CTRL_expressions_mouthLowerLipBiteL" });
|
||||
Retargeting->CurveRemapping.Emplace(EOculusXRFaceExpression::LipSuckLT, { "CTRL_expressions_mouthUpperLipBiteL" });
|
||||
Retargeting->CurveRemapping.Emplace(EOculusXRFaceExpression::LipSuckRB, { "CTRL_expressions_mouthLowerLipBiteR" });
|
||||
Retargeting->CurveRemapping.Emplace(EOculusXRFaceExpression::LipSuckRT, { "CTRL_expressions_mouthUpperLipBiteR" });
|
||||
Retargeting->CurveRemapping.Emplace(EOculusXRFaceExpression::LipTightenerL, { "CTRL_expressions_mouthLipsTightenDL", "CTRL_expressions_mouthLipsTightenUL" });
|
||||
Retargeting->CurveRemapping.Emplace(EOculusXRFaceExpression::LipTightenerR, { "CTRL_expressions_mouthLipsTightenDR", "CTRL_expressions_mouthLipsTightenUR" });
|
||||
Retargeting->CurveRemapping.Emplace(EOculusXRFaceExpression::LipsToward, { "CTRL_expressions_jawChinRaiseDL", "CTRL_expressions_jawChinRaiseDR", "CTRL_expressions_jawChinRaiseUL", "CTRL_expressions_jawChinRaiseUR" });
|
||||
Retargeting->CurveRemapping.Emplace(EOculusXRFaceExpression::LowerLipDepressorL, { "CTRL_expressions_mouthLowerLipDepressL" });
|
||||
Retargeting->CurveRemapping.Emplace(EOculusXRFaceExpression::LowerLipDepressorR, { "CTRL_expressions_mouthLowerLipDepressR" });
|
||||
Retargeting->CurveRemapping.Emplace(EOculusXRFaceExpression::MouthLeft, { "CTRL_expressions_mouthLeft" });
|
||||
Retargeting->CurveRemapping.Emplace(EOculusXRFaceExpression::MouthRight, { "CTRL_expressions_mouthRight" });
|
||||
Retargeting->CurveRemapping.Emplace(EOculusXRFaceExpression::NoseWrinklerL, { "CTRL_expressions_noseWrinkleL" });
|
||||
Retargeting->CurveRemapping.Emplace(EOculusXRFaceExpression::NoseWrinklerR, { "CTRL_expressions_noseWrinkleR" });
|
||||
Retargeting->CurveRemapping.Emplace(EOculusXRFaceExpression::OuterBrowRaiserL, { "CTRL_expressions_browRaiseOuterL" });
|
||||
Retargeting->CurveRemapping.Emplace(EOculusXRFaceExpression::OuterBrowRaiserR, { "CTRL_expressions_browRaiseOuterR" });
|
||||
Retargeting->CurveRemapping.Emplace(EOculusXRFaceExpression::UpperLidRaiserL, { "CTRL_expressions_eyeUpperLidUpL" });
|
||||
Retargeting->CurveRemapping.Emplace(EOculusXRFaceExpression::UpperLidRaiserR, { "CTRL_expressions_eyeUpperLidUpR" });
|
||||
Retargeting->CurveRemapping.Emplace(EOculusXRFaceExpression::UpperLipRaiserL, { "CTRL_expressions_mouthUpperLipRaiseL" });
|
||||
Retargeting->CurveRemapping.Emplace(EOculusXRFaceExpression::UpperLipRaiserR, { "CTRL_expressions_mouthUpperLipRaiseR" });
|
||||
}
|
||||
}
|
||||
|
||||
UOculusXRFaceVisemesRetargetAssetFactory::UOculusXRFaceVisemesRetargetAssetFactory(const FObjectInitializer& ObjectInitializer)
|
||||
: Super(ObjectInitializer)
|
||||
{
|
||||
ParentClass = UOculusXRLiveLinkRetargetFaceVisemesAsset::StaticClass();
|
||||
}
|
||||
|
||||
FText UOculusXRFaceVisemesRetargetAssetFactory::GetDisplayName() const
|
||||
{
|
||||
return LOCTEXT("DisplayNameMetahumanFace", "Face retarget asset for OculusXRMovement and Viseme based assets");
|
||||
}
|
||||
|
||||
void UOculusXRFaceVisemesRetargetAssetFactory::SetDefaults(const TSubclassOf<UObject> GeneratedClass) const
|
||||
{
|
||||
if (UOculusXRLiveLinkRetargetFaceVisemesAsset* Retargeting = GeneratedClass->GetDefaultObject<UOculusXRLiveLinkRetargetFaceVisemesAsset>())
|
||||
{
|
||||
Retargeting->CurveRemapping.Emplace(EOculusXRFaceVisemesExpression::SIL, { "viseme_sil" });
|
||||
Retargeting->CurveRemapping.Emplace(EOculusXRFaceVisemesExpression::PP, { "viseme_PP" });
|
||||
Retargeting->CurveRemapping.Emplace(EOculusXRFaceVisemesExpression::FF, { "viseme_FF" });
|
||||
Retargeting->CurveRemapping.Emplace(EOculusXRFaceVisemesExpression::TH, { "viseme_TH" });
|
||||
Retargeting->CurveRemapping.Emplace(EOculusXRFaceVisemesExpression::DD, { "viseme_DD" });
|
||||
Retargeting->CurveRemapping.Emplace(EOculusXRFaceVisemesExpression::KK, { "viseme_kk" });
|
||||
Retargeting->CurveRemapping.Emplace(EOculusXRFaceVisemesExpression::CH, { "viseme_CH" });
|
||||
Retargeting->CurveRemapping.Emplace(EOculusXRFaceVisemesExpression::SS, { "viseme_SS" });
|
||||
Retargeting->CurveRemapping.Emplace(EOculusXRFaceVisemesExpression::NN, { "viseme_nn" });
|
||||
Retargeting->CurveRemapping.Emplace(EOculusXRFaceVisemesExpression::RR, { "viseme_RR" });
|
||||
Retargeting->CurveRemapping.Emplace(EOculusXRFaceVisemesExpression::AA, { "viseme_aa" });
|
||||
Retargeting->CurveRemapping.Emplace(EOculusXRFaceVisemesExpression::E, { "viseme_E" });
|
||||
Retargeting->CurveRemapping.Emplace(EOculusXRFaceVisemesExpression::IH, { "viseme_I" });
|
||||
Retargeting->CurveRemapping.Emplace(EOculusXRFaceVisemesExpression::OH, { "viseme_O" });
|
||||
Retargeting->CurveRemapping.Emplace(EOculusXRFaceVisemesExpression::OU, { "viseme_U" });
|
||||
}
|
||||
}
|
||||
|
||||
UOculusXRMetahumanBodyRetargetAssetFactory::UOculusXRMetahumanBodyRetargetAssetFactory(const FObjectInitializer& ObjectInitializer)
|
||||
: Super(ObjectInitializer)
|
||||
{
|
||||
ParentClass = UOculusXRLiveLinkRetargetBodyAsset::StaticClass();
|
||||
}
|
||||
|
||||
FText UOculusXRMetahumanBodyRetargetAssetFactory::GetDisplayName() const
|
||||
{
|
||||
return LOCTEXT("DisplayNameMetahumanBody", "Body retarget asset for OculusXRMovement and Metahuman");
|
||||
}
|
||||
|
||||
void UOculusXRMetahumanBodyRetargetAssetFactory::SetDefaults(const TSubclassOf<UObject> GeneratedClass) const
|
||||
{
|
||||
if (UOculusXRLiveLinkRetargetBodyAsset* Retargeting = GeneratedClass->GetDefaultObject<UOculusXRLiveLinkRetargetBodyAsset>())
|
||||
{
|
||||
Retargeting->BoneRemapping.Emplace(EOculusXRBoneID::BodyRoot, "root");
|
||||
Retargeting->BoneRemapping.Emplace(EOculusXRBoneID::BodyHips, "pelvis");
|
||||
Retargeting->BoneRemapping.Emplace(EOculusXRBoneID::BodySpineLower, "spine_01");
|
||||
Retargeting->BoneRemapping.Emplace(EOculusXRBoneID::BodySpineMiddle, "spine_02");
|
||||
Retargeting->BoneRemapping.Emplace(EOculusXRBoneID::BodySpineUpper, "spine_04");
|
||||
Retargeting->BoneRemapping.Emplace(EOculusXRBoneID::BodyChest, "spine_05");
|
||||
Retargeting->BoneRemapping.Emplace(EOculusXRBoneID::BodyNeck, "neck_02");
|
||||
Retargeting->BoneRemapping.Emplace(EOculusXRBoneID::BodyHead, "head");
|
||||
|
||||
Retargeting->BoneRemapping.Emplace(EOculusXRBoneID::BodyLeftShoulder, "clavicle_l");
|
||||
Retargeting->BoneRemapping.Emplace(EOculusXRBoneID::BodyLeftScapula, NAME_None);
|
||||
Retargeting->BoneRemapping.Emplace(EOculusXRBoneID::BodyLeftArmUpper, "upperarm_l");
|
||||
Retargeting->BoneRemapping.Emplace(EOculusXRBoneID::BodyLeftArmLower, "lowerarm_l");
|
||||
Retargeting->BoneRemapping.Emplace(EOculusXRBoneID::BodyLeftHandWristTwist, NAME_None);
|
||||
|
||||
Retargeting->BoneRemapping.Emplace(EOculusXRBoneID::BodyRightShoulder, "clavicle_r");
|
||||
Retargeting->BoneRemapping.Emplace(EOculusXRBoneID::BodyRightScapula, NAME_None);
|
||||
Retargeting->BoneRemapping.Emplace(EOculusXRBoneID::BodyRightArmUpper, "upperarm_r");
|
||||
Retargeting->BoneRemapping.Emplace(EOculusXRBoneID::BodyRightArmLower, "lowerarm_r");
|
||||
Retargeting->BoneRemapping.Emplace(EOculusXRBoneID::BodyRightHandWristTwist, NAME_None);
|
||||
|
||||
Retargeting->BoneRemapping.Emplace(EOculusXRBoneID::BodyLeftHandPalm, NAME_None);
|
||||
Retargeting->BoneRemapping.Emplace(EOculusXRBoneID::BodyLeftHandWrist, "hand_l");
|
||||
Retargeting->BoneRemapping.Emplace(EOculusXRBoneID::BodyLeftHandThumbMetacarpal, "thumb_01_l");
|
||||
Retargeting->BoneRemapping.Emplace(EOculusXRBoneID::BodyLeftHandThumbProximal, "thumb_02_l");
|
||||
Retargeting->BoneRemapping.Emplace(EOculusXRBoneID::BodyLeftHandThumbDistal, "thumb_03_l");
|
||||
Retargeting->BoneRemapping.Emplace(EOculusXRBoneID::BodyLeftHandThumbTip, NAME_None);
|
||||
Retargeting->BoneRemapping.Emplace(EOculusXRBoneID::BodyLeftHandIndexMetacarpal, "index_metacarpal_l");
|
||||
Retargeting->BoneRemapping.Emplace(EOculusXRBoneID::BodyLeftHandIndexProximal, "index_01_l");
|
||||
Retargeting->BoneRemapping.Emplace(EOculusXRBoneID::BodyLeftHandIndexIntermediate, "index_02_l");
|
||||
Retargeting->BoneRemapping.Emplace(EOculusXRBoneID::BodyLeftHandIndexDistal, "index_03_l");
|
||||
Retargeting->BoneRemapping.Emplace(EOculusXRBoneID::BodyLeftHandIndexTip, NAME_None);
|
||||
Retargeting->BoneRemapping.Emplace(EOculusXRBoneID::BodyLeftHandMiddleMetacarpal, "middle_metacarpal_l");
|
||||
Retargeting->BoneRemapping.Emplace(EOculusXRBoneID::BodyLeftHandMiddleProximal, "middle_01_l");
|
||||
Retargeting->BoneRemapping.Emplace(EOculusXRBoneID::BodyLeftHandMiddleIntermediate, "middle_02_l");
|
||||
Retargeting->BoneRemapping.Emplace(EOculusXRBoneID::BodyLeftHandMiddleDistal, "middle_03_l");
|
||||
Retargeting->BoneRemapping.Emplace(EOculusXRBoneID::BodyLeftHandMiddleTip, NAME_None);
|
||||
Retargeting->BoneRemapping.Emplace(EOculusXRBoneID::BodyLeftHandRingMetacarpal, "ring_metacarpal_l");
|
||||
Retargeting->BoneRemapping.Emplace(EOculusXRBoneID::BodyLeftHandRingProximal, "ring_01_l");
|
||||
Retargeting->BoneRemapping.Emplace(EOculusXRBoneID::BodyLeftHandRingIntermediate, "ring_02_l");
|
||||
Retargeting->BoneRemapping.Emplace(EOculusXRBoneID::BodyLeftHandRingDistal, "ring_03_l");
|
||||
Retargeting->BoneRemapping.Emplace(EOculusXRBoneID::BodyLeftHandRingTip, NAME_None);
|
||||
Retargeting->BoneRemapping.Emplace(EOculusXRBoneID::BodyLeftHandLittleMetacarpal, "pinky_metacarpal_l");
|
||||
Retargeting->BoneRemapping.Emplace(EOculusXRBoneID::BodyLeftHandLittleProximal, "pinky_01_l");
|
||||
Retargeting->BoneRemapping.Emplace(EOculusXRBoneID::BodyLeftHandLittleIntermediate, "pinky_02_l");
|
||||
Retargeting->BoneRemapping.Emplace(EOculusXRBoneID::BodyLeftHandLittleDistal, "pinky_03_l");
|
||||
Retargeting->BoneRemapping.Emplace(EOculusXRBoneID::BodyLeftHandLittleTip, NAME_None);
|
||||
|
||||
Retargeting->BoneRemapping.Emplace(EOculusXRBoneID::BodyRightHandPalm, NAME_None);
|
||||
Retargeting->BoneRemapping.Emplace(EOculusXRBoneID::BodyRightHandWrist, "hand_r");
|
||||
Retargeting->BoneRemapping.Emplace(EOculusXRBoneID::BodyRightHandThumbMetacarpal, "thumb_01_r");
|
||||
Retargeting->BoneRemapping.Emplace(EOculusXRBoneID::BodyRightHandThumbProximal, "thumb_02_r");
|
||||
Retargeting->BoneRemapping.Emplace(EOculusXRBoneID::BodyRightHandThumbDistal, "thumb_03_r");
|
||||
Retargeting->BoneRemapping.Emplace(EOculusXRBoneID::BodyRightHandThumbTip, NAME_None);
|
||||
Retargeting->BoneRemapping.Emplace(EOculusXRBoneID::BodyRightHandIndexMetacarpal, "index_metacarpal_r");
|
||||
Retargeting->BoneRemapping.Emplace(EOculusXRBoneID::BodyRightHandIndexProximal, "index_01_r");
|
||||
Retargeting->BoneRemapping.Emplace(EOculusXRBoneID::BodyRightHandIndexIntermediate, "index_02_r");
|
||||
Retargeting->BoneRemapping.Emplace(EOculusXRBoneID::BodyRightHandIndexDistal, "index_03_r");
|
||||
Retargeting->BoneRemapping.Emplace(EOculusXRBoneID::BodyRightHandIndexTip, NAME_None);
|
||||
Retargeting->BoneRemapping.Emplace(EOculusXRBoneID::BodyRightHandMiddleMetacarpal, "middle_metacarpal_r");
|
||||
Retargeting->BoneRemapping.Emplace(EOculusXRBoneID::BodyRightHandMiddleProximal, "middle_01_r");
|
||||
Retargeting->BoneRemapping.Emplace(EOculusXRBoneID::BodyRightHandMiddleIntermediate, "middle_02_r");
|
||||
Retargeting->BoneRemapping.Emplace(EOculusXRBoneID::BodyRightHandMiddleDistal, "middle_03_r");
|
||||
Retargeting->BoneRemapping.Emplace(EOculusXRBoneID::BodyRightHandMiddleTip, NAME_None);
|
||||
Retargeting->BoneRemapping.Emplace(EOculusXRBoneID::BodyRightHandRingMetacarpal, "ring_metacarpal_r");
|
||||
Retargeting->BoneRemapping.Emplace(EOculusXRBoneID::BodyRightHandRingProximal, "ring_01_r");
|
||||
Retargeting->BoneRemapping.Emplace(EOculusXRBoneID::BodyRightHandRingIntermediate, "ring_02_r");
|
||||
Retargeting->BoneRemapping.Emplace(EOculusXRBoneID::BodyRightHandRingDistal, "ring_03_r");
|
||||
Retargeting->BoneRemapping.Emplace(EOculusXRBoneID::BodyRightHandRingTip, NAME_None);
|
||||
Retargeting->BoneRemapping.Emplace(EOculusXRBoneID::BodyRightHandLittleMetacarpal, "pinky_metacarpal_r");
|
||||
Retargeting->BoneRemapping.Emplace(EOculusXRBoneID::BodyRightHandLittleProximal, "pinky_01_r");
|
||||
Retargeting->BoneRemapping.Emplace(EOculusXRBoneID::BodyRightHandLittleIntermediate, "pinky_02_r");
|
||||
Retargeting->BoneRemapping.Emplace(EOculusXRBoneID::BodyRightHandLittleDistal, "pinky_03_r");
|
||||
Retargeting->BoneRemapping.Emplace(EOculusXRBoneID::BodyRightHandLittleTip, NAME_None);
|
||||
|
||||
Retargeting->BoneRemapping.Emplace(EOculusXRBoneID::BodyLeftUpperLeg, "thigh_l");
|
||||
Retargeting->BoneRemapping.Emplace(EOculusXRBoneID::BodyLeftLowerLeg, "calf_l");
|
||||
Retargeting->BoneRemapping.Emplace(EOculusXRBoneID::BodyLeftFootAnkleTwist, NAME_None);
|
||||
Retargeting->BoneRemapping.Emplace(EOculusXRBoneID::BodyLeftFootAnkle, "foot_l");
|
||||
Retargeting->BoneRemapping.Emplace(EOculusXRBoneID::BodyLeftFootSubtalar, NAME_None);
|
||||
Retargeting->BoneRemapping.Emplace(EOculusXRBoneID::BodyLeftFootTransverse, NAME_None);
|
||||
Retargeting->BoneRemapping.Emplace(EOculusXRBoneID::BodyLeftFootBall, "ball_l");
|
||||
Retargeting->BoneRemapping.Emplace(EOculusXRBoneID::BodyRightUpperLeg, "thigh_r");
|
||||
Retargeting->BoneRemapping.Emplace(EOculusXRBoneID::BodyRightLowerLeg, "calf_r");
|
||||
Retargeting->BoneRemapping.Emplace(EOculusXRBoneID::BodyRightFootAnkleTwist, NAME_None);
|
||||
Retargeting->BoneRemapping.Emplace(EOculusXRBoneID::BodyRightFootAnkle, "foot_r");
|
||||
Retargeting->BoneRemapping.Emplace(EOculusXRBoneID::BodyRightFootSubtalar, NAME_None);
|
||||
Retargeting->BoneRemapping.Emplace(EOculusXRBoneID::BodyRightFootTransverse, NAME_None);
|
||||
Retargeting->BoneRemapping.Emplace(EOculusXRBoneID::BodyRightFootBall, "ball_r");
|
||||
|
||||
{
|
||||
FOculusXRBoneCorrection FromOculusToUnreal;
|
||||
FromOculusToUnreal.RotationOffset.Roll = -90;
|
||||
FromOculusToUnreal.RotationOffset.Yaw = -90;
|
||||
Retargeting->GlobalCorrection = FromOculusToUnreal;
|
||||
}
|
||||
{
|
||||
FOculusXRBoneCorrectionSet Root;
|
||||
Root.Bones.Add(EOculusXRBoneID::BodyRoot);
|
||||
Root.BoneCorrection.RotationOffset.Roll = 90;
|
||||
Retargeting->LocalCorrections.Add(Root);
|
||||
}
|
||||
{
|
||||
FOculusXRBoneCorrectionSet Hips;
|
||||
Hips.Bones.Add(EOculusXRBoneID::BodyHips);
|
||||
Hips.BoneCorrection.RotationOffset.Yaw = 5;
|
||||
Retargeting->LocalCorrections.Add(Hips);
|
||||
}
|
||||
{
|
||||
FOculusXRBoneCorrectionSet SpineLowerPart;
|
||||
SpineLowerPart.Bones.Add(EOculusXRBoneID::BodySpineLower);
|
||||
SpineLowerPart.Bones.Add(EOculusXRBoneID::BodySpineMiddle);
|
||||
SpineLowerPart.BoneCorrection.RotationOffset.Yaw = 10;
|
||||
Retargeting->LocalCorrections.Add(SpineLowerPart);
|
||||
}
|
||||
{
|
||||
FOculusXRBoneCorrectionSet SpineUpperPart;
|
||||
SpineUpperPart.Bones.Add(EOculusXRBoneID::BodySpineUpper);
|
||||
SpineUpperPart.BoneCorrection.PositionOffset.Y = 3;
|
||||
SpineUpperPart.BoneCorrection.RotationOffset.Yaw = -5;
|
||||
Retargeting->LocalCorrections.Add(SpineUpperPart);
|
||||
}
|
||||
{
|
||||
FOculusXRBoneCorrectionSet Chest;
|
||||
Chest.Bones.Add(EOculusXRBoneID::BodyChest);
|
||||
Chest.BoneCorrection.PositionOffset.Y = 3;
|
||||
Chest.BoneCorrection.RotationOffset.Yaw = -5;
|
||||
Retargeting->LocalCorrections.Add(Chest);
|
||||
}
|
||||
{
|
||||
FOculusXRBoneCorrectionSet Head;
|
||||
Head.Bones.Add(EOculusXRBoneID::BodyHead);
|
||||
Head.Bones.Add(EOculusXRBoneID::BodyNeck);
|
||||
Head.BoneCorrection.PositionOffset.Y = -3;
|
||||
Head.BoneCorrection.RotationOffset.Yaw = 5;
|
||||
Retargeting->LocalCorrections.Add(Head);
|
||||
}
|
||||
{
|
||||
FOculusXRBoneCorrectionSet LeftShoulder;
|
||||
LeftShoulder.Bones.Add(EOculusXRBoneID::BodyLeftShoulder);
|
||||
LeftShoulder.BoneCorrection.RotationOffset.Pitch = -5;
|
||||
LeftShoulder.BoneCorrection.RotationOffset.Yaw = 30;
|
||||
LeftShoulder.BoneCorrection.PositionOffset.X = 5;
|
||||
LeftShoulder.BoneCorrection.PositionOffset.Y = -6;
|
||||
Retargeting->LocalCorrections.Add(LeftShoulder);
|
||||
}
|
||||
{
|
||||
FOculusXRBoneCorrectionSet RightShoulder;
|
||||
RightShoulder.Bones.Add(EOculusXRBoneID::BodyRightShoulder);
|
||||
RightShoulder.BoneCorrection.RotationOffset.Pitch = -5;
|
||||
RightShoulder.BoneCorrection.RotationOffset.Yaw = 30;
|
||||
RightShoulder.BoneCorrection.PositionOffset.X = -6;
|
||||
RightShoulder.BoneCorrection.PositionOffset.Y = 5;
|
||||
Retargeting->LocalCorrections.Add(RightShoulder);
|
||||
}
|
||||
{
|
||||
FOculusXRBoneCorrectionSet Hands;
|
||||
for (uint8 BoneId = static_cast<uint8>(EOculusXRBoneID::BodyLeftHandPalm); BoneId <= static_cast<uint8>(EOculusXRBoneID::BodyRightHandLittleTip); ++BoneId)
|
||||
{
|
||||
Hands.Bones.Emplace(static_cast<EOculusXRBoneID>(BoneId));
|
||||
}
|
||||
Hands.BoneCorrection.RotationOffset.Roll = 180;
|
||||
Retargeting->LocalCorrections.Add(Hands);
|
||||
}
|
||||
{
|
||||
FOculusXRBoneCorrectionSet Legs;
|
||||
Legs.Bones.Add(EOculusXRBoneID::BodyLeftUpperLeg);
|
||||
Legs.Bones.Add(EOculusXRBoneID::BodyLeftLowerLeg);
|
||||
Legs.Bones.Add(EOculusXRBoneID::BodyRightUpperLeg);
|
||||
Legs.Bones.Add(EOculusXRBoneID::BodyRightLowerLeg);
|
||||
Legs.BoneCorrection.RotationOffset.Yaw = 180;
|
||||
Retargeting->LocalCorrections.Add(Legs);
|
||||
}
|
||||
{
|
||||
FOculusXRBoneCorrectionSet FootAnkles;
|
||||
FootAnkles.Bones.Add(EOculusXRBoneID::BodyLeftFootAnkle);
|
||||
FootAnkles.Bones.Add(EOculusXRBoneID::BodyRightFootAnkle);
|
||||
FootAnkles.BoneCorrection.RotationOffset.Roll = 180;
|
||||
FootAnkles.BoneCorrection.RotationOffset.Pitch = 175;
|
||||
FootAnkles.BoneCorrection.RotationOffset.Yaw = -80;
|
||||
Retargeting->LocalCorrections.Add(FootAnkles);
|
||||
}
|
||||
{
|
||||
FOculusXRBoneCorrectionSet FootBalls;
|
||||
FootBalls.Bones.Add(EOculusXRBoneID::BodyLeftFootBall);
|
||||
FootBalls.BoneCorrection.RotationOffset.Yaw = 200;
|
||||
FootBalls.BoneCorrection.PositionOffset.Y = -5;
|
||||
FootBalls.BoneCorrection.PositionOffset.Z = 1;
|
||||
Retargeting->LocalCorrections.Add(FootBalls);
|
||||
}
|
||||
{
|
||||
FOculusXRBoneCorrectionSet FootBalls;
|
||||
FootBalls.Bones.Add(EOculusXRBoneID::BodyRightFootBall);
|
||||
FootBalls.BoneCorrection.RotationOffset.Yaw = 200;
|
||||
FootBalls.BoneCorrection.PositionOffset.Y = 5;
|
||||
FootBalls.BoneCorrection.PositionOffset.Z = -1;
|
||||
Retargeting->LocalCorrections.Add(FootBalls);
|
||||
}
|
||||
|
||||
Retargeting->RetargetingMode = EOculusXRRetargetingMode::RotationsPlusHips;
|
||||
Retargeting->ForwardMesh = EOculusXRAxis::Y;
|
||||
}
|
||||
}
|
||||
|
||||
#undef LOCTEXT_NAMESPACE
|
||||
@@ -0,0 +1,62 @@
|
||||
// Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "Factories/BlueprintFactory.h"
|
||||
|
||||
#include "OculusXRMovementAssetsFactories.generated.h"
|
||||
|
||||
UCLASS(Abstract, hidecategories = Object, MinimalAPI)
|
||||
class UOculusXRMetahumanRetargetAssetFactory : public UBlueprintFactory
|
||||
{
|
||||
GENERATED_BODY()
|
||||
public:
|
||||
UOculusXRMetahumanRetargetAssetFactory(const FObjectInitializer& ObjectInitializer);
|
||||
|
||||
virtual bool ConfigureProperties() override;
|
||||
virtual UObject* FactoryCreateNew(UClass* Class, UObject* InParent, FName Name, EObjectFlags Flags, UObject* Context, FFeedbackContext* Warn, FName CallingContext) override;
|
||||
virtual uint32 GetMenuCategories() const override;
|
||||
|
||||
protected:
|
||||
virtual void SetDefaults(const TSubclassOf<UObject> GeneratedClass) const PURE_VIRTUAL(UOculusXRMetahumanRetargetAssetFactory::SetDefaults, );
|
||||
};
|
||||
|
||||
UCLASS(hidecategories = Object, MinimalAPI)
|
||||
class UOculusXRMetahumanFaceRetargetAssetFactory : public UOculusXRMetahumanRetargetAssetFactory
|
||||
{
|
||||
GENERATED_BODY()
|
||||
public:
|
||||
UOculusXRMetahumanFaceRetargetAssetFactory(const FObjectInitializer& ObjectInitializer);
|
||||
|
||||
virtual FText GetDisplayName() const override;
|
||||
|
||||
protected:
|
||||
virtual void SetDefaults(const TSubclassOf<UObject> GeneratedClass) const override;
|
||||
};
|
||||
|
||||
UCLASS(hidecategories = Object, MinimalAPI)
|
||||
class UOculusXRFaceVisemesRetargetAssetFactory : public UOculusXRMetahumanRetargetAssetFactory
|
||||
{
|
||||
GENERATED_BODY()
|
||||
public:
|
||||
UOculusXRFaceVisemesRetargetAssetFactory(const FObjectInitializer& ObjectInitializer);
|
||||
|
||||
virtual FText GetDisplayName() const override;
|
||||
|
||||
protected:
|
||||
virtual void SetDefaults(const TSubclassOf<UObject> GeneratedClass) const override;
|
||||
};
|
||||
|
||||
UCLASS(hidecategories = Object, MinimalAPI)
|
||||
class UOculusXRMetahumanBodyRetargetAssetFactory : public UOculusXRMetahumanRetargetAssetFactory
|
||||
{
|
||||
GENERATED_BODY()
|
||||
public:
|
||||
UOculusXRMetahumanBodyRetargetAssetFactory(const FObjectInitializer& ObjectInitializer);
|
||||
|
||||
virtual FText GetDisplayName() const override;
|
||||
|
||||
protected:
|
||||
virtual void SetDefaults(const TSubclassOf<UObject> GeneratedClass) const override;
|
||||
};
|
||||
@@ -0,0 +1,93 @@
|
||||
// Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
|
||||
#include "OculusXRPTLayerComponentDetailsCustomization.h"
|
||||
#include "OculusXRPassthroughLayerComponent.h"
|
||||
#include "Components/StereoLayerComponent.h"
|
||||
#include "DetailWidgetRow.h"
|
||||
#include "PropertyRestriction.h"
|
||||
#include "DetailLayoutBuilder.h"
|
||||
#include "UObject/Field.h"
|
||||
#include "Widgets/Text/STextBlock.h"
|
||||
|
||||
#define LOCTEXT_NAMESPACE "OculusXREditor"
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// FOculusXRPTLayerComponentDetailsCustomization
|
||||
|
||||
TSharedRef<IDetailCustomization> FOculusXRPTLayerComponentDetailsCustomization::MakeInstance()
|
||||
{
|
||||
return MakeShareable(new FOculusXRPTLayerComponentDetailsCustomization);
|
||||
}
|
||||
|
||||
void FOculusXRPTLayerComponentDetailsCustomization::CustomizeDetails(IDetailLayoutBuilder& DetailBuilder)
|
||||
{
|
||||
TArray<FName> Categories;
|
||||
DetailBuilder.GetCategoryNames(Categories);
|
||||
for (FName CategoryName : Categories)
|
||||
{
|
||||
IDetailCategoryBuilder& CategoryBuilder = DetailBuilder.EditCategory(CategoryName, FText::GetEmpty(), ECategoryPriority::Important);
|
||||
|
||||
TArray<TSharedRef<IPropertyHandle>> DefaultProperties;
|
||||
CategoryBuilder.GetDefaultProperties(DefaultProperties);
|
||||
|
||||
for (TSharedRef<IPropertyHandle> PropertyHandle : DefaultProperties)
|
||||
{
|
||||
if (PropertyHandle->GetProperty()->GetName() == FName("Shape"))
|
||||
{
|
||||
ShapePropertyHandle = PropertyHandle;
|
||||
|
||||
static const FName WarningColorStyle("Colors.AccentYellow");
|
||||
/* clang-format off */
|
||||
CategoryBuilder.AddCustomRow(LOCTEXT("OculusXRPTComponentShapeWarning", "Warning for UOculusXRPassthroughLayerComponent::Shape property"))
|
||||
.Visibility(TAttribute<EVisibility>(this, &FOculusXRPTLayerComponentDetailsCustomization::GetShapeWarningVisibility))
|
||||
[
|
||||
SNew(SVerticalBox)
|
||||
+ SVerticalBox::Slot().FillHeight(1.f).VAlign(EVerticalAlignment::VAlign_Center)
|
||||
[
|
||||
SNew(STextBlock)
|
||||
.Font(IDetailLayoutBuilder::GetDetailFont())
|
||||
.AutoWrapText(true)
|
||||
.Justification(ETextJustify::Center)
|
||||
.Text(TAttribute<FText>(this, &FOculusXRPTLayerComponentDetailsCustomization::GetShapeWarningText))
|
||||
.ColorAndOpacity(FAppStyle::Get().GetSlateColor(WarningColorStyle))
|
||||
]
|
||||
];
|
||||
/* clang-format on */
|
||||
}
|
||||
|
||||
IDetailPropertyRow& Property = CategoryBuilder.AddProperty(PropertyHandle);
|
||||
Property.Visibility(TAttribute<EVisibility>::CreateLambda([PropertyHandle]() -> EVisibility {
|
||||
return PropertyHandle->IsEditConst() ? EVisibility::Hidden : EVisibility::Visible;
|
||||
}));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
EVisibility FOculusXRPTLayerComponentDetailsCustomization::GetShapeWarningVisibility() const
|
||||
{
|
||||
UObject* Shape = nullptr;
|
||||
ShapePropertyHandle->GetValue(Shape);
|
||||
|
||||
if (!IsValid(Shape) || Shape->IsA<UOculusXRStereoLayerShapeUserDefined>())
|
||||
return EVisibility::Collapsed;
|
||||
else
|
||||
return EVisibility::Visible;
|
||||
}
|
||||
|
||||
FText FOculusXRPTLayerComponentDetailsCustomization::GetShapeWarningText() const
|
||||
{
|
||||
UObject* Shape = nullptr;
|
||||
ShapePropertyHandle->GetValue(Shape);
|
||||
|
||||
if (!IsValid(Shape) || Shape->IsA<UOculusXRStereoLayerShapeUserDefined>())
|
||||
return FText::GetEmpty();
|
||||
else if (Shape->IsA<UOculusXRStereoLayerShapeReconstructed>())
|
||||
return LOCTEXT("OculusXRPTComponentShapeWarningText_Reconstructed",
|
||||
"If you wish to use the Reconstructed Passthrough Layer shape, the recommended method is to use the passthrough subsystem.\nFrom blueprint, call the \"Passthrough Subsytem->Initialize Persistent Passthrough\" node on startup instead of using this component.");
|
||||
else
|
||||
return FText::Format(LOCTEXT("OculusXRPTComponentShapeWarningText", "Please use a Shape class supporting passthrough with this component.\nIf you wish to continue using {0}, consider a Stereo Layer component instead"), FText::FromString(Shape->GetClass()->GetName()));
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#undef LOCTEXT_NAMESPACE
|
||||
@@ -0,0 +1,25 @@
|
||||
// Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "PropertyHandle.h"
|
||||
#include "IDetailCustomization.h"
|
||||
|
||||
class IDetailLayoutBuilder;
|
||||
|
||||
class FOculusXRPTLayerComponentDetailsCustomization : public IDetailCustomization
|
||||
{
|
||||
public:
|
||||
/** Makes a new instance of this detail layout class for a specific detail view requesting it */
|
||||
static TSharedRef<IDetailCustomization> MakeInstance();
|
||||
|
||||
// IDetailCustomization interface
|
||||
virtual void CustomizeDetails(IDetailLayoutBuilder& DetailLayout) override;
|
||||
// End of IDetailCustomization interface
|
||||
|
||||
EVisibility GetShapeWarningVisibility() const;
|
||||
FText GetShapeWarningText() const;
|
||||
|
||||
private:
|
||||
TSharedPtr<IPropertyHandle> ShapePropertyHandle;
|
||||
};
|
||||
@@ -0,0 +1,59 @@
|
||||
// Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
|
||||
#include "OculusXRPassthroughColorLutAsset.h"
|
||||
#include "AssetTypeCategories.h"
|
||||
#include "UObject/ObjectMacros.h"
|
||||
#include "UObject/Object.h"
|
||||
#include "OculusXRPassthroughColorLut.h"
|
||||
|
||||
#define LOCTEXT_NAMESPACE "AssetTypeActions"
|
||||
|
||||
FText FAssetTypeActions_OculusXRPassthroughColorLut::GetName() const
|
||||
{
|
||||
return NSLOCTEXT("AssetTypeActions", "AssetTypeActions_PassthroughColorLUT", "PassthroughColorLUT");
|
||||
}
|
||||
|
||||
FColor FAssetTypeActions_OculusXRPassthroughColorLut::GetTypeColor() const
|
||||
{
|
||||
return FColor(100, 100, 100);
|
||||
}
|
||||
|
||||
const TArray<FText>& FAssetTypeActions_OculusXRPassthroughColorLut::GetSubMenus() const
|
||||
{
|
||||
static const TArray<FText> SubMenus{
|
||||
LOCTEXT("AssetOculusXRPassthroughColorLutSubMenu", "OculusXR")
|
||||
};
|
||||
|
||||
return SubMenus;
|
||||
}
|
||||
|
||||
UClass* FAssetTypeActions_OculusXRPassthroughColorLut::GetSupportedClass() const
|
||||
{
|
||||
return UOculusXRPassthroughColorLut::StaticClass();
|
||||
}
|
||||
|
||||
uint32 FAssetTypeActions_OculusXRPassthroughColorLut::GetCategories()
|
||||
{
|
||||
return EAssetTypeCategories::Misc;
|
||||
}
|
||||
|
||||
UOculusXRPassthroughColorLutFactory::UOculusXRPassthroughColorLutFactory(const FObjectInitializer& ObjectInitializer)
|
||||
: Super(ObjectInitializer)
|
||||
{
|
||||
SupportedClass = UOculusXRPassthroughColorLut::StaticClass();
|
||||
|
||||
bCreateNew = true;
|
||||
bEditAfterNew = true;
|
||||
}
|
||||
|
||||
UObject* UOculusXRPassthroughColorLutFactory::FactoryCreateNew(UClass* Class, UObject* InParent, FName Name, EObjectFlags Flags, UObject* Context,
|
||||
FFeedbackContext* Warn)
|
||||
{
|
||||
return NewObject<UOculusXRPassthroughColorLut>(InParent, Name, Flags);
|
||||
}
|
||||
|
||||
uint32 UOculusXRPassthroughColorLutFactory::GetMenuCategories() const
|
||||
{
|
||||
return EAssetTypeCategories::Misc;
|
||||
}
|
||||
#undef LOCTEXT_NAMESPACE
|
||||
@@ -0,0 +1,33 @@
|
||||
// Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "Factories/Factory.h"
|
||||
#include "AssetTypeActions_Base.h"
|
||||
|
||||
#include "OculusXRPassthroughColorLutAsset.generated.h"
|
||||
|
||||
class FAssetTypeActions_OculusXRPassthroughColorLut : public FAssetTypeActions_Base
|
||||
{
|
||||
public:
|
||||
virtual FText GetName() const override;
|
||||
virtual FColor GetTypeColor() const override;
|
||||
virtual const TArray<FText>& GetSubMenus() const override;
|
||||
virtual UClass* GetSupportedClass() const override;
|
||||
virtual uint32 GetCategories() override;
|
||||
};
|
||||
|
||||
UCLASS(hidecategories = Object, MinimalAPI)
|
||||
class UOculusXRPassthroughColorLutFactory : public UFactory
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
public:
|
||||
UOculusXRPassthroughColorLutFactory(const FObjectInitializer& ObjectInitializer);
|
||||
|
||||
virtual UObject* FactoryCreateNew(UClass* Class, UObject* InParent, FName Name, EObjectFlags Flags, UObject* Context,
|
||||
FFeedbackContext* Warn) override;
|
||||
|
||||
virtual uint32 GetMenuCategories() const override;
|
||||
};
|
||||
@@ -0,0 +1,25 @@
|
||||
// @lint-ignore-every LICENSELINT
|
||||
// Copyright Epic Games, Inc. All Rights Reserved.
|
||||
|
||||
#include "OculusXRPlatformToolSettings.h"
|
||||
|
||||
UOculusXRPlatformToolSettings::UOculusXRPlatformToolSettings()
|
||||
: OculusTargetPlatform(EOculusXRPlatformTarget::Rift)
|
||||
{
|
||||
uint8 NumPlatforms = (uint8)EOculusXRPlatformTarget::Length;
|
||||
OculusApplicationID.Init("", NumPlatforms);
|
||||
OculusApplicationToken.Init("", NumPlatforms);
|
||||
OculusReleaseChannel.Init("Alpha", NumPlatforms);
|
||||
OculusReleaseNote.Init("", NumPlatforms);
|
||||
OculusLaunchFilePath.Init("", NumPlatforms);
|
||||
OculusSymbolDirPath.Init("", NumPlatforms);
|
||||
OculusLanguagePacksPath.Init("", NumPlatforms);
|
||||
OculusExpansionFilesPath.Init("", NumPlatforms);
|
||||
OculusAssetConfigs.Init(FOculusXRAssetConfigArray(), NumPlatforms);
|
||||
UploadDebugSymbols = true;
|
||||
|
||||
for (int i = 0; i < NumPlatforms; i++)
|
||||
{
|
||||
OculusAssetConfigs[i].ConfigArray = TArray<FOculusXRAssetConfig>();
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,223 @@
|
||||
// @lint-ignore-every LICENSELINT
|
||||
// Copyright Epic Games, Inc. All Rights Reserved.
|
||||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "OculusXRPlatformToolSettings.h"
|
||||
#include "Widgets/SWidget.h"
|
||||
#include "Widgets/SCompoundWidget.h"
|
||||
#include "Widgets/DeclarativeSyntaxSupport.h"
|
||||
#include "Widgets/Input/SEditableTextBox.h"
|
||||
#include "Widgets/Input/SMultiLineEditableTextBox.h"
|
||||
#include "Widgets/Input/SComboBox.h"
|
||||
#include "Widgets/Input/STextComboBox.h"
|
||||
#include "Widgets/Layout/SScrollBox.h"
|
||||
#include "Widgets/Input/SButton.h"
|
||||
#include "Widgets/Input/SCheckBox.h"
|
||||
#include "Engine/PostProcessVolume.h"
|
||||
#include "Framework/Text/SlateHyperlinkRun.h"
|
||||
#include "HttpModule.h"
|
||||
#include "HttpManager.h"
|
||||
#include "Interfaces/IHttpResponse.h"
|
||||
#include "Async/AsyncWork.h"
|
||||
#include "HAL/Event.h"
|
||||
#include "HAL/ThreadSafeBool.h"
|
||||
#include "OculusXRPluginWrapper.h"
|
||||
#include "Brushes/SlateDynamicImageBrush.h"
|
||||
|
||||
class SOculusPlatformToolWidget;
|
||||
|
||||
// Function Delegates
|
||||
DECLARE_DELEGATE_OneParam(FEnableUploadButtonDel, bool);
|
||||
DECLARE_DELEGATE_OneParam(FUpdateLogTextDel, FString);
|
||||
DECLARE_DELEGATE_OneParam(FSetProcessDel, FProcHandle);
|
||||
DECLARE_DELEGATE_RetVal_TwoParams(bool, FFieldValidatorDel, FString, FString&);
|
||||
|
||||
class SOculusPlatformToolWidget : public SCompoundWidget
|
||||
{
|
||||
public:
|
||||
typedef void (SOculusPlatformToolWidget::*PTextComboBoxDel)(TSharedPtr<FString>, ESelectInfo::Type);
|
||||
typedef void (SOculusPlatformToolWidget::*PTextComittedDel)(const FText&, ETextCommit::Type);
|
||||
typedef FReply (SOculusPlatformToolWidget::*PButtonClickedDel)();
|
||||
typedef bool (SOculusPlatformToolWidget::*PFieldValidatorDel)(FString, FString&);
|
||||
typedef void (SOculusPlatformToolWidget::*PCheckBoxChangedDel)(ECheckBoxState);
|
||||
|
||||
SLATE_BEGIN_ARGS(SOculusPlatformToolWidget)
|
||||
{
|
||||
}
|
||||
SLATE_END_ARGS();
|
||||
|
||||
SOculusPlatformToolWidget();
|
||||
void Construct(const FArguments& InArgs);
|
||||
virtual void Tick(const FGeometry& AllottedGeometry, const double InCurrentTime, const float InDeltaTime) override;
|
||||
|
||||
static FString LogText;
|
||||
|
||||
private:
|
||||
TSharedPtr<SMultiLineEditableTextBox> ToolConsoleLog;
|
||||
TSharedPtr<SVerticalBox> GeneralSettingsBox;
|
||||
TSharedPtr<SHorizontalBox> ButtonToolbar;
|
||||
TSharedPtr<SVerticalBox> OptionalSettings;
|
||||
TSharedPtr<SVerticalBox> ExpansionFilesSettings;
|
||||
TSharedPtr<FSlateDynamicImageBrush> ODHIconDynamicImageBrush;
|
||||
|
||||
UEnum* PlatformEnum;
|
||||
UEnum* GamepadEmulationEnum;
|
||||
UEnum* AssetTypeEnum;
|
||||
UOculusXRPlatformToolSettings* PlatformSettings;
|
||||
TArray<TSharedPtr<FString>> OculusPlatforms;
|
||||
TArray<TSharedPtr<FString>> RiftGamepadEmulation;
|
||||
TArray<TSharedPtr<FString>> AssetType;
|
||||
|
||||
bool Options2DCollapsed;
|
||||
bool OptionsRedistPackagesCollapsed;
|
||||
bool ActiveUploadButton;
|
||||
bool RequestUploadButtonActive;
|
||||
FProcHandle PlatformProcess;
|
||||
FThreadSafeBool LogTextUpdated;
|
||||
|
||||
FEnableUploadButtonDel EnableUploadButtonDel;
|
||||
FUpdateLogTextDel UpdateLogTextDel;
|
||||
FSetProcessDel SetProcessDel;
|
||||
|
||||
// Callbacks
|
||||
FReply OnStartPlatformUpload();
|
||||
FReply OnSelectRiftBuildDirectory();
|
||||
FReply OnClearRiftBuildDirectory();
|
||||
FReply OnSelectLaunchFilePath();
|
||||
FReply OnClearLaunchFilePath();
|
||||
FReply OnSelectSymbolDirPath();
|
||||
FReply OnClearSymbolDirPath();
|
||||
FReply OnSelect2DLaunchPath();
|
||||
FReply OnClear2DLaunchPath();
|
||||
FReply OnCancelUpload();
|
||||
FReply OnSelectLanguagePacksPath();
|
||||
FReply OnClearLanguagePacksPath();
|
||||
FReply OnSelectExpansionFilesPath();
|
||||
FReply OnClearExpansionFilesPath();
|
||||
|
||||
FString GenerateSymbolPath();
|
||||
|
||||
void OnPlatformSettingChanged(TSharedPtr<FString> ItemSelected, ESelectInfo::Type SelectInfo);
|
||||
void OnApplicationIDChanged(const FText& InText, ETextCommit::Type InCommitType);
|
||||
void OnApplicationTokenChanged(const FText& InText, ETextCommit::Type InCommitType);
|
||||
void OnReleaseChannelChanged(const FText& InText, ETextCommit::Type InCommitType);
|
||||
void OnReleaseNoteChanged(const FText& InText, ETextCommit::Type InCommitType);
|
||||
void OnRiftBuildVersionChanged(const FText& InText, ETextCommit::Type InCommitType);
|
||||
void OnRiftLaunchParamsChanged(const FText& InText, ETextCommit::Type InCommitType);
|
||||
void OnRiftFirewallChanged(ECheckBoxState CheckState);
|
||||
void OnRedistPackageStateChanged(ECheckBoxState CheckState, FOculusXRRedistPackage* Package);
|
||||
void OnRiftGamepadEmulationChanged(TSharedPtr<FString> ItemSelected, ESelectInfo::Type SelectInfo);
|
||||
void On2DLaunchParamsChanged(const FText& InText, ETextCommit::Type InCommitType);
|
||||
void On2DOptionsExpanded(bool bExpanded);
|
||||
void OnRedistPackagesExpanded(bool bExpanded);
|
||||
void OnAssetConfigRequiredChanged(ECheckBoxState CheckState, int i);
|
||||
void OnAssetConfigTypeChanged(TSharedPtr<FString> ItemSelected, ESelectInfo::Type SelectInfo, int i);
|
||||
void OnAssetConfigSKUChanged(const FText& InText, ETextCommit::Type InCommitType, int i);
|
||||
void OnUploadDebugSymbolsChanged(ECheckBoxState CheckState);
|
||||
void OnDebugSymbolsOnlyChanged(ECheckBoxState CheckState);
|
||||
void OnBuildIDChanged(const FText& InText, ETextCommit::Type InCommitType);
|
||||
|
||||
// UI Constructors
|
||||
void BuildGeneralSettingsBox(TSharedPtr<SVerticalBox> box);
|
||||
void BuildTextComboBoxField(TSharedPtr<SVerticalBox> box, FText name, TArray<TSharedPtr<FString>>* options, TSharedPtr<FString> current, PTextComboBoxDel deleg, int32 indentAmount = 0);
|
||||
void BuildTextField(TSharedPtr<SVerticalBox> box, FText name, FText text, FText tooltip, PTextComittedDel deleg, bool isPassword = false, int32 indentAmount = 0);
|
||||
void BuildFileDirectoryField(TSharedPtr<SVerticalBox> box, FText name, FText path, FText tooltip, PButtonClickedDel deleg, PButtonClickedDel clearDeleg, int32 indentAmount = 0);
|
||||
void BuildCheckBoxField(TSharedPtr<SVerticalBox> box, FText name, bool check, FText tooltip, PCheckBoxChangedDel deleg, int32 indentAmount = 0);
|
||||
void BuildButtonToolbar(TSharedPtr<SHorizontalBox> box);
|
||||
void BuildRiftOptionalFields(TSharedPtr<SVerticalBox> area);
|
||||
void BuildRedistPackagesBox(TSharedPtr<SVerticalBox> box);
|
||||
void BuildExpansionFileBox(TSharedPtr<SVerticalBox> box);
|
||||
void BuildAssetConfigBox(TSharedPtr<SVerticalBox> box, FOculusXRAssetConfig config, int index);
|
||||
|
||||
// Text Field Validators
|
||||
void ValidateTextField(PFieldValidatorDel del, FString text, FString name, bool& success);
|
||||
bool GenericFieldValidator(FString text, FString& error);
|
||||
bool IDFieldValidator(FString text, FString& error);
|
||||
bool DirectoryFieldValidator(FString text, FString& error);
|
||||
bool FileFieldValidator(FString text, FString& error);
|
||||
bool LaunchParamValidator(FString text, FString& error);
|
||||
|
||||
bool ConstructArguments(FString& args);
|
||||
bool ConstructDebugSymbolArguments(FString& args);
|
||||
void EnableUploadButton(bool enabled);
|
||||
void LoadConfigSettings();
|
||||
void UpdateLogText(FString text);
|
||||
void SetPlatformProcess(FProcHandle proc);
|
||||
void LoadRedistPackages();
|
||||
};
|
||||
|
||||
class FPlatformDownloadTask : public FNonAbandonableTask
|
||||
{
|
||||
friend class FAsyncTask<FPlatformDownloadTask>;
|
||||
|
||||
private:
|
||||
FUpdateLogTextDel UpdateLogText;
|
||||
FString ToolConsoleLog;
|
||||
FEvent* downloadCompleteEvent;
|
||||
FEvent* SaveCompleteEvent;
|
||||
TArray<uint8> httpData;
|
||||
|
||||
public:
|
||||
FPlatformDownloadTask(FUpdateLogTextDel textDel, FEvent* saveEvent);
|
||||
|
||||
void OnDownloadRequestComplete(FHttpRequestPtr HttpRequest, FHttpResponsePtr HttpResponse, bool bSucceeded);
|
||||
void OnRequestDownloadProgress64(FHttpRequestPtr HttpRequest, uint64 BytesSend, uint64 InBytesReceived);
|
||||
void OnRequestDownloadProgress(FHttpRequestPtr HttpRequest, int32 BytesSend, int32 InBytesReceived);
|
||||
|
||||
protected:
|
||||
void DoWork();
|
||||
void UpdateProgressLog(int progress);
|
||||
|
||||
FORCEINLINE TStatId GetStatId() const
|
||||
{
|
||||
RETURN_QUICK_DECLARE_CYCLE_STAT(FPlatformDownloadTask, STATGROUP_ThreadPoolAsyncTasks);
|
||||
}
|
||||
};
|
||||
|
||||
class FPlatformUploadTask : public FNonAbandonableTask
|
||||
{
|
||||
friend class FAsyncTask<FPlatformUploadTask>;
|
||||
|
||||
public:
|
||||
FPlatformUploadTask(FString args, FEnableUploadButtonDel del, FUpdateLogTextDel textDel, FSetProcessDel procDel);
|
||||
|
||||
private:
|
||||
void* ReadPipe;
|
||||
void* WritePipe;
|
||||
|
||||
FSetProcessDel SetProcess;
|
||||
FUpdateLogTextDel UpdateLogText;
|
||||
FEnableUploadButtonDel EnableUploadButton;
|
||||
FString LaunchArgs;
|
||||
|
||||
protected:
|
||||
void DoWork();
|
||||
|
||||
FORCEINLINE TStatId GetStatId() const
|
||||
{
|
||||
RETURN_QUICK_DECLARE_CYCLE_STAT(FPlatformUploadTask, STATGROUP_ThreadPoolAsyncTasks);
|
||||
}
|
||||
};
|
||||
|
||||
class FPlatformLoadRedistPackagesTask : public FNonAbandonableTask
|
||||
{
|
||||
friend class FAsyncTask<FPlatformLoadRedistPackagesTask>;
|
||||
|
||||
public:
|
||||
FPlatformLoadRedistPackagesTask(FUpdateLogTextDel textDel);
|
||||
|
||||
private:
|
||||
void* ReadPipe;
|
||||
void* WritePipe;
|
||||
|
||||
FUpdateLogTextDel UpdateLogText;
|
||||
|
||||
protected:
|
||||
void DoWork();
|
||||
|
||||
FORCEINLINE TStatId GetStatId() const
|
||||
{
|
||||
RETURN_QUICK_DECLARE_CYCLE_STAT(FPlatformLoadRedistPackagesTask, STATGROUP_ThreadPoolAsyncTasks);
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,316 @@
|
||||
// Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
|
||||
#include "OculusXRPrivacyNotification.h"
|
||||
|
||||
#include <regex>
|
||||
|
||||
#include "ISettingsModule.h"
|
||||
#include "Framework/Notifications/NotificationManager.h"
|
||||
#include "Widgets/Notifications/SNotificationList.h"
|
||||
|
||||
#include "OculusXRHMDModule.h"
|
||||
#include "OculusXRTelemetry.h"
|
||||
#include "OculusXRToolStyle.h"
|
||||
#include "Interfaces/IMainFrameModule.h"
|
||||
#include "Widgets/Notifications/INotificationWidget.h"
|
||||
#include "Widgets/Text/SRichTextBlock.h"
|
||||
#include "Widgets/Input/SButton.h"
|
||||
#include "Widgets/Layout/SBox.h"
|
||||
#include "Widgets/Images/SImage.h"
|
||||
#include "Framework/Application/SlateApplication.h"
|
||||
#include "OculusXRTelemetryPrivacySettings.h"
|
||||
|
||||
#define LOCTEXT_NAMESPACE "OculusXRTelemetryPrivacySettings"
|
||||
|
||||
namespace OculusXRTelemetry
|
||||
{
|
||||
namespace
|
||||
{
|
||||
constexpr int CONSENT_TITLE_MAX_LENGTH = 256;
|
||||
constexpr int CONSENT_TEXT_MAX_LENGTH = 2048;
|
||||
constexpr int CONSENT_NOTIFICATION_MAX_LENGTH = 1024;
|
||||
|
||||
void OnBrowserLinkClicked(const FSlateHyperlinkRun::FMetadata& Metadata)
|
||||
{
|
||||
const FString* Url = Metadata.Find(TEXT("href"));
|
||||
if (Url)
|
||||
{
|
||||
FPlatformProcess::LaunchURL(**Url, nullptr, nullptr);
|
||||
}
|
||||
}
|
||||
|
||||
void UpdateNotificationShown()
|
||||
{
|
||||
FOculusXRHMDModule::GetPluginWrapper().SetNotificationShown(UNREAL_TOOL_ID);
|
||||
}
|
||||
|
||||
std::string MarkdownToRTF(const std::string& markdown)
|
||||
{
|
||||
const std::regex boldText(R"(\*\*(.*?)\*\*)");
|
||||
const std::string boldReplacement = "<NormalText.Important>$1</>";
|
||||
|
||||
std::string rtf = "";
|
||||
rtf = std::regex_replace(markdown, boldText, boldReplacement);
|
||||
|
||||
const std::regex linkRegex(R"(\[(.*?)\]\((.*?)\))");
|
||||
const std::string linkReplacement = "<a id=\"browser\" style=\"Hyperlink\" href=\"$2\">$1</>";
|
||||
rtf = std::regex_replace(rtf, linkRegex, linkReplacement);
|
||||
return rtf;
|
||||
}
|
||||
} // namespace
|
||||
|
||||
class SOculusXRPrivacyNotification : public SCompoundWidget, public INotificationWidget
|
||||
{
|
||||
public:
|
||||
SLATE_BEGIN_ARGS(SOculusXRPrivacyNotification) {}
|
||||
SLATE_ARGUMENT(std::string, ConsentText);
|
||||
/** Invoked when any button is clicked, needed for fading out notification */
|
||||
SLATE_EVENT(FSimpleDelegate, OnClicked)
|
||||
SLATE_END_ARGS()
|
||||
|
||||
void Construct(const FArguments& InArgs)
|
||||
{
|
||||
OnClicked = InArgs._OnClicked;
|
||||
|
||||
// Container for the text and optional interactive widgets (buttons, check box, and hyperlink)
|
||||
TSharedRef<SVerticalBox> InteractiveWidgetsBox = SNew(SVerticalBox);
|
||||
|
||||
InteractiveWidgetsBox->AddSlot()
|
||||
.Padding(FMargin(0.0f, 10.0f, 0.0f, 2.0f))
|
||||
.AutoHeight()
|
||||
[SNew(SRichTextBlock)
|
||||
.Text(FText::FromString(MarkdownToRTF(InArgs._ConsentText).data()))
|
||||
.AutoWrapText(true)
|
||||
+ SRichTextBlock::HyperlinkDecorator(TEXT("browser"), FSlateHyperlinkRun::FOnClick::CreateStatic(&OnBrowserLinkClicked))
|
||||
+ SRichTextBlock::HyperlinkDecorator(TEXT("PrivacySettings"), FSlateHyperlinkRun::FOnClick::CreateRaw(this, &SOculusXRPrivacyNotification::OpenPrivacySettings))];
|
||||
|
||||
ChildSlot
|
||||
[SNew(SBox)
|
||||
[SNew(SHorizontalBox)
|
||||
+ SHorizontalBox::Slot()
|
||||
.AutoWidth()
|
||||
.VAlign(VAlign_Top)
|
||||
.HAlign(HAlign_Left)
|
||||
[SNew(SOverlay)
|
||||
+ SOverlay::Slot()
|
||||
.VAlign(VAlign_Center)
|
||||
.HAlign(HAlign_Center)
|
||||
[SNew(SImage)
|
||||
.Image(FOculusToolStyle::Get().GetBrush("OculusTool.MetaLogo"))
|
||||
.DesiredSizeOverride(FVector2D(32, 32))]]
|
||||
+ SHorizontalBox::Slot()
|
||||
.Padding(10.f, 0.f, 5.f, 0.f)
|
||||
[InteractiveWidgetsBox]
|
||||
+ SHorizontalBox::Slot()
|
||||
.AutoWidth()
|
||||
.VAlign(VAlign_Top)
|
||||
.HAlign(HAlign_Right)
|
||||
[SNew(SButton)
|
||||
.Cursor(EMouseCursor::Default)
|
||||
.ButtonStyle(FAppStyle::Get(), "SimpleButton")
|
||||
.ContentPadding(0.0f)
|
||||
.OnClicked(this, &SOculusXRPrivacyNotification::CloseButtonClicked)
|
||||
.Content()
|
||||
[SNew(SImage)
|
||||
.Image(FAppStyle::GetBrush("Icons.X"))
|
||||
.ColorAndOpacity(FSlateColor::UseForeground())]]]];
|
||||
}
|
||||
|
||||
private:
|
||||
virtual TSharedRef<SWidget> AsWidget() override
|
||||
{
|
||||
return AsShared();
|
||||
}
|
||||
|
||||
virtual void OnSetCompletionState(SNotificationItem::ECompletionState InState) override
|
||||
{
|
||||
if (InState == SNotificationItem::ECompletionState::CS_Success)
|
||||
{
|
||||
UpdateNotificationShown();
|
||||
}
|
||||
}
|
||||
|
||||
FReply CloseButtonClicked()
|
||||
{
|
||||
OnClicked.ExecuteIfBound();
|
||||
return FReply::Handled();
|
||||
}
|
||||
|
||||
void OpenPrivacySettings(const FSlateHyperlinkRun::FMetadata& /*Metadata*/) const
|
||||
{
|
||||
OnClicked.ExecuteIfBound();
|
||||
FModuleManager::LoadModuleChecked<ISettingsModule>("Settings").ShowViewer(FName("Editor"), FName("Privacy"), FName("OculusXR"));
|
||||
}
|
||||
|
||||
FSimpleDelegate OnClicked;
|
||||
};
|
||||
|
||||
class SOculusTelemetryWindow : public SCompoundWidget
|
||||
{
|
||||
SLATE_BEGIN_ARGS(SOculusTelemetryWindow) {}
|
||||
SLATE_ARGUMENT(std::string, ConsentText);
|
||||
SLATE_END_ARGS()
|
||||
|
||||
/** Construct the slate layout for the widget */
|
||||
void Construct(const FArguments& InArgs)
|
||||
{
|
||||
TSharedPtr<SVerticalBox> RootContainer = SNew(SVerticalBox);
|
||||
const TSharedPtr<SHorizontalBox> ButtonsWidget = SNew(SHorizontalBox);
|
||||
|
||||
ButtonsWidget->AddSlot()
|
||||
[SNew(SHorizontalBox)
|
||||
+ SHorizontalBox::Slot()
|
||||
[SNew(SButton)
|
||||
.HAlign(HAlign_Center)
|
||||
.VAlign(VAlign_Center)
|
||||
.ContentPadding(5)
|
||||
.OnClicked(this, &SOculusTelemetryWindow::OnNotShareClicked)
|
||||
.Text(LOCTEXT("NotShare", "Only share essential data"))]];
|
||||
|
||||
ButtonsWidget->AddSlot()
|
||||
[SNew(SHorizontalBox)
|
||||
+ SHorizontalBox::Slot()
|
||||
[SNew(SButton)
|
||||
.HAlign(HAlign_Center)
|
||||
.VAlign(VAlign_Center)
|
||||
.ContentPadding(5)
|
||||
.OnClicked(this, &SOculusTelemetryWindow::OnShareClicked)
|
||||
.ButtonStyle(&FAppStyle::Get().GetWidgetStyle<FButtonStyle>("PrimaryButton"))
|
||||
.Text(LOCTEXT("Share", "Share additional data"))]];
|
||||
|
||||
// Construct the text widget
|
||||
const TSharedPtr<SVerticalBox> TextWidget = SNew(SVerticalBox);
|
||||
|
||||
TextWidget->AddSlot()
|
||||
.AutoHeight()
|
||||
[SNew(SRichTextBlock)
|
||||
.AutoWrapText(true)
|
||||
.Text(FText::FromString(MarkdownToRTF(InArgs._ConsentText).data()))
|
||||
.DecoratorStyleSet(&FAppStyle::Get())
|
||||
+ SRichTextBlock::HyperlinkDecorator(TEXT("browser"), FSlateHyperlinkRun::FOnClick::CreateStatic(&OnBrowserLinkClicked))];
|
||||
|
||||
RootContainer->AddSlot()
|
||||
[SNew(SVerticalBox)
|
||||
+ SVerticalBox::Slot()
|
||||
.Padding(20, 20, 20, 20)
|
||||
.VAlign(VAlign_Center)
|
||||
[TextWidget.ToSharedRef()]];
|
||||
|
||||
RootContainer->AddSlot()
|
||||
[SNew(SVerticalBox)
|
||||
+ SVerticalBox::Slot()
|
||||
.Padding(20, 20)
|
||||
.VAlign(VAlign_Bottom)
|
||||
[ButtonsWidget.ToSharedRef()]];
|
||||
ChildSlot
|
||||
[SNew(SBox)
|
||||
.WidthOverride(960)
|
||||
[RootContainer.ToSharedRef()]];
|
||||
}
|
||||
|
||||
private:
|
||||
FReply OnShareClicked()
|
||||
{
|
||||
FOculusXRHMDModule::GetPluginWrapper().SaveUnifiedConsent(UNREAL_TOOL_ID, ovrpBool_True);
|
||||
if (UOculusXRTelemetryPrivacySettings* EditorPrivacySettings = GetMutableDefault<UOculusXRTelemetryPrivacySettings>())
|
||||
{
|
||||
EditorPrivacySettings->bIsEnabled = true;
|
||||
}
|
||||
PropagateTelemetryConsent();
|
||||
FSlateApplication::Get().FindWidgetWindow(AsShared())->RequestDestroyWindow();
|
||||
return FReply::Handled();
|
||||
}
|
||||
|
||||
FReply OnNotShareClicked()
|
||||
{
|
||||
FOculusXRHMDModule::GetPluginWrapper().SaveUnifiedConsent(UNREAL_TOOL_ID, ovrpBool_False);
|
||||
if (UOculusXRTelemetryPrivacySettings* EditorPrivacySettings = GetMutableDefault<UOculusXRTelemetryPrivacySettings>())
|
||||
{
|
||||
EditorPrivacySettings->bIsEnabled = false;
|
||||
}
|
||||
PropagateTelemetryConsent();
|
||||
FSlateApplication::Get().FindWidgetWindow(AsShared())->RequestDestroyWindow();
|
||||
return FReply::Handled();
|
||||
}
|
||||
};
|
||||
|
||||
void SpawnFullConsentWindow()
|
||||
{
|
||||
if (FSlateApplication::Get().IsRenderingOffScreen())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
char TelemetryWindowTitle[CONSENT_TITLE_MAX_LENGTH];
|
||||
char ConsentText[CONSENT_TEXT_MAX_LENGTH];
|
||||
if (FOculusXRHMDModule::GetPluginWrapper().GetConsentTitle(TelemetryWindowTitle) == ovrpFailure || FOculusXRHMDModule::GetPluginWrapper().GetConsentMarkdownText(ConsentText) == ovrpFailure)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
std::string Title(TelemetryWindowTitle);
|
||||
std::string MarkdownText(ConsentText);
|
||||
|
||||
IMainFrameModule::Get().OnMainFrameCreationFinished().AddLambda([Title, MarkdownText](const TSharedPtr<SWindow>& RootWindow, bool /*bIsRunningStartupDialog*/) {
|
||||
const TSharedRef<SWindow> Window = SNew(SWindow)
|
||||
.Title(FText::FromString(Title.c_str()))
|
||||
.SizingRule(ESizingRule::Autosized)
|
||||
.SupportsMaximize(false)
|
||||
.SupportsMinimize(false)[SNew(SOculusTelemetryWindow).ConsentText(MarkdownText)];
|
||||
|
||||
FSlateApplication::Get().AddModalWindow(Window, RootWindow);
|
||||
});
|
||||
}
|
||||
|
||||
void SpawnNotification()
|
||||
{
|
||||
char NotificationText[CONSENT_NOTIFICATION_MAX_LENGTH];
|
||||
if (FOculusXRHMDModule::GetPluginWrapper().GetConsentNotificationMarkdownText("<a id=\"PrivacySettings\">Settings</>", NotificationText) == ovrpFailure)
|
||||
{
|
||||
return;
|
||||
}
|
||||
TPromise<TSharedPtr<SNotificationItem>> BtnNotificationPromise;
|
||||
const auto OnClicked = [NotificationFuture = BtnNotificationPromise.GetFuture().Share()]() {
|
||||
const TSharedPtr<SNotificationItem> Notification = NotificationFuture.Get();
|
||||
Notification->SetCompletionState(SNotificationItem::CS_Success);
|
||||
Notification->Fadeout();
|
||||
};
|
||||
|
||||
FNotificationInfo Info(SNew(SOculusXRPrivacyNotification).OnClicked_Lambda(OnClicked).ConsentText(NotificationText));
|
||||
Info.ExpireDuration = 60.0f;
|
||||
|
||||
const TSharedPtr<SNotificationItem> PrivacyNotification = FSlateNotificationManager::Get().AddNotification(Info);
|
||||
if (PrivacyNotification.IsValid())
|
||||
{
|
||||
PrivacyNotification->SetCompletionState(SNotificationItem::CS_Pending);
|
||||
BtnNotificationPromise.SetValue(PrivacyNotification);
|
||||
}
|
||||
}
|
||||
|
||||
void MaybeSpawnTelemetryConsent()
|
||||
{
|
||||
if (!FOculusXRHMDModule::Get().IsOVRPluginAvailable() || !FOculusXRHMDModule::GetPluginWrapper().IsInitialized())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (!FModuleManager::Get().IsModuleLoaded("MainFrame"))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
const auto& PluginWrapper = FOculusXRHMDModule::GetPluginWrapper();
|
||||
|
||||
if (PluginWrapper.ShouldShowTelemetryConsentWindow(UNREAL_TOOL_ID))
|
||||
{
|
||||
SpawnFullConsentWindow();
|
||||
}
|
||||
|
||||
if (PluginWrapper.ShouldShowTelemetryNotification(UNREAL_TOOL_ID))
|
||||
{
|
||||
SpawnNotification();
|
||||
}
|
||||
}
|
||||
} // namespace OculusXRTelemetry
|
||||
|
||||
#undef LOCTEXT_NAMESPACE
|
||||
@@ -0,0 +1,7 @@
|
||||
// Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
|
||||
#pragma once
|
||||
namespace OculusXRTelemetry
|
||||
{
|
||||
void MaybeSpawnTelemetryConsent();
|
||||
} // namespace OculusXRTelemetry
|
||||
@@ -0,0 +1,215 @@
|
||||
|
||||
// @lint-ignore-every LICENSELINT
|
||||
// Copyright Epic Games, Inc. All Rights Reserved.
|
||||
|
||||
#include "OculusXRSettingsToggle.h"
|
||||
|
||||
#include "Containers/Array.h"
|
||||
#include "Delegates/Delegate.h"
|
||||
#include "DetailCategoryBuilder.h"
|
||||
#include "DetailLayoutBuilder.h"
|
||||
#include "DetailWidgetRow.h"
|
||||
#include "Engine/ImportantToggleSettingInterface.h"
|
||||
#include "Fonts/SlateFontInfo.h"
|
||||
#include "HAL/PlatformProcess.h"
|
||||
#include "IDetailPropertyRow.h"
|
||||
#include "OculusXRHMDModule.h"
|
||||
#include "OculusXRTelemetry.h"
|
||||
#include "Layout/Children.h"
|
||||
#include "Layout/Margin.h"
|
||||
#include "Misc/Attribute.h"
|
||||
#include "PropertyHandle.h"
|
||||
#include "SlotBase.h"
|
||||
#include "Styling/AppStyle.h"
|
||||
#include "Styling/SlateColor.h"
|
||||
#include "Styling/SlateTypes.h"
|
||||
#include "Templates/Casts.h"
|
||||
#include "Types/SlateEnums.h"
|
||||
#include "UObject/NameTypes.h"
|
||||
#include "UObject/Object.h"
|
||||
#include "Widgets/DeclarativeSyntaxSupport.h"
|
||||
#include "Widgets/Input/SCheckBox.h"
|
||||
#include "Widgets/Input/SHyperlink.h"
|
||||
#include "Widgets/SBoxPanel.h"
|
||||
#include "Widgets/SCompoundWidget.h"
|
||||
#include "Widgets/Text/STextBlock.h"
|
||||
|
||||
#define LOCTEXT_NAMESPACE "OculusXRSettingsToggle"
|
||||
|
||||
class SImportantToggleButton : public SCompoundWidget
|
||||
{
|
||||
public:
|
||||
SLATE_BEGIN_ARGS(SImportantToggleButton)
|
||||
: _Text()
|
||||
{
|
||||
}
|
||||
|
||||
SLATE_STYLE_ARGUMENT(FCheckBoxStyle, CheckBoxStyle)
|
||||
SLATE_ARGUMENT(FText, Text)
|
||||
SLATE_ARGUMENT(FText, ToolTipText)
|
||||
SLATE_ATTRIBUTE(bool, IsSet)
|
||||
SLATE_EVENT(FSimpleDelegate, OnToggled)
|
||||
|
||||
SLATE_END_ARGS()
|
||||
|
||||
void Construct(const FArguments& InArgs)
|
||||
{
|
||||
OnToggled = InArgs._OnToggled;
|
||||
IsSetAttribute = InArgs._IsSet;
|
||||
|
||||
FSlateFontInfo LargeDetailsFont = IDetailLayoutBuilder::GetDetailFontBold();
|
||||
LargeDetailsFont.Size += 4;
|
||||
|
||||
ChildSlot
|
||||
[SNew(SCheckBox)
|
||||
.Style(InArgs._CheckBoxStyle)
|
||||
.IsChecked(this, &SImportantToggleButton::GetCheckedState)
|
||||
.OnCheckStateChanged(this, &SImportantToggleButton::OnClick)
|
||||
.ToolTipText(InArgs._ToolTipText)
|
||||
.Padding(FMargin(16.0f, 12.0f))
|
||||
.ForegroundColor(FSlateColor::UseForeground())
|
||||
.IsFocusable(true)
|
||||
[SNew(STextBlock)
|
||||
.Text(InArgs._Text)
|
||||
.Font(LargeDetailsFont)]];
|
||||
}
|
||||
|
||||
private:
|
||||
void OnClick(ECheckBoxState State)
|
||||
{
|
||||
OnToggled.ExecuteIfBound();
|
||||
}
|
||||
|
||||
ECheckBoxState GetCheckedState() const
|
||||
{
|
||||
return IsSetAttribute.Get() ? ECheckBoxState::Checked : ECheckBoxState::Unchecked;
|
||||
}
|
||||
|
||||
TAttribute<bool> IsSetAttribute;
|
||||
FSimpleDelegate OnToggled;
|
||||
};
|
||||
|
||||
TSharedRef<IDetailCustomization> FOculusXRSettingsToggle::MakeInstance()
|
||||
{
|
||||
return MakeShareable(new FOculusXRSettingsToggle);
|
||||
}
|
||||
|
||||
void FOculusXRSettingsToggle::CustomizeDetails(IDetailLayoutBuilder& DetailBuilder)
|
||||
{
|
||||
if (!ToggleEnabled.IsSet() && FOculusXRHMDModule::Get().IsOVRPluginAvailable() && FOculusXRHMDModule::GetPluginWrapper().IsInitialized())
|
||||
{
|
||||
ToggleEnabled = FOculusXRHMDModule::GetPluginWrapper().IsConsentSettingsChangeEnabled(OculusXRTelemetry::UNREAL_TOOL_ID) == ovrpBool_True;
|
||||
}
|
||||
|
||||
TArray<TWeakObjectPtr<UObject>> Objects;
|
||||
DetailBuilder.GetObjectsBeingCustomized(Objects);
|
||||
|
||||
if (Objects.Num() == 1)
|
||||
{
|
||||
ToggleSettingObject = Objects[0];
|
||||
IImportantToggleSettingInterface* ToggleSettingInterface = Cast<IImportantToggleSettingInterface>(ToggleSettingObject.Get());
|
||||
|
||||
if (ToggleSettingInterface != nullptr)
|
||||
{
|
||||
FName CategoryName;
|
||||
FName PropertyName;
|
||||
ToggleSettingInterface->GetToggleCategoryAndPropertyNames(CategoryName, PropertyName);
|
||||
|
||||
IDetailCategoryBuilder& Category = DetailBuilder.EditCategory(CategoryName);
|
||||
TogglePropertyHandle = DetailBuilder.GetProperty(PropertyName);
|
||||
|
||||
FSlateFontInfo StateDescriptionFont = IDetailLayoutBuilder::GetDetailFont();
|
||||
StateDescriptionFont.Size += 4;
|
||||
|
||||
// Customize collision section
|
||||
Category.InitiallyCollapsed(false)
|
||||
.AddProperty(TogglePropertyHandle)
|
||||
.ShouldAutoExpand(true)
|
||||
.CustomWidget()
|
||||
[SNew(SVerticalBox)
|
||||
+ SVerticalBox::Slot()
|
||||
.AutoHeight()
|
||||
.Padding(0.0f, 12.0f, 0.0f, 0.0f)
|
||||
[SNew(SHorizontalBox)
|
||||
+ SHorizontalBox::Slot()
|
||||
.AutoWidth()
|
||||
[SNew(SImportantToggleButton)
|
||||
.CheckBoxStyle(FAppStyle::Get(), "Property.ToggleButton.Start")
|
||||
.Text(ToggleSettingInterface->GetFalseStateLabel())
|
||||
.ToolTipText(ToggleSettingInterface->GetFalseStateTooltip())
|
||||
.IsSet(this, &FOculusXRSettingsToggle::IsToggleValue, false)
|
||||
.OnToggled(this, &FOculusXRSettingsToggle::OnToggledTo, false)
|
||||
.IsEnabled(this, &FOculusXRSettingsToggle::IsEnabled)]
|
||||
+ SHorizontalBox::Slot()
|
||||
.AutoWidth()
|
||||
[SNew(SImportantToggleButton)
|
||||
.CheckBoxStyle(FAppStyle::Get(), "Property.ToggleButton.End")
|
||||
.Text(ToggleSettingInterface->GetTrueStateLabel())
|
||||
.ToolTipText(ToggleSettingInterface->GetTrueStateTooltip())
|
||||
.IsSet(this, &FOculusXRSettingsToggle::IsToggleValue, true)
|
||||
.OnToggled(this, &FOculusXRSettingsToggle::OnToggledTo, true)
|
||||
.IsEnabled(this, &FOculusXRSettingsToggle::IsEnabled)]
|
||||
+ SHorizontalBox::Slot()
|
||||
.HAlign(HAlign_Right)
|
||||
.Padding(0.0f, 12.0f)
|
||||
[SNew(SVerticalBox)
|
||||
+ SVerticalBox::Slot()
|
||||
.VAlign(VAlign_Center)
|
||||
[SNew(SHyperlink)
|
||||
.Text(ToggleSettingInterface->GetAdditionalInfoUrlLabel())
|
||||
.OnNavigate(this, &FOculusXRSettingsToggle::OnNavigateHyperlink, ToggleSettingInterface->GetAdditionalInfoUrl())]]]
|
||||
+ SVerticalBox::Slot()
|
||||
.AutoHeight()
|
||||
.Padding(0.0f, 12.0f)
|
||||
[SNew(STextBlock)
|
||||
.AutoWrapText(true)
|
||||
.Text(this, &FOculusXRSettingsToggle::GetDescriptionText)
|
||||
.Font(StateDescriptionFont)]];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool FOculusXRSettingsToggle::IsToggleValue(bool bValue) const
|
||||
{
|
||||
bool bPropertyValue = false;
|
||||
TogglePropertyHandle->GetValue(bPropertyValue);
|
||||
return bPropertyValue == bValue;
|
||||
}
|
||||
|
||||
bool FOculusXRSettingsToggle::IsEnabled() const
|
||||
{
|
||||
return ToggleEnabled.IsSet() && ToggleEnabled.GetValue();
|
||||
}
|
||||
|
||||
void FOculusXRSettingsToggle::OnToggledTo(bool bSetTo)
|
||||
{
|
||||
TogglePropertyHandle->SetValue(bSetTo);
|
||||
}
|
||||
|
||||
void FOculusXRSettingsToggle::OnNavigateHyperlink(FString Url)
|
||||
{
|
||||
FPlatformProcess::LaunchURL(*Url, nullptr, nullptr);
|
||||
}
|
||||
|
||||
FText FOculusXRSettingsToggle::GetDescriptionText() const
|
||||
{
|
||||
IImportantToggleSettingInterface* ToogleSettingInterface = Cast<IImportantToggleSettingInterface>(ToggleSettingObject.Get());
|
||||
|
||||
if (ToogleSettingInterface != nullptr)
|
||||
{
|
||||
bool bPropertyValue = false;
|
||||
TogglePropertyHandle->GetValue(bPropertyValue);
|
||||
|
||||
if (bPropertyValue)
|
||||
{
|
||||
return ToogleSettingInterface->GetTrueStateDescription();
|
||||
}
|
||||
else
|
||||
{
|
||||
return ToogleSettingInterface->GetFalseStateDescription();
|
||||
}
|
||||
}
|
||||
return FText::GetEmpty();
|
||||
}
|
||||
|
||||
#undef LOCTEXT_NAMESPACE
|
||||
@@ -0,0 +1,30 @@
|
||||
|
||||
// @lint-ignore-every LICENSELINT
|
||||
// Copyright Epic Games, Inc. All Rights Reserved.
|
||||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "IDetailCustomization.h"
|
||||
#include "UObject/WeakObjectPtr.h"
|
||||
|
||||
class IPropertyHandle;
|
||||
|
||||
class OCULUSXREDITOR_API FOculusXRSettingsToggle : public IDetailCustomization
|
||||
{
|
||||
public:
|
||||
static TSharedRef<IDetailCustomization> MakeInstance();
|
||||
|
||||
// IDetailCustomization interface
|
||||
virtual void CustomizeDetails(IDetailLayoutBuilder& DetailBuilder) override;
|
||||
// End of IDetailCustomization interface
|
||||
private:
|
||||
bool IsToggleValue(bool bValue) const;
|
||||
bool IsEnabled() const;
|
||||
void OnToggledTo(bool bSetTo);
|
||||
void OnNavigateHyperlink(FString Url);
|
||||
FText GetDescriptionText() const;
|
||||
|
||||
TSharedPtr<IPropertyHandle> TogglePropertyHandle;
|
||||
TWeakObjectPtr<UObject> ToggleSettingObject;
|
||||
TOptional<bool> ToggleEnabled;
|
||||
};
|
||||
@@ -0,0 +1,10 @@
|
||||
// Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "OculusXRTelemetry.h"
|
||||
|
||||
namespace OculusXRTelemetry::Events
|
||||
{
|
||||
using FEditorStart = TMarker<191956532>;
|
||||
} // namespace OculusXRTelemetry::Events
|
||||
@@ -0,0 +1,67 @@
|
||||
// @lint-ignore-every LICENSELINT
|
||||
// Copyright Epic Games, Inc. All Rights Reserved.
|
||||
|
||||
#include "OculusXRToolCommands.h"
|
||||
|
||||
#include "OculusXRProjectSetupToolModule.h"
|
||||
#include "OculusXRSyntheticEnvironmentServer.h"
|
||||
#include "Framework/Docking/TabManager.h"
|
||||
#include "Misc/EngineVersionComparison.h"
|
||||
|
||||
#define LOCTEXT_NAMESPACE "FOculusXREditorModule"
|
||||
|
||||
#if UE_VERSION_OLDER_THAN(5, 5, 0)
|
||||
#define AS_LOCALIZABLE_ADVANCED(Namespace, Key, TextLiteral) \
|
||||
FInternationalization::ForUseOnlyByLocMacroAndGraphNodeTextLiterals_CreateText(TextLiteral, Namespace, Key)
|
||||
#else
|
||||
#define AS_LOCALIZABLE_ADVANCED(Namespace, Key, TextLiteral) \
|
||||
FText::AsLocalizable_Advanced(Namespace, Key, TextLiteral)
|
||||
#endif
|
||||
|
||||
void FOculusToolCommands::RegisterCommands()
|
||||
{
|
||||
UI_COMMAND(OpenProjectSetupTool, "Meta XR Project Setup Tool", "Show Meta XR Project Setup Tool", EUserInterfaceActionType::Button, FInputChord());
|
||||
UI_COMMAND(ToggleDeploySo, "Deploy compiled .so directly to device", "Faster deploy when we only have code changes by deploying compiled .so directly to device", EUserInterfaceActionType::ToggleButton, FInputChord());
|
||||
UI_COMMAND(ToggleIterativeCookOnTheFly, "Enable Iterative Cook on the Fly", "Faster deploy for asset changes by keeping previously cooked contents on the device (Uses Cook on the Fly)", EUserInterfaceActionType::ToggleButton, FInputChord());
|
||||
UI_COMMAND(OpenPlatWindow, "Meta XR Platform Window", "Show Meta XR Platform Window", EUserInterfaceActionType::Button, FInputChord());
|
||||
|
||||
UI_COMMAND(ToggleMetaXRSim, "Meta XR Simulator", "Activate/Deactivate Meta XR Simulator", EUserInterfaceActionType::ToggleButton, FInputChord());
|
||||
|
||||
#if PLATFORM_WINDOWS
|
||||
static const FString launch("Launch ");
|
||||
static const FString dot(".");
|
||||
const auto& rooms = FMetaXRSES::GetSynthEnvRooms();
|
||||
for (const auto& room : rooms)
|
||||
{
|
||||
TSharedPtr<FUICommandInfo> command;
|
||||
const FString DotCommandName = dot + room.GuiName;
|
||||
const FString InDescription = launch + room.GuiName;
|
||||
const FString InCommandNameUnderscoreTooltip = room.GuiName + TEXT("_ToolTip");
|
||||
|
||||
const FString InSubNamespace = TEXT(LOCTEXT_NAMESPACE);
|
||||
const FString UICommandsStr = TEXT("UICommands");
|
||||
const FString Namespace = UICommandsStr + dot + InSubNamespace;
|
||||
|
||||
FUICommandInfo::MakeCommandInfo(
|
||||
this->AsShared(),
|
||||
command,
|
||||
FName(InCommandNameUnderscoreTooltip),
|
||||
AS_LOCALIZABLE_ADVANCED(*Namespace, *InDescription, *InDescription),
|
||||
AS_LOCALIZABLE_ADVANCED(*Namespace, InCommandNameUnderscoreTooltip.GetCharArray().GetData(), *InDescription),
|
||||
FSlateIcon(),
|
||||
EUserInterfaceActionType::Button,
|
||||
FInputChord(),
|
||||
FInputChord());
|
||||
RoomCommands.Add(command);
|
||||
}
|
||||
#endif
|
||||
|
||||
UI_COMMAND(StopServer, "Stop Server", "Stop Server", EUserInterfaceActionType::Button, FInputChord());
|
||||
}
|
||||
|
||||
void FOculusToolCommands::ShowOculusTool()
|
||||
{
|
||||
IOculusXRProjectSetupToolModule::Get().ShowProjectSetupTool("Console");
|
||||
}
|
||||
|
||||
#undef LOCTEXT_NAMESPACE
|
||||
@@ -0,0 +1,44 @@
|
||||
// @lint-ignore-every LICENSELINT
|
||||
// Copyright Epic Games, Inc. All Rights Reserved.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "Framework/Commands/Commands.h"
|
||||
#include "OculusXRToolStyle.h"
|
||||
#include "OculusXREditorModule.h"
|
||||
#include "HAL/IConsoleManager.h"
|
||||
|
||||
class FOculusToolCommands : public TCommands<FOculusToolCommands>
|
||||
{
|
||||
public:
|
||||
FOculusToolCommands()
|
||||
: TCommands<FOculusToolCommands>(
|
||||
TEXT("OculusTool"), NSLOCTEXT("Contexts", "OculusXREditor", "OculusXREditor Plugin"), NAME_None,
|
||||
FOculusToolStyle::GetStyleSetName())
|
||||
, ShowOculusToolCommand(
|
||||
TEXT("vr.oculus.ShowToolWindow"),
|
||||
*NSLOCTEXT("OculusRift", "CCommandText_ShowToolWindow",
|
||||
"Show the Oculus Editor Tool window (editor only).")
|
||||
.ToString(),
|
||||
FConsoleCommandDelegate::CreateRaw(this, &FOculusToolCommands::ShowOculusTool))
|
||||
{
|
||||
}
|
||||
|
||||
// TCommands<> interface
|
||||
virtual void RegisterCommands() override;
|
||||
|
||||
TSharedPtr<FUICommandInfo> OpenProjectSetupTool;
|
||||
TSharedPtr<FUICommandInfo> ToggleDeploySo;
|
||||
TSharedPtr<FUICommandInfo> ToggleIterativeCookOnTheFly;
|
||||
TSharedPtr<FUICommandInfo> OpenPlatWindow;
|
||||
TSharedPtr<FUICommandInfo> ToggleMetaXRSim;
|
||||
TSharedPtr<FUICommandInfo> StopServer;
|
||||
|
||||
TArray<TSharedPtr<FUICommandInfo>> RoomCommands;
|
||||
|
||||
private:
|
||||
void ShowOculusTool();
|
||||
|
||||
FAutoConsoleCommand ShowOculusToolCommand;
|
||||
};
|
||||
@@ -0,0 +1,75 @@
|
||||
// @lint-ignore-every LICENSELINT
|
||||
// Copyright Epic Games, Inc. All Rights Reserved.
|
||||
|
||||
#include "OculusXRToolStyle.h"
|
||||
#include "Styling/SlateStyleRegistry.h"
|
||||
#include "Framework/Application/SlateApplication.h"
|
||||
#include "Slate/SlateGameResources.h"
|
||||
#include "Interfaces/IPluginManager.h"
|
||||
|
||||
TSharedPtr<FSlateStyleSet> FOculusToolStyle::StyleInstance = nullptr;
|
||||
|
||||
void FOculusToolStyle::Initialize()
|
||||
{
|
||||
if (!StyleInstance.IsValid())
|
||||
{
|
||||
StyleInstance = Create();
|
||||
FSlateStyleRegistry::RegisterSlateStyle(*StyleInstance);
|
||||
}
|
||||
}
|
||||
|
||||
void FOculusToolStyle::Shutdown()
|
||||
{
|
||||
FSlateStyleRegistry::UnRegisterSlateStyle(*StyleInstance);
|
||||
ensure(StyleInstance.IsUnique());
|
||||
StyleInstance.Reset();
|
||||
}
|
||||
|
||||
FName FOculusToolStyle::GetStyleSetName()
|
||||
{
|
||||
static FName StyleSetName(TEXT("OculusToolStyle"));
|
||||
return StyleSetName;
|
||||
}
|
||||
|
||||
#define IMAGE_BRUSH(RelativePath, ...) FSlateImageBrush(Style->RootToContentDir(RelativePath, TEXT(".png")), __VA_ARGS__)
|
||||
#define BOX_BRUSH(RelativePath, ...) FSlateBoxBrush(Style->RootToContentDir(RelativePath, TEXT(".png")), __VA_ARGS__)
|
||||
#define BORDER_BRUSH(RelativePath, ...) FSlateBorderBrush(Style->RootToContentDir(RelativePath, TEXT(".png")), __VA_ARGS__)
|
||||
#define TTF_FONT(RelativePath, ...) FSlateFontInfo(Style->RootToContentDir(RelativePath, TEXT(".ttf")), __VA_ARGS__)
|
||||
#define OTF_FONT(RelativePath, ...) FSlateFontInfo(Style->RootToContentDir(RelativePath, TEXT(".otf")), __VA_ARGS__)
|
||||
|
||||
const FVector2D Icon16x16(16.0f, 16.0f);
|
||||
const FVector2D Icon20x20(20.0f, 20.0f);
|
||||
const FVector2D Icon40x40(40.0f, 40.0f);
|
||||
|
||||
TSharedRef<FSlateStyleSet> FOculusToolStyle::Create()
|
||||
{
|
||||
TSharedRef<FSlateStyleSet> Style = MakeShareable(new FSlateStyleSet("OculusToolStyle"));
|
||||
Style->SetContentRoot(IPluginManager::Get().FindPlugin("OculusXR")->GetBaseDir() / TEXT("Resources"));
|
||||
|
||||
Style->Set("OculusTool.MenuButton", new IMAGE_BRUSH(TEXT("ButtonIcon_80x"), Icon40x40));
|
||||
Style->Set("OculusTool.OpenPluginWindow", new IMAGE_BRUSH(TEXT("ButtonIcon_80x"), Icon40x40));
|
||||
Style->Set("OculusTool.MetaLogo",
|
||||
new FSlateVectorImageBrush(Style->RootToContentDir("MetaLogo", TEXT(".svg")),
|
||||
FVector2D(32.0f, 32.0f)));
|
||||
|
||||
return Style;
|
||||
}
|
||||
|
||||
#undef IMAGE_BRUSH
|
||||
#undef BOX_BRUSH
|
||||
#undef BORDER_BRUSH
|
||||
#undef TTF_FONT
|
||||
#undef OTF_FONT
|
||||
|
||||
void FOculusToolStyle::ReloadTextures()
|
||||
{
|
||||
if (FSlateApplication::IsInitialized())
|
||||
{
|
||||
FSlateApplication::Get().GetRenderer()->ReloadTextureResources();
|
||||
}
|
||||
}
|
||||
|
||||
const ISlateStyle& FOculusToolStyle::Get()
|
||||
{
|
||||
return *StyleInstance;
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
// @lint-ignore-every LICENSELINT
|
||||
// Copyright Epic Games, Inc. All Rights Reserved.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "Styling/SlateStyle.h"
|
||||
|
||||
/** */
|
||||
class FOculusToolStyle
|
||||
{
|
||||
public:
|
||||
static void Initialize();
|
||||
|
||||
static void Shutdown();
|
||||
|
||||
/** reloads textures used by slate renderer */
|
||||
static void ReloadTextures();
|
||||
|
||||
/** @return The Slate style set for the Shooter game */
|
||||
static const ISlateStyle& Get();
|
||||
|
||||
static FName GetStyleSetName();
|
||||
|
||||
private:
|
||||
static TSharedRef<class FSlateStyleSet> Create();
|
||||
|
||||
private:
|
||||
static TSharedPtr<class FSlateStyleSet> StyleInstance;
|
||||
};
|
||||
@@ -0,0 +1,19 @@
|
||||
// @lint-ignore-every LICENSELINT
|
||||
// Copyright Epic Games, Inc. All Rights Reserved.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "Modules/ModuleInterface.h"
|
||||
|
||||
class FToolBarBuilder;
|
||||
class FMenuBuilder;
|
||||
|
||||
#define OCULUS_EDITOR_MODULE_NAME "OculusXREditor"
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// IOculusXREditorModule
|
||||
|
||||
class IOculusXREditorModule : public IModuleInterface
|
||||
{
|
||||
};
|
||||
@@ -0,0 +1,37 @@
|
||||
// @lint-ignore-every LICENSELINT
|
||||
// Copyright Epic Games, Inc. All Rights Reserved.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "UObject/NoExportTypes.h"
|
||||
#include "OculusXREditorSettings.generated.h"
|
||||
|
||||
UENUM()
|
||||
enum class EOculusXRPlatform : uint8
|
||||
{
|
||||
PC UMETA(DisplayName = "PC"),
|
||||
Mobile UMETA(DisplayName = "Mobile"),
|
||||
Length UMETA(DisplayName = "Invalid")
|
||||
};
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
UCLASS(config = Editor)
|
||||
class OCULUSXREDITOR_API UOculusXREditorSettings : public UObject
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
public:
|
||||
UOculusXREditorSettings();
|
||||
|
||||
UPROPERTY(config, EditAnywhere, Category = MetaXR)
|
||||
TMap<FName, bool> PerfToolIgnoreList;
|
||||
|
||||
UPROPERTY(config, EditAnywhere, Category = MetaXR)
|
||||
EOculusXRPlatform PerfToolTargetPlatform;
|
||||
|
||||
UPROPERTY(globalconfig, EditAnywhere, Category = MetaXR)
|
||||
bool bAddMenuOption;
|
||||
};
|
||||
@@ -0,0 +1,272 @@
|
||||
// @lint-ignore-every LICENSELINT
|
||||
// Copyright Epic Games, Inc. All Rights Reserved.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "UObject/NoExportTypes.h"
|
||||
#include "OculusXRPlatformToolSettings.generated.h"
|
||||
|
||||
UENUM()
|
||||
enum class EOculusXRPlatformTarget : uint8
|
||||
{
|
||||
Rift UMETA(DisplayName = "Rift"),
|
||||
Quest UMETA(DisplayName = "Quest"),
|
||||
Length UMETA(DisplayName = "Invalid")
|
||||
};
|
||||
|
||||
UENUM()
|
||||
enum class EOculusXRGamepadEmulation : uint8
|
||||
{
|
||||
Off UMETA(DisplayName = "Off"),
|
||||
Twinstick UMETA(DisplayName = "Twinstick"),
|
||||
RightDPad UMETA(DisplayName = "Right D Pad"),
|
||||
LeftDPad UMETA(DisplayName = "Left D Pad"),
|
||||
Length UMETA(DisplayName = "Invalid")
|
||||
};
|
||||
|
||||
UENUM()
|
||||
enum class EOculusXRAssetType : uint8
|
||||
{
|
||||
Default UMETA(DisplayName = "Default"),
|
||||
Store UMETA(DisplayName = "Store"),
|
||||
Language_Pack UMETA(DisplayName = "Language Pack"),
|
||||
Length UMETA(DisplayName = "Invlaid"),
|
||||
};
|
||||
|
||||
USTRUCT()
|
||||
struct FOculusXRRedistPackage
|
||||
{
|
||||
GENERATED_USTRUCT_BODY()
|
||||
|
||||
UPROPERTY(config, EditAnywhere, Category = MetaXR)
|
||||
bool Included = false;
|
||||
|
||||
UPROPERTY(config, EditAnywhere, Category = MetaXR)
|
||||
FString Name;
|
||||
|
||||
UPROPERTY(config, EditAnywhere, Category = MetaXR)
|
||||
FString Id;
|
||||
};
|
||||
|
||||
USTRUCT()
|
||||
struct FOculusXRAssetConfig
|
||||
{
|
||||
GENERATED_USTRUCT_BODY()
|
||||
|
||||
UPROPERTY(config, EditAnywhere, Category = MetaXR)
|
||||
EOculusXRAssetType AssetType = EOculusXRAssetType::Default;
|
||||
|
||||
UPROPERTY(config, EditAnywhere, Category = MetaXR)
|
||||
bool Required = false;
|
||||
|
||||
UPROPERTY(config, EditAnywhere, Category = MetaXR)
|
||||
FString Name;
|
||||
|
||||
UPROPERTY(config, EditAnywhere, Category = MetaXR)
|
||||
FString Sku;
|
||||
};
|
||||
|
||||
USTRUCT()
|
||||
struct FOculusXRAssetConfigArray
|
||||
{
|
||||
GENERATED_USTRUCT_BODY()
|
||||
|
||||
UPROPERTY(config, EditAnywhere, Category = MetaXR)
|
||||
TArray<FOculusXRAssetConfig> ConfigArray;
|
||||
};
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
UCLASS(config = Editor)
|
||||
class OCULUSXREDITOR_API UOculusXRPlatformToolSettings : public UObject
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
public:
|
||||
UOculusXRPlatformToolSettings();
|
||||
|
||||
uint8 GetTargetPlatform()
|
||||
{
|
||||
return (uint8)OculusTargetPlatform;
|
||||
}
|
||||
void SetTargetPlatform(uint8 i)
|
||||
{
|
||||
OculusTargetPlatform = (EOculusXRPlatformTarget)i;
|
||||
}
|
||||
|
||||
FString GetApplicationID()
|
||||
{
|
||||
return (uint8)OculusTargetPlatform < OculusApplicationID.Num() ? OculusApplicationID[(uint8)OculusTargetPlatform] : "";
|
||||
}
|
||||
void SetApplicationID(FString s)
|
||||
{
|
||||
if (OculusTargetPlatform < EOculusXRPlatformTarget::Length)
|
||||
{
|
||||
OculusApplicationID[(uint8)OculusTargetPlatform] = s;
|
||||
}
|
||||
}
|
||||
|
||||
FString GetApplicationToken()
|
||||
{
|
||||
return (uint8)OculusTargetPlatform < OculusApplicationToken.Num() ? OculusApplicationToken[(uint8)OculusTargetPlatform] : "";
|
||||
}
|
||||
void SetApplicationToken(FString s)
|
||||
{
|
||||
if (OculusTargetPlatform < EOculusXRPlatformTarget::Length)
|
||||
{
|
||||
OculusApplicationToken[(uint8)OculusTargetPlatform] = s;
|
||||
}
|
||||
}
|
||||
|
||||
FString GetReleaseChannel()
|
||||
{
|
||||
return (uint8)OculusTargetPlatform < OculusReleaseChannel.Num() ? OculusReleaseChannel[(uint8)OculusTargetPlatform] : "Alpha";
|
||||
}
|
||||
void SetReleaseChannel(FString s)
|
||||
{
|
||||
if (OculusTargetPlatform < EOculusXRPlatformTarget::Length)
|
||||
{
|
||||
OculusReleaseChannel[(uint8)OculusTargetPlatform] = s;
|
||||
}
|
||||
}
|
||||
|
||||
FString GetReleaseNote()
|
||||
{
|
||||
return (uint8)OculusTargetPlatform < OculusReleaseNote.Num() ? OculusReleaseNote[(uint8)OculusTargetPlatform] : "";
|
||||
}
|
||||
void SetReleaseNote(FString s)
|
||||
{
|
||||
if (OculusTargetPlatform < EOculusXRPlatformTarget::Length)
|
||||
{
|
||||
OculusReleaseNote[(uint8)OculusTargetPlatform] = s;
|
||||
}
|
||||
}
|
||||
|
||||
FString GetLaunchFilePath()
|
||||
{
|
||||
return (uint8)OculusTargetPlatform < OculusLaunchFilePath.Num() ? OculusLaunchFilePath[(uint8)OculusTargetPlatform] : "";
|
||||
}
|
||||
void SetLaunchFilePath(FString s)
|
||||
{
|
||||
if (OculusTargetPlatform < EOculusXRPlatformTarget::Length)
|
||||
{
|
||||
OculusLaunchFilePath[(uint8)OculusTargetPlatform] = s;
|
||||
}
|
||||
}
|
||||
|
||||
EOculusXRGamepadEmulation GetRiftGamepadEmulation()
|
||||
{
|
||||
return OculusRiftGamepadEmulation;
|
||||
}
|
||||
void SetRiftGamepadEmulation(uint8 i)
|
||||
{
|
||||
OculusRiftGamepadEmulation = (EOculusXRGamepadEmulation)i;
|
||||
}
|
||||
|
||||
FString GetLanguagePacksPath()
|
||||
{
|
||||
return (uint8)OculusTargetPlatform < OculusLanguagePacksPath.Num() ? OculusLanguagePacksPath[(uint8)OculusTargetPlatform] : "";
|
||||
}
|
||||
void SetLanguagePacksPath(FString s)
|
||||
{
|
||||
if (OculusTargetPlatform < EOculusXRPlatformTarget::Length)
|
||||
{
|
||||
OculusLanguagePacksPath[(uint8)OculusTargetPlatform] = s;
|
||||
}
|
||||
}
|
||||
|
||||
FString GetExpansionFilesPath()
|
||||
{
|
||||
return (uint8)OculusTargetPlatform < OculusExpansionFilesPath.Num() ? OculusExpansionFilesPath[(uint8)OculusTargetPlatform] : "";
|
||||
}
|
||||
void SetExpansionFilesPath(FString s)
|
||||
{
|
||||
if (OculusTargetPlatform < EOculusXRPlatformTarget::Length)
|
||||
{
|
||||
OculusExpansionFilesPath[(uint8)OculusTargetPlatform] = s;
|
||||
}
|
||||
}
|
||||
|
||||
FString GetSymbolDirPath()
|
||||
{
|
||||
return (uint8)OculusTargetPlatform < OculusSymbolDirPath.Num() ? OculusSymbolDirPath[(uint8)OculusTargetPlatform] : "";
|
||||
}
|
||||
void SetSymbolDirPath(FString s)
|
||||
{
|
||||
if (OculusTargetPlatform < EOculusXRPlatformTarget::Length)
|
||||
{
|
||||
OculusSymbolDirPath[(uint8)OculusTargetPlatform] = s;
|
||||
}
|
||||
}
|
||||
|
||||
TArray<FOculusXRAssetConfig>* GetAssetConfigs()
|
||||
{
|
||||
return (uint8)OculusTargetPlatform < OculusAssetConfigs.Num() ? &OculusAssetConfigs[(uint8)OculusTargetPlatform].ConfigArray : nullptr;
|
||||
}
|
||||
|
||||
UPROPERTY(config, EditAnywhere, Category = MetaXR)
|
||||
FString OculusRiftBuildDirectory;
|
||||
|
||||
UPROPERTY(config, EditAnywhere, Category = MetaXR)
|
||||
FString OculusRiftBuildVersion;
|
||||
|
||||
UPROPERTY(config, EditAnywhere, Category = MetaXR)
|
||||
FString OculusRiftLaunchParams;
|
||||
|
||||
UPROPERTY(config, EditAnywhere, Category = MetaXR)
|
||||
bool OculusRiftFireWallException;
|
||||
|
||||
UPROPERTY(config, EditAnywhere, Category = MetaXR)
|
||||
FString OculusRift2DLaunchPath;
|
||||
|
||||
UPROPERTY(config, EditAnywhere, Category = MetaXR)
|
||||
FString OculusRift2DLaunchParams;
|
||||
|
||||
UPROPERTY(config, EditAnywhere, Category = MetaXR)
|
||||
TArray<FOculusXRRedistPackage> OculusRedistPackages;
|
||||
|
||||
UPROPERTY(config, EditAnywhere, Category = MetaXR)
|
||||
bool UploadDebugSymbols;
|
||||
|
||||
UPROPERTY(config, EditAnywhere, Category = MetaXR)
|
||||
bool DebugSymbolsOnly;
|
||||
|
||||
UPROPERTY(config, EditAnywhere, Category = MetaXR)
|
||||
FString BuildID;
|
||||
|
||||
private:
|
||||
UPROPERTY(config, EditAnywhere, Category = MetaXR)
|
||||
EOculusXRPlatformTarget OculusTargetPlatform;
|
||||
|
||||
UPROPERTY(config, EditAnywhere, Category = MetaXR)
|
||||
TArray<FString> OculusApplicationID;
|
||||
|
||||
UPROPERTY(config, EditAnywhere, Category = MetaXR)
|
||||
TArray<FString> OculusApplicationToken;
|
||||
|
||||
UPROPERTY(config, EditAnywhere, Category = MetaXR)
|
||||
TArray<FString> OculusReleaseChannel;
|
||||
|
||||
UPROPERTY(config, EditAnywhere, Category = MetaXR)
|
||||
TArray<FString> OculusReleaseNote;
|
||||
|
||||
UPROPERTY(config, EditAnywhere, Category = MetaXR)
|
||||
TArray<FString> OculusLaunchFilePath;
|
||||
|
||||
UPROPERTY(config, EditAnywhere, Category = MetaXR)
|
||||
EOculusXRGamepadEmulation OculusRiftGamepadEmulation;
|
||||
|
||||
UPROPERTY(config, EditAnywhere, Category = MetaXR)
|
||||
TArray<FString> OculusLanguagePacksPath;
|
||||
|
||||
UPROPERTY(config, EditAnywhere, Category = MetaXR)
|
||||
TArray<FString> OculusExpansionFilesPath;
|
||||
|
||||
UPROPERTY(config, EditAnywhere, Category = MetaXR)
|
||||
TArray<FString> OculusSymbolDirPath;
|
||||
|
||||
UPROPERTY(config, EditAnywhere, Category = MetaXR)
|
||||
TArray<FOculusXRAssetConfigArray> OculusAssetConfigs;
|
||||
};
|
||||
Reference in New Issue
Block a user