Compare commits
2 Commits
960abba07f
...
4680a0f3f4
| Author | SHA1 | Date | |
|---|---|---|---|
| 4680a0f3f4 | |||
| 3f6ef4b56c |
1
.gitignore
vendored
1
.gitignore
vendored
@@ -52,3 +52,4 @@ GPF-output/**
|
|||||||
__pycache__/
|
__pycache__/
|
||||||
.clangd-query/
|
.clangd-query/
|
||||||
COMMIT.txt
|
COMMIT.txt
|
||||||
|
CLAUDE.md
|
||||||
|
|||||||
Binary file not shown.
@@ -28,72 +28,53 @@ Our window management system, in order to keep things
|
|||||||
simple, has to make some assumptions about how Luprex games
|
simple, has to make some assumptions about how Luprex games
|
||||||
work. So, here are the rules.
|
work. So, here are the rules.
|
||||||
|
|
||||||
The presumption is that most of the time, you're interacting
|
Top-level UserWidgets get inserted into a "Root Canvas",
|
||||||
with the 3D world, and importantly, we assume that if you're
|
instead of into the viewport. The root canvas implements most
|
||||||
using keyboard and mouse, you're using the mouse to control
|
of the functionality of our window management system.
|
||||||
the camera - aka "mouselook."
|
|
||||||
|
|
||||||
We also assume that as you interact with the 3D world, you
|
The keyboard focus rule is simple: the UserWidget in front
|
||||||
will occasionally be popping up GUI widgets that can
|
according to the z-order gets keyboard focus. The window
|
||||||
coexist with mouselook. These mouselook-compatible
|
management system will put focus on the front widget and
|
||||||
widgets don't need a mouse pointer, they don't need you to
|
will keep it there. The *only* way to give a UserWidget
|
||||||
click on anything. They rely on buttons alone. We assume
|
keyboard focus is to raise it to the front of the z-order.
|
||||||
that most of the GUI elements you interact with will be
|
|
||||||
mouselook-compatible, in order to allow you to stay
|
|
||||||
immersed in the 3D world.
|
|
||||||
|
|
||||||
But we also assume that there may be moments when you want
|
Mouse movements events are handled in two different ways:
|
||||||
to pop up a very complicated widget, for example, a big
|
the system can shift between "mouselook" mode and
|
||||||
inventory management screen, for which a mouse pointer would
|
"point-and-click" mode. Every top-level UserWidget declares
|
||||||
be very helpful. For occasions like these, a widget can
|
whether it wants a mouse pointer or not. If the front
|
||||||
declare "ShowPointer".
|
UserWidget wants a pointer, the system shifts into
|
||||||
|
point-and-click mode.
|
||||||
|
|
||||||
When one of these ShowPointer widgets is on the screen,
|
In point-and-click mode, enhanced input mouse move events
|
||||||
the entire system switches into point-and-click mode.
|
cannot happen. In mouselook mode, widget OnMouseDown and
|
||||||
In point-and-click mode, the pointer is visible. Mouse
|
OnMouseMove events cannot happen. In both modes, you can
|
||||||
movements move the pointer. Mouse movements do *not* get
|
track mouse movement, but you have to use different
|
||||||
translated into mouselook.
|
mechanisms.
|
||||||
|
|
||||||
Widgets have a z-order: one widget is always "in front." In
|
Widgets that declare that they want a pointer are
|
||||||
mouselook mode, only the front widget can get keyboard
|
automatically put in front of widgets that don't want a
|
||||||
focus. In mouselook mode, the window management system will
|
pointer. Because of this rule, the system essentially
|
||||||
put focus on the front widget, and it will keep it there.
|
separates into the "mouselook" layer underneath, and the
|
||||||
If you want some other widget to have focus, you'll have to
|
"point-and-click" layer on top. When the point-and-click
|
||||||
bring that widget to the front.
|
layer gets out of the way, then you can drive the 3D world.
|
||||||
|
|
||||||
In point-and-click mode, the keyboard focus rules differ.
|
# State Variables of the Window Management System
|
||||||
When you raise a widget to the front, the window management
|
|
||||||
system will give it focus. But, if you click the mouse
|
|
||||||
pointer on a different widget - say, on a text box in a
|
|
||||||
different widget - keyboard focus can get transferred.
|
|
||||||
|
|
||||||
When a ShowPointer window is on the screen, not only
|
I have made an effort to keep the number of state variables
|
||||||
does the system shift to point-and-click mode, but it
|
that you have to control to an absolute minimum, and to
|
||||||
also keeps all ShowPointer windows in front of any
|
concentrate them all in one place. That place is the "Root
|
||||||
non-ShowPointer window.
|
Canvas Slot."
|
||||||
|
|
||||||
Basically, you can think of the system as a 3D world with
|
|
||||||
its mouselook-compatible widgets as one layer, and the
|
|
||||||
point-and-click stuff as a second layer on top of that.
|
|
||||||
When the point-and-click layer gets out of the way, then you
|
|
||||||
can drive the 3D world.
|
|
||||||
|
|
||||||
# The Root Canvas
|
|
||||||
|
|
||||||
Typically, in Unreal, when you create a new top-level
|
Typically, in Unreal, when you create a new top-level
|
||||||
widget, you insert it into the viewport using
|
widget, you insert it into the viewport using AddToViewport.
|
||||||
AddToViewport. But to use our window management
|
But to use our window management system, you must instead
|
||||||
system, you must instead insert top-level widgets into a
|
insert top-level widgets into a 'root canvas', using
|
||||||
'root canvas', using AddWidgetToRoot.
|
AddWidgetToRoot.
|
||||||
|
|
||||||
The main reason for the creation of the root canvas is that
|
The root canvas object associates a RootCanvasSlot to each
|
||||||
it gives us a place to store window-management related
|
|
||||||
hints, and window-management related state.
|
|
||||||
|
|
||||||
The root canvas object attaches a RootCanvasSlot to each
|
|
||||||
top-level widget. The RootCanvasSlot is a place where we can
|
top-level widget. The RootCanvasSlot is a place where we can
|
||||||
store management-related hints for that widget. The contents
|
store window management-related hints for that widget. The
|
||||||
of the RootCanvasSlot include the following:
|
contents of the RootCanvasSlot include the following:
|
||||||
|
|
||||||
- `ShowPointer`: If true, this is a point-and-click widget.
|
- `ShowPointer`: If true, this is a point-and-click widget.
|
||||||
When this widget is in front, the pointer is visible,
|
When this widget is in front, the pointer is visible,
|
||||||
@@ -106,20 +87,23 @@ of the RootCanvasSlot include the following:
|
|||||||
*this* widget are disabled.
|
*this* widget are disabled.
|
||||||
|
|
||||||
- `BringToFrontCount`: Effectively, a timestamp indicating
|
- `BringToFrontCount`: Effectively, a timestamp indicating
|
||||||
the last time this window was brought to the front.
|
the last time this window was brought to the front. This
|
||||||
|
is the main factor determining the z-order of the widgets.
|
||||||
|
|
||||||
In addition, the top-level widget itself contains some
|
In addition, the top-level widget itself contains some
|
||||||
window-management related properties. Currently, these are:
|
window-management related properties. Currently, these are:
|
||||||
|
|
||||||
- `DesiredFocusWidget`: Indicates which sub-widget, if any,
|
- `DesiredFocusWidget`: Indicates which sub-widget, if any,
|
||||||
should be given focus.
|
should be given focus. When the system grants focus to
|
||||||
|
the frontmost UserWidget, the focus actually goes here.
|
||||||
|
|
||||||
That is all the state variables that control our new window
|
There are deliberately *no other variables* that control our
|
||||||
management system. If your blueprint is managing these
|
new window management system. If your blueprint is managing
|
||||||
properties, then it is doing everything it needs to do.
|
these properties, then it is doing everything it needs to
|
||||||
|
do.
|
||||||
|
|
||||||
The function SetWidgetWindowManagement can set all of these
|
The function SetWidgetWindowManagement can set all of these
|
||||||
properties in a single operation. That one function is all
|
variables in a single operation. That one function is all
|
||||||
you need to control the entire window management system.
|
you need to control the entire window management system.
|
||||||
|
|
||||||
# Handling Keyboard and Gamepad Buttons
|
# Handling Keyboard and Gamepad Buttons
|
||||||
@@ -177,7 +161,8 @@ This is all almost entirely unchanged from Unreal's default
|
|||||||
behavior. We've only made two tiny tweaks: we send enhanced
|
behavior. We've only made two tiny tweaks: we send enhanced
|
||||||
input to widgets in front-to-back order, and, widgets
|
input to widgets in front-to-back order, and, widgets
|
||||||
disable enhanced input by setting a flag instead of by
|
disable enhanced input by setting a flag instead of by
|
||||||
unregistering their input component.
|
unregistering their input component. Other than that, this
|
||||||
|
is all just stock unreal.
|
||||||
|
|
||||||
# Handling mouse buttons
|
# Handling mouse buttons
|
||||||
|
|
||||||
@@ -185,9 +170,9 @@ Mouse buttons behave differently than keyboard buttons.
|
|||||||
|
|
||||||
Widgets have an OnMouseDown handler. This is only active in
|
Widgets have an OnMouseDown handler. This is only active in
|
||||||
point-and-click mode. OnMouseDown only fires when three
|
point-and-click mode. OnMouseDown only fires when three
|
||||||
things are true: the pointer is visible, the pointer is
|
things are true: the system must be in point-and-click mode,
|
||||||
inside the rectangle of a widget, and the widget is marked
|
the pointer must be inside the rectangle of a widget, and
|
||||||
hit-testable.
|
the widget must be marked hit-testable.
|
||||||
|
|
||||||
If no OnMouseDown event fires, or if OnMouseDown declares
|
If no OnMouseDown event fires, or if OnMouseDown declares
|
||||||
the mouse down to be "not handled," then the mouse down
|
the mouse down to be "not handled," then the mouse down
|
||||||
@@ -199,18 +184,18 @@ buttons. It can be mapped to an enhanced input event by the
|
|||||||
input mapping context, and then from there, it can be
|
input mapping context, and then from there, it can be
|
||||||
handled by any enhanced input event handler in a blueprint.
|
handled by any enhanced input event handler in a blueprint.
|
||||||
|
|
||||||
The upshot of all this is: if you want to think of a
|
The upshot of all this is: if you want to think of a mouse
|
||||||
mouse button as "just another button," then the
|
button as "just another button," then the way to achieve
|
||||||
way to achieve that is to handle the mouse button using
|
that is to *not* write an OnMouseDown handler, but instead,
|
||||||
an enhanced input handler.
|
to deal with it through enhanced input.
|
||||||
|
|
||||||
We have very slightly tweaked the default behavior of
|
We have tweaked the default behavior of unreal. If the
|
||||||
unreal. If the pointer is visible, and you click on a
|
system is in point-and-click mode, and you click on a widget
|
||||||
widget that is hit-testable, but which has no OnMouseDown
|
that is hit-testable, but which has no OnMouseDown handler,
|
||||||
handler, we provide a default OnMouseDown behavior: we
|
we provide a default OnMouseDown behavior: we bring the
|
||||||
bring the widget to the front. Because our system
|
top-level UserWidget to the front. Because our system grants
|
||||||
grants keyboard focus to the widget in front, this
|
keyboard focus to the widget in front, this will also grant
|
||||||
will grant focus, if the widget can accept it.
|
focus.
|
||||||
|
|
||||||
# Handling Mouse Movement
|
# Handling Mouse Movement
|
||||||
|
|
||||||
@@ -251,17 +236,19 @@ If you're using our Luprex window management system, there are
|
|||||||
several things your blueprint should *NOT* do:
|
several things your blueprint should *NOT* do:
|
||||||
|
|
||||||
- DO NOT use SetKeyboardFocus, SetUserFocus, or any other
|
- DO NOT use SetKeyboardFocus, SetUserFocus, or any other
|
||||||
function with Set-Focus in the name. Instead, set
|
function with Set-Focus in the name. Instead, just
|
||||||
the DesiredFocusWidget inside a top-level widget, and our
|
be aware that the frontmost UserWidget will get focus.
|
||||||
window management system will decide who gets focus.
|
It can delegate that focus to one of its components by
|
||||||
|
setting DesiredFocusWidget.
|
||||||
|
|
||||||
- DO NOT use SetShowMouseCursor, or set the bShowMouseCursor
|
- DO NOT use SetShowMouseCursor, or set the bShowMouseCursor
|
||||||
flag. Instead, set the ShowPointer flag in the configuration
|
flag. Instead, set the ShowPointer flag in the
|
||||||
of any top-level widget.
|
RootCanvasSlot of any top-level widget.
|
||||||
|
|
||||||
- DO NOT use UserWidget::RegisterInputComponent or
|
- DO NOT use UserWidget::RegisterInputComponent or
|
||||||
UserWidget::UnregisterInputComponent. These will be ignored.
|
UserWidget::UnregisterInputComponent. These will be
|
||||||
Instead, set or unset the flag EnableEnhancedInput, which
|
ignored. Instead, set or unset the flag
|
||||||
|
EnableEnhancedInput in the RootCanvasSlot, which
|
||||||
effectively does the same thing.
|
effectively does the same thing.
|
||||||
|
|
||||||
- DO NOT use SetZOrder. If you try, you will be overridden
|
- DO NOT use SetZOrder. If you try, you will be overridden
|
||||||
@@ -279,7 +266,7 @@ several things your blueprint should *NOT* do:
|
|||||||
window management system.
|
window management system.
|
||||||
|
|
||||||
- DO NOT use AddToViewport or AddToPlayerScreen. Top level
|
- DO NOT use AddToViewport or AddToPlayerScreen. Top level
|
||||||
widgets should be inserted into the root canvas using
|
UserWidgets should be inserted into the root canvas using
|
||||||
AddWidgetToRoot.
|
AddWidgetToRoot.
|
||||||
|
|
||||||
- DO NOT use SetIgnoreInput. You will be overridden. Our
|
- DO NOT use SetIgnoreInput. You will be overridden. Our
|
||||||
@@ -287,7 +274,8 @@ several things your blueprint should *NOT* do:
|
|||||||
system being active, turning it off would cause everything
|
system being active, turning it off would cause everything
|
||||||
to fail. However, a widget can handle keyboard or
|
to fail. However, a widget can handle keyboard or
|
||||||
character events, causing them not to be propagated, it
|
character events, causing them not to be propagated, it
|
||||||
can also block events to any window lower in the z-order.
|
can also block events to any widget lower in the z-order,
|
||||||
|
and to the player controller and character.
|
||||||
|
|
||||||
- DO NOT use SetInputModeXXX. Be aware that there is no
|
- DO NOT use SetInputModeXXX. Be aware that there is no
|
||||||
"input mode" enum or "input mode" variable anywhere in
|
"input mode" enum or "input mode" variable anywhere in
|
||||||
|
|||||||
@@ -6,6 +6,8 @@
|
|||||||
#include "Layout/Geometry.h"
|
#include "Layout/Geometry.h"
|
||||||
#include "Widgets/Layout/Anchors.h"
|
#include "Widgets/Layout/Anchors.h"
|
||||||
#include "Common.h"
|
#include "Common.h"
|
||||||
|
#include "Engine/GameViewportClient.h"
|
||||||
|
#include "Slate/SGameLayerManager.h"
|
||||||
#include "Kismet/KismetTextLibrary.h"
|
#include "Kismet/KismetTextLibrary.h"
|
||||||
#include "UObject/UObjectIterator.h"
|
#include "UObject/UObjectIterator.h"
|
||||||
|
|
||||||
@@ -246,17 +248,32 @@ FFormatArgumentData UlxFormatDataLibrary::FormatArgumentDataTransform(const FTra
|
|||||||
|
|
||||||
FFormatArgumentData UlxFormatDataLibrary::FormatArgumentDataGeometry(const FGeometry &AutoConvertedValue, const FString &Name)
|
FFormatArgumentData UlxFormatDataLibrary::FormatArgumentDataGeometry(const FGeometry &AutoConvertedValue, const FString &Name)
|
||||||
{
|
{
|
||||||
FVector2D LocalSize = AutoConvertedValue.GetLocalSize();
|
FVector2D UL = AutoConvertedValue.GetAbsolutePosition();
|
||||||
FVector2D AbsPos = AutoConvertedValue.GetAbsolutePosition();
|
FVector2D LR = AutoConvertedValue.GetAbsolutePositionAtCoordinates(FVector2f(1.0f, 1.0f));
|
||||||
FVector2D AbsSize = AutoConvertedValue.GetAbsoluteSize();
|
if (GEngine && GEngine->GameViewport)
|
||||||
|
{
|
||||||
|
TSharedPtr<IGameLayerManager> GameLayerManager = GEngine->GameViewport->GetGameLayerManager();
|
||||||
|
if (GameLayerManager.IsValid())
|
||||||
|
{
|
||||||
|
const FGeometry ViewportGeometry = GameLayerManager->GetViewportWidgetHostGeometry();
|
||||||
|
const FVector2D ViewportLocalSize = FVector2D(ViewportGeometry.GetLocalSize());
|
||||||
|
FVector2D ViewportPixelSize;
|
||||||
|
GEngine->GameViewport->GetViewportSize(ViewportPixelSize);
|
||||||
|
if (ViewportLocalSize.X > 0.0 && ViewportLocalSize.Y > 0.0)
|
||||||
|
{
|
||||||
|
const FVector2D PixelScale = ViewportPixelSize / ViewportLocalSize;
|
||||||
|
UL = ViewportGeometry.AbsoluteToLocal(UL) * PixelScale;
|
||||||
|
LR = ViewportGeometry.AbsoluteToLocal(LR) * PixelScale;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
FFormatArgumentData Result;
|
FFormatArgumentData Result;
|
||||||
Result.ArgumentValueType = EFormatArgumentType::Text;
|
Result.ArgumentValueType = EFormatArgumentType::Text;
|
||||||
Result.ArgumentName = Name;
|
Result.ArgumentName = Name;
|
||||||
Result.ArgumentValue = FText::Format(
|
Result.ArgumentValue = FText::Format(
|
||||||
INVTEXT("Geom(Local={0}x{1} Abs={2}x{3} Pos={4},{5})"),
|
INVTEXT("UL={0},{1} LR={2},{3}"),
|
||||||
FText::AsNumber(LocalSize.X), FText::AsNumber(LocalSize.Y),
|
FText::AsNumber(UL.X), FText::AsNumber(UL.Y),
|
||||||
FText::AsNumber(AbsSize.X), FText::AsNumber(AbsSize.Y),
|
FText::AsNumber(LR.X), FText::AsNumber(LR.Y));
|
||||||
FText::AsNumber(AbsPos.X), FText::AsNumber(AbsPos.Y));
|
|
||||||
return Result;
|
return Result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -312,7 +329,7 @@ void UlxFormatDataLibrary::FormatLogMessageInternal(UObject *Context, ElxFormatL
|
|||||||
double Now = FPlatformTime::Seconds();
|
double Now = FPlatformTime::Seconds();
|
||||||
FString Key = Context->GetClass()->GetName() + TEXT("::") + InPattern;
|
FString Key = Context->GetClass()->GetName() + TEXT("::") + InPattern;
|
||||||
double &Last = LastLogTime.FindOrAdd(Key, 0.0);
|
double &Last = LastLogTime.FindOrAdd(Key, 0.0);
|
||||||
if (Now - Last < 1.0)
|
if (Now - Last < 2.0)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -131,13 +131,6 @@ UInputComponent* AlxPlayerControllerBase::GetWidgetInputComponent(UUserWidget *W
|
|||||||
return Cast<UInputComponent>(Value);
|
return Cast<UInputComponent>(Value);
|
||||||
}
|
}
|
||||||
|
|
||||||
void AlxPlayerControllerBase::RestoreFocusToFrontWidget(const UObject *Context)
|
|
||||||
{
|
|
||||||
// This will trigger UpdateInputMode to shift focus back to
|
|
||||||
// the front window, if the front window wants focus.
|
|
||||||
FromContext(Context)->RootCanvas->LastWidgetGrantedFocus = nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
void AlxPlayerControllerBase::AddWidgetToRoot(UUserWidget *Widget)
|
void AlxPlayerControllerBase::AddWidgetToRoot(UUserWidget *Widget)
|
||||||
{
|
{
|
||||||
if (!IsValid(Widget))
|
if (!IsValid(Widget))
|
||||||
@@ -309,32 +302,20 @@ void AlxPlayerControllerBase::UpdateInputMode()
|
|||||||
|
|
||||||
GameViewportClient->SetIgnoreInput(false);
|
GameViewportClient->SetIgnoreInput(false);
|
||||||
|
|
||||||
// How we handle focus depends on whether we're showing the pointer.
|
// We always put keyboard focus on whatever user widget is in
|
||||||
// In pointer mode, we set focus to the desired state just once,
|
// front. If the front widget doesn't want keyboard focus,
|
||||||
// and then we let the pointer control it from there on. In
|
// then we put keyboard focus on the viewport.
|
||||||
// no-pointer mode, we set focus to the desired state and
|
if (Focus)
|
||||||
// keep putting it back forever.
|
|
||||||
//
|
|
||||||
// If the user clicks the mouse on a focusable widget, the
|
|
||||||
// viewport client notifies us of that fact. We then focus the
|
|
||||||
// widget if possible.
|
|
||||||
//
|
|
||||||
if ((!ShowPointer) || (RootCanvas->LastWidgetGrantedFocus != Focus))
|
|
||||||
{
|
{
|
||||||
if (Focus)
|
if (TSharedPtr<SWidget> SlateFocus = Focus->GetCachedWidget())
|
||||||
{
|
{
|
||||||
if (TSharedPtr<SWidget> SlateFocus = Focus->GetCachedWidget())
|
SlateOperations.SetUserFocus(SlateFocus.ToSharedRef());
|
||||||
{
|
|
||||||
SlateOperations.SetUserFocus(SlateFocus.ToSharedRef());
|
|
||||||
RootCanvas->LastWidgetGrantedFocus = Focus;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
SlateOperations.SetUserFocus(ViewportWidgetRef);
|
|
||||||
RootCanvas->LastWidgetGrantedFocus = nullptr;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
SlateOperations.SetUserFocus(ViewportWidgetRef);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void AlxPlayerControllerBase::UpdateLookAt()
|
void AlxPlayerControllerBase::UpdateLookAt()
|
||||||
|
|||||||
@@ -65,10 +65,6 @@ public:
|
|||||||
// FProperty so we always see the current value without caching it.
|
// FProperty so we always see the current value without caching it.
|
||||||
static class UInputComponent* GetWidgetInputComponent(class UUserWidget *Widget);
|
static class UInputComponent* GetWidgetInputComponent(class UUserWidget *Widget);
|
||||||
|
|
||||||
// Restore focus back to the window that is in front, if it wants focus.
|
|
||||||
UFUNCTION(BlueprintCallable, meta = (WorldContext = "Context"), Category = "Luprex|Root Canvas")
|
|
||||||
static void RestoreFocusToFrontWidget(const UObject *Context);
|
|
||||||
|
|
||||||
// Add a widget to the root canvas at ZOrder 0 with default slot flags.
|
// Add a widget to the root canvas at ZOrder 0 with default slot flags.
|
||||||
UFUNCTION(BlueprintCallable, Category = "Luprex|Root Canvas",
|
UFUNCTION(BlueprintCallable, Category = "Luprex|Root Canvas",
|
||||||
meta = (DefaultToSelf = "Widget", HideSelfPin = "true"))
|
meta = (DefaultToSelf = "Widget", HideSelfPin = "true"))
|
||||||
|
|||||||
@@ -101,8 +101,6 @@ void UlxRootCanvasPanel::BringToFront(UUserWidget *Widget)
|
|||||||
UlxRootCanvasPanel *Panel = Cast<UlxRootCanvasPanel>(Slot->Parent);
|
UlxRootCanvasPanel *Panel = Cast<UlxRootCanvasPanel>(Slot->Parent);
|
||||||
if (!Panel) return;
|
if (!Panel) return;
|
||||||
Slot->BringToFrontCount = ++Panel->BringToFrontCounter;
|
Slot->BringToFrontCount = ++Panel->BringToFrontCounter;
|
||||||
// This refocuses the widget, even if it was already in front.
|
|
||||||
Panel->LastWidgetGrantedFocus = Panel;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void UlxRootCanvasPanel::SetWidgetWindowManagement(class UUserWidget *Widget,
|
void UlxRootCanvasPanel::SetWidgetWindowManagement(class UUserWidget *Widget,
|
||||||
|
|||||||
@@ -129,9 +129,6 @@ public:
|
|||||||
meta = (DefaultToSelf = "Widget", ExpandEnumAsExecs = "Result"))
|
meta = (DefaultToSelf = "Widget", ExpandEnumAsExecs = "Result"))
|
||||||
static UlxRootCanvasSlot *GetRootCanvasSlot(class UUserWidget *Widget, ElxSuccessOrWrongType &Result);
|
static UlxRootCanvasSlot *GetRootCanvasSlot(class UUserWidget *Widget, ElxSuccessOrWrongType &Result);
|
||||||
|
|
||||||
// The last widget whose focus request was granted.
|
|
||||||
TObjectKey<UWidget> LastWidgetGrantedFocus;
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
// We inherit most of our code from CanvasPanel. This causes the
|
// We inherit most of our code from CanvasPanel. This causes the
|
||||||
|
|||||||
Reference in New Issue
Block a user