CogImGui: Rework input with viewports (still wip)

This commit is contained in:
Arnaud Jamin
2023-11-28 17:08:17 -05:00
parent 4df4df3ee7
commit cf07a05424
13 changed files with 632 additions and 393 deletions
Binary file not shown.
Binary file not shown.
@@ -1,55 +0,0 @@
#pragma once
#include "Framework/Application/IInputProcessor.h"
class SCogImguiWidget;
class UPlayerInput;
enum ImGuiKey : int;
struct FKeyBind;
class FImGuiInputProcessor : public IInputProcessor
{
public:
FImGuiInputProcessor(UPlayerInput* InPlayerInput, SCogImguiWidget* InWidget);
virtual void Tick(const float DeltaTime, FSlateApplication& SlateApp, TSharedRef<ICursor> SlateCursor) override;
virtual bool HandleKeyDownEvent(FSlateApplication& SlateApp, const FKeyEvent& Event) override;
virtual bool HandleKeyUpEvent(FSlateApplication& SlateApp, const FKeyEvent& Event) override;
virtual bool HandleAnalogInputEvent(FSlateApplication& SlateApp, const FAnalogInputEvent& Event) override;
virtual bool HandleMouseMoveEvent(FSlateApplication& SlateApp, const FPointerEvent& Event) override;
virtual bool HandleMouseButtonDownEvent(FSlateApplication& SlateApp, const FPointerEvent& Event) override;
virtual bool HandleMouseButtonUpEvent(FSlateApplication& SlateApp, const FPointerEvent& Event) override;
virtual bool HandleMouseButtonDoubleClickEvent(FSlateApplication& SlateApp, const FPointerEvent& Event) override;
virtual bool HandleMouseWheelOrGestureEvent(FSlateApplication& SlateApp, const FPointerEvent& Event, const FPointerEvent* GestureEvent) override;
protected:
bool HandleKeyEvent(FSlateApplication& SlateApp, const FKeyEvent& Event, bool IsKeyDown);
bool HandleMouseButtonEvent(FSlateApplication& SlateApp, const FPointerEvent& Event, bool IsButtonDown);
bool IsKeyBoundToCommand(const FKeyEvent& KeyEvent);
static ImGuiKey ToImKey(const FKey& Key);
static bool IsKeyEventMatchingKeyBind(const FKeyEvent& KeyEvent, const FKeyBind& KeyBind);
static bool IsConsoleEvent(const FKeyEvent& KeyEvent);
static bool IsStopPlaySessionEvent(const FKeyEvent& KeyEvent);
static uint32 ToImGuiMouseButton(const FKey& MouseButton);
TObjectPtr<UPlayerInput> PlayerInput = nullptr;
TObjectPtr<SCogImguiWidget> MainWidget = nullptr;
};
@@ -4,21 +4,11 @@
#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
#include "Kismet2/DebuggerCommands.h"
#endif //WITH_EDITOR
constexpr bool ForwardEvent = false;
constexpr bool TerminateEvent = true;
//--------------------------------------------------------------------------------------------------------------------------
FImGuiInputProcessor::FImGuiInputProcessor(UPlayerInput* InPlayerInput, FCogImguiContext* InContext, SCogImguiWidget* InMainWidget)
FCogImGuiInputProcessor::FCogImGuiInputProcessor(UPlayerInput* InPlayerInput, FCogImguiContext* InContext, SCogImguiWidget* InMainWidget)
{
PlayerInput = InPlayerInput;
Context = InContext;
@@ -26,14 +16,7 @@ FImGuiInputProcessor::FImGuiInputProcessor(UPlayerInput* InPlayerInput, FCogImgu
}
//--------------------------------------------------------------------------------------------------------------------------
static FVector2D TransformScreenPointToImGui(const FGeometry& MyGeometry, const FVector2D& Point)
{
const FSlateRenderTransform ImGuiToScreen = MyGeometry.GetAccumulatedRenderTransform();
return ImGuiToScreen.Inverse().TransformPoint(Point);
}
//--------------------------------------------------------------------------------------------------------------------------
void FImGuiInputProcessor::Tick(const float DeltaTime, FSlateApplication& SlateApp, TSharedRef<ICursor> SlateCursor)
void FCogImGuiInputProcessor::Tick(const float DeltaTime, FSlateApplication& SlateApp, TSharedRef<ICursor> SlateCursor)
{
ImGuiIO& IO = ImGui::GetIO();
@@ -41,7 +24,7 @@ void FImGuiInputProcessor::Tick(const float DeltaTime, FSlateApplication& SlateA
if (bHasGamepad != SlateApp.IsGamepadAttached())
{
IO.BackendFlags ^= ImGuiBackendFlags_HasGamepad;
UE_LOG(LogCogImGui, VeryVerbose, TEXT("FImGuiInputProcessor::Tick | HasGamePad Changed"));
UE_LOG(LogCogImGui, VeryVerbose, TEXT("FCogImGuiInputProcessor::Tick | HasGamePad Changed"));
}
AddMousePosEvent(SlateApp.GetCursorPos());
@@ -56,42 +39,42 @@ void FImGuiInputProcessor::Tick(const float DeltaTime, FSlateApplication& SlateA
if (IO.WantSetMousePos)
{
SlateApp.SetCursorPos(FCogImguiHelper::ToFVector2D(IO.MousePos));
//UE_LOG(LogCogImGui, VeryVerbose, TEXT("FImGuiInputProcessor::Tick | SetCursorPos"));
//UE_LOG(LogCogImGui, VeryVerbose, TEXT("FCogImGuiInputProcessor::Tick | SetCursorPos"));
}
}
//--------------------------------------------------------------------------------------------------------------------------
bool FImGuiInputProcessor::HandleKeyDownEvent(FSlateApplication& SlateApp, const FKeyEvent& Event)
bool FCogImGuiInputProcessor::HandleKeyDownEvent(FSlateApplication& SlateApp, const FKeyEvent& Event)
{
return HandleKeyEvent(SlateApp, Event, true);
}
//--------------------------------------------------------------------------------------------------------------------------
bool FImGuiInputProcessor::HandleKeyUpEvent(FSlateApplication& SlateApp, const FKeyEvent& Event)
bool FCogImGuiInputProcessor::HandleKeyUpEvent(FSlateApplication& SlateApp, const FKeyEvent& Event)
{
return HandleKeyEvent(SlateApp, Event, false);
}
//--------------------------------------------------------------------------------------------------------------------------
bool FImGuiInputProcessor::HandleKeyEvent(FSlateApplication& SlateApp, const FKeyEvent& Event, bool IsKeyDown)
bool FCogImGuiInputProcessor::HandleKeyEvent(FSlateApplication& SlateApp, const FKeyEvent& Event, bool IsKeyDown)
{
//------------------------------------------------------------------------------------------------
// We want the user to be able to open the console command when imgui has the input.
//------------------------------------------------------------------------------------------------
if (IsConsoleEvent(Event))
if (FCogImguiInputHelper::IsConsoleEvent(Event))
{
const bool Result = ForwardEvent;
UE_LOG(LogCogImGui, VeryVerbose, TEXT("FImGuiInputProcessor::HandleKeyEvent | Key:%s | IsKeyDown:%d | TerminateEvent:%d | ConsoleEvent"), *Event.GetKey().ToString(), IsKeyDown, Result);
UE_LOG(LogCogImGui, VeryVerbose, TEXT("FCogImGuiInputProcessor::HandleKeyEvent | Key:%s | IsKeyDown:%d | TerminateEvent:%d | ConsoleEvent"), *Event.GetKey().ToString(), IsKeyDown, Result);
return Result;
}
//------------------------------------------------------------------------------------------------
// We want the user to be able to stop its session by pressing Esc, even when imgui has the input
//------------------------------------------------------------------------------------------------
if (IsStopPlaySessionEvent(Event))
if (FCogImguiInputHelper::IsStopPlaySessionEvent(Event))
{
const bool Result = ForwardEvent;
UE_LOG(LogCogImGui, VeryVerbose, TEXT("FImGuiInputProcessor::HandleKeyEvent | Key:%s | IsKeyDown:%d | TerminateEvent:%d | StopPlaySessionEvent"), *Event.GetKey().ToString(), IsKeyDown, Result);
UE_LOG(LogCogImGui, VeryVerbose, TEXT("FCogImGuiInputProcessor::HandleKeyEvent | Key:%s | IsKeyDown:%d | TerminateEvent:%d | StopPlaySessionEvent"), *Event.GetKey().ToString(), IsKeyDown, Result);
return Result;
}
@@ -100,16 +83,16 @@ bool FImGuiInputProcessor::HandleKeyEvent(FSlateApplication& SlateApp, const FKe
// We actually use a console command to toggle the input from the game to imgui, and other
// windows command such as LoadLayout.
//------------------------------------------------------------------------------------------------
if (IsKeyBoundToCommand(Event))
if (FCogImguiInputHelper::IsKeyBoundToCommand(PlayerInput, Event))
{
const bool Result = ForwardEvent;
UE_LOG(LogCogImGui, VeryVerbose, TEXT("FImGuiInputProcessor::HandleKeyEvent | Key:%s | IsKeyDown:%d | TerminateEvent:%d | KeyBoundToCommand"), *Event.GetKey().ToString(), IsKeyDown, Result);
UE_LOG(LogCogImGui, VeryVerbose, TEXT("FCogImGuiInputProcessor::HandleKeyEvent | Key:%s | IsKeyDown:%d | TerminateEvent:%d | KeyBoundToCommand"), *Event.GetKey().ToString(), IsKeyDown, Result);
return Result;
}
ImGuiIO& IO = ImGui::GetIO();
IO.AddKeyEvent(ToImKey(Event.GetKey()), IsKeyDown);
IO.AddKeyEvent(FCogImguiInputHelper::ToImKey(Event.GetKey()), IsKeyDown);
const FModifierKeysState& ModifierKeys = Event.GetModifierKeys();
IO.AddKeyEvent(ImGuiMod_Ctrl, ModifierKeys.IsControlDown());
@@ -128,7 +111,7 @@ bool FImGuiInputProcessor::HandleKeyEvent(FSlateApplication& SlateApp, const FKe
if (IsModifierKey)
{
const bool Result = ForwardEvent;
UE_LOG(LogCogImGui, VeryVerbose, TEXT("FImGuiInputProcessor::HandleKeyEvent | Key:%s | IsKeyDown:%d | TerminateEvent:%d | IsModifierKey"), *Event.GetKey().ToString(), IsKeyDown, Result);
UE_LOG(LogCogImGui, VeryVerbose, TEXT("FCogImGuiInputProcessor::HandleKeyEvent | Key:%s | IsKeyDown:%d | TerminateEvent:%d | IsModifierKey"), *Event.GetKey().ToString(), IsKeyDown, Result);
return Result;
}
@@ -137,23 +120,23 @@ bool FImGuiInputProcessor::HandleKeyEvent(FSlateApplication& SlateApp, const FKe
if (IO.WantCaptureKeyboard && (IO.ConfigFlags & ImGuiConfigFlags_NavEnableGamepad))
{
const bool Result = TerminateEvent;
UE_LOG(LogCogImGui, VeryVerbose, TEXT("FImGuiInputProcessor::HandleKeyEvent | Key:%s | IsKeyDown:%d | TerminateEvent:%d | NavEnableGamepad"), *Event.GetKey().ToString(), IsKeyDown, Result);
UE_LOG(LogCogImGui, VeryVerbose, TEXT("FCogImGuiInputProcessor::HandleKeyEvent | Key:%s | IsKeyDown:%d | TerminateEvent:%d | NavEnableGamepad"), *Event.GetKey().ToString(), IsKeyDown, Result);
return Result;
}
}
const bool Result = IO.WantCaptureKeyboard ? TerminateEvent : ForwardEvent;
UE_LOG(LogCogImGui, VeryVerbose, TEXT("FImGuiInputProcessor::HandleKeyEvent | Key:%s | IsKeyDown:%d | WantCaptureKeyboard:%d | TerminateEvent:%d"), *Event.GetKey().ToString(), IsKeyDown, IO.WantCaptureKeyboard, Result);
UE_LOG(LogCogImGui, VeryVerbose, TEXT("FCogImGuiInputProcessor::HandleKeyEvent | Key:%s | IsKeyDown:%d | WantCaptureKeyboard:%d | TerminateEvent:%d"), *Event.GetKey().ToString(), IsKeyDown, IO.WantCaptureKeyboard, Result);
return Result;
}
//--------------------------------------------------------------------------------------------------------------------------
bool FImGuiInputProcessor::HandleAnalogInputEvent(FSlateApplication& SlateApp, const FAnalogInputEvent& Event)
bool FCogImGuiInputProcessor::HandleAnalogInputEvent(FSlateApplication& SlateApp, const FAnalogInputEvent& Event)
{
const float Value = Event.GetAnalogValue();
ImGuiIO& IO = ImGui::GetIO();
IO.AddKeyAnalogEvent(ToImKey(Event.GetKey()), FMath::Abs(Value) > 0.0f, Value);
IO.AddKeyAnalogEvent(FCogImguiInputHelper::ToImKey(Event.GetKey()), FMath::Abs(Value) > 0.0f, Value);
if (Event.GetKey().IsGamepadKey())
{
@@ -176,11 +159,11 @@ bool FImGuiInputProcessor::HandleAnalogInputEvent(FSlateApplication& SlateApp, c
}
//--------------------------------------------------------------------------------------------------------------------------
bool FImGuiInputProcessor::HandleMouseMoveEvent(FSlateApplication& SlateApp, const FPointerEvent& Event)
bool FCogImGuiInputProcessor::HandleMouseMoveEvent(FSlateApplication& SlateApp, const FPointerEvent& Event)
{
AddMousePosEvent(Event.GetScreenSpacePosition());
if (Context->GetEnableInput() && Context->GetShareMouse() == false && IsMouseInsideMainViewport())
if (Context->GetEnableInput() && Context->GetShareMouse() == false && FCogImguiInputHelper::IsMouseInsideMainViewport())
{
return TerminateEvent;
}
@@ -191,44 +174,44 @@ bool FImGuiInputProcessor::HandleMouseMoveEvent(FSlateApplication& SlateApp, con
}
//--------------------------------------------------------------------------------------------------------------------------
bool FImGuiInputProcessor::HandleMouseButtonDownEvent(FSlateApplication& SlateApp, const FPointerEvent& Event)
bool FCogImGuiInputProcessor::HandleMouseButtonDownEvent(FSlateApplication& SlateApp, const FPointerEvent& Event)
{
return HandleMouseButtonEvent(SlateApp, Event, true);
}
//--------------------------------------------------------------------------------------------------------------------------
bool FImGuiInputProcessor::HandleMouseButtonUpEvent(FSlateApplication& SlateApp, const FPointerEvent& Event)
bool FCogImGuiInputProcessor::HandleMouseButtonUpEvent(FSlateApplication& SlateApp, const FPointerEvent& Event)
{
return HandleMouseButtonEvent(SlateApp, Event, false);
}
//--------------------------------------------------------------------------------------------------------------------------
bool FImGuiInputProcessor::HandleMouseButtonDoubleClickEvent(FSlateApplication& SlateApp, const FPointerEvent& Event)
bool FCogImGuiInputProcessor::HandleMouseButtonDoubleClickEvent(FSlateApplication& SlateApp, const FPointerEvent& Event)
{
return HandleMouseButtonEvent(SlateApp, Event, true);
}
//--------------------------------------------------------------------------------------------------------------------------
bool FImGuiInputProcessor::HandleMouseButtonEvent(FSlateApplication& SlateApp, const FPointerEvent& Event, bool IsButtonDown)
bool FCogImGuiInputProcessor::HandleMouseButtonEvent(FSlateApplication& SlateApp, const FPointerEvent& Event, bool IsButtonDown)
{
ImGuiIO& IO = ImGui::GetIO();
const uint32 Button = ToImGuiMouseButton(Event.GetEffectingButton());
const uint32 Button = FCogImguiInputHelper::ToImGuiMouseButton(Event.GetEffectingButton());
IO.AddMouseButtonEvent(Button, IsButtonDown);
if (Context->GetEnableInput() && Context->GetShareMouse() == false && IsMouseInsideMainViewport())
if (Context->GetEnableInput() && Context->GetShareMouse() == false && FCogImguiInputHelper::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);
UE_LOG(LogCogImGui, VeryVerbose, TEXT("FCogImGuiInputProcessor::HandleMouseButtonEvent | Button:%d | IsButtonDown:%d | WantCaptureMouse:%d | TerminateEvent:%d | ShareMouse == false"), Button, IsButtonDown, IO.WantCaptureMouse, Result);
return Result;
}
const bool Result = IO.WantCaptureMouse ? TerminateEvent : ForwardEvent;
UE_LOG(LogCogImGui, VeryVerbose, TEXT("FImGuiInputProcessor::HandleMouseButtonEvent | Button:%d | IsButtonDown:%d | WantCaptureMouse:%d | TerminateEvent:%d"), Button, IsButtonDown, IO.WantCaptureMouse, Result);
UE_LOG(LogCogImGui, VeryVerbose, TEXT("FCogImGuiInputProcessor::HandleMouseButtonEvent | Button:%d | IsButtonDown:%d | WantCaptureMouse:%d | TerminateEvent:%d"), Button, IsButtonDown, IO.WantCaptureMouse, Result);
return Result;
}
//--------------------------------------------------------------------------------------------------------------------------
void FImGuiInputProcessor::AddMousePosEvent(const FVector2D& MousePosition) const
void FCogImGuiInputProcessor::AddMousePosEvent(const FVector2D& MousePosition) const
{
ImGuiIO& IO = ImGui::GetIO();
if (IO.ConfigFlags & ImGuiConfigFlags_ViewportsEnable)
@@ -243,20 +226,7 @@ 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)
bool FCogImGuiInputProcessor::HandleMouseWheelOrGestureEvent(FSlateApplication& SlateApp, const FPointerEvent& Event, const FPointerEvent* GestureEvent)
{
ImGuiIO& IO = ImGui::GetIO();
@@ -264,237 +234,3 @@ bool FImGuiInputProcessor::HandleMouseWheelOrGestureEvent(FSlateApplication& Sla
return IO.WantCaptureMouse;
}
//--------------------------------------------------------------------------------------------------------------------------
bool FImGuiInputProcessor::IsKeyEventMatchingKeyBind(const FKeyEvent& KeyEvent, const FKeyBind& KeyBind)
{
if (KeyBind.bDisabled)
{
return false;
}
if (KeyBind.Key != KeyEvent.GetKey())
{
return false;
}
const bool bControlPressed = KeyEvent.IsControlDown();
const bool bShiftPressed = KeyEvent.IsShiftDown();
const bool bAltPressed = KeyEvent.IsAltDown();
const bool bCmdPressed = KeyEvent.IsCommandDown();
if ((!KeyBind.Control || bControlPressed)
&& (!KeyBind.Shift || bShiftPressed)
&& (!KeyBind.Alt || bAltPressed)
&& (!KeyBind.Cmd || bCmdPressed)
&& (!KeyBind.bIgnoreCtrl || !bControlPressed)
&& (!KeyBind.bIgnoreShift || !bShiftPressed)
&& (!KeyBind.bIgnoreAlt || !bAltPressed)
&& (!KeyBind.bIgnoreCmd || !bCmdPressed))
{
return true;
}
return false;
}
//--------------------------------------------------------------------------------------------------------------------------
bool FImGuiInputProcessor::IsKeyBoundToCommand(const FKeyEvent& KeyEvent)
{
if (PlayerInput == nullptr)
{
return false;
}
for (const FKeyBind& KeyBind : PlayerInput->DebugExecBindings)
{
if (IsKeyEventMatchingKeyBind(KeyEvent, KeyBind))
{
return true;
}
}
return false;
}
//--------------------------------------------------------------------------------------------------------------------------
bool FImGuiInputProcessor::IsConsoleEvent(const FKeyEvent& KeyEvent)
{
const bool bModifierDown = KeyEvent.IsControlDown() || KeyEvent.IsShiftDown() || KeyEvent.IsAltDown() || KeyEvent.IsCommandDown();
const bool Result = !bModifierDown && GetDefault<UInputSettings>()->ConsoleKeys.Contains(KeyEvent.GetKey());
return Result;
}
//--------------------------------------------------------------------------------------------------------------------------
bool FImGuiInputProcessor::IsStopPlaySessionEvent(const FKeyEvent& KeyEvent)
{
#if WITH_EDITOR
static TSharedPtr<FUICommandInfo> StopPlaySessionCommandInfo = FInputBindingManager::Get().FindCommandInContext("PlayWorld", "StopPlaySession");
if (StopPlaySessionCommandInfo.IsValid())
{
const FInputChord InputChord(KeyEvent.GetKey(), KeyEvent.IsShiftDown(), KeyEvent.IsControlDown(), KeyEvent.IsAltDown(), KeyEvent.IsCommandDown());
const bool bHasActiveChord = StopPlaySessionCommandInfo->HasActiveChord(InputChord);
return bHasActiveChord && FPlayWorldCommands::GlobalPlayWorldActions->CanExecuteAction(StopPlaySessionCommandInfo.ToSharedRef());
}
#endif // WITH_EDITOR
return false;
}
//--------------------------------------------------------------------------------------------------------------------------
uint32 FImGuiInputProcessor::ToImGuiMouseButton(const FKey& MouseButton)
{
if (MouseButton == EKeys::LeftMouseButton) { return 0; }
if (MouseButton == EKeys::RightMouseButton) { return 1; }
if (MouseButton == EKeys::MiddleMouseButton) { return 2; }
if (MouseButton == EKeys::ThumbMouseButton) { return 3; }
if (MouseButton == EKeys::ThumbMouseButton2) { return 4; }
return -1;
}
//--------------------------------------------------------------------------------------------------------------------------
ImGuiKey FImGuiInputProcessor::ToImKey(const FKey& Key)
{
static const TMap<FKey, ImGuiKey> LookupMap = {
{ EKeys::Tab, ImGuiKey_Tab },
{ EKeys::Left, ImGuiKey_LeftArrow },
{ EKeys::Right, ImGuiKey_RightArrow },
{ EKeys::Up, ImGuiKey_UpArrow },
{ EKeys::Down, ImGuiKey_DownArrow },
{ EKeys::PageUp, ImGuiKey_PageUp },
{ EKeys::PageDown, ImGuiKey_PageDown },
{ EKeys::Home, ImGuiKey_Home },
{ EKeys::End, ImGuiKey_End },
{ EKeys::Insert, ImGuiKey_Insert },
{ EKeys::Delete, ImGuiKey_Delete },
{ EKeys::BackSpace, ImGuiKey_Backspace },
{ EKeys::SpaceBar, ImGuiKey_Space },
{ EKeys::Enter, ImGuiKey_Enter },
{ EKeys::Escape, ImGuiKey_Escape },
{ EKeys::LeftControl, ImGuiKey_LeftCtrl },
{ EKeys::LeftShift, ImGuiKey_LeftShift },
{ EKeys::LeftAlt, ImGuiKey_LeftAlt },
{ EKeys::LeftCommand, ImGuiKey_LeftSuper },
{ EKeys::RightControl, ImGuiKey_RightCtrl },
{ EKeys::RightShift, ImGuiKey_RightShift },
{ EKeys::RightAlt, ImGuiKey_RightAlt },
{ EKeys::RightCommand, ImGuiKey_RightSuper },
{ EKeys::Zero, ImGuiKey_0 },
{ EKeys::One, ImGuiKey_1 },
{ EKeys::Two, ImGuiKey_2 },
{ EKeys::Three, ImGuiKey_3 },
{ EKeys::Four, ImGuiKey_4 },
{ EKeys::Five, ImGuiKey_5 },
{ EKeys::Six, ImGuiKey_6 },
{ EKeys::Seven, ImGuiKey_7 },
{ EKeys::Eight, ImGuiKey_8 },
{ EKeys::Nine, ImGuiKey_9 },
{ EKeys::A, ImGuiKey_A },
{ EKeys::B, ImGuiKey_B },
{ EKeys::C, ImGuiKey_C },
{ EKeys::D, ImGuiKey_D },
{ EKeys::E, ImGuiKey_E },
{ EKeys::F, ImGuiKey_F },
{ EKeys::G, ImGuiKey_G },
{ EKeys::H, ImGuiKey_H },
{ EKeys::I, ImGuiKey_I },
{ EKeys::J, ImGuiKey_J },
{ EKeys::K, ImGuiKey_K },
{ EKeys::L, ImGuiKey_L },
{ EKeys::M, ImGuiKey_M },
{ EKeys::N, ImGuiKey_N },
{ EKeys::O, ImGuiKey_O },
{ EKeys::P, ImGuiKey_P },
{ EKeys::Q, ImGuiKey_Q },
{ EKeys::R, ImGuiKey_R },
{ EKeys::S, ImGuiKey_S },
{ EKeys::T, ImGuiKey_T },
{ EKeys::U, ImGuiKey_U },
{ EKeys::V, ImGuiKey_V },
{ EKeys::W, ImGuiKey_W },
{ EKeys::X, ImGuiKey_X },
{ EKeys::Y, ImGuiKey_Y },
{ EKeys::Z, ImGuiKey_Z },
{ EKeys::F1, ImGuiKey_F1 },
{ EKeys::F2, ImGuiKey_F2 },
{ EKeys::F3, ImGuiKey_F3 },
{ EKeys::F4, ImGuiKey_F4 },
{ EKeys::F5, ImGuiKey_F5 },
{ EKeys::F6, ImGuiKey_F6 },
{ EKeys::F7, ImGuiKey_F7 },
{ EKeys::F8, ImGuiKey_F8 },
{ EKeys::F9, ImGuiKey_F9 },
{ EKeys::F10, ImGuiKey_F10 },
{ EKeys::F11, ImGuiKey_F11 },
{ EKeys::F12, ImGuiKey_F12 },
{ EKeys::Apostrophe, ImGuiKey_Apostrophe },
{ EKeys::Comma, ImGuiKey_Comma },
{ EKeys::Period, ImGuiKey_Period },
{ EKeys::Slash, ImGuiKey_Slash },
{ EKeys::Semicolon, ImGuiKey_Semicolon },
{ EKeys::LeftBracket, ImGuiKey_LeftBracket },
{ EKeys::Backslash, ImGuiKey_Backslash },
{ EKeys::RightBracket, ImGuiKey_RightBracket },
{ EKeys::CapsLock, ImGuiKey_CapsLock },
{ EKeys::ScrollLock, ImGuiKey_ScrollLock },
{ EKeys::NumLock, ImGuiKey_NumLock },
{ EKeys::Pause, ImGuiKey_Pause },
{ EKeys::NumPadZero, ImGuiKey_Keypad0 },
{ EKeys::NumPadOne, ImGuiKey_Keypad1 },
{ EKeys::NumPadTwo, ImGuiKey_Keypad2 },
{ EKeys::NumPadThree, ImGuiKey_Keypad3 },
{ EKeys::NumPadFour, ImGuiKey_Keypad4 },
{ EKeys::NumPadFive, ImGuiKey_Keypad5 },
{ EKeys::NumPadSix, ImGuiKey_Keypad6 },
{ EKeys::NumPadSeven, ImGuiKey_Keypad7 },
{ EKeys::NumPadEight, ImGuiKey_Keypad8 },
{ EKeys::NumPadNine, ImGuiKey_Keypad9 },
{ EKeys::Decimal, ImGuiKey_KeypadDecimal },
{ EKeys::Divide, ImGuiKey_KeypadDivide },
{ EKeys::Multiply, ImGuiKey_KeypadMultiply },
{ EKeys::Subtract, ImGuiKey_KeypadSubtract },
{ EKeys::Add, ImGuiKey_KeypadAdd },
{ EKeys::Equals, ImGuiKey_KeypadEqual },
{ EKeys::Gamepad_Special_Right, ImGuiKey_GamepadStart },
{ EKeys::Gamepad_Special_Left, ImGuiKey_GamepadBack },
{ EKeys::Gamepad_FaceButton_Left, ImGuiKey_GamepadFaceLeft },
{ EKeys::Gamepad_FaceButton_Right, ImGuiKey_GamepadFaceRight },
{ EKeys::Gamepad_FaceButton_Top, ImGuiKey_GamepadFaceUp },
{ EKeys::Gamepad_FaceButton_Bottom, ImGuiKey_GamepadFaceDown },
{ EKeys::Gamepad_DPad_Left, ImGuiKey_GamepadDpadLeft },
{ EKeys::Gamepad_DPad_Right, ImGuiKey_GamepadDpadRight },
{ EKeys::Gamepad_DPad_Up, ImGuiKey_GamepadDpadUp },
{ EKeys::Gamepad_DPad_Down, ImGuiKey_GamepadDpadDown },
{ EKeys::Gamepad_LeftShoulder, ImGuiKey_GamepadL1 },
{ EKeys::Gamepad_RightShoulder, ImGuiKey_GamepadR1 },
{ EKeys::Gamepad_LeftTrigger, ImGuiKey_GamepadL2 },
{ EKeys::Gamepad_RightTrigger, ImGuiKey_GamepadR2 },
{ EKeys::Gamepad_LeftThumbstick, ImGuiKey_GamepadL3 },
{ EKeys::Gamepad_RightThumbstick, ImGuiKey_GamepadR3 },
{ EKeys::Gamepad_LeftStick_Left, ImGuiKey_GamepadLStickLeft },
{ EKeys::Gamepad_LeftStick_Right, ImGuiKey_GamepadLStickRight },
{ EKeys::Gamepad_LeftStick_Up, ImGuiKey_GamepadLStickUp },
{ EKeys::Gamepad_LeftStick_Down, ImGuiKey_GamepadLStickDown },
{ EKeys::Gamepad_RightStick_Left, ImGuiKey_GamepadRStickLeft },
{ EKeys::Gamepad_RightStick_Right, ImGuiKey_GamepadRStickRight },
{ EKeys::Gamepad_RightStick_Up, ImGuiKey_GamepadRStickUp },
{ EKeys::Gamepad_RightStick_Down, ImGuiKey_GamepadRStickDown }
};
const ImGuiKey* Result = LookupMap.Find(Key);
return (Result != nullptr) ? *Result : ImGuiKey_None;
}
@@ -1,5 +1,6 @@
#include "CogImGuiContext.h"
#include "Application/ThrottleManager.h"
#include "CogImguiHelper.h"
#include "CogImguiInputHelper.h"
#include "CogImguiInputProcessor.h"
@@ -40,12 +41,12 @@ void FCogImguiContext::Initialize()
//--------------------------------------------------------------------
// Register input processor to forward input events to imgui
//--------------------------------------------------------------------
if (FSlateApplication::IsInitialized())
{
UPlayerInput* PlayerInput = FCogImguiInputHelper::GetPlayerInput(*GameViewport->GetWorld());
InputProcessor = MakeShared<FImGuiInputProcessor>(PlayerInput, this, MainWidget.Get());
FSlateApplication::Get().RegisterInputPreProcessor(InputProcessor.ToSharedRef(), 0);
}
//if (FSlateApplication::IsInitialized())
//{
// UPlayerInput* PlayerInput = FCogImguiInputHelper::GetPlayerInput(*GameViewport->GetWorld());
// InputProcessor = MakeShared<FCogImGuiInputProcessor>(PlayerInput, this, MainWidget.Get());
// FSlateApplication::Get().RegisterInputPreProcessor(InputProcessor.ToSharedRef(), 0);
//}
ImGuiContext = ImGui::CreateContext();
PlotContext = ImPlot::CreateContext();
@@ -103,6 +104,7 @@ void FCogImguiContext::Initialize()
PlatformApplication->OnDisplayMetricsChanged().AddRaw(this, &FCogImguiContext::OnDisplayMetricsChanged);
OnDisplayMetricsChanged(DisplayMetrics);
}
}
//--------------------------------------------------------------------------------------------------------------------------
@@ -119,10 +121,10 @@ void FCogImguiContext::Shutdown()
{
FSlateApplication& SlateApp = FSlateApplication::Get();
if (InputProcessor.IsValid())
{
SlateApp.UnregisterInputPreProcessor(InputProcessor);
}
//if (InputProcessor.IsValid())
//{
// SlateApp.UnregisterInputPreProcessor(InputProcessor);
//}
if (const TSharedPtr<GenericApplication> PlatformApplication = SlateApp.GetPlatformApplication())
{
@@ -228,14 +230,14 @@ void FCogImguiContext::BeginFrame(float InDeltaTime)
if (bEnableInput)
{
IO.ConfigFlags &= ~ImGuiConfigFlags_NoMouse;
TryReleaseGameMouseCapture();
}
else
{
IO.ConfigFlags |= ImGuiConfigFlags_NoMouse;
}
TickFocus();
//-------------------------------------------------------------------------------------------------------
//
//-------------------------------------------------------------------------------------------------------
@@ -246,6 +248,20 @@ void FCogImguiContext::BeginFrame(float InDeltaTime)
MainWidget->SetCursor(FCogImguiInputHelper::ToSlateMouseCursor(ImGui::GetMouseCursor()));
}
//-------------------------------------------------------------------------------------------------------
//
//-------------------------------------------------------------------------------------------------------
const FVector2D& MousePosition = SlateApp.GetCursorPos();
if (IO.ConfigFlags & ImGuiConfigFlags_ViewportsEnable)
{
IO.AddMousePosEvent(MousePosition.X, MousePosition.Y);
}
else
{
const FVector2D TransformedMousePosition = MousePosition - MainWidget->GetTickSpaceGeometry().GetAbsolutePosition();
IO.AddMousePosEvent(TransformedMousePosition.X, TransformedMousePosition.Y);
}
//-------------------------------------------------------------------------------------------------------
//
//-------------------------------------------------------------------------------------------------------
@@ -260,6 +276,7 @@ void FCogImguiContext::BeginFrame(float InDeltaTime)
NewStyle.ScaleAllSizes(DpiScale);
}
ImGui::NewFrame();
//DrawDebug();
@@ -313,7 +330,8 @@ void FCogImguiContext::ImGui_CreateWindow(ImGuiViewport* Viewport)
const TSharedRef<SWindow> Window =
SNew(SWindow)
.Type(bTooltipWindow ? EWindowType::ToolTip : EWindowType::Normal)
//.Type(bTooltipWindow ? EWindowType::ToolTip : EWindowType::Normal)
.Type(EWindowType::ToolTip)
.Style(&WindowStyle)
.ScreenPosition(FCogImguiHelper::ToFVector2D(Viewport->Pos))
.ClientSize(FCogImguiHelper::ToFVector2D(Viewport->Size))
@@ -343,6 +361,8 @@ void FCogImguiContext::ImGui_CreateWindow(ImGuiViewport* Viewport)
FSlateApplication::Get().AddWindow(Window);
}
Widget->SetWindow(Window);
FImGuiViewportData* ViewportData = new FImGuiViewportData();
Viewport->PlatformUserData = ViewportData;
ViewportData->Context = ParentViewportData->Context;
@@ -559,10 +579,15 @@ void FCogImguiContext::SetEnableInput(bool Value)
{
bEnableInput = Value;
FSlateThrottleManager::Get().DisableThrottle(bEnableInput);
if (bEnableInput == false)
{
TryGiveMouseCaptureBackToGame();
}
else
{
}
}
//--------------------------------------------------------------------------------------------------------------------------
@@ -718,3 +743,80 @@ ULocalPlayer* FCogImguiContext::GetLocalPlayer() const
ULocalPlayer* LocalPlayer = World->GetFirstLocalPlayerFromController();
return LocalPlayer;
}
//--------------------------------------------------------------------------------------------------------------------------
void FCogImguiContext::TickFocus()
{
const bool bShouldEnableInput = bEnableInput;
if (bEnableInput != bShouldEnableInput)
{
bEnableInput = bShouldEnableInput;
if (bEnableInput)
{
TakeFocus();
}
else
{
ReturnFocus();
}
}
else if (bEnableInput)
{
const auto& ViewportWidget = GameViewport->GetGameViewportWidget();
if (!MainWidget->HasKeyboardFocus() && !IsConsoleOpened() && (ViewportWidget->HasKeyboardFocus() || ViewportWidget->HasFocusedDescendants()))
{
TakeFocus();
}
}
}
//--------------------------------------------------------------------------------------------------------------------------
void FCogImguiContext::TakeFocus()
{
FSlateApplication& SlateApplication = FSlateApplication::Get();
PreviousMouseCaptor = SlateApplication.GetUserFocusedWidget(SlateApplication.GetUserIndexForKeyboard());
if (ULocalPlayer* LocalPlayer = GetLocalPlayer())
{
TSharedRef<SWidget> FocusWidget = MainWidget->AsShared();
LocalPlayer->GetSlateOperations().CaptureMouse(FocusWidget);
LocalPlayer->GetSlateOperations().SetUserFocus(FocusWidget);
}
else
{
SlateApplication.SetKeyboardFocus(MainWidget->AsShared());
}
}
//--------------------------------------------------------------------------------------------------------------------------
void FCogImguiContext::ReturnFocus()
{
//if (MainWidget->HasKeyboardFocus())
//{
// auto FocusWidgetPtr = PreviousMouseCaptor.IsValid()
// ? PreviousMouseCaptor.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);
// }
//}
//PreviousMouseCaptor.Reset();
}
@@ -1,5 +1,6 @@
#include "CogImguiInputHelper.h"
#include "CogImGuiInputProcessor.h"
#include "CogImguiModule.h"
#include "Framework/Commands/UICommandInfo.h"
#include "GameFramework/GameUserSettings.h"
@@ -64,7 +65,7 @@ bool FCogImguiInputHelper::IsKeyEventHandled(UWorld* World, const FKeyEvent& Key
// If we receive a key modifier, we want to let others systems know about it.
// Otherwise, the console command bindings that are bound to something like CTRL+Key
// won't work, even if we let the KeyEvent pass with 'IsKeyBoundToCommand' below.
// It seems the command binings system needs to know about the modifier key press event itself,
// It seems the command bindings system needs to know about the modifier key press event itself,
// and not the Key+Modifier event.
// We update ImGui modifier keys in SCogImguiWidget::TickKeyModifiers().
//------------------------------------------------------------------------------------------------
@@ -74,7 +75,7 @@ bool FCogImguiInputHelper::IsKeyEventHandled(UWorld* World, const FKeyEvent& Key
}
//------------------------------------------------------------------------------------------------
// We want the user to be able to use command bingings, even when imgui has the input.
// We want the user to be able to use command bindings, even when imgui has the input.
// We actually use a console command to toggle the input from the game to imgui, and other
// windows command such as LoadLayout.
//------------------------------------------------------------------------------------------------
@@ -163,15 +164,6 @@ void FCogImguiInputHelper::KeyInfoToKeyBind(const FCogImGuiKeyInfo& KeyInfo, FKe
BREAK_CHECKBOX_STATE(KeyInfo.Cmd, KeyBind.Cmd, KeyBind.bIgnoreCmd);
}
//--------------------------------------------------------------------------------------------------------------------------
bool FCogImguiInputHelper::IsKeyEventMatchingKeyBind(const FKeyEvent& KeyEvent, const FKeyBind& KeyBind)
{
FCogImGuiKeyInfo KeyInfo;
KeyBindToKeyInfo(KeyBind, KeyInfo);
const bool Result = IsKeyEventMatchingKeyInfo(KeyEvent, KeyInfo);
return Result;
}
//--------------------------------------------------------------------------------------------------------------------------
bool FCogImguiInputHelper::WasKeyInfoJustPressed(APlayerController& PlayerController, const FCogImGuiKeyInfo& KeyInfo)
{
@@ -242,7 +234,7 @@ bool FCogImguiInputHelper::IsStopPlaySessionEvent(const FKeyEvent& KeyEvent)
}
//--------------------------------------------------------------------------------------------------------------------------
uint32 FCogImguiInputHelper::MouseButtonToImGuiMouseButton(const FKey& MouseButton)
uint32 FCogImguiInputHelper::ToImGuiMouseButton(const FKey& MouseButton)
{
if (MouseButton == EKeys::LeftMouseButton) { return 0; }
if (MouseButton == EKeys::RightMouseButton) { return 1; }
@@ -335,3 +327,214 @@ FString FCogImguiInputHelper::KeyBindToString(const FKeyBind& KeyBind)
return Result;
}
//--------------------------------------------------------------------------------------------------------------------------
bool FCogImguiInputHelper::IsKeyEventMatchingKeyBind(const FKeyEvent& KeyEvent, const FKeyBind& KeyBind)
{
if (KeyBind.bDisabled)
{
return false;
}
if (KeyBind.Key != KeyEvent.GetKey())
{
return false;
}
const bool bControlPressed = KeyEvent.IsControlDown();
const bool bShiftPressed = KeyEvent.IsShiftDown();
const bool bAltPressed = KeyEvent.IsAltDown();
const bool bCmdPressed = KeyEvent.IsCommandDown();
if ((!KeyBind.Control || bControlPressed)
&& (!KeyBind.Shift || bShiftPressed)
&& (!KeyBind.Alt || bAltPressed)
&& (!KeyBind.Cmd || bCmdPressed)
&& (!KeyBind.bIgnoreCtrl || !bControlPressed)
&& (!KeyBind.bIgnoreShift || !bShiftPressed)
&& (!KeyBind.bIgnoreAlt || !bAltPressed)
&& (!KeyBind.bIgnoreCmd || !bCmdPressed))
{
return true;
}
return false;
}
//--------------------------------------------------------------------------------------------------------------------------
bool FCogImguiInputHelper::IsKeyBoundToCommand(const UPlayerInput* InPlayerInput, const FKeyEvent& KeyEvent)
{
if (InPlayerInput == nullptr)
{
return false;
}
for (const FKeyBind& KeyBind : InPlayerInput->DebugExecBindings)
{
if (IsKeyEventMatchingKeyBind(KeyEvent, KeyBind))
{
return true;
}
}
return false;
}
//--------------------------------------------------------------------------------------------------------------------------
bool FCogImguiInputHelper::IsMouseInsideMainViewport()
{
if (ImGuiViewportP* Viewport = (ImGuiViewportP*)ImGui::GetMainViewport())
{
ImGuiIO& IO = ImGui::GetIO();
const bool Result = Viewport->GetMainRect().Contains(IO.MousePos);
return Result;
}
return false;
}
//--------------------------------------------------------------------------------------------------------------------------
ImGuiKey FCogImguiInputHelper::ToImKey(const FKey& Key)
{
static const TMap<FKey, ImGuiKey> LookupMap = {
{ EKeys::Tab, ImGuiKey_Tab },
{ EKeys::Left, ImGuiKey_LeftArrow },
{ EKeys::Right, ImGuiKey_RightArrow },
{ EKeys::Up, ImGuiKey_UpArrow },
{ EKeys::Down, ImGuiKey_DownArrow },
{ EKeys::PageUp, ImGuiKey_PageUp },
{ EKeys::PageDown, ImGuiKey_PageDown },
{ EKeys::Home, ImGuiKey_Home },
{ EKeys::End, ImGuiKey_End },
{ EKeys::Insert, ImGuiKey_Insert },
{ EKeys::Delete, ImGuiKey_Delete },
{ EKeys::BackSpace, ImGuiKey_Backspace },
{ EKeys::SpaceBar, ImGuiKey_Space },
{ EKeys::Enter, ImGuiKey_Enter },
{ EKeys::Escape, ImGuiKey_Escape },
{ EKeys::LeftControl, ImGuiKey_LeftCtrl },
{ EKeys::LeftShift, ImGuiKey_LeftShift },
{ EKeys::LeftAlt, ImGuiKey_LeftAlt },
{ EKeys::LeftCommand, ImGuiKey_LeftSuper },
{ EKeys::RightControl, ImGuiKey_RightCtrl },
{ EKeys::RightShift, ImGuiKey_RightShift },
{ EKeys::RightAlt, ImGuiKey_RightAlt },
{ EKeys::RightCommand, ImGuiKey_RightSuper },
{ EKeys::Zero, ImGuiKey_0 },
{ EKeys::One, ImGuiKey_1 },
{ EKeys::Two, ImGuiKey_2 },
{ EKeys::Three, ImGuiKey_3 },
{ EKeys::Four, ImGuiKey_4 },
{ EKeys::Five, ImGuiKey_5 },
{ EKeys::Six, ImGuiKey_6 },
{ EKeys::Seven, ImGuiKey_7 },
{ EKeys::Eight, ImGuiKey_8 },
{ EKeys::Nine, ImGuiKey_9 },
{ EKeys::A, ImGuiKey_A },
{ EKeys::B, ImGuiKey_B },
{ EKeys::C, ImGuiKey_C },
{ EKeys::D, ImGuiKey_D },
{ EKeys::E, ImGuiKey_E },
{ EKeys::F, ImGuiKey_F },
{ EKeys::G, ImGuiKey_G },
{ EKeys::H, ImGuiKey_H },
{ EKeys::I, ImGuiKey_I },
{ EKeys::J, ImGuiKey_J },
{ EKeys::K, ImGuiKey_K },
{ EKeys::L, ImGuiKey_L },
{ EKeys::M, ImGuiKey_M },
{ EKeys::N, ImGuiKey_N },
{ EKeys::O, ImGuiKey_O },
{ EKeys::P, ImGuiKey_P },
{ EKeys::Q, ImGuiKey_Q },
{ EKeys::R, ImGuiKey_R },
{ EKeys::S, ImGuiKey_S },
{ EKeys::T, ImGuiKey_T },
{ EKeys::U, ImGuiKey_U },
{ EKeys::V, ImGuiKey_V },
{ EKeys::W, ImGuiKey_W },
{ EKeys::X, ImGuiKey_X },
{ EKeys::Y, ImGuiKey_Y },
{ EKeys::Z, ImGuiKey_Z },
{ EKeys::F1, ImGuiKey_F1 },
{ EKeys::F2, ImGuiKey_F2 },
{ EKeys::F3, ImGuiKey_F3 },
{ EKeys::F4, ImGuiKey_F4 },
{ EKeys::F5, ImGuiKey_F5 },
{ EKeys::F6, ImGuiKey_F6 },
{ EKeys::F7, ImGuiKey_F7 },
{ EKeys::F8, ImGuiKey_F8 },
{ EKeys::F9, ImGuiKey_F9 },
{ EKeys::F10, ImGuiKey_F10 },
{ EKeys::F11, ImGuiKey_F11 },
{ EKeys::F12, ImGuiKey_F12 },
{ EKeys::Apostrophe, ImGuiKey_Apostrophe },
{ EKeys::Comma, ImGuiKey_Comma },
{ EKeys::Period, ImGuiKey_Period },
{ EKeys::Slash, ImGuiKey_Slash },
{ EKeys::Semicolon, ImGuiKey_Semicolon },
{ EKeys::LeftBracket, ImGuiKey_LeftBracket },
{ EKeys::Backslash, ImGuiKey_Backslash },
{ EKeys::RightBracket, ImGuiKey_RightBracket },
{ EKeys::CapsLock, ImGuiKey_CapsLock },
{ EKeys::ScrollLock, ImGuiKey_ScrollLock },
{ EKeys::NumLock, ImGuiKey_NumLock },
{ EKeys::Pause, ImGuiKey_Pause },
{ EKeys::NumPadZero, ImGuiKey_Keypad0 },
{ EKeys::NumPadOne, ImGuiKey_Keypad1 },
{ EKeys::NumPadTwo, ImGuiKey_Keypad2 },
{ EKeys::NumPadThree, ImGuiKey_Keypad3 },
{ EKeys::NumPadFour, ImGuiKey_Keypad4 },
{ EKeys::NumPadFive, ImGuiKey_Keypad5 },
{ EKeys::NumPadSix, ImGuiKey_Keypad6 },
{ EKeys::NumPadSeven, ImGuiKey_Keypad7 },
{ EKeys::NumPadEight, ImGuiKey_Keypad8 },
{ EKeys::NumPadNine, ImGuiKey_Keypad9 },
{ EKeys::Decimal, ImGuiKey_KeypadDecimal },
{ EKeys::Divide, ImGuiKey_KeypadDivide },
{ EKeys::Multiply, ImGuiKey_KeypadMultiply },
{ EKeys::Subtract, ImGuiKey_KeypadSubtract },
{ EKeys::Add, ImGuiKey_KeypadAdd },
{ EKeys::Equals, ImGuiKey_KeypadEqual },
{ EKeys::Gamepad_Special_Right, ImGuiKey_GamepadStart },
{ EKeys::Gamepad_Special_Left, ImGuiKey_GamepadBack },
{ EKeys::Gamepad_FaceButton_Left, ImGuiKey_GamepadFaceLeft },
{ EKeys::Gamepad_FaceButton_Right, ImGuiKey_GamepadFaceRight },
{ EKeys::Gamepad_FaceButton_Top, ImGuiKey_GamepadFaceUp },
{ EKeys::Gamepad_FaceButton_Bottom, ImGuiKey_GamepadFaceDown },
{ EKeys::Gamepad_DPad_Left, ImGuiKey_GamepadDpadLeft },
{ EKeys::Gamepad_DPad_Right, ImGuiKey_GamepadDpadRight },
{ EKeys::Gamepad_DPad_Up, ImGuiKey_GamepadDpadUp },
{ EKeys::Gamepad_DPad_Down, ImGuiKey_GamepadDpadDown },
{ EKeys::Gamepad_LeftShoulder, ImGuiKey_GamepadL1 },
{ EKeys::Gamepad_RightShoulder, ImGuiKey_GamepadR1 },
{ EKeys::Gamepad_LeftTrigger, ImGuiKey_GamepadL2 },
{ EKeys::Gamepad_RightTrigger, ImGuiKey_GamepadR2 },
{ EKeys::Gamepad_LeftThumbstick, ImGuiKey_GamepadL3 },
{ EKeys::Gamepad_RightThumbstick, ImGuiKey_GamepadR3 },
{ EKeys::Gamepad_LeftStick_Left, ImGuiKey_GamepadLStickLeft },
{ EKeys::Gamepad_LeftStick_Right, ImGuiKey_GamepadLStickRight },
{ EKeys::Gamepad_LeftStick_Up, ImGuiKey_GamepadLStickUp },
{ EKeys::Gamepad_LeftStick_Down, ImGuiKey_GamepadLStickDown },
{ EKeys::Gamepad_RightStick_Left, ImGuiKey_GamepadRStickLeft },
{ EKeys::Gamepad_RightStick_Right, ImGuiKey_GamepadRStickRight },
{ EKeys::Gamepad_RightStick_Up, ImGuiKey_GamepadRStickUp },
{ EKeys::Gamepad_RightStick_Down, ImGuiKey_GamepadRStickDown }
};
const ImGuiKey* Result = LookupMap.Find(Key);
return (Result != nullptr) ? *Result : ImGuiKey_None;
}
@@ -3,6 +3,8 @@
#include "CogImguiInputHelper.h"
#include "CogImguiModule.h"
#include "CogImguiWidget.h"
#include "CogImGuiContext.h"
#include "imgui.h"
#include "SlateOptMacros.h"
@@ -12,7 +14,8 @@ void SCogImguiWidget::Construct(const FArguments& InArgs)
{
Context = InArgs._Context;
SetVisibility(EVisibility::SelfHitTestInvisible);
//SetVisibility(EVisibility::SelfHitTestInvisible);
SetVisibility(EVisibility::Visible);
}
END_SLATE_FUNCTION_BUILD_OPTIMIZATION
@@ -126,5 +129,226 @@ FReply SCogImguiWidget::OnKeyChar(const FGeometry& MyGeometry, const FCharacterE
return Result;
}
//--------------------------------------------------------------------------------------------------------------------------
FReply SCogImguiWidget::OnKeyDown(const FGeometry& MyGeometry, const FKeyEvent& KeyEvent)
{
return HandleKeyEvent(MyGeometry, KeyEvent);
}
//--------------------------------------------------------------------------------------------------------------------------
FReply SCogImguiWidget::OnKeyUp(const FGeometry& MyGeometry, const FKeyEvent& KeyEvent)
{
return HandleKeyEvent(MyGeometry, KeyEvent);
}
//--------------------------------------------------------------------------------------------------------------------------
FReply SCogImguiWidget::HandleKeyEvent(const FGeometry& MyGeometry, const FKeyEvent& KeyEvent)
{
if (Context->GetEnableInput() == false)
{
return FReply::Unhandled();
}
if (KeyEvent.GetKey().IsGamepadKey())
{
//if (bShareGamepad)
//{
// // TODO: handle imgui gamepad
// return FReply::Unhandled();
//}
}
else
{
if (FCogImguiInputHelper::IsKeyEventHandled(Context->GetGameViewport()->GetWorld(), KeyEvent) == false)
{
return FReply::Unhandled();
}
ImGuiIO& IO = ImGui::GetIO();
IO.AddKeyEvent(FCogImguiInputHelper::ToImKey(KeyEvent.GetKey()), false);
IO.AddKeyEvent(ImGuiMod_Ctrl, KeyEvent.IsControlDown());
IO.AddKeyEvent(ImGuiMod_Shift, KeyEvent.IsShiftDown());
IO.AddKeyEvent(ImGuiMod_Alt, KeyEvent.IsAltDown());
IO.AddKeyEvent(ImGuiMod_Super, KeyEvent.IsCommandDown());
//if (bShareKeyboard)
//{
// return FReply::Unhandled();
//}
}
return FReply::Handled();
}
//--------------------------------------------------------------------------------------------------------------------------
FReply SCogImguiWidget::OnAnalogValueChanged(const FGeometry& MyGeometry, const FAnalogInputEvent& AnalogInputEvent)
{
if (AnalogInputEvent.GetKey().IsGamepadKey())
{
//if (bShareGamepad)
//{
// // TODO: handle imgui gamepad
// return FReply::Unhandled();
//}
return FReply::Unhandled();
}
else
{
//if (bShareKeyboard)
//{
// return FReply::Unhandled();
//}
}
return FReply::Handled();
}
//--------------------------------------------------------------------------------------------------------------------------
FReply SCogImguiWidget::OnMouseButtonDown(const FGeometry& MyGeometry, const FPointerEvent& MouseEvent)
{
if (Context->GetEnableInput() == false)
{
UE_LOG(LogCogImGui, VeryVerbose, TEXT("SCogImguiWidget::OnMouseButtonDown | %s | Unhandled | EnableInput == false"), Window.IsValid() ? *Window->GetTitle().ToString() : *FString("None"));
return FReply::Unhandled();
}
const uint32 MouseButton = FCogImguiInputHelper::ToImGuiMouseButton(MouseEvent.GetEffectingButton());
ImGui::GetIO().AddMouseSourceEvent(ImGuiMouseSource_Mouse);
ImGui::GetIO().AddMouseButtonEvent(MouseButton, true);
UE_LOG(LogCogImGui, VeryVerbose, TEXT("SCogImguiWidget::OnMouseButtonDown | Window:%s | Handled"), Window.IsValid() ? *Window->GetTitle().ToString() : *FString("None"));
return FReply::Handled();
}
//--------------------------------------------------------------------------------------------------------------------------
FReply SCogImguiWidget::OnMouseButtonUp(const FGeometry& MyGeometry, const FPointerEvent& MouseEvent)
{
if (Context->GetEnableInput() == false)
{
UE_LOG(LogCogImGui, VeryVerbose, TEXT("SCogImguiWidget::OnMouseButtonUp | Window:%s | Unhandled | EnableInput == false"), Window.IsValid() ? *Window->GetTitle().ToString() : *FString("None"));
return FReply::Unhandled();
}
const uint32 MouseButton = FCogImguiInputHelper::ToImGuiMouseButton(MouseEvent.GetEffectingButton());
ImGui::GetIO().AddMouseSourceEvent(ImGuiMouseSource_Mouse);
ImGui::GetIO().AddMouseButtonEvent(MouseButton, false);
UE_LOG(LogCogImGui, VeryVerbose, TEXT("SCogImguiWidget::OnMouseButtonUp | Window:%s | Handled"), Window.IsValid() ? *Window->GetTitle().ToString() : *FString("None"));
return FReply::Handled();
}
//--------------------------------------------------------------------------------------------------------------------------
FReply SCogImguiWidget::OnMouseWheel(const FGeometry& MyGeometry, const FPointerEvent& MouseEvent)
{
if (Context->GetEnableInput() == false)
{
return FReply::Unhandled();
}
ImGui::GetIO().AddMouseSourceEvent(ImGuiMouseSource_Mouse);
ImGui::GetIO().AddMouseWheelEvent(0, MouseEvent.GetWheelDelta());
return FReply::Handled();
}
//--------------------------------------------------------------------------------------------------------------------------
FReply SCogImguiWidget::OnMouseMove(const FGeometry& MyGeometry, const FPointerEvent& MouseEvent)
{
if (Context->GetEnableInput() == false)
{
//UE_LOG(LogCogImGui, VeryVerbose, TEXT("SCogImguiWidget::OnMouseMove | Window:%s | Unhandled | EnableInput == false"), Window.IsValid() ? *Window->GetTitle().ToString() : *FString("None"));
return FReply::Unhandled();
}
ImGuiIO& IO = ImGui::GetIO();
if (IO.ConfigFlags & ImGuiConfigFlags_ViewportsEnable)
{
IO.AddMousePosEvent(MouseEvent.GetScreenSpacePosition().X, MouseEvent.GetScreenSpacePosition().Y);
}
else
{
const FVector2D TransformedMousePosition = MouseEvent.GetScreenSpacePosition() - Context->GetMainWidget()->GetTickSpaceGeometry().GetAbsolutePosition();
IO.AddMousePosEvent(TransformedMousePosition.X, TransformedMousePosition.Y);
}
//UE_LOG(LogCogImGui, VeryVerbose, TEXT("SCogImguiWidget::OnMouseMove | Window:%s | Handled"), Window.IsValid() ? *Window->GetTitle().ToString() : *FString("None"));
return FReply::Handled();
}
//--------------------------------------------------------------------------------------------------------------------------
FReply SCogImguiWidget::OnFocusReceived(const FGeometry& MyGeometry, const FFocusEvent& FocusEvent)
{
return Super::OnFocusReceived(MyGeometry, FocusEvent);
}
//--------------------------------------------------------------------------------------------------------------------------
//void SCogImguiWidget::TickFocus()
//{
// FCogImguiModule& Module = FCogImguiModule::Get();
//
// const bool bShouldEnableInput = Module.GetEnableInput();
// if (bEnableInput != bShouldEnableInput)
// {
// bEnableInput = bShouldEnableInput;
//
// if (bEnableInput)
// {
// TakeFocus();
// }
// else
// {
// ReturnFocus();
// }
// }
// else 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<SWidget> 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();
//}
@@ -8,11 +8,11 @@ class UPlayerInput;
enum ImGuiKey : int;
struct FKeyBind;
class FImGuiInputProcessor : public IInputProcessor
class FCogImGuiInputProcessor : public IInputProcessor
{
public:
FImGuiInputProcessor(UPlayerInput* InPlayerInput, FCogImguiContext* InContext, SCogImguiWidget* InWidget);
FCogImGuiInputProcessor(UPlayerInput* InPlayerInput, FCogImguiContext* InContext, SCogImguiWidget* InWidget);
virtual void Tick(const float DeltaTime, FSlateApplication& SlateApp, TSharedRef<ICursor> SlateCursor) override;
@@ -38,22 +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);
static ImGuiKey ToImKey(const FKey& Key);
static bool IsKeyEventMatchingKeyBind(const FKeyEvent& KeyEvent, const FKeyBind& KeyBind);
static bool IsConsoleEvent(const FKeyEvent& KeyEvent);
static bool IsStopPlaySessionEvent(const FKeyEvent& KeyEvent);
static uint32 ToImGuiMouseButton(const FKey& MouseButton);
TObjectPtr<FCogImguiContext> Context = nullptr;
TObjectPtr<UPlayerInput> PlayerInput = nullptr;
@@ -45,6 +45,10 @@ public:
void SetDPIScale(float Value);
TObjectPtr<const UGameViewportClient> GetGameViewport() const { return GameViewport; }
TSharedPtr<const SCogImguiWidget> GetMainWidget() const { return MainWidget; }
private:
void OnDisplayMetricsChanged(const FDisplayMetrics& DisplayMetrics) const;
@@ -59,6 +63,12 @@ private:
void BuildFont();
void ReturnFocus();
void TickFocus();
void TakeFocus();
ULocalPlayer* GetLocalPlayer() const;
static void ImGui_CreateWindow(ImGuiViewport* Viewport);
@@ -10,6 +10,9 @@ struct ImGuiWindow;
using CogTextureIndex = int32;
constexpr bool ForwardEvent = false;
constexpr bool TerminateEvent = true;
class COGIMGUI_API FCogImguiHelper
{
public:
@@ -38,7 +38,9 @@ public:
static bool IsStopPlaySessionEvent(const FKeyEvent& KeyEvent);
static uint32 MouseButtonToImGuiMouseButton(const FKey& MouseButton);
static uint32 ToImGuiMouseButton(const FKey& MouseButton);
static ImGuiKey ToImKey(const FKey& Key);
static EMouseCursor::Type ToSlateMouseCursor(ImGuiMouseCursor MouseCursor);
@@ -48,6 +50,10 @@ public:
static FString KeyBindToString(const FKeyBind& KeyBind);
static bool IsMouseInsideMainViewport();
static bool IsKeyBoundToCommand(const UPlayerInput* InPlayerInput, const FKeyEvent& KeyEvent);
template<typename T, std::enable_if_t<(sizeof(T) <= sizeof(ImWchar)), T>* = nullptr>
static ImWchar CastInputChar(T Char)
{
@@ -8,6 +8,7 @@
#include "Widgets/SLeafWidget.h"
class FCogImguiContext;
class SWindow;
class UGameViewportClient;
//--------------------------------------------------------------------------------------------------------------------------
@@ -33,12 +34,35 @@ public:
virtual FVector2D ComputeDesiredSize(float Scale) const override;
virtual FReply OnKeyDown(const FGeometry& MyGeometry, const FKeyEvent& KeyEvent) override;
virtual FReply OnKeyUp(const FGeometry& MyGeometry, const FKeyEvent& KeyEvent) override;
virtual FReply OnAnalogValueChanged(const FGeometry& MyGeometry, const FAnalogInputEvent& AnalogInputEvent) override;
virtual FReply OnMouseButtonDown(const FGeometry& MyGeometry, const FPointerEvent& MouseEvent) override;
virtual FReply OnMouseButtonUp(const FGeometry& MyGeometry, const FPointerEvent& MouseEvent) override;
virtual FReply OnMouseWheel(const FGeometry& MyGeometry, const FPointerEvent& MouseEvent) override;
virtual FReply OnMouseMove(const FGeometry& MyGeometry, const FPointerEvent& MouseEvent) override;
virtual FReply OnFocusReceived(const FGeometry& MyGeometry, const FFocusEvent& FocusEvent) override;
void SetDrawData(const ImDrawData* InDrawData);
TSharedPtr<const SWindow> GetWindow() const { return Window; }
void SetWindow(TSharedPtr<SWindow> Value) { Window = Value; }
protected:
FReply HandleKeyEvent(const FGeometry& MyGeometry, const FKeyEvent& KeyEvent);
void TickFocus();
void TakeFocus();
void ReturnFocus();
TObjectPtr<FCogImguiContext> Context = nullptr;
TSharedPtr<SWindow> Window = nullptr;
FSlateRenderTransform ImGuiRenderTransform;
mutable TArray<FSlateVertex> VertexBuffer;