From 9f468ebbd27341163891bcc682b47981a16081ed Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Rombauts?= Date: Mon, 15 Jan 2024 16:40:10 +0100 Subject: [PATCH 1/4] Implement FPlasticSourceControlMenu::OpenDeskoptApp() - Checks the Windows Registry to find Unity Version Control install location - Implemented and test for both the regular "Plastic" GUI and Gluon Also implemented the correct application & path for MacOS and symlinks for Linux, but they are not supported and not tested at all. --- Resources/gluon.ico | Bin 0 -> 60494 bytes .../Private/PlasticSourceControlMenu.cpp | 65 +++++++++++++++++- .../Private/PlasticSourceControlMenu.h | 1 + .../Private/PlasticSourceControlStyle.cpp | 1 + 4 files changed, 66 insertions(+), 1 deletion(-) create mode 100644 Resources/gluon.ico diff --git a/Resources/gluon.ico b/Resources/gluon.ico new file mode 100644 index 0000000000000000000000000000000000000000..5c326e4c13682da05e0bd4fefa0688e046a3e1a3 GIT binary patch literal 60494 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

-7SV|&}2aGUQ53tL%c72b0Z>rNp>>>b5 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%0Ad?cZ;r5ZlrsntPu~?HP(%V=N4<14 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 1 #include "Styling/AppStyle.h" #else @@ -31,6 +33,11 @@ #include "ToolMenus.h" #include "ToolMenuMisc.h" +#if PLATFORM_WINDOWS +#include "Windows/AllowWindowsPlatformTypes.h" +#include "Windows/WindowsPlatformMisc.h" +#endif + #define LOCTEXT_NAMESPACE "PlasticSourceControl" FName FPlasticSourceControlMenu::UnityVersionControlMainMenuOwnerName = TEXT("UnityVersionControlMenu"); @@ -529,6 +536,41 @@ void FPlasticSourceControlMenu::VisitLockRulesURLClicked(const FString InOrganiz FPlatformProcess::LaunchURL(*OrganizationLockRulesURL, NULL, NULL); } +void FPlasticSourceControlMenu::OpenDeskoptApp() const +{ +#if PLATFORM_WINDOWS + // On Windows, use the registry to find the install location + FString InstallLocation = TEXT("C:/Program Files/PlasticSCM5"); + if (FWindowsPlatformMisc::QueryRegKey(HKEY_LOCAL_MACHINE, TEXT("SOFTWARE\\Unity Software Inc.\\Unity DevOps Version Control"), TEXT("Location"), InstallLocation)) + { + FPaths::NormalizeDirectoryName(InstallLocation); + } + + const TCHAR* PlasticExe = TEXT("client/plastic.exe"); + const TCHAR* GluonExe = TEXT("client/gluon.exe"); + const FString DeskoptAppPath = FPaths::Combine(InstallLocation, FPlasticSourceControlModule::Get().GetProvider().IsPartialWorkspace() ? GluonExe : PlasticExe); +#elif PLATFORM_MAC + const TCHAR* PlasticExe = "/Applications/PlasticSCM.app/Contents/MacOS/macplasticx"; + const TCHAR* GluonExe = "/Applications/Gluon.app/Contents/MacOS/macgluonx"; + const TCHAR* DeskoptAppPath = FPlasticSourceControlModule::Get().GetProvider().IsPartialWorkspace() ? GluonExe : PlasticExe); +#elif PLATFORM_LINUX + const TCHAR* PlasticExe = "/usr/bin/plasticgui "; + const TCHAR* GluonExe = "/usr/bin/gluon"; + const TCHAR* DeskoptAppPath = FPlasticSourceControlModule::Get().GetProvider().IsPartialWorkspace() ? GluonExe : PlasticExe); +#endif + + const FString CommandLineArguments = FString::Printf(TEXT("--wk=\"%s\""), *FPlasticSourceControlModule::Get().GetProvider().GetPathToWorkspaceRoot()); + + UE_LOG(LogSourceControl, Log, TEXT("Opening the Desktop application (%s %s)"), *InstallLocation, *CommandLineArguments); + + FProcHandle Proc = FPlatformProcess::CreateProc(*DeskoptAppPath, *CommandLineArguments, true, false, false, nullptr, 0, nullptr, nullptr, nullptr); + if (!Proc.IsValid()) + { + UE_LOG(LogSourceControl, Error, TEXT("Opening the Desktop application (%s %s) failed."), *DeskoptAppPath, *CommandLineArguments); + FPlatformProcess::CloseProc(Proc); + } +} + void FPlasticSourceControlMenu::OpenBranchesWindow() const { FPlasticSourceControlModule::Get().GetBranchesWindow().OpenTab(); @@ -566,6 +608,8 @@ void FPlasticSourceControlMenu::AddMenuExtension(FMenuBuilder& Menu) void FPlasticSourceControlMenu::AddMenuExtension(FToolMenuSection& Menu) #endif { + FPlasticSourceControlProvider& Provider = FPlasticSourceControlModule::Get().GetProvider(); + Menu.AddMenuEntry( #if ENGINE_MAJOR_VERSION == 5 "PlasticSync", @@ -750,6 +794,25 @@ void FPlasticSourceControlMenu::AddMenuExtension(FToolMenuSection& Menu) ); } + Menu.AddMenuEntry( +#if ENGINE_MAJOR_VERSION == 5 + "PlasticDesktopApp", +#endif + TAttribute::CreateLambda([&Provider]() + { + return Provider.IsPartialWorkspace() ? LOCTEXT("PlasticGluon", "Open in Gluon") : LOCTEXT("PlasticDesktopApp", "Open in Desktop App"); + }), + TAttribute::CreateLambda([&Provider]() + { + return Provider.IsPartialWorkspace() ? LOCTEXT("PlasticDesktopAppTooltip", "Open the workspace in Unity Version Control Gluon Application.") : LOCTEXT("PlasticGluonTooltip", "Open the workspace in Unity Version Control Desktop Application."); + }), + TAttribute::CreateLambda([&Provider]() + { + return FSlateIcon(FPlasticSourceControlStyle::Get().GetStyleSetName(), Provider.IsPartialWorkspace() ? "PlasticSourceControl.GluonIcon.Small" : "PlasticSourceControl.PluginIcon.Small"); + }), + FUIAction(FExecuteAction::CreateRaw(this, &FPlasticSourceControlMenu::OpenDeskoptApp)) + ); + AddViewBranches(Menu); } diff --git a/Source/PlasticSourceControl/Private/PlasticSourceControlMenu.h b/Source/PlasticSourceControl/Private/PlasticSourceControlMenu.h index d9fe4bf6..4d7b14a7 100644 --- a/Source/PlasticSourceControl/Private/PlasticSourceControlMenu.h +++ b/Source/PlasticSourceControl/Private/PlasticSourceControlMenu.h @@ -29,6 +29,7 @@ class FPlasticSourceControlMenu void VisitDocsURLClicked() const; void VisitSupportURLClicked() const; void VisitLockRulesURLClicked(const FString InOrganizationName) const; + void OpenDeskoptApp() const; void OpenBranchesWindow() const; private: diff --git a/Source/PlasticSourceControl/Private/PlasticSourceControlStyle.cpp b/Source/PlasticSourceControl/Private/PlasticSourceControlStyle.cpp index 1c8add02..5bd34250 100644 --- a/Source/PlasticSourceControl/Private/PlasticSourceControlStyle.cpp +++ b/Source/PlasticSourceControl/Private/PlasticSourceControlStyle.cpp @@ -45,6 +45,7 @@ TSharedRef FPlasticSourceControlStyle::Create() Style->SetContentRoot(FPlasticSourceControlModule::GetPlugin()->GetBaseDir() / TEXT("Resources")); Style->Set("PlasticSourceControl.PluginIcon.Small", new FSlateImageBrush(FPlasticSourceControlStyle::InContent("Icon128", ".png"), Icon16x16)); + Style->Set("PlasticSourceControl.GluonIcon.Small", new FSlateImageBrush(FPlasticSourceControlStyle::InContent("gluon", ".ico"), Icon16x16)); return Style; } From d01ec19c98e9aac3837c36d64c8aeed3e3469542 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Rombauts?= Date: Thu, 18 Jan 2024 13:04:11 +0100 Subject: [PATCH 2/4] Fix compilation for Unreal Engine 4.27 --- .../Private/PlasticSourceControlMenu.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/Source/PlasticSourceControl/Private/PlasticSourceControlMenu.cpp b/Source/PlasticSourceControl/Private/PlasticSourceControlMenu.cpp index fa2e5fad..20b5ba96 100644 --- a/Source/PlasticSourceControl/Private/PlasticSourceControlMenu.cpp +++ b/Source/PlasticSourceControl/Private/PlasticSourceControlMenu.cpp @@ -797,7 +797,6 @@ void FPlasticSourceControlMenu::AddMenuExtension(FToolMenuSection& Menu) Menu.AddMenuEntry( #if ENGINE_MAJOR_VERSION == 5 "PlasticDesktopApp", -#endif TAttribute::CreateLambda([&Provider]() { return Provider.IsPartialWorkspace() ? LOCTEXT("PlasticGluon", "Open in Gluon") : LOCTEXT("PlasticDesktopApp", "Open in Desktop App"); @@ -810,6 +809,11 @@ void FPlasticSourceControlMenu::AddMenuExtension(FToolMenuSection& Menu) { return FSlateIcon(FPlasticSourceControlStyle::Get().GetStyleSetName(), Provider.IsPartialWorkspace() ? "PlasticSourceControl.GluonIcon.Small" : "PlasticSourceControl.PluginIcon.Small"); }), +#else + Provider.IsPartialWorkspace() ? LOCTEXT("PlasticGluon", "Open in Gluon") : LOCTEXT("PlasticDesktopApp", "Open in Desktop App"), + Provider.IsPartialWorkspace() ? LOCTEXT("PlasticDesktopAppTooltip", "Open the workspace in Unity Version Control Gluon Application.") : LOCTEXT("PlasticGluonTooltip", "Open the workspace in Unity Version Control Desktop Application."), + FSlateIcon(FPlasticSourceControlStyle::Get().GetStyleSetName(), Provider.IsPartialWorkspace() ? "PlasticSourceControl.GluonIcon.Small" : "PlasticSourceControl.PluginIcon.Small"), +#endif FUIAction(FExecuteAction::CreateRaw(this, &FPlasticSourceControlMenu::OpenDeskoptApp)) ); From f87459a45515c467c152591e395b54fb55ccbdb5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Rombauts?= Date: Thu, 18 Jan 2024 13:06:32 +0100 Subject: [PATCH 3/4] Fix compilation: #undef GetUserName when including Windows symbols Only triggers an issue when bUseUnityBuild = true; in UE5PlasticPluginDevEditor.Target.cs (the default) since the Unity Builds principle make the imported Windows symbols bleeds into all other compiled files as well --- Source/PlasticSourceControl/Private/PlasticSourceControlMenu.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/Source/PlasticSourceControl/Private/PlasticSourceControlMenu.cpp b/Source/PlasticSourceControl/Private/PlasticSourceControlMenu.cpp index 20b5ba96..b21a9403 100644 --- a/Source/PlasticSourceControl/Private/PlasticSourceControlMenu.cpp +++ b/Source/PlasticSourceControl/Private/PlasticSourceControlMenu.cpp @@ -36,6 +36,7 @@ #if PLATFORM_WINDOWS #include "Windows/AllowWindowsPlatformTypes.h" #include "Windows/WindowsPlatformMisc.h" +#undef GetUserName #endif #define LOCTEXT_NAMESPACE "PlasticSourceControl" From 38f8bdde5b7a734472e6c7dc117c4cfc888ed577 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Rombauts?= Date: Thu, 18 Jan 2024 15:06:40 +0100 Subject: [PATCH 4/4] Move the OS dependant logic into a new PlasticSourceControlUtils::FindDesktopApplicationPath() --- .../Private/PlasticSourceControlMenu.cpp | 37 +++---------------- .../Private/PlasticSourceControlUtils.cpp | 34 +++++++++++++++++ .../Private/PlasticSourceControlUtils.h | 5 +++ 3 files changed, 45 insertions(+), 31 deletions(-) diff --git a/Source/PlasticSourceControl/Private/PlasticSourceControlMenu.cpp b/Source/PlasticSourceControl/Private/PlasticSourceControlMenu.cpp index b21a9403..080abfea 100644 --- a/Source/PlasticSourceControl/Private/PlasticSourceControlMenu.cpp +++ b/Source/PlasticSourceControl/Private/PlasticSourceControlMenu.cpp @@ -4,9 +4,10 @@ #include "PlasticSourceControlBranchesWindow.h" #include "PlasticSourceControlModule.h" +#include "PlasticSourceControlOperations.h" #include "PlasticSourceControlProvider.h" #include "PlasticSourceControlStyle.h" -#include "PlasticSourceControlOperations.h" +#include "PlasticSourceControlUtils.h" #include "SPlasticSourceControlStatusBar.h" #include "ISourceControlModule.h" @@ -33,12 +34,6 @@ #include "ToolMenus.h" #include "ToolMenuMisc.h" -#if PLATFORM_WINDOWS -#include "Windows/AllowWindowsPlatformTypes.h" -#include "Windows/WindowsPlatformMisc.h" -#undef GetUserName -#endif - #define LOCTEXT_NAMESPACE "PlasticSourceControl" FName FPlasticSourceControlMenu::UnityVersionControlMainMenuOwnerName = TEXT("UnityVersionControlMenu"); @@ -539,35 +534,15 @@ void FPlasticSourceControlMenu::VisitLockRulesURLClicked(const FString InOrganiz void FPlasticSourceControlMenu::OpenDeskoptApp() const { -#if PLATFORM_WINDOWS - // On Windows, use the registry to find the install location - FString InstallLocation = TEXT("C:/Program Files/PlasticSCM5"); - if (FWindowsPlatformMisc::QueryRegKey(HKEY_LOCAL_MACHINE, TEXT("SOFTWARE\\Unity Software Inc.\\Unity DevOps Version Control"), TEXT("Location"), InstallLocation)) - { - FPaths::NormalizeDirectoryName(InstallLocation); - } - - const TCHAR* PlasticExe = TEXT("client/plastic.exe"); - const TCHAR* GluonExe = TEXT("client/gluon.exe"); - const FString DeskoptAppPath = FPaths::Combine(InstallLocation, FPlasticSourceControlModule::Get().GetProvider().IsPartialWorkspace() ? GluonExe : PlasticExe); -#elif PLATFORM_MAC - const TCHAR* PlasticExe = "/Applications/PlasticSCM.app/Contents/MacOS/macplasticx"; - const TCHAR* GluonExe = "/Applications/Gluon.app/Contents/MacOS/macgluonx"; - const TCHAR* DeskoptAppPath = FPlasticSourceControlModule::Get().GetProvider().IsPartialWorkspace() ? GluonExe : PlasticExe); -#elif PLATFORM_LINUX - const TCHAR* PlasticExe = "/usr/bin/plasticgui "; - const TCHAR* GluonExe = "/usr/bin/gluon"; - const TCHAR* DeskoptAppPath = FPlasticSourceControlModule::Get().GetProvider().IsPartialWorkspace() ? GluonExe : PlasticExe); -#endif - + const FString DesktopAppPath = PlasticSourceControlUtils::FindDesktopApplicationPath(); const FString CommandLineArguments = FString::Printf(TEXT("--wk=\"%s\""), *FPlasticSourceControlModule::Get().GetProvider().GetPathToWorkspaceRoot()); - UE_LOG(LogSourceControl, Log, TEXT("Opening the Desktop application (%s %s)"), *InstallLocation, *CommandLineArguments); + UE_LOG(LogSourceControl, Log, TEXT("Opening the Desktop application (%s %s)"), *DesktopAppPath, *CommandLineArguments); - FProcHandle Proc = FPlatformProcess::CreateProc(*DeskoptAppPath, *CommandLineArguments, true, false, false, nullptr, 0, nullptr, nullptr, nullptr); + FProcHandle Proc = FPlatformProcess::CreateProc(*DesktopAppPath, *CommandLineArguments, true, false, false, nullptr, 0, nullptr, nullptr, nullptr); if (!Proc.IsValid()) { - UE_LOG(LogSourceControl, Error, TEXT("Opening the Desktop application (%s %s) failed."), *DeskoptAppPath, *CommandLineArguments); + UE_LOG(LogSourceControl, Error, TEXT("Opening the Desktop application (%s %s) failed."), *DesktopAppPath, *CommandLineArguments); FPlatformProcess::CloseProc(Proc); } } diff --git a/Source/PlasticSourceControl/Private/PlasticSourceControlUtils.cpp b/Source/PlasticSourceControl/Private/PlasticSourceControlUtils.cpp index 6af63eac..b197152e 100644 --- a/Source/PlasticSourceControl/Private/PlasticSourceControlUtils.cpp +++ b/Source/PlasticSourceControl/Private/PlasticSourceControlUtils.cpp @@ -24,6 +24,12 @@ #include "PlasticSourceControlChangelistState.h" #endif +#if PLATFORM_WINDOWS +#include "Windows/AllowWindowsPlatformTypes.h" +#include "Windows/WindowsPlatformMisc.h" +#undef GetUserName +#endif + namespace PlasticSourceControlUtils { @@ -58,6 +64,34 @@ FString FindPlasticBinaryPath() #endif } +FString FindDesktopApplicationPath() +{ + FString DesktopAppPath; + +#if PLATFORM_WINDOWS + // On Windows, use the registry to find the install location + FString InstallLocation = TEXT("C:/Program Files/PlasticSCM5"); + if (FWindowsPlatformMisc::QueryRegKey(HKEY_LOCAL_MACHINE, TEXT("SOFTWARE\\Unity Software Inc.\\Unity DevOps Version Control"), TEXT("Location"), InstallLocation)) + { + FPaths::NormalizeDirectoryName(InstallLocation); + } + + const TCHAR* PlasticExe = TEXT("client/plastic.exe"); + const TCHAR* GluonExe = TEXT("client/gluon.exe"); + DesktopAppPath = FPaths::Combine(InstallLocation, FPlasticSourceControlModule::Get().GetProvider().IsPartialWorkspace() ? GluonExe : PlasticExe); +#elif PLATFORM_MAC + const TCHAR* PlasticExe = "/Applications/PlasticSCM.app/Contents/MacOS/macplasticx"; + const TCHAR* GluonExe = "/Applications/Gluon.app/Contents/MacOS/macgluonx"; + DesktopAppPath = FPlasticSourceControlModule::Get().GetProvider().IsPartialWorkspace() ? GluonExe : PlasticExe); +#elif PLATFORM_LINUX + const TCHAR* PlasticExe = "/usr/bin/plasticgui "; + const TCHAR* GluonExe = "/usr/bin/gluon"; + DesktopAppPath = FPlasticSourceControlModule::Get().GetProvider().IsPartialWorkspace() ? GluonExe : PlasticExe); +#endif + + return DesktopAppPath; +} + // Find the root of the workspace, looking from the provided path and upward in its parent directories. bool GetWorkspacePath(const FString& InPath, FString& OutWorkspaceRoot) { diff --git a/Source/PlasticSourceControl/Private/PlasticSourceControlUtils.h b/Source/PlasticSourceControl/Private/PlasticSourceControlUtils.h index 43260fa8..559cccbd 100644 --- a/Source/PlasticSourceControl/Private/PlasticSourceControlUtils.h +++ b/Source/PlasticSourceControl/Private/PlasticSourceControlUtils.h @@ -53,6 +53,11 @@ bool RunCommand(const FString& InCommand, const TArray& InParameters, c */ FString FindPlasticBinaryPath(); +/** + * Find the path to the Desktop Application: uses the registry on Windows. + */ +FString FindDesktopApplicationPath(); + /** * Find the root of the Plastic workspace, looking from the GameDir and upward in its parent directories * @param InPathToGameDir The path to the Game Directory