diff --git a/Immutable.uplugin b/Immutable.uplugin index 7ad616b..dc1e345 100644 --- a/Immutable.uplugin +++ b/Immutable.uplugin @@ -1,51 +1,45 @@ { - "FileVersion": 3, - "Version": 1, - "VersionName": "1.3.0.alpha", - "FriendlyName": "Immutable", - "Description": "", - "Category": "Other", - "CreatedBy": "", - "CreatedByURL": "", - "DocsURL": "", - "MarketplaceURL": "", - "SupportURL": "", - "CanContainContent": true, - "IsBetaVersion": true, - "IsExperimentalVersion": true, - "Installed": true, - "EnabledByDefault": true, - "Modules": [ - { - "Name": "Immutable", - "Type": "Runtime", - "LoadingPhase": "Default" - }, - { - "Name": "ImmutableEditor", - "Type": "Editor", - "LoadingPhase": "Default" - }, - { - "Name": "ImmutableOrderbook", - "Type": "Runtime", - "LoadingPhase": "Default" - }, - { - "Name": "ImmutablezkEVMAPI", - "Type": "Runtime", - "LoadingPhase": "Default" - } - ], - "Plugins": [ - { - "Name": "WebBrowserWidget", - "Enabled": true - }, - { - "Name": "BLUI", - "Enabled": true, - "Optional": true - } - ] + "FileVersion": 3, + "Version": 1, + "VersionName": "1.3.0.alpha", + "FriendlyName": "Immutable", + "Description": "", + "Category": "Other", + "CreatedBy": "", + "CreatedByURL": "", + "DocsURL": "", + "MarketplaceURL": "", + "SupportURL": "", + "EnabledByDefault": true, + "CanContainContent": true, + "IsBetaVersion": true, + "IsExperimentalVersion": true, + "Installed": true, + "Modules": [ + { + "Name": "Immutable", + "Type": "Runtime", + "LoadingPhase": "Default" + }, + { + "Name": "ImmutableEditor", + "Type": "Editor", + "LoadingPhase": "Default" + }, + { + "Name": "ImmutablePluginManager", + "Type": "Runtime", + "LoadingPhase": "EarliestPossible" + }, + { + "Name": "ImmutableOrderbook", + "Type": "Runtime", + "LoadingPhase": "Default" + }, + { + "Name": "ImmutablezkEVMAPI", + "Type": "Runtime", + "LoadingPhase": "Default" + } + ] } \ No newline at end of file diff --git a/Source/Immutable/Immutable.Build.cs b/Source/Immutable/Immutable.Build.cs index a5317f2..953881b 100644 --- a/Source/Immutable/Immutable.Build.cs +++ b/Source/Immutable/Immutable.Build.cs @@ -38,14 +38,21 @@ public Immutable(ReadOnlyTargetRules Target) : base(Target) ); #if UE_5_0_OR_LATER - PublicDependencyModuleNames.Add("WebBrowserWidget"); + PublicDependencyModuleNames.Add("WebBrowserWidget"); +#else + if (Target.Platform == UnrealTargetPlatform.Win64) + { + PublicDependencyModuleNames.Add("Blu"); + } +#endif + +#if UE_5_0_OR_LATER PrivateDependencyModuleNames.Add("WebBrowser"); PublicDefinitions.Add("USING_BUNDLED_CEF=1"); PublicDefinitions.Add("USING_BLUI_CEF=0"); #else if (Target.Platform == UnrealTargetPlatform.Win64) { - PrivateDependencyModuleNames.Add("Blu"); PublicDefinitions.Add("USING_BLUI_CEF=1"); } else diff --git a/Source/Immutable/Private/Immutable/ImtblBlui.cpp b/Source/Immutable/Private/Immutable/ImtblBlui.cpp index 8b085f4..c991b81 100644 --- a/Source/Immutable/Private/Immutable/ImtblBlui.cpp +++ b/Source/Immutable/Private/Immutable/ImtblBlui.cpp @@ -35,15 +35,18 @@ void UImtblBlui::OnLogEvent(const FString& LogText) void UImtblBlui::WorldTickStart(UWorld* World, ELevelTick LevelTick, float X) { #if USING_BLUI_CEF - if (!GetBluEye()->IsBrowserLoading() && !bLoadedIndexJS) + if (UBluEye* BluEye = GetBluEye()) { - FString JavaScript; - - IMTBL_LOG("BLUI CEF Browser loaded"); - bLoadedIndexJS = true; - if (FImmutableUtilities::LoadGameBridge(JavaScript)) + if (!BluEye->IsBrowserLoading() && !bLoadedIndexJS) { - GetBluEye()->ExecuteJS(JavaScript); + FString JavaScript; + + IMTBL_LOG("BLUI CEF Browser loaded"); + bLoadedIndexJS = true; + if (FImmutableUtilities::LoadGameBridge(JavaScript)) + { + BluEye->ExecuteJS(JavaScript); + } } } #endif diff --git a/Source/Immutable/Private/Immutable/Tests/ImtblMessagesTest.cpp b/Source/Immutable/Private/Immutable/Tests/ImtblMessagesTest.cpp index 8d91005..e860b82 100644 --- a/Source/Immutable/Private/Immutable/Tests/ImtblMessagesTest.cpp +++ b/Source/Immutable/Private/Immutable/Tests/ImtblMessagesTest.cpp @@ -2,6 +2,8 @@ #include "Containers/UnrealString.h" #include "CoreTypes.h" +#include "Runtime/Launch/Resources/Version.h" + #include "Immutable/ImmutablePassport.h" #include "Misc/AutomationTest.h" @@ -15,7 +17,11 @@ #if WITH_DEV_AUTOMATION_TESTS -IMPLEMENT_SIMPLE_AUTOMATION_TEST(FImtblMessagesTest, "Immutable.JSMessages", EAutomationTestFlags::ApplicationContextMask | EAutomationTestFlags::ServerContext | EAutomationTestFlags::ProductFilter) +#if ((ENGINE_MAJOR_VERSION <= 4) || (ENGINE_MAJOR_VERSION == 5 && ENGINE_MINOR_VERSION <= 4)) +IMPLEMENT_SIMPLE_AUTOMATION_TEST(FImtblMessagesTest, "Immutable.JSMessages", EAutomationTestFlags::ApplicationContextMask | EAutomationTestFlags::EngineFilter) +#else +IMPLEMENT_SIMPLE_AUTOMATION_TEST(FImtblMessagesTest, "Immutable.JSMessages", EAutomationTestFlags_ApplicationContextMask | EAutomationTestFlags::EngineFilter) +#endif // EAutomationTestFlags::SmokeFilter -- note that SmokeFilter will run // automatically during cooking diff --git a/Source/ImmutablePluginManager/ImmutablePluginManager.Build.cs b/Source/ImmutablePluginManager/ImmutablePluginManager.Build.cs new file mode 100644 index 0000000..a6f66da --- /dev/null +++ b/Source/ImmutablePluginManager/ImmutablePluginManager.Build.cs @@ -0,0 +1,19 @@ +using UnrealBuildTool; + +/** + * ImmutablePluginManager establishes the rules for this module. + */ +public class ImmutablePluginManager : ModuleRules +{ + public ImmutablePluginManager(ReadOnlyTargetRules Target) : base(Target) + { + PCHUsage = ModuleRules.PCHUsageMode.UseExplicitOrSharedPCHs; + + PublicDependencyModuleNames.AddRange(new string[] + { + "Core", + "CoreUObject", + "Projects" + }); + } +} \ No newline at end of file diff --git a/Source/ImmutablePluginManager/Private/ImmutablePluginManager.cpp b/Source/ImmutablePluginManager/Private/ImmutablePluginManager.cpp new file mode 100644 index 0000000..ef3e5df --- /dev/null +++ b/Source/ImmutablePluginManager/Private/ImmutablePluginManager.cpp @@ -0,0 +1,129 @@ +#include "ImmutablePluginManager.h" + +#include "Interfaces/IPluginManager.h" +#include "Misc/CoreDelegates.h" +#include "Misc/MessageDialog.h" +#include "Runtime/Launch/Resources/Version.h" + +#include "Runtime/Projects/Private/PluginManager.h" + +DEFINE_LOG_CATEGORY(LogImtblPluginManager); + +#define LOCTEXT_NAMESPACE "FImmutablePluginManagerModule" + +/** + * ImmutablePluginManagerInternal manages the enabling/disabling of BLUI and WebBrowserWidget. + */ +class FImmutablePluginManagerInternal +{ +public: + FImmutablePluginManagerInternal() + { +#if ENGINE_MAJOR_VERSION <= 4 + FImmutablePluginManagerModule::EnablePlugin(TEXT("BLUI")); + FImmutablePluginManagerModule::DisablePlugin(TEXT("WebBrowserWidget")); +#else + FImmutablePluginManagerModule::DisablePlugin(TEXT("BLUI")); + FImmutablePluginManagerModule::EnablePlugin(TEXT("WebBrowserWidget")); +#endif + } +}; + +TOptional GImmutablePluginManagerInternal(InPlace); + +void FImmutablePluginManagerModule::EnablePlugin(const FString& PluginName) +{ + TogglePlugin(PluginName, true); +} + +void FImmutablePluginManagerModule::DisablePlugin(const FString& PluginName) +{ + TogglePlugin(PluginName, false); +} + +void FImmutablePluginManagerModule::TogglePlugin(const FString& PluginName, bool bEnabled) +{ + UpdateImmutablePluginDescriptor_PluginDependency(PluginName, bEnabled); + + UpdatePluginManager(PluginName, bEnabled); +} + +bool FImmutablePluginManagerModule::UpdateImmutablePluginDescriptor_PluginDependency(const FString& PluginName, bool bEnabled) +{ + bool bUpdateImmutablePluginDescriptor = false; + + IPluginManager& PluginManager = IPluginManager::Get(); + + TSharedPtr ImmutablePlugin = PluginManager.FindPlugin("Immutable"); + ensureAlways(ImmutablePlugin.IsValid()); + + FPluginDescriptor& ImmutablePluginDescriptor = const_cast(ImmutablePlugin->GetDescriptor()); + + FPluginReferenceDescriptor* PluginDependencyReferenceDescriptor = ImmutablePluginDescriptor.Plugins.FindByPredicate([PluginName](const FPluginReferenceDescriptor& Descriptor) + { + return Descriptor.Name == PluginName; + }); + + if (PluginDependencyReferenceDescriptor) + { + if (PluginDependencyReferenceDescriptor->bEnabled != bEnabled) + { + PluginDependencyReferenceDescriptor->bEnabled = bEnabled; + + bUpdateImmutablePluginDescriptor = true; + } + } + else + { + TSharedPtr Plugin = IPluginManager::Get().FindPlugin(PluginName); + + if (ensureAlways(Plugin.IsValid())) + { + ImmutablePluginDescriptor.Plugins.Add(FPluginReferenceDescriptor(Plugin->GetName(), bEnabled)); + + bUpdateImmutablePluginDescriptor = true; + } + } + + if (bUpdateImmutablePluginDescriptor) + { + FText FailReason; + const bool bUpdateDescriptor = ImmutablePlugin->UpdateDescriptor(ImmutablePluginDescriptor, FailReason); + + ensureAlways(bUpdateDescriptor); + ensureAlways(FailReason.IsEmpty()); + } + + return bUpdateImmutablePluginDescriptor; +} + +void FImmutablePluginManagerModule::UpdatePluginManager(const FString& PluginName, bool bEnabled) +{ + IPluginManager& PluginManager = IPluginManager::Get(); + TSharedPtr PluginInterface = PluginManager.FindPlugin(PluginName); + + if (ensureAlways(PluginInterface.IsValid())) + { + FPlugin* Plugin = reinterpret_cast(PluginInterface.Get()); + + if (ensureAlways(Plugin)) + { + if (Plugin->bEnabled != bEnabled) + { + Plugin->bEnabled = bEnabled; + } + } + } +} + +void FImmutablePluginManagerModule::StartupModule() +{ +} + +void FImmutablePluginManagerModule::ShutdownModule() +{ +} + +#undef LOCTEXT_NAMESPACE + +IMPLEMENT_MODULE(FImmutablePluginManagerModule, ImmutablePluginManager) \ No newline at end of file diff --git a/Source/ImmutablePluginManager/Public/ImmutablePluginManager.h b/Source/ImmutablePluginManager/Public/ImmutablePluginManager.h new file mode 100644 index 0000000..ed2f947 --- /dev/null +++ b/Source/ImmutablePluginManager/Public/ImmutablePluginManager.h @@ -0,0 +1,25 @@ +#pragma once + +#include "Modules/ModuleInterface.h" + +IMMUTABLEPLUGINMANAGER_API DECLARE_LOG_CATEGORY_EXTERN(LogImtblPluginManager, Log, All); + +/** + * Plugin manager module that automatically switches between the BLUI and Epic's WebBrowserWidget plugins at build time. + * This eliminates the need for developers to manually disable either plugin by editing the .uplugin file, streamlining the installation process. + */ +class FImmutablePluginManagerModule : public IModuleInterface +{ +public: + static void EnablePlugin(const FString& PluginName); + static void DisablePlugin(const FString& PluginName); + + static void TogglePlugin(const FString& PluginName, bool bEnabled); + + static bool UpdateImmutablePluginDescriptor_PluginDependency(const FString& PluginName, bool bEnabled); + static void UpdatePluginManager(const FString& PluginName, bool bEnabled); + +public: + virtual void StartupModule() override; + virtual void ShutdownModule() override; +}; \ No newline at end of file