Changed to hardware cursor as a default cursor in input mode and added ImGui.DrawMouseCursor console variable to allow to switch to ImGui cursor.

Using ImGui to draw cursor helps to reduce visual error between mouse cursor and position in ImGui. But it has been reported that this works really bad when frame-rate drops and becomes unusable below ~20 FPS. Taking that into account hardware cursor seems like a better default option. Old behaviour can be enabled with ImGui.DrawMouseCursor console variable.
This commit is contained in:
Sebastian 2018-03-13 23:42:37 +00:00
parent f3a5e8e6b9
commit f18e1f0b68
7 changed files with 68 additions and 10 deletions

View File

@ -23,7 +23,7 @@ The base aim of the project is to provide a basic integration of Dear ImGui, wit
This is a work in progress but it supports key Unreal features, like Multi-PIE sessions etc.
When running Multi-PIE session, each world gets its own ImGui context where world specific data can be visualised. When world update begins contexts are switched automatically, so using ImGui during objects update should be as easy as calling ImGui API functions.
When running Multi-PIE session, each world gets its own ImGui context to draw world specific data. When world update begins contexts are switched automatically, so using ImGui during objects update should be as easy as calling ImGui API functions.
For scenarios where automatic context switching above is not enough I'm planning to add mechanism allowing to explicitly select contexts. After that I plan to add example project, more usability features, better documentation and integration of Remote ImGui which enables using ImGui from a browser and to investigate possibility of opening ImGui for Blueprints.
@ -51,7 +51,8 @@ You should now be able to use ImGui.
*Console variables:*
- **ImGui.InputEnabled** - Allows to enable or disable ImGui input mode. 0: disabled (default); 1: enabled, input is routed to ImGui and with a few exceptions is consumed. Note: this is going to be supported by a keyboard short-cut, but in the meantime ImGui input can be enabled/disabled using console.
- **ImGui.InputEnabled** - Enable or disable ImGui input mode. 0: disabled (default); 1: enabled, input is routed to ImGui and with a few exceptions is consumed. Note: this is going to be supported by a keyboard short-cut, but in the meantime ImGui input can be enabled/disabled using console.
- **ImGui.DrawMouseCursor** - Whether or not mouse cursor in input mode should be drawn by ImGui. 0: disabled, hardware cursor will be used (default); 1: enabled, ImGui will take care for drawing mouse cursor.
- **ImGui.ShowDemo** - Show ImGui demo. 0: disabled (default); 1: enabled.
- **ImGui.Debug.Widget** - Show self-debug for the widget that renders ImGui output. 0: disabled (default); 1: enabled.

View File

@ -144,11 +144,13 @@ void FImGuiContextProxy::Tick(float DeltaSeconds, FSimpleMulticastDelegate* Shar
EndFrame();
}
// Update context information (some data, like mouse cursor, may be cleaned in new frame, so we should collect it
// beforehand).
bHasActiveItem = ImGui::IsAnyItemActive();
MouseCursor = ImGuiInterops::ToSlateMouseCursor(ImGui::GetMouseCursor());
// Begin a new frame and set the context back to a state in which it allows to draw controls.
BeginFrame(DeltaSeconds);
// Update context information.
bHasActiveItem = ImGui::IsAnyItemActive();
}
void FImGuiContextProxy::BeginFrame(float DeltaTime)

View File

@ -4,6 +4,8 @@
#include "ImGuiDrawData.h"
#include <ICursor.h>
#include <imgui.h>
#include <string>
@ -49,6 +51,8 @@ public:
bool HasActiveItem() const { return bHasActiveItem; }
EMouseCursor::Type GetMouseCursor() const { return MouseCursor; }
// Delegate called right before ending the frame to allows listeners draw their controls.
FSimpleMulticastDelegate& OnDraw() { return DrawEvent; }
@ -66,6 +70,7 @@ private:
ImGuiContext* Context = nullptr;
bool bHasActiveItem = false;
EMouseCursor::Type MouseCursor = EMouseCursor::None;
bool bIsFrameStarted = false;
FSimpleMulticastDelegate DrawEvent;

View File

