diff --git a/Content/Core/Hud/WBP_Menu.uasset b/Content/Core/Hud/WBP_Menu.uasset index 15529b2..a901381 100644 Binary files a/Content/Core/Hud/WBP_Menu.uasset and b/Content/Core/Hud/WBP_Menu.uasset differ diff --git a/Plugins/Cog/Source/CogEngine/Private/CogEngineWindow_Collisions.cpp b/Plugins/Cog/Source/CogEngine/Private/CogEngineWindow_Collisions.cpp index 0037553..fa41a16 100644 --- a/Plugins/Cog/Source/CogEngine/Private/CogEngineWindow_Collisions.cpp +++ b/Plugins/Cog/Source/CogEngine/Private/CogEngineWindow_Collisions.cpp @@ -228,7 +228,7 @@ void FCogEngineWindow_Collisions::RenderContent() case 2: { FVector Direction; - UGameplayStatics::DeprojectScreenToWorld(PlayerController, FCogImguiHelper::ToVector2D(ImGui::GetMousePos()), QueryStart, Direction); + UGameplayStatics::DeprojectScreenToWorld(PlayerController, FCogImguiHelper::ToFVector2D(ImGui::GetMousePos()), QueryStart, Direction); QueryEnd = QueryStart + Direction * Config->QueryDistance; QueryRadius = Config->QueryThickness; break; diff --git a/Plugins/Cog/Source/CogEngine/Private/CogEngineWindow_Selection.cpp b/Plugins/Cog/Source/CogEngine/Private/CogEngineWindow_Selection.cpp index f58e7f0..40781fc 100644 --- a/Plugins/Cog/Source/CogEngine/Private/CogEngineWindow_Selection.cpp +++ b/Plugins/Cog/Source/CogEngine/Private/CogEngineWindow_Selection.cpp @@ -4,6 +4,7 @@ #include "CogDebugSettings.h" #include "CogEngineReplicator.h" #include "CogImguiModule.h" +#include "CogImguiHelper.h" #include "CogImguiInputHelper.h" #include "CogWindowManager.h" #include "CogWindowWidgets.h" @@ -136,8 +137,8 @@ void FCogEngineWindow_Selection::ToggleSelectionMode() void FCogEngineWindow_Selection::ActivateSelectionMode() { bSelectionModeActive = true; - bIsInputEnabledBeforeEnteringSelectionMode = GetOwner()->GetImGuiWidget()->GetEnableInput(); - GetOwner()->GetImGuiWidget()->SetEnableInput(true); + bIsInputEnabledBeforeEnteringSelectionMode = GetOwner()->GetContext().GetEnableInput(); + GetOwner()->GetContext().SetEnableInput(true); GetOwner()->SetHideAllWindows(true); } @@ -158,7 +159,7 @@ void FCogEngineWindow_Selection::DeactivateSelectionMode() // When in selection mode we need imgui to have the input focus // When leaving selection mode we want to leave it as is was before //-------------------------------------------------------------------------------------------- - GetOwner()->GetImGuiWidget()->SetEnableInput(bIsInputEnabledBeforeEnteringSelectionMode); + GetOwner()->GetContext().SetEnableInput(bIsInputEnabledBeforeEnteringSelectionMode); GetOwner()->SetHideAllWindows(false); } @@ -393,15 +394,23 @@ void FCogEngineWindow_Selection::TickSelectionMode() return; } - ImDrawList* DrawList = ImGui::GetBackgroundDrawList(); - DrawList->AddRect(ImVec2(0, 0), ImGui::GetIO().DisplaySize, IM_COL32(255, 0, 0, 128), 0.0f, 0, 20.0f); - FCogWindowWidgets::AddTextWithShadow(DrawList, ImVec2(20, 20), IM_COL32(255, 255, 255, 255), "Picking Mode. \n[LMB] Pick \n[RMB] Cancel"); + ImGuiViewport* Viewport = ImGui::GetMainViewport(); + if (Viewport == nullptr) + { + return; + } + + const ImVec2 ViewportPos = Viewport->Pos; + const ImVec2 ViewportSize = Viewport->Size; + ImDrawList* DrawList = ImGui::GetBackgroundDrawList(Viewport); + DrawList->AddRect(ViewportPos, ViewportPos + ViewportSize, IM_COL32(255, 0, 0, 128), 0.0f, 0, 20.0f); + FCogWindowWidgets::AddTextWithShadow(DrawList, ViewportPos + ImVec2(20, 20), IM_COL32(255, 255, 255, 255), "Picking Mode. \n[LMB] Pick \n[RMB] Cancel"); TSubclassOf SelectedActorClass = GetSelectedActorClass(); AActor* HoveredActor = nullptr; FVector WorldOrigin, WorldDirection; - if (UGameplayStatics::DeprojectScreenToWorld(PlayerController, FCogImguiHelper::ToVector2D(ImGui::GetMousePos()), WorldOrigin, WorldDirection)) + if (UGameplayStatics::DeprojectScreenToWorld(PlayerController, FCogImguiHelper::ToFVector2D(ImGui::GetMousePos() - ViewportPos), WorldOrigin, WorldDirection)) { //-------------------------------------------------------------------------------------------------------- // Prioritize another actor than the selected actor unless we only touch the selected actor. @@ -463,7 +472,13 @@ void FCogEngineWindow_Selection::DrawActorFrame(const AActor& Actor) return; } - ImDrawList* DrawList = ImGui::GetBackgroundDrawList(); + ImGuiViewport* Viewport = ImGui::GetMainViewport(); + if (Viewport == nullptr) + { + return; + } + + ImDrawList* DrawList = ImGui::GetBackgroundDrawList(Viewport); FVector BoxOrigin, BoxExtent; @@ -502,8 +517,8 @@ void FCogEngineWindow_Selection::DrawActorFrame(const AActor& Actor) if (ComputeBoundingBoxScreenPosition(PlayerController, BoxOrigin, BoxExtent, ScreenPosMin, ScreenPosMax)) { const ImU32 Color = (&Actor == GetSelection()) ? IM_COL32(255, 255, 255, 255) : IM_COL32(255, 255, 255, 128); - DrawList->AddRect(FCogImguiHelper::ToImVec2(ScreenPosMin), FCogImguiHelper::ToImVec2(ScreenPosMax), Color, 0.0f, 0, 1.0f); - FCogWindowWidgets::AddTextWithShadow(DrawList, FCogImguiHelper::ToImVec2(ScreenPosMin + FVector2D(0, -14.0f)), Color, TCHAR_TO_ANSI(*GetActorName(Actor))); + DrawList->AddRect(FCogImguiHelper::ToImVec2(ScreenPosMin) + Viewport->Pos, FCogImguiHelper::ToImVec2(ScreenPosMax) + Viewport->Pos, Color, 0.0f, 0, 1.0f); + FCogWindowWidgets::AddTextWithShadow(DrawList, FCogImguiHelper::ToImVec2(ScreenPosMin + FVector2D(0, -14.0f)) + Viewport->Pos, Color, TCHAR_TO_ANSI(*GetActorName(Actor))); } } diff --git a/Plugins/Cog/Source/CogEngine/Private/CogEngineWindow_Slate.cpp b/Plugins/Cog/Source/CogEngine/Private/CogEngineWindow_Slate.cpp new file mode 100644 index 0000000..1d5837a --- /dev/null +++ b/Plugins/Cog/Source/CogEngine/Private/CogEngineWindow_Slate.cpp @@ -0,0 +1,105 @@ +#include "CogEngineWindow_Slate.h" + +#include "CogImguiHelper.h" +#include "Framework/Application/SlateApplication.h" +#include "Framework/Application/SlateUser.h" + +//-------------------------------------------------------------------------------------------------------------------------- +void FCogEngineWindow_Slate::RenderHelp() +{ + ImGui::Text( + "This window displays slate debug info. " + ); +} + +//-------------------------------------------------------------------------------------------------------------------------- +void FCogEngineWindow_Slate::RenderContent() +{ + Super::RenderContent(); + + + if (FSlateApplication::IsInitialized() == false) + { + ImGui::Text("Not initialized"); + return; + } + + FSlateApplication& SlateApp = FSlateApplication::Get(); + + static int32 SelectedUserIndex = 0; + + ImGui::SetNextItemWidth(-1); + if (ImGui::BeginCombo("##User", TCHAR_TO_ANSI(*FString::Printf(TEXT("%d"), SelectedUserIndex)))) + { + SlateApp.ForEachUser([this](FSlateUser& User) + { + if (ImGui::Selectable(TCHAR_TO_ANSI(*FString::Printf(TEXT("%d"), SelectedUserIndex)), false)) + { + SelectedUserIndex = User.GetUserIndex(); + } + }); + ImGui::EndCombo(); + } + + if (TSharedPtr User = SlateApp.GetUser(SelectedUserIndex)) + { + RenderUser(*User.Get()); + } + +} + +//-------------------------------------------------------------------------------------------------------------------------- +void FCogEngineWindow_Slate::RenderUser(FSlateUser& User) +{ + + if (ImGui::BeginTable("SlateUser", 2, ImGuiTableFlags_Borders)) + { + const ImVec4 LabelColor(1.0f, 1.0f, 1.0f, 0.5f); + + ImGui::TableSetupColumn("Property"); + ImGui::TableSetupColumn("Value"); + + + //------------------------ + // Focused Widget + //------------------------ + ImGui::TableNextRow(); + ImGui::TableNextColumn(); + ImGui::TextColored(LabelColor, "Focused Widget"); + ImGui::TableNextColumn(); + FString FocusedWidgetText = "None"; + if (TSharedPtr FocusedWidget = User.GetFocusedWidget()) + { + FocusedWidgetText = FocusedWidget->ToString(); + } + ImGui::Text("%s", TCHAR_TO_ANSI(*FocusedWidgetText)); + + //------------------------ + // Cursor Captor + //------------------------ + ImGui::TableNextRow(); + ImGui::TableNextColumn(); + ImGui::TextColored(LabelColor, "Cursor Captor"); + ImGui::TableNextColumn(); + FString CursorCaptoreWidgetText = "None"; + if (TSharedPtr CursorCaptoreWidget = User.GetCursorCaptor()) + { + CursorCaptoreWidgetText = CursorCaptoreWidget->ToString(); + } + ImGui::Text("%s", TCHAR_TO_ANSI(*CursorCaptoreWidgetText)); + + //------------------------ + // Cursor Position + //------------------------ + ImGui::TableNextRow(); + ImGui::TableNextColumn(); + ImGui::TextColored(LabelColor, "Cursor Position"); + ImGui::TableNextColumn(); + ImVec2 CursorPosition = FCogImguiHelper::ToImVec2(User.GetCursorPosition()); + ImGui::InputFloat2("##Cursor Position", &CursorPosition.x, "%0.0f"); + + + + ImGui::EndTable(); + } +} \ No newline at end of file diff --git a/Plugins/Cog/Source/CogEngine/Public/CogEngineWindow_Slate.h b/Plugins/Cog/Source/CogEngine/Public/CogEngineWindow_Slate.h new file mode 100644 index 0000000..2780ea0 --- /dev/null +++ b/Plugins/Cog/Source/CogEngine/Public/CogEngineWindow_Slate.h @@ -0,0 +1,22 @@ +#pragma once + +#include "CoreMinimal.h" +#include "CogWindow.h" + +class FSlateUser; + +class COGENGINE_API FCogEngineWindow_Slate : public FCogWindow +{ + typedef FCogWindow Super; + +public: + +protected: + + virtual void RenderHelp() override; + + virtual void RenderContent() override; + + virtual void RenderUser(FSlateUser& User); + +}; diff --git a/Plugins/Cog/Source/CogImgui/Private/CogImGuiInputProcessor.cpp b/Plugins/Cog/Source/CogImgui/Private/CogImGuiInputProcessor.cpp index d7ee6ce..fb04382 100644 --- a/Plugins/Cog/Source/CogImgui/Private/CogImGuiInputProcessor.cpp +++ b/Plugins/Cog/Source/CogImgui/Private/CogImGuiInputProcessor.cpp @@ -3,9 +3,11 @@ #include "CogImguiHelper.h" #include "CogImguiInputHelper.h" #include "CogImguiWidget.h" +#include "CogImguiContext.h" #include "GameFramework/InputSettings.h" #include "GameFramework/PlayerInput.h" #include "imgui.h" +#include "imgui_internal.h" #include "Slate/SGameLayerManager.h" #if WITH_EDITOR @@ -16,9 +18,10 @@ constexpr bool ForwardEvent = false; constexpr bool TerminateEvent = true; //-------------------------------------------------------------------------------------------------------------------------- -FImGuiInputProcessor::FImGuiInputProcessor(UPlayerInput* InPlayerInput, SCogImguiWidget* InMainWidget) +FImGuiInputProcessor::FImGuiInputProcessor(UPlayerInput* InPlayerInput, FCogImguiContext* InContext, SCogImguiWidget* InMainWidget) { PlayerInput = InPlayerInput; + Context = InContext; MainWidget = InMainWidget; } @@ -43,14 +46,16 @@ void FImGuiInputProcessor::Tick(const float DeltaTime, FSlateApplication& SlateA AddMousePosEvent(SlateApp.GetCursorPos()); - if ((IO.ConfigFlags & ImGuiConfigFlags_NoMouse) == 0) + const bool bHasMouse = (IO.ConfigFlags & ImGuiConfigFlags_NoMouse) == 0; + const bool bUpdateMouseMouseCursor = (IO.ConfigFlags & ImGuiConfigFlags_NoMouseCursorChange) == 0; + if (bHasMouse && bUpdateMouseMouseCursor) { SlateCursor->SetType(FCogImguiInputHelper::ToSlateMouseCursor(ImGui::GetMouseCursor())); } if (IO.WantSetMousePos) { - SlateApp.SetCursorPos(FCogImguiHelper::ToVector2D(IO.MousePos)); + SlateApp.SetCursorPos(FCogImguiHelper::ToFVector2D(IO.MousePos)); //UE_LOG(LogCogImGui, VeryVerbose, TEXT("FImGuiInputProcessor::Tick | SetCursorPos")); } } @@ -175,7 +180,7 @@ bool FImGuiInputProcessor::HandleMouseMoveEvent(FSlateApplication& SlateApp, con { AddMousePosEvent(Event.GetScreenSpacePosition()); - if (MainWidget->GetEnableInput() && MainWidget->GetShareMouse() == false) + if (Context->GetEnableInput() && Context->GetShareMouse() == false && IsMouseInsideMainViewport()) { return TerminateEvent; } @@ -211,7 +216,7 @@ bool FImGuiInputProcessor::HandleMouseButtonEvent(FSlateApplication& SlateApp, c const uint32 Button = ToImGuiMouseButton(Event.GetEffectingButton()); IO.AddMouseButtonEvent(Button, IsButtonDown); - if (MainWidget->GetEnableInput() && MainWidget->GetShareMouse() == false) + if (Context->GetEnableInput() && Context->GetShareMouse() == false && IsMouseInsideMainViewport()) { const bool Result = TerminateEvent; UE_LOG(LogCogImGui, VeryVerbose, TEXT("FImGuiInputProcessor::HandleMouseButtonEvent | Button:%d | IsButtonDown:%d | WantCaptureMouse:%d | TerminateEvent:%d | ShareMouse == false"), Button, IsButtonDown, IO.WantCaptureMouse, Result); @@ -237,6 +242,19 @@ void FImGuiInputProcessor::AddMousePosEvent(const FVector2D& MousePosition) cons } } +//-------------------------------------------------------------------------------------------------------------------------- +bool FImGuiInputProcessor::IsMouseInsideMainViewport() +{ + if (ImGuiViewportP* Viewport = (ImGuiViewportP*)ImGui::GetMainViewport()) + { + ImGuiIO& IO = ImGui::GetIO(); + const bool Result = Viewport->GetMainRect().Contains(IO.MousePos); + return Result; + } + + return false; +} + //-------------------------------------------------------------------------------------------------------------------------- bool FImGuiInputProcessor::HandleMouseWheelOrGestureEvent(FSlateApplication& SlateApp, const FPointerEvent& Event, const FPointerEvent* GestureEvent) { diff --git a/Plugins/Cog/Source/CogImgui/Private/CogImguiContext.cpp b/Plugins/Cog/Source/CogImgui/Private/CogImguiContext.cpp new file mode 100644 index 0000000..5acbee3 --- /dev/null +++ b/Plugins/Cog/Source/CogImgui/Private/CogImguiContext.cpp @@ -0,0 +1,726 @@ +#include "CogImGuiContext.h" + +#include "CogImguiHelper.h" +#include "CogImguiInputHelper.h" +#include "CogImguiInputProcessor.h" +#include "CogImguiWidget.h" +#include "Engine/Console.h" +#include "Engine/LocalPlayer.h" +#include "Framework/Application/SlateApplication.h" +#include "Framework/Application/SlateUser.h" +#include "GameFramework/PlayerController.h" +#include "GameFramework/PlayerInput.h" +#include "imgui.h" +#include "imgui_internal.h" +#include "implot.h" +#include "TextureResource.h" +#include "Widgets/SViewport.h" +#include "Widgets/SWindow.h" + +static UPlayerInput* GetPlayerInput(const UWorld* World); + +//-------------------------------------------------------------------------------------------------------------------------- +void FCogImguiContext::Initialize() +{ + IMGUI_CHECKVERSION(); + + if (FSlateApplication::IsInitialized() == false) + { + return; + } + FSlateApplication& SlateApp = FSlateApplication::Get(); + + GameViewport = GEngine->GameViewport; + + SAssignNew(MainWidget, SCogImguiWidget) + .Context(this); + + GameViewport->AddViewportWidgetContent(MainWidget.ToSharedRef(), TNumericLimits::Max()); + + //-------------------------------------------------------------------- + // Register input processor to forward input events to imgui + //-------------------------------------------------------------------- + if (FSlateApplication::IsInitialized()) + { + UPlayerInput* PlayerInput = FCogImguiInputHelper::GetPlayerInput(*GameViewport->GetWorld()); + InputProcessor = MakeShared(PlayerInput, this, MainWidget.Get()); + FSlateApplication::Get().RegisterInputPreProcessor(InputProcessor.ToSharedRef(), 0); + } + + ImGuiContext = ImGui::CreateContext(); + PlotContext = ImPlot::CreateContext(); + ImPlot::SetImGuiContext(ImGuiContext); + + ImGuiIO& IO = ImGui::GetIO(); + IO.UserData = this; + + IO.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard; + IO.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad; + IO.ConfigFlags |= ImGuiConfigFlags_NavNoCaptureKeyboard; + IO.ConfigFlags |= ImGuiConfigFlags_NavEnableSetMousePos; + IO.ConfigFlags |= ImGuiConfigFlags_DockingEnable; + + IO.BackendFlags |= ImGuiBackendFlags_HasMouseCursors; + IO.BackendFlags |= ImGuiBackendFlags_HasSetMousePos; + IO.BackendFlags |= ImGuiBackendFlags_PlatformHasViewports; + IO.BackendFlags |= ImGuiBackendFlags_HasMouseHoveredViewport; + IO.BackendFlags |= ImGuiBackendFlags_RendererHasViewports; + IO.BackendFlags |= ImGuiBackendFlags_RendererHasVtxOffset; + + //-------------------------------------------------------------------- + // + //-------------------------------------------------------------------- + ImGuiViewport* MainViewport = ImGui::GetMainViewport(); + FImGuiViewportData* ViewportData = new FImGuiViewportData(); + MainViewport->PlatformUserData = ViewportData; + ViewportData->Window = SlateApp.GetActiveTopLevelWindow(); + ViewportData->Context = this; + ViewportData->Widget = MainWidget; + + const char* InitFilenameTemp = TCHAR_TO_ANSI(*FCogImguiHelper::GetIniFilePath("imgui")); + ImStrncpy(IniFilename, InitFilenameTemp, IM_ARRAYSIZE(IniFilename)); + IO.IniFilename = IniFilename; + + ImGuiPlatformIO& PlatformIO = ImGui::GetPlatformIO(); + PlatformIO.Platform_CreateWindow = ImGui_CreateWindow; + PlatformIO.Platform_DestroyWindow = ImGui_DestroyWindow; + PlatformIO.Platform_ShowWindow = ImGui_ShowWindow; + PlatformIO.Platform_SetWindowPos = ImGui_SetWindowPos; + PlatformIO.Platform_GetWindowPos = ImGui_GetWindowPos; + PlatformIO.Platform_SetWindowSize = ImGui_SetWindowSize; + PlatformIO.Platform_GetWindowSize = ImGui_GetWindowSize; + PlatformIO.Platform_SetWindowFocus = ImGui_SetWindowFocus; + PlatformIO.Platform_GetWindowFocus = ImGui_GetWindowFocus; + PlatformIO.Platform_GetWindowMinimized = ImGui_GetWindowMinimized; + PlatformIO.Platform_SetWindowTitle = ImGui_SetWindowTitle; + PlatformIO.Platform_SetWindowAlpha = ImGui_SetWindowAlpha; + PlatformIO.Platform_RenderWindow = ImGui_RenderWindow; + + if (const TSharedPtr PlatformApplication = SlateApp.GetPlatformApplication()) + { + FDisplayMetrics DisplayMetrics; + PlatformApplication->GetInitialDisplayMetrics(DisplayMetrics); + PlatformApplication->OnDisplayMetricsChanged().AddRaw(this, &FCogImguiContext::OnDisplayMetricsChanged); + OnDisplayMetricsChanged(DisplayMetrics); + } +} + +//-------------------------------------------------------------------------------------------------------------------------- +void FCogImguiContext::Shutdown() +{ + ImGuiViewport* MainViewport = ImGui::GetMainViewport(); + if (const FImGuiViewportData* ViewportData = static_cast(MainViewport->PlatformUserData)) + { + delete ViewportData; + MainViewport->PlatformUserData = nullptr; + } + + if (FSlateApplication::IsInitialized()) + { + FSlateApplication& SlateApp = FSlateApplication::Get(); + + if (InputProcessor.IsValid()) + { + SlateApp.UnregisterInputPreProcessor(InputProcessor); + } + + if (const TSharedPtr PlatformApplication = SlateApp.GetPlatformApplication()) + { + PlatformApplication->OnDisplayMetricsChanged().RemoveAll(this); + } + } + + if (PlotContext) + { + ImPlot::DestroyContext(PlotContext); + PlotContext = nullptr; + } + + if (ImGuiContext) + { + ImGui::DestroyContext(ImGuiContext); + ImGuiContext = nullptr; + } +} + +//-------------------------------------------------------------------------------------------------------------------------- +void FCogImguiContext::OnDisplayMetricsChanged(const FDisplayMetrics& DisplayMetrics) const +{ + ImGuiPlatformIO& PlatformIO = ImGui::GetPlatformIO(); + PlatformIO.Monitors.resize(0); + + for (const FMonitorInfo& Monitor : DisplayMetrics.MonitorInfo) + { + ImGuiPlatformMonitor ImGuiMonitor; + ImGuiMonitor.MainPos = ImVec2(Monitor.DisplayRect.Left, Monitor.DisplayRect.Top); + ImGuiMonitor.MainSize = ImVec2(Monitor.DisplayRect.Right - Monitor.DisplayRect.Left, Monitor.DisplayRect.Bottom - Monitor.DisplayRect.Top); + ImGuiMonitor.WorkPos = ImVec2(Monitor.WorkArea.Left, Monitor.WorkArea.Top); + ImGuiMonitor.WorkSize = ImVec2(Monitor.WorkArea.Right - Monitor.WorkArea.Left, Monitor.WorkArea.Bottom - Monitor.WorkArea.Top); + ImGuiMonitor.DpiScale = Monitor.DPI; + + if (Monitor.bIsPrimary) + { + PlatformIO.Monitors.push_front(ImGuiMonitor); + } + else + { + PlatformIO.Monitors.push_back(ImGuiMonitor); + } + } +} + +//-------------------------------------------------------------------------------------------------------------------------- +void FCogImguiContext::BeginFrame(float InDeltaTime) +{ + ImGui::SetCurrentContext(ImGuiContext); + ImPlot::SetImGuiContext(ImGuiContext); + ImPlot::SetCurrentContext(PlotContext); + + ImGuiIO& IO = ImGui::GetIO(); + IO.DeltaTime = InDeltaTime; + IO.DisplaySize = FCogImguiHelper::ToImVec2(MainWidget->GetTickSpaceGeometry().GetAbsoluteSize()); + + //------------------------------------------------------------------------------------------------------- + // Build font + //------------------------------------------------------------------------------------------------------- + if (IO.Fonts->IsBuilt() == false || FontAtlasTexturePtr.IsValid() == false) + { + BuildFont(); + } + + //------------------------------------------------------------------------------------------------------- + // Update which viewport is under the mouse + //------------------------------------------------------------------------------------------------------- + ImGuiID MouseViewportId = 0; + + FSlateApplication& SlateApp = FSlateApplication::Get(); + FWidgetPath WidgetsUnderCursor = SlateApp.LocateWindowUnderMouse(SlateApp.GetCursorPos(), SlateApp.GetInteractiveTopLevelWindows()); + if (WidgetsUnderCursor.IsValid()) + { + TSharedRef Window = WidgetsUnderCursor.GetWindow(); + ImGuiID* ViewportId = WindowToViewportMap.Find(Window); + + if (ViewportId != nullptr) + { + MouseViewportId = *ViewportId; + } + else + { + MouseViewportId = ImGui::GetMainViewport()->ID; + } + } + + IO.AddMouseViewportEvent(MouseViewportId); + + //------------------------------------------------------------------------------------------------------- + // Refresh modifiers otherwise, when pressing ALT-TAB, the Alt modifier is always true + //------------------------------------------------------------------------------------------------------- + FModifierKeysState ModifierKeys = FSlateApplication::Get().GetModifierKeys(); + if (ModifierKeys.IsControlDown() != IO.KeyCtrl) { IO.AddKeyEvent(ImGuiMod_Ctrl, ModifierKeys.IsControlDown()); } + if (ModifierKeys.IsShiftDown() != IO.KeyShift) { IO.AddKeyEvent(ImGuiMod_Shift, ModifierKeys.IsShiftDown()); } + if (ModifierKeys.IsAltDown() != IO.KeyAlt) { IO.AddKeyEvent(ImGuiMod_Alt, ModifierKeys.IsAltDown()); } + if (ModifierKeys.IsCommandDown() != IO.KeySuper) { IO.AddKeyEvent(ImGuiMod_Super, ModifierKeys.IsCommandDown()); } + + + //------------------------------------------------------------------------------------------------------- + // + //------------------------------------------------------------------------------------------------------- + if (bEnableInput) + { + IO.ConfigFlags &= ~ImGuiConfigFlags_NoMouse; + + TryReleaseGameMouseCapture(); + } + else + { + IO.ConfigFlags |= ImGuiConfigFlags_NoMouse; + } + + //------------------------------------------------------------------------------------------------------- + // + //------------------------------------------------------------------------------------------------------- + const bool bHasMouse = (IO.ConfigFlags & ImGuiConfigFlags_NoMouse) == 0; + const bool bUpdateMouseMouseCursor = (IO.ConfigFlags & ImGuiConfigFlags_NoMouseCursorChange) == 0; + if (bHasMouse && bUpdateMouseMouseCursor) + { + MainWidget->SetCursor(FCogImguiInputHelper::ToSlateMouseCursor(ImGui::GetMouseCursor())); + } + + //------------------------------------------------------------------------------------------------------- + // + //------------------------------------------------------------------------------------------------------- + if (bRefreshDPIScale) + { + RefreshDPIScale(); + } + + ImGui::NewFrame(); + + DrawDebug(); +} + +//-------------------------------------------------------------------------------------------------------------------------- +void FCogImguiContext::EndFrame() +{ + ImGui::Render(); + ImGui_RenderWindow(ImGui::GetMainViewport(), nullptr); + + ImGui::UpdatePlatformWindows(); + ImGui::RenderPlatformWindowsDefault(); +} + +//-------------------------------------------------------------------------------------------------------------------------- +void FCogImguiContext::ImGui_CreateWindow(ImGuiViewport* Viewport) +{ + if (Viewport->ParentViewportId == 0) + { + return; + } + + ImGuiViewport* ParentViewport = ImGui::FindViewportByID(Viewport->ParentViewportId); + if (ParentViewport == nullptr) + { + return; + } + + const FImGuiViewportData* ParentViewportData = static_cast(ParentViewport->PlatformUserData); + if (ParentViewportData == nullptr) + { + return; + } + + FCogImguiContext* Context = ParentViewportData->Context.Get(); + + const bool bTooltipWindow = (Viewport->Flags & ImGuiViewportFlags_TopMost); + const bool bPopupWindow = (Viewport->Flags & ImGuiViewportFlags_NoTaskBarIcon); + + static FWindowStyle WindowStyle = FWindowStyle() + .SetActiveTitleBrush(FSlateNoResource()) + .SetInactiveTitleBrush(FSlateNoResource()) + .SetFlashTitleBrush(FSlateNoResource()) + .SetOutlineBrush(FSlateNoResource()) + .SetBorderBrush(FSlateNoResource()) + .SetBackgroundBrush(FSlateNoResource()) + .SetChildBackgroundBrush(FSlateNoResource()); + + TSharedPtr Widget; + + const TSharedRef Window = + SNew(SWindow) + .Type(bTooltipWindow ? EWindowType::ToolTip : EWindowType::Normal) + .Style(&WindowStyle) + .ScreenPosition(FCogImguiHelper::ToFVector2D(Viewport->Pos)) + .ClientSize(FCogImguiHelper::ToFVector2D(Viewport->Size)) + .SupportsTransparency(EWindowTransparency::PerWindow) + .SizingRule(ESizingRule::UserSized) + .IsPopupWindow(bTooltipWindow || bPopupWindow) + .IsTopmostWindow(bTooltipWindow) + .FocusWhenFirstShown(!(Viewport->Flags & ImGuiViewportFlags_NoFocusOnAppearing)) + .HasCloseButton(false) + .SupportsMaximize(false) + .SupportsMinimize(false) + .CreateTitleBar(false) + .LayoutBorder(0) + .UserResizeBorder(0) + .UseOSWindowBorder(false) + [ + SAssignNew(Widget, SCogImguiWidget) + .Context(Context) + ]; + + if (ParentViewportData->Window.IsValid()) + { + FSlateApplication::Get().AddWindowAsNativeChild(Window, ParentViewportData->Window.Pin().ToSharedRef()); + } + else + { + FSlateApplication::Get().AddWindow(Window); + } + + FImGuiViewportData* ViewportData = new FImGuiViewportData(); + Viewport->PlatformUserData = ViewportData; + ViewportData->Context = ParentViewportData->Context; + ViewportData->Widget = Widget; + ViewportData->Window = Window; + + ParentViewportData->Context->WindowToViewportMap.Add(Window, Viewport->ID); + + Viewport->PlatformRequestResize = false; +} + +//-------------------------------------------------------------------------------------------------------------------------- +void FCogImguiContext::ImGui_DestroyWindow(ImGuiViewport* Viewport) +{ + FImGuiViewportData* ViewportData = static_cast(Viewport->PlatformUserData); + if (ViewportData == nullptr) + { + return; + } + + if ((Viewport->Flags & ImGuiViewportFlags_OwnedByApp)) + { + return; + } + + ViewportData->Context->WindowToViewportMap.Remove(ViewportData->Window); + + if (const TSharedPtr Window = ViewportData->Window.Pin()) + { + Window->RequestDestroyWindow(); + } + + delete ViewportData; + Viewport->PlatformUserData = nullptr; +} + +//-------------------------------------------------------------------------------------------------------------------------- +void FCogImguiContext::ImGui_ShowWindow(ImGuiViewport* Viewport) +{ + if (const FImGuiViewportData* ViewportData = static_cast(Viewport->PlatformUserData)) + { + if (const TSharedPtr Window = ViewportData->Window.Pin()) + { + Window->ShowWindow(); + } + } +} + +//-------------------------------------------------------------------------------------------------------------------------- +void FCogImguiContext::ImGui_SetWindowPos(ImGuiViewport* Viewport, ImVec2 Pos) +{ + if (const FImGuiViewportData* ViewportData = static_cast(Viewport->PlatformUserData)) + { + if (const TSharedPtr Window = ViewportData->Window.Pin()) + { + Window->MoveWindowTo(FCogImguiHelper::ToFVector2D(Pos)); + } + } +} + +//-------------------------------------------------------------------------------------------------------------------------- +ImVec2 FCogImguiContext::ImGui_GetWindowPos(ImGuiViewport* Viewport) +{ + if (const FImGuiViewportData* ViewportData = static_cast(Viewport->PlatformUserData)) + { + if (const TSharedPtr Widget = ViewportData->Widget.Pin()) + { + return FCogImguiHelper::ToImVec2(Widget->GetTickSpaceGeometry().GetAbsolutePosition()); + } + } + + return ImVec2(0, 0); +} + +//-------------------------------------------------------------------------------------------------------------------------- +void FCogImguiContext::ImGui_SetWindowSize(ImGuiViewport* Viewport, ImVec2 Size) +{ + if (const FImGuiViewportData* ViewportData = static_cast(Viewport->PlatformUserData)) + { + if (const TSharedPtr Window = ViewportData->Window.Pin()) + { + Window->Resize(FCogImguiHelper::ToFVector2D(Size)); + } + } +} + +//-------------------------------------------------------------------------------------------------------------------------- +ImVec2 FCogImguiContext::ImGui_GetWindowSize(ImGuiViewport* Viewport) +{ + if (const FImGuiViewportData* ViewportData = static_cast(Viewport->PlatformUserData)) + { + if (const TSharedPtr Widget = ViewportData->Widget.Pin()) + { + return FCogImguiHelper::ToImVec2(Widget->GetTickSpaceGeometry().GetAbsoluteSize()); + } + } + + return ImVec2(0, 0); +} + +//-------------------------------------------------------------------------------------------------------------------------- +void FCogImguiContext::ImGui_SetWindowFocus(ImGuiViewport* Viewport) +{ + if (const FImGuiViewportData* ViewportData = static_cast(Viewport->PlatformUserData)) + { + if (const TSharedPtr Window = ViewportData->Window.Pin()) + { + if (const TSharedPtr NativeWindow = Window->GetNativeWindow()) + { + NativeWindow->BringToFront(); + NativeWindow->SetWindowFocus(); + } + } + } +} + +//-------------------------------------------------------------------------------------------------------------------------- +bool FCogImguiContext::ImGui_GetWindowFocus(ImGuiViewport* Viewport) +{ + if (const FImGuiViewportData* ViewportData = static_cast(Viewport->PlatformUserData)) + { + if (const TSharedPtr Window = ViewportData->Window.Pin()) + { + if (const TSharedPtr NativeWindow = Window->GetNativeWindow()) + { + return NativeWindow->IsForegroundWindow(); + } + } + } + + return false; +} + +//-------------------------------------------------------------------------------------------------------------------------- +bool FCogImguiContext::ImGui_GetWindowMinimized(ImGuiViewport* Viewport) +{ + if (const FImGuiViewportData* ViewportData = static_cast(Viewport->PlatformUserData)) + { + if (const TSharedPtr Window = ViewportData->Window.Pin()) + { + return Window->IsWindowMinimized(); + } + } + + return false; +} + +//-------------------------------------------------------------------------------------------------------------------------- +void FCogImguiContext::ImGui_SetWindowTitle(ImGuiViewport* Viewport, const char* TitleAnsi) +{ + if (const FImGuiViewportData* ViewportData = static_cast(Viewport->PlatformUserData)) + { + if (const TSharedPtr Window = ViewportData->Window.Pin()) + { + Window->SetTitle(FText::FromString(ANSI_TO_TCHAR(TitleAnsi))); + } + } +} + +//-------------------------------------------------------------------------------------------------------------------------- +void FCogImguiContext::ImGui_SetWindowAlpha(ImGuiViewport* Viewport, float Alpha) +{ + if (const FImGuiViewportData* ViewportData = static_cast(Viewport->PlatformUserData)) + { + if (const TSharedPtr Window = ViewportData->Window.Pin()) + { + Window->SetOpacity(Alpha); + } + } +} + +//-------------------------------------------------------------------------------------------------------------------------- +void FCogImguiContext::ImGui_RenderWindow(ImGuiViewport* Viewport, void* Data) +{ + if (const FImGuiViewportData* ViewportData = static_cast(Viewport->PlatformUserData)) + { + if (const TSharedPtr Widget = ViewportData->Widget.Pin()) + { + Widget->SetDrawData(Viewport->DrawData); + } + } +} + +//-------------------------------------------------------------------------------------------------------------------------- +static UPlayerInput* GetPlayerInput(const UWorld* World) +{ + if (World == nullptr) + { + return nullptr; + } + + APlayerController* PlayerController = nullptr; + for (FConstPlayerControllerIterator Iterator = World->GetPlayerControllerIterator(); Iterator; ++Iterator) + { + APlayerController* ItPlayerController = Iterator->Get(); + if (ItPlayerController->IsLocalController()) + { + PlayerController = ItPlayerController; + break; + } + } + + if (PlayerController == nullptr) + { + return nullptr; + } + + UPlayerInput* PlayerInput = PlayerController->PlayerInput; + return PlayerInput; +} + +//-------------------------------------------------------------------------------------------------------------------------- +void FCogImguiContext::SetEnableInput(bool Value) +{ + bEnableInput = Value; + + if (bEnableInput == false) + { + TryGiveMouseCaptureBackToGame(); + } +} + +//-------------------------------------------------------------------------------------------------------------------------- +void FCogImguiContext::SetShareMouse(bool Value) +{ + bShareMouse = Value; + + if (bEnableInput == false) + { + TryGiveMouseCaptureBackToGame(); + } +} + +//-------------------------------------------------------------------------------------------------------------------------- +void FCogImguiContext::TryReleaseGameMouseCapture() +{ + if (bShareMouse) + { + return; + } + + if (TSharedPtr User = FSlateApplication::Get().GetCursorUser()) + { + if (User->HasCursorCapture()) + { + PreviousMouseCaptor = User->GetCursorCaptor(); + } + } + + if (ULocalPlayer* LocalPlayer = GetLocalPlayer()) + { + LocalPlayer->GetSlateOperations() + .ReleaseMouseLock() + .ReleaseMouseCapture(); + } +} + +//-------------------------------------------------------------------------------------------------------------------------- +void FCogImguiContext::TryGiveMouseCaptureBackToGame() +{ + if (PreviousMouseCaptor.IsValid() == false) + { + return; + } + + TSharedRef PreviousMouseCaptorRef = PreviousMouseCaptor.Pin().ToSharedRef(); + + if (ULocalPlayer* LocalPlayer = GetLocalPlayer()) + { + LocalPlayer->GetSlateOperations().CaptureMouse(PreviousMouseCaptorRef); + } + + PreviousMouseCaptor.Reset(); +} + +//-------------------------------------------------------------------------------------------------------------------------- +void FCogImguiContext::SetDPIScale(float Value) +{ + if (DpiScale == Value) + { + return; + } + + DpiScale = Value; + bRefreshDPIScale = true; +} + +//-------------------------------------------------------------------------------------------------------------------------- +void FCogImguiContext::RefreshDPIScale() +{ + bRefreshDPIScale = false; + + BuildFont(); + + ImGuiStyle NewStyle = ImGuiStyle(); + ImGui::GetStyle() = MoveTemp(NewStyle); + NewStyle.ScaleAllSizes(DpiScale); +} + +//-------------------------------------------------------------------------------------------------------------------------- +void FCogImguiContext::BuildFont() +{ + ImGuiIO& IO = ImGui::GetIO(); + IO.Fonts->Clear(); + + ImFontConfig FontConfig; + FontConfig.SizePixels = FMath::RoundFromZero(13.f * DpiScale); + IO.Fonts->AddFontDefault(&FontConfig); + + uint8* TextureDataRaw; + int32 TextureWidth, TextureHeight, BytesPerPixel; + IO.Fonts->GetTexDataAsRGBA32(&TextureDataRaw, &TextureWidth, &TextureHeight, &BytesPerPixel); + + UTexture2D* FontAtlasTexture = UTexture2D::CreateTransient(TextureWidth, TextureHeight, PF_R8G8B8A8, TEXT("ImGuiFontAtlas")); + FontAtlasTexture->Filter = TF_Bilinear; + FontAtlasTexture->AddressX = TA_Wrap; + FontAtlasTexture->AddressY = TA_Wrap; + + uint8* FontAtlasTextureData = static_cast(FontAtlasTexture->GetPlatformData()->Mips[0].BulkData.Lock(LOCK_READ_WRITE)); + FMemory::Memcpy(FontAtlasTextureData, TextureDataRaw, TextureWidth * TextureHeight * BytesPerPixel); + FontAtlasTexture->GetPlatformData()->Mips[0].BulkData.Unlock(); + FontAtlasTexture->UpdateResource(); + + IO.Fonts->SetTexID(FontAtlasTexture); + FontAtlasTexturePtr.Reset(FontAtlasTexture); +} + +//-------------------------------------------------------------------------------------------------------------------------- +bool FCogImguiContext::IsConsoleOpened() const +{ + return GameViewport->ViewportConsole && GameViewport->ViewportConsole->ConsoleState != NAME_None; +} + +//-------------------------------------------------------------------------------------------------------------------------- +void FCogImguiContext::DrawDebug() +{ + if (ImGui::Begin("ImGui Integration Debug")) + { + ImGui::BeginDisabled(); + + ImVec2 AbsPos = FCogImguiHelper::ToImVec2(MainWidget->GetTickSpaceGeometry().GetAbsolutePosition()); + ImGui::InputFloat2("Widget Abs Pos", &AbsPos.x, "%0.1f"); + + ImVec2 AbsSize = FCogImguiHelper::ToImVec2(MainWidget->GetTickSpaceGeometry().GetAbsoluteSize()); + ImGui::InputFloat2("Widget Abs Size", &AbsSize.x, "%0.1f"); + + ImVec2 LocalSize = FCogImguiHelper::ToImVec2(MainWidget->GetTickSpaceGeometry().GetLocalSize()); + ImGui::InputFloat2("Widget Local Size", &LocalSize.x, "%0.1f"); + + FSlateApplication& SlateApp = FSlateApplication::Get(); + ImVec2 MousePosition = FCogImguiHelper::ToImVec2(SlateApp.GetCursorPos()); + ImGui::InputFloat2("Mouse", &MousePosition.x, "%0.1f"); + + ImGuiIO& IO = ImGui::GetIO(); + ImGui::InputFloat2("ImGui Mouse", &IO.MousePos.x, "%0.1f"); + + FString Focus = "None"; + if (TSharedPtr KeyboardFocusedWidget = SlateApp.GetKeyboardFocusedWidget()) + { + Focus = KeyboardFocusedWidget->ToString(); + } + static char Buffer[256] = ""; + ImStrncpy(Buffer, TCHAR_TO_ANSI(*Focus), IM_ARRAYSIZE(Buffer)); + ImGui::InputText("Keyboard Focus", Buffer, IM_ARRAYSIZE(Buffer)); + + ImGui::EndDisabled(); + } + ImGui::End(); +} + +//-------------------------------------------------------------------------------------------------------------------------- +ULocalPlayer* FCogImguiContext::GetLocalPlayer() const +{ + if (GameViewport == nullptr) + { + return nullptr; + } + + UWorld* World = GameViewport->GetWorld(); + if (World == nullptr) + { + return nullptr; + } + + ULocalPlayer* LocalPlayer = World->GetFirstLocalPlayerFromController(); + return LocalPlayer; +} diff --git a/Plugins/Cog/Source/CogImgui/Private/CogImguiDrawList.cpp b/Plugins/Cog/Source/CogImgui/Private/CogImguiDrawList.cpp index c55e439..303dbcd 100644 --- a/Plugins/Cog/Source/CogImgui/Private/CogImguiDrawList.cpp +++ b/Plugins/Cog/Source/CogImgui/Private/CogImguiDrawList.cpp @@ -1,66 +1,28 @@ #include "CogImguiDrawList.h" +#include "CogImguiHelper.h" + //-------------------------------------------------------------------------------------------------------------------------- -void FCogImguiDrawList::CopyVertexData(TArray& OutVertexBuffer, const FTransform2D& Transform) const +FCogImguiDrawList::FCogImguiDrawList(ImDrawList* Source) { - // Reset and reserve space in destination buffer. - OutVertexBuffer.SetNumUninitialized(ImGuiVertexBuffer.Size, false); - - // Transform and copy vertex data. - for (int Idx = 0; Idx < ImGuiVertexBuffer.Size; Idx++) - { - const ImDrawVert& ImGuiVertex = ImGuiVertexBuffer[Idx]; - FSlateVertex& SlateVertex = OutVertexBuffer[Idx]; - - // Final UV is calculated in shader as XY * ZW, so we need set all components. - SlateVertex.TexCoords[0] = ImGuiVertex.uv.x; - SlateVertex.TexCoords[1] = ImGuiVertex.uv.y; - SlateVertex.TexCoords[2] = SlateVertex.TexCoords[3] = 1.f; - - const FVector2D VertexPosition = Transform.TransformPoint(FCogImguiHelper::ToVector2D(ImGuiVertex.pos)); - SlateVertex.Position[0] = VertexPosition.X; - SlateVertex.Position[1] = VertexPosition.Y; - - // Unpack ImU32 color. - SlateVertex.Color = FCogImguiHelper::UnpackImU32Color(ImGuiVertex.col); - } + VtxBuffer.swap(Source->VtxBuffer); + IdxBuffer.swap(Source->IdxBuffer); + CmdBuffer.swap(Source->CmdBuffer); + Flags = Source->Flags; } //-------------------------------------------------------------------------------------------------------------------------- -FCogImguiDrawList::DrawCommand FCogImguiDrawList::GetCommand(int CommandCount, const FTransform2D& Transform) const +FCogImguiDrawData::FCogImguiDrawData(const ImDrawData* Source) { - const ImDrawCmd& ImGuiCommand = ImGuiCommandBuffer[CommandCount]; - return - { - ImGuiCommand.ElemCount, - TransformRect(Transform, FCogImguiHelper::ToSlateRect(ImGuiCommand.ClipRect)), - FCogImguiHelper::ToTextureIndex(ImGuiCommand.TextureId) - }; -} - -//-------------------------------------------------------------------------------------------------------------------------- -void FCogImguiDrawList::CopyIndexData(TArray& OutIndexBuffer, const int32 StartIndex, const int32 NumElements) const -{ - // Reset buffer. - OutIndexBuffer.SetNumUninitialized(NumElements, false); - - // Copy elements (slow copy because of different sizes of ImDrawIdx and SlateIndex and because SlateIndex can - // have different size on different platforms). - for (int i = 0; i < NumElements; i++) - { - OutIndexBuffer[i] = ImGuiIndexBuffer[StartIndex + i]; - } -} - -//-------------------------------------------------------------------------------------------------------------------------- -void FCogImguiDrawList::TransferDrawData(ImDrawList& Src) -{ - // Move data from source to this list. - Src.CmdBuffer.swap(ImGuiCommandBuffer); - Src.IdxBuffer.swap(ImGuiIndexBuffer); - Src.VtxBuffer.swap(ImGuiVertexBuffer); - - // ImGui seems to clear draw lists in every frame, but since source list can contain pointers to buffers that - // we just swapped, it is better to clear explicitly here. - Src._ResetForNewFrame(); + bValid = Source->Valid; + + TotalIdxCount = Source->TotalIdxCount; + TotalVtxCount = Source->TotalVtxCount; + + DrawLists.SetNumUninitialized(Source->CmdListsCount); + ConstructItems(DrawLists.GetData(), Source->CmdLists.Data, Source->CmdListsCount); + + DisplayPos = FCogImguiHelper::ToFVector2f(Source->DisplayPos); + DisplaySize = FCogImguiHelper::ToFVector2f(Source->DisplaySize); + FrameBufferScale = FCogImguiHelper::ToFVector2f(Source->FramebufferScale); } diff --git a/Plugins/Cog/Source/CogImgui/Private/CogImguiHelper.cpp b/Plugins/Cog/Source/CogImgui/Private/CogImguiHelper.cpp index 4cb08cf..3299f36 100644 --- a/Plugins/Cog/Source/CogImgui/Private/CogImguiHelper.cpp +++ b/Plugins/Cog/Source/CogImgui/Private/CogImguiHelper.cpp @@ -31,7 +31,7 @@ ImGuiWindow* FCogImguiHelper::GetCurrentWindow() } //-------------------------------------------------------------------------------------------------------------------------- -FColor FCogImguiHelper::UnpackImU32Color(ImU32 Color) +FColor FCogImguiHelper::ToFColor(ImU32 Color) { return FColor { @@ -49,7 +49,13 @@ FSlateRect FCogImguiHelper::ToSlateRect(const ImVec4& Value) } //-------------------------------------------------------------------------------------------------------------------------- -FVector2D FCogImguiHelper::ToVector2D(const ImVec2& Value) +FVector2f FCogImguiHelper::ToFVector2f(const ImVec2& Value) +{ + return FVector2f(Value.x, Value.y); +} + +//-------------------------------------------------------------------------------------------------------------------------- +FVector2D FCogImguiHelper::ToFVector2D(const ImVec2& Value) { return FVector2D(Value.x, Value.y); } @@ -90,7 +96,6 @@ ImVec4 FCogImguiHelper::ToImVec4(const FVector4f& Value) return ImVec4(Value.X, Value.Y, Value.Z, Value.W); } - //-------------------------------------------------------------------------------------------------------------------------- ImU32 FCogImguiHelper::ToImU32(const FColor& Value) { diff --git a/Plugins/Cog/Source/CogImgui/Private/CogImguiModule.cpp b/Plugins/Cog/Source/CogImgui/Private/CogImguiModule.cpp index 856d0bb..adf113f 100644 --- a/Plugins/Cog/Source/CogImgui/Private/CogImguiModule.cpp +++ b/Plugins/Cog/Source/CogImgui/Private/CogImguiModule.cpp @@ -1,18 +1,11 @@ #include "CogImguiModule.h" -#include "CogImguiWidget.h" -#include "Engine/Engine.h" -#include "Engine/GameViewportClient.h" +#include "imgui.h" #include "HAL/LowLevelMemTracker.h" #include "HAL/UnrealMemory.h" -#include "Widgets/Layout/SScaleBox.h" #define LOCTEXT_NAMESPACE "FCogImguiModule" -//-------------------------------------------------------------------------------------------------------------------------- - -constexpr int32 Cog_ZOrder = 10000; - //-------------------------------------------------------------------------------------------------------------------------- static void* ImGui_MemAlloc(size_t Size, void* UserData) { @@ -37,64 +30,6 @@ void FCogImguiModule::ShutdownModule() { } -//-------------------------------------------------------------------------------------------------------------------------- -void FCogImguiModule::Initialize() -{ - TextureManager.InitializeErrorTexture(); - TextureManager.CreatePlainTexture("ImGuiModule_Plain", 2, 2, FColor::White); - - unsigned char* Pixels; - int Width, Height, Bpp; - - DefaultFontAtlas.Clear(); - DefaultFontAtlas.GetTexDataAsRGBA32(&Pixels, &Width, &Height, &Bpp); - const CogTextureIndex FontsTexureIndex = TextureManager.CreateTexture("ImGuiModule_FontAtlas", Width, Height, Bpp, Pixels); - DefaultFontAtlas.TexID = FCogImguiHelper::ToImTextureID(FontsTexureIndex); -} - -//-------------------------------------------------------------------------------------------------------------------------- -TSharedPtr FCogImguiModule::CreateImGuiWidget(UGameViewportClient* GameViewport, FCogImguiRenderFunction Render, ImFontAtlas* FontAtlas /*= nullptr*/) -{ - if (bIsInitialized == false) - { - Initialize(); - bIsInitialized = true; - } - - if (FontAtlas == nullptr) - { - FontAtlas = &DefaultFontAtlas; - } - - TSharedPtr ImguiWidget; - SAssignNew(ImguiWidget, SCogImguiWidget) - .GameViewport(GameViewport) - .FontAtlas(FontAtlas) - .Render(Render); - - GameViewport->AddViewportWidgetContent(ImguiWidget.ToSharedRef(), TNumericLimits::Max()); - - return ImguiWidget; -} - -//-------------------------------------------------------------------------------------------------------------------------- -void FCogImguiModule::DestroyImGuiWidget(TSharedPtr ImGuiWidget) -{ - UGameViewportClient* Viewport = ImGuiWidget->GetGameViewport().Get(); - if (Viewport == nullptr) - { - return; - } - - TSharedPtr ParentWidget = ImGuiWidget->GetParentWidget(); - if (ParentWidget.IsValid() == false) - { - return; - } - - Viewport->RemoveViewportWidgetContent(ParentWidget.ToSharedRef()); -} - //-------------------------------------------------------------------------------------------------------------------------- #undef LOCTEXT_NAMESPACE diff --git a/Plugins/Cog/Source/CogImgui/Private/CogImguiTextureManager.cpp b/Plugins/Cog/Source/CogImgui/Private/CogImguiTextureManager.cpp deleted file mode 100644 index 2c323f0..0000000 --- a/Plugins/Cog/Source/CogImgui/Private/CogImguiTextureManager.cpp +++ /dev/null @@ -1,195 +0,0 @@ -#include "CogImguiTextureManager.h" - -#include "Framework/Application/SlateApplication.h" - -//-------------------------------------------------------------------------------------------------------------------------- -void FCogImguiTextureManager::InitializeErrorTexture() -{ - CreatePlainTextureInternal(NAME_ErrorTexture, 2, 2, FColor::Magenta); -} - -//-------------------------------------------------------------------------------------------------------------------------- -CogTextureIndex FCogImguiTextureManager::CreateTexture(const FName& Name, int32 Width, int32 Height, uint32 SrcBpp, uint8* SrcData, TFunction SrcDataCleanup) -{ - checkf(Name != NAME_None, TEXT("Trying to create a texture with a name 'NAME_None' is not allowed.")); - - return CreateTextureInternal(Name, Width, Height, SrcBpp, SrcData, SrcDataCleanup); -} - -//-------------------------------------------------------------------------------------------------------------------------- -CogTextureIndex FCogImguiTextureManager::CreatePlainTexture(const FName& Name, int32 Width, int32 Height, FColor Color) -{ - checkf(Name != NAME_None, TEXT("Trying to create a texture with a name 'NAME_None' is not allowed.")); - - return CreatePlainTextureInternal(Name, Width, Height, Color); -} - -//-------------------------------------------------------------------------------------------------------------------------- -CogTextureIndex FCogImguiTextureManager::CreateTextureResources(const FName& Name, UTexture2D* Texture) -{ - checkf(Name != NAME_None, TEXT("Trying to create texture resources with a name 'NAME_None' is not allowed.")); - checkf(Texture, TEXT("Null Texture.")); - - // Create an entry for the texture. - return AddTextureEntry(Name, Texture, false); -} - -//-------------------------------------------------------------------------------------------------------------------------- -void FCogImguiTextureManager::ReleaseTextureResources(CogTextureIndex Index) -{ - checkf(IsInRange(Index), TEXT("Invalid texture index %d. Texture resources array has %d entries total."), Index, TextureResources.Num()); - - TextureResources[Index] = {}; -} - -//-------------------------------------------------------------------------------------------------------------------------- -CogTextureIndex FCogImguiTextureManager::CreateTextureInternal(const FName& Name, int32 Width, int32 Height, uint32 SrcBpp, uint8* SrcData, TFunction SrcDataCleanup) -{ - // Create a texture. - UTexture2D* Texture = UTexture2D::CreateTransient(Width, Height); - - // Create a new resource for that texture. - Texture->UpdateResource(); - - // Update texture data. - FUpdateTextureRegion2D* TextureRegion = new FUpdateTextureRegion2D(0, 0, 0, 0, Width, Height); - auto DataCleanup = [SrcDataCleanup](uint8* Data, const FUpdateTextureRegion2D* UpdateRegion) - { - SrcDataCleanup(Data); - delete UpdateRegion; - }; - Texture->UpdateTextureRegions(0, 1u, TextureRegion, SrcBpp * Width, SrcBpp, SrcData, DataCleanup); - - // Create an entry for the texture. - if (Name == NAME_ErrorTexture) - { - ErrorTexture = { Name, Texture, true }; - return INDEX_ErrorTexture; - } - else - { - return AddTextureEntry(Name, Texture, true); - } -} - -//-------------------------------------------------------------------------------------------------------------------------- -CogTextureIndex FCogImguiTextureManager::CreatePlainTextureInternal(const FName& Name, int32 Width, int32 Height, const FColor& Color) -{ - // Create buffer with raw data. - const uint32 ColorPacked = Color.ToPackedARGB(); - const uint32 Bpp = sizeof(ColorPacked); - const uint32 SizeInPixels = Width * Height; - const uint32 SizeInBytes = SizeInPixels * Bpp; - uint8* SrcData = new uint8[SizeInBytes]; - std::fill(reinterpret_cast(SrcData), reinterpret_cast(SrcData) + SizeInPixels, ColorPacked); - auto SrcDataCleanup = [](uint8* Data) { delete[] Data; }; - - // Create new texture from raw data. - return CreateTextureInternal(Name, Width, Height, Bpp, SrcData, SrcDataCleanup); -} - -//-------------------------------------------------------------------------------------------------------------------------- -CogTextureIndex FCogImguiTextureManager::AddTextureEntry(const FName& Name, UTexture2D* Texture, bool bAddToRoot) -{ - // Try to find an entry with that name. - CogTextureIndex Index = FindTextureIndex(Name); - - // If this is a new name, try to find an entry to reuse. - if (Index == INDEX_NONE) - { - Index = FindTextureIndex(NAME_None); - } - - // Either update/reuse an entry or add a new one. - if (Index != INDEX_NONE) - { - TextureResources[Index] = { Name, Texture, bAddToRoot }; - return Index; - } - else - { - return TextureResources.Emplace(Name, Texture, bAddToRoot); - } -} - -//-------------------------------------------------------------------------------------------------------------------------- -FCogImguiTextureManager::FTextureEntry::FTextureEntry(const FName& InName, UTexture2D* InTexture, bool bAddToRoot) - : Name(InName) -{ - checkf(InTexture, TEXT("Null texture.")); - - if (bAddToRoot) - { - // Get pointer only for textures that we added to root, so we can later release them. - Texture = InTexture; - // Add texture to the root to prevent garbage collection. - InTexture->AddToRoot(); - } - - // Create brush and resource handle for input texture. - Brush.SetResourceObject(InTexture); - CachedResourceHandle = FSlateApplication::Get().GetRenderer()->GetResourceHandle(Brush); -} - -//-------------------------------------------------------------------------------------------------------------------------- -FCogImguiTextureManager::FTextureEntry::~FTextureEntry() -{ - Reset(true); -} - -//-------------------------------------------------------------------------------------------------------------------------- -FCogImguiTextureManager::FTextureEntry& FCogImguiTextureManager::FTextureEntry::operator=(FTextureEntry&& Other) -{ - // Release old resources if allocated. - Reset(true); - - // Move data and ownership to this instance. - Name = MoveTemp(Other.Name); - Texture = MoveTemp(Other.Texture); - Brush = MoveTemp(Other.Brush); - CachedResourceHandle = MoveTemp(Other.CachedResourceHandle); - - // Reset the other entry (without releasing resources which are already moved to this instance) to remove tracks - // of ownership and mark it as empty/reusable. - Other.Reset(false); - - return *this; -} - -//-------------------------------------------------------------------------------------------------------------------------- -const FSlateResourceHandle& FCogImguiTextureManager::FTextureEntry::GetResourceHandle() const -{ - if (!CachedResourceHandle.IsValid() && Brush.HasUObject()) - { - CachedResourceHandle = FSlateApplication::Get().GetRenderer()->GetResourceHandle(Brush); - } - return CachedResourceHandle; -} - -//-------------------------------------------------------------------------------------------------------------------------- -void FCogImguiTextureManager::FTextureEntry::Reset(bool bReleaseResources) -{ - if (bReleaseResources) - { - // Release brush. - if (Brush.HasUObject() && FSlateApplication::IsInitialized()) - { - FSlateApplication::Get().GetRenderer()->ReleaseDynamicResource(Brush); - } - - // Remove texture from root to allow for garbage collection (it might be invalid, if we never set it - // or this is an application shutdown). - if (Texture.IsValid()) - { - Texture->RemoveFromRoot(); - } - } - - // We use empty name to mark unused entries. - Name = NAME_None; - - // Clean fields to make sure that we don't reference released or moved resources. - Texture.Reset(); - Brush = FSlateNoResource(); - CachedResourceHandle = FSlateResourceHandle(); -} diff --git a/Plugins/Cog/Source/CogImgui/Private/CogImguiWidget.cpp b/Plugins/Cog/Source/CogImgui/Private/CogImguiWidget.cpp index f170fad..a5a16f6 100644 --- a/Plugins/Cog/Source/CogImgui/Private/CogImguiWidget.cpp +++ b/Plugins/Cog/Source/CogImgui/Private/CogImguiWidget.cpp @@ -1,227 +1,32 @@ #include "CogImguiWidget.h" #include "CogImguiInputHelper.h" -#include "CogImguiInputHelper.h" -#include "CogImGuiInputProcessor.h" #include "CogImguiModule.h" -#include "CogImguiModule.h" -#include "CogImguiTextureManager.h" #include "CogImguiWidget.h" -#include "Engine/Console.h" -#include "Engine/GameViewportClient.h" -#include "Engine/LocalPlayer.h" -#include "Framework/Application/SlateApplication.h" -#include "GameFramework/PlayerController.h" #include "imgui.h" -#include "imgui_internal.h" -#include "implot.h" #include "SlateOptMacros.h" -#include "UnrealClient.h" -#include "Widgets/Layout/SBorder.h" -#include "Widgets/Layout/SBox.h" -#include "Widgets/SViewport.h" //-------------------------------------------------------------------------------------------------------------------------- BEGIN_SLATE_FUNCTION_BUILD_OPTIMIZATION void SCogImguiWidget::Construct(const FArguments& InArgs) { - checkf(InArgs._GameViewport, TEXT("Null Game Viewport argument")); - - GameViewport = InArgs._GameViewport; - FontAtlas = InArgs._FontAtlas; - Render = InArgs._Render; + Context = InArgs._Context; SetVisibility(EVisibility::SelfHitTestInvisible); - - ImGuiContext = ImGui::CreateContext(FontAtlas); - ImPlotContext = ImPlot::CreateContext(); - ImPlot::SetImGuiContext(ImGuiContext); - - const char* InitFilenameTemp = TCHAR_TO_ANSI(*FCogImguiHelper::GetIniFilePath("imgui")); - ImStrncpy(IniFilename, InitFilenameTemp, IM_ARRAYSIZE(IniFilename)); - - ImGuiIO& IO = ImGui::GetIO(); - IO.IniFilename = IniFilename; - IO.DisplaySize = ImVec2(100, 100); - IO.ConfigFlags |= ImGuiConfigFlags_DockingEnable; - IO.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard; - IO.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad; - IO.ConfigFlags |= ImGuiConfigFlags_NavNoCaptureKeyboard; - - //-------------------------------------------------------------------- - // Register input processor to forward input events to imgui - //-------------------------------------------------------------------- - if (FSlateApplication::IsInitialized()) - { - UPlayerInput* PlayerInput = FCogImguiInputHelper::GetPlayerInput(*GameViewport->GetWorld()); - InputProcessor = MakeShared(PlayerInput, this); - FSlateApplication::Get().RegisterInputPreProcessor(InputProcessor.ToSharedRef(), 0); - } } END_SLATE_FUNCTION_BUILD_OPTIMIZATION //-------------------------------------------------------------------------------------------------------------------------- SCogImguiWidget::~SCogImguiWidget() { - if (FSlateApplication::IsInitialized()) - { - if (InputProcessor.IsValid()) - { - FSlateApplication::Get().UnregisterInputPreProcessor(InputProcessor); - } - } - - DestroyImGuiContext(); } //-------------------------------------------------------------------------------------------------------------------------- -void SCogImguiWidget::DestroyImGuiContext() +void SCogImguiWidget::SetDrawData(const ImDrawData* InDrawData) { - if (ImPlotContext != nullptr) - { - ImPlot::DestroyContext(ImPlotContext); - ImPlotContext = nullptr; - } - - if (ImGuiContext != nullptr) - { - ImGui::DestroyContext(ImGuiContext); - ImGuiContext = nullptr; - } + DrawData = FCogImguiDrawData(InDrawData); } -//-------------------------------------------------------------------------------------------------------------------------- -void SCogImguiWidget::Tick(const FGeometry& AllottedGeometry, const double InCurrentTime, const float InDeltaTime) -{ - Super::Tick(AllottedGeometry, InCurrentTime, InDeltaTime); - - TickKeyModifiers(); - TickFocus(); - TickImGui(InDeltaTime); -} - -//-------------------------------------------------------------------------------------------------------------------------- -void SCogImguiWidget::TickKeyModifiers() -{ - //------------------------------------------------------------------------------------------------------- - // Refresh modifiers otherwise, when pressing ALT-TAB, the Alt modifier is always true - //------------------------------------------------------------------------------------------------------- - FModifierKeysState ModifierKeys = FSlateApplication::Get().GetModifierKeys(); - - ImGuiIO& IO = ImGui::GetIO(); - if (ModifierKeys.IsControlDown() != IO.KeyCtrl) { IO.AddKeyEvent(ImGuiMod_Ctrl, ModifierKeys.IsControlDown()); } - if (ModifierKeys.IsShiftDown() != IO.KeyShift) { IO.AddKeyEvent(ImGuiMod_Shift, ModifierKeys.IsShiftDown()); } - if (ModifierKeys.IsAltDown() != IO.KeyAlt) { IO.AddKeyEvent(ImGuiMod_Alt, ModifierKeys.IsAltDown()); } - if (ModifierKeys.IsCommandDown() != IO.KeySuper) { IO.AddKeyEvent(ImGuiMod_Super, ModifierKeys.IsCommandDown()); } -} - -//-------------------------------------------------------------------------------------------------------------------------- -void SCogImguiWidget::TickImGui(float InDeltaTime) -{ - if (ImGuiContext == nullptr) - { - return; - } - - ImGui::SetCurrentContext(ImGuiContext); - ImPlot::SetImGuiContext(ImGuiContext); - ImPlot::SetCurrentContext(ImPlotContext); - - ImGuiIO& IO = ImGui::GetIO(); - IO.DeltaTime = FApp::GetDeltaTime(); - IO.DisplaySize = FCogImguiHelper::ToImVec2(GetTickSpaceGeometry().GetAbsoluteSize()); - - ImGui::NewFrame(); - - Render(InDeltaTime); - //DrawDebug(); - - ImGui::Render(); - - if ((IO.ConfigFlags & ImGuiConfigFlags_NoMouse) == 0) - { - SetCursor(FCogImguiInputHelper::ToSlateMouseCursor(ImGui::GetMouseCursor())); - } - - ImDrawData* DrawData = ImGui::GetDrawData(); - if (DrawData && DrawData->CmdListsCount > 0) - { - DrawLists.SetNum(DrawData->CmdListsCount, false); - for (int i = 0; i < DrawData->CmdListsCount; i++) - { - DrawLists[i].TransferDrawData(*DrawData->CmdLists[i]); - } - } - else - { - DrawLists.Empty(); - } -} - -//-------------------------------------------------------------------------------------------------------------------------- -void SCogImguiWidget::TickFocus() -{ - if (bEnableInput) - { - const auto& ViewportWidget = GameViewport->GetGameViewportWidget(); - if (!HasKeyboardFocus() && !IsConsoleOpened() && (ViewportWidget->HasKeyboardFocus() || ViewportWidget->HasFocusedDescendants())) - { - TakeFocus(); - } - } -} - -//-------------------------------------------------------------------------------------------------------------------------- -void SCogImguiWidget::TakeFocus() -{ - FSlateApplication& SlateApplication = FSlateApplication::Get(); - - PreviousUserFocusedWidget = SlateApplication.GetUserFocusedWidget(SlateApplication.GetUserIndexForKeyboard()); - - if (ULocalPlayer* LocalPlayer = GetLocalPlayer()) - { - TSharedRef FocusWidget = SharedThis(this); - LocalPlayer->GetSlateOperations().CaptureMouse(FocusWidget); - LocalPlayer->GetSlateOperations().SetUserFocus(FocusWidget); - } - else - { - SlateApplication.SetKeyboardFocus(SharedThis(this)); - } -} - -//-------------------------------------------------------------------------------------------------------------------------- -void SCogImguiWidget::ReturnFocus() -{ - if (HasKeyboardFocus()) - { - auto FocusWidgetPtr = PreviousUserFocusedWidget.IsValid() - ? PreviousUserFocusedWidget.Pin() - : GameViewport->GetGameViewportWidget(); - - if (ULocalPlayer* LocalPlayer = GetLocalPlayer()) - { - auto FocusWidgetRef = FocusWidgetPtr.ToSharedRef(); - - if (FocusWidgetPtr == GameViewport->GetGameViewportWidget()) - { - LocalPlayer->GetSlateOperations().CaptureMouse(FocusWidgetRef); - } - - LocalPlayer->GetSlateOperations().SetUserFocus(FocusWidgetRef); - } - else - { - FSlateApplication& SlateApplication = FSlateApplication::Get(); - SlateApplication.ResetToDefaultPointerInputSettings(); - SlateApplication.SetUserFocus(SlateApplication.GetUserIndexForKeyboard(), FocusWidgetPtr); - } - } - - PreviousUserFocusedWidget.Reset(); -} - - //-------------------------------------------------------------------------------------------------------------------------- int32 SCogImguiWidget::OnPaint( const FPaintArgs& Args, @@ -233,36 +38,56 @@ int32 SCogImguiWidget::OnPaint( bool bParentEnabled) const { - const FSlateRenderTransform& WidgetToScreen = AllottedGeometry.GetAccumulatedRenderTransform().GetTranslation(); - const FSlateRenderTransform ImGuiToScreen = FCogImguiHelper::RoundTranslation(ImGuiRenderTransform.Concatenate(WidgetToScreen)); + const FSlateRenderTransform Transform(FCogImguiHelper::RoundTranslation(AllottedGeometry.GetAccumulatedRenderTransform().GetTranslation() - FVector2d(DrawData.DisplayPos))); - FCogImguiTextureManager& TextureManager = FCogImguiModule::Get().GetTextureManager(); - - for (const auto& DrawList : DrawLists) + FSlateBrush TextureBrush; + for (const FCogImguiDrawList& DrawList : DrawData.DrawLists) { - DrawList.CopyVertexData(VertexBuffer, ImGuiToScreen); - - int IndexBufferOffset = 0; - for (int i = 0; i < DrawList.NumCommands(); i++) + TArray Vertices; + Vertices.SetNumUninitialized(DrawList.VtxBuffer.Size); + for (int32 BufferIdx = 0; BufferIdx < Vertices.Num(); ++BufferIdx) { - const auto& DrawCommand = DrawList.GetCommand(i, ImGuiToScreen); + const ImDrawVert& Vtx = DrawList.VtxBuffer.Data[BufferIdx]; + Vertices[BufferIdx] = FSlateVertex::Make(Transform, FCogImguiHelper::ToFVector2f(Vtx.pos), FCogImguiHelper::ToFVector2f(Vtx.uv), FVector2f::UnitVector, FCogImguiHelper::ToFColor(Vtx.col)); + } - DrawList.CopyIndexData(IndexBuffer, IndexBufferOffset, DrawCommand.NumElements); + TArray Indices; + Indices.SetNumUninitialized(DrawList.IdxBuffer.Size); + for (int32 BufferIdx = 0; BufferIdx < Indices.Num(); ++BufferIdx) + { + Indices[BufferIdx] = DrawList.IdxBuffer.Data[BufferIdx]; + } - // Advance offset by number of copied elements to position it for the next command. - IndexBufferOffset += DrawCommand.NumElements; + for (const ImDrawCmd& DrawCmd : DrawList.CmdBuffer) + { + TArray VerticesSlice(Vertices.GetData() + DrawCmd.VtxOffset, Vertices.Num() - DrawCmd.VtxOffset); + TArray IndicesSlice(Indices.GetData() + DrawCmd.IdxOffset, DrawCmd.ElemCount); - // Get texture resource handle for this draw command (null index will be also mapped to a valid texture). - const FSlateResourceHandle& Handle = TextureManager.GetTextureHandle(DrawCommand.TextureId); + UTexture2D* Texture = DrawCmd.GetTexID(); + if (TextureBrush.GetResourceObject() != Texture) + { + TextureBrush.SetResourceObject(Texture); + if (IsValid(Texture)) + { + TextureBrush.ImageSize.X = Texture->GetSizeX(); + TextureBrush.ImageSize.Y = Texture->GetSizeY(); + TextureBrush.ImageType = ESlateBrushImageType::FullColor; + TextureBrush.DrawAs = ESlateBrushDrawType::Image; + } + else + { + TextureBrush.ImageSize.X = 0; + TextureBrush.ImageSize.Y = 0; + TextureBrush.ImageType = ESlateBrushImageType::NoImage; + TextureBrush.DrawAs = ESlateBrushDrawType::NoDrawType; + } + } - // Transform clipping rectangle to screen space and apply to elements that we draw. - const FSlateRect ClippingRect = DrawCommand.ClippingRect.IntersectionWith(MyClippingRect); - - OutDrawElements.PushClip(FSlateClippingZone{ ClippingRect }); - - // Add elements to the list. - FSlateDrawElement::MakeCustomVerts(OutDrawElements, LayerId, Handle, VertexBuffer, IndexBuffer, nullptr, 0, 0); + FSlateRect ClipRect(DrawCmd.ClipRect.x, DrawCmd.ClipRect.y, DrawCmd.ClipRect.z, DrawCmd.ClipRect.w); + ClipRect = TransformRect(Transform, ClipRect); + OutDrawElements.PushClip(FSlateClippingZone(ClipRect)); + FSlateDrawElement::MakeCustomVerts(OutDrawElements, LayerId, TextureBrush.GetRenderingResource(), VerticesSlice, IndicesSlice, nullptr, 0, 0); OutDrawElements.PopClip(); } } @@ -274,128 +99,22 @@ int32 SCogImguiWidget::OnPaint( FVector2D SCogImguiWidget::ComputeDesiredSize(float Scale) const { return FVector2D::ZeroVector; - //return Super::ComputeDesiredSize(Scale); } -//-------------------------------------------------------------------------------------------------------------------------- -ULocalPlayer* SCogImguiWidget::GetLocalPlayer() const -{ - if (GameViewport.IsValid() == false) - { - return nullptr; - } - - UWorld* World = GameViewport->GetWorld(); - if (World == nullptr) - { - return nullptr; - } - - ULocalPlayer* LocalPlayer = World->GetFirstLocalPlayerFromController(); - return LocalPlayer; -} - -//-------------------------------------------------------------------------------------------------------------------------- -FVector2D SCogImguiWidget::TransformScreenPointToImGui(const FGeometry& MyGeometry, const FVector2D& Point) const -{ - const FSlateRenderTransform ImGuiToScreen = MyGeometry.GetAccumulatedRenderTransform(); - return ImGuiToScreen.Inverse().TransformPoint(Point); -} - -//-------------------------------------------------------------------------------------------------------------------------- -bool SCogImguiWidget::IsConsoleOpened() const -{ - return GameViewport->ViewportConsole && GameViewport->ViewportConsole->ConsoleState != NAME_None; -} - -//-------------------------------------------------------------------------------------------------------------------------- -bool SCogImguiWidget::IsCurrentContext() const -{ - return ImGui::GetCurrentContext() == ImGuiContext; -} - -//-------------------------------------------------------------------------------------------------------------------------- -void SCogImguiWidget::SetAsCurrentContext() -{ - ImGui::SetCurrentContext(ImGuiContext); -} - -//-------------------------------------------------------------------------------------------------------------------------- -void SCogImguiWidget::SetEnableInput(bool Value) -{ - bEnableInput = Value; - - if (bEnableInput) - { - TakeFocus(); - } - else - { - ReturnFocus(); - } - - ImGuiIO& IO = ImGui::GetIO(); - if (bEnableInput) - { - IO.ConfigFlags &= ~ImGuiConfigFlags_NoMouse; - } - else - { - IO.ConfigFlags |= ImGuiConfigFlags_NoMouse; - } -} - -//-------------------------------------------------------------------------------------------------------------------------- -void SCogImguiWidget::SetDPIScale(float Value) -{ - if (DpiScale == Value) - { - return; - } - - DpiScale = Value; - OnDpiChanged(); -} - -//-------------------------------------------------------------------------------------------------------------------------- -void SCogImguiWidget::OnDpiChanged() -{ - if (FontAtlas == nullptr) - { - return; - } - - FontAtlas->Clear(); - - ImFontConfig FontConfig = {}; - FontConfig.SizePixels = FMath::RoundFromZero(13.f * DpiScale); - FontAtlas->AddFontDefault(&FontConfig); - - unsigned char* Pixels; - int Width, Height, Bpp; - FontAtlas->GetTexDataAsRGBA32(&Pixels, &Width, &Height, &Bpp); - const CogTextureIndex FontsTexureIndex = FCogImguiModule::Get().GetTextureManager().CreateTexture("xx", Width, Height, Bpp, Pixels); - FontAtlas->TexID = FCogImguiHelper::ToImTextureID(FontsTexureIndex); - - ImGuiStyle NewStyle = ImGuiStyle(); - ImGui::GetStyle() = MoveTemp(NewStyle); - NewStyle.ScaleAllSizes(DpiScale); -} - -//-------------------------------------------------------------------------------------------------------------------------- -FReply SCogImguiWidget::OnFocusReceived(const FGeometry& MyGeometry, const FFocusEvent& FocusEvent) -{ - if (bEnableInput == false) - { - return FReply::Unhandled(); - } - - Super::OnFocusReceived(MyGeometry, FocusEvent); - - FSlateApplication::Get().ResetToDefaultPointerInputSettings(); - - return FReply::Handled(); -} +////-------------------------------------------------------------------------------------------------------------------------- +//FReply SCogImguiWidget::OnFocusReceived(const FGeometry& MyGeometry, const FFocusEvent& FocusEvent) +//{ +// if (bEnableInput == false) +// { +// return FReply::Unhandled(); +// } +// +// Super::OnFocusReceived(MyGeometry, FocusEvent); +// +// FSlateApplication::Get().ResetToDefaultPointerInputSettings(); +// +// return FReply::Handled(); +//} //-------------------------------------------------------------------------------------------------------------------------- FReply SCogImguiWidget::OnKeyChar(const FGeometry& MyGeometry, const FCharacterEvent& CharacterEvent) @@ -408,33 +127,4 @@ FReply SCogImguiWidget::OnKeyChar(const FGeometry& MyGeometry, const FCharacterE } -//-------------------------------------------------------------------------------------------------------------------------- -void SCogImguiWidget::DrawDebug() -{ - if (ImGui::Begin("ImGui Integration Debug")) - { - ImGui::BeginDisabled(); - - ImVec2 AbsPos = FCogImguiHelper::ToImVec2(GetTickSpaceGeometry().GetAbsolutePosition()); - ImGui::InputFloat2("Widget Abs Pos", &AbsPos.x, "%0.1f"); - - ImVec2 AbsSize = FCogImguiHelper::ToImVec2(GetTickSpaceGeometry().GetAbsoluteSize()); - ImGui::InputFloat2("Widget Abs Size", &AbsSize.x, "%0.1f"); - - ImVec2 LocalSize = FCogImguiHelper::ToImVec2(GetTickSpaceGeometry().GetLocalSize()); - ImGui::InputFloat2("Widget Local Size", &LocalSize.x, "%0.1f"); - - FSlateApplication& SlateApp = FSlateApplication::Get(); - ImVec2 MousePosition = FCogImguiHelper::ToImVec2(SlateApp.GetCursorPos()); - ImGui::InputFloat2("Mouse", &MousePosition.x, "%0.1f"); - - ImGuiIO& IO = ImGui::GetIO(); - ImGui::InputFloat2("ImGui Mouse", &IO.MousePos.x, "%0.1f"); - - ImGui::EndDisabled(); - } - ImGui::End(); -} - - diff --git a/Plugins/Cog/Source/CogImgui/Public/CogImGuiInputProcessor.h b/Plugins/Cog/Source/CogImgui/Public/CogImGuiInputProcessor.h index c5d075c..508c874 100644 --- a/Plugins/Cog/Source/CogImgui/Public/CogImGuiInputProcessor.h +++ b/Plugins/Cog/Source/CogImgui/Public/CogImGuiInputProcessor.h @@ -2,6 +2,7 @@ #include "Framework/Application/IInputProcessor.h" +class FCogImguiContext; class SCogImguiWidget; class UPlayerInput; enum ImGuiKey : int; @@ -11,7 +12,7 @@ class FImGuiInputProcessor : public IInputProcessor { public: - FImGuiInputProcessor(UPlayerInput* InPlayerInput, SCogImguiWidget* InWidget); + FImGuiInputProcessor(UPlayerInput* InPlayerInput, FCogImguiContext* InContext, SCogImguiWidget* InWidget); virtual void Tick(const float DeltaTime, FSlateApplication& SlateApp, TSharedRef SlateCursor) override; @@ -37,6 +38,8 @@ protected: bool HandleMouseButtonEvent(FSlateApplication& SlateApp, const FPointerEvent& Event, bool IsButtonDown); + bool IsMouseInsideMainViewport(); + void AddMousePosEvent(const FVector2D& MousePosition) const; bool IsKeyBoundToCommand(const FKeyEvent& KeyEvent); @@ -51,6 +54,8 @@ protected: static uint32 ToImGuiMouseButton(const FKey& MouseButton); + TObjectPtr Context = nullptr; + TObjectPtr PlayerInput = nullptr; TObjectPtr MainWidget = nullptr; diff --git a/Plugins/Cog/Source/CogImgui/Public/CogImguiContext.h b/Plugins/Cog/Source/CogImgui/Public/CogImguiContext.h new file mode 100644 index 0000000..62c6176 --- /dev/null +++ b/Plugins/Cog/Source/CogImgui/Public/CogImguiContext.h @@ -0,0 +1,117 @@ +#pragma once + +#include "CoreMinimal.h" +#include "Engine/Texture2D.h" +#include "Templates/SharedPointer.h" +#include "UObject/StrongObjectPtr.h" +#include "imgui.h" + +class FCogImguiContext; +class IInputProcessor; +class SCogImguiWidget; +class SCogImguiWidget; +class SWindow; +class UGameViewportClient; +struct FDisplayMetrics; +struct ImPlotContext; + +struct COGIMGUI_API FImGuiViewportData +{ + TWeakPtr Window = nullptr; + TObjectPtr Context = nullptr; + TWeakPtr Widget = nullptr; +}; + +class COGIMGUI_API FCogImguiContext : public TSharedFromThis +{ +public: + void Initialize(); + + void Shutdown(); + + bool GetEnableInput() const { return bEnableInput; } + + void SetEnableInput(bool Value); + + bool GetShareMouse() const { return bShareMouse; } + + void SetShareMouse(bool Value); + + void BeginFrame(float InDeltaTime); + + void EndFrame(); + + float GetDpiScale() const { return DpiScale; } + + void SetDPIScale(float Value); + +private: + + void OnDisplayMetricsChanged(const FDisplayMetrics& DisplayMetrics) const; + + bool IsConsoleOpened() const; + + void DrawDebug(); + + void TryGiveMouseCaptureBackToGame(); + + void TryReleaseGameMouseCapture(); + + void RefreshDPIScale(); + + void BuildFont(); + + ULocalPlayer* GetLocalPlayer() const; + + static void ImGui_CreateWindow(ImGuiViewport* Viewport); + + static void ImGui_DestroyWindow(ImGuiViewport* Viewport); + + static void ImGui_ShowWindow(ImGuiViewport* Viewport); + + static void ImGui_SetWindowPos(ImGuiViewport* Viewport, ImVec2 Pos); + + static ImVec2 ImGui_GetWindowPos(ImGuiViewport* Viewport); + + static void ImGui_SetWindowSize(ImGuiViewport* Viewport, ImVec2 Size); + + static ImVec2 ImGui_GetWindowSize(ImGuiViewport* Viewport); + + static void ImGui_SetWindowFocus(ImGuiViewport* Viewport); + + static bool ImGui_GetWindowFocus(ImGuiViewport* Viewport); + + static bool ImGui_GetWindowMinimized(ImGuiViewport* Viewport); + + static void ImGui_SetWindowTitle(ImGuiViewport* Viewport, const char* TitleAnsi); + + static void ImGui_SetWindowAlpha(ImGuiViewport* Viewport, float Alpha); + + static void ImGui_RenderWindow(ImGuiViewport* Viewport, void* Data); + + TMap, ImGuiID> WindowToViewportMap; + + TSharedPtr InputProcessor = nullptr; + + TStrongObjectPtr FontAtlasTexturePtr = nullptr; + + TSharedPtr MainWidget = nullptr; + + TWeakPtr PreviousMouseCaptor = nullptr; + + TObjectPtr GameViewport = nullptr; + + ImGuiContext* ImGuiContext = nullptr; + + ImPlotContext* PlotContext = nullptr; + + char IniFilename[512] = {}; + + bool bEnableInput = false; + + bool bShareMouse = true; + + float DpiScale = 1.f; + + bool bRefreshDPIScale = false; +}; diff --git a/Plugins/Cog/Source/CogImgui/Public/CogImguiDrawList.h b/Plugins/Cog/Source/CogImgui/Public/CogImguiDrawList.h index 623ab5b..415f155 100644 --- a/Plugins/Cog/Source/CogImgui/Public/CogImguiDrawList.h +++ b/Plugins/Cog/Source/CogImgui/Public/CogImguiDrawList.h @@ -6,44 +6,39 @@ #include "Rendering/RenderingCommon.h" //-------------------------------------------------------------------------------------------------------------------------- -class FCogImguiDrawList +struct FCogImguiDrawList { -public: + FCogImguiDrawList() {}; + + FCogImguiDrawList(ImDrawList* Source); - struct DrawCommand - { - uint32 NumElements; - FSlateRect ClippingRect; - CogTextureIndex TextureId; - }; + ImVector VtxBuffer; + + ImVector IdxBuffer; + + ImVector CmdBuffer; - // Get the number of draw commands in this list. - FORCEINLINE int NumCommands() const { return ImGuiCommandBuffer.Size; } - - // Get the draw command by number. - // @param CommandNb - Number of draw command - // @param Transform - Transform to apply to clipping rectangle - // @returns Draw command data - DrawCommand GetCommand(int CommandCount, const FTransform2D& Transform) const; - - // Transform and copy vertex data to target buffer (old data in the target buffer are replaced). - // @param OutVertexBuffer - Destination buffer - // @param Transform - Transform to apply to all vertices - void CopyVertexData(TArray& OutVertexBuffer, const FTransform2D& Transform) const; - - // Transform and copy index data to target buffer (old data in the target buffer are replaced). - // Internal index buffer contains enough data to match the sum of NumElements from all draw commands. - // @param OutIndexBuffer - Destination buffer - // @param StartIndex - Start copying source data starting from this index - // @param NumElements - How many elements we want to copy - void CopyIndexData(TArray& OutIndexBuffer, const int32 StartIndex, const int32 NumElements) const; - - // Transfers data from ImGui source list to this object. Leaves source cleared. - void TransferDrawData(ImDrawList& Src); - -private: - - ImVector ImGuiCommandBuffer; - ImVector ImGuiIndexBuffer; - ImVector ImGuiVertexBuffer; + ImDrawListFlags Flags = ImDrawListFlags_None; }; + +//-------------------------------------------------------------------------------------------------------------------------- +struct FCogImguiDrawData +{ + FCogImguiDrawData() {}; + + FCogImguiDrawData(const ImDrawData* Source); + + bool bValid = false; + + int32 TotalIdxCount = 0; + + int32 TotalVtxCount = 0; + + TArray DrawLists; + + FVector2f DisplayPos = FVector2f::ZeroVector; + + FVector2f DisplaySize = FVector2f::ZeroVector; + + FVector2f FrameBufferScale = FVector2f::ZeroVector; +}; \ No newline at end of file diff --git a/Plugins/Cog/Source/CogImgui/Public/CogImguiHelper.h b/Plugins/Cog/Source/CogImgui/Public/CogImguiHelper.h index 858f6e9..b54f84a 100644 --- a/Plugins/Cog/Source/CogImgui/Public/CogImguiHelper.h +++ b/Plugins/Cog/Source/CogImgui/Public/CogImguiHelper.h @@ -20,11 +20,13 @@ public: static ImGuiWindow* GetCurrentWindow(); - static FColor UnpackImU32Color(ImU32 Color); + static FColor ToFColor(ImU32 Color); static FSlateRect ToSlateRect(const ImVec4& Value); - static FVector2D ToVector2D(const ImVec2& Value); + static FVector2f ToFVector2f(const ImVec2& Value); + + static FVector2D ToFVector2D(const ImVec2& Value); static ImVec2 ToImVec2(const FVector2D& Value); diff --git a/Plugins/Cog/Source/CogImgui/Public/CogImguiModule.h b/Plugins/Cog/Source/CogImgui/Public/CogImguiModule.h index f5d95a6..73a474c 100644 --- a/Plugins/Cog/Source/CogImgui/Public/CogImguiModule.h +++ b/Plugins/Cog/Source/CogImgui/Public/CogImguiModule.h @@ -1,10 +1,6 @@ #pragma once #include "CoreMinimal.h" -#include "CogImguiWidget.h" -#include "CogImguiKeyInfo.h" -#include "CogImguiTextureManager.h" -#include "imgui.h" #include "Modules/ModuleManager.h" class COGIMGUI_API FCogImguiModule : public IModuleInterface @@ -22,22 +18,6 @@ public: virtual void StartupModule() override; virtual void ShutdownModule() override; - //---------------------------------------------------------------------------------------------------------------------- - TSharedPtr CreateImGuiWidget(UGameViewportClient* GameViewport, FCogImguiRenderFunction Render, ImFontAtlas* FontAtlas = nullptr); - - void DestroyImGuiWidget(TSharedPtr ImGuiWidget); - - FCogImguiTextureManager& GetTextureManager() { return TextureManager; } - - ImFontAtlas& GetDefaultFontAtlas() { return DefaultFontAtlas; } - private: - void Initialize(); - - FCogImguiTextureManager TextureManager; - - ImFontAtlas DefaultFontAtlas; - - bool bIsInitialized = false; }; diff --git a/Plugins/Cog/Source/CogImgui/Public/CogImguiTextureManager.h b/Plugins/Cog/Source/CogImgui/Public/CogImguiTextureManager.h deleted file mode 100644 index e690465..0000000 --- a/Plugins/Cog/Source/CogImgui/Public/CogImguiTextureManager.h +++ /dev/null @@ -1,147 +0,0 @@ -#pragma once - -#include "CoreMinimal.h" -#include "CogImguiHelper.h" -#include "Engine/Texture2D.h" -#include "Styling/SlateBrush.h" -#include "Textures/SlateShaderResource.h" -#include "UObject/WeakObjectPtr.h" - -//-------------------------------------------------------------------------------------------------------------------------- -class FCogImguiTextureManager -{ -public: - - // Creates an empty manager. - FCogImguiTextureManager() = default; - - // Copying is disabled to protected resource ownership. - FCogImguiTextureManager(const FCogImguiTextureManager&) = delete; - FCogImguiTextureManager& operator=(const FCogImguiTextureManager&) = delete; - - // Moving transfers ownership and leaves source empty. - FCogImguiTextureManager(FCogImguiTextureManager&&) = delete; - FCogImguiTextureManager& operator=(FCogImguiTextureManager&&) = delete; - - void InitializeErrorTexture(); - - // Find texture index by name. - // @param Name - The name of a texture to find - // @returns The index of a texture with given name or INDEX_NONE if there is no such texture - CogTextureIndex FindTextureIndex(const FName& Name) const - { - return TextureResources.IndexOfByPredicate([&](const auto& Entry) { return Entry.GetName() == Name; }); - } - - // Get the name of a texture at given index. Returns NAME_None, if index is out of range. - // @param Index - Index of a texture - // @returns The name of a texture at given index or NAME_None if index is out of range. - FName GetTextureName(CogTextureIndex Index) const - { - return IsInRange(Index) ? TextureResources[Index].GetName() : NAME_None; - } - - // Get the Slate Resource Handle to a texture at given index. If index is out of range or resources are not valid - // it returns a handle to the error texture. - // @param Index - Index of a texture - // @returns The Slate Resource Handle for a texture at given index or to error texture, if no valid resources were - // found at given index - const FSlateResourceHandle& GetTextureHandle(CogTextureIndex Index) const - { - return IsValidTexture(Index) ? TextureResources[Index].GetResourceHandle() : ErrorTexture.GetResourceHandle(); - } - - // Create a texture from raw data. - // @param Name - The texture name - // @param Width - The texture width - // @param Height - The texture height - // @param SrcBpp - The size in bytes of one pixel - // @param SrcData - The source data - // @param SrcDataCleanup - Optional function called to release source data after texture is created (only needed, if data need to be released) - // @returns The index of a texture that was created - CogTextureIndex CreateTexture(const FName& Name, int32 Width, int32 Height, uint32 SrcBpp, uint8* SrcData, TFunction SrcDataCleanup = [](uint8*) {}); - - // Create a plain texture. - // @param Name - The texture name - // @param Width - The texture width - // @param Height - The texture height - // @param Color - The texture color - // @returns The index of a texture that was created - CogTextureIndex CreatePlainTexture(const FName& Name, int32 Width, int32 Height, FColor Color); - - // Create Slate resources to an existing texture, managed externally. - // @param Name - The texture name - // @param Texture - The texture - // @returns The index to created/updated texture resources - CogTextureIndex CreateTextureResources(const FName& Name, UTexture2D* Texture); - - // Release resources for given texture. Ignores invalid indices. - // @param Index - The index of a texture resources - void ReleaseTextureResources(CogTextureIndex Index); - -private: - - // See CreateTexture for general description. - // Internal implementations doesn't validate name or resource uniqueness. Instead it uses NAME_ErrorTexture - // (aka NAME_None) and INDEX_ErrorTexture (aka INDEX_NONE) to identify ErrorTexture. - CogTextureIndex CreateTextureInternal(const FName& Name, int32 Width, int32 Height, uint32 SrcBpp, uint8* SrcData, TFunction SrcDataCleanup = [](uint8*) {}); - - // See CreatePlainTexture for general description. - // Internal implementations doesn't validate name or resource uniqueness. Instead it uses NAME_ErrorTexture - // (aka NAME_None) and INDEX_ErrorTexture (aka INDEX_NONE) to identify ErrorTexture. - CogTextureIndex CreatePlainTextureInternal(const FName& Name, int32 Width, int32 Height, const FColor& Color); - - // Add or reuse texture entry. - // @param Name - The texture name - // @param Texture - The texture - // @param bAddToRoot - If true, we should add texture to root to prevent garbage collection (use for own textures) - // @returns The index of the entry that we created or reused - CogTextureIndex AddTextureEntry(const FName& Name, UTexture2D* Texture, bool bAddToRoot); - - // Check whether index is in range allocated for TextureResources (it doesn't mean that resources are valid). - FORCEINLINE bool IsInRange(CogTextureIndex Index) const - { - return static_cast(Index) < static_cast(TextureResources.Num()); - } - - // Check whether index is in range and whether texture resources are valid (using NAME_None sentinel). - FORCEINLINE bool IsValidTexture(CogTextureIndex Index) const - { - return IsInRange(Index) && TextureResources[Index].GetName() != NAME_None; - } - - // Entry for texture resources. Only supports explicit construction. - struct FTextureEntry - { - FTextureEntry() = default; - FTextureEntry(const FName& InName, UTexture2D* InTexture, bool bAddToRoot); - ~FTextureEntry(); - - // Copying is not supported. - FTextureEntry(const FTextureEntry&) = delete; - FTextureEntry& operator=(const FTextureEntry&) = delete; - - // We rely on TArray and don't implement custom move constructor... - FTextureEntry(FTextureEntry&&) = delete; - // ... but we need move assignment to support reusing entries. - FTextureEntry& operator=(FTextureEntry&& Other); - - const FName& GetName() const { return Name; } - const FSlateResourceHandle& GetResourceHandle() const; - - private: - - void Reset(bool bReleaseResources); - - FName Name = NAME_None; - mutable FSlateResourceHandle CachedResourceHandle; - TWeakObjectPtr Texture; - FSlateBrush Brush; - }; - - TArray TextureResources; - FTextureEntry ErrorTexture; - - static constexpr EName NAME_ErrorTexture = NAME_None; - static constexpr CogTextureIndex INDEX_ErrorTexture = INDEX_NONE; -}; diff --git a/Plugins/Cog/Source/CogImgui/Public/CogImguiWidget.h b/Plugins/Cog/Source/CogImgui/Public/CogImguiWidget.h index de15ccc..2aa0c5a 100644 --- a/Plugins/Cog/Source/CogImgui/Public/CogImguiWidget.h +++ b/Plugins/Cog/Source/CogImgui/Public/CogImguiWidget.h @@ -7,14 +7,8 @@ #include "Widgets/DeclarativeSyntaxSupport.h" #include "Widgets/SLeafWidget.h" -class IInputProcessor; +class FCogImguiContext; class UGameViewportClient; -class ULocalPlayer; -struct ImFontAtlas; -struct ImGuiContext; -struct ImPlotContext; - -using FCogImguiRenderFunction = TFunction; //-------------------------------------------------------------------------------------------------------------------------- class COGIMGUI_API SCogImguiWidget : public SLeafWidget @@ -24,81 +18,26 @@ class COGIMGUI_API SCogImguiWidget : public SLeafWidget public: SLATE_BEGIN_ARGS(SCogImguiWidget) {} - SLATE_ARGUMENT(UGameViewportClient*, GameViewport) - SLATE_ARGUMENT(ImFontAtlas*, FontAtlas) - SLATE_ARGUMENT(FCogImguiRenderFunction, Render) + SLATE_ARGUMENT(FCogImguiContext*, Context) SLATE_END_ARGS() void Construct(const FArguments& InArgs); ~SCogImguiWidget(); - //---------------------------------------------------------------------------------------------------- - // SWidget overrides - //---------------------------------------------------------------------------------------------------- - virtual void Tick(const FGeometry& AllottedGeometry, const double InCurrentTime, const float InDeltaTime) override; - virtual int32 OnPaint(const FPaintArgs& Args, const FGeometry& AllottedGeometry, const FSlateRect& MyClippingRect, FSlateWindowElementList& OutDrawElements, int32 LayerId, const FWidgetStyle& WidgetStyle, bool bParentEnabled) const override; virtual bool SupportsKeyboardFocus() const override { return true; } virtual FReply OnKeyChar(const FGeometry& MyGeometry, const FCharacterEvent& CharacterEvent) override; - virtual FReply OnFocusReceived(const FGeometry& MyGeometry, const FFocusEvent& FocusEvent) override; - virtual FVector2D ComputeDesiredSize(float Scale) const override; - ULocalPlayer* GetLocalPlayer() const; - - bool GetEnableInput() const { return bEnableInput; } - - void SetEnableInput(bool Value); - - bool GetShareMouse() const { return bShareMouse; } - - void SetShareMouse(bool Value) { bShareMouse = Value; } - - float GetDpiScale() const { return DpiScale; } - - void SetDPIScale(float Value); - - bool IsCurrentContext() const; - - void SetAsCurrentContext(); - - TWeakObjectPtr GetGameViewport() const { return GameViewport; } - - void DestroyImGuiContext(); + void SetDrawData(const ImDrawData* InDrawData); protected: - FVector2D TransformScreenPointToImGui(const FGeometry& MyGeometry, const FVector2D& Point) const; - - virtual void TickKeyModifiers(); - - virtual void TickImGui(float InDeltaTime); - - virtual void TickFocus(); - - virtual void TakeFocus(); - - virtual void ReturnFocus(); - - virtual void OnDpiChanged(); - - virtual bool IsConsoleOpened() const; - - virtual void DrawDebug(); - - TWeakObjectPtr GameViewport; - - ImFontAtlas* FontAtlas = nullptr; - - TWeakPtr PreviousUserFocusedWidget; - - bool bEnableInput = false; - - bool bShareMouse = true; + TObjectPtr Context = nullptr; FSlateRenderTransform ImGuiRenderTransform; @@ -106,17 +45,5 @@ protected: mutable TArray IndexBuffer; - TArray DrawLists; - - ImGuiContext* ImGuiContext = nullptr; - - ImPlotContext* ImPlotContext = nullptr; - - FCogImguiRenderFunction Render; - - float DpiScale = 1.f; - - char IniFilename[512]; - - TSharedPtr InputProcessor = nullptr; + FCogImguiDrawData DrawData; }; diff --git a/Plugins/Cog/Source/CogWindow/Private/CogWindow.cpp b/Plugins/Cog/Source/CogWindow/Private/CogWindow.cpp index 5e3586d..65fbff2 100644 --- a/Plugins/Cog/Source/CogWindow/Private/CogWindow.cpp +++ b/Plugins/Cog/Source/CogWindow/Private/CogWindow.cpp @@ -2,6 +2,7 @@ #include "CogDebugDraw.h" #include "CogDebugSettings.h" +#include "CogWindow_Settings.h" #include "CogWindowManager.h" #include "CogWindowWidgets.h" #include "Engine/World.h" @@ -75,7 +76,7 @@ void FCogWindow::Render(float DeltaTime) ImGui::PopStyleVar(1); } - if (GetOwner()->GetShowHelp()) + if (GetOwner()->GetSettingsWindow()->GetSettingsConfig()->bShowHelp) { if (ImGui::IsItemHovered()) { diff --git a/Plugins/Cog/Source/CogWindow/Private/CogWindowManager.cpp b/Plugins/Cog/Source/CogWindow/Private/CogWindowManager.cpp index f102cbc..7818efd 100644 --- a/Plugins/Cog/Source/CogWindow/Private/CogWindowManager.cpp +++ b/Plugins/Cog/Source/CogWindow/Private/CogWindowManager.cpp @@ -1,9 +1,9 @@ #include "CogWindowManager.h" #include "CogDebugDrawImGui.h" +#include "CogImguiHelper.h" #include "CogImguiInputHelper.h" #include "CogImguiModule.h" -#include "CogWindow_Inputs.h" #include "CogWindow_Layouts.h" #include "CogWindow_Settings.h" #include "CogWindow_Spacing.h" @@ -41,7 +41,7 @@ void UCogWindowManager::PostInitProperties() //-------------------------------------------------------------------------------------------------------------------------- void UCogWindowManager::InitializeInternal() { - ImGuiWidget = FCogImguiModule::Get().CreateImGuiWidget(GEngine->GameViewport, [this](float DeltaTime) { Render(DeltaTime); }); + Context.Initialize(); ImGuiSettingsHandler IniHandler; IniHandler.TypeName = "Cog"; @@ -59,7 +59,6 @@ void UCogWindowManager::InitializeInternal() SpaceWindows.Add(AddWindow("Spacing 3", false)); SpaceWindows.Add(AddWindow("Spacing 4", false)); - InputsWindow = AddWindow("Window.Inputs", false); LayoutsWindow = AddWindow("Window.Layouts", false); SettingsWindow = AddWindow("Window.Settings", false); @@ -86,7 +85,8 @@ void UCogWindowManager::InitializeInternal() TEXT("Save the layout. Cog.SaveLayout "), FConsoleCommandWithArgsDelegate::CreateLambda([this](const TArray& Args) { if (Args.Num() > 0) { SaveLayout(FCString::Atoi(*Args[0])); }}), ECVF_Cheat)); - + + IsInitialized = true; } //-------------------------------------------------------------------------------------------------------------------------- @@ -105,7 +105,7 @@ void UCogWindowManager::Shutdown() // Destroy ImGui before destroying the windows to make sure // imgui serialize their visibility state in imgui.ini //------------------------------------------------------------ - ImGuiWidget->DestroyImGuiContext(); + Context.Shutdown(); SaveConfig(); @@ -125,8 +125,6 @@ void UCogWindowManager::Shutdown() { IConsoleManager::Get().UnregisterConsoleObject(ConsoleCommand); } - - FCogImguiModule::Get().DestroyImGuiWidget(ImGuiWidget); } //-------------------------------------------------------------------------------------------------------------------------- @@ -137,7 +135,7 @@ void UCogWindowManager::Tick(float DeltaTime) return; } - if (ImGuiWidget.IsValid() == false) + if (IsInitialized == false) { InitializeInternal(); } @@ -149,16 +147,14 @@ void UCogWindowManager::Tick(float DeltaTime) LayoutToLoad = -1; } - if (bRefreshDPIScale) - { - RefreshDPIScale(); - bRefreshDPIScale = false; - } - for (FCogWindow* Window : Windows) { Window->GameTick(DeltaTime); } + + Context.BeginFrame(DeltaTime); + Render(DeltaTime); + Context.EndFrame(); } //-------------------------------------------------------------------------------------------------------------------------- @@ -168,7 +164,7 @@ void UCogWindowManager::Render(float DeltaTime) ImGui::DockSpaceOverViewport(0, ImGuiDockNodeFlags_PassthruCentralNode | ImGuiDockNodeFlags_NoDockingInCentralNode | ImGuiDockNodeFlags_AutoHideTabBar); ImGui::PopStyleColor(1); - bool bCompactSaved = bCompactMode; + bool bCompactSaved = SettingsWindow->GetSettingsConfig()->bCompactMode; if (bCompactSaved) { FCogWindowWidgets::PushStyleCompact(); @@ -176,7 +172,7 @@ void UCogWindowManager::Render(float DeltaTime) if (bHideAllWindows == false) { - if (ImGuiWidget->GetEnableInput() || bHideMainMenuOnGameInput == false) + if (Context.GetEnableInput()) { RenderMainMenu(); } @@ -188,7 +184,7 @@ void UCogWindowManager::Render(float DeltaTime) if (Window->GetIsVisible() && bHideAllWindows == false) { - if (bTransparentMode) + if (SettingsWindow->GetSettingsConfig()->bTransparentMode) { ImGui::SetNextWindowBgAlpha(0.35f); } @@ -202,8 +198,6 @@ void UCogWindowManager::Render(float DeltaTime) FCogWindowWidgets::PopStyleCompact(); } - TickDPI(); - FCogDebugDrawImGui::Draw(); } @@ -354,8 +348,6 @@ void UCogWindowManager::RenderMainMenu() ImGui::Separator(); - RenderMenuItem(*InputsWindow, "Inputs"); - RenderMenuItem(*LayoutsWindow, "Layouts"); RenderMenuItem(*SettingsWindow, "Settings"); @@ -508,7 +500,7 @@ void UCogWindowManager::RenderOptionMenu(UCogWindowManager::FMenu& Menu) //-------------------------------------------------------------------------------------------------------------------------- void UCogWindowManager::RenderMenuItem(FCogWindow& Window, const char* MenuItemName) { - if (bShowWindowsInMainMenu) + if (SettingsWindow->GetSettingsConfig()->bShowWindowsInMainMenu) { ImGui::SetNextWindowSizeConstraints( ImVec2(FCogWindowWidgets::GetFontWidth() * 40, ImGui::GetTextLineHeightWithSpacing() * 5), @@ -535,31 +527,7 @@ void UCogWindowManager::RenderMenuItem(FCogWindow& Window, const char* MenuItemN } } -//-------------------------------------------------------------------------------------------------------------------------- -void UCogWindowManager::TickDPI() -{ - const float MouseWheel = ImGui::GetIO().MouseWheel; - const bool IsControlDown = ImGui::GetIO().KeyCtrl; - if (IsControlDown && MouseWheel != 0) - { - SetDPIScale(FMath::Clamp(DPIScale + (MouseWheel > 0 ? 0.1f : -0.1f), 0.5f, 2.0f)); - } - const bool IsMiddleMouseClicked = ImGui::GetIO().MouseClicked[2]; - if (IsControlDown && IsMiddleMouseClicked) - { - SetDPIScale(1.0f); - } -} - -//-------------------------------------------------------------------------------------------------------------------------- -void UCogWindowManager::RefreshDPIScale() -{ - if (SCogImguiWidget* Widget = ImGuiWidget.Get()) - { - Widget->SetDPIScale(DPIScale); - } -} //-------------------------------------------------------------------------------------------------------------------------- void UCogWindowManager::SettingsHandler_ClearAll(ImGuiContext* Context, ImGuiSettingsHandler* Handler) @@ -652,18 +620,6 @@ void UCogWindowManager::SettingsHandler_WriteAll(ImGuiContext* Context, ImGuiSet Buffer->append("\n"); } -//-------------------------------------------------------------------------------------------------------------------------- -void UCogWindowManager::SetDPIScale(float Value) -{ - if (DPIScale == Value) - { - return; - } - - DPIScale = Value; - bRefreshDPIScale = true; -} - //-------------------------------------------------------------------------------------------------------------------------- void UCogWindowManager::ResetAllWindowsConfig() { @@ -786,5 +742,5 @@ const UObject* UCogWindowManager::GetAsset(const TSubclassOf AssetClass void UCogWindowManager::ToggleInputMode() { UE_LOG(LogCogImGui, Verbose, TEXT("UCogWindowManager::ToggleInputMode")); - ImGuiWidget->SetEnableInput(!ImGuiWidget->GetEnableInput()); + Context.SetEnableInput(!Context.GetEnableInput()); } \ No newline at end of file diff --git a/Plugins/Cog/Source/CogWindow/Private/CogWindow_Inputs.cpp b/Plugins/Cog/Source/CogWindow/Private/CogWindow_Inputs.cpp index 1169b81..5a44d55 100644 --- a/Plugins/Cog/Source/CogWindow/Private/CogWindow_Inputs.cpp +++ b/Plugins/Cog/Source/CogWindow/Private/CogWindow_Inputs.cpp @@ -1,89 +1,2 @@ #include "CogWindow_Inputs.h" -#include "CogImguiInputHelper.h" -#include "CogImguiWidget.h" -#include "CogWindowManager.h" -#include "CogWindowWidgets.h" -#include "InputCoreTypes.h" -#include "imgui.h" - -//-------------------------------------------------------------------------------------------------------------------------- -void FCogWindow_Inputs::Initialize() -{ - Super::Initialize(); - - bHasMenu = false; - - Config = GetConfig(); - - SCogImguiWidget* ImGuiWidget = GetOwner()->GetImGuiWidget().Get(); - ImGuiWidget->SetEnableInput(Config->bEnableInput); - - ImGuiIO& IO = ImGui::GetIO(); - FCogImguiHelper::SetFlags(IO.ConfigFlags, ImGuiConfigFlags_NavEnableKeyboard, Config->bNavEnableKeyboard); - FCogImguiHelper::SetFlags(IO.ConfigFlags, ImGuiConfigFlags_NavEnableGamepad, Config->bNavEnableGamepad); - FCogImguiHelper::SetFlags(IO.ConfigFlags, ImGuiConfigFlags_NavNoCaptureKeyboard, Config->bNavNoCaptureInput); -} - -//-------------------------------------------------------------------------------------------------------------------------- -void FCogWindow_Inputs::PreSaveConfig() -{ - Super::PreSaveConfig(); - - ImGuiIO& IO = ImGui::GetIO(); - Config->bNavEnableKeyboard = IO.ConfigFlags & ImGuiConfigFlags_NavEnableKeyboard; - Config->bNavEnableGamepad = IO.ConfigFlags & ImGuiConfigFlags_NavEnableGamepad; - Config->bNavNoCaptureInput = IO.ConfigFlags & ImGuiConfigFlags_NavNoCaptureKeyboard; - - if (SCogImguiWidget* ImGuiWidget = GetOwner()->GetImGuiWidget().Get()) - { - Config->bEnableInput = ImGuiWidget->GetEnableInput(); - Config->bShareMouse = ImGuiWidget->GetShareMouse(); - } -} - -//-------------------------------------------------------------------------------------------------------------------------- -void FCogWindow_Inputs::RenderContent() -{ - const UPlayerInput* PlayerInput = FCogImguiInputHelper::GetPlayerInput(*GetWorld()); - if (PlayerInput == nullptr) - { - return; - } - - SCogImguiWidget* ImGuiWidget = GetOwner()->GetImGuiWidget().Get(); - if (ImGuiWidget == nullptr) - { - return; - } - - bool bEnableInput = ImGuiWidget->GetEnableInput(); - if (ImGui::Checkbox("Enable Input", &bEnableInput)) - { - ImGuiWidget->SetEnableInput(bEnableInput); - } - - const char* ShortcutText = TCHAR_TO_ANSI(*FCogImguiInputHelper::CommandToString(PlayerInput, UCogWindowManager::ToggleInputCommand)); - const float ShortcutWidth = (ShortcutText && ShortcutText[0]) ? ImGui::CalcTextSize(ShortcutText, NULL).x : 0.0f; - if (ShortcutWidth > 0.0f) - { - ImGui::SameLine(); - ImGui::SetCursorPosX(ImGui::GetWindowContentRegionMax().x - ShortcutWidth); - ImGui::PushStyleColor(ImGuiCol_Text, ImGui::GetStyle().Colors[ImGuiCol_TextDisabled]); - ImGui::Text(ShortcutText); - ImGui::PopStyleColor(); - } - - ImGui::Separator(); - - bool bShareMouse = ImGuiWidget->GetShareMouse(); - if (ImGui::Checkbox("Share Mouse", &bShareMouse)) - { - ImGuiWidget->SetShareMouse(bShareMouse); - } - - ImGuiIO& IO = ImGui::GetIO(); - ImGui::CheckboxFlags("Keyboard Navigation", &IO.ConfigFlags, ImGuiConfigFlags_NavEnableKeyboard); - ImGui::CheckboxFlags("Gamepad Navigation", &IO.ConfigFlags, ImGuiConfigFlags_NavEnableGamepad); - ImGui::CheckboxFlags("Navigation No Capture", &IO.ConfigFlags, ImGuiConfigFlags_NavNoCaptureKeyboard); -} diff --git a/Plugins/Cog/Source/CogWindow/Private/CogWindow_Settings.cpp b/Plugins/Cog/Source/CogWindow/Private/CogWindow_Settings.cpp index 59d92e9..15ed0b6 100644 --- a/Plugins/Cog/Source/CogWindow/Private/CogWindow_Settings.cpp +++ b/Plugins/Cog/Source/CogWindow/Private/CogWindow_Settings.cpp @@ -1,8 +1,12 @@ #include "CogWindow_Settings.h" +#include "CogImguiHelper.h" +#include "CogImguiInputHelper.h" #include "CogImguiModule.h" +#include "CogImguiWidget.h" #include "CogWindowManager.h" #include "CogWindowWidgets.h" +#include "imgui.h" #include "InputCoreTypes.h" //-------------------------------------------------------------------------------------------------------------------------- @@ -11,17 +15,86 @@ void FCogWindow_Settings::Initialize() Super::Initialize(); bHasMenu = false; + + Config = GetConfig(); + + ImGuiIO& IO = ImGui::GetIO(); + FCogImguiHelper::SetFlags(IO.ConfigFlags, ImGuiConfigFlags_ViewportsEnable, Config->bEnableViewports); + + GetOwner()->GetContext().SetDPIScale(Config->DPIScale); + + FCogImguiContext& Context = GetOwner()->GetContext(); + Context.SetEnableInput(Config->bEnableInput); + Context.SetShareMouse(Config->bShareMouse); + + FCogImguiHelper::SetFlags(IO.ConfigFlags, ImGuiConfigFlags_NavEnableKeyboard, Config->bNavEnableKeyboard); + FCogImguiHelper::SetFlags(IO.ConfigFlags, ImGuiConfigFlags_NavEnableGamepad, Config->bNavEnableGamepad); + FCogImguiHelper::SetFlags(IO.ConfigFlags, ImGuiConfigFlags_NavNoCaptureKeyboard, Config->bNavNoCaptureInput); + FCogImguiHelper::SetFlags(IO.ConfigFlags, ImGuiConfigFlags_NoMouseCursorChange, Config->bNoMouseCursorChange); +} + +//-------------------------------------------------------------------------------------------------------------------------- +void FCogWindow_Settings::PreSaveConfig() +{ + Super::PreSaveConfig(); + + ImGuiIO& IO = ImGui::GetIO(); + Config->bNavEnableKeyboard = IO.ConfigFlags & ImGuiConfigFlags_NavEnableKeyboard; + Config->bNavEnableGamepad = IO.ConfigFlags & ImGuiConfigFlags_NavEnableGamepad; + Config->bNavNoCaptureInput = IO.ConfigFlags & ImGuiConfigFlags_NavNoCaptureKeyboard; + Config->bNoMouseCursorChange = IO.ConfigFlags & ImGuiConfigFlags_NoMouseCursorChange; + + const FCogImguiContext& Context = GetOwner()->GetContext(); + Config->bEnableInput = Context.GetEnableInput(); + Config->bShareMouse = Context.GetShareMouse(); +} + +//-------------------------------------------------------------------------------------------------------------------------- +void FCogWindow_Settings::ResetConfig() +{ + Super::ResetConfig(); + + Config->Reset(); } //-------------------------------------------------------------------------------------------------------------------------- void FCogWindow_Settings::RenderContent() { + const UPlayerInput* PlayerInput = FCogImguiInputHelper::GetPlayerInput(*GetWorld()); + if (PlayerInput == nullptr) + { + return; + } + + ImGuiIO& IO = ImGui::GetIO(); + + FCogImguiContext& Context = GetOwner()->GetContext(); + bool bEnableInput = Context.GetEnableInput(); + if (ImGui::Checkbox("Enable Input", &bEnableInput)) + { + Context.SetEnableInput(bEnableInput); + } + + const char* ShortcutText = TCHAR_TO_ANSI(*FCogImguiInputHelper::CommandToString(PlayerInput, UCogWindowManager::ToggleInputCommand)); + const float ShortcutWidth = (ShortcutText && ShortcutText[0]) ? ImGui::CalcTextSize(ShortcutText, NULL).x : 0.0f; + if (ShortcutWidth > 0.0f) + { + ImGui::SameLine(); + ImGui::SetCursorPosX(ImGui::GetWindowContentRegionMax().x - ShortcutWidth); + ImGui::PushStyleColor(ImGuiCol_Text, ImGui::GetStyle().Colors[ImGuiCol_TextDisabled]); + ImGui::Text(ShortcutText); + ImGui::PopStyleColor(); + } + + ImGui::Separator(); + FCogWindowWidgets::SetNextItemToShortWidth(); - ImGui::SliderFloat("DPI Scale", &GetOwner()->DPIScale, 0.5f, 2.0f, "%.1f"); + ImGui::SliderFloat("DPI Scale", &Config->DPIScale, 0.5f, 2.0f, "%.1f"); if (ImGui::IsItemDeactivatedAfterEdit()) { - GetOwner()->bRefreshDPIScale = true; + SetDPIScale(Config->DPIScale); } + if (ImGui::IsItemHovered()) { ImGui::BeginTooltip(); @@ -30,20 +103,63 @@ void FCogWindow_Settings::RenderContent() ImGui::EndTooltip(); } - ImGui::Checkbox("Compact Mode", &GetOwner()->bCompactMode); + ImGui::Separator(); - ImGui::Checkbox("Show Windows In Main Menu", &GetOwner()->bShowWindowsInMainMenu); + if (ImGui::Checkbox("Enable Viewports", &Config->bEnableViewports)) + { + FCogImguiHelper::SetFlags(IO.ConfigFlags, ImGuiConfigFlags_ViewportsEnable, Config->bEnableViewports); + } - ImGui::Checkbox("Hide Main Menu On Game Input", &GetOwner()->bHideMainMenuOnGameInput); + ImGui::Checkbox("Compact Mode", &Config->bCompactMode); - ImGui::Checkbox("Show Window Help", &GetOwner()->bShowHelp); + ImGui::Checkbox("Show Windows In Main Menu", &Config->bShowWindowsInMainMenu); + + ImGui::Checkbox("Show Window Help", &Config->bShowHelp); + + ImGui::Separator(); + + bool bShareMouse = Context.GetShareMouse(); + if (ImGui::Checkbox("Share Mouse", &bShareMouse)) + { + Context.SetShareMouse(bShareMouse); + } + + ImGui::CheckboxFlags("Keyboard Navigation", &IO.ConfigFlags, ImGuiConfigFlags_NavEnableKeyboard); + ImGui::CheckboxFlags("Gamepad Navigation", &IO.ConfigFlags, ImGuiConfigFlags_NavEnableGamepad); + ImGui::CheckboxFlags("Navigation No Capture", &IO.ConfigFlags, ImGuiConfigFlags_NavNoCaptureKeyboard); + ImGui::CheckboxFlags("No Mouse Cursor Change", &IO.ConfigFlags, ImGuiConfigFlags_NoMouseCursorChange); ImGui::Separator(); - ImGui::Spacing(); - ImGui::Spacing(); if (ImGui::Button("Reset All Windows Config")) { GetOwner()->ResetAllWindowsConfig(); } + +} + +//-------------------------------------------------------------------------------------------------------------------------- +void FCogWindow_Settings::RenderTick(float DeltaTime) +{ + Super::RenderTick(DeltaTime); + + const float MouseWheel = ImGui::GetIO().MouseWheel; + const bool IsControlDown = ImGui::GetIO().KeyCtrl; + if (IsControlDown && MouseWheel != 0) + { + SetDPIScale(FMath::Clamp(Config->DPIScale + (MouseWheel > 0 ? 0.1f : -0.1f), 0.5f, 2.0f)); + } + + const bool IsMiddleMouseClicked = ImGui::GetIO().MouseClicked[2]; + if (IsControlDown && IsMiddleMouseClicked) + { + SetDPIScale(1.0f); + } +} + +//-------------------------------------------------------------------------------------------------------------------------- +void FCogWindow_Settings::SetDPIScale(float Value) +{ + Config->DPIScale = Value; + GetOwner()->GetContext().SetDPIScale(Config->DPIScale); } diff --git a/Plugins/Cog/Source/CogWindow/Public/CogWindowManager.h b/Plugins/Cog/Source/CogWindow/Public/CogWindowManager.h index bb5a960..8abf719 100644 --- a/Plugins/Cog/Source/CogWindow/Public/CogWindowManager.h +++ b/Plugins/Cog/Source/CogWindow/Public/CogWindowManager.h @@ -1,12 +1,11 @@ #pragma once #include "CoreMinimal.h" -#include "CogImguiWidget.h" +#include "CogImguiContext.h" #include "imgui.h" #include "CogWindowManager.generated.h" class FCogWindow; -class FCogWindow_Inputs; class FCogWindow_Layouts; class FCogWindow_Settings; class IConsoleObject; @@ -55,26 +54,12 @@ public: virtual void SetHideAllWindows(bool Value); - virtual float GetDPIScale() const { return DPIScale; } - - virtual void SetDPIScale(float Value); - - virtual bool GetCompactMode() const { return bCompactMode; } - - virtual void SetCompactMode(bool Value) { bCompactMode = Value; } - - virtual bool GetShowHelp() const { return bShowHelp; } - - virtual void SetShowHelp(bool Value) { bShowHelp = Value; } - - virtual bool GetPreviewWindowsInMenu() const { return bShowWindowsInMainMenu; } - - virtual void SetPreviewWindowsInMenu(bool Value) { bShowWindowsInMainMenu = Value; } - virtual void ResetAllWindowsConfig(); virtual bool RegisterDefaultCommandBindings(); + const FCogWindow_Settings* GetSettingsWindow() const { return SettingsWindow; } + UCogWindowConfig* GetConfig(const TSubclassOf ConfigClass); template @@ -85,7 +70,9 @@ public: template T* GetAsset(); - TSharedPtr GetImGuiWidget() const { return ImGuiWidget; } + const FCogImguiContext& GetContext() const { return Context; } + + FCogImguiContext& GetContext() { return Context; } static void AddCommand(UPlayerInput* PlayerInput, const FString& Command, const FKey& Key); @@ -93,7 +80,6 @@ public: protected: - friend class FCogWindow_Inputs; friend class FCogWindow_Layouts; friend class FCogWindow_Settings; @@ -106,8 +92,6 @@ protected: virtual void InitializeInternal(); - virtual void RefreshDPIScale(); - virtual void RenderMainMenu(); virtual FMenu* AddMenu(const FString& Name); @@ -116,8 +100,6 @@ protected: virtual void RenderMenuItem(FCogWindow& Window, const char* MenuItemName); - virtual void TickDPI(); - virtual void ToggleInputMode(); static void SettingsHandler_ClearAll(ImGuiContext* ctx, ImGuiSettingsHandler*); @@ -144,37 +126,10 @@ protected: UPROPERTY() mutable TArray Assets; - UPROPERTY(Config) - bool bCompactMode = false; - - UPROPERTY(Config) - bool bTransparentMode = false; - - UPROPERTY(Config) - float DPIScale = 1.0f; - - UPROPERTY(Config) - bool bShowHelp = true; - - UPROPERTY(Config) - bool bShowWindowsInMainMenu = true; - UPROPERTY(Config) bool bRegisterDefaultCommands = true; - UPROPERTY(Config) - bool bAuthorizeInactiveInput = true; - - UPROPERTY(Config) - bool bAuthorizeExclusiveInput = true; - - UPROPERTY(Config) - bool bAuthorizeSharedInput = true; - - UPROPERTY(Config) - bool bHideMainMenuOnGameInput = true; - - TSharedPtr ImGuiWidget = nullptr; + FCogImguiContext Context; TArray Windows; @@ -184,8 +139,6 @@ protected: TArray SpaceWindows; - FCogWindow_Inputs* InputsWindow = nullptr; - FCogWindow_Settings* SettingsWindow = nullptr; FCogWindow_Layouts* LayoutsWindow = nullptr; @@ -198,7 +151,7 @@ protected: bool bHideAllWindows = false; - bool bRefreshDPIScale = false; + bool IsInitialized = false; TArray ConsoleCommands; }; diff --git a/Plugins/Cog/Source/CogWindow/Public/CogWindow_Inputs.h b/Plugins/Cog/Source/CogWindow/Public/CogWindow_Inputs.h index 89b15ca..6f70f09 100644 --- a/Plugins/Cog/Source/CogWindow/Public/CogWindow_Inputs.h +++ b/Plugins/Cog/Source/CogWindow/Public/CogWindow_Inputs.h @@ -1,60 +1 @@ #pragma once - -#include "CoreMinimal.h" -#include "CogWindow.h" -#include "CogWindowConfig.h" -#include "CogWindow_Inputs.generated.h" - -class UCogEngineConfig_Inputs; - -class COGWINDOW_API FCogWindow_Inputs : public FCogWindow -{ - typedef FCogWindow Super; - -public: - - virtual void Initialize() override; - - virtual void PreSaveConfig() override; - -protected: - - virtual void RenderContent() override; - - TObjectPtr Config = nullptr; -}; - -//-------------------------------------------------------------------------------------------------------------------------- -UCLASS(Config = Cog) -class UCogEngineConfig_Inputs : public UCogWindowConfig -{ - GENERATED_BODY() - -public: - - UPROPERTY(Config) - bool bEnableInput = false; - - UPROPERTY(Config) - bool bShareMouse = true; - - UPROPERTY(Config) - bool bNavEnableKeyboard = true; - - UPROPERTY(Config) - bool bNavEnableGamepad = true; - - UPROPERTY(Config) - bool bNavNoCaptureInput = true; - - virtual void Reset() override - { - Super::Reset(); - - bEnableInput = false; - bShareMouse = true; - bNavEnableKeyboard = true; - bNavEnableGamepad = true; - bNavNoCaptureInput = true; - } -}; \ No newline at end of file diff --git a/Plugins/Cog/Source/CogWindow/Public/CogWindow_Settings.h b/Plugins/Cog/Source/CogWindow/Public/CogWindow_Settings.h index adfce0f..b6cf101 100644 --- a/Plugins/Cog/Source/CogWindow/Public/CogWindow_Settings.h +++ b/Plugins/Cog/Source/CogWindow/Public/CogWindow_Settings.h @@ -2,7 +2,12 @@ #include "CoreMinimal.h" #include "CogWindow.h" +#include "CogWindowConfig.h" +#include "CogWindow_Settings.generated.h" +class UCogEngineConfig_Settings; + +//-------------------------------------------------------------------------------------------------------------------------- class COGWINDOW_API FCogWindow_Settings : public FCogWindow { typedef FCogWindow Super; @@ -11,7 +16,83 @@ public: virtual void Initialize() override; + virtual void RenderTick(float DeltaTime) override; + + const UCogWindowConfig_Settings* GetSettingsConfig() const { return Config; } + + void SetDPIScale(float Value); + protected: virtual void RenderContent() override; + + virtual void PreSaveConfig() override; + + virtual void ResetConfig() override; + + TObjectPtr Config = nullptr; }; + + +//-------------------------------------------------------------------------------------------------------------------------- +UCLASS(Config = Cog) +class UCogWindowConfig_Settings : public UCogWindowConfig +{ + GENERATED_BODY() + +public: + + UPROPERTY(Config) + float DPIScale = 1.0f; + + UPROPERTY(Config) + bool bEnableViewports = false; + + UPROPERTY(Config) + bool bCompactMode = false; + + UPROPERTY(Config) + bool bTransparentMode = false; + + UPROPERTY(Config) + bool bShowHelp = true; + + UPROPERTY(Config) + bool bShowWindowsInMainMenu = true; + + UPROPERTY(Config) + bool bEnableInput = false; + + UPROPERTY(Config) + bool bShareMouse = true; + + UPROPERTY(Config) + bool bNavEnableKeyboard = true; + + UPROPERTY(Config) + bool bNavEnableGamepad = true; + + UPROPERTY(Config) + bool bNavNoCaptureInput = true; + + UPROPERTY(Config) + bool bNoMouseCursorChange = false; + + virtual void Reset() override + { + Super::Reset(); + + DPIScale = 1.0f; + bEnableViewports = false; + bCompactMode = false; + bTransparentMode = false; + bShowHelp = true; + bShowWindowsInMainMenu = true; + bEnableInput = false; + bShareMouse = true; + bNavEnableKeyboard = true; + bNavEnableGamepad = true; + bNavNoCaptureInput = true; + bNoMouseCursorChange = false; + } +}; \ No newline at end of file diff --git a/Source/CogSample/CogSampleGameState.cpp b/Source/CogSample/CogSampleGameState.cpp index 54b34e5..e68584b 100644 --- a/Source/CogSample/CogSampleGameState.cpp +++ b/Source/CogSample/CogSampleGameState.cpp @@ -36,6 +36,7 @@ #include "CogEngineWindow_Scalability.h" #include "CogEngineWindow_Selection.h" #include "CogEngineWindow_Skeleton.h" +#include "CogEngineWindow_Slate.h" #include "CogEngineWindow_Spawns.h" #include "CogEngineWindow_Stats.h" #include "CogEngineWindow_TimeScale.h" @@ -162,6 +163,8 @@ void ACogSampleGameState::InitializeCog() CogWindowManager->AddWindow("Engine.Skeleton"); + CogWindowManager->AddWindow("Engine.Slate"); + CogWindowManager->AddWindow("Engine.Spawns"); FCogEngineWindow_Stats* StatsWindow = CogWindowManager->AddWindow("Engine.Stats");