diff --git a/Source/ImGui/Private/ImGuiInputState.cpp b/Source/ImGui/Private/ImGuiInputState.cpp index 575a856..5961183 100644 --- a/Source/ImGui/Private/ImGuiInputState.cpp +++ b/Source/ImGui/Private/ImGuiInputState.cpp @@ -7,7 +7,7 @@ FImGuiInputState::FImGuiInputState() { - ClearState(); + ResetState(); } void FImGuiInputState::AddCharacter(TCHAR Char) @@ -45,22 +45,23 @@ void FImGuiInputState::SetMouseDown(uint32 MouseIndex, bool bIsDown) } } -void FImGuiInputState::ClearState() +void FImGuiInputState::ResetState() { ClearCharacters(); + ClearKeys(); - using std::fill; - fill(KeysDown, &KeysDown[Utilities::GetArraySize(KeysDown)], false); - fill(MouseButtonsDown, &MouseButtonsDown[Utilities::GetArraySize(MouseButtonsDown)], false); + ClearMouseButtons(); + ClearMouseAnalogue(); - // Fully expanding dirty parts of both arrays, to inform about the change. - KeysUpdateRange.SetFull(); - MouseButtonsUpdateRange.SetFull(); + ClearModifierKeys(); } void FImGuiInputState::ClearUpdateState() { - ClearCharacters(); + if (InputCharactersNum > 0) + { + ClearCharacters(); + } KeysUpdateRange.SetEmpty(); MouseButtonsUpdateRange.SetEmpty(); @@ -70,6 +71,38 @@ void FImGuiInputState::ClearUpdateState() void FImGuiInputState::ClearCharacters() { + using std::fill; + fill(InputCharacters, &InputCharacters[Utilities::GetArraySize(InputCharacters)], 0); InputCharactersNum = 0; - InputCharacters[0]; +} + +void FImGuiInputState::ClearKeys() +{ + using std::fill; + fill(KeysDown, &KeysDown[Utilities::GetArraySize(KeysDown)], false); + + // Expand update range because keys array has been updated. + KeysUpdateRange.SetFull(); +} + +void FImGuiInputState::ClearMouseButtons() +{ + using std::fill; + fill(MouseButtonsDown, &MouseButtonsDown[Utilities::GetArraySize(MouseButtonsDown)], false); + + // Expand update range because mouse buttons array has been updated. + MouseButtonsUpdateRange.SetFull(); +} + +void FImGuiInputState::ClearMouseAnalogue() +{ + MousePosition = FVector2D::ZeroVector; + MouseWheelDelta = 0.f; +} + +void FImGuiInputState::ClearModifierKeys() +{ + bIsControlDown = false; + bIsShiftDown = false; + bIsAltDown = false; } diff --git a/Source/ImGui/Private/ImGuiInputState.h b/Source/ImGui/Private/ImGuiInputState.h index 62b90a4..1312723 100644 --- a/Source/ImGui/Private/ImGuiInputState.h +++ b/Source/ImGui/Private/ImGuiInputState.h @@ -76,8 +76,29 @@ public: // @param Position - New mouse position void SetMousePosition(const FVector2D& Position) { MousePosition = Position; } - // Clear state and mark as dirty. - void ClearState(); + // Get Control down state. + bool IsControlDown() const { return bIsControlDown; } + + // Set Control down state. + // @param bIsDown - True, if Control is down + void SetControlDown(bool bIsDown) { bIsControlDown = bIsDown; } + + // Get Shift down state. + bool IsShiftDown() const { return bIsShiftDown; } + + // Set Shift down state. + // @param bIsDown - True, if Shift is down + void SetShiftDown(bool bIsDown) { bIsShiftDown = bIsDown; } + + // Get Alt down state. + bool IsAltDown() const { return bIsAltDown; } + + // Set Alt down state. + // @param bIsDown - True, if Alt is down + void SetAltDown(bool bIsDown) { bIsAltDown = bIsDown; } + + // Reset state and mark as dirty. + void ResetState(); // Clear part of the state that is meant to be updated in every frame like: accumulators, buffers and information // about dirty parts of keys or mouse buttons arrays. @@ -86,6 +107,10 @@ public: private: void ClearCharacters(); + void ClearKeys(); + void ClearMouseButtons(); + void ClearMouseAnalogue(); + void ClearModifierKeys(); FVector2D MousePosition = FVector2D::ZeroVector; float MouseWheelDelta = 0.f; @@ -98,4 +123,8 @@ private: FKeysArray KeysDown; FKeysIndexRange KeysUpdateRange; + + bool bIsControlDown = false; + bool bIsShiftDown = false; + bool bIsAltDown = false; }; diff --git a/Source/ImGui/Private/ImGuiInteroperability.cpp b/Source/ImGui/Private/ImGuiInteroperability.cpp index 656ec50..044058d 100644 --- a/Source/ImGui/Private/ImGuiInteroperability.cpp +++ b/Source/ImGui/Private/ImGuiInteroperability.cpp @@ -154,9 +154,9 @@ namespace ImGuiInterops IO.MouseWheel += InputState.GetMouseWheelDelta(); // Copy key modifiers. - IO.KeyCtrl = InputState.GetKeys()[LeftControl] || InputState.GetKeys()[RightControl]; - IO.KeyShift = InputState.GetKeys()[LeftShift] || InputState.GetKeys()[RightShift]; - IO.KeyAlt = InputState.GetKeys()[LeftAlt] || InputState.GetKeys()[RightAlt]; + IO.KeyCtrl = InputState.IsControlDown(); + IO.KeyShift = InputState.IsShiftDown(); + IO.KeyAlt = InputState.IsAltDown(); IO.KeySuper = false; // Copy buffers. @@ -172,7 +172,7 @@ namespace ImGuiInterops if (InputState.GetCharactersNum() > 0) { - Copy(InputState.GetCharacters(), IO.InputCharacters, InputState.GetCharactersNum()); + Copy(InputState.GetCharacters(), IO.InputCharacters); } } } diff --git a/Source/ImGui/Private/SImGuiWidget.cpp b/Source/ImGui/Private/SImGuiWidget.cpp index eca6bd0..9660fd4 100644 --- a/Source/ImGui/Private/SImGuiWidget.cpp +++ b/Source/ImGui/Private/SImGuiWidget.cpp @@ -29,12 +29,14 @@ SImGuiWidget::~SImGuiWidget() FReply SImGuiWidget::OnKeyChar(const FGeometry& MyGeometry, const FCharacterEvent& CharacterEvent) { InputState.AddCharacter(CharacterEvent.GetCharacter()); + return FReply::Handled(); } FReply SImGuiWidget::OnKeyDown(const FGeometry& MyGeometry, const FKeyEvent& KeyEvent) { InputState.SetKeyDown(ImGuiInterops::GetKeyIndex(KeyEvent), true); + CopyModifierKeys(KeyEvent); // If this is tilde key then let input through and release the focus to allow console to process it. if (KeyEvent.GetKey() == EKeys::Tilde) @@ -48,39 +50,58 @@ FReply SImGuiWidget::OnKeyDown(const FGeometry& MyGeometry, const FKeyEvent& Key FReply SImGuiWidget::OnKeyUp(const FGeometry& MyGeometry, const FKeyEvent& KeyEvent) { InputState.SetKeyDown(ImGuiInterops::GetKeyIndex(KeyEvent), false); + CopyModifierKeys(KeyEvent); + return FReply::Handled(); } FReply SImGuiWidget::OnMouseButtonDown(const FGeometry& MyGeometry, const FPointerEvent& MouseEvent) { InputState.SetMouseDown(ImGuiInterops::GetMouseIndex(MouseEvent), true); + CopyModifierKeys(MouseEvent); + return FReply::Handled(); } FReply SImGuiWidget::OnMouseButtonDoubleClick(const FGeometry& MyGeometry, const FPointerEvent& MouseEvent) { InputState.SetMouseDown(ImGuiInterops::GetMouseIndex(MouseEvent), true); + CopyModifierKeys(MouseEvent); + return FReply::Handled(); } FReply SImGuiWidget::OnMouseButtonUp(const FGeometry& MyGeometry, const FPointerEvent& MouseEvent) { InputState.SetMouseDown(ImGuiInterops::GetMouseIndex(MouseEvent), false); + CopyModifierKeys(MouseEvent); + return FReply::Handled(); } FReply SImGuiWidget::OnMouseWheel(const FGeometry& MyGeometry, const FPointerEvent& MouseEvent) { InputState.AddMouseWheelDelta(MouseEvent.GetWheelDelta()); + CopyModifierKeys(MouseEvent); + return FReply::Handled(); } FReply SImGuiWidget::OnMouseMove(const FGeometry& MyGeometry, const FPointerEvent& MouseEvent) { InputState.SetMousePosition(MouseEvent.GetScreenSpacePosition() - MyGeometry.AbsolutePosition); + CopyModifierKeys(MouseEvent); + return FReply::Handled(); } +void SImGuiWidget::CopyModifierKeys(const FInputEvent& InputEvent) +{ + InputState.SetControlDown(InputEvent.IsControlDown()); + InputState.SetShiftDown(InputEvent.IsShiftDown()); + InputState.SetAltDown(InputEvent.IsAltDown()); +} + void SImGuiWidget::OnPostImGuiUpdate() { InputState.ClearUpdateState(); diff --git a/Source/ImGui/Private/SImGuiWidget.h b/Source/ImGui/Private/SImGuiWidget.h index c6a775b..56703b0 100644 --- a/Source/ImGui/Private/SImGuiWidget.h +++ b/Source/ImGui/Private/SImGuiWidget.h @@ -12,6 +12,8 @@ class FImGuiModuleManager; // Slate widget for rendering ImGui output and storing Slate inputs. class SImGuiWidget : public SLeafWidget { + typedef SLeafWidget Super; + public: SLATE_BEGIN_ARGS(SImGuiWidget) @@ -49,6 +51,8 @@ public: private: + FORCEINLINE void CopyModifierKeys(const FInputEvent& InputEvent); + void OnPostImGuiUpdate(); virtual int32 OnPaint(const FPaintArgs& Args, const FGeometry& AllottedGeometry, const FSlateRect& MyClippingRect, FSlateWindowElementList& OutDrawElements, int32 LayerId, const FWidgetStyle& WidgetStyle, bool bParentEnabled) const override;