@ -133,6 +133,30 @@ namespace ImGuiInterops
return -1;
}
EMouseCursor::Type ToSlateMouseCursor(ImGuiMouseCursor MouseCursor)
{
switch (MouseCursor)
{
case ImGuiMouseCursor_Arrow:
return EMouseCursor::Default;
case ImGuiMouseCursor_TextInput:
return EMouseCursor::TextEditBeam;
case ImGuiMouseCursor_Move:
return EMouseCursor::CardinalCross;
case ImGuiMouseCursor_ResizeNS:
return EMouseCursor::ResizeUpDown;
case ImGuiMouseCursor_ResizeEW:
return EMouseCursor::ResizeLeftRight;
case ImGuiMouseCursor_ResizeNESW:
return EMouseCursor::ResizeSouthWest;
case ImGuiMouseCursor_ResizeNWSE:
return EMouseCursor::ResizeSouthEast;
case ImGuiMouseCursor_None:
default:
return EMouseCursor::None;
}
}
//====================================================================================================
// Input State Copying
//====================================================================================================

View File

@ -4,6 +4,8 @@
#include "TextureManager.h"
#include <ICursor.h>
#include <imgui.h>
@ -52,6 +54,8 @@ namespace ImGuiInterops
return GetMouseIndex(MouseEvent.GetEffectingButton());
}
EMouseCursor::Type ToSlateMouseCursor(ImGuiMouseCursor MouseCursor);
//====================================================================================================
// Input State Copying

View File

@ -33,21 +33,27 @@ DEFINE_LOG_CATEGORY_STATIC(LogImGuiWidget, Warning, All);
namespace CVars
{
TAutoConsoleVariable<int> InputEnabled(TEXT("ImGui.InputEnabled"), 0,
TEXT("Allows to enable or disable ImGui input mode.\n")
TEXT("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."),
TEXT("1: enabled, input is routed to ImGui and with a few exceptions is consumed"),
ECVF_Default);
TAutoConsoleVariable<int> DrawMouseCursor(TEXT("ImGui.DrawMouseCursor"), 0,
TEXT("Whether or not mouse cursor in input mode should be drawn by ImGui.\n")
TEXT("0: disabled, hardware cursor will be used (default)\n")
TEXT("1: enabled, ImGui will take care for drawing mouse cursor"),
ECVF_Default);
TAutoConsoleVariable<int> DebugWidget(TEXT("ImGui.Debug.Widget"), 0,
TEXT("Show debug for SImGuiWidget.\n")
TEXT("0: disabled (default)\n")
TEXT("1: enabled."),
TEXT("1: enabled"),
ECVF_Default);
TAutoConsoleVariable<int> DebugInput(TEXT("ImGui.Debug.Input"), 0,
TEXT("Show debug for input state.\n")
TEXT("0: disabled (default)\n")
TEXT("1: enabled."),
TEXT("1: enabled"),
ECVF_Default);
}
@ -189,6 +195,20 @@ FReply SImGuiWidget::OnMouseWheel(const FGeometry& MyGeometry, const FPointerEve
return FReply::Handled();
}
FCursorReply SImGuiWidget::OnCursorQuery(const FGeometry& MyGeometry, const FPointerEvent& CursorEvent) const
{
EMouseCursor::Type MouseCursor = EMouseCursor::None;
if (CVars::DrawMouseCursor.GetValueOnGameThread() <= 0)
{
if (FImGuiContextProxy* ContextProxy = ModuleManager->GetContextManager().GetContextProxy(ContextIndex))
{
MouseCursor = ContextProxy->GetMouseCursor();
}
}
return FCursorReply::Cursor(MouseCursor);
}
FReply SImGuiWidget::OnMouseMove(const FGeometry& MyGeometry, const FPointerEvent& MouseEvent)
{
InputState.SetMousePosition(MouseEvent.GetScreenSpacePosition() - MyGeometry.AbsolutePosition);
@ -381,7 +401,7 @@ void SImGuiWidget::UpdateInputMode(bool bHasKeyboardFocus, bool bHasMousePointer
ClearMouseEventNotification();
}
InputState.SetMousePointer(bHasMousePointer);
InputState.SetMousePointer(bHasMousePointer && CVars::DrawMouseCursor.GetValueOnGameThread() > 0);
}
void SImGuiWidget::UpdateMouseStatus()

View File

@ -61,6 +61,8 @@ public:
virtual FReply OnMouseWheel(const FGeometry& MyGeometry, const FPointerEvent& MouseEvent) override;
virtual FCursorReply OnCursorQuery(const FGeometry& MyGeometry, const FPointerEvent& CursorEvent) const override;
virtual FReply OnMouseMove(const FGeometry& MyGeometry, const FPointerEvent& MouseEvent) override;
virtual FReply OnFocusReceived(const FGeometry& MyGeometry, const FFocusEvent& FocusEvent) override;