UnrealImGui/Source/ImGui/Private/SImGuiWidget.h
Sebastian fa32fd95e3 Added to ImGui Widget a canvas map mode that allows to drag and change scale of the ImGui canvas.
Map mode allows to reach areas of the canvas that otherwise would be inaccessible (for instance modal windows positioned in the centre of the canvas) and to modify which part should be visible by default.
2018-04-21 22:43:15 +01:00

188 lines
6.6 KiB
C++

// Distributed under the MIT License (MIT) (see accompanying LICENSE file)
#pragma once
#include "ImGuiInputState.h"
#include <Widgets/SLeafWidget.h>
class FImGuiModuleManager;
// Slate widget for rendering ImGui output and storing Slate inputs.
class SImGuiWidget : public SLeafWidget
{
typedef SLeafWidget Super;
public:
SLATE_BEGIN_ARGS(SImGuiWidget)
{}
SLATE_ARGUMENT(FImGuiModuleManager*, ModuleManager)
SLATE_ARGUMENT(UGameViewportClient*, GameViewport)
SLATE_ARGUMENT(int32, ContextIndex)
SLATE_END_ARGS()
void Construct(const FArguments& InArgs);
~SImGuiWidget();
// Get index of the context that this widget is targeting.
int32 GetContextIndex() const { return ContextIndex; }
// Get input state associated with this widget.
const FImGuiInputState& GetInputState() const { return InputState; }
// Get the game viewport to which this widget is attached.
const TWeakObjectPtr<UGameViewportClient>& GetGameViewport() const { return GameViewport; }
// Detach widget from viewport assigned during construction (effectively allowing to dispose this widget).
void Detach();
//----------------------------------------------------------------------------------------------------
// SWidget overrides
//----------------------------------------------------------------------------------------------------
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;
virtual FReply OnKeyDown(const FGeometry& MyGeometry, const FKeyEvent& KeyEvent) override;
virtual FReply OnKeyUp(const FGeometry& MyGeometry, const FKeyEvent& KeyEvent) override;
virtual FReply OnMouseButtonDown(const FGeometry& MyGeometry, const FPointerEvent& MouseEvent) override;
virtual FReply OnMouseButtonDoubleClick(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 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;
virtual void OnFocusLost(const FFocusEvent& FocusEvent) override;
virtual void OnMouseEnter(const FGeometry& MyGeometry, const FPointerEvent& MouseEvent) override;
virtual void OnMouseLeave(const FPointerEvent& MouseEvent) override;
private:
enum class EInputMode : uint8
{
None,
// Mouse pointer only without user focus
MousePointerOnly,
// Full input with user focus
MouseAndKeyboard
};
// If needed, add to event reply a mouse lock or unlock request.
FORCEINLINE FReply WithMouseLockRequests(FReply&& Reply);
FORCEINLINE void CopyModifierKeys(const FInputEvent& InputEvent);
FORCEINLINE void CopyModifierKeys(const FPointerEvent& MouseEvent);
bool IsConsoleOpened() const;
bool IgnoreKeyEvent(const FKeyEvent& KeyEvent) const;
void SetMouseCursorOverride(EMouseCursor::Type InMouseCursorOverride);
// Update visibility based on input enabled state.
void SetVisibilityFromInputEnabled();
// Update input enabled state from console variable.
void UpdateInputEnabled();
// Determine new input mode based on hints.
void UpdateInputMode(bool bHasKeyboardFocus, bool bHasMousePointer);
void UpdateMouseStatus();
FORCEINLINE bool HasMouseEventNotification() const { return bReceivedMouseEvent; }
FORCEINLINE void NotifyMouseEvent() { bReceivedMouseEvent = true; }
FORCEINLINE void ClearMouseEventNotification() { bReceivedMouseEvent = false; }
void OnPostImGuiUpdate();
// Update canvas map mode based on input state.
void UpdateCanvasMapMode(const FInputEvent& InputEvent);
void SetCanvasMapMode(bool bEnabled);
void AddCanvasScale(float Delta);
void UdateCanvasScale(float DeltaSeconds);
void UpdateCanvasDraggingConditions(const FPointerEvent& MouseEvent);
void UpdateCanvasDragging(const FGeometry& MyGeometry, const FPointerEvent& MouseEvent);
// Canvas scale in which the whole canvas is visible in the viewport. We don't scale below that value.
float GetMinCanvasScale() const;
// Normalized canvas scale mapping range [MinCanvasScale..1] to [0..1].
float GetNormalizedCanvasScale(float Scale) const;
// Position of the canvas origin, given the current canvas scale and offset. Uses NormalizedCanvasScale to smoothly
// transition between showing visible canvas area at scale 1 and the whole canvas at min canvas scale.
FVector2D GetCanvasPosition(float Scale, const FVector2D& Offset) const;
bool InFrameGrabbingRange(const FVector2D& Position, float Scale, const FVector2D& Offset) const;
FVector2D GetViewportSize() const;
virtual int32 OnPaint(const FPaintArgs& Args, const FGeometry& AllottedGeometry, const FSlateRect& MyClippingRect, FSlateWindowElementList& OutDrawElements, int32 LayerId, const FWidgetStyle& WidgetStyle, bool bParentEnabled) const override;
virtual FVector2D ComputeDesiredSize(float) const override;
void OnDebugDraw();
FImGuiModuleManager* ModuleManager = nullptr;
TWeakObjectPtr<UGameViewportClient> GameViewport;
mutable TArray<FSlateVertex> VertexBuffer;
mutable TArray<SlateIndex> IndexBuffer;
int32 ContextIndex = 0;
FImGuiInputState InputState;
EInputMode InputMode = EInputMode::None;
bool bInputEnabled = false;
bool bReceivedMouseEvent = false;
bool bMouseLock = false;
// Canvas map mode allows to zoom in/out and navigate between different parts of ImGui canvas.
bool bCanvasMapMode = false;
// If enabled (only if not fully zoomed out), allows to drag ImGui canvas. Dragging canvas modifies canvas offset.
bool bCanvasDragging = false;
// If enabled (only if zoomed out), allows to drag a frame that represents a visible area of the ImGui canvas.
// Mouse deltas are converted to canvas offset by linear formula derived from GetCanvasPosition function.
bool bFrameDragging = false;
// True, if mouse and input are in state that allows to start frame dragging. Used for highlighting.
bool bFrameDraggingReady = false;
bool bFrameDraggingSkipMouseMove = false;
EMouseCursor::Type MouseCursorOverride = EMouseCursor::None;
float TargetCanvasScale = 1.f;
float CanvasScale = 1.f;
FVector2D CanvasOffset = FVector2D::ZeroVector;
float ImGuiFrameCanvasScale = 1.f;
FVector2D ImGuiFrameCanvasOffset = FVector2D::ZeroVector;
TWeakPtr<SWidget> PreviousUserFocusedWidget;
};