From 69d59ec862dc3dbb8f24ad19c2334f3deab52dfa Mon Sep 17 00:00:00 2001 From: Sebastian Pape <Sebastian.Pape@rwth-aachen.de> Date: Wed, 16 Oct 2019 16:16:02 +0200 Subject: [PATCH] Refactored and renamed all classes to not have "CAVE" in their name, since this plugin also works with ROLV and Desktop --- NDisplayLaunchButton.uplugin | 23 +++ Resources/NDisplay_40x.png | Bin 0 -> 384 bytes .../NDisplayLaunchButton.Build.cs | 59 ++++++ .../Private/NDisplayLaunchButton.cpp | 168 ++++++++++++++++++ .../Private/NDisplayLaunchButtonCommands.cpp | 13 ++ .../Private/NDisplayLaunchButtonStyle.cpp | 56 ++++++ .../Private/SocketHelper.h | 65 +++++++ .../Public/NDisplayLaunchButton.h | 29 +++ .../Public/NDisplayLaunchButtonCommands.h | 23 +++ .../Public/NDisplayLaunchButtonSettings.h | 116 ++++++++++++ .../Public/NDisplayLaunchButtonStyle.h | 31 ++++ 11 files changed, 583 insertions(+) create mode 100644 NDisplayLaunchButton.uplugin create mode 100644 Resources/NDisplay_40x.png create mode 100644 Source/NDisplayLaunchButton/NDisplayLaunchButton.Build.cs create mode 100644 Source/NDisplayLaunchButton/Private/NDisplayLaunchButton.cpp create mode 100644 Source/NDisplayLaunchButton/Private/NDisplayLaunchButtonCommands.cpp create mode 100644 Source/NDisplayLaunchButton/Private/NDisplayLaunchButtonStyle.cpp create mode 100644 Source/NDisplayLaunchButton/Private/SocketHelper.h create mode 100644 Source/NDisplayLaunchButton/Public/NDisplayLaunchButton.h create mode 100644 Source/NDisplayLaunchButton/Public/NDisplayLaunchButtonCommands.h create mode 100644 Source/NDisplayLaunchButton/Public/NDisplayLaunchButtonSettings.h create mode 100644 Source/NDisplayLaunchButton/Public/NDisplayLaunchButtonStyle.h diff --git a/NDisplayLaunchButton.uplugin b/NDisplayLaunchButton.uplugin new file mode 100644 index 0000000..988d95d --- /dev/null +++ b/NDisplayLaunchButton.uplugin @@ -0,0 +1,23 @@ +{ + "FileVersion": 3, + "Version": 1, + "VersionName": "1.0", + "FriendlyName": "NDisplayLaunchButton", + "Description": "", + "Category": "Other", + "CreatedBy": "", + "CreatedByURL": "", + "DocsURL": "", + "MarketplaceURL": "", + "SupportURL": "", + "CanContainContent": true, + "IsBetaVersion": false, + "EnabledByDefault" : true, + "Modules": [ + { + "Name": "NDisplayLaunchButton", + "Type": "Editor", + "LoadingPhase": "Default" + } + ] +} \ No newline at end of file diff --git a/Resources/NDisplay_40x.png b/Resources/NDisplay_40x.png new file mode 100644 index 0000000000000000000000000000000000000000..810021b85a32e7e5129a3e0872474ccef6e6a0c1 GIT binary patch literal 384 zcmeAS@N?(olHy`uVBq!ia0y~yV9)?z4mJh`hMs>rav2yH*pj^6T^Rm@;DWu&Co?cG zntHl8hD5Z!oxazL#ZaX6{JFFL_VljcDBITkTcD{obe8J}$s<XL)~i|L4|r|da4Rb? z<zsHj9G^96Y7cZ$-i5mDh!<6xe0X}&vm%Dp;|n6!Y|9I@ir^1OYmgS2_WZX=|NQfL zapLRNt@%E)lG#FObIlH$S<DTYW?t;o+rls0*dqV0v!AQvdt5X_=YrMR)m23f%9F(- z>cYP4xYxF4(ajGI+hiDgcpfb7ZnNpnv1E|o<=ylBVZx+>-(k<C-#z&Evvux7jyM^y z-1l#nyiM{CKR)-<vg@-qyi5DizCuA<^vR;8n2-tH?^)|h#f~d`2maGuIN77LgKcG> z@V=y#e1h}1OXs}zQ@Wz)G%w(|r;>`5OV5#dQ^6@O1Pp~_mw#XE$GQ_{OqKqO9;=sp gigydA=+!VDTvsW6zqNfW0|Nttr>mdKI;Vst08(0|&Hw-a literal 0 HcmV?d00001 diff --git a/Source/NDisplayLaunchButton/NDisplayLaunchButton.Build.cs b/Source/NDisplayLaunchButton/NDisplayLaunchButton.Build.cs new file mode 100644 index 0000000..2406882 --- /dev/null +++ b/Source/NDisplayLaunchButton/NDisplayLaunchButton.Build.cs @@ -0,0 +1,59 @@ +// Copyright 1998-2019 Epic Games, Inc. All Rights Reserved. + +using UnrealBuildTool; + +public class NDisplayLaunchButton : ModuleRules +{ + public NDisplayLaunchButton(ReadOnlyTargetRules Target) : base(Target) + { + PCHUsage = ModuleRules.PCHUsageMode.UseExplicitOrSharedPCHs; + + PublicIncludePaths.AddRange( + new string[] { + // ... add public include paths required here ... + } + ); + + + PrivateIncludePaths.AddRange( + new string[] { + // ... add other private include paths required here ... + } + ); + + + PublicDependencyModuleNames.AddRange( + new string[] + { + "Core", + // ... add other public dependencies that you statically link with here ... + } + ); + + + PrivateDependencyModuleNames.AddRange( + new string[] + { + "Projects", + "InputCore", + "UnrealEd", + "LevelEditor", + "CoreUObject", + "Engine", + "Slate", + "SlateCore", + "Sockets", + "Networking" + // ... add private dependencies that you statically link with here ... + } + ); + + + DynamicallyLoadedModuleNames.AddRange( + new string[] + { + // ... add any modules that your module loads dynamically here ... + } + ); + } +} diff --git a/Source/NDisplayLaunchButton/Private/NDisplayLaunchButton.cpp b/Source/NDisplayLaunchButton/Private/NDisplayLaunchButton.cpp new file mode 100644 index 0000000..a71a7b6 --- /dev/null +++ b/Source/NDisplayLaunchButton/Private/NDisplayLaunchButton.cpp @@ -0,0 +1,168 @@ +// Copyright 1998-2019 Epic Games, Inc. All Rights Reserved. +#include "NDisplayLaunchButton.h" + +#include "NDisplayLaunchButtonStyle.h" +#include "NDisplayLaunchButtonSettings.h" +#include "NDisplayLaunchButtonCommands.h" +#include "Misc/MessageDialog.h" +#include "Framework/MultiBox/MultiBoxBuilder.h" +#include "IPluginManager.h" +#include "Misc/EngineVersion.h" +#include "Networking.h" +#include "SocketHelper.h" +#include "LevelEditor.h" +#include "FileHelpers.h" + +DEFINE_LOG_CATEGORY(LogNDisplayLaunchButton); + +void FNDisplayLaunchButtonModule::StartupModule() +{ + const UNDisplayLaunchButtonSettings* Settings = GetDefault<UNDisplayLaunchButtonSettings>(); + FNDisplayLaunchButtonStyle::Initialize(); + FNDisplayLaunchButtonStyle::ReloadTextures(); + FNDisplayLaunchButtonCommands::Register(); + + TSharedPtr<class FUICommandList> PluginCommands = MakeShareable(new FUICommandList); + PluginCommands->MapAction( + FNDisplayLaunchButtonCommands::Get().PluginAction, + FExecuteAction::CreateRaw(this, &FNDisplayLaunchButtonModule::PluginButtonClicked), + FCanExecuteAction()); + + FLevelEditorModule& LevelEditorModule = FModuleManager::LoadModuleChecked<FLevelEditorModule>("LevelEditor"); + TSharedPtr<FExtender> ToolbarExtender = MakeShareable(new FExtender); + ToolbarExtender->AddToolBarExtension("Game", EExtensionHook::First, PluginCommands, FToolBarExtensionDelegate::CreateLambda([](FToolBarBuilder& Builder) + { + Builder.AddToolBarButton(FNDisplayLaunchButtonCommands::Get().PluginAction); + })); + LevelEditorModule.GetToolBarExtensibilityManager()->AddExtender(ToolbarExtender); +} + +void FNDisplayLaunchButtonModule::ShutdownModule() +{ + FNDisplayLaunchButtonStyle::Shutdown(); + FNDisplayLaunchButtonCommands::Unregister(); +} + +void FNDisplayLaunchButtonModule::PluginButtonClicked() +{ + const UNDisplayLaunchButtonSettings* Settings = GetDefault<UNDisplayLaunchButtonSettings>(); + if (Settings->LaunchType == NONE) + { + GEngine->AddOnScreenDebugMessage(-1, 3, FColor::White, TEXT("The Button is set to do nothing.")); + return; + } + + if (!UEditorLoadingAndSavingUtils::SaveDirtyPackagesWithDialog(true, true)) return; + + // minimize the root window to provide max performance for the preview. + TSharedPtr<SWindow> RootWindow = FGlobalTabmanager::Get()->GetRootWindow(); + if (RootWindow.IsValid()) RootWindow->Minimize(); + + if (Settings->LaunchType == ROLV) + { + FString EditorExecutable = "UE4Editor.exe"; + FString Parameters = "\"" + FPaths::GetProjectFilePath() + "\" -game dc_cfg=\"" + Settings->RolvConfig.FilePath + "\"" + ((Settings->ROLVLogToProjectDir) ? ("-log ABSLOG=" + FPaths::ProjectDir() + "\\ROLV_Launch.log") : ""); + + FProcHandle VRPN; + ProjectorDisplayType ModeFromBefore = DisplayType_Error; + if (Settings->StartVRPN) VRPN = FPlatformProcess::CreateProc(*Settings->VRPNPath.FilePath, *FString("-f \"" + Settings->VRPNConfigPath.FilePath + "\" -millisleep 0"), false, false, false, nullptr, 0, nullptr, nullptr); + if (Settings->StartDTrack) SendToDTrack(Settings->DTrackIP, Settings->DTrackPort, "dtrack2 tracking start\0"); + if (Settings->SwitchProjector) ModeFromBefore = SwitchProjectorToState(Settings->ProjectorIP, Settings->ProjectorPort, Settings->ProjectorType); + + FProcHandle Instance = FPlatformProcess::CreateProc(*EditorExecutable, *(Parameters + " " + Settings->ROLVLaunchParameters), true, false, false, nullptr, 0, nullptr, nullptr); + FPlatformProcess::WaitForProc(Instance); + + if (Settings->StartVRPN) FPlatformProcess::TerminateProc(VRPN); + FPlatformProcess::CloseProc(VRPN); + if (Settings->StartDTrack) SendToDTrack(Settings->DTrackIP, Settings->DTrackPort, "dtrack2 tracking stop\0"); + if (Settings->SwitchProjector && ModeFromBefore != DisplayType_Error) SwitchProjectorToState(Settings->ProjectorIP, Settings->ProjectorPort, ModeFromBefore); + } + + if (Settings->LaunchType == MiniCAVE) + { + FString Config = IPluginManager::Get().FindPlugin("CAVELaunchButton")->GetBaseDir() + "/LaunchConfig/minicave.cfg"; + FString EditorExecutable = "UE4Editor.exe"; + FString Parameters = "\"" + FPaths::GetProjectFilePath() + "\" -game dc_cfg=\"" + Config + "\" " + Settings->MiniCAVELaunchParameters; + + const int Num_Nodes = 5; + FString Windows_Node_Specific_Commands[Num_Nodes] = { + "dc_node=node_floor WinX=720 WinY=300 ResX=480 ResY=480" + ((Settings->MiniCAVELogToProjectDir) ? (" -log ABSLOG=" + FPaths::ProjectDir() + "\\MiniCaveMulti.log") : "") + " " + Settings->MiniCAVEAdditionalLaunchParametersMaster, + "dc_node=node_front WinX=720 WinY=0 ResX=480 ResY=300", + "dc_node=node_left WinX=420 WinY=300 ResX=300 ResY=480", + "dc_node=node_right WinX=1200 WinY=300 ResX=300 ResY=480", + "dc_node=node_back WinX=720 WinY=780 ResX=480 ResY=300" + }; + + FProcHandle Processes[Num_Nodes]; + for (int i = 0; i < Num_Nodes; i++) + { + Processes[i] = FPlatformProcess::CreateProc(*EditorExecutable, *(Parameters + " " + Windows_Node_Specific_Commands[i]), true, false, false, nullptr, 0, nullptr, nullptr); + } + FPlatformProcess::WaitForProc(Processes[Num_Nodes - 1]); //wait for only one of them + } + + if (Settings->LaunchType == CAVE) + { + FProcHandle Instance = FPlatformProcess::CreateProc( + *Settings->CAVELaunchScriptPath.FilePath, + *("\"" + (FPaths::ConvertRelativePathToFull(".") + "/UE4Editor\"") + + " " + FPaths::ConvertRelativePathToFull(FPaths::GetProjectFilePath()) + + " " + FString::FromInt(FEngineVersion::Current().GetMajor()) + + FString::FromInt(FEngineVersion::Current().GetMinor())), + true, false, false, nullptr, 0, nullptr, nullptr); + FPlatformProcess::WaitForProc(Instance); + } + + if (RootWindow.IsValid()) RootWindow->Maximize(); +} + +void FNDisplayLaunchButtonModule::SendToDTrack(FString Address, int Port, FString Message) +{ + FSocket* Socket = USocketHelper::OpenSocket(Address, Port, "DTrackSocket"); + if (!Socket) return; + if (USocketHelper::SendSocket(Socket, Message) <= 0) return; + FString Response = USocketHelper::ReceiveSocket<100>(Socket); + if (Response.Compare("dtrack2 ok") != 0) + { + UE_LOG(LogTemp, Error, TEXT("DTrack Command Failed. Response: '%s'"), *Response); + } + Socket->Shutdown(ESocketShutdownMode::ReadWrite); + Socket->Close(); +} + +//Returns old state +ProjectorDisplayType FNDisplayLaunchButtonModule::SwitchProjectorToState(FString Address, int Port, ProjectorDisplayType State) +{ + ProjectorDisplayType ModeBefore = ProjectorDisplayType::DisplayType_Error; + FSocket* Socket = USocketHelper::OpenSocket(Address, Port, "ProjectorSocket"); + if (!Socket) return ModeBefore; + + //Get mode from before + if (USocketHelper::SendSocket(Socket, ":TDSM ?\r") <= 0) return ModeBefore; + FString Response = USocketHelper::ReceiveSocket<100>(Socket); //Response looks like: %001 TDSM 000000 + + if (!Response.IsEmpty()) + { + int32 Position = 0; + Response.FindLastChar(' ', Position); + ModeBefore = static_cast<ProjectorDisplayType>(FCString::Atoi(*Response.RightChop(Position))); + } + + if (Response.IsEmpty() || USocketHelper::SendSocket(Socket, ":TDSM " + FString::FromInt(State) + "\r") <= 0) + { + Socket->Shutdown(ESocketShutdownMode::ReadWrite); + Socket->Close(); + return ModeBefore; + } + Response = USocketHelper::ReceiveSocket<100>(Socket); + if (Response.EndsWith(")")) + { + //Errors are marked like this + UE_LOG(LogTemp, Error, TEXT("Projector Type Change Failed. Response: '%s'"), *Response); + } + Socket->Shutdown(ESocketShutdownMode::ReadWrite); + Socket->Close(); + return ModeBefore; +} + +IMPLEMENT_MODULE(FNDisplayLaunchButtonModule, NDisplayLaunchButton) diff --git a/Source/NDisplayLaunchButton/Private/NDisplayLaunchButtonCommands.cpp b/Source/NDisplayLaunchButton/Private/NDisplayLaunchButtonCommands.cpp new file mode 100644 index 0000000..230f98f --- /dev/null +++ b/Source/NDisplayLaunchButton/Private/NDisplayLaunchButtonCommands.cpp @@ -0,0 +1,13 @@ +// Copyright 1998-2019 Epic Games, Inc. All Rights Reserved. + +#include "NDisplayLaunchButtonCommands.h" +#include "NDisplayLaunchButtonSettings.h" + +#define LOCTEXT_NAMESPACE "FNDisplayLaunchButtonModule" + +void FNDisplayLaunchButtonCommands::RegisterCommands() +{ + UI_COMMAND(PluginAction, "N-Display", "Launch current project via N-Display", EUserInterfaceActionType::Button, FInputChord()); +} + +#undef LOCTEXT_NAMESPACE diff --git a/Source/NDisplayLaunchButton/Private/NDisplayLaunchButtonStyle.cpp b/Source/NDisplayLaunchButton/Private/NDisplayLaunchButtonStyle.cpp new file mode 100644 index 0000000..82a9ae4 --- /dev/null +++ b/Source/NDisplayLaunchButton/Private/NDisplayLaunchButtonStyle.cpp @@ -0,0 +1,56 @@ +// Copyright 1998-2019 Epic Games, Inc. All Rights Reserved. + +#include "NDisplayLaunchButtonStyle.h" +#include "NDisplayLaunchButton.h" +#include "Framework/Application/SlateApplication.h" +#include "Styling/SlateStyleRegistry.h" +#include "Slate/SlateGameResources.h" +#include "Interfaces/IPluginManager.h" + +TSharedPtr< FSlateStyleSet > FNDisplayLaunchButtonStyle::StyleInstance = NULL; + +void FNDisplayLaunchButtonStyle::Initialize() +{ + if (!StyleInstance.IsValid()) + { + StyleInstance = Create(); + FSlateStyleRegistry::RegisterSlateStyle(*StyleInstance); + } +} + +void FNDisplayLaunchButtonStyle::Shutdown() +{ + FSlateStyleRegistry::UnRegisterSlateStyle(*StyleInstance); + ensure(StyleInstance.IsUnique()); + StyleInstance.Reset(); +} + +FName FNDisplayLaunchButtonStyle::GetStyleSetName() +{ + static FName StyleSetName(TEXT("NDisplayLaunchButtonStyle")); + return StyleSetName; +} + +TSharedRef< FSlateStyleSet > FNDisplayLaunchButtonStyle::Create() +{ + TSharedRef< FSlateStyleSet > Style = MakeShareable(new FSlateStyleSet("NDisplayLaunchButtonStyle")); + Style->SetContentRoot(IPluginManager::Get().FindPlugin("NDisplayLaunchButton")->GetBaseDir() / TEXT("Resources")); + + const FVector2D Icon40x40(40.0f, 40.0f); + Style->Set("NDisplayLaunchButton.PluginAction", new FSlateImageBrush(Style->RootToContentDir(TEXT("NDisplay_40x"), TEXT(".png")), Icon40x40));; + + return Style; +} + +void FNDisplayLaunchButtonStyle::ReloadTextures() +{ + if (FSlateApplication::IsInitialized()) + { + FSlateApplication::Get().GetRenderer()->ReloadTextureResources(); + } +} + +const ISlateStyle& FNDisplayLaunchButtonStyle::Get() +{ + return *StyleInstance; +} diff --git a/Source/NDisplayLaunchButton/Private/SocketHelper.h b/Source/NDisplayLaunchButton/Private/SocketHelper.h new file mode 100644 index 0000000..1384bff --- /dev/null +++ b/Source/NDisplayLaunchButton/Private/SocketHelper.h @@ -0,0 +1,65 @@ +#pragma once +#include <string> + +#include "CoreMinimal.h" +#include "Sockets.h" +#include "IPv4Address.h" +#include "IPv4Endpoint.h" +#include "TcpSocketBuilder.h" +#include "SocketHelper.generated.h" + +DECLARE_LOG_CATEGORY_CLASS(LogNDisplayLaunchButtonSockerHelper, Log, All); + +UCLASS() +class USocketHelper : public UObject{ + GENERATED_BODY() + +public: + + static FSocket* OpenSocket(FString Address, int Port, FString SocketName) { + FIPv4Address ParsedAddress; + if (!FIPv4Address::Parse(Address, ParsedAddress)) { + UE_LOG(LogNDisplayLaunchButtonSockerHelper, Error, TEXT("Could not parse Address %s"), *Address); + return nullptr; + } + + FIPv4Endpoint Endpoint(ParsedAddress, Port); + FSocket* Socket = FTcpSocketBuilder(*SocketName); + if (!Socket->Connect(Endpoint.ToInternetAddr().Get())) + { + UE_LOG(LogNDisplayLaunchButtonSockerHelper, Error, TEXT("Error connecting to server %s:%d via %s"), *Address, Port, *SocketName); + Socket->Close(); + return nullptr; + } + return Socket; + } + + static int32 SendSocket(FSocket* Socket, FString Message) { + Socket->Wait(ESocketWaitConditions::WaitForWrite, FTimespan::FromSeconds(5)); + std::string Buffer = std::string(TCHAR_TO_UTF8(*Message)); + int32 Sent = 0; + if (!Socket->Send(reinterpret_cast<const uint8 *>(Buffer.c_str()), Buffer.length(), Sent)) + { + UE_LOG(LogNDisplayLaunchButtonSockerHelper, Error, TEXT("Error sending via %s. Sent %d bytes"), *Socket->GetDescription(), Sent); + Socket->Close(); + } + return Sent; + } + + template<int32 BufferSize> static FString ReceiveSocket(FSocket* Socket) { + Socket->Wait(ESocketWaitConditions::WaitForRead, FTimespan::FromSeconds(5)); + char ReceiveBuffer[BufferSize]; + int BytesReceived = 0; + if (!Socket->Recv(reinterpret_cast<uint8*>(&ReceiveBuffer), BufferSize, BytesReceived)) { + UE_LOG(LogNDisplayLaunchButtonSockerHelper, Error, TEXT("No valid response from %s. Response: '%s'"), *Socket->GetDescription(), *FString(std::string(ReceiveBuffer, BytesReceived).c_str())); + Socket->Close(); + } + if (BytesReceived <= 0) return FString(""); + return FString(std::string(ReceiveBuffer, BytesReceived).c_str()); + } + + static void CloseSocket(FSocket* Socket) { + Socket->Shutdown(ESocketShutdownMode::ReadWrite); + Socket->Close(); + } +}; diff --git a/Source/NDisplayLaunchButton/Public/NDisplayLaunchButton.h b/Source/NDisplayLaunchButton/Public/NDisplayLaunchButton.h new file mode 100644 index 0000000..5a228c5 --- /dev/null +++ b/Source/NDisplayLaunchButton/Public/NDisplayLaunchButton.h @@ -0,0 +1,29 @@ +// Copyright 1998-2019 Epic Games, Inc. All Rights Reserved. + +#pragma once + +#include "CoreMinimal.h" +#include "Modules/ModuleManager.h" +#include "NDisplayLaunchButtonSettings.h" +#include "LogMacros.h" +#include "Framework/MultiBox/MultiBoxBuilder.h" + +class FToolBarBuilder; +class FMenuBuilder; + +DECLARE_LOG_CATEGORY_EXTERN(LogNDisplayLaunchButton, Log, All); + +class FNDisplayLaunchButtonModule : public IModuleInterface +{ +public: + + /** IModuleInterface implementation */ + virtual void StartupModule() override; + virtual void ShutdownModule() override; + + /** This function will be bound to Command. */ + void PluginButtonClicked(); + + void SendToDTrack(FString Address, int Port, FString Message); + ProjectorDisplayType SwitchProjectorToState(FString Address, int Port, ProjectorDisplayType State); +}; diff --git a/Source/NDisplayLaunchButton/Public/NDisplayLaunchButtonCommands.h b/Source/NDisplayLaunchButton/Public/NDisplayLaunchButtonCommands.h new file mode 100644 index 0000000..5c2f355 --- /dev/null +++ b/Source/NDisplayLaunchButton/Public/NDisplayLaunchButtonCommands.h @@ -0,0 +1,23 @@ +// Copyright 1998-2019 Epic Games, Inc. All Rights Reserved. + +#pragma once + +#include "CoreMinimal.h" +#include "Framework/Commands/Commands.h" +#include "NDisplayLaunchButtonStyle.h" + +class FNDisplayLaunchButtonCommands : public TCommands<FNDisplayLaunchButtonCommands> +{ +public: + + FNDisplayLaunchButtonCommands() + : TCommands<FNDisplayLaunchButtonCommands>(TEXT("NDisplayLaunchButton"), NSLOCTEXT("Contexts", "NDisplayLaunchButton", "NDisplayLaunchButton Plugin"), NAME_None, FNDisplayLaunchButtonStyle::GetStyleSetName()) + { + } + + // TCommands<> interface + virtual void RegisterCommands() override; + +public: + TSharedPtr< FUICommandInfo > PluginAction; +}; diff --git a/Source/NDisplayLaunchButton/Public/NDisplayLaunchButtonSettings.h b/Source/NDisplayLaunchButton/Public/NDisplayLaunchButtonSettings.h new file mode 100644 index 0000000..160ed3c --- /dev/null +++ b/Source/NDisplayLaunchButton/Public/NDisplayLaunchButtonSettings.h @@ -0,0 +1,116 @@ +#pragma once +#include "CoreMinimal.h" +#include "Engine/EngineTypes.h" +#include "Engine/DeveloperSettings.h" +#include "NDisplayLaunchButtonSettings.generated.h" + +UENUM(BlueprintType) +enum ProjectorDisplayType +{ + DisplayType_Off = 0 UMETA(DisplayName = "Off"), + DisplayType_Frame_Sequential = 1 UMETA(DisplayName = "Frame Sequential"), + DisplayType_Side_By_Side = 2 UMETA(DisplayName = "Side By Side"), + DisplayType_DualHead = 3 UMETA(DisplayName = "Dual Head"), + DisplayType_Error = 4 UMETA(Hidden) +}; + +UENUM(BlueprintType) +enum ButtonLaunchType +{ + NONE UMETA(DisplayName = "Nothing"), + MiniCAVE UMETA(DisplayName = "MiniCAVE"), + CAVE UMETA(DisplayName = "CAVE"), + ROLV UMETA(DisplayName = "ROLV") +}; + +UCLASS(config=Engine, defaultconfig, meta=(DisplayName="nDisplay Launch Button")) +class UNDisplayLaunchButtonSettings : public UDeveloperSettings +{ + GENERATED_BODY() + +public: + UPROPERTY(EditAnywhere, config, Category = "General", meta = (DisplayName = "Start ")) + TEnumAsByte<ButtonLaunchType> LaunchType; + + /* + * Mini CAVE Options + */ + UPROPERTY(EditAnywhere, config, Category = "General|MiniCAVE", meta = (DisplayName = "Launch Parameters")) + FString MiniCAVELaunchParameters = "-dc_cluster -dc_dev_mono -windowed -fixedseed -notexturestreaming -opengl4"; + UPROPERTY(EditAnywhere, config, Category = "General|MiniCAVE", meta = (DisplayName = "Additioanl Launch Parameters for Master")) + FString MiniCAVEAdditionalLaunchParametersMaster = ""; + UPROPERTY(EditAnywhere, config, Category = "General|MiniCAVE", meta = (DisplayName = "Write Log to Project Directory")) + bool MiniCAVELogToProjectDir = true; + + /* + * CAVE Options + */ + UPROPERTY(EditAnywhere, config, Category = "General|CAVE", meta = (DisplayName = "Path to Launch Script")) + FFilePath CAVELaunchScriptPath; + + /* + * ROLV Options + */ + UPROPERTY(EditAnywhere, config, Category = "General|ROLV", meta = (DisplayName = "Path to the ROLV nDisplay Config")) + FFilePath RolvConfig; + UPROPERTY(EditAnywhere, config, Category = "General|ROLV", meta = (DisplayName = "Launch Parameters")) + FString ROLVLaunchParameters = "-dc_cluster -nosplash -fixedseed -dx11 -dc_dev_side_by_side -notexturestreaming -fullscreen dc_node=node_main"; + UPROPERTY(EditAnywhere, config, Category = "General|ROLV", meta = (DisplayName = "Write Log to Project Directory")) + bool ROLVLogToProjectDir = true; + + UPROPERTY(EditAnywhere, config, Category = "General|ROLV|Projector", meta = (DisplayName = "Change Projector Mode on Startup")) + bool SwitchProjector = true; + UPROPERTY(EditAnywhere, config, Category = "General|ROLV|Projector", meta = (DisplayName = "Switch to ")) + TEnumAsByte<ProjectorDisplayType> ProjectorType; + UPROPERTY(EditAnywhere, config, Category = "General|ROLV|Projector", meta = (DisplayName = "Projector IP")) + FString ProjectorIP; + UPROPERTY(EditAnywhere, config, Category = "General|ROLV|Projector", meta = (DisplayName = "Projector Port")) + int ProjectorPort = 1025; + + UPROPERTY(EditAnywhere, config, Category = "General|ROLV|VRPN", meta = (DisplayName = "Start VRPN in the Background")) + bool StartVRPN = true; + UPROPERTY(EditAnywhere, config, Category = "General|ROLV|VRPN", meta = (DisplayName = "Path to VRPN Executable")) + FFilePath VRPNPath; + UPROPERTY(EditAnywhere, config, Category = "General|ROLV|VRPN", meta = (DisplayName = "Path to VRPN Config")) + FFilePath VRPNConfigPath; + + UPROPERTY(EditAnywhere, config, Category = "General|ROLV|DTRACK", meta = (DisplayName = "Start DTrack in the Background")) + bool StartDTrack = true; + UPROPERTY(EditAnywhere, config, Category = "General|ROLV|DTRACK", meta = (DisplayName = "DTrack IP")) + FString DTrackIP; + UPROPERTY(EditAnywhere, config, Category = "General|ROLV|DTRACK", meta = (DisplayName = "DTrack Port")) + int DTrackPort = 50105; + + //Macro used to shorten code +#define PROPERTY_CONDITION_CHECK(Variable, Condition) if (InProperty->GetFName() == GET_MEMBER_NAME_CHECKED(UNDisplayLaunchButtonSettings, Variable)) return Condition; + + bool CanEditChange(const UProperty* InProperty) const override + { + const bool ParentVal = Super::CanEditChange(InProperty); + + //TODO: This Code is not executed for all FFilePath Properties. Check if this works in 4.23 with the EditCondition Parser and remove this method + + PROPERTY_CONDITION_CHECK(MiniCAVELaunchParameters, LaunchType == MiniCAVE) + PROPERTY_CONDITION_CHECK(MiniCAVEAdditionalLaunchParametersMaster, LaunchType == MiniCAVE) + PROPERTY_CONDITION_CHECK(MiniCAVELogToProjectDir, LaunchType == MiniCAVE) + + PROPERTY_CONDITION_CHECK(CAVELaunchScriptPath, LaunchType == CAVE) + + PROPERTY_CONDITION_CHECK(RolvConfig, LaunchType == ROLV) + PROPERTY_CONDITION_CHECK(ROLVLaunchParameters, LaunchType == ROLV) + PROPERTY_CONDITION_CHECK(ROLVLogToProjectDir, LaunchType == ROLV) + PROPERTY_CONDITION_CHECK(SwitchProjector, LaunchType == ROLV) + PROPERTY_CONDITION_CHECK(ProjectorType, LaunchType == ROLV && SwitchProjector) + PROPERTY_CONDITION_CHECK(ProjectorIP, LaunchType == ROLV && SwitchProjector) + PROPERTY_CONDITION_CHECK(ProjectorPort, LaunchType == ROLV && SwitchProjector) + PROPERTY_CONDITION_CHECK(VRPNConfigPath, LaunchType == ROLV && StartVRPN) + PROPERTY_CONDITION_CHECK(StartVRPN, LaunchType == ROLV) + PROPERTY_CONDITION_CHECK(VRPNPath, LaunchType == ROLV && StartVRPN) + PROPERTY_CONDITION_CHECK(VRPNConfigPath, LaunchType == ROLV && StartVRPN) + PROPERTY_CONDITION_CHECK(StartDTrack, LaunchType == ROLV) + PROPERTY_CONDITION_CHECK(DTrackIP, LaunchType == ROLV && StartDTrack) + PROPERTY_CONDITION_CHECK(DTrackPort, LaunchType == ROLV && StartDTrack) + + return ParentVal; + } +}; diff --git a/Source/NDisplayLaunchButton/Public/NDisplayLaunchButtonStyle.h b/Source/NDisplayLaunchButton/Public/NDisplayLaunchButtonStyle.h new file mode 100644 index 0000000..2ab4108 --- /dev/null +++ b/Source/NDisplayLaunchButton/Public/NDisplayLaunchButtonStyle.h @@ -0,0 +1,31 @@ +// Copyright 1998-2019 Epic Games, Inc. All Rights Reserved. + +#pragma once + +#include "CoreMinimal.h" +#include "Styling/SlateStyle.h" + +class FNDisplayLaunchButtonStyle +{ +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; +}; -- GitLab