From f7816ee1fd7cdd7fe3f01f13dcaa57205ce78c80 Mon Sep 17 00:00:00 2001 From: Sebastian Date: Sat, 2 Sep 2017 18:42:41 +0100 Subject: [PATCH] Added ImGui.InputEnabled console variable to control when ImGui should receive inputs. --- Source/ImGui/Private/SImGuiWidget.cpp | 56 +++++++++++++++++++++++++++ Source/ImGui/Private/SImGuiWidget.h | 13 ++++++- 2 files changed, 67 insertions(+), 2 deletions(-) diff --git a/Source/ImGui/Private/SImGuiWidget.cpp b/Source/ImGui/Private/SImGuiWidget.cpp index 476b648..7043714 100644 --- a/Source/ImGui/Private/SImGuiWidget.cpp +++ b/Source/ImGui/Private/SImGuiWidget.cpp @@ -12,6 +12,15 @@ #include "Utilities/ScopeGuards.h" +namespace CVars +{ + TAutoConsoleVariable InputEnabled(TEXT("ImGui.InputEnabled"), 0, + TEXT("Allows to enable or disable ImGui input mode.\n") + TEXT("0: disabled (default)\n") + TEXT("1: enabled, input is routed to ImGui and with a few exceptions is consumed."), + ECVF_Default); +} + BEGIN_SLATE_FUNCTION_BUILD_OPTIMIZATION void SImGuiWidget::Construct(const FArguments& InArgs) { @@ -20,6 +29,9 @@ void SImGuiWidget::Construct(const FArguments& InArgs) ContextIndex = InArgs._ContextIndex; ModuleManager->OnPostImGuiUpdate().AddRaw(this, &SImGuiWidget::OnPostImGuiUpdate); + + // Sync visibility with default input enabled state. + SetVisibilityFromInputEnabled(); } END_SLATE_FUNCTION_BUILD_OPTIMIZATION @@ -28,6 +40,15 @@ SImGuiWidget::~SImGuiWidget() ModuleManager->OnPostImGuiUpdate().RemoveAll(this); } +void SImGuiWidget::Tick(const FGeometry& AllottedGeometry, const double InCurrentTime, const float InDeltaTime) +{ + Super::Tick(AllottedGeometry, InCurrentTime, InDeltaTime); + + // Note: Moving that update to console variable sink or callback might seem like a better alternative but input + // setup in this function is better handled here. + UpdateInputEnabled(); +} + FReply SImGuiWidget::OnKeyChar(const FGeometry& MyGeometry, const FCharacterEvent& CharacterEvent) { InputState.AddCharacter(CharacterEvent.GetCharacter()); @@ -154,6 +175,41 @@ void SImGuiWidget::CopyModifierKeys(const FPointerEvent& MouseEvent) } } +void SImGuiWidget::SetVisibilityFromInputEnabled() +{ + // If we don't use input disable hit test to make this widget invisible for cursors hit detection. + SetVisibility(bInputEnabled ? EVisibility::Visible : EVisibility::HitTestInvisible); +} + +void SImGuiWidget::UpdateInputEnabled() +{ + const bool bEnabled = CVars::InputEnabled.GetValueOnGameThread() > 0; + if (bInputEnabled != bEnabled) + { + bInputEnabled = bEnabled; + + SetVisibilityFromInputEnabled(); + + // Setup input to show cursor and take focus when we use input or clear state and pass focus back to viewport + // when we don't. + auto& Slate = FSlateApplication::Get(); + if (bInputEnabled) + { + Slate.ResetToDefaultPointerInputSettings(); + Slate.SetKeyboardFocus(SharedThis(this)); + } + else + { + if (Slate.GetKeyboardFocusedWidget().Get() == this) + { + Slate.SetUserFocusToGameViewport(Slate.GetUserIndexForKeyboard()); + } + + UpdateInputMode(false, false); + } + } +} + void SImGuiWidget::UpdateInputMode(bool bNeedKeyboard, bool bNeedMouse) { const EInputMode NewInputMode = diff --git a/Source/ImGui/Private/SImGuiWidget.h b/Source/ImGui/Private/SImGuiWidget.h index 27bb843..10861e9 100644 --- a/Source/ImGui/Private/SImGuiWidget.h +++ b/Source/ImGui/Private/SImGuiWidget.h @@ -36,7 +36,9 @@ public: // SWidget overrides //---------------------------------------------------------------------------------------------------- - virtual bool SupportsKeyboardFocus() const override { return true; } + virtual void Tick(const FGeometry& AllottedGeometry, const double InCurrentTime, const float InDeltaTime) override; + + virtual bool SupportsKeyboardFocus() const override { return bInputEnabled; } virtual FReply OnKeyChar(const FGeometry& MyGeometry, const FCharacterEvent& CharacterEvent) override; @@ -64,7 +66,7 @@ public: private: - enum class EInputMode + enum class EInputMode : uint8 { None, MouseOnly, @@ -74,6 +76,12 @@ private: FORCEINLINE void CopyModifierKeys(const FInputEvent& InputEvent); FORCEINLINE void CopyModifierKeys(const FPointerEvent& MouseEvent); + // Update visibility based on input enabled state. + void SetVisibilityFromInputEnabled(); + + // Update input enabled state from console variable. + void UpdateInputEnabled(); + // Determine new input mode based on requirement hints. void UpdateInputMode(bool bNeedKeyboard, bool bNeedMouse); @@ -91,6 +99,7 @@ private: int32 ContextIndex = 0; EInputMode InputMode = EInputMode::None; + bool bInputEnabled = false; FImGuiInputState InputState; };