├── .gitignore ├── Resources └── Icon128.png ├── Source ├── ImGui │ ├── Private │ │ ├── Utilities │ │ │ ├── DebugExecBindings.h │ │ │ ├── WorldContext.cpp │ │ │ ├── WorldContext.h │ │ │ ├── WorldContextIndex.h │ │ │ ├── Arrays.h │ │ │ ├── RedirectingHandle.h │ │ │ ├── DebugExecBindings.cpp │ │ │ └── Range.h │ │ ├── ImGuiImplementation.h │ │ ├── ImGuiModuleDebug.h │ │ ├── ImGuiInputHandlerFactory.h │ │ ├── ImGuiDemo.h │ │ ├── Editor │ │ │ ├── ImGuiEditor.h │ │ │ ├── ImGuiKeyInfoCustomization.h │ │ │ ├── ImGuiCanvasSizeInfoCustomization.h │ │ │ ├── ImGuiEditor.cpp │ │ │ ├── ImGuiCanvasSizeInfoCustomization.cpp │ │ │ └── ImGuiKeyInfoCustomization.cpp │ │ ├── ImGuiTextureHandle.cpp │ │ ├── ImGuiDelegates.cpp │ │ ├── Widgets │ │ │ ├── SImGuiLayout.h │ │ │ ├── SImGuiLayout.cpp │ │ │ ├── SImGuiCanvasControl.h │ │ │ └── SImGuiWidget.h │ │ ├── ImGuiInputHandlerFactory.cpp │ │ ├── ImGuiModuleCommands.h │ │ ├── ImGuiDelegatesContainer.h │ │ ├── VersionCompatibility.h │ │ ├── ImGuiImplementation.cpp │ │ ├── ImGuiInputState.cpp │ │ ├── ImGuiDelegatesContainer.cpp │ │ ├── ImGuiDrawData.cpp │ │ ├── ImGuiDrawData.h │ │ ├── ImGuiDemo.cpp │ │ ├── ImGuiModuleManager.h │ │ ├── ImGuiModuleCommands.cpp │ │ ├── ImGuiContextProxy.h │ │ ├── ImGuiContextManager.h │ │ ├── ImGuiInteroperability.h │ │ ├── ImGuiModuleSettings.cpp │ │ ├── TextureManager.cpp │ │ ├── TextureManager.h │ │ ├── ImGuiModuleManager.cpp │ │ ├── ImGuiContextProxy.cpp │ │ └── ImGuiInputState.h │ ├── Public │ │ ├── ImGuiTextureHandle.h │ │ ├── ImGuiModuleProperties.h │ │ ├── ImGuiDelegates.h │ │ ├── ImGuiInputHandler.h │ │ └── ImGuiModule.h │ └── ImGui.Build.cs └── ThirdParty │ └── ImGuiLibrary │ ├── ImGuiLibrary.Build.cs │ ├── ImGuiLibrary.tps │ ├── LICENSE.txt │ ├── Docs │ └── BACKENDS.md │ └── Include │ └── imconfig.h ├── ImGui.uplugin ├── LICENSE ├── CHANGES.md └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | /Binaries/ 2 | /Intermediate/ 3 | -------------------------------------------------------------------------------- /Resources/Icon128.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/benui-dev/UnrealImGui/HEAD/Resources/Icon128.png -------------------------------------------------------------------------------- /Source/ImGui/Private/Utilities/DebugExecBindings.h: -------------------------------------------------------------------------------- 1 | // Distributed under the MIT License (MIT) (see accompanying LICENSE file) 2 | 3 | #pragma once 4 | 5 | class FString; 6 | struct FImGuiKeyInfo; 7 | 8 | namespace DebugExecBindings 9 | { 10 | void UpdatePlayerInputs(const FImGuiKeyInfo& KeyInfo, const FString& Command); 11 | } 12 | -------------------------------------------------------------------------------- /Source/ThirdParty/ImGuiLibrary/ImGuiLibrary.Build.cs: -------------------------------------------------------------------------------- 1 | using UnrealBuildTool; 2 | 3 | public class ImGuiLibrary : ModuleRules 4 | { 5 | #if WITH_FORWARDED_MODULE_RULES_CTOR 6 | public ImGuiLibrary(ReadOnlyTargetRules Target) : base(Target) 7 | #else 8 | public ImGuiLibrary(TargetInfo Target) 9 | #endif 10 | { 11 | Type = ModuleType.External; 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /Source/ThirdParty/ImGuiLibrary/ImGuiLibrary.tps: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Dear ImGui source files re-packaged to be included in Unreal Engine. Original Omar Cornut's repository can be found at https://github.com/ocornut/imgui. 5 | 6 | 7 | -------------------------------------------------------------------------------- /Source/ImGui/Private/ImGuiImplementation.h: -------------------------------------------------------------------------------- 1 | // Distributed under the MIT License (MIT) (see accompanying LICENSE file) 2 | 3 | #pragma once 4 | 5 | struct FImGuiContextHandle; 6 | 7 | // Gives access to selected ImGui implementation features. 8 | namespace ImGuiImplementation 9 | { 10 | #if WITH_EDITOR 11 | // Get the handle to the ImGui Context pointer. 12 | FImGuiContextHandle& GetContextHandle(); 13 | 14 | // Set the ImGui Context pointer handle. 15 | void SetParentContextHandle(FImGuiContextHandle& Parent); 16 | #endif // WITH_EDITOR 17 | } 18 | -------------------------------------------------------------------------------- /Source/ImGui/Private/ImGuiModuleDebug.h: -------------------------------------------------------------------------------- 1 | // Distributed under the MIT License (MIT) (see accompanying LICENSE file) 2 | 3 | #pragma once 4 | 5 | #include 6 | 7 | 8 | // Module-wide debug symbols and loggers. 9 | 10 | 11 | // If enabled, it activates debug code and console variables that in normal usage are hidden. 12 | #define IMGUI_MODULE_DEVELOPER 0 13 | 14 | 15 | // Input Handler logger (used also in non-developer mode to raise problems with handler extensions). 16 | DECLARE_LOG_CATEGORY_EXTERN(LogImGuiInputHandler, Warning, All); 17 | -------------------------------------------------------------------------------- /ImGui.uplugin: -------------------------------------------------------------------------------- 1 | { 2 | "FileVersion": 3, 3 | "Version": 1, 4 | "VersionName": "1.22", 5 | "FriendlyName": "ImGui", 6 | "Description": "", 7 | "Category": "Debug", 8 | "CreatedBy": "", 9 | "CreatedByURL": "", 10 | "DocsURL": "", 11 | "MarketplaceURL": "", 12 | "SupportURL": "", 13 | "CanContainContent": false, 14 | "IsBetaVersion": false, 15 | "Installed": false, 16 | "Modules": [ 17 | { 18 | "Name": "ImGui", 19 | "Type": "DeveloperTool", 20 | "LoadingPhase": "PreDefault" 21 | } 22 | ], 23 | "Plugins": [ 24 | { 25 | "Name": "EnhancedInput", 26 | "Enabled": true 27 | } 28 | ] 29 | } -------------------------------------------------------------------------------- /Source/ImGui/Private/ImGuiInputHandlerFactory.h: -------------------------------------------------------------------------------- 1 | // Distributed under the MIT License (MIT) (see accompanying LICENSE file) 2 | 3 | #pragma once 4 | 5 | #include "ImGuiModuleSettings.h" 6 | 7 | 8 | class FImGuiModuleManager; 9 | class UGameViewportClient; 10 | class UImGuiInputHandler; 11 | 12 | class FImGuiInputHandlerFactory 13 | { 14 | public: 15 | 16 | static UImGuiInputHandler* NewHandler(const FSoftClassPath& HandlerClassReference, FImGuiModuleManager* ModuleManager, UGameViewportClient* GameViewport, int32 ContextIndex); 17 | 18 | static void ReleaseHandler(UImGuiInputHandler* Handler); 19 | }; 20 | -------------------------------------------------------------------------------- /Source/ImGui/Private/Utilities/WorldContext.cpp: -------------------------------------------------------------------------------- 1 | // Distributed under the MIT License (MIT) (see accompanying LICENSE file) 2 | 3 | #include "WorldContext.h" 4 | 5 | 6 | namespace Utilities 7 | { 8 | const FWorldContext* GetWorldContextFromNetMode(ENetMode NetMode) 9 | { 10 | checkf(GEngine, TEXT("GEngine required to get list of worlds.")); 11 | 12 | for (const FWorldContext& WorldContext : GEngine->GetWorldContexts()) 13 | { 14 | if (WorldContext.World() && WorldContext.World()->GetNetMode() == NetMode) 15 | { 16 | return &WorldContext; 17 | } 18 | } 19 | 20 | return nullptr; 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /Source/ImGui/Private/ImGuiDemo.h: -------------------------------------------------------------------------------- 1 | // Distributed under the MIT License (MIT) (see accompanying LICENSE file) 2 | 3 | #pragma once 4 | 5 | #include 6 | 7 | #include 8 | 9 | class FImGuiModuleProperties; 10 | 11 | // Widget drawing ImGui demo. 12 | class FImGuiDemo 13 | { 14 | public: 15 | 16 | FImGuiDemo(FImGuiModuleProperties& InProperties) 17 | : Properties(InProperties) 18 | { 19 | } 20 | 21 | void DrawControls(int32 ContextIndex); 22 | 23 | private: 24 | 25 | FImGuiModuleProperties& Properties; 26 | 27 | ImVec4 ClearColor = ImColor{ 114, 144, 154 }; 28 | 29 | int32 ShowDemoWindowMask = 0; 30 | int32 ShowAnotherWindowMask = 0; 31 | 32 | int32 DemoWindowCounter = 0; 33 | uint32 LastDemoWindowFrameNumber = 0; 34 | }; 35 | -------------------------------------------------------------------------------- /Source/ImGui/Private/Editor/ImGuiEditor.h: -------------------------------------------------------------------------------- 1 | // Copyright 1998-2018 Epic Games, Inc. All Rights Reserved. 2 | 3 | #pragma once 4 | 5 | #if WITH_EDITOR 6 | 7 | #include 8 | 9 | 10 | // Registers module's settings in editor (due to a small size of this code we don't use a separate editor module). 11 | class FImGuiEditor 12 | { 13 | public: 14 | 15 | FImGuiEditor(); 16 | ~FImGuiEditor(); 17 | 18 | private: 19 | 20 | bool IsRegistrationCompleted() const { return bSettingsRegistered && bCustomPropertyTypeLayoutsRegistered; } 21 | 22 | void Register(); 23 | void Unregister(); 24 | 25 | void CreateRegistrator(); 26 | void ReleaseRegistrator(); 27 | 28 | FDelegateHandle RegistratorHandle; 29 | 30 | bool bSettingsRegistered = false; 31 | bool bCustomPropertyTypeLayoutsRegistered = false; 32 | }; 33 | 34 | #endif // WITH_EDITOR 35 | -------------------------------------------------------------------------------- /Source/ImGui/Private/Editor/ImGuiKeyInfoCustomization.h: -------------------------------------------------------------------------------- 1 | // Copyright 1998-2018 Epic Games, Inc. All Rights Reserved. 2 | 3 | #pragma once 4 | 5 | #if WITH_EDITOR 6 | 7 | #include 8 | #include 9 | 10 | 11 | // Property type customization for FImGuiKeyInfo. 12 | class FImGuiKeyInfoCustomization : public IPropertyTypeCustomization 13 | { 14 | public: 15 | static TSharedRef MakeInstance(); 16 | 17 | // IPropertyTypeCustomization interface 18 | virtual void CustomizeHeader(TSharedRef InStructPropertyHandle, FDetailWidgetRow& HeaderRow, IPropertyTypeCustomizationUtils& StructCustomizationUtils) override; 19 | virtual void CustomizeChildren(TSharedRef InStructPropertyHandle, IDetailChildrenBuilder& StructBuilder, IPropertyTypeCustomizationUtils& StructCustomizationUtils) override; 20 | }; 21 | 22 | #endif // WITH_EDITOR 23 | -------------------------------------------------------------------------------- /Source/ImGui/Private/Editor/ImGuiCanvasSizeInfoCustomization.h: -------------------------------------------------------------------------------- 1 | // Copyright 1998-2018 Epic Games, Inc. All Rights Reserved. 2 | 3 | #pragma once 4 | 5 | #if WITH_EDITOR 6 | 7 | #include 8 | #include 9 | 10 | 11 | // Property type customization for FImGuiCanvasSizeInfo. 12 | class FImGuiCanvasSizeInfoCustomization : public IPropertyTypeCustomization 13 | { 14 | public: 15 | static TSharedRef MakeInstance(); 16 | 17 | // IPropertyTypeCustomization interface 18 | virtual void CustomizeHeader(TSharedRef InStructPropertyHandle, FDetailWidgetRow& HeaderRow, IPropertyTypeCustomizationUtils& StructCustomizationUtils) override; 19 | virtual void CustomizeChildren(TSharedRef InStructPropertyHandle, IDetailChildrenBuilder& StructBuilder, IPropertyTypeCustomizationUtils& StructCustomizationUtils) override; 20 | }; 21 | 22 | #endif // WITH_EDITOR 23 | -------------------------------------------------------------------------------- /Source/ImGui/Private/ImGuiTextureHandle.cpp: -------------------------------------------------------------------------------- 1 | // Distributed under the MIT License (MIT) (see accompanying LICENSE file) 2 | 3 | #include "ImGuiTextureHandle.h" 4 | 5 | #include "ImGuiInteroperability.h" 6 | 7 | 8 | FImGuiTextureHandle::FImGuiTextureHandle() 9 | : FImGuiTextureHandle(NAME_None, ImGuiInterops::ToImTextureID(INDEX_NONE)) 10 | { 11 | } 12 | 13 | FImGuiTextureHandle::FImGuiTextureHandle(const FName& InName, ImTextureID InTextureId) 14 | : Name(InName) 15 | , TextureId(InTextureId) 16 | { 17 | const TextureIndex Index = ImGuiInterops::ToTextureIndex(TextureId); 18 | checkf((Index == INDEX_NONE) == (Name == NAME_None), 19 | TEXT("Mismatch between Name and TextureId parameters, with only one indicating a null handle.") 20 | TEXT(" Name = '%s', TextureIndex(TextureId) = %d"), *Name.ToString(), Index); 21 | } 22 | 23 | // FImGuiTextureHandle::HasValidEntry() is implemented in ImGuiModule.cpp to get access to FImGuiModuleManager instance 24 | // without referencing in this class. 25 | -------------------------------------------------------------------------------- /Source/ImGui/Private/ImGuiDelegates.cpp: -------------------------------------------------------------------------------- 1 | // Distributed under the MIT License (MIT) (see accompanying LICENSE file) 2 | 3 | #include "ImGuiDelegates.h" 4 | #include "ImGuiDelegatesContainer.h" 5 | 6 | #include 7 | 8 | 9 | FSimpleMulticastDelegate& FImGuiDelegates::OnWorldEarlyDebug() 10 | { 11 | return OnWorldEarlyDebug(GWorld); 12 | } 13 | 14 | FSimpleMulticastDelegate& FImGuiDelegates::OnWorldEarlyDebug(UWorld* World) 15 | { 16 | return FImGuiDelegatesContainer::Get().OnWorldEarlyDebug(World); 17 | } 18 | 19 | FSimpleMulticastDelegate& FImGuiDelegates::OnMultiContextEarlyDebug() 20 | { 21 | return FImGuiDelegatesContainer::Get().OnMultiContextEarlyDebug(); 22 | } 23 | 24 | FSimpleMulticastDelegate& FImGuiDelegates::OnWorldDebug() 25 | { 26 | return OnWorldDebug(GWorld); 27 | } 28 | 29 | FSimpleMulticastDelegate& FImGuiDelegates::OnWorldDebug(UWorld* World) 30 | { 31 | return FImGuiDelegatesContainer::Get().OnWorldDebug(World); 32 | } 33 | 34 | FSimpleMulticastDelegate& FImGuiDelegates::OnMultiContextDebug() 35 | { 36 | return FImGuiDelegatesContainer::Get().OnMultiContextDebug(); 37 | } 38 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2017-2021 Sebastian Gross 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /Source/ThirdParty/ImGuiLibrary/LICENSE.txt: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2014-2022 Omar Cornut 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /Source/ImGui/Private/Widgets/SImGuiLayout.h: -------------------------------------------------------------------------------- 1 | // Distributed under the MIT License (MIT) (see accompanying LICENSE file) 2 | 3 | #pragma once 4 | 5 | #include 6 | #include 7 | #include 8 | 9 | 10 | class FImGuiModuleManager; 11 | class UGameViewportClient; 12 | struct FImGuiDPIScaleInfo; 13 | 14 | // Layout preset for ImGui Widget. 15 | class SImGuiLayout : public SCompoundWidget 16 | { 17 | typedef SCompoundWidget Super; 18 | 19 | public: 20 | 21 | SLATE_BEGIN_ARGS(SImGuiLayout) 22 | {} 23 | SLATE_ARGUMENT(FImGuiModuleManager*, ModuleManager) 24 | SLATE_ARGUMENT(UGameViewportClient*, GameViewport) 25 | SLATE_ARGUMENT(int32, ContextIndex) 26 | SLATE_END_ARGS() 27 | 28 | void Construct(const FArguments& InArgs); 29 | 30 | ~SImGuiLayout(); 31 | 32 | const TWeakObjectPtr& GetGameViewport() const { return GameViewport; } 33 | 34 | private: 35 | 36 | float GetDPIScale() const { return DPIScale; } 37 | void SetDPIScale(const FImGuiDPIScaleInfo& ScaleInfo); 38 | 39 | FImGuiModuleManager* ModuleManager = nullptr; 40 | TWeakObjectPtr GameViewport; 41 | 42 | float DPIScale = 1.f; 43 | }; 44 | -------------------------------------------------------------------------------- /Source/ImGui/Private/Utilities/WorldContext.h: -------------------------------------------------------------------------------- 1 | // Distributed under the MIT License (MIT) (see accompanying LICENSE file) 2 | 3 | #pragma once 4 | 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | 11 | // Utilities helping to get a World Context. 12 | 13 | namespace Utilities 14 | { 15 | template 16 | FORCEINLINE const FWorldContext* GetWorldContext(const T* Obj); 17 | 18 | FORCEINLINE const FWorldContext* GetWorldContext(const UGameInstance& GameInstance) 19 | { 20 | return GameInstance.GetWorldContext(); 21 | } 22 | 23 | template 24 | FORCEINLINE const FWorldContext* GetWorldContext(const TWeakObjectPtr& Obj) 25 | { 26 | return Obj.IsValid() ? GetWorldContext(*Obj.Get()) : nullptr; 27 | } 28 | 29 | FORCEINLINE const FWorldContext* GetWorldContext(const UGameViewportClient& GameViewportClient) 30 | { 31 | return GetWorldContext(GameViewportClient.GetGameInstance()); 32 | } 33 | 34 | FORCEINLINE const FWorldContext* GetWorldContext(const UWorld& World) 35 | { 36 | return GetWorldContext(World.GetGameInstance()); 37 | } 38 | 39 | template 40 | FORCEINLINE const FWorldContext* GetWorldContext(const T* Obj) 41 | { 42 | return Obj ? GetWorldContext(*Obj) : nullptr; 43 | } 44 | 45 | const FWorldContext* GetWorldContextFromNetMode(ENetMode NetMode); 46 | } 47 | -------------------------------------------------------------------------------- /Source/ImGui/Private/ImGuiInputHandlerFactory.cpp: -------------------------------------------------------------------------------- 1 | // Distributed under the MIT License (MIT) (see accompanying LICENSE file) 2 | 3 | #include "ImGuiInputHandlerFactory.h" 4 | #include "ImGuiInputHandler.h" 5 | 6 | #include "ImGuiModuleDebug.h" 7 | 8 | #include 9 | #include 10 | 11 | 12 | UImGuiInputHandler* FImGuiInputHandlerFactory::NewHandler(const FSoftClassPath& HandlerClassReference, FImGuiModuleManager* ModuleManager, UGameViewportClient* GameViewport, int32 ContextIndex) 13 | { 14 | UClass* HandlerClass = nullptr; 15 | if (HandlerClassReference.IsValid()) 16 | { 17 | HandlerClass = HandlerClassReference.TryLoadClass(); 18 | 19 | if (!HandlerClass) 20 | { 21 | UE_LOG(LogImGuiInputHandler, Error, TEXT("Couldn't load ImGui Input Handler class '%s'."), *HandlerClassReference.ToString()); 22 | } 23 | } 24 | 25 | if (!HandlerClass) 26 | { 27 | HandlerClass = UImGuiInputHandler::StaticClass(); 28 | } 29 | 30 | UImGuiInputHandler* Handler = NewObject(GameViewport, HandlerClass); 31 | if (Handler) 32 | { 33 | Handler->Initialize(ModuleManager, GameViewport, ContextIndex); 34 | Handler->AddToRoot(); 35 | } 36 | else 37 | { 38 | UE_LOG(LogImGuiInputHandler, Error, TEXT("Failed attempt to create Input Handler: HandlerClass = %s."), *GetNameSafe(HandlerClass)); 39 | } 40 | 41 | return Handler; 42 | } 43 | 44 | void FImGuiInputHandlerFactory::ReleaseHandler(UImGuiInputHandler* Handler) 45 | { 46 | if (Handler) 47 | { 48 | Handler->RemoveFromRoot(); 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /Source/ImGui/Private/ImGuiModuleCommands.h: -------------------------------------------------------------------------------- 1 | // Distributed under the MIT License (MIT) (see accompanying LICENSE file) 2 | 3 | #pragma once 4 | 5 | #include 6 | 7 | 8 | struct FImGuiKeyInfo; 9 | class FImGuiModuleProperties; 10 | 11 | // Manges ImGui module console commands. 12 | class FImGuiModuleCommands 13 | { 14 | public: 15 | 16 | static const TCHAR* const ToggleInput; 17 | static const TCHAR* const ToggleKeyboardNavigation; 18 | static const TCHAR* const ToggleGamepadNavigation; 19 | static const TCHAR* const ToggleKeyboardInputSharing; 20 | static const TCHAR* const ToggleGamepadInputSharing; 21 | static const TCHAR* const ToggleMouseInputSharing; 22 | static const TCHAR* const SetMouseInputSharing; 23 | static const TCHAR* const ToggleDemo; 24 | 25 | FImGuiModuleCommands(FImGuiModuleProperties& InProperties); 26 | 27 | void SetKeyBinding(const TCHAR* CommandName, const FImGuiKeyInfo& KeyInfo); 28 | 29 | private: 30 | 31 | void ToggleInputImpl(); 32 | void ToggleKeyboardNavigationImpl(); 33 | void ToggleGamepadNavigationImpl(); 34 | void ToggleKeyboardInputSharingImpl(); 35 | void ToggleGamepadInputSharingImpl(); 36 | void ToggleMouseInputSharingImpl(); 37 | void SetMouseInputSharingImpl(const TArray< FString >& Args); 38 | void ToggleDemoImpl(); 39 | 40 | FImGuiModuleProperties& Properties; 41 | 42 | FAutoConsoleCommand ToggleInputCommand; 43 | FAutoConsoleCommand ToggleKeyboardNavigationCommand; 44 | FAutoConsoleCommand ToggleGamepadNavigationCommand; 45 | FAutoConsoleCommand ToggleKeyboardInputSharingCommand; 46 | FAutoConsoleCommand ToggleGamepadInputSharingCommand; 47 | FAutoConsoleCommand ToggleMouseInputSharingCommand; 48 | FAutoConsoleCommand SetMouseInputSharingCommand; 49 | FAutoConsoleCommand ToggleDemoCommand; 50 | }; 51 | -------------------------------------------------------------------------------- /Source/ImGui/Private/Utilities/WorldContextIndex.h: -------------------------------------------------------------------------------- 1 | // Distributed under the MIT License (MIT) (see accompanying LICENSE file) 2 | 3 | #pragma once 4 | 5 | #include "Utilities/WorldContext.h" 6 | 7 | 8 | // Utilities mapping worlds to indices that we use to identify ImGui contexts. 9 | 10 | namespace Utilities 11 | { 12 | // Invalid context index for parameters that cannot be resolved to a valid world. 13 | static constexpr int32 INVALID_CONTEXT_INDEX = -10; 14 | 15 | // Standalone context index. 16 | static constexpr int32 STANDALONE_GAME_CONTEXT_INDEX = -2; 17 | 18 | #if WITH_EDITOR 19 | 20 | // Editor context index. We are lacking flexibility here, so we might need to change it somehow. 21 | static constexpr int32 EDITOR_CONTEXT_INDEX = -1; 22 | 23 | FORCEINLINE int32 GetWorldContextIndex(const FWorldContext& WorldContext) 24 | { 25 | switch (WorldContext.WorldType) 26 | { 27 | case EWorldType::PIE: 28 | return WorldContext.PIEInstance; 29 | case EWorldType::Game: 30 | return STANDALONE_GAME_CONTEXT_INDEX; 31 | case EWorldType::Editor: 32 | return EDITOR_CONTEXT_INDEX; 33 | default: 34 | return INVALID_CONTEXT_INDEX; 35 | } 36 | } 37 | 38 | template 39 | FORCEINLINE int32 GetWorldContextIndex(const T& Obj) 40 | { 41 | const FWorldContext* WorldContext = GetWorldContext(Obj); 42 | return WorldContext ? GetWorldContextIndex(*WorldContext) : INVALID_CONTEXT_INDEX; 43 | } 44 | 45 | FORCEINLINE int32 GetWorldContextIndex(const UWorld& World) 46 | { 47 | return (World.WorldType == EWorldType::Editor) ? EDITOR_CONTEXT_INDEX : GetWorldContextIndex(World.GetGameInstance()); 48 | } 49 | 50 | FORCEINLINE int32 GetWorldContextIndex(const UWorld* World) 51 | { 52 | return World ? GetWorldContextIndex(*World) : INVALID_CONTEXT_INDEX; 53 | } 54 | 55 | #else 56 | 57 | template 58 | constexpr int32 GetWorldContextIndex(const T&) 59 | { 60 | // The only option is standalone game with one context. 61 | return STANDALONE_GAME_CONTEXT_INDEX; 62 | } 63 | 64 | #endif // #if WITH_EDITOR 65 | } 66 | -------------------------------------------------------------------------------- /Source/ImGui/Private/Utilities/Arrays.h: -------------------------------------------------------------------------------- 1 | // Distributed under the MIT License (MIT) (see accompanying LICENSE file) 2 | 3 | #pragma once 4 | 5 | #include "Range.h" 6 | 7 | #include 8 | #include 9 | #include 10 | 11 | 12 | // Utilities to work with one-dimensional, statically bound arrays. Code relying on those utilities should work without 13 | // modifications with fixed-sized arrays (currently used in ImGui) and with standard arrays. 14 | 15 | namespace Utilities 16 | { 17 | //==================================================================================================== 18 | // Helper functions 19 | //==================================================================================================== 20 | 21 | // Function to determine number of elements in fixed size array. 22 | template 23 | constexpr std::size_t GetArraySize(const T(&)[N]) 24 | { 25 | return N; 26 | } 27 | 28 | // Function to determine number of elements in std array. 29 | template 30 | constexpr std::size_t GetArraySize(const std::array&) 31 | { 32 | return N; 33 | } 34 | 35 | 36 | //==================================================================================================== 37 | // Traits 38 | //==================================================================================================== 39 | 40 | template 41 | struct ArraySize; 42 | 43 | // Struct to determine number of elements in fixed size array. 44 | template 45 | struct ArraySize : std::extent 46 | { 47 | }; 48 | 49 | // Struct to determine number of elements in std array. 50 | template 51 | struct ArraySize> : std::tuple_size> 52 | { 53 | }; 54 | 55 | 56 | //==================================================================================================== 57 | // Ranges 58 | //==================================================================================================== 59 | 60 | // Array indices range. Limited by 0 and array size. 61 | template 62 | using TArrayIndexRange = TBoundedRange::value>; 63 | } 64 | -------------------------------------------------------------------------------- /Source/ImGui/Private/ImGuiDelegatesContainer.h: -------------------------------------------------------------------------------- 1 | // Distributed under the MIT License (MIT) (see accompanying LICENSE file) 2 | 3 | #pragma once 4 | 5 | #include 6 | #include 7 | 8 | 9 | #if WITH_EDITOR 10 | struct FImGuiDelegatesContainerHandle; 11 | #endif 12 | 13 | struct FImGuiDelegatesContainer 14 | { 15 | public: 16 | 17 | // Get the current instance (can change during hot-reloading). 18 | static FImGuiDelegatesContainer& Get(); 19 | 20 | #if WITH_EDITOR 21 | // Get the handle to the container instance (can attach to other handles in hot-reloaded modules). 22 | static FImGuiDelegatesContainerHandle& GetHandle(); 23 | 24 | // Redirect to the other container and if this one is still active move its data to the other one. 25 | static void MoveContainer(FImGuiDelegatesContainerHandle& OtherContainerHandle); 26 | #endif 27 | 28 | // Get delegate to ImGui world early debug event from known world instance. 29 | FSimpleMulticastDelegate& OnWorldEarlyDebug(UWorld* World) { return OnWorldEarlyDebug(GetContextIndex(World)); } 30 | 31 | // Get delegate to ImGui world early debug event from known context index. 32 | FSimpleMulticastDelegate& OnWorldEarlyDebug(int32 ContextIndex) { return WorldEarlyDebugDelegates.FindOrAdd(ContextIndex); } 33 | 34 | // Get delegate to ImGui multi-context early debug event. 35 | FSimpleMulticastDelegate& OnMultiContextEarlyDebug() { return MultiContextEarlyDebugDelegate; } 36 | 37 | // Get delegate to ImGui world debug event from known world instance. 38 | FSimpleMulticastDelegate& OnWorldDebug(UWorld* World) { return OnWorldDebug(GetContextIndex(World)); } 39 | 40 | // Get delegate to ImGui world debug event from known context index. 41 | FSimpleMulticastDelegate& OnWorldDebug(int32 ContextIndex) { return WorldDebugDelegates.FindOrAdd(ContextIndex); } 42 | 43 | // Get delegate to ImGui multi-context debug event. 44 | FSimpleMulticastDelegate& OnMultiContextDebug() { return MultiContextDebugDelegate; } 45 | 46 | private: 47 | 48 | int32 GetContextIndex(UWorld* World); 49 | 50 | void Clear(); 51 | 52 | TMap WorldEarlyDebugDelegates; 53 | TMap WorldDebugDelegates; 54 | FSimpleMulticastDelegate MultiContextEarlyDebugDelegate; 55 | FSimpleMulticastDelegate MultiContextDebugDelegate; 56 | }; 57 | -------------------------------------------------------------------------------- /Source/ImGui/Private/VersionCompatibility.h: -------------------------------------------------------------------------------- 1 | // Distributed under the MIT License (MIT) (see accompanying LICENSE file) 2 | 3 | #include 4 | 5 | #define BELOW_ENGINE_VERSION(Major, Minor) (ENGINE_MAJOR_VERSION < (Major) || (ENGINE_MAJOR_VERSION == (Major) && ENGINE_MINOR_VERSION < (Minor))) 6 | #define FROM_ENGINE_VERSION(Major, Minor) !BELOW_ENGINE_VERSION(Major, Minor) 7 | 8 | 9 | // One place to define compatibility with older engine versions. 10 | 11 | 12 | // Starting from version 4.17, Slate has an improved clipping API. Old version required to specify per-vertex clipping 13 | // rectangle and unofficial GSlateScissorRect to correctly clip custom vertices made with FSlateDrawElement. 14 | #define ENGINE_COMPATIBILITY_LEGACY_CLIPPING_API BELOW_ENGINE_VERSION(4, 17) 15 | 16 | // Starting from version 4.18, FPaths::GameSavedDir() has been superseded by FPaths::ProjectSavedDir(). 17 | #define ENGINE_COMPATIBILITY_LEGACY_SAVED_DIR BELOW_ENGINE_VERSION(4, 18) 18 | 19 | // Starting from version 4.18, we have support for dual key bindings. 20 | #define ENGINE_COMPATIBILITY_SINGLE_KEY_BINDING BELOW_ENGINE_VERSION(4, 18) 21 | 22 | // Starting from version 4.18, FStringClassReference is replaced by FSoftClassPath. The new header contains a typedef 23 | // that renames FStringClassReference to FSoftClassPath, so it is still possible tu use the old type name in code. 24 | // The old header forwards to the new one but if used it outputs a warning, so we want to avoid it. 25 | #define ENGINE_COMPATIBILITY_LEGACY_STRING_CLASS_REF BELOW_ENGINE_VERSION(4, 18) 26 | 27 | // Starting from version 4.18, engine has a world post actor tick event which if available, provides a good opportunity 28 | // to call debug delegates after world actors are already updated. 29 | #define ENGINE_COMPATIBILITY_WITH_WORLD_POST_ACTOR_TICK FROM_ENGINE_VERSION(4, 18) 30 | 31 | // Starting from version 4.24, world actor tick event has additional world parameter. 32 | #define ENGINE_COMPATIBILITY_LEGACY_WORLD_ACTOR_TICK BELOW_ENGINE_VERSION(4, 24) 33 | 34 | // Starting from version 4.26, FKey::IsFloatAxis and FKey::IsVectorAxis are deprecated and replaced with FKey::IsAxis[1|2|3]D methods. 35 | #define ENGINE_COMPATIBILITY_LEGACY_KEY_AXIS_API BELOW_ENGINE_VERSION(4, 26) 36 | 37 | #define ENGINE_COMPATIBILITY_LEGACY_VECTOR2F BELOW_ENGINE_VERSION(5, 0) 38 | -------------------------------------------------------------------------------- /Source/ImGui/Public/ImGuiTextureHandle.h: -------------------------------------------------------------------------------- 1 | // Distributed under the MIT License (MIT) (see accompanying LICENSE file) 2 | 3 | #pragma once 4 | 5 | #include 6 | 7 | #include 8 | 9 | 10 | /** 11 | * Handle to texture resources registered in module instance. Returned after successful texture registration. 12 | * Can be implicitly converted to ImTextureID making it possible to use it directly with ImGui interface. 13 | * Once texture is not needed handle can be used to release resources. 14 | */ 15 | class IMGUI_API FImGuiTextureHandle 16 | { 17 | public: 18 | 19 | /** Creates an empty (null and not valid) texture handle. */ 20 | FImGuiTextureHandle(); 21 | 22 | /** 23 | * Checks whether this handle is null. Can be used as a quick test whether it points to any resources but it does 24 | * not check whether those resources are valid (see @ IsValid). 25 | * 26 | * @returns True, if this handle is null (Name is NAME_None and TextureId is invalid) and false otherwise. 27 | */ 28 | bool IsNull() const { return Name == NAME_None; } 29 | 30 | /** 31 | * Checks whether this handle is not null and valid. Valid handle points to valid texture resources. 32 | * It is slower but safer test, more useful when there is no guarantee that resources haven't been released. 33 | * 34 | * @returns True, if this handle is not null and valid, false otherwise. 35 | */ 36 | bool IsValid() const { return !IsNull() && HasValidEntry(); } 37 | 38 | /** Get the name of the texture resources (NAME_None if handle is null). */ 39 | const FName& GetName() const { return Name; } 40 | 41 | /** Get the ImGui texture id for this texture (invalid if handle is null). */ 42 | ImTextureID GetTextureId() const { return TextureId; } 43 | 44 | /** Implicit conversion to ImTextureID. */ 45 | operator ImTextureID() const { return GetTextureId(); } 46 | 47 | private: 48 | 49 | /** 50 | * Creates a texture handle with known name and texture id. 51 | * @param InName - Name of the texture 52 | * @param InTextureId - ImGui id of texture 53 | */ 54 | FImGuiTextureHandle(const FName& InName, ImTextureID InTextureId); 55 | 56 | /** Checks if texture manager has entry that matches this name and texture id index. */ 57 | bool HasValidEntry() const; 58 | 59 | FName Name; 60 | ImTextureID TextureId; 61 | 62 | // Give module class a private access, so it can create valid handles. 63 | friend class FImGuiModule; 64 | }; 65 | -------------------------------------------------------------------------------- /Source/ImGui/Private/ImGuiImplementation.cpp: -------------------------------------------------------------------------------- 1 | // Distributed under the MIT License (MIT) (see accompanying LICENSE file) 2 | 3 | #include "ImGuiImplementation.h" 4 | 5 | #include 6 | 7 | // For convenience and easy access to the ImGui source code, we build it as part of this module. 8 | // We don't need to define IMGUI_API manually because it is already done for this module. 9 | // UE 5.1 stopped defining PLATFORM_XBOXONE, so be safe if not defined 10 | #if !defined(PLATFORM_XBOXONE) 11 | #define PLATFORM_XBOXONE 0 12 | #endif 13 | #if PLATFORM_XBOXONE 14 | // Disable Win32 functions used in ImGui and not supported on XBox. 15 | #define IMGUI_DISABLE_WIN32_DEFAULT_CLIPBOARD_FUNCTIONS 16 | #define IMGUI_DISABLE_WIN32_DEFAULT_IME_FUNCTIONS 17 | #endif // PLATFORM_XBOXONE 18 | 19 | #if PLATFORM_WINDOWS 20 | #include 21 | #endif // PLATFORM_WINDOWS 22 | 23 | #if WITH_EDITOR 24 | 25 | #include "ImGuiModule.h" 26 | #include "Utilities/RedirectingHandle.h" 27 | 28 | // Redirecting handle which will automatically bind to another one, if a different instance of the module is loaded. 29 | struct FImGuiContextHandle : public Utilities::TRedirectingHandle 30 | { 31 | FImGuiContextHandle(ImGuiContext*& InDefaultContext) 32 | : Utilities::TRedirectingHandle(InDefaultContext) 33 | { 34 | if (FImGuiModule* Module = FModuleManager::GetModulePtr("ImGui")) 35 | { 36 | SetParent(Module->ImGuiContextHandle); 37 | } 38 | } 39 | }; 40 | 41 | static ImGuiContext* ImGuiContextPtr = nullptr; 42 | static FImGuiContextHandle ImGuiContextPtrHandle(ImGuiContextPtr); 43 | 44 | // Get the global ImGui context pointer (GImGui) indirectly to allow redirections in obsolete modules. 45 | #define GImGui (ImGuiContextPtrHandle.Get()) 46 | #endif // WITH_EDITOR 47 | 48 | #include "imgui.cpp" 49 | #include "imgui_demo.cpp" 50 | #include "imgui_draw.cpp" 51 | #include "imgui_widgets.cpp" 52 | 53 | #include "imgui_tables.cpp" 54 | 55 | #if PLATFORM_WINDOWS 56 | #include 57 | #endif // PLATFORM_WINDOWS 58 | 59 | #include "ImGuiInteroperability.h" 60 | 61 | 62 | namespace ImGuiImplementation 63 | { 64 | #if WITH_EDITOR 65 | FImGuiContextHandle& GetContextHandle() 66 | { 67 | return ImGuiContextPtrHandle; 68 | } 69 | 70 | void SetParentContextHandle(FImGuiContextHandle& Parent) 71 | { 72 | ImGuiContextPtrHandle.SetParent(&Parent); 73 | } 74 | #endif // WITH_EDITOR 75 | } 76 | -------------------------------------------------------------------------------- /Source/ImGui/Private/Widgets/SImGuiLayout.cpp: -------------------------------------------------------------------------------- 1 | // Distributed under the MIT License (MIT) (see accompanying LICENSE file) 2 | 3 | #include "SImGuiLayout.h" 4 | #include "SImGuiWidget.h" 5 | 6 | #include "ImGuiModuleManager.h" 7 | #include "ImGuiModuleSettings.h" 8 | 9 | #include 10 | #include 11 | #include 12 | #include 13 | 14 | 15 | BEGIN_SLATE_FUNCTION_BUILD_OPTIMIZATION 16 | void SImGuiLayout::Construct(const FArguments& InArgs) 17 | { 18 | checkf(InArgs._GameViewport, TEXT("Null Game Viewport argument")); 19 | 20 | ModuleManager = InArgs._ModuleManager; 21 | GameViewport = InArgs._GameViewport; 22 | 23 | if (ModuleManager) 24 | { 25 | auto& Settings = ModuleManager->GetSettings(); 26 | SetDPIScale(Settings.GetDPIScaleInfo()); 27 | if (!Settings.OnDPIScaleChangedDelegate.IsBoundToObject(this)) 28 | { 29 | Settings.OnDPIScaleChangedDelegate.AddRaw(this, &SImGuiLayout::SetDPIScale); 30 | } 31 | } 32 | 33 | ChildSlot 34 | [ 35 | // Remove accumulated scale to manually control how we draw data. 36 | SNew(SScaleBox) 37 | .IgnoreInheritedScale(true) 38 | .HAlign(HAlign_Fill) 39 | .VAlign(VAlign_Fill) 40 | .Visibility(EVisibility::SelfHitTestInvisible) 41 | [ 42 | // Apply custom scale if needed. 43 | SNew(SDPIScaler) 44 | .DPIScale(TAttribute(this, &SImGuiLayout::GetDPIScale)) 45 | .Visibility(EVisibility::SelfHitTestInvisible) 46 | [ 47 | SNew(SConstraintCanvas) 48 | + SConstraintCanvas::Slot() 49 | .Anchors(FAnchors(0.f, 0.f, 1.f, 1.f)) 50 | .AutoSize(true) 51 | .Offset(FMargin(1.f, 1.f, 0.f, 1.f)) 52 | .Alignment(FVector2D::ZeroVector) 53 | [ 54 | SNew(SImGuiWidget) 55 | .ModuleManager(InArgs._ModuleManager) 56 | .GameViewport(InArgs._GameViewport) 57 | .ContextIndex(InArgs._ContextIndex) 58 | #if !ENGINE_COMPATIBILITY_LEGACY_CLIPPING_API 59 | // To correctly clip borders. Using SScissorRectBox in older versions seems to be not necessary. 60 | .Clipping(EWidgetClipping::ClipToBounds) 61 | #endif 62 | ] 63 | ] 64 | ] 65 | ]; 66 | 67 | SetVisibility(EVisibility::SelfHitTestInvisible); 68 | } 69 | 70 | SImGuiLayout::~SImGuiLayout() 71 | { 72 | if (ModuleManager) 73 | { 74 | ModuleManager->GetSettings().OnDPIScaleChangedDelegate.RemoveAll(this); 75 | } 76 | } 77 | 78 | END_SLATE_FUNCTION_BUILD_OPTIMIZATION 79 | 80 | void SImGuiLayout::SetDPIScale(const FImGuiDPIScaleInfo& ScaleInfo) 81 | { 82 | DPIScale = ScaleInfo.GetSlateScale(); 83 | } 84 | -------------------------------------------------------------------------------- /Source/ImGui/Private/Utilities/RedirectingHandle.h: -------------------------------------------------------------------------------- 1 | // Distributed under the MIT License (MIT) (see accompanying LICENSE file) 2 | 3 | #pragma once 4 | 5 | #include 6 | #include 7 | 8 | 9 | namespace Utilities 10 | { 11 | // Handle initialized as a pointer to a default value, but can be redirected to follow other handles. 12 | // When detached, it will revert to the default value. Intended for cross-module redirections. 13 | template 14 | struct TRedirectingHandle 15 | { 16 | TRedirectingHandle(T& InDefaultValue) 17 | : Handle(&InDefaultValue) 18 | , DefaultHandle(&InDefaultValue) 19 | { 20 | } 21 | 22 | ~TRedirectingHandle() 23 | { 24 | // Broadcast null pointer as a request to detach. 25 | OnRedirectionUpdate.Broadcast(nullptr); 26 | } 27 | 28 | // Check whether this handle points to the default value. 29 | bool IsDefault() const 30 | { 31 | return (Handle == DefaultHandle); 32 | } 33 | 34 | // Get the current value. 35 | T& Get() const 36 | { 37 | return *Handle; 38 | } 39 | 40 | // Set the other handle as a parent to this one. Passing null or itself will result with detaching from 41 | // the current parent (if any) and reverting back to the default value. 42 | void SetParent(TRedirectingHandle* InParent) 43 | { 44 | if (InParent != Parent) 45 | { 46 | if (Parent) 47 | { 48 | Parent->OnRedirectionUpdate.RemoveAll(this); 49 | } 50 | 51 | // Protecting from setting itself as a parent. 52 | Parent = (InParent != this) ? InParent : nullptr; 53 | 54 | if (Parent) 55 | { 56 | Parent->OnRedirectionUpdate.AddRaw(this, &TRedirectingHandle::UpdateRedirection); 57 | } 58 | 59 | SetHandle((Parent) ? Parent->Handle : DefaultHandle); 60 | } 61 | } 62 | 63 | protected: 64 | 65 | void UpdateRedirection(T* InHandle) 66 | { 67 | if (InHandle) 68 | { 69 | SetHandle(InHandle); 70 | } 71 | else 72 | { 73 | // Interpreting null as a signal to detach. 74 | SetParent(nullptr); 75 | } 76 | } 77 | 78 | void SetHandle(T* InHandle) 79 | { 80 | if (InHandle != Handle) 81 | { 82 | Handle = InHandle; 83 | OnRedirectionUpdate.Broadcast(Handle); 84 | } 85 | } 86 | 87 | T* Handle; 88 | T* DefaultHandle; 89 | 90 | TRedirectingHandle* Parent = nullptr; 91 | 92 | // Event with a new handle value or null pointer as a signal to detach. 93 | DECLARE_MULTICAST_DELEGATE_OneParam(FRedirectionUpdateDelegate, T*); 94 | FRedirectionUpdateDelegate OnRedirectionUpdate; 95 | }; 96 | } 97 | -------------------------------------------------------------------------------- /Source/ImGui/Private/ImGuiInputState.cpp: -------------------------------------------------------------------------------- 1 | // Distributed under the MIT License (MIT) (see accompanying LICENSE file) 2 | 3 | #include "ImGuiInputState.h" 4 | 5 | #include 6 | #include 7 | #include 8 | 9 | 10 | FImGuiInputState::FImGuiInputState() 11 | { 12 | Reset(); 13 | } 14 | 15 | void FImGuiInputState::AddCharacter(TCHAR Char) 16 | { 17 | InputCharacters.Add(Char); 18 | } 19 | 20 | void FImGuiInputState::SetKeyDown(uint32 KeyIndex, bool bIsDown) 21 | { 22 | if (KeyIndex < Utilities::GetArraySize(KeysDown)) 23 | { 24 | if (KeysDown[KeyIndex] != bIsDown) 25 | { 26 | KeysDown[KeyIndex] = bIsDown; 27 | KeysUpdateRange.AddPosition(KeyIndex); 28 | } 29 | } 30 | } 31 | 32 | void FImGuiInputState::SetMouseDown(uint32 MouseIndex, bool bIsDown) 33 | { 34 | if (MouseIndex < Utilities::GetArraySize(MouseButtonsDown)) 35 | { 36 | if (MouseButtonsDown[MouseIndex] != bIsDown) 37 | { 38 | MouseButtonsDown[MouseIndex] = bIsDown; 39 | MouseButtonsUpdateRange.AddPosition(MouseIndex); 40 | } 41 | } 42 | } 43 | 44 | void FImGuiInputState::ClearUpdateState() 45 | { 46 | ClearCharacters(); 47 | 48 | KeyDownEvents.Reset(); 49 | KeyUpEvents.Reset(); 50 | 51 | KeysUpdateRange.SetEmpty(); 52 | MouseButtonsUpdateRange.SetEmpty(); 53 | 54 | MouseWheelDelta = 0.f; 55 | 56 | bTouchProcessed = bTouchDown; 57 | } 58 | 59 | void FImGuiInputState::ClearCharacters() 60 | { 61 | InputCharacters.Empty(); 62 | } 63 | 64 | void FImGuiInputState::ClearKeys() 65 | { 66 | using std::fill; 67 | fill(KeysDown, &KeysDown[Utilities::GetArraySize(KeysDown)], false); 68 | 69 | // Mark the whole array as dirty because potentially each entry could be affected. 70 | KeysUpdateRange.SetFull(); 71 | } 72 | 73 | void FImGuiInputState::ClearMouseButtons() 74 | { 75 | using std::fill; 76 | fill(MouseButtonsDown, &MouseButtonsDown[Utilities::GetArraySize(MouseButtonsDown)], false); 77 | 78 | // Mark the whole array as dirty because potentially each entry could be affected. 79 | MouseButtonsUpdateRange.SetFull(); 80 | } 81 | 82 | void FImGuiInputState::ClearMouseAnalogue() 83 | { 84 | MousePosition = FVector2D::ZeroVector; 85 | MouseWheelDelta = 0.f; 86 | } 87 | 88 | void FImGuiInputState::ClearModifierKeys() 89 | { 90 | bIsControlDown = false; 91 | bIsShiftDown = false; 92 | bIsAltDown = false; 93 | } 94 | 95 | void FImGuiInputState::ClearNavigationInputs() 96 | { 97 | using std::fill; 98 | fill(NavigationInputs, &NavigationInputs[Utilities::GetArraySize(NavigationInputs)], 0.f); 99 | } 100 | 101 | -------------------------------------------------------------------------------- /Source/ImGui/Private/ImGuiDelegatesContainer.cpp: -------------------------------------------------------------------------------- 1 | // Distributed under the MIT License (MIT) (see accompanying LICENSE file) 2 | 3 | #include "ImGuiDelegatesContainer.h" 4 | 5 | #include "ImGuiModule.h" 6 | #include "Utilities/WorldContextIndex.h" 7 | 8 | 9 | #if !WITH_EDITOR 10 | // 11 | // Non-editor version without container redirection 12 | // 13 | 14 | FImGuiDelegatesContainer& FImGuiDelegatesContainer::Get() 15 | { 16 | static FImGuiDelegatesContainer* Container = new FImGuiDelegatesContainer(); 17 | return *Container; 18 | } 19 | 20 | #endif // !WITH_EDITOR 21 | 22 | 23 | #if WITH_EDITOR 24 | // 25 | // Editor version supporting container redirection needed for hot-reloading 26 | // 27 | 28 | #include "Utilities/RedirectingHandle.h" 29 | 30 | // Redirecting handle which will always bind to a container from the currently loaded module. 31 | struct FImGuiDelegatesContainerHandle : Utilities::TRedirectingHandle 32 | { 33 | FImGuiDelegatesContainerHandle(FImGuiDelegatesContainer& InDefaultContainer) 34 | : Utilities::TRedirectingHandle(InDefaultContainer) 35 | { 36 | if (FImGuiModule* Module = FModuleManager::GetModulePtr("ImGui")) 37 | { 38 | SetParent(Module->DelegatesContainerHandle); 39 | } 40 | } 41 | }; 42 | 43 | FImGuiDelegatesContainer& FImGuiDelegatesContainer::Get() 44 | { 45 | return GetHandle().Get(); 46 | } 47 | 48 | FImGuiDelegatesContainerHandle& FImGuiDelegatesContainer::GetHandle() 49 | { 50 | struct FContainerInstance 51 | { 52 | FContainerInstance() : Container(), Handle(Container) {} 53 | FImGuiDelegatesContainer Container; 54 | FImGuiDelegatesContainerHandle Handle; 55 | }; 56 | static FContainerInstance* Instance = new FContainerInstance(); 57 | return Instance->Handle; 58 | } 59 | 60 | void FImGuiDelegatesContainer::MoveContainer(FImGuiDelegatesContainerHandle& OtherContainerHandle) 61 | { 62 | // Only move data if pointer points to default instance, otherwise our data has already been moved and we only 63 | // keep pointer to a more recent version. 64 | if (GetHandle().IsDefault()) 65 | { 66 | OtherContainerHandle.Get() = MoveTemp(GetHandle().Get()); 67 | GetHandle().Get().Clear(); 68 | } 69 | 70 | // Update pointer to the most recent version. 71 | GetHandle().SetParent(&OtherContainerHandle); 72 | } 73 | 74 | #endif // WITH_EDITOR 75 | 76 | 77 | int32 FImGuiDelegatesContainer::GetContextIndex(UWorld* World) 78 | { 79 | return Utilities::GetWorldContextIndex(*World); 80 | } 81 | 82 | void FImGuiDelegatesContainer::Clear() 83 | { 84 | WorldEarlyDebugDelegates.Empty(); 85 | WorldDebugDelegates.Empty(); 86 | MultiContextEarlyDebugDelegate.Clear(); 87 | MultiContextDebugDelegate.Clear(); 88 | } 89 | -------------------------------------------------------------------------------- /Source/ImGui/Private/ImGuiDrawData.cpp: -------------------------------------------------------------------------------- 1 | // Distributed under the MIT License (MIT) (see accompanying LICENSE file) 2 | 3 | #include "ImGuiDrawData.h" 4 | 5 | 6 | #if ENGINE_COMPATIBILITY_LEGACY_CLIPPING_API 7 | void FImGuiDrawList::CopyVertexData(TArray& OutVertexBuffer, const FTransform2D& Transform, const FSlateRotatedRect& VertexClippingRect) const 8 | #else 9 | void FImGuiDrawList::CopyVertexData(TArray& OutVertexBuffer, const FTransform2D& Transform) const 10 | #endif // ENGINE_COMPATIBILITY_LEGACY_CLIPPING_API 11 | { 12 | // Reset and reserve space in destination buffer. 13 | OutVertexBuffer.SetNumUninitialized(ImGuiVertexBuffer.Size, false); 14 | 15 | // Transform and copy vertex data. 16 | for (int Idx = 0; Idx < ImGuiVertexBuffer.Size; Idx++) 17 | { 18 | const ImDrawVert& ImGuiVertex = ImGuiVertexBuffer[Idx]; 19 | FSlateVertex& SlateVertex = OutVertexBuffer[Idx]; 20 | 21 | // Final UV is calculated in shader as XY * ZW, so we need set all components. 22 | SlateVertex.TexCoords[0] = ImGuiVertex.uv.x; 23 | SlateVertex.TexCoords[1] = ImGuiVertex.uv.y; 24 | SlateVertex.TexCoords[2] = SlateVertex.TexCoords[3] = 1.f; 25 | 26 | #if ENGINE_COMPATIBILITY_LEGACY_CLIPPING_API 27 | const FVector2D VertexPosition = Transform.TransformPoint(ImGuiInterops::ToVector2D(ImGuiVertex.pos)); 28 | SlateVertex.Position[0] = VertexPosition.X; 29 | SlateVertex.Position[1] = VertexPosition.Y; 30 | SlateVertex.ClipRect = VertexClippingRect; 31 | #else 32 | #if ENGINE_COMPATIBILITY_LEGACY_VECTOR2F 33 | SlateVertex.Position = Transform.TransformPoint(ImGuiInterops::ToVector2D(ImGuiVertex.pos)); 34 | #else 35 | SlateVertex.Position = (FVector2f)Transform.TransformPoint(ImGuiInterops::ToVector2D(ImGuiVertex.pos)); 36 | #endif // ENGINE_COMPATIBILITY_LEGACY_VECTOR2F 37 | #endif // ENGINE_COMPATIBILITY_LEGACY_CLIPPING_API 38 | 39 | // Unpack ImU32 color. 40 | SlateVertex.Color = ImGuiInterops::UnpackImU32Color(ImGuiVertex.col); 41 | } 42 | } 43 | 44 | void FImGuiDrawList::CopyIndexData(TArray& OutIndexBuffer, const int32 StartIndex, const int32 NumElements) const 45 | { 46 | // Reset buffer. 47 | OutIndexBuffer.SetNumUninitialized(NumElements, false); 48 | 49 | // Copy elements (slow copy because of different sizes of ImDrawIdx and SlateIndex and because SlateIndex can 50 | // have different size on different platforms). 51 | for (int i = 0; i < NumElements; i++) 52 | { 53 | OutIndexBuffer[i] = ImGuiIndexBuffer[StartIndex + i]; 54 | } 55 | } 56 | 57 | void FImGuiDrawList::TransferDrawData(ImDrawList& Src) 58 | { 59 | // Move data from source to this list. 60 | Src.CmdBuffer.swap(ImGuiCommandBuffer); 61 | Src.IdxBuffer.swap(ImGuiIndexBuffer); 62 | Src.VtxBuffer.swap(ImGuiVertexBuffer); 63 | } 64 | -------------------------------------------------------------------------------- /Source/ImGui/ImGui.Build.cs: -------------------------------------------------------------------------------- 1 | // Distributed under the MIT License (MIT) (see accompanying LICENSE file) 2 | 3 | using System.Collections.Generic; 4 | using System.IO; 5 | using UnrealBuildTool; 6 | 7 | public class ImGui : ModuleRules 8 | { 9 | #if WITH_FORWARDED_MODULE_RULES_CTOR 10 | public ImGui(ReadOnlyTargetRules Target) : base(Target) 11 | #else 12 | public ImGui(TargetInfo Target) 13 | #endif 14 | { 15 | 16 | #if WITH_FORWARDED_MODULE_RULES_CTOR 17 | bool bBuildEditor = Target.bBuildEditor; 18 | #else 19 | bool bBuildEditor = (Target.Type == TargetRules.TargetType.Editor); 20 | #endif 21 | 22 | // Developer modules are automatically loaded only in editor builds but can be stripped out from other builds. 23 | // Enable runtime loader, if you want this module to be automatically loaded in runtime builds (monolithic). 24 | bool bEnableRuntimeLoader = true; 25 | 26 | PCHUsage = PCHUsageMode.UseExplicitOrSharedPCHs; 27 | 28 | #if UE_4_24_OR_LATER 29 | bLegacyPublicIncludePaths = false; 30 | ShadowVariableWarningLevel = WarningLevel.Error; 31 | bTreatAsEngineModule = true; 32 | #endif 33 | 34 | PublicIncludePaths.AddRange( 35 | new string[] { 36 | Path.Combine(ModuleDirectory, "../ThirdParty/ImGuiLibrary/Include"), 37 | // ... add public include paths required here ... 38 | } 39 | ); 40 | 41 | 42 | PrivateIncludePaths.AddRange( 43 | new string[] { 44 | "ImGui/Private", 45 | "ThirdParty/ImGuiLibrary/Private", 46 | // ... add other private include paths required here ... 47 | } 48 | ); 49 | 50 | 51 | PublicDependencyModuleNames.AddRange( 52 | new string[] 53 | { 54 | "Core", 55 | "Projects" 56 | // ... add other public dependencies that you statically link with here ... 57 | } 58 | ); 59 | 60 | 61 | PrivateDependencyModuleNames.AddRange( 62 | new string[] 63 | { 64 | "CoreUObject", 65 | "EnhancedInput", 66 | "Engine", 67 | "InputCore", 68 | "Slate", 69 | "SlateCore" 70 | // ... add private dependencies that you statically link with here ... 71 | } 72 | ); 73 | 74 | 75 | if (bBuildEditor) 76 | { 77 | PrivateDependencyModuleNames.AddRange( 78 | new string[] 79 | { 80 | "EditorStyle", 81 | "Settings", 82 | "UnrealEd", 83 | } 84 | ); 85 | } 86 | 87 | 88 | DynamicallyLoadedModuleNames.AddRange( 89 | new string[] 90 | { 91 | // ... add any modules that your module loads dynamically here ... 92 | } 93 | ); 94 | 95 | 96 | #if !UE_4_19_OR_LATER 97 | List PrivateDefinitions = Definitions; 98 | #endif 99 | 100 | PrivateDefinitions.Add(string.Format("RUNTIME_LOADER_ENABLED={0}", bEnableRuntimeLoader ? 1 : 0)); 101 | } 102 | } 103 | -------------------------------------------------------------------------------- /Source/ImGui/Private/ImGuiDrawData.h: -------------------------------------------------------------------------------- 1 | // Distributed under the MIT License (MIT) (see accompanying LICENSE file) 2 | 3 | #pragma once 4 | 5 | #include "ImGuiInteroperability.h" 6 | #include "VersionCompatibility.h" 7 | 8 | #include 9 | 10 | #include 11 | 12 | 13 | // ImGui draw command data transformed for Slate. 14 | struct FImGuiDrawCommand 15 | { 16 | uint32 NumElements; 17 | FSlateRect ClippingRect; 18 | TextureIndex TextureId; 19 | }; 20 | 21 | // Wraps raw ImGui draw list data in utilities that transform them for Slate. 22 | class FImGuiDrawList 23 | { 24 | public: 25 | 26 | // Get the number of draw commands in this list. 27 | FORCEINLINE int NumCommands() const { return ImGuiCommandBuffer.Size; } 28 | 29 | // Get the draw command by number. 30 | // @param CommandNb - Number of draw command 31 | // @param Transform - Transform to apply to clipping rectangle 32 | // @returns Draw command data 33 | FImGuiDrawCommand GetCommand(int CommandNb, const FTransform2D& Transform) const 34 | { 35 | const ImDrawCmd& ImGuiCommand = ImGuiCommandBuffer[CommandNb]; 36 | return { ImGuiCommand.ElemCount, TransformRect(Transform, ImGuiInterops::ToSlateRect(ImGuiCommand.ClipRect)), 37 | ImGuiInterops::ToTextureIndex(ImGuiCommand.TextureId) }; 38 | } 39 | 40 | #if ENGINE_COMPATIBILITY_LEGACY_CLIPPING_API 41 | // Transform and copy vertex data to target buffer (old data in the target buffer are replaced). 42 | // @param OutVertexBuffer - Destination buffer 43 | // @param Transform - Transform to apply to all vertices 44 | // @param VertexClippingRect - Clipping rectangle for transformed Slate vertices 45 | void CopyVertexData(TArray& OutVertexBuffer, const FTransform2D& Transform, const FSlateRotatedRect& VertexClippingRect) const; 46 | #else 47 | // Transform and copy vertex data to target buffer (old data in the target buffer are replaced). 48 | // @param OutVertexBuffer - Destination buffer 49 | // @param Transform - Transform to apply to all vertices 50 | void CopyVertexData(TArray& OutVertexBuffer, const FTransform2D& Transform) const; 51 | #endif // ENGINE_COMPATIBILITY_LEGACY_CLIPPING_API 52 | 53 | // Transform and copy index data to target buffer (old data in the target buffer are replaced). 54 | // Internal index buffer contains enough data to match the sum of NumElements from all draw commands. 55 | // @param OutIndexBuffer - Destination buffer 56 | // @param StartIndex - Start copying source data starting from this index 57 | // @param NumElements - How many elements we want to copy 58 | void CopyIndexData(TArray& OutIndexBuffer, const int32 StartIndex, const int32 NumElements) const; 59 | 60 | // Transfers data from ImGui source list to this object. Leaves source cleared. 61 | void TransferDrawData(ImDrawList& Src); 62 | 63 | private: 64 | 65 | ImVector ImGuiCommandBuffer; 66 | ImVector ImGuiIndexBuffer; 67 | ImVector ImGuiVertexBuffer; 68 | }; 69 | -------------------------------------------------------------------------------- /Source/ImGui/Private/ImGuiDemo.cpp: -------------------------------------------------------------------------------- 1 | // Distributed under the MIT License (MIT) (see accompanying LICENSE file) 2 | 3 | #include "ImGuiDemo.h" 4 | 5 | #include "ImGuiModuleProperties.h" 6 | 7 | #include 8 | 9 | 10 | // Demo copied (with minor modifications) from ImGui examples. See https://github.com/ocornut/imgui. 11 | void FImGuiDemo::DrawControls(int32 ContextIndex) 12 | { 13 | if (Properties.ShowDemo()) 14 | { 15 | const int32 ContextBit = ContextIndex < 0 ? 0 : 1 << ContextIndex; 16 | 17 | // 1. Show a simple window 18 | // Tip: if we don't call ImGui::Begin()/ImGui::End() the widgets appears in a window automatically called "Debug" 19 | { 20 | static float f = 0.0f; 21 | ImGui::Text("Hello, world!"); 22 | ImGui::SliderFloat("float", &f, 0.0f, 1.0f); 23 | ImGui::ColorEdit3("clear color", (float*)&ClearColor); 24 | 25 | if (ContextBit) 26 | { 27 | if (ImGui::Button("Demo Window")) ShowDemoWindowMask ^= ContextBit; 28 | if (ImGui::Button("Another Window")) ShowAnotherWindowMask ^= ContextBit; 29 | } 30 | ImGui::Text("Application average %.3f ms/frame (%.1f FPS)", 1000.0f / ImGui::GetIO().Framerate, ImGui::GetIO().Framerate); 31 | } 32 | 33 | // 2. Show another simple window, this time using an explicit Begin/End pair 34 | if (ShowAnotherWindowMask & ContextBit) 35 | { 36 | ImGui::SetNextWindowSize(ImVec2(200, 100), ImGuiCond_FirstUseEver); 37 | ImGui::Begin("Another Window"); 38 | ImGui::Text("Hello"); 39 | ImGui::End(); 40 | } 41 | 42 | // 3. Show the ImGui test window. Most of the sample code is in ImGui::ShowTestWindow() 43 | if (ShowDemoWindowMask & ContextBit) 44 | { 45 | // If more than one demo window is opened display warning about running ImGui examples in multiple contexts. 46 | 47 | // For everything, but the first windows in this frame we assume warning. 48 | bool bWarning = true; 49 | if (GFrameNumber > LastDemoWindowFrameNumber) 50 | { 51 | // If this is the first window in this frame, then we need to look at the last frame to see whether 52 | // there were more than one windows. Higher frame distance automatically means that there were not. 53 | bWarning = ((GFrameNumber - LastDemoWindowFrameNumber) == 1) && (DemoWindowCounter > 1); 54 | 55 | LastDemoWindowFrameNumber = GFrameNumber; 56 | DemoWindowCounter = 0; 57 | } 58 | 59 | DemoWindowCounter++; 60 | 61 | if (bWarning) 62 | { 63 | ImGui::Spacing(); 64 | 65 | ImGui::PushStyleColor(ImGuiCol_Text, { 1.f, 1.f, 0.5f, 1.f }); 66 | ImGui::TextWrapped("Demo Window is opened in more than one context, some of the ImGui examples may not work correctly."); 67 | ImGui::PopStyleColor(); 68 | 69 | if (ImGui::IsItemHovered()) 70 | { 71 | ImGui::SetTooltip( 72 | "Some of the ImGui examples that use static variables may not work correctly\n" 73 | "when run concurrently in multiple contexts.\n" 74 | "If you have a problem with an example try to run it in one context only."); 75 | } 76 | } 77 | 78 | // Draw demo window. 79 | ImGui::SetNextWindowPos(ImVec2(650, 20), ImGuiCond_FirstUseEver); 80 | ImGui::ShowDemoWindow(); 81 | } 82 | } 83 | } 84 | -------------------------------------------------------------------------------- /Source/ImGui/Private/ImGuiModuleManager.h: -------------------------------------------------------------------------------- 1 | // Distributed under the MIT License (MIT) (see accompanying LICENSE file) 2 | 3 | #pragma once 4 | 5 | #include "ImGuiContextManager.h" 6 | #include "ImGuiDemo.h" 7 | #include "ImGuiModuleCommands.h" 8 | #include "ImGuiModuleProperties.h" 9 | #include "ImGuiModuleSettings.h" 10 | #include "TextureManager.h" 11 | #include "Widgets/SImGuiLayout.h" 12 | 13 | 14 | // Central manager that implements module logic. It initializes and controls remaining module components. 15 | class FImGuiModuleManager 16 | { 17 | // Allow module to control life-cycle of this class. 18 | friend class FImGuiModule; 19 | 20 | public: 21 | 22 | // Get interface to module settings. 23 | FImGuiModuleSettings& GetSettings() { return Settings; } 24 | 25 | // Get interface to module state properties. 26 | FImGuiModuleProperties& GetProperties() { return Properties; } 27 | 28 | // Get ImGui contexts manager. 29 | FImGuiContextManager& GetContextManager() { return ContextManager; } 30 | 31 | // Get texture resources manager. 32 | FTextureManager& GetTextureManager() { return TextureManager; } 33 | 34 | // Event called right after ImGui is updated, to give other subsystems chance to react. 35 | FSimpleMulticastDelegate& OnPostImGuiUpdate() { return PostImGuiUpdateEvent; } 36 | 37 | void RebuildFontAtlas(); 38 | 39 | private: 40 | 41 | FImGuiModuleManager(); 42 | ~FImGuiModuleManager(); 43 | 44 | FImGuiModuleManager(const FImGuiModuleManager&) = delete; 45 | FImGuiModuleManager& operator=(const FImGuiModuleManager&) = delete; 46 | 47 | FImGuiModuleManager(FImGuiModuleManager&&) = delete; 48 | FImGuiModuleManager& operator=(FImGuiModuleManager&&) = delete; 49 | 50 | void LoadTextures(); 51 | void BuildFontAtlasTexture(); 52 | 53 | bool IsTickRegistered() { return TickDelegateHandle.IsValid(); } 54 | void RegisterTick(); 55 | void UnregisterTick(); 56 | 57 | void CreateTickInitializer(); 58 | void ReleaseTickInitializer(); 59 | 60 | void Tick(float DeltaSeconds); 61 | 62 | void OnViewportCreated(); 63 | 64 | void AddWidgetToViewport(UGameViewportClient* GameViewport); 65 | void AddWidgetsToActiveViewports(); 66 | 67 | void OnContextProxyCreated(int32 ContextIndex, FImGuiContextProxy& ContextProxy); 68 | 69 | // Event that we call after ImGui is updated. 70 | FSimpleMulticastDelegate PostImGuiUpdateEvent; 71 | 72 | // Collection of module state properties. 73 | FImGuiModuleProperties Properties; 74 | 75 | // Tying module console commands to life-cycle of this manager and module. 76 | FImGuiModuleCommands Commands; 77 | 78 | // ImGui settings proxy (valid in every loading stage). 79 | FImGuiModuleSettings Settings; 80 | 81 | // Widget that we add to all created contexts to draw ImGui demo. 82 | FImGuiDemo ImGuiDemo; 83 | 84 | // Manager for ImGui contexts. 85 | FImGuiContextManager ContextManager; 86 | 87 | // Manager for textures resources. 88 | FTextureManager TextureManager; 89 | 90 | // Slate widgets that we created. 91 | TArray> Widgets; 92 | 93 | FDelegateHandle TickInitializerHandle; 94 | FDelegateHandle TickDelegateHandle; 95 | FDelegateHandle ViewportCreatedHandle; 96 | 97 | bool bTexturesLoaded = false; 98 | }; 99 | -------------------------------------------------------------------------------- /Source/ImGui/Private/Utilities/DebugExecBindings.cpp: -------------------------------------------------------------------------------- 1 | // Distributed under the MIT License (MIT) (see accompanying LICENSE file) 2 | 3 | #include "DebugExecBindings.h" 4 | 5 | #include "ImGuiModuleSettings.h" 6 | 7 | #include 8 | #include 9 | 10 | #include "EnhancedPlayerInput.h" 11 | 12 | 13 | namespace 14 | { 15 | FKeyBind CreateKeyBind(const FImGuiKeyInfo& KeyInfo, const FString& Command) 16 | { 17 | FKeyBind KeyBind; 18 | KeyBind.Command = Command; 19 | KeyBind.Key = KeyInfo.Key; 20 | KeyBind.bDisabled = false; 21 | 22 | #define FILL_MODIFIER_DATA(KeyInfoProperty, BindProperty, BindIgnoreProperty)\ 23 | if (KeyInfo.KeyInfoProperty == ECheckBoxState::Undetermined)\ 24 | {\ 25 | KeyBind.BindProperty = KeyBind.BindIgnoreProperty = false;\ 26 | }\ 27 | else\ 28 | {\ 29 | KeyBind.BindProperty = (KeyInfo.KeyInfoProperty == ECheckBoxState::Checked);\ 30 | KeyBind.BindIgnoreProperty = !KeyBind.BindProperty;\ 31 | } 32 | 33 | FILL_MODIFIER_DATA(Shift, Shift, bIgnoreShift); 34 | FILL_MODIFIER_DATA(Ctrl, Control, bIgnoreCtrl); 35 | FILL_MODIFIER_DATA(Alt, Alt, bIgnoreAlt); 36 | FILL_MODIFIER_DATA(Cmd, Cmd, bIgnoreCmd); 37 | 38 | #undef FILL_MODIFIER_DATA 39 | 40 | return KeyBind; 41 | } 42 | 43 | bool IsBindable(const FKey& Key) 44 | { 45 | #if ENGINE_COMPATIBILITY_LEGACY_KEY_AXIS_API 46 | return Key.IsValid() && Key != EKeys::AnyKey && !Key.IsFloatAxis() && !Key.IsVectorAxis() 47 | && !Key.IsGamepadKey() && !Key.IsModifierKey() && !Key.IsMouseButton(); 48 | #else 49 | return Key.IsValid() && Key != EKeys::AnyKey && !Key.IsAxis1D() && !Key.IsAxis2D() 50 | && !Key.IsAxis3D() && !Key.IsGamepadKey() && !Key.IsModifierKey() && !Key.IsMouseButton(); 51 | #endif 52 | } 53 | 54 | void UpdatePlayerInput(UEnhancedPlayerInput* PlayerInput, const FKeyBind& KeyBind) 55 | { 56 | const int32 Index = PlayerInput->DebugExecBindings.IndexOfByPredicate([&](const FKeyBind& PlayerKeyBind) 57 | { 58 | return PlayerKeyBind.Command.Equals(KeyBind.Command, ESearchCase::IgnoreCase); 59 | }); 60 | 61 | if (IsBindable(KeyBind.Key)) 62 | { 63 | if (Index != INDEX_NONE) 64 | { 65 | PlayerInput->DebugExecBindings[Index] = KeyBind; 66 | } 67 | else 68 | { 69 | PlayerInput->DebugExecBindings.Add(KeyBind); 70 | } 71 | } 72 | else 73 | { 74 | if (Index != INDEX_NONE) 75 | { 76 | PlayerInput->DebugExecBindings.RemoveAt(Index); 77 | } 78 | } 79 | } 80 | } 81 | 82 | namespace DebugExecBindings 83 | { 84 | void UpdatePlayerInputs(const FImGuiKeyInfo& KeyInfo, const FString& Command) 85 | { 86 | checkf(!Command.IsEmpty(), TEXT("Empty command.")); 87 | 88 | const FKeyBind KeyBind = CreateKeyBind(KeyInfo, Command); 89 | 90 | // Update default player input, so changes will be visible in all PIE sessions created after this point. 91 | if (UEnhancedPlayerInput* DefaultPlayerInput = GetMutableDefault()) 92 | { 93 | UpdatePlayerInput(DefaultPlayerInput, KeyBind); 94 | } 95 | 96 | // Update all existing player inputs to see changes in running PIE session. 97 | for (TObjectIterator It; It; ++It) 98 | { 99 | UpdatePlayerInput(*It, KeyBind); 100 | } 101 | } 102 | } 103 | -------------------------------------------------------------------------------- /Source/ImGui/Public/ImGuiModuleProperties.h: -------------------------------------------------------------------------------- 1 | // Distributed under the MIT License (MIT) (see accompanying LICENSE file) 2 | 3 | #pragma once 4 | 5 | struct ImFontConfig; 6 | 7 | /** Properties that define state of the ImGui module. */ 8 | class IMGUI_API FImGuiModuleProperties 9 | { 10 | public: 11 | 12 | /** Check whether input is enabled. */ 13 | bool IsInputEnabled() const { return bInputEnabled; } 14 | 15 | /** Enable or disable ImGui input. */ 16 | void SetInputEnabled(bool bEnabled) { bInputEnabled = bEnabled; } 17 | 18 | /** Toggle ImGui input. */ 19 | void ToggleInput() { SetInputEnabled(!IsInputEnabled()); } 20 | 21 | /** Check whether keyboard navigation is enabled. */ 22 | bool IsKeyboardNavigationEnabled() const { return bKeyboardNavigationEnabled; } 23 | 24 | /** Enable or disable keyboard navigation. */ 25 | void SetKeyboardNavigationEnabled(bool bEnabled) { bKeyboardNavigationEnabled = bEnabled; } 26 | 27 | /** Toggle keyboard navigation. */ 28 | void ToggleKeyboardNavigation() { SetKeyboardNavigationEnabled(!IsKeyboardNavigationEnabled()); } 29 | 30 | /** Check whether gamepad navigation is enabled. */ 31 | bool IsGamepadNavigationEnabled() const { return bGamepadNavigationEnabled; } 32 | 33 | /** Enable or disable gamepad navigation. */ 34 | void SetGamepadNavigationEnabled(bool bEnabled) { bGamepadNavigationEnabled = bEnabled; } 35 | 36 | /** Toggle gamepad navigation. */ 37 | void ToggleGamepadNavigation() { SetGamepadNavigationEnabled(!IsGamepadNavigationEnabled()); } 38 | 39 | /** Check whether keyboard input is shared with game. */ 40 | bool IsKeyboardInputShared() const { return bKeyboardInputShared; } 41 | 42 | /** Set whether keyboard input should be shared with game. */ 43 | void SetKeyboardInputShared(bool bShared) { bKeyboardInputShared = bShared; } 44 | 45 | /** Toggle whether keyboard input should be shared with game. */ 46 | void ToggleKeyboardInputSharing() { SetKeyboardInputShared(!IsKeyboardInputShared()); } 47 | 48 | /** Check whether gamepad input is shared with game. */ 49 | bool IsGamepadInputShared() const { return bGamepadInputShared; } 50 | 51 | /** Set whether gamepad input should be shared with game. */ 52 | void SetGamepadInputShared(bool bShared) { bGamepadInputShared = bShared; } 53 | 54 | /** Toggle whether gamepad input should be shared with game. */ 55 | void ToggleGamepadInputSharing() { SetGamepadInputShared(!IsGamepadInputShared()); } 56 | 57 | /** Check whether mouse input is shared with game. */ 58 | bool IsMouseInputShared() const { return bMouseInputShared; } 59 | 60 | /** Set whether mouse input should be shared with game. */ 61 | void SetMouseInputShared(bool bShared) { bMouseInputShared = bShared; } 62 | 63 | /** Toggle whether mouse input should be shared with game. */ 64 | void ToggleMouseInputSharing() { SetMouseInputShared(!IsMouseInputShared()); } 65 | 66 | /** Check whether ImGui demo is visible. */ 67 | bool ShowDemo() const { return bShowDemo; } 68 | 69 | /** Show or hide ImGui demo. */ 70 | void SetShowDemo(bool bShow) { bShowDemo = bShow; } 71 | 72 | /** Toggle ImGui demo. */ 73 | void ToggleDemo() { SetShowDemo(!ShowDemo()); } 74 | 75 | /** Adds a new font to initialize */ 76 | void AddCustomFont(FName FontName, TSharedPtr Font) { CustomFonts.Emplace(FontName, Font); } 77 | 78 | /** Removes a font from the custom font list */ 79 | void RemoveCustomFont(FName FontName) { CustomFonts.Remove(FontName); } 80 | 81 | /** Gets the map of registered custom fonts */ 82 | TMap>& GetCustomFonts() { return CustomFonts; } 83 | 84 | private: 85 | 86 | bool bInputEnabled = false; 87 | 88 | bool bKeyboardNavigationEnabled = false; 89 | bool bGamepadNavigationEnabled = false; 90 | 91 | bool bKeyboardInputShared = false; 92 | bool bGamepadInputShared = false; 93 | bool bMouseInputShared = false; 94 | 95 | bool bShowDemo = false; 96 | 97 | TMap> CustomFonts; 98 | }; 99 | -------------------------------------------------------------------------------- /Source/ImGui/Private/Editor/ImGuiEditor.cpp: -------------------------------------------------------------------------------- 1 | // Distributed under the MIT License (MIT) (see accompanying LICENSE file) 2 | 3 | #include "ImGuiEditor.h" 4 | 5 | #if WITH_EDITOR 6 | 7 | #include "ImGuiCanvasSizeInfoCustomization.h" 8 | #include "ImGuiKeyInfoCustomization.h" 9 | #include "ImGuiModuleSettings.h" 10 | 11 | #include 12 | #include 13 | 14 | 15 | #define LOCTEXT_NAMESPACE "ImGuiEditor" 16 | 17 | #define SETTINGS_CONTAINER TEXT("Project"), TEXT("Plugins"), TEXT("ImGui") 18 | 19 | 20 | namespace 21 | { 22 | ISettingsModule* GetSettingsModule() 23 | { 24 | return FModuleManager::GetModulePtr("Settings"); 25 | } 26 | 27 | FPropertyEditorModule* GetPropertyEditorModule() 28 | { 29 | return FModuleManager::GetModulePtr("PropertyEditor"); 30 | } 31 | } 32 | 33 | FImGuiEditor::FImGuiEditor() 34 | { 35 | Register(); 36 | 37 | // As a side effect of being part of the ImGui module, we need to support deferred registration (only executed if 38 | // module is loaded manually at the very early stage). 39 | if (!IsRegistrationCompleted()) 40 | { 41 | CreateRegistrator(); 42 | } 43 | } 44 | 45 | FImGuiEditor::~FImGuiEditor() 46 | { 47 | Unregister(); 48 | } 49 | 50 | void FImGuiEditor::Register() 51 | { 52 | // Only register after UImGuiSettings class is initialized (necessary to check in early loading stages). 53 | if (!bSettingsRegistered && UImGuiSettings::Get()) 54 | { 55 | if (ISettingsModule* SettingsModule = GetSettingsModule()) 56 | { 57 | bSettingsRegistered = true; 58 | 59 | SettingsModule->RegisterSettings(SETTINGS_CONTAINER, 60 | LOCTEXT("ImGuiSettingsName", "ImGui"), 61 | LOCTEXT("ImGuiSettingsDescription", "Configure the Unreal ImGui plugin."), 62 | UImGuiSettings::Get()); 63 | } 64 | } 65 | 66 | if (!bCustomPropertyTypeLayoutsRegistered) 67 | { 68 | if (FPropertyEditorModule* PropertyModule = GetPropertyEditorModule()) 69 | { 70 | bCustomPropertyTypeLayoutsRegistered = true; 71 | 72 | PropertyModule->RegisterCustomPropertyTypeLayout("ImGuiCanvasSizeInfo", 73 | FOnGetPropertyTypeCustomizationInstance::CreateStatic(&FImGuiCanvasSizeInfoCustomization::MakeInstance)); 74 | PropertyModule->RegisterCustomPropertyTypeLayout("ImGuiKeyInfo", 75 | FOnGetPropertyTypeCustomizationInstance::CreateStatic(&FImGuiKeyInfoCustomization::MakeInstance)); 76 | } 77 | } 78 | } 79 | 80 | void FImGuiEditor::Unregister() 81 | { 82 | if (bSettingsRegistered) 83 | { 84 | bSettingsRegistered = false; 85 | 86 | if (ISettingsModule* SettingsModule = GetSettingsModule()) 87 | { 88 | SettingsModule->UnregisterSettings(SETTINGS_CONTAINER); 89 | } 90 | } 91 | 92 | if (bCustomPropertyTypeLayoutsRegistered) 93 | { 94 | bCustomPropertyTypeLayoutsRegistered = false; 95 | 96 | if (FPropertyEditorModule* PropertyModule = GetPropertyEditorModule()) 97 | { 98 | PropertyModule->UnregisterCustomPropertyTypeLayout("ImGuiCanvasSizeInfo"); 99 | PropertyModule->UnregisterCustomPropertyTypeLayout("ImGuiKeyInfo"); 100 | } 101 | } 102 | } 103 | 104 | void FImGuiEditor::CreateRegistrator() 105 | { 106 | if (!RegistratorHandle.IsValid()) 107 | { 108 | RegistratorHandle = FModuleManager::Get().OnModulesChanged().AddLambda([this](FName Name, EModuleChangeReason Reason) 109 | { 110 | if (Reason == EModuleChangeReason::ModuleLoaded) 111 | { 112 | Register(); 113 | } 114 | 115 | if (IsRegistrationCompleted()) 116 | { 117 | ReleaseRegistrator(); 118 | } 119 | }); 120 | } 121 | } 122 | 123 | void FImGuiEditor::ReleaseRegistrator() 124 | { 125 | if (RegistratorHandle.IsValid()) 126 | { 127 | FModuleManager::Get().OnModulesChanged().Remove(RegistratorHandle); 128 | RegistratorHandle.Reset(); 129 | } 130 | } 131 | 132 | 133 | #undef SETTINGS_CONTAINER 134 | #undef LOCTEXT_NAMESPACE 135 | 136 | #endif // WITH_EDITOR 137 | -------------------------------------------------------------------------------- /Source/ImGui/Private/ImGuiModuleCommands.cpp: -------------------------------------------------------------------------------- 1 | // Distributed under the MIT License (MIT) (see accompanying LICENSE file) 2 | 3 | #include "ImGuiModuleCommands.h" 4 | 5 | #include "ImGuiModuleProperties.h" 6 | #include "Utilities/DebugExecBindings.h" 7 | 8 | 9 | const TCHAR* const FImGuiModuleCommands::ToggleInput = TEXT("ImGui.ToggleInput"); 10 | const TCHAR* const FImGuiModuleCommands::ToggleKeyboardNavigation = TEXT("ImGui.ToggleKeyboardNavigation"); 11 | const TCHAR* const FImGuiModuleCommands::ToggleGamepadNavigation = TEXT("ImGui.ToggleGamepadNavigation"); 12 | const TCHAR* const FImGuiModuleCommands::ToggleKeyboardInputSharing = TEXT("ImGui.ToggleKeyboardInputSharing"); 13 | const TCHAR* const FImGuiModuleCommands::ToggleGamepadInputSharing = TEXT("ImGui.ToggleGamepadInputSharing"); 14 | const TCHAR* const FImGuiModuleCommands::ToggleMouseInputSharing = TEXT("ImGui.ToggleMouseInputSharing"); 15 | const TCHAR* const FImGuiModuleCommands::SetMouseInputSharing = TEXT("ImGui.SetMouseInputSharing"); 16 | const TCHAR* const FImGuiModuleCommands::ToggleDemo = TEXT("ImGui.ToggleDemo"); 17 | 18 | FImGuiModuleCommands::FImGuiModuleCommands(FImGuiModuleProperties& InProperties) 19 | : Properties(InProperties) 20 | , ToggleInputCommand(ToggleInput, 21 | TEXT("Toggle ImGui input mode."), 22 | FConsoleCommandDelegate::CreateRaw(this, &FImGuiModuleCommands::ToggleInputImpl)) 23 | , ToggleKeyboardNavigationCommand(ToggleKeyboardNavigation, 24 | TEXT("Toggle ImGui keyboard navigation."), 25 | FConsoleCommandDelegate::CreateRaw(this, &FImGuiModuleCommands::ToggleKeyboardNavigationImpl)) 26 | , ToggleGamepadNavigationCommand(ToggleGamepadNavigation, 27 | TEXT("Toggle ImGui gamepad navigation."), 28 | FConsoleCommandDelegate::CreateRaw(this, &FImGuiModuleCommands::ToggleGamepadNavigationImpl)) 29 | , ToggleKeyboardInputSharingCommand(ToggleKeyboardInputSharing, 30 | TEXT("Toggle ImGui keyboard input sharing."), 31 | FConsoleCommandDelegate::CreateRaw(this, &FImGuiModuleCommands::ToggleKeyboardInputSharingImpl)) 32 | , ToggleGamepadInputSharingCommand(ToggleGamepadInputSharing, 33 | TEXT("Toggle ImGui gamepad input sharing."), 34 | FConsoleCommandDelegate::CreateRaw(this, &FImGuiModuleCommands::ToggleGamepadInputSharingImpl)) 35 | , ToggleMouseInputSharingCommand(ToggleMouseInputSharing, 36 | TEXT("Toggle ImGui mouse input sharing."), 37 | FConsoleCommandDelegate::CreateRaw(this, &FImGuiModuleCommands::ToggleMouseInputSharingImpl)) 38 | , SetMouseInputSharingCommand(SetMouseInputSharing, 39 | TEXT("Toggle ImGui mouse input sharing."), 40 | FConsoleCommandWithArgsDelegate::CreateRaw(this, &FImGuiModuleCommands::SetMouseInputSharingImpl)) 41 | , ToggleDemoCommand(ToggleDemo, 42 | TEXT("Toggle ImGui demo."), 43 | FConsoleCommandDelegate::CreateRaw(this, &FImGuiModuleCommands::ToggleDemoImpl)) 44 | { 45 | } 46 | 47 | void FImGuiModuleCommands::SetKeyBinding(const TCHAR* CommandName, const FImGuiKeyInfo& KeyInfo) 48 | { 49 | DebugExecBindings::UpdatePlayerInputs(KeyInfo, CommandName); 50 | } 51 | 52 | void FImGuiModuleCommands::ToggleInputImpl() 53 | { 54 | Properties.ToggleInput(); 55 | } 56 | 57 | void FImGuiModuleCommands::ToggleKeyboardNavigationImpl() 58 | { 59 | Properties.ToggleKeyboardNavigation(); 60 | } 61 | 62 | void FImGuiModuleCommands::ToggleGamepadNavigationImpl() 63 | { 64 | Properties.ToggleGamepadNavigation(); 65 | } 66 | 67 | void FImGuiModuleCommands::ToggleKeyboardInputSharingImpl() 68 | { 69 | Properties.ToggleKeyboardInputSharing(); 70 | } 71 | 72 | void FImGuiModuleCommands::ToggleGamepadInputSharingImpl() 73 | { 74 | Properties.ToggleGamepadInputSharing(); 75 | } 76 | 77 | void FImGuiModuleCommands::ToggleMouseInputSharingImpl() 78 | { 79 | Properties.ToggleMouseInputSharing(); 80 | } 81 | 82 | void FImGuiModuleCommands::SetMouseInputSharingImpl(const TArray& Args) 83 | { 84 | bool bIsEnabled = false; 85 | if (Args.Num() > 0) 86 | { 87 | LexFromString(bIsEnabled, *Args[0]); 88 | } 89 | Properties.SetMouseInputShared(bIsEnabled); 90 | } 91 | 92 | void FImGuiModuleCommands::ToggleDemoImpl() 93 | { 94 | Properties.ToggleDemo(); 95 | } 96 | -------------------------------------------------------------------------------- /Source/ImGui/Public/ImGuiDelegates.h: -------------------------------------------------------------------------------- 1 | // Distributed under the MIT License (MIT) (see accompanying LICENSE file) 2 | 3 | #pragma once 4 | 5 | #include 6 | 7 | 8 | class UWorld; 9 | 10 | /** 11 | * Delegates to ImGui debug events. World delegates are called once per frame during world updates and have invocation 12 | * lists cleared after their worlds become invalid. Multi-context delegates are called once for every updated world. 13 | * Early debug delegates are called during world tick start and debug delegates are called during world post actor tick 14 | * or in engine versions below 4.18 during world tick start. 15 | * 16 | * Order of events is defined in a way that multi-context delegates can be used to draw headers and/or footers: 17 | * multi-context early debug, world early debug, world debug, multi-context debug. 18 | */ 19 | class IMGUI_API FImGuiDelegates 20 | { 21 | public: 22 | 23 | /** 24 | * Get a delegate to ImGui world early debug event for current world (GWorld). 25 | * @returns Simple multicast delegate to debug events called once per frame to debug current world 26 | */ 27 | static FSimpleMulticastDelegate& OnWorldEarlyDebug(); 28 | 29 | /** 30 | * Get a delegate to ImGui world early debug event for given world. 31 | * @param World - World for which we need a delegate 32 | * @returns Simple multicast delegate to debug events called once per frame to debug given world 33 | */ 34 | static FSimpleMulticastDelegate& OnWorldEarlyDebug(UWorld* World); 35 | 36 | /** 37 | * Get a delegate to ImGui multi-context early debug event. 38 | * @returns Simple multicast delegate to debug events called once per frame for every world to debug 39 | */ 40 | static FSimpleMulticastDelegate& OnMultiContextEarlyDebug(); 41 | 42 | /** 43 | * Get a delegate to ImGui world debug event for current world (GWorld). 44 | * @returns Simple multicast delegate to debug events called once per frame to debug current world 45 | */ 46 | static FSimpleMulticastDelegate& OnWorldDebug(); 47 | 48 | /** 49 | * Get a delegate to ImGui world debug event for given world. 50 | * @param World - World for which we need a delegate 51 | * @returns Simple multicast delegate to debug events called once per frame to debug given world 52 | */ 53 | static FSimpleMulticastDelegate& OnWorldDebug(UWorld* World); 54 | 55 | /** 56 | * Get a delegate to ImGui multi-context debug event. 57 | * @returns Simple multicast delegate to debug events called once per frame for every world to debug 58 | */ 59 | static FSimpleMulticastDelegate& OnMultiContextDebug(); 60 | }; 61 | 62 | 63 | /** Enable to support legacy ImGui delegates API. */ 64 | #define IMGUI_WITH_OBSOLETE_DELEGATES 1 65 | 66 | #if IMGUI_WITH_OBSOLETE_DELEGATES 67 | 68 | /** Delegate that allows to subscribe for ImGui events. */ 69 | typedef FSimpleMulticastDelegate::FDelegate FImGuiDelegate; 70 | 71 | /** 72 | * Handle to ImGui delegate. Contains additional information locating delegates in different contexts. 73 | */ 74 | class FImGuiDelegateHandle 75 | { 76 | public: 77 | 78 | FImGuiDelegateHandle() = default; 79 | 80 | bool IsValid() const 81 | { 82 | return Handle.IsValid(); 83 | } 84 | 85 | void Reset() 86 | { 87 | Handle.Reset(); 88 | Index = 0; 89 | } 90 | 91 | private: 92 | 93 | FImGuiDelegateHandle(const FDelegateHandle& InHandle, int32 InCategory, int32 InIndex = 0) 94 | : Handle(InHandle) 95 | , Category(InCategory) 96 | , Index(InIndex) 97 | { 98 | } 99 | 100 | friend bool operator==(const FImGuiDelegateHandle& Lhs, const FImGuiDelegateHandle& Rhs) 101 | { 102 | return Lhs.Handle == Rhs.Handle && Lhs.Category == Rhs.Category && Lhs.Index == Rhs.Index; 103 | } 104 | 105 | friend bool operator!=(const FImGuiDelegateHandle& Lhs, const FImGuiDelegateHandle& Rhs) 106 | { 107 | return !(Lhs == Rhs); 108 | } 109 | 110 | FDelegateHandle Handle; 111 | int32 Category = 0; 112 | int32 Index = 0; 113 | 114 | friend class FImGuiModule; 115 | }; 116 | 117 | #endif // IMGUI_WITH_OBSOLETE_DELEGATES 118 | -------------------------------------------------------------------------------- /Source/ImGui/Private/ImGuiContextProxy.h: -------------------------------------------------------------------------------- 1 | // Distributed under the MIT License (MIT) (see accompanying LICENSE file) 2 | 3 | #pragma once 4 | 5 | #include "ImGuiDrawData.h" 6 | #include "ImGuiInputState.h" 7 | #include "Utilities/WorldContextIndex.h" 8 | 9 | #include 10 | 11 | #include 12 | 13 | #include 14 | 15 | 16 | // Represents a single ImGui context. All the context updates should be done through this proxy. During update it 17 | // broadcasts draw events to allow listeners draw their controls. After update it stores draw data. 18 | class FImGuiContextProxy 19 | { 20 | public: 21 | 22 | FImGuiContextProxy(const FString& Name, int32 InContextIndex, ImFontAtlas* InFontAtlas, float InDPIScale); 23 | ~FImGuiContextProxy(); 24 | 25 | FImGuiContextProxy(const FImGuiContextProxy&) = delete; 26 | FImGuiContextProxy& operator=(const FImGuiContextProxy&) = delete; 27 | 28 | FImGuiContextProxy(FImGuiContextProxy&&) = delete; 29 | FImGuiContextProxy& operator=(FImGuiContextProxy&&) = delete; 30 | 31 | // Get the name of this context. 32 | const FString& GetName() const { return Name; } 33 | 34 | // Get draw data from the last frame. 35 | const TArray& GetDrawData() const { return DrawLists; } 36 | 37 | // Get input state used by this context. 38 | FImGuiInputState& GetInputState() { return InputState; } 39 | const FImGuiInputState& GetInputState() const { return InputState; } 40 | 41 | // Is this context the current ImGui context. 42 | bool IsCurrentContext() const { return ImGui::GetCurrentContext() == Context; } 43 | 44 | // Set this context as current ImGui context. 45 | void SetAsCurrent() { ImGui::SetCurrentContext(Context); } 46 | 47 | // Get the desired context display size. 48 | const FVector2D& GetDisplaySize() const { return DisplaySize; } 49 | 50 | // Set the desired context display size. 51 | void SetDisplaySize(const FVector2D& Size) { DisplaySize = Size; } 52 | 53 | // Reset the desired context display size to default size. 54 | void ResetDisplaySize(); 55 | 56 | // Get the DPI scale set for this context. 57 | float GetDPIScale() const { return DPIScale; } 58 | 59 | // Set the DPI scale for this context. 60 | void SetDPIScale(float Scale); 61 | 62 | // Whether this context has an active item (read once per frame during context update). 63 | bool HasActiveItem() const { return bHasActiveItem; } 64 | 65 | // Whether ImGui will use the mouse inputs (read once per frame during context update). 66 | bool WantsMouseCapture() const { return bWantsMouseCapture; } 67 | 68 | // Cursor type desired by this context (updated once per frame during context update). 69 | EMouseCursor::Type GetMouseCursor() const { return MouseCursor; } 70 | 71 | // Internal draw event used to draw module's examples and debug widgets. Unlike the delegates container, it is not 72 | // passed when the module is reloaded, so all objects that are unloaded with the module should register here. 73 | FSimpleMulticastDelegate& OnDraw() { return DrawEvent; } 74 | 75 | // Call early debug events to allow listeners draw their debug widgets. 76 | void DrawEarlyDebug(); 77 | 78 | // Call debug events to allow listeners draw their debug widgets. 79 | void DrawDebug(); 80 | 81 | // Tick to advance context to the next frame. Only one call per frame will be processed. 82 | void Tick(float DeltaSeconds); 83 | 84 | private: 85 | 86 | void BeginFrame(float DeltaTime = 1.f / 60.f); 87 | void EndFrame(); 88 | 89 | void UpdateDrawData(ImDrawData* DrawData); 90 | 91 | void BroadcastWorldEarlyDebug(); 92 | void BroadcastMultiContextEarlyDebug(); 93 | 94 | void BroadcastWorldDebug(); 95 | void BroadcastMultiContextDebug(); 96 | 97 | ImGuiContext* Context; 98 | 99 | FVector2D DisplaySize = FVector2D::ZeroVector; 100 | float DPIScale = 1.f; 101 | 102 | EMouseCursor::Type MouseCursor = EMouseCursor::None; 103 | bool bHasActiveItem = false; 104 | bool bWantsMouseCapture = false; 105 | 106 | bool bIsFrameStarted = false; 107 | bool bIsDrawEarlyDebugCalled = false; 108 | bool bIsDrawDebugCalled = false; 109 | 110 | FImGuiInputState InputState; 111 | 112 | TArray DrawLists; 113 | 114 | FString Name; 115 | int32 ContextIndex = Utilities::INVALID_CONTEXT_INDEX; 116 | 117 | uint32 LastFrameNumber = 0; 118 | 119 | FSimpleMulticastDelegate DrawEvent; 120 | 121 | std::string IniFilename; 122 | }; 123 | -------------------------------------------------------------------------------- /Source/ImGui/Private/Utilities/Range.h: -------------------------------------------------------------------------------- 1 | // Distributed under the MIT License (MIT) (see accompanying LICENSE file) 2 | 3 | #pragma once 4 | 5 | #include 6 | 7 | 8 | namespace Utilities 9 | { 10 | //==================================================================================================== 11 | // Range 12 | //==================================================================================================== 13 | 14 | template 15 | class TRange 16 | { 17 | public: 18 | 19 | TRange() {} 20 | 21 | TRange(const T& RangeBegin, const T& RangeEnd) { SetRange(RangeBegin, RangeEnd); } 22 | 23 | const T& GetBegin() const { return Begin; } 24 | const T& GetEnd() const { return End; } 25 | 26 | bool IsEmpty() const { return Begin == End; } 27 | 28 | void SetEmpty() { Begin = End = T(); } 29 | 30 | void SetRange(const T& RangeBegin, const T& RangeEnd) 31 | { 32 | checkf(RangeBegin <= RangeEnd, TEXT("Invalid arguments: RangeBegin > RangeEnd.")); 33 | Begin = RangeBegin; 34 | End = RangeEnd; 35 | } 36 | 37 | void AddPosition(const T& Position) 38 | { 39 | AddRangeUnchecked(Position, Position + 1); 40 | } 41 | 42 | void AddRange(const T& RangeBegin, const T& RangeEnd) 43 | { 44 | checkf(RangeBegin <= RangeEnd, TEXT("Invalid arguments: RangeBegin > RangeEnd.")); 45 | AddRangeUnchecked(RangeBegin, RangeEnd); 46 | } 47 | 48 | private: 49 | 50 | void AddRangeUnchecked(const T& RangeBegin, const T& RangeEnd) 51 | { 52 | if (IsEmpty()) 53 | { 54 | Begin = RangeBegin; 55 | End = RangeEnd; 56 | } 57 | else 58 | { 59 | if (Begin > RangeBegin) 60 | { 61 | Begin = RangeBegin; 62 | } 63 | 64 | if (End < RangeEnd) 65 | { 66 | End = RangeEnd; 67 | } 68 | } 69 | } 70 | 71 | T Begin = T(); 72 | T End = T(); 73 | }; 74 | 75 | 76 | // Enable range-based loops 77 | 78 | template 79 | const T& begin(const TRange& Range) 80 | { 81 | return Range.GetBegin(); 82 | } 83 | 84 | template 85 | const T& end(const TRange& Range) 86 | { 87 | return Range.GetEnd(); 88 | } 89 | 90 | 91 | //==================================================================================================== 92 | // Bounded Range 93 | //==================================================================================================== 94 | 95 | template 96 | class TBoundedRange 97 | { 98 | public: 99 | 100 | constexpr const T& GetLowerBound() const { return BeginBound; } 101 | constexpr const T& GetUpperBound() const { return EndBound; } 102 | 103 | const T& GetBegin() const { return Begin; } 104 | const T& GetEnd() const { return End; } 105 | 106 | bool IsEmpty() const { return Begin == End; } 107 | 108 | void SetEmpty() { Begin = End = BeginBound; } 109 | 110 | void SetFull() 111 | { 112 | Begin = BeginBound; 113 | End = EndBound; 114 | } 115 | 116 | void AddPosition(const T& Position) 117 | { 118 | checkf(Position >= BeginBound && Position < EndBound, TEXT("Position out of range.")); 119 | 120 | AddRangeUnchecked(Position, Position + 1); 121 | } 122 | 123 | void AddRange(const T& RangeBegin, const T& RangeEnd) 124 | { 125 | checkf(RangeBegin <= RangeEnd, TEXT("Invalid arguments: RangeBegin > MaxPosition.")); 126 | checkf(RangeBegin >= BeginBound, TEXT("RangeBegin out of range.")); 127 | checkf(RangeBegin <= EndBound, TEXT("RangeEnd out of range.")); 128 | 129 | AddRangeUnchecked(RangeBegin, RangeEnd); 130 | } 131 | 132 | private: 133 | 134 | void AddRangeUnchecked(const T& RangeBegin, const T& RangeEnd) 135 | { 136 | if (IsEmpty()) 137 | { 138 | Begin = RangeBegin; 139 | End = RangeEnd; 140 | } 141 | else 142 | { 143 | if (Begin > RangeBegin) 144 | { 145 | Begin = RangeBegin; 146 | } 147 | 148 | if (End < RangeEnd) 149 | { 150 | End = RangeEnd; 151 | } 152 | } 153 | } 154 | 155 | T Begin = EndBound; 156 | T End = BeginBound; 157 | }; 158 | 159 | 160 | // Enable range-based loops 161 | 162 | template 163 | const T& begin(const TBoundedRange& Range) 164 | { 165 | return Range.GetBegin(); 166 | } 167 | 168 | template 169 | const T& end(const TBoundedRange& Range) 170 | { 171 | return Range.GetEnd(); 172 | } 173 | } 174 | -------------------------------------------------------------------------------- /Source/ImGui/Private/ImGuiContextManager.h: -------------------------------------------------------------------------------- 1 | // Distributed under the MIT License (MIT) (see accompanying LICENSE file) 2 | 3 | #pragma once 4 | 5 | #include "ImGuiContextProxy.h" 6 | #include "VersionCompatibility.h" 7 | 8 | 9 | class FImGuiModuleSettings; 10 | struct FImGuiDPIScaleInfo; 11 | 12 | // TODO: It might be useful to broadcast FContextProxyCreatedDelegate to users, to support similar cases to our ImGui 13 | // demo, but we would need to remove from that interface internal classes. 14 | 15 | // Delegate called when new context proxy is created. 16 | // @param ContextIndex - Index for that world 17 | // @param ContextProxy - Created context proxy 18 | DECLARE_MULTICAST_DELEGATE_TwoParams(FContextProxyCreatedDelegate, int32, FImGuiContextProxy&); 19 | 20 | // Manages ImGui context proxies. 21 | class FImGuiContextManager 22 | { 23 | public: 24 | 25 | FImGuiContextManager(FImGuiModuleSettings& InSettings); 26 | 27 | FImGuiContextManager(const FImGuiContextManager&) = delete; 28 | FImGuiContextManager& operator=(const FImGuiContextManager&) = delete; 29 | 30 | FImGuiContextManager(FImGuiContextManager&&) = delete; 31 | FImGuiContextManager& operator=(FImGuiContextManager&&) = delete; 32 | 33 | ~FImGuiContextManager(); 34 | 35 | ImFontAtlas& GetFontAtlas() { return FontAtlas; } 36 | const ImFontAtlas& GetFontAtlas() const { return FontAtlas; } 37 | 38 | #if WITH_EDITOR 39 | // Get or create editor ImGui context proxy. 40 | FORCEINLINE FImGuiContextProxy& GetEditorContextProxy() { return *GetEditorContextData().ContextProxy; } 41 | #endif 42 | 43 | #if !WITH_EDITOR 44 | // Get or create standalone game ImGui context proxy. 45 | FORCEINLINE FImGuiContextProxy& GetWorldContextProxy() { return *GetStandaloneWorldContextData().ContextProxy; } 46 | #endif 47 | 48 | // Get or create ImGui context proxy for given world. 49 | FORCEINLINE FImGuiContextProxy& GetWorldContextProxy(const UWorld& World) { return *GetWorldContextData(World).ContextProxy; } 50 | 51 | // Get or create ImGui context proxy for given world. Additionally get context index for that proxy. 52 | FORCEINLINE FImGuiContextProxy& GetWorldContextProxy(const UWorld& World, int32& OutContextIndex) { return *GetWorldContextData(World, &OutContextIndex).ContextProxy; } 53 | 54 | // Get context proxy by index, or null if context with that index doesn't exist. 55 | FORCEINLINE FImGuiContextProxy* GetContextProxy(int32 ContextIndex) 56 | { 57 | FContextData* Data = Contexts.Find(ContextIndex); 58 | return Data ? Data->ContextProxy.Get() : nullptr; 59 | } 60 | 61 | // Delegate called when a new context proxy is created. 62 | FContextProxyCreatedDelegate OnContextProxyCreated; 63 | 64 | // Delegate called after font atlas is built. 65 | FSimpleMulticastDelegate OnFontAtlasBuilt; 66 | 67 | void Tick(float DeltaSeconds); 68 | 69 | void RebuildFontAtlas(); 70 | 71 | private: 72 | 73 | struct FContextData 74 | { 75 | FContextData(const FString& ContextName, int32 ContextIndex, ImFontAtlas& FontAtlas, float DPIScale, int32 InPIEInstance = -1) 76 | : PIEInstance(InPIEInstance) 77 | , ContextProxy(new FImGuiContextProxy(ContextName, ContextIndex, &FontAtlas, DPIScale)) 78 | { 79 | } 80 | 81 | FORCEINLINE bool CanTick() const { return PIEInstance < 0 || GEngine->GetWorldContextFromPIEInstance(PIEInstance); } 82 | 83 | int32 PIEInstance = -1; 84 | TUniquePtr ContextProxy; 85 | }; 86 | 87 | #if ENGINE_COMPATIBILITY_LEGACY_WORLD_ACTOR_TICK 88 | void OnWorldTickStart(ELevelTick TickType, float DeltaSeconds); 89 | #endif 90 | void OnWorldTickStart(UWorld* World, ELevelTick TickType, float DeltaSeconds); 91 | 92 | #if ENGINE_COMPATIBILITY_WITH_WORLD_POST_ACTOR_TICK 93 | void OnWorldPostActorTick(UWorld* World, ELevelTick TickType, float DeltaSeconds); 94 | #endif 95 | 96 | #if WITH_EDITOR 97 | FContextData& GetEditorContextData(); 98 | #endif 99 | 100 | #if !WITH_EDITOR 101 | FContextData& GetStandaloneWorldContextData(); 102 | #endif 103 | 104 | FContextData& GetWorldContextData(const UWorld& World, int32* OutContextIndex = nullptr); 105 | 106 | void SetDPIScale(const FImGuiDPIScaleInfo& ScaleInfo); 107 | void BuildFontAtlas(const TMap>& CustomFontConfigs = {}); 108 | 109 | TMap Contexts; 110 | 111 | ImFontAtlas FontAtlas; 112 | TArray> FontResourcesToRelease; 113 | 114 | FImGuiModuleSettings& Settings; 115 | 116 | float DPIScale = -1.f; 117 | int32 FontResourcesReleaseCountdown = 0; 118 | }; 119 | -------------------------------------------------------------------------------- /Source/ImGui/Private/Widgets/SImGuiCanvasControl.h: -------------------------------------------------------------------------------- 1 | // Distributed under the MIT License (MIT) (see accompanying LICENSE file) 2 | 3 | #pragma once 4 | 5 | #include "ImGuiInputState.h" 6 | #include "ImGuiModuleSettings.h" 7 | 8 | #include 9 | #include 10 | #include 11 | 12 | 13 | // Widget that controls transform of ImGui canvas/space. 14 | // When active, additionally it shows boundaries of ImGui canvas and default visible area. 15 | // TODO: Bind to ImGui context or properties to dynamically read canvas size. 16 | // TODO: Bind to properties to allow configure colors. 17 | class SImGuiCanvasControl : public SLeafWidget 18 | { 19 | typedef SLeafWidget Super; 20 | 21 | public: 22 | 23 | DECLARE_DELEGATE_OneParam(FOnTransformChanged, const FSlateRenderTransform&); 24 | 25 | SLATE_BEGIN_ARGS(SImGuiCanvasControl) 26 | {} 27 | SLATE_EVENT(FOnTransformChanged, OnTransformChanged) 28 | SLATE_END_ARGS() 29 | 30 | void Construct(const FArguments& InArgs); 31 | 32 | bool IsActive() const { return bActive; } 33 | void SetActive(bool bInActive); 34 | 35 | const FSlateRenderTransform& GetTransform() const { return Transform; } 36 | 37 | //---------------------------------------------------------------------------------------------------- 38 | // SWidget overrides 39 | //---------------------------------------------------------------------------------------------------- 40 | 41 | virtual void Tick(const FGeometry& AllottedGeometry, const double InCurrentTime, const float InDeltaTime) override; 42 | 43 | virtual FReply OnMouseButtonDown(const FGeometry& MyGeometry, const FPointerEvent& MouseEvent) override; 44 | 45 | virtual FReply OnMouseButtonUp(const FGeometry& MyGeometry, const FPointerEvent& MouseEvent) override; 46 | 47 | virtual FReply OnMouseWheel(const FGeometry& MyGeometry, const FPointerEvent& MouseEvent) override; 48 | 49 | virtual FReply OnDragDetected(const FGeometry& MyGeometry, const FPointerEvent& MouseEvent) override; 50 | 51 | virtual FReply OnDragOver(const FGeometry& MyGeometry, const FDragDropEvent& DragDropEvent) override; 52 | 53 | virtual FReply OnDrop(const FGeometry& MyGeometry, const FDragDropEvent& DragDropEvent) override; 54 | 55 | virtual FVector2D ComputeDesiredSize(float InScale) const override; 56 | 57 | virtual int32 OnPaint(const FPaintArgs& Args, const FGeometry& AllottedGeometry, const FSlateRect& MyCullingRect, FSlateWindowElementList& OutDrawElements, int32 LayerId, const FWidgetStyle& InWidgetStyle, bool bParentEnabled) const override; 58 | 59 | private: 60 | 61 | enum class EDragRequest : uint8 62 | { 63 | None, 64 | Content, 65 | Canvas 66 | }; 67 | 68 | void UpdateVisibility(); 69 | 70 | void Zoom(const FGeometry& MyGeometry, const float Delta, const FVector2D& MousePosition); 71 | 72 | void UpdateRenderTransform(); 73 | 74 | float GetMinScale(const FGeometry& MyGeometry); 75 | 76 | mutable FSlateBorderBrush CanvasBorderBrush = FSlateBorderBrush("SImGuiCanvasControl-CanvasBorder", FMargin(0.f, 0.f, 1.f, 1.f), FLinearColor::White); 77 | mutable FSlateBorderBrush FrameBorderBrush = FSlateBorderBrush("SImGuiCanvasControl-FrameBorder", FMargin(0.f, 0.f, 1.f, 1.f), FLinearColor::White); 78 | 79 | FOnTransformChanged OnTransformChanged; 80 | 81 | // Transform from ImGui space. 82 | FSlateRenderTransform Transform; 83 | 84 | // Offset of the ImGui content in ImGui space. 85 | FVector2D ContentOffset = FVector2D::ZeroVector; 86 | 87 | // Offset of the ImGui canvas in widget local space. 88 | FVector2D CanvasOffset = FVector2D::ZeroVector; 89 | 90 | // Scale of the ImGui canvas in widget local space. 91 | float CanvasScale = 1.f; 92 | 93 | // Opacity scaling visibility of elements during blending. 94 | float Opacity = 1.f; 95 | 96 | // Whether this widget is active. While active, widget allows to modify transform of ImGui canvas, shows its 97 | // boundaries and default visible area. 98 | bool bActive = false; 99 | 100 | // Whether we are blending out after widget was deactivated. While blending out, widget is visible but it doesn't 101 | // process inputs anymore. 102 | bool bBlendingOut = false; 103 | 104 | // Request is set on mouse button press before drag operation is started. It remains valid until activating button 105 | // is released or until drag operation is finished or until it is replaced by alternative request. 106 | // Highlights are bound to requests, what means that they can also be activated before drag operation is started. 107 | EDragRequest DragRequest = EDragRequest::None; 108 | }; 109 | -------------------------------------------------------------------------------- /Source/ImGui/Private/ImGuiInteroperability.h: -------------------------------------------------------------------------------- 1 | // Distributed under the MIT License (MIT) (see accompanying LICENSE file) 2 | 3 | #pragma once 4 | 5 | #include "TextureManager.h" 6 | 7 | #include 8 | #include 9 | 10 | #include 11 | 12 | 13 | class FImGuiInputState; 14 | 15 | // Utilities to help standardise operations between Unreal and ImGui. 16 | namespace ImGuiInterops 17 | { 18 | //==================================================================================================== 19 | // ImGui Types 20 | //==================================================================================================== 21 | 22 | namespace ImGuiTypes 23 | { 24 | using FMouseButtonsArray = decltype(ImGuiIO::MouseDown); 25 | using FKeysArray = decltype(ImGuiIO::KeysDown); 26 | using FNavInputArray = decltype(ImGuiIO::NavInputs); 27 | 28 | using FKeyMap = decltype(ImGuiIO::KeyMap); 29 | } 30 | 31 | 32 | //==================================================================================================== 33 | // Input Mapping 34 | //==================================================================================================== 35 | 36 | // Set in ImGui IO mapping to recognize indices generated from Unreal input events. 37 | void SetUnrealKeyMap(ImGuiIO& IO); 38 | 39 | // Map FKey to index in keys buffer. 40 | uint32 GetKeyIndex(const FKey& Key); 41 | 42 | // Map key event to index in keys buffer. 43 | uint32 GetKeyIndex(const FKeyEvent& KeyEvent); 44 | 45 | // Map mouse FKey to index in mouse buttons buffer. 46 | uint32 GetMouseIndex(const FKey& MouseButton); 47 | 48 | // Map pointer event to index in mouse buttons buffer. 49 | FORCEINLINE uint32 GetMouseIndex(const FPointerEvent& MouseEvent) 50 | { 51 | return GetMouseIndex(MouseEvent.GetEffectingButton()); 52 | } 53 | 54 | // Convert from ImGuiMouseCursor type to EMouseCursor. 55 | EMouseCursor::Type ToSlateMouseCursor(ImGuiMouseCursor MouseCursor); 56 | 57 | // Set in the target array navigation input corresponding to gamepad key. 58 | // @param NavInputs - Target array 59 | // @param Key - Gamepad key mapped to navigation input (non-mapped keys will be ignored) 60 | // @param bIsDown - True, if key is down 61 | void SetGamepadNavigationKey(ImGuiTypes::FNavInputArray& NavInputs, const FKey& Key, bool bIsDown); 62 | 63 | // Set in the target array navigation input corresponding to gamepad axis. 64 | // @param NavInputs - Target array 65 | // @param Key - Gamepad axis key mapped to navigation input (non-axis or non-mapped inputs will be ignored) 66 | // @param Value - Axis value (-1..1 values from Unreal are mapped to separate ImGui axes with values in range 0..1) 67 | void SetGamepadNavigationAxis(ImGuiTypes::FNavInputArray& NavInputs, const FKey& Key, float Value); 68 | 69 | 70 | //==================================================================================================== 71 | // Input State Copying 72 | //==================================================================================================== 73 | 74 | // Copy input to ImGui IO. 75 | // @param IO - Target ImGui IO 76 | // @param InputState - Input state to copy 77 | void CopyInput(ImGuiIO& IO, const FImGuiInputState& InputState); 78 | 79 | 80 | //==================================================================================================== 81 | // Conversions 82 | //==================================================================================================== 83 | 84 | // Convert from ImGui packed color to FColor. 85 | FORCEINLINE FColor UnpackImU32Color(ImU32 Color) 86 | { 87 | // We use IM_COL32_R/G/B/A_SHIFT macros to support different ImGui configurations. 88 | return FColor{ (uint8)((Color >> IM_COL32_R_SHIFT) & 0xFF), (uint8)((Color >> IM_COL32_G_SHIFT) & 0xFF), 89 | (uint8)((Color >> IM_COL32_B_SHIFT) & 0xFF), (uint8)((Color >> IM_COL32_A_SHIFT) & 0xFF) }; 90 | } 91 | 92 | // Convert from ImVec4 rectangle to FSlateRect. 93 | FORCEINLINE FSlateRect ToSlateRect(const ImVec4& ImGuiRect) 94 | { 95 | return FSlateRect{ ImGuiRect.x, ImGuiRect.y, ImGuiRect.z, ImGuiRect.w }; 96 | } 97 | 98 | // Convert from ImVec2 rectangle to FVector2D. 99 | FORCEINLINE FVector2D ToVector2D(const ImVec2& ImGuiVector) 100 | { 101 | return FVector2D{ ImGuiVector.x, ImGuiVector.y }; 102 | } 103 | 104 | // Convert from ImGui Texture Id to Texture Index that we use for texture resources. 105 | FORCEINLINE TextureIndex ToTextureIndex(ImTextureID Index) 106 | { 107 | return static_cast(reinterpret_cast(Index)); 108 | } 109 | 110 | // Convert from Texture Index to ImGui Texture Id that we pass to ImGui. 111 | FORCEINLINE ImTextureID ToImTextureID(TextureIndex Index) 112 | { 113 | return reinterpret_cast(static_cast(Index)); 114 | } 115 | } 116 | -------------------------------------------------------------------------------- /Source/ImGui/Private/Editor/ImGuiCanvasSizeInfoCustomization.cpp: -------------------------------------------------------------------------------- 1 | // Distributed under the MIT License (MIT) (see accompanying LICENSE file) 2 | 3 | #include "ImGuiCanvasSizeInfoCustomization.h" 4 | 5 | #if WITH_EDITOR 6 | 7 | #include "ImGuiModuleSettings.h" 8 | 9 | #include 10 | 11 | 12 | #define LOCTEXT_NAMESPACE "ImGuiEditor" 13 | 14 | 15 | namespace 16 | { 17 | EImGuiCanvasSizeType GetCanvasSizeTypeEnumValue(const TSharedPtr& TypeHandle) 18 | { 19 | uint8 ValueAsByte = 0; 20 | if (TypeHandle.IsValid()) 21 | { 22 | TypeHandle->GetValue(ValueAsByte); 23 | } 24 | return static_cast(ValueAsByte); 25 | } 26 | 27 | bool IsAny(const TSharedPtr& TypeHandle, EImGuiCanvasSizeType Value) 28 | { 29 | return GetCanvasSizeTypeEnumValue(TypeHandle) == Value; 30 | } 31 | 32 | template 33 | bool IsAny(const TSharedPtr& TypeHandle, EImGuiCanvasSizeType First, TRest... Rest) 34 | { 35 | return IsAny(TypeHandle, First) || IsAny(TypeHandle, Rest...); 36 | } 37 | 38 | float ShowToHeight(bool bShow) 39 | { 40 | return bShow ? 0.f /* Infinity */ : SMALL_NUMBER; 41 | } 42 | 43 | EVisibility ShowToVisibility(bool bShow) 44 | { 45 | return bShow ? EVisibility::SelfHitTestInvisible : EVisibility::Hidden; 46 | } 47 | } 48 | 49 | //---------------------------------------------------------------------------------------------------- 50 | // FImGuiKeyInfoCustomization implementation 51 | //---------------------------------------------------------------------------------------------------- 52 | 53 | TSharedRef FImGuiCanvasSizeInfoCustomization::MakeInstance() 54 | { 55 | return MakeShareable(new FImGuiCanvasSizeInfoCustomization); 56 | } 57 | 58 | void FImGuiCanvasSizeInfoCustomization::CustomizeHeader(TSharedRef InStructPropertyHandle, FDetailWidgetRow& HeaderRow, IPropertyTypeCustomizationUtils& StructCustomizationUtils) 59 | { 60 | TSharedPtr TypeHandle = InStructPropertyHandle->GetChildHandle(GET_MEMBER_NAME_CHECKED(FImGuiCanvasSizeInfo, SizeType)); 61 | TSharedPtr WidthHandle = InStructPropertyHandle->GetChildHandle(GET_MEMBER_NAME_CHECKED(FImGuiCanvasSizeInfo, Width)); 62 | TSharedPtr HeightHandle = InStructPropertyHandle->GetChildHandle(GET_MEMBER_NAME_CHECKED(FImGuiCanvasSizeInfo, Height)); 63 | TSharedPtr ExtendToViewportHandle = InStructPropertyHandle->GetChildHandle(GET_MEMBER_NAME_CHECKED(FImGuiCanvasSizeInfo, bExtendToViewport)); 64 | 65 | #define ADD_DIMENSION_SLOT(Handle, LPadding) \ 66 | + SHorizontalBox::Slot()\ 67 | .Padding(LPadding, 0.f, 0.f, 0.f)\ 68 | .HAlign(HAlign_Fill)\ 69 | .MaxWidth(80.f)\ 70 | [\ 71 | SNew(SVerticalBox)\ 72 | + SVerticalBox::Slot()\ 73 | .AutoHeight()\ 74 | [\ 75 | Handle->CreatePropertyNameWidget()\ 76 | ]\ 77 | + SVerticalBox::Slot()\ 78 | .HAlign(HAlign_Fill)\ 79 | .AutoHeight()\ 80 | [\ 81 | Handle->CreatePropertyValueWidget()\ 82 | ]\ 83 | ] 84 | 85 | auto SizeRowHeight = TAttribute::Create([TypeHandle]() 86 | { 87 | return ShowToHeight(IsAny(TypeHandle, EImGuiCanvasSizeType::Custom)); 88 | }); 89 | 90 | auto SizeRowVisibility = TAttribute::Create([TypeHandle]() 91 | { 92 | return ShowToVisibility(IsAny(TypeHandle, EImGuiCanvasSizeType::Custom)); 93 | }); 94 | 95 | auto ExtendRowHeight = TAttribute::Create([TypeHandle]() 96 | { 97 | return ShowToHeight(IsAny(TypeHandle, EImGuiCanvasSizeType::Custom, EImGuiCanvasSizeType::Desktop)); 98 | }); 99 | 100 | auto ExtendRowVisibility = TAttribute::Create([TypeHandle]() 101 | { 102 | return ShowToVisibility(IsAny(TypeHandle, EImGuiCanvasSizeType::Custom, EImGuiCanvasSizeType::Desktop)); 103 | }); 104 | 105 | HeaderRow 106 | .NameContent() 107 | [ 108 | InStructPropertyHandle->CreatePropertyNameWidget() 109 | ] 110 | .ValueContent() 111 | .MinDesiredWidth(168.f) 112 | [ 113 | SNew(SVerticalBox) 114 | + SVerticalBox::Slot() 115 | .AutoHeight() 116 | [ 117 | TypeHandle->CreatePropertyValueWidget() 118 | ] 119 | + SVerticalBox::Slot() 120 | .AutoHeight() 121 | .MaxHeight(SizeRowHeight) 122 | [ 123 | SNew(SHorizontalBox) 124 | .Visibility(SizeRowVisibility) 125 | ADD_DIMENSION_SLOT(WidthHandle, 0.f) 126 | ADD_DIMENSION_SLOT(HeightHandle, 6.f) 127 | ] 128 | + SVerticalBox::Slot() 129 | .AutoHeight() 130 | .MaxHeight(ExtendRowHeight) 131 | [ 132 | SNew(SHorizontalBox) 133 | .Visibility(ExtendRowVisibility) 134 | + SHorizontalBox::Slot() 135 | .AutoWidth() 136 | [ 137 | ExtendToViewportHandle->CreatePropertyValueWidget() 138 | ] 139 | + SHorizontalBox::Slot() 140 | .Padding(4.f, 0.f, 0.f, 0.f) 141 | .AutoWidth() 142 | [ 143 | ExtendToViewportHandle->CreatePropertyNameWidget() 144 | ] 145 | ] 146 | ]; 147 | 148 | #undef ADD_DIMENSION_SLOT 149 | } 150 | 151 | void FImGuiCanvasSizeInfoCustomization::CustomizeChildren(TSharedRef InStructPropertyHandle, IDetailChildrenBuilder& StructBuilder, IPropertyTypeCustomizationUtils& StructCustomizationUtils) 152 | { 153 | } 154 | 155 | 156 | #undef LOCTEXT_NAMESPACE 157 | 158 | #endif // WITH_EDITOR 159 | -------------------------------------------------------------------------------- /Source/ImGui/Private/Widgets/SImGuiWidget.h: -------------------------------------------------------------------------------- 1 | // Distributed under the MIT License (MIT) (see accompanying LICENSE file) 2 | 3 | #pragma once 4 | 5 | #include "ImGuiModuleDebug.h" 6 | #include "ImGuiModuleSettings.h" 7 | 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | 14 | // Hide ImGui Widget debug in non-developer mode. 15 | #define IMGUI_WIDGET_DEBUG IMGUI_MODULE_DEVELOPER 16 | 17 | class FImGuiModuleManager; 18 | class SImGuiCanvasControl; 19 | class UImGuiInputHandler; 20 | 21 | class UGameViewportClient; 22 | class ULocalPlayer; 23 | 24 | // Slate widget for rendering ImGui output and storing Slate inputs. 25 | class SImGuiWidget : public SCompoundWidget 26 | { 27 | typedef SCompoundWidget Super; 28 | 29 | public: 30 | 31 | SLATE_BEGIN_ARGS(SImGuiWidget) 32 | {} 33 | SLATE_ARGUMENT(FImGuiModuleManager*, ModuleManager) 34 | SLATE_ARGUMENT(UGameViewportClient*, GameViewport) 35 | SLATE_ARGUMENT(int32, ContextIndex) 36 | SLATE_END_ARGS() 37 | 38 | void Construct(const FArguments& InArgs); 39 | 40 | ~SImGuiWidget(); 41 | 42 | // Get index of the context that this widget is targeting. 43 | int32 GetContextIndex() const { return ContextIndex; } 44 | 45 | //---------------------------------------------------------------------------------------------------- 46 | // SWidget overrides 47 | //---------------------------------------------------------------------------------------------------- 48 | 49 | virtual void Tick(const FGeometry& AllottedGeometry, const double InCurrentTime, const float InDeltaTime) override; 50 | 51 | virtual bool SupportsKeyboardFocus() const override { return bInputEnabled && !IsConsoleOpened(); } 52 | 53 | virtual FReply OnKeyChar(const FGeometry& MyGeometry, const FCharacterEvent& CharacterEvent) override; 54 | 55 | virtual FReply OnKeyDown(const FGeometry& MyGeometry, const FKeyEvent& KeyEvent) override; 56 | 57 | virtual FReply OnKeyUp(const FGeometry& MyGeometry, const FKeyEvent& KeyEvent) override; 58 | 59 | virtual FReply OnAnalogValueChanged(const FGeometry& MyGeometry, const FAnalogInputEvent& AnalogInputEvent) override; 60 | 61 | virtual FReply OnMouseButtonDown(const FGeometry& MyGeometry, const FPointerEvent& MouseEvent) override; 62 | 63 | virtual FReply OnMouseButtonDoubleClick(const FGeometry& MyGeometry, const FPointerEvent& MouseEvent) override; 64 | 65 | virtual FReply OnMouseButtonUp(const FGeometry& MyGeometry, const FPointerEvent& MouseEvent) override; 66 | 67 | virtual FReply OnMouseWheel(const FGeometry& MyGeometry, const FPointerEvent& MouseEvent) override; 68 | 69 | virtual FReply OnMouseMove(const FGeometry& MyGeometry, const FPointerEvent& MouseEvent) override; 70 | 71 | virtual FReply OnFocusReceived(const FGeometry& MyGeometry, const FFocusEvent& FocusEvent) override; 72 | 73 | virtual void OnFocusLost(const FFocusEvent& FocusEvent) override; 74 | 75 | virtual void OnMouseEnter(const FGeometry& MyGeometry, const FPointerEvent& MouseEvent) override; 76 | 77 | virtual void OnMouseLeave(const FPointerEvent& MouseEvent) override; 78 | 79 | virtual FReply OnTouchStarted(const FGeometry& MyGeometry, const FPointerEvent& TouchEvent) override; 80 | 81 | virtual FReply OnTouchMoved(const FGeometry& MyGeometry, const FPointerEvent& TouchEvent) override; 82 | 83 | virtual FReply OnTouchEnded(const FGeometry& MyGeometry, const FPointerEvent& TouchEvent) override; 84 | 85 | private: 86 | 87 | void CreateInputHandler(const FSoftClassPath& HandlerClassReference); 88 | void ReleaseInputHandler(); 89 | 90 | void RegisterImGuiSettingsDelegates(); 91 | void UnregisterImGuiSettingsDelegates(); 92 | 93 | void SetHideMouseCursor(bool bHide); 94 | 95 | bool IsConsoleOpened() const; 96 | 97 | // Update visibility based on input state. 98 | void UpdateVisibility(); 99 | 100 | // Update cursor based on input state. 101 | void UpdateMouseCursor(); 102 | 103 | ULocalPlayer* GetLocalPlayer() const; 104 | void TakeFocus(); 105 | void ReturnFocus(); 106 | 107 | // Update input state. 108 | void UpdateInputState(); 109 | void UpdateTransparentMouseInput(const FGeometry& AllottedGeometry); 110 | void HandleWindowFocusLost(); 111 | 112 | void SetDPIScale(const FImGuiDPIScaleInfo& ScaleInfo); 113 | 114 | void SetCanvasSizeInfo(const FImGuiCanvasSizeInfo& CanvasSizeInfo); 115 | void UpdateCanvasSize(); 116 | 117 | void UpdateCanvasControlMode(const FInputEvent& InputEvent); 118 | 119 | void OnPostImGuiUpdate(); 120 | 121 | FVector2D TransformScreenPointToImGui(const FGeometry& MyGeometry, const FVector2D& Point) const; 122 | 123 | virtual int32 OnPaint(const FPaintArgs& Args, const FGeometry& AllottedGeometry, const FSlateRect& MyClippingRect, FSlateWindowElementList& OutDrawElements, int32 LayerId, const FWidgetStyle& WidgetStyle, bool bParentEnabled) const override; 124 | 125 | virtual FVector2D ComputeDesiredSize(float) const override; 126 | 127 | void SetImGuiTransform(const FSlateRenderTransform& Transform) { ImGuiTransform = Transform; } 128 | 129 | #if IMGUI_WIDGET_DEBUG 130 | void OnDebugDraw(); 131 | #endif // IMGUI_WIDGET_DEBUG 132 | 133 | FImGuiModuleManager* ModuleManager = nullptr; 134 | TWeakObjectPtr GameViewport; 135 | TWeakObjectPtr InputHandler; 136 | 137 | FSlateRenderTransform ImGuiTransform; 138 | FSlateRenderTransform ImGuiRenderTransform; 139 | 140 | mutable TArray VertexBuffer; 141 | mutable TArray IndexBuffer; 142 | 143 | int32 ContextIndex = 0; 144 | 145 | FVector2D MinCanvasSize = FVector2D::ZeroVector; 146 | FVector2D CanvasSize = FVector2D::ZeroVector; 147 | 148 | float DPIScale = 1.f; 149 | 150 | bool bInputEnabled = false; 151 | bool bForegroundWindow = false; 152 | bool bHideMouseCursor = true; 153 | bool bTransparentMouseInput = false; 154 | bool bAdaptiveCanvasSize = false; 155 | bool bUpdateCanvasSize = false; 156 | bool bCanvasControlEnabled = false; 157 | 158 | TSharedPtr CanvasControlWidget; 159 | TWeakPtr PreviousUserFocusedWidget; 160 | }; 161 | -------------------------------------------------------------------------------- /Source/ImGui/Private/Editor/ImGuiKeyInfoCustomization.cpp: -------------------------------------------------------------------------------- 1 | // Distributed under the MIT License (MIT) (see accompanying LICENSE file) 2 | 3 | #include "ImGuiKeyInfoCustomization.h" 4 | 5 | #if WITH_EDITOR 6 | 7 | #include "ImGuiModuleSettings.h" 8 | 9 | #include 10 | #include 11 | #include 12 | #include 13 | 14 | 15 | #define LOCTEXT_NAMESPACE "ImGuiEditor" 16 | 17 | 18 | //---------------------------------------------------------------------------------------------------- 19 | // Helper widgets 20 | //---------------------------------------------------------------------------------------------------- 21 | 22 | namespace 23 | { 24 | class SPropertyKeySelector : public SCompoundWidget 25 | { 26 | public: 27 | SLATE_BEGIN_ARGS(SPropertyKeySelector) 28 | {} 29 | SLATE_ARGUMENT(TSharedPtr, KeyHandle) 30 | SLATE_ATTRIBUTE(FSlateFontInfo, Font) 31 | SLATE_END_ARGS() 32 | 33 | void Construct(const FArguments& InArgs) 34 | { 35 | KeyHandle = InArgs._KeyHandle; 36 | 37 | ChildSlot 38 | [ 39 | SNew(SKeySelector) 40 | .CurrentKey(this, &SPropertyKeySelector::GetCurrentKey) 41 | .OnKeyChanged(this, &SPropertyKeySelector::OnKeyChanged) 42 | .Font(InArgs._Font) 43 | ]; 44 | } 45 | 46 | TOptional GetCurrentKey() const 47 | { 48 | TArray RawPtrs; 49 | KeyHandle->AccessRawData(RawPtrs); 50 | 51 | if (RawPtrs.Num()) 52 | { 53 | FKey* KeyPtr = static_cast(RawPtrs[0]); 54 | 55 | if (KeyPtr) 56 | { 57 | for (int32 Index = 1; Index < RawPtrs.Num(); Index++) 58 | { 59 | if (*static_cast(RawPtrs[Index]) != *KeyPtr) 60 | { 61 | return TOptional(); 62 | } 63 | } 64 | 65 | return *KeyPtr; 66 | } 67 | } 68 | 69 | return FKey(); 70 | } 71 | 72 | void OnKeyChanged(TSharedPtr SelectedKey) 73 | { 74 | KeyHandle->SetValueFromFormattedString(SelectedKey->ToString()); 75 | } 76 | 77 | private: 78 | 79 | TSharedPtr KeyHandle; 80 | }; 81 | 82 | class SPropertyTriStateCheckBox : public SCompoundWidget 83 | { 84 | public: 85 | 86 | using FCheckBoxStateRaw = std::underlying_type::type; 87 | 88 | SLATE_BEGIN_ARGS(SPropertyTriStateCheckBox) 89 | {} 90 | SLATE_ARGUMENT(TSharedPtr, PropertyHandle) 91 | SLATE_END_ARGS() 92 | 93 | void Construct(const FArguments& InArgs) 94 | { 95 | PropertyHandle = InArgs._PropertyHandle; 96 | 97 | // We are abusing SCheckBox a bit but our GetPropertyValue with custom OnCheckBoxStateChanged implementation 98 | // gives a checkbox that allows to cycle between all three states. 99 | ChildSlot 100 | [ 101 | SNew(SCheckBox) 102 | .IsChecked(this, &SPropertyTriStateCheckBox::GetPropertyValue) 103 | .OnCheckStateChanged(this, &SPropertyTriStateCheckBox::OnCheckBoxStateChanged) 104 | ]; 105 | } 106 | 107 | FCheckBoxStateRaw GetPropertyRawValue() const 108 | { 109 | FCheckBoxStateRaw Value; 110 | PropertyHandle.Get()->GetValue(Value); 111 | return Value; 112 | } 113 | 114 | ECheckBoxState GetPropertyValue() const 115 | { 116 | return static_cast(GetPropertyRawValue()); 117 | } 118 | 119 | void OnCheckBoxStateChanged(ECheckBoxState State) 120 | { 121 | const FCheckBoxStateRaw PrevEnumValue = (GetPropertyRawValue() + 2) % 3; 122 | PropertyHandle.Get()->SetValue(PrevEnumValue); 123 | } 124 | 125 | private: 126 | 127 | TSharedPtr PropertyHandle; 128 | }; 129 | } 130 | 131 | 132 | //---------------------------------------------------------------------------------------------------- 133 | // FImGuiKeyInfoCustomization implementation 134 | //---------------------------------------------------------------------------------------------------- 135 | 136 | namespace InputConstants 137 | { 138 | static const FMargin PropertyPadding(0.0f, 0.0f, 4.0f, 0.0f); 139 | } 140 | 141 | TSharedRef FImGuiKeyInfoCustomization::MakeInstance() 142 | { 143 | return MakeShareable(new FImGuiKeyInfoCustomization); 144 | } 145 | 146 | void FImGuiKeyInfoCustomization::CustomizeHeader(TSharedRef InStructPropertyHandle, FDetailWidgetRow& HeaderRow, IPropertyTypeCustomizationUtils& StructCustomizationUtils) 147 | { 148 | TSharedPtr KeyHandle = InStructPropertyHandle->GetChildHandle(GET_MEMBER_NAME_CHECKED(FImGuiKeyInfo, Key)); 149 | TSharedPtr ShiftHandle = InStructPropertyHandle->GetChildHandle(GET_MEMBER_NAME_CHECKED(FImGuiKeyInfo, Shift)); 150 | TSharedPtr CtrlHandle = InStructPropertyHandle->GetChildHandle(GET_MEMBER_NAME_CHECKED(FImGuiKeyInfo, Ctrl)); 151 | TSharedPtr AltHandle = InStructPropertyHandle->GetChildHandle(GET_MEMBER_NAME_CHECKED(FImGuiKeyInfo, Alt)); 152 | TSharedPtr CmdHandle = InStructPropertyHandle->GetChildHandle(GET_MEMBER_NAME_CHECKED(FImGuiKeyInfo, Cmd)); 153 | 154 | #define ADD_CHECK_BOX_SLOT(Handle) \ 155 | + SHorizontalBox::Slot()\ 156 | .Padding(InputConstants::PropertyPadding)\ 157 | .HAlign(HAlign_Left)\ 158 | .VAlign(VAlign_Center)\ 159 | .AutoWidth()\ 160 | [\ 161 | Handle->CreatePropertyNameWidget()\ 162 | ]\ 163 | + SHorizontalBox::Slot()\ 164 | .Padding(InputConstants::PropertyPadding)\ 165 | .HAlign(HAlign_Left)\ 166 | .VAlign(VAlign_Center)\ 167 | .AutoWidth()\ 168 | [\ 169 | SNew(SPropertyTriStateCheckBox).PropertyHandle(Handle)\ 170 | ] 171 | 172 | HeaderRow 173 | .NameContent() 174 | [ 175 | InStructPropertyHandle->CreatePropertyNameWidget() 176 | ] 177 | .ValueContent() 178 | .MaxDesiredWidth(400.f) 179 | [ 180 | SNew(SHorizontalBox) 181 | + SHorizontalBox::Slot() 182 | .Padding(InputConstants::PropertyPadding) 183 | .AutoWidth() 184 | [ 185 | SNew(SBox) 186 | .WidthOverride(200.f) 187 | [ 188 | SNew(SPropertyKeySelector) 189 | .KeyHandle(KeyHandle) 190 | .Font(StructCustomizationUtils.GetRegularFont()) 191 | ] 192 | ] 193 | ADD_CHECK_BOX_SLOT(ShiftHandle) 194 | ADD_CHECK_BOX_SLOT(CtrlHandle) 195 | ADD_CHECK_BOX_SLOT(AltHandle) 196 | ADD_CHECK_BOX_SLOT(CmdHandle) 197 | ]; 198 | 199 | #undef ADD_CHECK_BOX_SLOT 200 | } 201 | 202 | void FImGuiKeyInfoCustomization::CustomizeChildren(TSharedRef InStructPropertyHandle, IDetailChildrenBuilder& StructBuilder, IPropertyTypeCustomizationUtils& StructCustomizationUtils) 203 | { 204 | } 205 | 206 | 207 | #undef LOCTEXT_NAMESPACE 208 | 209 | #endif // WITH_EDITOR 210 | -------------------------------------------------------------------------------- /Source/ImGui/Private/ImGuiModuleSettings.cpp: -------------------------------------------------------------------------------- 1 | // Distributed under the MIT License (MIT) (see accompanying LICENSE file) 2 | 3 | #include "ImGuiModuleSettings.h" 4 | 5 | #include "ImGuiModuleCommands.h" 6 | #include "ImGuiModuleProperties.h" 7 | 8 | #include 9 | #include 10 | #include 11 | 12 | 13 | //==================================================================================================== 14 | // FImGuiDPIScaleInfo 15 | //==================================================================================================== 16 | 17 | FImGuiDPIScaleInfo::FImGuiDPIScaleInfo() 18 | { 19 | if (FRichCurve* Curve = DPICurve.GetRichCurve()) 20 | { 21 | Curve->AddKey( 0.0f, 1.f); 22 | 23 | Curve->AddKey(2159.5f, 1.f); 24 | Curve->AddKey(2160.0f, 2.f); 25 | 26 | Curve->AddKey(4319.5f, 2.f); 27 | Curve->AddKey(4320.0f, 4.f); 28 | } 29 | } 30 | 31 | float FImGuiDPIScaleInfo::CalculateResolutionBasedScale() const 32 | { 33 | float ResolutionBasedScale = 1.f; 34 | if (bScaleWithCurve && GEngine && GEngine->GameUserSettings) 35 | { 36 | if (const FRichCurve* Curve = DPICurve.GetRichCurveConst()) 37 | { 38 | ResolutionBasedScale *= Curve->Eval((float)GEngine->GameUserSettings->GetDesktopResolution().Y, 1.f); 39 | } 40 | } 41 | return ResolutionBasedScale; 42 | } 43 | 44 | //==================================================================================================== 45 | // UImGuiSettings 46 | //==================================================================================================== 47 | 48 | UImGuiSettings* UImGuiSettings::DefaultInstance = nullptr; 49 | 50 | FSimpleMulticastDelegate UImGuiSettings::OnSettingsLoaded; 51 | 52 | void UImGuiSettings::PostInitProperties() 53 | { 54 | Super::PostInitProperties(); 55 | 56 | if (IsTemplate()) 57 | { 58 | DefaultInstance = this; 59 | OnSettingsLoaded.Broadcast(); 60 | } 61 | } 62 | 63 | void UImGuiSettings::BeginDestroy() 64 | { 65 | Super::BeginDestroy(); 66 | 67 | if (DefaultInstance == this) 68 | { 69 | DefaultInstance = nullptr; 70 | } 71 | } 72 | 73 | //==================================================================================================== 74 | // FImGuiModuleSettings 75 | //==================================================================================================== 76 | 77 | FImGuiModuleSettings::FImGuiModuleSettings(FImGuiModuleProperties& InProperties, FImGuiModuleCommands& InCommands) 78 | : Properties(InProperties) 79 | , Commands(InCommands) 80 | { 81 | #if WITH_EDITOR 82 | FCoreUObjectDelegates::OnObjectPropertyChanged.AddRaw(this, &FImGuiModuleSettings::OnPropertyChanged); 83 | #endif 84 | 85 | // Delegate initializer to support settings loaded after this object creation (in stand-alone builds) and potential 86 | // reloading of settings. 87 | UImGuiSettings::OnSettingsLoaded.AddRaw(this, &FImGuiModuleSettings::InitializeAllSettings); 88 | 89 | // Call initializer to support settings already loaded (editor). 90 | InitializeAllSettings(); 91 | } 92 | 93 | FImGuiModuleSettings::~FImGuiModuleSettings() 94 | { 95 | 96 | UImGuiSettings::OnSettingsLoaded.RemoveAll(this); 97 | 98 | #if WITH_EDITOR 99 | FCoreUObjectDelegates::OnObjectPropertyChanged.RemoveAll(this); 100 | #endif 101 | } 102 | 103 | void FImGuiModuleSettings::InitializeAllSettings() 104 | { 105 | UpdateSettings(); 106 | UpdateDPIScaleInfo(); 107 | } 108 | 109 | void FImGuiModuleSettings::UpdateSettings() 110 | { 111 | if (UImGuiSettings* SettingsObject = UImGuiSettings::Get()) 112 | { 113 | SetImGuiInputHandlerClass(SettingsObject->ImGuiInputHandlerClass); 114 | SetShareKeyboardInput(SettingsObject->bShareKeyboardInput); 115 | SetShareGamepadInput(SettingsObject->bShareGamepadInput); 116 | SetShareMouseInput(SettingsObject->bShareMouseInput); 117 | SetUseSoftwareCursor(SettingsObject->bUseSoftwareCursor); 118 | SetToggleInputKey(SettingsObject->ToggleInput); 119 | SetCanvasSizeInfo(SettingsObject->CanvasSize); 120 | } 121 | } 122 | 123 | void FImGuiModuleSettings::UpdateDPIScaleInfo() 124 | { 125 | if (UImGuiSettings* SettingsObject = UImGuiSettings::Get()) 126 | { 127 | SetDPIScaleInfo(SettingsObject->DPIScale); 128 | } 129 | } 130 | 131 | void FImGuiModuleSettings::SetImGuiInputHandlerClass(const FSoftClassPath& ClassReference) 132 | { 133 | if (ImGuiInputHandlerClass != ClassReference) 134 | { 135 | ImGuiInputHandlerClass = ClassReference; 136 | OnImGuiInputHandlerClassChanged.Broadcast(ClassReference); 137 | } 138 | } 139 | 140 | void FImGuiModuleSettings::SetShareKeyboardInput(bool bShare) 141 | { 142 | if (bShareKeyboardInput != bShare) 143 | { 144 | bShareKeyboardInput = bShare; 145 | Properties.SetKeyboardInputShared(bShare); 146 | } 147 | } 148 | 149 | void FImGuiModuleSettings::SetShareGamepadInput(bool bShare) 150 | { 151 | if (bShareGamepadInput != bShare) 152 | { 153 | bShareGamepadInput = bShare; 154 | Properties.SetGamepadInputShared(bShare); 155 | } 156 | } 157 | 158 | void FImGuiModuleSettings::SetShareMouseInput(bool bShare) 159 | { 160 | if (bShareMouseInput != bShare) 161 | { 162 | bShareMouseInput = bShare; 163 | Properties.SetMouseInputShared(bShare); 164 | } 165 | } 166 | 167 | void FImGuiModuleSettings::SetUseSoftwareCursor(bool bUse) 168 | { 169 | if (bUseSoftwareCursor != bUse) 170 | { 171 | bUseSoftwareCursor = bUse; 172 | OnUseSoftwareCursorChanged.Broadcast(bUse); 173 | } 174 | } 175 | 176 | void FImGuiModuleSettings::SetToggleInputKey(const FImGuiKeyInfo& KeyInfo) 177 | { 178 | if (ToggleInputKey != KeyInfo) 179 | { 180 | ToggleInputKey = KeyInfo; 181 | Commands.SetKeyBinding(FImGuiModuleCommands::ToggleInput, ToggleInputKey); 182 | } 183 | } 184 | 185 | void FImGuiModuleSettings::SetCanvasSizeInfo(const FImGuiCanvasSizeInfo& CanvasSizeInfo) 186 | { 187 | if (CanvasSize != CanvasSizeInfo) 188 | { 189 | CanvasSize = CanvasSizeInfo; 190 | OnCanvasSizeChangedDelegate.Broadcast(CanvasSize); 191 | } 192 | } 193 | 194 | void FImGuiModuleSettings::SetDPIScaleInfo(const FImGuiDPIScaleInfo& ScaleInfo) 195 | { 196 | DPIScale = ScaleInfo; 197 | OnDPIScaleChangedDelegate.Broadcast(DPIScale); 198 | } 199 | 200 | #if WITH_EDITOR 201 | 202 | void FImGuiModuleSettings::OnPropertyChanged(class UObject* ObjectBeingModified, struct FPropertyChangedEvent& PropertyChangedEvent) 203 | { 204 | if (ObjectBeingModified == UImGuiSettings::Get()) 205 | { 206 | UpdateSettings(); 207 | if (PropertyChangedEvent.MemberProperty 208 | && (PropertyChangedEvent.MemberProperty->GetFName() == GET_MEMBER_NAME_CHECKED(FImGuiModuleSettings, DPIScale))) 209 | { 210 | UpdateDPIScaleInfo(); 211 | } 212 | } 213 | } 214 | 215 | #endif // WITH_EDITOR 216 | -------------------------------------------------------------------------------- /Source/ImGui/Public/ImGuiInputHandler.h: -------------------------------------------------------------------------------- 1 | // Distributed under the MIT License (MIT) (see accompanying LICENSE file) 2 | 3 | #pragma once 4 | 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | #include "ImGuiInputHandler.generated.h" 11 | 12 | 13 | class FImGuiModuleManager; 14 | class UGameViewportClient; 15 | 16 | struct FAnalogInputEvent; 17 | struct FCharacterEvent; 18 | struct FKeyEvent; 19 | 20 | #if WITH_EDITOR 21 | class FUICommandInfo; 22 | #endif // WITH_EDITOR 23 | 24 | 25 | /** 26 | * Handles input and sends it to the input state, which is copied to the ImGui IO at the beginning of the frame. 27 | * Implementation of the input handler can be changed in the ImGui project settings by changing ImGuiInputHandlerClass. 28 | */ 29 | UCLASS() 30 | class IMGUI_API UImGuiInputHandler : public UObject 31 | { 32 | GENERATED_BODY() 33 | 34 | public: 35 | 36 | /** 37 | * Called to handle character events. 38 | * @returns Response whether the event was handled 39 | */ 40 | virtual FReply OnKeyChar(const struct FCharacterEvent& CharacterEvent); 41 | 42 | /** 43 | * Called to handle key down events. 44 | * @returns Response whether the event was handled 45 | */ 46 | virtual FReply OnKeyDown(const FKeyEvent& KeyEvent); 47 | 48 | /** 49 | * Called to handle key up events. 50 | * @returns Response whether the event was handled 51 | */ 52 | virtual FReply OnKeyUp(const FKeyEvent& KeyEvent); 53 | 54 | /** 55 | * Called to handle analog value change events. 56 | * @returns Response whether the event was handled 57 | */ 58 | virtual FReply OnAnalogValueChanged(const FAnalogInputEvent& AnalogInputEvent); 59 | 60 | /** 61 | * Called to handle mouse button down events. 62 | * @returns Response whether the event was handled 63 | */ 64 | virtual FReply OnMouseButtonDown(const FPointerEvent& MouseEvent); 65 | 66 | /** 67 | * Called to handle mouse button double-click events. 68 | * @returns Response whether the event was handled 69 | */ 70 | virtual FReply OnMouseButtonDoubleClick(const FPointerEvent& MouseEvent); 71 | 72 | /** 73 | * Called to handle mouse button up events. 74 | * @returns Response whether the event was handled 75 | */ 76 | virtual FReply OnMouseButtonUp(const FPointerEvent& MouseEvent); 77 | 78 | /** 79 | * Called to handle mouse wheel events. 80 | * @returns Response whether the event was handled 81 | */ 82 | virtual FReply OnMouseWheel(const FPointerEvent& MouseEvent); 83 | 84 | /** 85 | * Called to handle mouse move events. 86 | * @param MousePosition Mouse position (in ImGui space) 87 | * @param MouseEvent Optional mouse event passed from Slate 88 | * @returns Response whether the event was handled 89 | */ 90 | virtual FReply OnMouseMove(const FVector2D& MousePosition, const FPointerEvent& MouseEvent); 91 | virtual FReply OnMouseMove(const FVector2D& MousePosition); 92 | 93 | /** 94 | * Called to handle touch started event. 95 | * @param TouchPosition Touch position (in ImGui space) 96 | * @param TouchEvent Touch event passed from Slate 97 | * @returns Response whether the event was handled 98 | */ 99 | virtual FReply OnTouchStarted(const FVector2D& TouchPosition, const FPointerEvent& TouchEvent); 100 | 101 | /** 102 | * Called to handle touch moved event. 103 | * @param TouchPosition Touch position (in ImGui space) 104 | * @param TouchEvent Touch event passed from Slate 105 | * @returns Response whether the event was handled 106 | */ 107 | virtual FReply OnTouchMoved(const FVector2D& TouchPosition, const FPointerEvent& TouchEvent); 108 | 109 | /** 110 | * Called to handle touch ended event. 111 | * @param TouchPosition Touch position (in ImGui space) 112 | * @param TouchEvent Touch event passed from Slate 113 | * @returns Response whether the event was handled 114 | */ 115 | virtual FReply OnTouchEnded(const FVector2D& TouchPosition, const FPointerEvent& TouchEvent); 116 | 117 | /** Called to handle activation of the keyboard input. */ 118 | virtual void OnKeyboardInputEnabled(); 119 | 120 | /** Called to handle deactivation of the keyboard input. */ 121 | virtual void OnKeyboardInputDisabled(); 122 | 123 | /** Called to handle activation of the gamepad input. */ 124 | virtual void OnGamepadInputEnabled(); 125 | 126 | /** Called to handle deactivation of the gamepad input. */ 127 | virtual void OnGamepadInputDisabled(); 128 | 129 | /** Called to handle activation of the mouse input. */ 130 | virtual void OnMouseInputEnabled(); 131 | 132 | /** Called to handle deactivation of the mouse input. */ 133 | virtual void OnMouseInputDisabled(); 134 | 135 | protected: 136 | 137 | /** Copy state of modifier keys to input state. */ 138 | void CopyModifierKeys(const FInputEvent& InputEvent); 139 | 140 | /** 141 | * Checks whether this is a key event that can open console. 142 | * @param KeyEvent - Key event to test. 143 | * @returns True, if this key event can open console. 144 | */ 145 | bool IsConsoleEvent(const FKeyEvent& KeyEvent) const; 146 | 147 | #if WITH_EDITOR 148 | /** 149 | * Checks whether this is a key event that can stop PIE session. 150 | * @param KeyEvent - Key event to test. 151 | * @returns True, if this key event can stop PIE session. 152 | */ 153 | bool IsStopPlaySessionEvent(const FKeyEvent& KeyEvent) const; 154 | #endif 155 | 156 | /** 157 | * Checks whether this key event can toggle ImGui input (as defined in settings). 158 | * @param KeyEvent - Key event to test. 159 | * @returns True, if this key is bound to 'ImGui.ToggleInput' command that switches ImGui input mode. 160 | */ 161 | bool IsToggleInputEvent(const FKeyEvent& KeyEvent) const; 162 | 163 | /** 164 | * Checks whether corresponding ImGui context has an active item (holding cursor focus). 165 | * @returns True, if corresponding context has an active item. 166 | */ 167 | bool HasImGuiActiveItem() const; 168 | 169 | private: 170 | 171 | void UpdateInputStatePointer(); 172 | 173 | void OnSoftwareCursorChanged(bool); 174 | 175 | void OnPostImGuiUpdate(); 176 | 177 | void Initialize(FImGuiModuleManager* InModuleManager, UGameViewportClient* InGameViewport, int32 InContextIndex); 178 | 179 | virtual void BeginDestroy() override; 180 | 181 | class FImGuiInputState* InputState = nullptr; 182 | 183 | bool bMouseInputEnabled = false; 184 | bool bKeyboardInputEnabled = false; 185 | bool bGamepadInputEnabled = false; 186 | 187 | FImGuiModuleManager* ModuleManager = nullptr; 188 | 189 | TWeakObjectPtr GameViewport; 190 | 191 | int32 ContextIndex = -1; 192 | 193 | #if WITH_EDITOR 194 | TSharedPtr StopPlaySessionCommandInfo; 195 | #endif 196 | 197 | friend class FImGuiInputHandlerFactory; 198 | }; 199 | -------------------------------------------------------------------------------- /Source/ImGui/Private/TextureManager.cpp: -------------------------------------------------------------------------------- 1 | // Distributed under the MIT License (MIT) (see accompanying LICENSE file) 2 | 3 | #include "TextureManager.h" 4 | #include "RHITypes.h" 5 | #include 6 | #include 7 | 8 | #include 9 | 10 | 11 | void FTextureManager::InitializeErrorTexture(const FColor& Color) 12 | { 13 | CreatePlainTextureInternal(NAME_ErrorTexture, 2, 2, Color); 14 | } 15 | 16 | TextureIndex FTextureManager::CreateTexture(const FName& Name, int32 Width, int32 Height, uint32 SrcBpp, uint8* SrcData, TFunction SrcDataCleanup) 17 | { 18 | checkf(Name != NAME_None, TEXT("Trying to create a texture with a name 'NAME_None' is not allowed.")); 19 | 20 | return CreateTextureInternal(Name, Width, Height, SrcBpp, SrcData, SrcDataCleanup); 21 | } 22 | 23 | TextureIndex FTextureManager::CreatePlainTexture(const FName& Name, int32 Width, int32 Height, FColor Color) 24 | { 25 | checkf(Name != NAME_None, TEXT("Trying to create a texture with a name 'NAME_None' is not allowed.")); 26 | 27 | return CreatePlainTextureInternal(Name, Width, Height, Color); 28 | } 29 | 30 | TextureIndex FTextureManager::CreateTextureResources(const FName& Name, UTexture* Texture) 31 | { 32 | checkf(Name != NAME_None, TEXT("Trying to create texture resources with a name 'NAME_None' is not allowed.")); 33 | checkf(Texture, TEXT("Null Texture.")); 34 | 35 | // Create an entry for the texture. 36 | return AddTextureEntry(Name, Texture, false); 37 | } 38 | 39 | void FTextureManager::ReleaseTextureResources(TextureIndex Index) 40 | { 41 | checkf(IsInRange(Index), TEXT("Invalid texture index %d. Texture resources array has %d entries total."), Index, TextureResources.Num()); 42 | 43 | TextureResources[Index] = {}; 44 | } 45 | 46 | TextureIndex FTextureManager::CreateTextureInternal(const FName& Name, int32 Width, int32 Height, uint32 SrcBpp, uint8* SrcData, TFunction SrcDataCleanup) 47 | { 48 | // Create a texture. 49 | UTexture2D* Texture = UTexture2D::CreateTransient(Width, Height); 50 | 51 | // Create a new resource for that texture. 52 | Texture->UpdateResource(); 53 | 54 | // Update texture data. 55 | FUpdateTextureRegion2D* TextureRegion = new FUpdateTextureRegion2D(0, 0, 0, 0, Width, Height); 56 | auto DataCleanup = [SrcDataCleanup](uint8* Data, const FUpdateTextureRegion2D* UpdateRegion) 57 | { 58 | SrcDataCleanup(Data); 59 | delete UpdateRegion; 60 | }; 61 | Texture->UpdateTextureRegions(0, 1u, TextureRegion, SrcBpp * Width, SrcBpp, SrcData, DataCleanup); 62 | 63 | // Create an entry for the texture. 64 | if (Name == NAME_ErrorTexture) 65 | { 66 | ErrorTexture = { Name, Texture, true }; 67 | return INDEX_ErrorTexture; 68 | } 69 | else 70 | { 71 | return AddTextureEntry(Name, Texture, true); 72 | } 73 | } 74 | 75 | TextureIndex FTextureManager::CreatePlainTextureInternal(const FName& Name, int32 Width, int32 Height, const FColor& Color) 76 | { 77 | // Create buffer with raw data. 78 | const uint32 ColorPacked = Color.ToPackedARGB(); 79 | const uint32 Bpp = sizeof(ColorPacked); 80 | const uint32 SizeInPixels = Width * Height; 81 | const uint32 SizeInBytes = SizeInPixels * Bpp; 82 | uint8* SrcData = new uint8[SizeInBytes]; 83 | std::fill(reinterpret_cast(SrcData), reinterpret_cast(SrcData) + SizeInPixels, ColorPacked); 84 | auto SrcDataCleanup = [](uint8* Data) { delete[] Data; }; 85 | 86 | // Create new texture from raw data. 87 | return CreateTextureInternal(Name, Width, Height, Bpp, SrcData, SrcDataCleanup); 88 | } 89 | 90 | TextureIndex FTextureManager::AddTextureEntry(const FName& Name, UTexture* Texture, bool bAddToRoot) 91 | { 92 | // Try to find an entry with that name. 93 | TextureIndex Index = FindTextureIndex(Name); 94 | 95 | // If this is a new name, try to find an entry to reuse. 96 | if (Index == INDEX_NONE) 97 | { 98 | Index = FindTextureIndex(NAME_None); 99 | } 100 | 101 | // Either update/reuse an entry or add a new one. 102 | if (Index != INDEX_NONE) 103 | { 104 | TextureResources[Index] = { Name, Texture, bAddToRoot }; 105 | return Index; 106 | } 107 | else 108 | { 109 | return TextureResources.Emplace(Name, Texture, bAddToRoot); 110 | } 111 | } 112 | 113 | FTextureManager::FTextureEntry::FTextureEntry(const FName& InName, UTexture* InTexture, bool bAddToRoot) 114 | : Name(InName) 115 | { 116 | checkf(InTexture, TEXT("Null texture.")); 117 | 118 | if (bAddToRoot) 119 | { 120 | // Get pointer only for textures that we added to root, so we can later release them. 121 | Texture = InTexture; 122 | // Add texture to the root to prevent garbage collection. 123 | InTexture->AddToRoot(); 124 | } 125 | 126 | // Create brush and resource handle for input texture. 127 | Brush.SetResourceObject(InTexture); 128 | CachedResourceHandle = FSlateApplication::Get().GetRenderer()->GetResourceHandle(Brush); 129 | } 130 | 131 | FTextureManager::FTextureEntry::~FTextureEntry() 132 | { 133 | Reset(true); 134 | } 135 | 136 | FTextureManager::FTextureEntry& FTextureManager::FTextureEntry::operator=(FTextureEntry&& Other) 137 | { 138 | // Release old resources if allocated. 139 | Reset(true); 140 | 141 | // Move data and ownership to this instance. 142 | Name = MoveTemp(Other.Name); 143 | Texture = MoveTemp(Other.Texture); 144 | Brush = MoveTemp(Other.Brush); 145 | CachedResourceHandle = MoveTemp(Other.CachedResourceHandle); 146 | 147 | // Reset the other entry (without releasing resources which are already moved to this instance) to remove tracks 148 | // of ownership and mark it as empty/reusable. 149 | Other.Reset(false); 150 | 151 | return *this; 152 | } 153 | 154 | const FSlateResourceHandle& FTextureManager::FTextureEntry::GetResourceHandle() const 155 | { 156 | if (!CachedResourceHandle.IsValid() && Brush.HasUObject()) 157 | { 158 | CachedResourceHandle = FSlateApplication::Get().GetRenderer()->GetResourceHandle(Brush); 159 | } 160 | return CachedResourceHandle; 161 | } 162 | 163 | void FTextureManager::FTextureEntry::Reset(bool bReleaseResources) 164 | { 165 | if (bReleaseResources) 166 | { 167 | // Release brush. 168 | if (Brush.HasUObject() && FSlateApplication::IsInitialized()) 169 | { 170 | FSlateApplication::Get().GetRenderer()->ReleaseDynamicResource(Brush); 171 | } 172 | 173 | // Remove texture from root to allow for garbage collection (it might be invalid, if we never set it 174 | // or this is an application shutdown). 175 | if (Texture.IsValid()) 176 | { 177 | Texture->RemoveFromRoot(); 178 | } 179 | } 180 | 181 | // We use empty name to mark unused entries. 182 | Name = NAME_None; 183 | 184 | // Clean fields to make sure that we don't reference released or moved resources. 185 | Texture.Reset(); 186 | Brush = FSlateNoResource(); 187 | CachedResourceHandle = FSlateResourceHandle(); 188 | } 189 | -------------------------------------------------------------------------------- /Source/ImGui/Private/TextureManager.h: -------------------------------------------------------------------------------- 1 | // Distributed under the MIT License (MIT) (see accompanying LICENSE file) 2 | 3 | #pragma once 4 | 5 | #include 6 | #include 7 | #include 8 | 9 | 10 | class UTexture2D; 11 | 12 | // Index type to be used as a texture handle. 13 | using TextureIndex = int32; 14 | 15 | // Manager for textures resources which can be referenced by a unique name or index. 16 | // Name is primarily for lookup and index provides a direct access to resources. 17 | class FTextureManager 18 | { 19 | public: 20 | 21 | // Creates an empty manager. 22 | FTextureManager() = default; 23 | 24 | // Copying is disabled to protected resource ownership. 25 | FTextureManager(const FTextureManager&) = delete; 26 | FTextureManager& operator=(const FTextureManager&) = delete; 27 | 28 | // Moving transfers ownership and leaves source empty. 29 | FTextureManager(FTextureManager&&) = delete; 30 | FTextureManager& operator=(FTextureManager&&) = delete; 31 | 32 | // Initialize error texture that will be used for rendering textures without registered resources. Can be called 33 | // multiple time, if color needs to be changed. 34 | // Note: Because of any-time module loading and lazy resources initialization goals we can't simply call it from 35 | // constructor. 36 | // @param Color - The color of the error texture 37 | void InitializeErrorTexture(const FColor& Color); 38 | 39 | // Find texture index by name. 40 | // @param Name - The name of a texture to find 41 | // @returns The index of a texture with given name or INDEX_NONE if there is no such texture 42 | TextureIndex FindTextureIndex(const FName& Name) const 43 | { 44 | return TextureResources.IndexOfByPredicate([&](const auto& Entry) { return Entry.GetName() == Name; }); 45 | } 46 | 47 | // Get the name of a texture at given index. Returns NAME_None, if index is out of range. 48 | // @param Index - Index of a texture 49 | // @returns The name of a texture at given index or NAME_None if index is out of range. 50 | FName GetTextureName(TextureIndex Index) const 51 | { 52 | return IsInRange(Index) ? TextureResources[Index].GetName() : NAME_None; 53 | } 54 | 55 | // Get the Slate Resource Handle to a texture at given index. If index is out of range or resources are not valid 56 | // it returns a handle to the error texture. 57 | // @param Index - Index of a texture 58 | // @returns The Slate Resource Handle for a texture at given index or to error texture, if no valid resources were 59 | // found at given index 60 | const FSlateResourceHandle& GetTextureHandle(TextureIndex Index) const 61 | { 62 | return IsValidTexture(Index) ? TextureResources[Index].GetResourceHandle() : ErrorTexture.GetResourceHandle(); 63 | } 64 | 65 | // Create a texture from raw data. 66 | // @param Name - The texture name 67 | // @param Width - The texture width 68 | // @param Height - The texture height 69 | // @param SrcBpp - The size in bytes of one pixel 70 | // @param SrcData - The source data 71 | // @param SrcDataCleanup - Optional function called to release source data after texture is created (only needed, if data need to be released) 72 | // @returns The index of a texture that was created 73 | TextureIndex CreateTexture(const FName& Name, int32 Width, int32 Height, uint32 SrcBpp, uint8* SrcData, TFunction SrcDataCleanup = [](uint8*) {}); 74 | 75 | // Create a plain texture. 76 | // @param Name - The texture name 77 | // @param Width - The texture width 78 | // @param Height - The texture height 79 | // @param Color - The texture color 80 | // @returns The index of a texture that was created 81 | TextureIndex CreatePlainTexture(const FName& Name, int32 Width, int32 Height, FColor Color); 82 | 83 | // Create Slate resources to an existing texture, managed externally. 84 | // @param Name - The texture name 85 | // @param Texture - The texture 86 | // @returns The index to created/updated texture resources 87 | TextureIndex CreateTextureResources(const FName& Name, UTexture* Texture); 88 | 89 | // Release resources for given texture. Ignores invalid indices. 90 | // @param Index - The index of a texture resources 91 | void ReleaseTextureResources(TextureIndex Index); 92 | 93 | private: 94 | 95 | // See CreateTexture for general description. 96 | // Internal implementations doesn't validate name or resource uniqueness. Instead it uses NAME_ErrorTexture 97 | // (aka NAME_None) and INDEX_ErrorTexture (aka INDEX_NONE) to identify ErrorTexture. 98 | TextureIndex CreateTextureInternal(const FName& Name, int32 Width, int32 Height, uint32 SrcBpp, uint8* SrcData, TFunction SrcDataCleanup = [](uint8*) {}); 99 | 100 | // See CreatePlainTexture for general description. 101 | // Internal implementations doesn't validate name or resource uniqueness. Instead it uses NAME_ErrorTexture 102 | // (aka NAME_None) and INDEX_ErrorTexture (aka INDEX_NONE) to identify ErrorTexture. 103 | TextureIndex CreatePlainTextureInternal(const FName& Name, int32 Width, int32 Height, const FColor& Color); 104 | 105 | // Add or reuse texture entry. 106 | // @param Name - The texture name 107 | // @param Texture - The texture 108 | // @param bAddToRoot - If true, we should add texture to root to prevent garbage collection (use for own textures) 109 | // @returns The index of the entry that we created or reused 110 | TextureIndex AddTextureEntry(const FName& Name, UTexture* Texture, bool bAddToRoot); 111 | 112 | // Check whether index is in range allocated for TextureResources (it doesn't mean that resources are valid). 113 | FORCEINLINE bool IsInRange(TextureIndex Index) const 114 | { 115 | return static_cast(Index) < static_cast(TextureResources.Num()); 116 | } 117 | 118 | // Check whether index is in range and whether texture resources are valid (using NAME_None sentinel). 119 | FORCEINLINE bool IsValidTexture(TextureIndex Index) const 120 | { 121 | return IsInRange(Index) && TextureResources[Index].GetName() != NAME_None; 122 | } 123 | 124 | // Entry for texture resources. Only supports explicit construction. 125 | struct FTextureEntry 126 | { 127 | FTextureEntry() = default; 128 | FTextureEntry(const FName& InName, UTexture* InTexture, bool bAddToRoot); 129 | ~FTextureEntry(); 130 | 131 | // Copying is not supported. 132 | FTextureEntry(const FTextureEntry&) = delete; 133 | FTextureEntry& operator=(const FTextureEntry&) = delete; 134 | 135 | // We rely on TArray and don't implement custom move constructor... 136 | FTextureEntry(FTextureEntry&&) = delete; 137 | // ... but we need move assignment to support reusing entries. 138 | FTextureEntry& operator=(FTextureEntry&& Other); 139 | 140 | const FName& GetName() const { return Name; } 141 | const FSlateResourceHandle& GetResourceHandle() const; 142 | 143 | private: 144 | 145 | void Reset(bool bReleaseResources); 146 | 147 | FName Name = NAME_None; 148 | mutable FSlateResourceHandle CachedResourceHandle; 149 | TWeakObjectPtr Texture; 150 | FSlateBrush Brush; 151 | }; 152 | 153 | TArray TextureResources; 154 | FTextureEntry ErrorTexture; 155 | 156 | static constexpr EName NAME_ErrorTexture = NAME_None; 157 | static constexpr TextureIndex INDEX_ErrorTexture = INDEX_NONE; 158 | }; 159 | -------------------------------------------------------------------------------- /Source/ImGui/Public/ImGuiModule.h: -------------------------------------------------------------------------------- 1 | // Distributed under the MIT License (MIT) (see accompanying LICENSE file) 2 | 3 | #pragma once 4 | 5 | #include "ImGuiDelegates.h" 6 | #include "ImGuiModuleProperties.h" 7 | #include "ImGuiTextureHandle.h" 8 | 9 | #include 10 | 11 | 12 | class FImGuiModule : public IModuleInterface 13 | { 14 | public: 15 | 16 | /** 17 | * Singleton-like access to this module's interface. This is just for convenience! 18 | * Beware of calling this during the shutdown phase, though. Your module might have been unloaded already. 19 | * 20 | * @return Returns singleton instance, loading the module on demand if needed 21 | */ 22 | static inline FImGuiModule& Get() 23 | { 24 | return FModuleManager::LoadModuleChecked("ImGui"); 25 | } 26 | 27 | /** 28 | * Checks to see if this module is loaded and ready. It is only valid to call Get() if IsAvailable() returns true. 29 | * 30 | * @return True if the module is loaded and ready to use 31 | */ 32 | static inline bool IsAvailable() 33 | { 34 | return FModuleManager::Get().IsModuleLoaded("ImGui"); 35 | } 36 | 37 | #if IMGUI_WITH_OBSOLETE_DELEGATES 38 | 39 | #if WITH_EDITOR 40 | /** 41 | * Add a delegate called at the end of editor debug frame to draw debug controls in its ImGui context, creating 42 | * that context on demand. 43 | * 44 | * @param Delegate - Delegate that we want to add (@see FImGuiDelegate::Create...) 45 | * @returns Returns handle that can be used to remove delegate (@see RemoveImGuiDelegate) 46 | */ 47 | virtual FImGuiDelegateHandle AddEditorImGuiDelegate(const FImGuiDelegate& Delegate); 48 | #endif 49 | 50 | /** 51 | * Add a delegate called at the end of current world debug frame to draw debug controls in its ImGui context, 52 | * creating that context on demand. 53 | * This function will throw if called outside of a world context (i.e. current world cannot be found). 54 | * 55 | * @param Delegate - Delegate that we want to add (@see FImGuiDelegate::Create...) 56 | * @returns Returns handle that can be used to remove delegate (@see RemoveImGuiDelegate) 57 | */ 58 | virtual FImGuiDelegateHandle AddWorldImGuiDelegate(const FImGuiDelegate& Delegate); 59 | 60 | /** 61 | * Add a delegate called at the end of a specific world's debug frame to draw debug controls in its ImGui context, 62 | * creating that context on demand. 63 | * 64 | * @param World - A specific world to add the delegate to to 65 | * @param Delegate - Delegate that we want to add (@see FImGuiDelegate::Create...) 66 | * @returns Returns handle that can be used to remove delegate (@see RemoveImGuiDelegate) 67 | */ 68 | virtual FImGuiDelegateHandle AddWorldImGuiDelegate(const UWorld* World, const FImGuiDelegate& Delegate); 69 | 70 | /** 71 | * Add shared delegate called for each ImGui context at the end of debug frame, after calling context specific 72 | * delegate. This delegate will be used for any ImGui context, created before or after it is registered. 73 | * 74 | * @param Delegate - Delegate that we want to add (@see FImGuiDelegate::Create...) 75 | * @returns Returns handle that can be used to remove delegate (@see RemoveImGuiDelegate) 76 | */ 77 | virtual FImGuiDelegateHandle AddMultiContextImGuiDelegate(const FImGuiDelegate& Delegate); 78 | 79 | /** 80 | * Remove delegate added with any version of Add...ImGuiDelegate 81 | * 82 | * @param Handle - Delegate handle that was returned by adding function 83 | */ 84 | virtual void RemoveImGuiDelegate(const FImGuiDelegateHandle& Handle); 85 | 86 | #endif // #if IMGUI_WITH_OBSOLETE_DELEGATES 87 | 88 | /** 89 | * If it exists, get a handle to the texture with given resource name. 90 | * 91 | * @param Name - Resource name of a texture to find 92 | * @returns Handle to a registered texture or invalid handle if resources could not be found or were not valid 93 | */ 94 | virtual FImGuiTextureHandle FindTextureHandle(const FName& Name); 95 | 96 | /** 97 | * Register texture and create its Slate resources. If texture with that name already exists then it may be updated 98 | * or if bMakeUnique is true, exception will be thrown. Throws exception, if name argument is NAME_None or texture 99 | * is null. 100 | * 101 | * Note, that updating texture resources doesn't invalidate already existing handles and returned handle will have 102 | * the same value. 103 | * 104 | * @param Name - Resource name for the texture that needs to be registered or updated 105 | * @param Texture - Texture for which we want to create or update Slate resources 106 | * @param bMakeUnique - If false then existing resources are updated/overwritten (default). If true, then stricter 107 | * policy is applied and if resource with that name exists then exception is thrown. 108 | * @returns Handle to the texture resources, which can be used to release allocated resources and as an argument to 109 | * relevant ImGui functions 110 | */ 111 | virtual FImGuiTextureHandle RegisterTexture(const FName& Name, class UTexture* Texture, bool bMakeUnique = false); 112 | 113 | /** 114 | * Unregister texture and release its Slate resources. If handle is null or not valid, this function fails silently 115 | * (for definition of 'valid' look @ FImGuiTextureHandle). 116 | * 117 | * @returns ImGui Texture Handle to texture that needs to be unregistered 118 | */ 119 | virtual void ReleaseTexture(const FImGuiTextureHandle& Handle); 120 | 121 | virtual void RebuildFontAtlas(); 122 | 123 | /** 124 | * Get ImGui module properties. 125 | * 126 | * @returns Reference to an instance of ImGui module properties that allows to read and/or modify module state. 127 | */ 128 | virtual FImGuiModuleProperties& GetProperties(); 129 | virtual const FImGuiModuleProperties& GetProperties() const; 130 | 131 | /** 132 | * DEPRECIATED: Please use GetProperties() as this function is scheduled for removal. 133 | * Check whether Input Mode is enabled (tests ImGui.InputEnabled console variable). 134 | * 135 | * @returns True, if Input Mode is enabled (ImGui.InputEnabled != 0) and false otherwise. 136 | */ 137 | virtual bool IsInputMode() const; 138 | 139 | /** 140 | * DEPRECIATED: Please use GetProperties() as this function is scheduled for removal. 141 | * Set Input Mode state (sets ImGui.InputEnabled console variable, so it can be used together with a console). 142 | * 143 | * @param bEnabled - Whether Input Mode should be enabled (ImGui.InputEnabled = 1) or not (ImGui.InputEnabled = 0). 144 | */ 145 | virtual void SetInputMode(bool bEnabled); 146 | 147 | /** 148 | * DEPRECIATED: Please use GetProperties() as this function is scheduled for removal. 149 | * Toggle Input Mode state (changes ImGui.InputEnabled console variable). 150 | */ 151 | virtual void ToggleInputMode(); 152 | 153 | /** 154 | * DEPRECIATED: Please use GetProperties() as this function is scheduled for removal. 155 | * Check whether ImGui Demo is shown (tests ImGui.ShowDemo console variable). 156 | * 157 | * @returns True, if demo is shown (ImGui.ShowDemo != 0) and false otherwise. 158 | */ 159 | virtual bool IsShowingDemo() const; 160 | 161 | /** 162 | * DEPRECIATED: Please use GetProperties() as this function is scheduled for removal. 163 | * Set whether to show ImGui Demo (sets ImGui.ShowDemo console variable, so it can be used together with a console). 164 | * 165 | * @param bShow - Whether to show ImGui Demo (ImGui.ShowDemo = 1) or not (ImGui.ShowDemo = 0). 166 | */ 167 | virtual void SetShowDemo(bool bShow); 168 | 169 | /** 170 | * DEPRECIATED: Please use GetProperties() as this function is scheduled for removal. 171 | * Toggle ImGui Demo (changes ImGui.ShowDemo console variable). 172 | */ 173 | virtual void ToggleShowDemo(); 174 | 175 | /** IModuleInterface implementation */ 176 | virtual void StartupModule() override; 177 | virtual void ShutdownModule() override; 178 | 179 | private: 180 | #if WITH_EDITOR 181 | virtual void SetProperties(const FImGuiModuleProperties& Properties); 182 | struct FImGuiContextHandle* ImGuiContextHandle = nullptr; 183 | struct FImGuiDelegatesContainerHandle* DelegatesContainerHandle = nullptr; 184 | friend struct FImGuiContextHandle; 185 | friend struct FImGuiDelegatesContainerHandle; 186 | #endif 187 | }; 188 | -------------------------------------------------------------------------------- /Source/ImGui/Private/ImGuiModuleManager.cpp: -------------------------------------------------------------------------------- 1 | // Distributed under the MIT License (MIT) (see accompanying LICENSE file) 2 | 3 | #include "ImGuiModuleManager.h" 4 | 5 | #include "ImGuiInteroperability.h" 6 | #include "Utilities/WorldContextIndex.h" 7 | 8 | #include 9 | #include 10 | 11 | #include 12 | 13 | 14 | // High enough z-order guarantees that ImGui output is rendered on top of the game UI. 15 | constexpr int32 IMGUI_WIDGET_Z_ORDER = 10000; 16 | 17 | // Module texture names. 18 | const static FName PlainTextureName = "ImGuiModule_Plain"; 19 | const static FName FontAtlasTextureName = "ImGuiModule_FontAtlas"; 20 | 21 | FImGuiModuleManager::FImGuiModuleManager() 22 | : Commands(Properties) 23 | , Settings(Properties, Commands) 24 | , ImGuiDemo(Properties) 25 | , ContextManager(Settings) 26 | { 27 | // Register in context manager to get information whenever a new context proxy is created. 28 | ContextManager.OnContextProxyCreated.AddRaw(this, &FImGuiModuleManager::OnContextProxyCreated); 29 | 30 | // Typically we will use viewport created events to add widget to new game viewports. 31 | ViewportCreatedHandle = UGameViewportClient::OnViewportCreated().AddRaw(this, &FImGuiModuleManager::OnViewportCreated); 32 | 33 | // Try to register tick delegate (it may fail if Slate application isn't yet ready). 34 | RegisterTick(); 35 | 36 | // If we failed to register, create an initializer that will do it later. 37 | if (!IsTickRegistered()) 38 | { 39 | CreateTickInitializer(); 40 | } 41 | 42 | // We need to add widgets to active game viewports as they won't generate on-created events. This is especially 43 | // important during hot-reloading. 44 | AddWidgetsToActiveViewports(); 45 | } 46 | 47 | FImGuiModuleManager::~FImGuiModuleManager() 48 | { 49 | ContextManager.OnFontAtlasBuilt.RemoveAll(this); 50 | 51 | // We are no longer interested with adding widgets to viewports. 52 | if (ViewportCreatedHandle.IsValid()) 53 | { 54 | UGameViewportClient::OnViewportCreated().Remove(ViewportCreatedHandle); 55 | ViewportCreatedHandle.Reset(); 56 | } 57 | 58 | // Remove still active widgets (important during hot-reloading). 59 | for (auto& Widget : Widgets) 60 | { 61 | auto SharedWidget = Widget.Pin(); 62 | if (SharedWidget.IsValid()) 63 | { 64 | auto& WidgetGameViewport = SharedWidget->GetGameViewport(); 65 | if (WidgetGameViewport.IsValid()) 66 | { 67 | WidgetGameViewport->RemoveViewportWidgetContent(SharedWidget.ToSharedRef()); 68 | } 69 | } 70 | } 71 | 72 | // Deactivate this manager. 73 | ReleaseTickInitializer(); 74 | UnregisterTick(); 75 | } 76 | 77 | void FImGuiModuleManager::RebuildFontAtlas() 78 | { 79 | ContextManager.RebuildFontAtlas(); 80 | } 81 | 82 | void FImGuiModuleManager::LoadTextures() 83 | { 84 | checkf(FSlateApplication::IsInitialized(), TEXT("Slate should be initialized before we can create textures.")); 85 | 86 | if (!bTexturesLoaded) 87 | { 88 | bTexturesLoaded = true; 89 | 90 | TextureManager.InitializeErrorTexture(FColor::Magenta); 91 | 92 | // Create an empty texture at index 0. We will use it for ImGui outputs with null texture id. 93 | TextureManager.CreatePlainTexture(PlainTextureName, 2, 2, FColor::White); 94 | 95 | // Register for atlas built events, so we can rebuild textures. 96 | ContextManager.OnFontAtlasBuilt.AddRaw(this, &FImGuiModuleManager::BuildFontAtlasTexture); 97 | 98 | BuildFontAtlasTexture(); 99 | } 100 | } 101 | 102 | void FImGuiModuleManager::BuildFontAtlasTexture() 103 | { 104 | // Create a font atlas texture. 105 | ImFontAtlas& Fonts = ContextManager.GetFontAtlas(); 106 | 107 | unsigned char* Pixels; 108 | int Width, Height, Bpp; 109 | Fonts.GetTexDataAsRGBA32(&Pixels, &Width, &Height, &Bpp); 110 | 111 | const TextureIndex FontsTexureIndex = TextureManager.CreateTexture(FontAtlasTextureName, Width, Height, Bpp, Pixels); 112 | 113 | // Set the font texture index in the ImGui. 114 | Fonts.TexID = ImGuiInterops::ToImTextureID(FontsTexureIndex); 115 | } 116 | 117 | void FImGuiModuleManager::RegisterTick() 118 | { 119 | // Slate Post-Tick is a good moment to end and advance ImGui frame as it minimises a tearing. 120 | if (!TickDelegateHandle.IsValid() && FSlateApplication::IsInitialized()) 121 | { 122 | TickDelegateHandle = FSlateApplication::Get().OnPostTick().AddRaw(this, &FImGuiModuleManager::Tick); 123 | } 124 | } 125 | 126 | void FImGuiModuleManager::UnregisterTick() 127 | { 128 | if (TickDelegateHandle.IsValid()) 129 | { 130 | if (FSlateApplication::IsInitialized()) 131 | { 132 | FSlateApplication::Get().OnPostTick().Remove(TickDelegateHandle); 133 | } 134 | TickDelegateHandle.Reset(); 135 | } 136 | } 137 | 138 | void FImGuiModuleManager::CreateTickInitializer() 139 | { 140 | if (!TickInitializerHandle.IsValid()) 141 | { 142 | // Try to register tick delegate until we finally succeed. 143 | 144 | TickInitializerHandle = FModuleManager::Get().OnModulesChanged().AddLambda([this](FName Name, EModuleChangeReason Reason) 145 | { 146 | if (Reason == EModuleChangeReason::ModuleLoaded) 147 | { 148 | RegisterTick(); 149 | } 150 | 151 | if (IsTickRegistered()) 152 | { 153 | ReleaseTickInitializer(); 154 | } 155 | }); 156 | } 157 | } 158 | 159 | void FImGuiModuleManager::ReleaseTickInitializer() 160 | { 161 | if (TickInitializerHandle.IsValid()) 162 | { 163 | FModuleManager::Get().OnModulesChanged().Remove(TickInitializerHandle); 164 | TickInitializerHandle.Reset(); 165 | } 166 | } 167 | 168 | void FImGuiModuleManager::Tick(float DeltaSeconds) 169 | { 170 | if (IsInGameThread()) 171 | { 172 | // Update context manager to advance all ImGui contexts to the next frame. 173 | ContextManager.Tick(DeltaSeconds); 174 | 175 | // Inform that we finished updating ImGui, so other subsystems can react. 176 | PostImGuiUpdateEvent.Broadcast(); 177 | } 178 | } 179 | 180 | void FImGuiModuleManager::OnViewportCreated() 181 | { 182 | checkf(FSlateApplication::IsInitialized(), TEXT("We expect Slate to be initialized when game viewport is created.")); 183 | 184 | // Create widget to viewport responsible for this event. 185 | AddWidgetToViewport(GEngine->GameViewport); 186 | } 187 | 188 | void FImGuiModuleManager::AddWidgetToViewport(UGameViewportClient* GameViewport) 189 | { 190 | checkf(GameViewport, TEXT("Null game viewport.")); 191 | checkf(FSlateApplication::IsInitialized(), TEXT("Slate should be initialized before we can add widget to game viewports.")); 192 | 193 | // Make sure that we have a context for this viewport's world and get its index. 194 | int32 ContextIndex; 195 | auto& ContextProxy = ContextManager.GetWorldContextProxy(*GameViewport->GetWorld(), ContextIndex); 196 | 197 | // Make sure that textures are loaded before the first Slate widget is created. 198 | LoadTextures(); 199 | 200 | // Create and initialize the widget. 201 | TSharedPtr SharedWidget; 202 | SAssignNew(SharedWidget, SImGuiLayout).ModuleManager(this).GameViewport(GameViewport).ContextIndex(ContextIndex); 203 | 204 | GameViewport->AddViewportWidgetContent(SharedWidget.ToSharedRef(), IMGUI_WIDGET_Z_ORDER); 205 | 206 | // We transfer widget ownerships to viewports but we keep weak references in case we need to manually detach active 207 | // widgets during module shutdown (important during hot-reloading). 208 | if (TWeakPtr* Slot = Widgets.FindByPredicate([](auto& Widget) { return !Widget.IsValid(); })) 209 | { 210 | *Slot = SharedWidget; 211 | } 212 | else 213 | { 214 | Widgets.Emplace(SharedWidget); 215 | } 216 | } 217 | 218 | void FImGuiModuleManager::AddWidgetsToActiveViewports() 219 | { 220 | if (FSlateApplication::IsInitialized() && GEngine) 221 | { 222 | // Loop as long as we have a valid viewport or until we detect a cycle. 223 | UGameViewportClient* GameViewport = GEngine->GameViewport; 224 | while (GameViewport) 225 | { 226 | AddWidgetToViewport(GameViewport); 227 | 228 | GameViewport = GEngine->GetNextPIEViewport(GameViewport); 229 | if (GameViewport == GEngine->GameViewport) 230 | { 231 | break; 232 | } 233 | } 234 | } 235 | } 236 | 237 | void FImGuiModuleManager::OnContextProxyCreated(int32 ContextIndex, FImGuiContextProxy& ContextProxy) 238 | { 239 | ContextProxy.OnDraw().AddLambda([this, ContextIndex]() { ImGuiDemo.DrawControls(ContextIndex); }); 240 | } 241 | -------------------------------------------------------------------------------- /Source/ImGui/Private/ImGuiContextProxy.cpp: -------------------------------------------------------------------------------- 1 | // Distributed under the MIT License (MIT) (see accompanying LICENSE file) 2 | 3 | #include "ImGuiContextProxy.h" 4 | 5 | #include "ImGuiDelegatesContainer.h" 6 | #include "ImGuiImplementation.h" 7 | #include "ImGuiInteroperability.h" 8 | #include "Utilities/Arrays.h" 9 | #include "VersionCompatibility.h" 10 | 11 | #include 12 | #include 13 | 14 | 15 | static constexpr float DEFAULT_CANVAS_WIDTH = 3840.f; 16 | static constexpr float DEFAULT_CANVAS_HEIGHT = 2160.f; 17 | 18 | 19 | namespace 20 | { 21 | FString GetSaveDirectory() 22 | { 23 | #if ENGINE_COMPATIBILITY_LEGACY_SAVED_DIR 24 | const FString SavedDir = FPaths::GameSavedDir(); 25 | #else 26 | const FString SavedDir = FPaths::ProjectSavedDir(); 27 | #endif 28 | 29 | FString Directory = FPaths::Combine(*SavedDir, TEXT("ImGui")); 30 | 31 | // Make sure that directory is created. 32 | IPlatformFile::GetPlatformPhysical().CreateDirectory(*Directory); 33 | 34 | return Directory; 35 | } 36 | 37 | FString GetIniFile(const FString& Name) 38 | { 39 | static FString SaveDirectory = GetSaveDirectory(); 40 | return FPaths::Combine(SaveDirectory, Name + TEXT(".ini")); 41 | } 42 | 43 | struct FGuardCurrentContext 44 | { 45 | FGuardCurrentContext() 46 | : OldContext(ImGui::GetCurrentContext()) 47 | { 48 | } 49 | 50 | ~FGuardCurrentContext() 51 | { 52 | if (bRestore) 53 | { 54 | ImGui::SetCurrentContext(OldContext); 55 | } 56 | } 57 | 58 | FGuardCurrentContext(FGuardCurrentContext&& Other) 59 | : OldContext(MoveTemp(Other.OldContext)) 60 | { 61 | Other.bRestore = false; 62 | } 63 | 64 | FGuardCurrentContext& operator=(FGuardCurrentContext&&) = delete; 65 | 66 | FGuardCurrentContext(const FGuardCurrentContext&) = delete; 67 | FGuardCurrentContext& operator=(const FGuardCurrentContext&) = delete; 68 | 69 | private: 70 | 71 | ImGuiContext* OldContext = nullptr; 72 | bool bRestore = true; 73 | }; 74 | } 75 | 76 | FImGuiContextProxy::FImGuiContextProxy(const FString& InName, int32 InContextIndex, ImFontAtlas* InFontAtlas, float InDPIScale) 77 | : Name(InName) 78 | , ContextIndex(InContextIndex) 79 | , IniFilename(TCHAR_TO_ANSI(*GetIniFile(InName))) 80 | { 81 | // Create context. 82 | Context = ImGui::CreateContext(InFontAtlas); 83 | 84 | // Set this context in ImGui for initialization (any allocations will be tracked in this context). 85 | SetAsCurrent(); 86 | 87 | // Start initialization. 88 | ImGuiIO& IO = ImGui::GetIO(); 89 | 90 | // Set session data storage. 91 | IO.IniFilename = IniFilename.c_str(); 92 | 93 | // Start with the default canvas size. 94 | ResetDisplaySize(); 95 | IO.DisplaySize = {(float)DisplaySize.X, (float)DisplaySize.Y}; 96 | 97 | // Set the initial DPI scale. 98 | SetDPIScale(InDPIScale); 99 | 100 | // Initialize key mapping, so context can correctly interpret input state. 101 | ImGuiInterops::SetUnrealKeyMap(IO); 102 | 103 | // Begin frame to complete context initialization (this is to avoid problems with other systems calling to ImGui 104 | // during startup). 105 | BeginFrame(); 106 | } 107 | 108 | FImGuiContextProxy::~FImGuiContextProxy() 109 | { 110 | if (Context) 111 | { 112 | // It seems that to properly shutdown context we need to set it as the current one (at least in this framework 113 | // version), even though we can pass it to the destroy function. 114 | SetAsCurrent(); 115 | 116 | // Save context data and destroy. 117 | ImGui::DestroyContext(Context); 118 | } 119 | } 120 | 121 | void FImGuiContextProxy::ResetDisplaySize() 122 | { 123 | DisplaySize = { DEFAULT_CANVAS_WIDTH, DEFAULT_CANVAS_HEIGHT }; 124 | } 125 | 126 | void FImGuiContextProxy::SetDPIScale(float Scale) 127 | { 128 | if (DPIScale != Scale) 129 | { 130 | DPIScale = Scale; 131 | 132 | ImGuiStyle NewStyle = ImGuiStyle(); 133 | NewStyle.ScaleAllSizes(Scale); 134 | 135 | FGuardCurrentContext GuardContext; 136 | SetAsCurrent(); 137 | ImGui::GetStyle() = MoveTemp(NewStyle); 138 | } 139 | } 140 | 141 | void FImGuiContextProxy::DrawEarlyDebug() 142 | { 143 | if (bIsFrameStarted && !bIsDrawEarlyDebugCalled) 144 | { 145 | bIsDrawEarlyDebugCalled = true; 146 | 147 | SetAsCurrent(); 148 | 149 | // Delegates called in order specified in FImGuiDelegates. 150 | BroadcastMultiContextEarlyDebug(); 151 | BroadcastWorldEarlyDebug(); 152 | } 153 | } 154 | 155 | void FImGuiContextProxy::DrawDebug() 156 | { 157 | if (bIsFrameStarted && !bIsDrawDebugCalled) 158 | { 159 | bIsDrawDebugCalled = true; 160 | 161 | // Make sure that early debug is always called first to guarantee order specified in FImGuiDelegates. 162 | DrawEarlyDebug(); 163 | 164 | SetAsCurrent(); 165 | 166 | // Delegates called in order specified in FImGuiDelegates. 167 | BroadcastWorldDebug(); 168 | BroadcastMultiContextDebug(); 169 | } 170 | } 171 | 172 | void FImGuiContextProxy::Tick(float DeltaSeconds) 173 | { 174 | // Making sure that we tick only once per frame. 175 | if (LastFrameNumber < GFrameNumber) 176 | { 177 | LastFrameNumber = GFrameNumber; 178 | 179 | SetAsCurrent(); 180 | 181 | if (bIsFrameStarted) 182 | { 183 | // Make sure that draw events are called before the end of the frame. 184 | DrawDebug(); 185 | 186 | // Ending frame will produce render output that we capture and store for later use. This also puts context to 187 | // state in which it does not allow to draw controls, so we want to immediately start a new frame. 188 | EndFrame(); 189 | } 190 | 191 | // Update context information (some data need to be collected before starting a new frame while some other data 192 | // may need to be collected after). 193 | bHasActiveItem = ImGui::IsAnyItemActive(); 194 | MouseCursor = ImGuiInterops::ToSlateMouseCursor(ImGui::GetMouseCursor()); 195 | 196 | // Begin a new frame and set the context back to a state in which it allows to draw controls. 197 | BeginFrame(DeltaSeconds); 198 | 199 | // Update remaining context information. 200 | bWantsMouseCapture = ImGui::GetIO().WantCaptureMouse; 201 | } 202 | } 203 | 204 | void FImGuiContextProxy::BeginFrame(float DeltaTime) 205 | { 206 | if (!bIsFrameStarted) 207 | { 208 | ImGuiIO& IO = ImGui::GetIO(); 209 | IO.DeltaTime = DeltaTime; 210 | 211 | ImGuiInterops::CopyInput(IO, InputState); 212 | InputState.ClearUpdateState(); 213 | 214 | IO.DisplaySize = { (float)DisplaySize.X, (float)DisplaySize.Y }; 215 | 216 | ImGui::NewFrame(); 217 | 218 | bIsFrameStarted = true; 219 | bIsDrawEarlyDebugCalled = false; 220 | bIsDrawDebugCalled = false; 221 | } 222 | } 223 | 224 | void FImGuiContextProxy::EndFrame() 225 | { 226 | if (bIsFrameStarted) 227 | { 228 | // Prepare draw data (after this call we cannot draw to this context until we start a new frame). 229 | ImGui::Render(); 230 | 231 | // Update our draw data, so we can use them later during Slate rendering while ImGui is in the middle of the 232 | // next frame. 233 | UpdateDrawData(ImGui::GetDrawData()); 234 | 235 | bIsFrameStarted = false; 236 | } 237 | } 238 | 239 | void FImGuiContextProxy::UpdateDrawData(ImDrawData* DrawData) 240 | { 241 | if (DrawData && DrawData->CmdListsCount > 0) 242 | { 243 | DrawLists.SetNum(DrawData->CmdListsCount, false); 244 | 245 | for (int Index = 0; Index < DrawData->CmdListsCount; Index++) 246 | { 247 | DrawLists[Index].TransferDrawData(*DrawData->CmdLists[Index]); 248 | } 249 | } 250 | else 251 | { 252 | // If we are not rendering then this might be a good moment to empty the array. 253 | DrawLists.Empty(); 254 | } 255 | } 256 | 257 | void FImGuiContextProxy::BroadcastWorldEarlyDebug() 258 | { 259 | if (ContextIndex != Utilities::INVALID_CONTEXT_INDEX) 260 | { 261 | FSimpleMulticastDelegate& WorldEarlyDebugEvent = FImGuiDelegatesContainer::Get().OnWorldEarlyDebug(ContextIndex); 262 | if (WorldEarlyDebugEvent.IsBound()) 263 | { 264 | WorldEarlyDebugEvent.Broadcast(); 265 | } 266 | } 267 | } 268 | 269 | void FImGuiContextProxy::BroadcastMultiContextEarlyDebug() 270 | { 271 | FSimpleMulticastDelegate& MultiContextEarlyDebugEvent = FImGuiDelegatesContainer::Get().OnMultiContextEarlyDebug(); 272 | if (MultiContextEarlyDebugEvent.IsBound()) 273 | { 274 | MultiContextEarlyDebugEvent.Broadcast(); 275 | } 276 | } 277 | 278 | void FImGuiContextProxy::BroadcastWorldDebug() 279 | { 280 | if (DrawEvent.IsBound()) 281 | { 282 | DrawEvent.Broadcast(); 283 | } 284 | 285 | if (ContextIndex != Utilities::INVALID_CONTEXT_INDEX) 286 | { 287 | FSimpleMulticastDelegate& WorldDebugEvent = FImGuiDelegatesContainer::Get().OnWorldDebug(ContextIndex); 288 | if (WorldDebugEvent.IsBound()) 289 | { 290 | WorldDebugEvent.Broadcast(); 291 | } 292 | } 293 | } 294 | 295 | void FImGuiContextProxy::BroadcastMultiContextDebug() 296 | { 297 | FSimpleMulticastDelegate& MultiContextDebugEvent = FImGuiDelegatesContainer::Get().OnMultiContextDebug(); 298 | if (MultiContextDebugEvent.IsBound()) 299 | { 300 | MultiContextDebugEvent.Broadcast(); 301 | } 302 | } 303 | -------------------------------------------------------------------------------- /CHANGES.md: -------------------------------------------------------------------------------- 1 | This is only a summary provided to give a quick overview of changes. It does not list details which can be found in commit messages. If you think that more detailed changelog would be beneficiary, please raise it as an issue. 2 | 3 | Versions marked as 'unofficial' are labelled only for the needs of this changelog. Officially I maintain version numbers since 2019/04, starting from version 1.14. If you have any of the earlier commits then you will see plugin signed as a version 1.0. 4 | 5 | Change History 6 | -------------- 7 | 8 | Version: 1.22 (2021/04) 9 | - Fixed potential for initialization fiasco when using delegates container. 10 | - Fixed bug in code protecting redirecting handles from self-referencing. 11 | - Fixed cached resource handles getting invalid after reloading texture resources. 12 | 13 | Version: 1.21 (2020/07-09) 14 | Improving stability 15 | - Fixed a crash in the input handler caused by invalidated by hot-reload instance trying to unregister a delegate. 16 | - Improved hot-reload stability and support for reloading after recompiling outside of the editor. Both methods should be equally supported and work together. 17 | - Improved behaviour of delegates when hot-reloading. 18 | - Changed context index mapping to fix issues with multi-PIE debugging in 4.25. 19 | - Fixed Linux crash caused by wrong mapping of key codes. 20 | 21 | Version: 1.20 (2020/06) 22 | Transition to IWYU and maintenance: 23 | - Replaced includes of monolithic headers. 24 | - Removed explicit PCH and switched to IWYU-style PCH model. 25 | - Fixed includes to compile without explicit PCH in non-unity mode. 26 | - Fixed a few issues causing compilation errors in older engine versions. 27 | - Fixed debug code to compile on platforms using other than char or wchar_t characters. 28 | - Fixed issues in recently added DPI scaling. 29 | - Cleaned obsolete and unused code. 30 | - Replaced custom scope guards with the template provided by the engine. 31 | 32 | Version: 1.19 (2020/03-06) 33 | - Integrated fix for issue with ImGui popup/modal windows not being able to be closed in transparent mouse input mode. 34 | - Integrated first version of Adaptive Canvas Size. 35 | - Added different options to define canvas size, with Adaptive Canvas Size being one of the options (viewport). 36 | - Added option for DPI scaling. 37 | 38 | Version: 1.18 (2020/01) 39 | - Updated to engine version 4.24. 40 | - Updated to ImGui version 1.74. 41 | 42 | Version: 1.17 (2019/04) 43 | - Added experimental support for touch input. 44 | - Integrated fixes allowing to build this as an engine plugin: 45 | - Added support for sharing with game mouse input. 46 | - Refactorization of input handling, with changes in SImGuiWidget and compatibility breaking changes in UImGuiInputHandler. 47 | 48 | Version: 1.16 (2019/05) 49 | - Fixed issue with SImGuiLayout blocking mouse input for other Slate widgets, which was introduced by refactorization of widgets (version 1.14, commit c144658f). 50 | 51 | Version: 1.15 (2019/04) 52 | - Added new FImGuiDelegates interface for ImGui debug delegates. 53 | - Added code preserving delegates during hot-reloading and moving them to a new module. 54 | - DEPRECIATED old FImGuiModule delegates interface and FImGuiDelegateHandle. 55 | - Delegates registered with depreciated interface are redirected and get benefit of being preserved during hot-reloading. This can be controlled with IMGUI_REDIRECT_OBSOLETE_DELEGATES. 56 | - Added IMGUI_WITH_OBSOLETE_DELEGATES allowing to strip depreciated interface from builds (that interface will be officially removed in one of later releases). 57 | - Added new ImGui early debug delegates called during world tick start. 58 | - Delegates are called in fixed order: multi-context early debug, world early debug (called during world tick start), world debug, multi-context debug (called during world post actor tick or if not available, during world tick start). 59 | - Removed from build script configuration of debug delegates. 60 | 61 | Version: 1.14 (2019/03) 62 | - Added SImGuiLayout to resets layout for SImGuiWidget. 63 | - Refactored rendering in SImGuiWidget to take advantage of layout reset. 64 | - Reworked ImGui canvas dragging and scaling and moved it to SImGuiCanvasControl. 65 | - Removed dependency on ImGui internal cursor data. 66 | 67 | Version: 1.13 (unofficial) (2019/03) 68 | - Fixed mapping from FKey to ImGui key index to gracefully handle unsupported keys and work on platforms that do not support all the keys defined in ImGui key map. 69 | - Fixed non-unity compile warnings and errors. 70 | 71 | Version: 1.12 (unofficial) (2018/12) 72 | - Added support for sharing with game keyboard and gamepad input. 73 | - Added FImGuiModuleSettings to handle delayed loading of UImGuiSettings and serve as settings proxy for other classes. 74 | 75 | Version: 1.11 (unofficial) (2018/10-11) 76 | - Moved ImGui Draw events to be called at the end of the world update during post actor tick event. Only available in UE 4.18 or later, with old behaviour available as an option. 77 | - Replaced console variable based configuration of ImGui Draw events with macros. 78 | - Replaced console variable based configuration of software cursor with a setting. 79 | - Console variables and logging that are primarily focused on module development are hidden by default and can be enabled by setting IMGUI_MODULE_DEVELOPER to 1. 80 | - Replaced console variables with module properties and settings. 81 | - Added console commands to control module properties. 82 | - Added support to preserve and move module properties to hot-reloaded module. 83 | - Moved properties to public interface. 84 | - Added FImGuiModule interface to access properties instance. 85 | - DEPRECIATED FImGuiModule functions to modify single properties. 86 | 87 | Version: 1.10 (unofficial) (2018/10) 88 | - Changed module type to 'Developer' to make it easier strip it from shipping or other builds. 89 | - Added runtime loader to allow automatically load developer module in runtime builds. 90 | 91 | Version: 1.09 (unofficial) (2018/08-09) 92 | - Added interface to register user textures for use in ImGui. 93 | - Fixed bad deallocation in Texture Manager. 94 | - Updated to ImGui 1.61. 95 | - Updated to UE 4.20. 96 | 97 | Version: 1.08 (unofficial) (2018/07-08) 98 | - Added ImGui Input Handler to allow to customization of input handling. 99 | - Added ImGui settings with editor page in project properties. 100 | - Added command to switch input mode with configurable key binding. 101 | - Added backward compatibility macros. 102 | - Fixed hot-reloading issues with using ImGui implementation. 103 | 104 | Version: 1.07 (unofficial) (2018/05) 105 | - Improved initialization to allow loading module in any loading phase. 106 | 107 | Version: 1.06 (unofficial) (2018/05) 108 | - Updated to ImGui 1.61 109 | - Added support for gamepad and keyboard navigation. 110 | 111 | Version: 1.05 (unofficial) (2018/04) 112 | - Added mode to scale and drag ImGui canvas. 113 | - Using ImGui internal cursor data to draw drag icon. 114 | 115 | Version: 1.04 (unofficial) (2018/03) 116 | - Minimised lag between ending ImGui frame and rendering draw data in Slate. 117 | - Moved ImGui Draw event to be called during world tick start with configuration to use old behaviour. 118 | 119 | Version: 1.03 (unofficial) (2018/01-03) 120 | - Fixed warnings and errors found in non-unity, Linux, PS4 or XBox builds. 121 | - Added configuration to choose between hardware and software cursor with hardware cursor used by default. 122 | 123 | Version: 1.02 (unofficial) (2018/01) 124 | - Updated to ImGui 1.53. 125 | - Fixed problems with ImGui Demo working in multi-context environment. 126 | - Added FImGuiModule interface to change input mode and demo visibility. 127 | - Fixed input state issues after application loses focus. 128 | - Added input state debugging and `ImGui.Debug.Input` console variable to switch it. 129 | 130 | Version: 1.01 (unofficial) (2017/10) 131 | - Added `ImGui.ShowDemo` console variable to show/hide ImGui demo. 132 | - Added automatic switching to right ImGui context at the beginning of the world tick. 133 | - Updated to UE 4.18 134 | 135 | Version: <=1.00 (unofficial) (2017/04-10) 136 | - Added ImGui source code as an external module to expose it in IDE. 137 | - Integrated ImGui source code to build as part of the ImGui module. 138 | - Added FImGuiModule to implement ImGui module interface. 139 | - Added FImGuiModuleManager to control other module components. 140 | - Added FTextureManager to manage texture resources and map them to ImTextureID. 141 | - Added SImGuiWidget to handle Slate input and render in Slate ImGui draw data. 142 | - Added FImGuiInputState to collect and store input before it can be copied to ImGui IO. 143 | - Added FContextProxy to represent a single ImGui context. 144 | - Added FImGuiContextManager to create and manage ImGui context proxies. 145 | - Added Multi-PIE support with each PIE instance getting a dedicated ImGui context proxy, input state and widget. 146 | - Added `ImGui.InputEnabled` console variable to control whether input mode is enabled. 147 | - Added widget debugging and `ImGui.Debug.Widget` console variable to switch it. 148 | - Added ImGui software cursor. 149 | - Added support for session reloading with ini file names based on world type and PIE index. 150 | - Added FImGuiModule interface to register ImGui delegates called to draw ImGui controls. 151 | -------------------------------------------------------------------------------- /Source/ThirdParty/ImGuiLibrary/Docs/BACKENDS.md: -------------------------------------------------------------------------------- 1 | _(You may browse this at https://github.com/ocornut/imgui/blob/master/docs/BACKENDS.md or view this file with any Markdown viewer)_ 2 | 3 | ## Dear ImGui: Backends 4 | 5 | **The backends/ folder contains backends for popular platforms/graphics API, which you can use in 6 | your application or engine to easily integrate Dear ImGui.** Each backend is typically self-contained in a pair of files: imgui_impl_XXXX.cpp + imgui_impl_XXXX.h. 7 | 8 | - The 'Platform' backends are in charge of: mouse/keyboard/gamepad inputs, cursor shape, timing, windowing.
9 | e.g. Windows ([imgui_impl_win32.cpp](https://github.com/ocornut/imgui/blob/master/backends/imgui_impl_win32.cpp)), GLFW ([imgui_impl_glfw.cpp](https://github.com/ocornut/imgui/blob/master/backends/imgui_impl_glfw.cpp)), SDL2 ([imgui_impl_sdl.cpp](https://github.com/ocornut/imgui/blob/master/backends/imgui_impl_sdl.cpp)), etc. 10 | 11 | - The 'Renderer' backends are in charge of: creating atlas texture, rendering imgui draw data.
12 | e.g. DirectX11 ([imgui_impl_dx11.cpp](https://github.com/ocornut/imgui/blob/master/backends/imgui_impl_dx11.cpp)), OpenGL/WebGL ([imgui_impl_opengl3.cpp](https://github.com/ocornut/imgui/blob/master/backends/imgui_impl_opengl3.cpp)), Vulkan ([imgui_impl_vulkan.cpp](https://github.com/ocornut/imgui/blob/master/backends/imgui_impl_vulkan.cpp)), etc. 13 | 14 | - For some high-level frameworks, a single backend usually handle both 'Platform' and 'Renderer' parts.
15 | e.g. Allegro 5 ([imgui_impl_allegro5.cpp](https://github.com/ocornut/imgui/blob/master/backends/imgui_impl_allegro5.cpp)). If you end up creating a custom backend for your engine, you may want to do the same. 16 | 17 | An application usually combines 1 Platform backend + 1 Renderer backend + main Dear ImGui sources. 18 | For example, the [example_win32_directx11](https://github.com/ocornut/imgui/tree/master/examples/example_win32_directx11) application combines imgui_impl_win32.cpp + imgui_impl_dx11.cpp. There are 20+ examples in the [examples/](https://github.com/ocornut/imgui/blob/master/examples/) folder. See [EXAMPLES.MD](https://github.com/ocornut/imgui/blob/master/docs/EXAMPLES.md) for details. 19 | 20 | **Once Dear ImGui is setup and running, run and refer to `ImGui::ShowDemoWindow()` in imgui_demo.cpp for usage of the end-user API.** 21 | 22 | 23 | ### What are backends 24 | 25 | Dear ImGui is highly portable and only requires a few things to run and render, typically: 26 | 27 | - Required: providing mouse/keyboard inputs (fed into the `ImGuiIO` structure). 28 | - Required: uploading the font atlas texture into graphics memory. 29 | - Required: rendering indexed textured triangles with a clipping rectangle. 30 | 31 | Extra features are opt-in, our backends try to support as many as possible: 32 | 33 | - Optional: custom texture binding support. 34 | - Optional: clipboard support. 35 | - Optional: gamepad support. 36 | - Optional: mouse cursor shape support. 37 | - Optional: IME support. 38 | - Optional: multi-viewports support. 39 | etc. 40 | 41 | This is essentially what each backend is doing + obligatory portability cruft. Using default backends ensure you can get all those features including the ones that would be harder to implement on your side (e.g. multi-viewports support). 42 | 43 | It is important to understand the difference between the core Dear ImGui library (files in the root folder) 44 | and backends which we are describing here (backends/ folder). 45 | 46 | - Some issues may only be backend or platform specific. 47 | - You should be able to write backends for pretty much any platform and any 3D graphics API. 48 | e.g. you can get creative and use software rendering or render remotely on a different machine. 49 | 50 | 51 | ### Integrating a backend 52 | 53 | See "Getting Started" section of [EXAMPLES.MD](https://github.com/ocornut/imgui/blob/master/docs/EXAMPLES.md) for more details. 54 | 55 | 56 | ### List of backends 57 | 58 | In the [backends/](https://github.com/ocornut/imgui/blob/master/backends) folder: 59 | 60 | List of Platforms Backends: 61 | 62 | imgui_impl_android.cpp ; Android native app API 63 | imgui_impl_glfw.cpp ; GLFW (Windows, macOS, Linux, etc.) http://www.glfw.org/ 64 | imgui_impl_osx.mm ; macOS native API (not as feature complete as glfw/sdl backends) 65 | imgui_impl_sdl.cpp ; SDL2 (Windows, macOS, Linux, iOS, Android) https://www.libsdl.org 66 | imgui_impl_win32.cpp ; Win32 native API (Windows) 67 | imgui_impl_glut.cpp ; GLUT/FreeGLUT (this is prehistoric software and absolutely not recommended today!) 68 | 69 | List of Renderer Backends: 70 | 71 | imgui_impl_dx9.cpp ; DirectX9 72 | imgui_impl_dx10.cpp ; DirectX10 73 | imgui_impl_dx11.cpp ; DirectX11 74 | imgui_impl_dx12.cpp ; DirectX12 75 | imgui_impl_metal.mm ; Metal (with ObjC) 76 | imgui_impl_opengl2.cpp ; OpenGL 2 (legacy, fixed pipeline <- don't use with modern OpenGL context) 77 | imgui_impl_opengl3.cpp ; OpenGL 3/4, OpenGL ES 2, OpenGL ES 3 (modern programmable pipeline) 78 | imgui_impl_sdlrenderer.cpp; SDL_Renderer (optional component of SDL2 available from SDL 2.0.18+) 79 | imgui_impl_vulkan.cpp ; Vulkan 80 | imgui_impl_wgpu.cpp ; WebGPU 81 | 82 | List of high-level Frameworks Backends (combining Platform + Renderer): 83 | 84 | imgui_impl_allegro5.cpp 85 | 86 | Emscripten is also supported. 87 | The [example_emscripten_opengl3](https://github.com/ocornut/imgui/tree/master/examples/example_emscripten_opengl3) app uses imgui_impl_sdl.cpp + imgui_impl_opengl3.cpp, but other combos are possible. 88 | 89 | ### Backends for third-party frameworks, graphics API or other languages 90 | 91 | See https://github.com/ocornut/imgui/wiki/Bindings for the full list (e.g. Adventure Game Studio, Cinder, Cocos2d-x, Game Maker Studio2, Godot, LÖVE+LUA, Magnum, Monogame, Ogre, openFrameworks, OpenSceneGraph, SFML, Sokol, Unity, Unreal Engine and many others). 92 | 93 | ### Recommended Backends 94 | 95 | If you are not sure which backend to use, the recommended platform/frameworks for portable applications: 96 | 97 | |Library |Website |Backend |Note | 98 | |--------|--------|--------|-----| 99 | | GLFW | https://github.com/glfw/glfw | imgui_impl_glfw.cpp | | 100 | | SDL2 | https://www.libsdl.org | imgui_impl_sdl.cpp | | 101 | | Sokol | https://github.com/floooh/sokol | [util/sokol_imgui.h](https://github.com/floooh/sokol/blob/master/util/sokol_imgui.h) | Lower-level than GLFW/SDL | 102 | 103 | 104 | ### Using a custom engine? 105 | 106 | You will likely be tempted to start by rewrite your own backend using your own custom/high-level facilities...
107 | Think twice! 108 | 109 | If you are new to Dear ImGui, first try using the existing backends as-is. 110 | You will save lots of time integrating the library. 111 | You can LATER decide to rewrite yourself a custom backend if you really need to. 112 | In most situations, custom backends have less features and more bugs than the standard backends we provide. 113 | If you want portability, you can use multiple backends and choose between them either at compile time 114 | or at runtime. 115 | 116 | **Example A**: your engine is built over Windows + DirectX11 but you have your own high-level rendering 117 | system layered over DirectX11.
118 | Suggestion: try using imgui_impl_win32.cpp + imgui_impl_dx11.cpp first. 119 | Once it works, if you really need it you can replace the imgui_impl_dx11.cpp code with a 120 | custom renderer using your own rendering functions, and keep using the standard Win32 code etc. 121 | 122 | **Example B**: your engine runs on Windows, Mac, Linux and uses DirectX11, Metal, Vulkan respectively.
123 | Suggestion: use multiple generic backends! 124 | Once it works, if you really need it you can replace parts of backends with your own abstractions. 125 | 126 | **Example C**: your engine runs on platforms we can't provide public backends for (e.g. PS4/PS5, Switch), 127 | and you have high-level systems everywhere.
128 | Suggestion: try using a non-portable backend first (e.g. win32 + underlying graphics API) to get 129 | your desktop builds working first. This will get you running faster and get your acquainted with 130 | how Dear ImGui works and is setup. You can then rewrite a custom backend using your own engine API... 131 | 132 | Generally: 133 | It is unlikely you will add value to your project by creating your own backend. 134 | 135 | Also: 136 | The [multi-viewports feature](https://github.com/ocornut/imgui/issues/1542) of the 'docking' branch allows 137 | Dear ImGui windows to be seamlessly detached from the main application window. This is achieved using an 138 | extra layer to the Platform and Renderer backends, which allows Dear ImGui to communicate platform-specific 139 | requests such as: "create an additional OS window", "create a render context", "get the OS position of this 140 | window" etc. See 'ImGuiPlatformIO' for details. 141 | Supporting the multi-viewports feature correctly using 100% of your own abstractions is more difficult 142 | than supporting single-viewport. 143 | If you decide to use unmodified imgui_impl_XXXX.cpp files, you can automatically benefit from 144 | improvements and fixes related to viewports and platform windows without extra work on your side. 145 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | NOTICE 2 | ====== 3 | 4 | This branch is no longer maintained, I would pick a different branch. 5 | 6 | 7 | Unreal ImGui 8 | ============ 9 | [![MIT licensed](https://img.shields.io/badge/license-MIT-blue.svg)](LICENSE.md) 10 | 11 | Unreal ImGui is an Unreal Engine 4 plug-in that integrates [Dear ImGui](https://github.com/ocornut/imgui) developed by Omar Cornut. 12 | 13 | Dear ImGui is an immediate-mode graphical user interface library that is very lightweight and easy to use. It can be very useful when creating debugging tools. 14 | 15 | :stop_button: Read Me First 16 | --------------------------- 17 | Please note that this is a forked project from [https://github.com/segross/UnrealImGui](https://github.com/segross/UnrealImGui). I do not take credit for the work he's put into making Dear ImGui work in Unreal Engine. The work I've done to this fork is listed below. 18 | 19 | I've removed large portions of this readme.md to keep redundant information between the base project and this fork to a minimum. If you wish to read the original readme.md, please see this link: [UnrealImGui ReadMe.md](https://github.com/segross/UnrealImGui/blob/master/README.md). 20 | 21 | Also note that the NetImGui branch is not up to date with any of this fork's changes. 22 | 23 | Fork Additions/Fixes 24 | -------------------- 25 | - Updated core source files for Unreal Engine 5. 26 | - Updated Dear ImGui to 1.87. 27 | - Added ImPlot v0.13 WIP. 28 | - `ImGui::IsKey*` now functional with all known ImGui keys. 29 | - Updated input handling flow to be [standard compliant](https://github.com/ocornut/imgui/issues/4921) with Dear ImGui 1.87 which makes ImGui react better at low FPS. Will add `IMGUI_DISABLE_OBSOLETE_KEYIO` preprocessor once I've ripped out old style input. 30 | - Allowed `UTexture` for Texture Manager so render targets can also be rendered to quads rather than just being limited to using `UTexture2D` instances. 31 | - Added the ability to instruct ImGui context to build custom fonts (like FontAwesome). 32 | 33 | Status 34 | ------ 35 | UnrealImGui Version: 1.22 36 | 37 | ImGui version: 1.87 38 | 39 | ImPlot version: v0.13 WIP 40 | 41 | Supported Unreal Engine version: 5.0* 42 | 43 | \* *The original repository has support for later versions of UE4. I've not tested this fork on UE4 variants, I only know it works for UE5 currently.* 44 | 45 | How to Set up 46 | ------------- 47 | On top of reading the base repository's [How to Set up](https://github.com/segross/UnrealImGui/blob/master/README.md#how-to-set-up) segment, you'll need to add the following line to your `[GameName].Build.cs` file otherwise you'll get linking errors: 48 | 49 | ```cpp 50 | // Tell the compiler we want to import the ImPlot symbols when linking against ImGui plugin 51 | PrivateDefinitions.Add(string.Format("IMPLOT_API=DLLIMPORT")); 52 | ``` 53 | 54 | # Additional Knowledge 55 | 56 | ## Using ImPlot 57 | 58 | It's pretty easy to use ImPlot, it's pretty much the same drill as using Dear ImGui with the UnrealImGui plugin. You can see documentation on how to use ImPlot here: [ImPlot](https://github.com/epezent/implot). 59 | 60 | The only thing you won't need to do is call the `ImPlot::CreateContext()` and `ImPlot::DestroyContext` routines as they're already called when ImGui's context is created within UnrealImGui's guts. 61 | 62 | ## Drawing a UTextureRenderTarget2D 63 | 64 | One might want to render viewports into the world in an ImGui window. You can do this pretty simply by generating a `UTextureRenderTarget2D` then assigning that to a `ASceneCapture2D` actor in your world. Here's some sample code for generating an correctly managing the `UTextureRenderTarget2D`: 65 | ```cpp 66 | void Init() 67 | { 68 | TextureRenderTarget = NewObject(); 69 | if(IsValid(TextureRenderTarget)) 70 | { 71 | TextureRenderTarget->InitAutoFormat(512, 512); 72 | TextureRenderTarget->UpdateResourceImmediate(true); 73 | } 74 | 75 | // ... Generate a unique TextureName here 76 | // Register this render target as an ImGui interop handled texture 77 | ImGuiTextureHandle = FImGuiModule::Get().FindTextureHandle(TextureName); 78 | if(!ImGuiTextureHandle.IsValid()) 79 | { 80 | if(IsValid(TextureRenderTarget)) 81 | { 82 | ImGuiTextureHandle = FImGuiModule::Get().RegisterTexture(TextureName, TextureRenderTarget, true); 83 | } 84 | } 85 | } 86 | 87 | ~Class() 88 | { 89 | // Requires releasing to avoid memory leak 90 | FImGuiModule::Get().ReleaseTexture(ImGuiTextureHandle); 91 | } 92 | 93 | void Render() 94 | { 95 | // Actually submit the draw command to ImGui to render the quad with the texture 96 | if(ImGuiTextureHandle.IsValid()) 97 | { 98 | ImGui::Image(ImGuiTextureHandle.GetTextureId(), {512.f, 512.f}); 99 | } 100 | } 101 | ``` 102 | 103 | Then generating the `ASceneCapture2D`: 104 | ```cpp 105 | void Init() 106 | { 107 | FActorSpawnParameters SpawnInfo; 108 | SceneCapture2D = World->SpawnActor(FVector::ZeroVector, FRotator::ZeroRotator, SpawnInfo); 109 | SceneCaptureComponent2D->TextureTarget = TextureRenderTarget; 110 | SceneCaptureComponent2D->UpdateContent(); 111 | 112 | // Need to use this in order to force capture to use tone curve and also set alpha to scene alpha (1) 113 | SceneCaptureComponent2D->CaptureSource = ESceneCaptureSource::SCS_FinalToneCurveHDR; 114 | } 115 | ``` 116 | 117 | ### Troubleshooting 118 | If you're using a scene capture and your quad is not drawing at all, make sure your scene capture "Capture Source" is set to "Final Color (with tone curve) in Linear sRGB gamut" to avoid alpha being set to 0 (since there's no way to instruct ImGui to ignore alpha without modding the core UnrealImGui plugin). 119 | 120 | If you're getting crashes or seg faults during rendering, make sure you're using `UPROPERTY()` on your class variables! 121 | 122 | ## Adding custom fonts 123 | ### FontAwesome 124 | Adding custom fonts is fairly simple. As a more complex and more commonly done, we're going to embed and build FontAwesome 6 into the font atlas. First thing you'll need is a binary C version of the FontAwesome font along with the necessary [companion descriptors](https://github.com/juliettef/IconFontCppHeaders/blob/main/IconsFontAwesome6.h). The descriptors are pre-generated, however if you have a new version of FA you wish to use, then use the Python script in that repository. As for the binary C, you'll need to compile Dear ImGui's [binary_to_compressed_c.cpp](https://github.com/ocornut/imgui/blob/master/misc/fonts/binary_to_compressed_c.cpp). 125 | 126 | Once you have the necessary files, you'll need to encode your FontAwesome font using the command: 127 | ``` 128 | binary_to_compressed_c.exe -nocompress fa-solid-900.ttf FontAwesomeFont > FontAwesomeFont.h 129 | ``` 130 | The only mandatory field here is `-nocompress` as this instructs the encoder to create an uncompressed binary file (1:1) since currently there's no immediate support for compressed fonts. 131 | 132 | Move over your descriptors and your binary C font file to an appropriate location for inclusion in your Unreal Engine project. The following code is how to instruct ImGui to build the font atlas with your FontAwesome font: 133 | 134 | ```cpp 135 | #include "FontAwesomeFont.h" 136 | #include "IconsFontAwesome6.h" 137 | 138 | // Add FontAwesome font glyphs from memory 139 | if(TSharedPtr FAFontConfig = MakeShareable(new ImFontConfig())) 140 | { 141 | static const ImWchar IconRange[] = { ICON_MIN_FA, ICON_MAX_FA, 0 }; 142 | 143 | FAFontConfig->FontDataOwnedByAtlas = false; // Global font data lifetime 144 | FAFontConfig->FontData = (void*)FontAwesomeData; // Declared in binary C .h file 145 | FAFontConfig->FontDataSize = FontAwesomeSize; // Declared in binary C .h file 146 | FAFontConfig->SizePixels = 16; 147 | FAFontConfig->MergeMode = true; // Forces ImGui to place this font into the same atlas as the previous font 148 | FAFontConfig->GlyphRanges = IconRange; // Required; instructs ImGui to use these glyphs 149 | FAFontConfig->GlyphMinAdvanceX = 16.f; // Use for monospaced icons 150 | FAFontConfig->PixelSnapH = true; // Better rendering (align to pixel grid) 151 | FAFontConfig->GlyphOffset = {0, 3}; // Moves icons around, for alignment with general typesets 152 | 153 | FImGuiModule::Get().GetProperties().AddCustomFont("FontAwesome", FAFontConfig); 154 | FImGuiModule::Get().RebuildFontAtlas(); 155 | } 156 | ``` 157 | 158 | That's it. Make sure you execute the above code once at the beginning of the first ImGui frame (or at any point of your framework where the ImGui context has been initialized correctly) and it should build the main atlas with FontAwesome inside it. ImFontConfig lifetime is currently managed via reference counting (`TSharedPtr`). 159 | 160 | ### Using the icons 161 | ```cpp 162 | #include "IconsFontAwesome6.h" 163 | 164 | void OnPaint() 165 | { 166 | ImGui::Text(ICON_FA_AWARD); 167 | } 168 | ``` 169 | 170 | Pretty simple. Building FStrings that incorporate FontAwesome icons however gets a little trickier: 171 | ```cpp 172 | FString Str = "Hello " + FString(UTF8_TO_TCHAR(ICON_FA_WAVE_SQUARE)) " World"; 173 | ImGui::TextUnformatted(TCHAR_TO_UTF8(*Str)); 174 | ``` 175 | 176 | ### More info 177 | - [Dear ImGui: Using Fonts](https://github.com/ocornut/imgui/blob/master/docs/FONTS.md) 178 | - [IconFontCppHeaders](https://github.com/juliettef/IconFontCppHeaders) 179 | - [FontAwesome with general Dear ImGui](https://pixtur.github.io/mkdocs-for-imgui/site/FONTS/) 180 | 181 | # Misc 182 | 183 | See also 184 | -------- 185 | - [Original Project by segross](https://github.com/segross/UnrealImGui) 186 | - [Dear ImGui](https://github.com/ocornut/imgui) 187 | - [ImPlot](https://github.com/epezent/implot) 188 | 189 | 190 | License 191 | ------- 192 | Unreal ImGui (and this fork) is licensed under the MIT License, see LICENSE for more information. 193 | -------------------------------------------------------------------------------- /Source/ImGui/Private/ImGuiInputState.h: -------------------------------------------------------------------------------- 1 | // Distributed under the MIT License (MIT) (see accompanying LICENSE file) 2 | 3 | #pragma once 4 | 5 | #include "ImGuiInteroperability.h" 6 | #include "Utilities/Arrays.h" 7 | 8 | #include 9 | 10 | 11 | // Collects and stores input state and updates for ImGui IO. 12 | class FImGuiInputState 13 | { 14 | public: 15 | 16 | // Characters buffer. 17 | using FCharactersBuffer = TArray>; 18 | 19 | // Array for mouse button states. 20 | using FMouseButtonsArray = ImGuiInterops::ImGuiTypes::FMouseButtonsArray; 21 | 22 | // Array for key states. 23 | using FKeysArray = ImGuiInterops::ImGuiTypes::FKeysArray; 24 | 25 | // Array for navigation input states. 26 | using FNavInputArray = ImGuiInterops::ImGuiTypes::FNavInputArray; 27 | 28 | // Pair of indices defining range in mouse buttons array. 29 | using FMouseButtonsIndexRange = Utilities::TArrayIndexRange; 30 | 31 | // Pair of indices defining range in keys array. 32 | using FKeysIndexRange = Utilities::TArrayIndexRange; 33 | 34 | // Create empty state with whole range instance with the whole update state marked as dirty. 35 | FImGuiInputState(); 36 | 37 | // Get reference to input characters buffer. 38 | const FCharactersBuffer& GetCharacters() const { return InputCharacters; } 39 | 40 | // Add a character to the characters buffer. We can store and send to ImGui up to 16 characters per frame. Any 41 | // character beyond that limit will be discarded. 42 | // @param Char - Character to add 43 | void AddCharacter(TCHAR Char); 44 | 45 | // Get reference to the array with key down states. 46 | const FKeysArray& GetKeys() const { return KeysDown; } 47 | 48 | // Get possibly empty range of indices bounding dirty part of the keys array. 49 | const FKeysIndexRange& GetKeysUpdateRange() const { return KeysUpdateRange; } 50 | 51 | // Change state of the key in the keys array and expand range bounding dirty part of the array. 52 | // @param KeyEvent - Key event representing the key 53 | // @param bIsDown - True, if key is down 54 | void SetKeyDown(const FKeyEvent& KeyEvent, bool bIsDown) { SetKeyDown(ImGuiInterops::GetKeyIndex(KeyEvent), bIsDown); } 55 | 56 | // Change state of the key in the keys array and expand range bounding dirty part of the array. 57 | // @param Key - Keyboard key 58 | // @param bIsDown - True, if key is down 59 | void SetKeyDown(const FKey& Key, bool bIsDown) { SetKeyDown(ImGuiInterops::GetKeyIndex(Key), bIsDown); } 60 | 61 | // Get reference to the array with mouse button down states. 62 | const FMouseButtonsArray& GetMouseButtons() const { return MouseButtonsDown; } 63 | 64 | // Get possibly empty range of indices bounding dirty part of the mouse buttons array. 65 | const FMouseButtonsIndexRange& GetMouseButtonsUpdateRange() const { return MouseButtonsUpdateRange; } 66 | 67 | // Change state of the button in the mouse buttons array and expand range bounding dirty part of the array. 68 | // @param MouseEvent - Mouse event representing mouse button 69 | // @param bIsDown - True, if button is down 70 | void SetMouseDown(const FPointerEvent& MouseEvent, bool bIsDown) { SetMouseDown(ImGuiInterops::GetMouseIndex(MouseEvent), bIsDown); } 71 | 72 | // Change state of the button in the mouse buttons array and expand range bounding dirty part of the array. 73 | // @param MouseButton - Mouse button key 74 | // @param bIsDown - True, if button is down 75 | void SetMouseDown(const FKey& MouseButton, bool bIsDown) { SetMouseDown(ImGuiInterops::GetMouseIndex(MouseButton), bIsDown); } 76 | 77 | // Get mouse wheel delta accumulated during the last frame. 78 | float GetMouseWheelDelta() const { return MouseWheelDelta; } 79 | 80 | // Add mouse wheel delta. 81 | // @param DeltaValue - Mouse wheel delta to add 82 | void AddMouseWheelDelta(float DeltaValue) { MouseWheelDelta += DeltaValue; } 83 | 84 | // Get the mouse position. 85 | const FVector2D& GetMousePosition() const { return MousePosition; } 86 | 87 | // Set the mouse position. 88 | // @param Position - Mouse position 89 | void SetMousePosition(const FVector2D& Position) { MousePosition = Position; } 90 | 91 | // Check whether input has active mouse pointer. 92 | bool HasMousePointer() const { return bHasMousePointer; } 93 | 94 | // Set whether input has active mouse pointer. 95 | // @param bHasPointer - True, if input has active mouse pointer 96 | void SetMousePointer(bool bInHasMousePointer) { bHasMousePointer = bInHasMousePointer; } 97 | 98 | // Check whether touch input is in progress. True, after touch is started until one frame after it has ended. 99 | // One frame delay is used to process mouse release in ImGui since touch-down is simulated with mouse-down. 100 | bool IsTouchActive() const { return bTouchDown || bTouchProcessed; } 101 | 102 | // Check whether touch input is down. 103 | bool IsTouchDown() const { return bTouchDown; } 104 | 105 | // Set whether touch input is down. 106 | // @param bIsDown - True, if touch is down (or started) and false, if touch is up (or ended) 107 | void SetTouchDown(bool bIsDown) { bTouchDown = bIsDown; } 108 | 109 | // Get the touch position. 110 | const FVector2D& GetTouchPosition() const { return TouchPosition; } 111 | 112 | // Set the touch position. 113 | // @param Position - Touch position 114 | void SetTouchPosition(const FVector2D& Position) { TouchPosition = Position; } 115 | 116 | // Get Control down state. 117 | bool IsControlDown() const { return bIsControlDown; } 118 | 119 | // Set Control down state. 120 | // @param bIsDown - True, if Control is down 121 | void SetControlDown(bool bIsDown) { bIsControlDown = bIsDown; } 122 | 123 | // Get Shift down state. 124 | bool IsShiftDown() const { return bIsShiftDown; } 125 | 126 | // Set Shift down state. 127 | // @param bIsDown - True, if Shift is down 128 | void SetShiftDown(bool bIsDown) { bIsShiftDown = bIsDown; } 129 | 130 | // Get Alt down state. 131 | bool IsAltDown() const { return bIsAltDown; } 132 | 133 | // Set Alt down state. 134 | // @param bIsDown - True, if Alt is down 135 | void SetAltDown(bool bIsDown) { bIsAltDown = bIsDown; } 136 | 137 | // Get reference to the array with navigation input states. 138 | const FNavInputArray& GetNavigationInputs() const { return NavigationInputs; } 139 | 140 | // Change state of the navigation input associated with this gamepad key. 141 | // @param KeyEvent - Key event with gamepad key input 142 | // @param bIsDown - True, if key is down 143 | void SetGamepadNavigationKey(const FKeyEvent& KeyEvent, bool bIsDown) { ImGuiInterops::SetGamepadNavigationKey(NavigationInputs, KeyEvent.GetKey(), bIsDown); } 144 | 145 | // Change state of the navigation input associated with this gamepad axis. 146 | // @param AnalogInputEvent - Analogue input event with gamepad axis input 147 | // @param Value - Analogue value that should be set for this axis 148 | void SetGamepadNavigationAxis(const FAnalogInputEvent& AnalogInputEvent, float Value) { ImGuiInterops::SetGamepadNavigationAxis(NavigationInputs, AnalogInputEvent.GetKey(), Value); } 149 | 150 | // Check whether keyboard navigation is enabled. 151 | bool IsKeyboardNavigationEnabled() const { return bKeyboardNavigationEnabled; } 152 | 153 | // Set whether keyboard navigation is enabled. 154 | // @param bEnabled - True, if navigation is enabled 155 | void SetKeyboardNavigationEnabled(bool bEnabled) { bKeyboardNavigationEnabled = bEnabled; } 156 | 157 | // Check whether gamepad navigation is enabled. 158 | bool IsGamepadNavigationEnabled() const { return bGamepadNavigationEnabled; } 159 | 160 | // Set whether gamepad navigation is enabled. 161 | // @param bEnabled - True, if navigation is enabled 162 | void SetGamepadNavigationEnabled(bool bEnabled) { bGamepadNavigationEnabled = bEnabled; } 163 | 164 | // Check whether gamepad is attached. 165 | bool HasGamepad() const { return bHasGamepad; } 166 | 167 | // Set whether gamepad is attached. 168 | // @param bInHasGamepad - True, if gamepad is attached 169 | void SetGamepad(bool bInHasGamepad) { bHasGamepad = bInHasGamepad; } 170 | 171 | // Reset the whole input state and mark it as dirty. 172 | void Reset() 173 | { 174 | ResetKeyboard(); 175 | ResetMouse(); 176 | ResetGamepadNavigation(); 177 | } 178 | 179 | // Reset the keyboard input state and mark it as dirty. 180 | void ResetKeyboard() 181 | { 182 | ClearCharacters(); 183 | ClearKeys(); 184 | ClearModifierKeys(); 185 | } 186 | 187 | // Reset the mouse input state and mark it as dirty. 188 | void ResetMouse() 189 | { 190 | ClearMouseButtons(); 191 | ClearMouseAnalogue(); 192 | } 193 | 194 | // Reset the gamepad navigation state. 195 | void ResetGamepadNavigation() 196 | { 197 | ClearNavigationInputs(); 198 | } 199 | 200 | // Clear part of the state that is meant to be updated in every frame like: accumulators, buffers, navigation data 201 | // and information about dirty parts of keys or mouse buttons arrays. 202 | void ClearUpdateState(); 203 | 204 | TMap KeyDownEvents; 205 | TMap KeyUpEvents; 206 | 207 | private: 208 | 209 | void SetKeyDown(uint32 KeyIndex, bool bIsDown); 210 | void SetMouseDown(uint32 MouseIndex, bool IsDown); 211 | 212 | void ClearCharacters(); 213 | void ClearKeys(); 214 | void ClearMouseButtons(); 215 | void ClearMouseAnalogue(); 216 | void ClearModifierKeys(); 217 | void ClearNavigationInputs(); 218 | 219 | FVector2D MousePosition = FVector2D::ZeroVector; 220 | FVector2D TouchPosition = FVector2D::ZeroVector; 221 | float MouseWheelDelta = 0.f; 222 | 223 | FMouseButtonsArray MouseButtonsDown; 224 | FMouseButtonsIndexRange MouseButtonsUpdateRange; 225 | 226 | FCharactersBuffer InputCharacters; 227 | 228 | FKeysArray KeysDown; 229 | FKeysIndexRange KeysUpdateRange; 230 | 231 | FNavInputArray NavigationInputs; 232 | 233 | bool bHasMousePointer = false; 234 | bool bTouchDown = false; 235 | bool bTouchProcessed = false; 236 | 237 | bool bIsControlDown = false; 238 | bool bIsShiftDown = false; 239 | bool bIsAltDown = false; 240 | 241 | bool bKeyboardNavigationEnabled = false; 242 | bool bGamepadNavigationEnabled = false; 243 | bool bHasGamepad = false; 244 | }; 245 | -------------------------------------------------------------------------------- /Source/ThirdParty/ImGuiLibrary/Include/imconfig.h: -------------------------------------------------------------------------------- 1 | //----------------------------------------------------------------------------- 2 | // COMPILE-TIME OPTIONS FOR DEAR IMGUI 3 | // Runtime options (clipboard callbacks, enabling various features, etc.) can generally be set via the ImGuiIO structure. 4 | // You can use ImGui::SetAllocatorFunctions() before calling ImGui::CreateContext() to rewire memory allocation functions. 5 | //----------------------------------------------------------------------------- 6 | // A) You may edit imconfig.h (and not overwrite it when updating Dear ImGui, or maintain a patch/rebased branch with your modifications to it) 7 | // B) or '#define IMGUI_USER_CONFIG "my_imgui_config.h"' in your project and then add directives in your own file without touching this template. 8 | //----------------------------------------------------------------------------- 9 | // You need to make sure that configuration settings are defined consistently _everywhere_ Dear ImGui is used, which include the imgui*.cpp 10 | // files but also _any_ of your code that uses Dear ImGui. This is because some compile-time options have an affect on data structures. 11 | // Defining those options in imconfig.h will ensure every compilation unit gets to see the same data structure layouts. 12 | // Call IMGUI_CHECKVERSION() from your .cpp files to verify that the data structures your files are using are matching the ones imgui.cpp is using. 13 | //----------------------------------------------------------------------------- 14 | 15 | #pragma once 16 | 17 | //---- Define assertion handler. Defaults to calling assert(). 18 | // If your macro uses multiple statements, make sure is enclosed in a 'do { .. } while (0)' block so it can be used as a single statement. 19 | //#define IM_ASSERT(_EXPR) MyAssert(_EXPR) 20 | //#define IM_ASSERT(_EXPR) ((void)(_EXPR)) // Disable asserts 21 | 22 | //---- Define attributes of all API symbols declarations, e.g. for DLL under Windows 23 | // Using Dear ImGui via a shared library is not recommended, because of function call overhead and because we don't guarantee backward nor forward ABI compatibility. 24 | // DLL users: heaps and globals are not shared across DLL boundaries! You will need to call SetCurrentContext() + SetAllocatorFunctions() 25 | // for each static/DLL boundary you are calling from. Read "Context and Memory Allocators" section of imgui.cpp for more details. 26 | //#define IMGUI_API __declspec( dllexport ) 27 | //#define IMGUI_API __declspec( dllimport ) 28 | 29 | //---- Don't define obsolete functions/enums/behaviors. Consider enabling from time to time after updating to avoid using soon-to-be obsolete function/names. 30 | //#define IMGUI_DISABLE_OBSOLETE_FUNCTIONS 31 | //#define IMGUI_DISABLE_OBSOLETE_KEYIO // 1.87: disable legacy io.KeyMap[]+io.KeysDown[] in favor io.AddKeyEvent(). This will be folded into IMGUI_DISABLE_OBSOLETE_FUNCTIONS in a few versions. 32 | 33 | //---- Disable all of Dear ImGui or don't implement standard windows. 34 | // It is very strongly recommended to NOT disable the demo windows during development. Please read comments in imgui_demo.cpp. 35 | //#define IMGUI_DISABLE // Disable everything: all headers and source files will be empty. 36 | //#define IMGUI_DISABLE_DEMO_WINDOWS // Disable demo windows: ShowDemoWindow()/ShowStyleEditor() will be empty. Not recommended. 37 | //#define IMGUI_DISABLE_METRICS_WINDOW // Disable metrics/debugger and other debug tools: ShowMetricsWindow() and ShowStackToolWindow() will be empty. 38 | 39 | //---- Don't implement some functions to reduce linkage requirements. 40 | //#define IMGUI_DISABLE_WIN32_DEFAULT_CLIPBOARD_FUNCTIONS // [Win32] Don't implement default clipboard handler. Won't use and link with OpenClipboard/GetClipboardData/CloseClipboard etc. (user32.lib/.a, kernel32.lib/.a) 41 | //#define IMGUI_ENABLE_WIN32_DEFAULT_IME_FUNCTIONS // [Win32] [Default with Visual Studio] Implement default IME handler (require imm32.lib/.a, auto-link for Visual Studio, -limm32 on command-line for MinGW) 42 | //#define IMGUI_DISABLE_WIN32_DEFAULT_IME_FUNCTIONS // [Win32] [Default with non-Visual Studio compilers] Don't implement default IME handler (won't require imm32.lib/.a) 43 | //#define IMGUI_DISABLE_WIN32_FUNCTIONS // [Win32] Won't use and link with any Win32 function (clipboard, ime). 44 | //#define IMGUI_ENABLE_OSX_DEFAULT_CLIPBOARD_FUNCTIONS // [OSX] Implement default OSX clipboard handler (need to link with '-framework ApplicationServices', this is why this is not the default). 45 | //#define IMGUI_DISABLE_DEFAULT_FORMAT_FUNCTIONS // Don't implement ImFormatString/ImFormatStringV so you can implement them yourself (e.g. if you don't want to link with vsnprintf) 46 | //#define IMGUI_DISABLE_DEFAULT_MATH_FUNCTIONS // Don't implement ImFabs/ImSqrt/ImPow/ImFmod/ImCos/ImSin/ImAcos/ImAtan2 so you can implement them yourself. 47 | //#define IMGUI_DISABLE_FILE_FUNCTIONS // Don't implement ImFileOpen/ImFileClose/ImFileRead/ImFileWrite and ImFileHandle at all (replace them with dummies) 48 | //#define IMGUI_DISABLE_DEFAULT_FILE_FUNCTIONS // Don't implement ImFileOpen/ImFileClose/ImFileRead/ImFileWrite and ImFileHandle so you can implement them yourself if you don't want to link with fopen/fclose/fread/fwrite. This will also disable the LogToTTY() function. 49 | //#define IMGUI_DISABLE_DEFAULT_ALLOCATORS // Don't implement default allocators calling malloc()/free() to avoid linking with them. You will need to call ImGui::SetAllocatorFunctions(). 50 | //#define IMGUI_DISABLE_SSE // Disable use of SSE intrinsics even if available 51 | 52 | //---- Include imgui_user.h at the end of imgui.h as a convenience 53 | //#define IMGUI_INCLUDE_IMGUI_USER_H 54 | 55 | //---- Pack colors to BGRA8 instead of RGBA8 (to avoid converting from one to another) 56 | //#define IMGUI_USE_BGRA_PACKED_COLOR 57 | 58 | //---- Use 32-bit for ImWchar (default is 16-bit) to support unicode planes 1-16. (e.g. point beyond 0xFFFF like emoticons, dingbats, symbols, shapes, ancient languages, etc...) 59 | //#define IMGUI_USE_WCHAR32 60 | 61 | //---- Avoid multiple STB libraries implementations, or redefine path/filenames to prioritize another version 62 | // By default the embedded implementations are declared static and not available outside of Dear ImGui sources files. 63 | //#define IMGUI_STB_TRUETYPE_FILENAME "my_folder/stb_truetype.h" 64 | //#define IMGUI_STB_RECT_PACK_FILENAME "my_folder/stb_rect_pack.h" 65 | //#define IMGUI_DISABLE_STB_TRUETYPE_IMPLEMENTATION 66 | //#define IMGUI_DISABLE_STB_RECT_PACK_IMPLEMENTATION 67 | 68 | //---- Use stb_printf's faster implementation of vsnprintf instead of the one from libc (unless IMGUI_DISABLE_DEFAULT_FORMAT_FUNCTIONS is defined) 69 | // Requires 'stb_sprintf.h' to be available in the include path. Compatibility checks of arguments and formats done by clang and GCC will be disabled in order to support the extra formats provided by STB sprintf. 70 | // #define IMGUI_USE_STB_SPRINTF 71 | 72 | //---- Use FreeType to build and rasterize the font atlas (instead of stb_truetype which is embedded by default in Dear ImGui) 73 | // Requires FreeType headers to be available in the include path. Requires program to be compiled with 'misc/freetype/imgui_freetype.cpp' (in this repository) + the FreeType library (not provided). 74 | // On Windows you may use vcpkg with 'vcpkg install freetype --triplet=x64-windows' + 'vcpkg integrate install'. 75 | //#define IMGUI_ENABLE_FREETYPE 76 | 77 | //---- Use stb_truetype to build and rasterize the font atlas (default) 78 | // The only purpose of this define is if you want force compilation of the stb_truetype backend ALONG with the FreeType backend. 79 | //#define IMGUI_ENABLE_STB_TRUETYPE 80 | 81 | //---- Define constructor and implicit cast operators to convert back<>forth between your math types and ImVec2/ImVec4. 82 | // This will be inlined as part of ImVec2 and ImVec4 class declarations. 83 | /* 84 | #define IM_VEC2_CLASS_EXTRA \ 85 | ImVec2(const MyVec2& f) { x = f.x; y = f.y; } \ 86 | operator MyVec2() const { return MyVec2(x,y); } 87 | 88 | #define IM_VEC4_CLASS_EXTRA \ 89 | ImVec4(const MyVec4& f) { x = f.x; y = f.y; z = f.z; w = f.w; } \ 90 | operator MyVec4() const { return MyVec4(x,y,z,w); } 91 | */ 92 | 93 | //---- Use 32-bit vertex indices (default is 16-bit) is one way to allow large meshes with more than 64K vertices. 94 | // Your renderer backend will need to support it (most example renderer backends support both 16/32-bit indices). 95 | // Another way to allow large meshes while keeping 16-bit indices is to handle ImDrawCmd::VtxOffset in your renderer. 96 | // Read about ImGuiBackendFlags_RendererHasVtxOffset for details. 97 | //#define ImDrawIdx unsigned int 98 | 99 | //---- Override ImDrawCallback signature (will need to modify renderer backends accordingly) 100 | //struct ImDrawList; 101 | //struct ImDrawCmd; 102 | //typedef void (*MyImDrawCallback)(const ImDrawList* draw_list, const ImDrawCmd* cmd, void* my_renderer_user_data); 103 | //#define ImDrawCallback MyImDrawCallback 104 | 105 | //---- Debug Tools: Macro to break in Debugger 106 | // (use 'Metrics->Tools->Item Picker' to pick widgets with the mouse and break into them for easy debugging.) 107 | //#define IM_DEBUG_BREAK IM_ASSERT(0) 108 | //#define IM_DEBUG_BREAK __debugbreak() 109 | 110 | //---- Debug Tools: Have the Item Picker break in the ItemAdd() function instead of ItemHoverable(), 111 | // (which comes earlier in the code, will catch a few extra items, allow picking items other than Hovered one.) 112 | // This adds a small runtime cost which is why it is not enabled by default. 113 | //#define IMGUI_DEBUG_TOOL_ITEM_PICKER_EX 114 | 115 | //---- Debug Tools: Enable slower asserts 116 | //#define IMGUI_DEBUG_PARANOID 117 | 118 | //---- Tip: You can add extra functions within the ImGui:: namespace, here or in your own headers files. 119 | /* 120 | namespace ImGui 121 | { 122 | void MyFunction(const char* name, const MyMatrix44& v); 123 | } 124 | */ 125 | --------------------------------------------------------------------------------