Fix some issues with new root canvas stuff
This commit is contained in:
@@ -2,13 +2,16 @@
|
||||
//
|
||||
// RootCanvas.h
|
||||
//
|
||||
// UlxRootCanvasPanel is a UCanvasPanel subclass whose
|
||||
// slots (UlxRootCanvasSlot) carry input-mode configuration
|
||||
// in addition to layout. The PlayerController scans these
|
||||
// slots, sorted by ZOrder, to arbitrate pointer visibility,
|
||||
// capture, focus, and input-component blocking for
|
||||
// top-level widgets. ZOrder therefore serves double duty:
|
||||
// it determines draw order AND input priority.
|
||||
// Luprex provides a "window management system" for root
|
||||
// widgets. In this system, all top-level widgets have to go
|
||||
// into the root canvas (instead of the viewport). The
|
||||
// window management system monitors the widgets within the
|
||||
// root canvas and continuously updates the z-orders, the
|
||||
// pointer visibility, the mouse capture mode, the keyboard
|
||||
// focus, and enhanced input event routing based on hints
|
||||
// and directives given by the widgets.
|
||||
//
|
||||
// To learn more, read Docs/Luprex-Window-Management.md
|
||||
//
|
||||
////////////////////////////////////////////////////////////
|
||||
|
||||
@@ -29,11 +32,6 @@ class UWidget;
|
||||
//
|
||||
// UlxRootCanvasSlot
|
||||
//
|
||||
// Luprex provides a "window management system" for root widgets.
|
||||
// This system is documented in Docs/Keyboard-Focus-and-Input-Modes.md
|
||||
// The Root Canvas Slot is how widgets ask the window management system
|
||||
// to engage certain behaviors.
|
||||
//
|
||||
////////////////////////////////////////////////////////////
|
||||
UCLASS()
|
||||
class INTEGRATION_API UlxRootCanvasSlot : public UCanvasPanelSlot
|
||||
@@ -60,32 +58,24 @@ public:
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Luprex|Input Mode")
|
||||
bool EnableEnhancedInput = true;
|
||||
|
||||
// Knowing whether the slot is under construction helps us to work
|
||||
// around some bugs in Unreal. See below.
|
||||
bool SlotUnderConstruction = true;
|
||||
|
||||
// Reliable version of SetZOrder. There is a bug in the normal version of
|
||||
// SetZOrder: it crashes if you use it during OnConstruct. We have a
|
||||
// workaround, but it requires using a different getter and setter.
|
||||
UFUNCTION(BlueprintCallable, Category = "Luprex|Input Mode")
|
||||
void SetZOrderReliable(int32 Order);
|
||||
// Sequence number assigned when this slot was last brought to front.
|
||||
int32 BringToFrontCount = 0;
|
||||
|
||||
// Reliable version of GetZOrder. There is a bug in the normal version of
|
||||
// SetZOrder: it crashes if you use it during OnConstruct. We have a
|
||||
// workaround, but it requires using a different getter and setter.
|
||||
UFUNCTION(BlueprintCallable, Category = "Luprex|Input Mode")
|
||||
int32 GetZOrderReliable();
|
||||
// Widget Z Ordering: widgets that show the pointer go on top of windows
|
||||
// that don't, and within a group, widgets that have greater BringToFrontCount
|
||||
// go on top. Sorting an array with this puts the top windows at the end
|
||||
// of the array.
|
||||
bool operator<(const UlxRootCanvasSlot &Other) const
|
||||
{
|
||||
if (ShowPointer != Other.ShowPointer) return !ShowPointer;
|
||||
return BringToFrontCount < Other.BringToFrontCount;
|
||||
}
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
//
|
||||
// UlxRootCanvasPanel
|
||||
//
|
||||
// A UCanvasPanel that uses UlxRootCanvasSlot for its
|
||||
// children instead of the plain UCanvasPanelSlot. Layout
|
||||
// behavior is identical to UCanvasPanel; only the slot
|
||||
// type differs.
|
||||
//
|
||||
////////////////////////////////////////////////////////////
|
||||
UCLASS()
|
||||
class INTEGRATION_API UlxRootCanvasPanel : public UCanvasPanel
|
||||
@@ -94,18 +84,18 @@ class INTEGRATION_API UlxRootCanvasPanel : public UCanvasPanel
|
||||
|
||||
public:
|
||||
|
||||
// Convenience wrapper around AddChild that returns the
|
||||
// derived slot type, so callers don't have to cast.
|
||||
// Add a child to the canvas. Also brings the child to the front
|
||||
// for the first time, ensuring that every widget has a unique
|
||||
// BringToFront counter.
|
||||
UFUNCTION()
|
||||
UlxRootCanvasSlot* AddChildToRootCanvas(UWidget* Content);
|
||||
|
||||
// Find children of type UserWidget. Return them in a sorted
|
||||
// order, with the highest Zorder first.
|
||||
// order, with the bottom window first and the top window last.
|
||||
TArray<UlxRootCanvasSlot*> GetSortedUserWidgets();
|
||||
|
||||
// Return the largest ZOrder across all slots, or 0 if empty.
|
||||
// Used as the basis for placing new widgets on top.
|
||||
int32 GetMaxZOrder() const;
|
||||
// Return the highest-priority UserWidget slot, or nullptr if there are none.
|
||||
UlxRootCanvasSlot* GetTopWidget();
|
||||
|
||||
// This function updates several window-management-related properties
|
||||
// which are stored in the UserWidget and the lxRootCanvasSlot. Note that
|
||||
@@ -119,6 +109,17 @@ public:
|
||||
bool ShowPointer, bool BlockInput, bool EnableEnhancedInput,
|
||||
bool BringToFront, UWidget *DesiredFocusWidget);
|
||||
|
||||
// Bring the widget to the front of the Z order within its group.
|
||||
// This is implemented using the BringToFront counter.
|
||||
UFUNCTION(BlueprintCallable, Category = "Luprex|Window Management",
|
||||
meta = (DefaultToSelf = "Widget"))
|
||||
static void BringToFront(class UUserWidget *Widget);
|
||||
|
||||
// Recompute and apply ZOrder values for all slots based on ShowPointer and
|
||||
// BringToFrontCount. Must be called from a context where SetZOrder is safe -
|
||||
// i.e. not during OnConstruct.
|
||||
void UpdateZOrders();
|
||||
|
||||
// Fetch the UlxRootCanvasSlot for a widget that is parented to a
|
||||
// UlxRootCanvasPanel. Returns nullptr via the WrongType exec pin
|
||||
// if the widget isn't a root widget (no slot, or slot is not a
|
||||
@@ -129,8 +130,17 @@ public:
|
||||
|
||||
protected:
|
||||
|
||||
// UPanelWidget
|
||||
// We inherit most of our code from CanvasPanel. This causes the
|
||||
// CanvasPanel code to allocate slots of type UlxRootCanvasSlot.
|
||||
virtual UClass* GetSlotClass() const override;
|
||||
|
||||
// We override OnSlotAdded in order to be able to be able to
|
||||
// fully finish initializing the slot before the widget
|
||||
// OnConstruct method has a chance to execute.
|
||||
virtual void OnSlotAdded(UPanelSlot* InSlot) override;
|
||||
|
||||
// Monotonic counter incremented each time any slot is brought to front.
|
||||
int32 BringToFrontCounter = 0;
|
||||
};
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user