mirror of
https://github.com/sinbad/StevesUEHelpers.git
synced 2025-02-23 09:35:25 +00:00
Menus section first draft
This commit is contained in:
parent
0b26f9b937
commit
eaca0d4a18
BIN
Resources/popmenu.png
Normal file
BIN
Resources/popmenu.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 47 KiB |
BIN
Resources/showingamenu.png
Normal file
BIN
Resources/showingamenu.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 264 KiB |
@ -22,7 +22,7 @@ auto GS = GetStevesGameSubsystem(GetWorld());
|
||||
|
||||
Blueprint:
|
||||
|
||||

|
||||

|
||||
|
||||
C++:
|
||||
|
||||
@ -34,7 +34,7 @@ EInputMode Mode = GS->GetLastInputModeUsed(PlayerIndex);
|
||||
|
||||
Blueprint:
|
||||
|
||||

|
||||

|
||||
|
||||
C++:
|
||||
|
||||
|
180
doc/Menus.md
Normal file
180
doc/Menus.md
Normal file
@ -0,0 +1,180 @@
|
||||
# Menus
|
||||
|
||||
There are 2 main classes to help you create menu systems: MenuBase and MenuStack.
|
||||
MenuStack keeps a stack of menus where the top item on the stack has the focus, and
|
||||
going "back" pops that off the top and returns focus to the previous menu.
|
||||
Fairly standard hierarchical menus.
|
||||
|
||||
The [Examples Project](https://github.com/sinbad/StevesUEExamples) includes a
|
||||
funcitoning menu you can look over to see how it's done, and/or you can follow
|
||||
these steps.
|
||||
|
||||
## Important: Disabling default focus rendering
|
||||
|
||||
Unreal makes a token effort at providing a way to render which of your controls
|
||||
has the keyboard / gamepad focus, but it's rubbish. It's a grey dotted line
|
||||
that looks awful. No-one wants that.
|
||||
|
||||
The FocusableButton widget in this library provides a much nicer default focus
|
||||
option (using the Hovered style), and also provides you focus events you can
|
||||
use to do something more advanced if you want. So we have no need for Unreal's
|
||||
dotted line nonsense.
|
||||
|
||||
1. Open Project Settings
|
||||
1. Find the Focus section
|
||||
1. Change Render Focus Rule to Never
|
||||
|
||||
All better. 😉
|
||||
|
||||
## Creating the MenuStack
|
||||
|
||||
The MenuStack class is best used as a dual purpose: keeping track of the stack
|
||||
of individual menus, and also being the container for them.
|
||||
|
||||
### 1. Create the Blueprint
|
||||
|
||||
Start by creating a new Widget Blueprint.
|
||||
|
||||
1. Right-click in Content browser
|
||||
1. Select User Interface
|
||||
1. Select Widget Blueprint
|
||||
1. Give it a name, like "Widget_MainMenuStack"
|
||||
|
||||
### 2. Reparent to MenuStack
|
||||
|
||||
We need our widget to be subclassed from MenuStack to gain its power.
|
||||
|
||||
1. Open the File Menu
|
||||
2. Select Reparent Blueprint
|
||||
3. Search for MenuStack and select it
|
||||
|
||||
### 3. Create a Container for the Menus
|
||||
|
||||
The menus need to live somewhere inside this widget. You can lay out this
|
||||
widget however you like, but somewhere there needs to be a Named Slot which is
|
||||
where your menus will live when they're displayed.
|
||||
|
||||
You can use any layout you like; in the [examples project](https://github.com/sinbad/StevesUEExamples) I've just centred the Named Slot and made it fit its content,
|
||||
meaning we have complete flexibility on how we size our menus.
|
||||
|
||||
1. In the Palette, search for Named Slot
|
||||
1. Place this Named Slot wherever you want the menus to appear in your layout
|
||||
1. Give the Named Slot a useful name, e.g. MenuContainer
|
||||
1. Select the root of your widget and look at the Details panel
|
||||
1. Set the "Menu Container" property to the Named Slot you just created
|
||||
1. Compile your widget
|
||||
|
||||
That's it, your MenuStack is ready to go.
|
||||
|
||||
## Creating a Menu
|
||||
|
||||
Now you need a menu to go in your stack. Let's create a basic main menu.
|
||||
|
||||
### 1. Create the Blueprint
|
||||
|
||||
Start by creating a new Widget Blueprint.
|
||||
|
||||
1. Right-click in Content browser
|
||||
1. Select User Interface
|
||||
1. Select Widget Blueprint
|
||||
1. Give it a name, like "Widget_MainMenuRoot"
|
||||
|
||||
### 2. Reparent to MenuBase
|
||||
|
||||
The MenuBase class gives us a bunch of nice convenience functionality, as well
|
||||
as being able to become part of a MenuStack. So our widget needs to be one of those.
|
||||
|
||||
1. Open the File Menu
|
||||
2. Select Reparent Blueprint
|
||||
3. Search for MenuBase and select it
|
||||
|
||||
### 3. Create the Menu Buttons
|
||||
|
||||
This library comes with a custom button which is perfect for menus, called
|
||||
FocusableButton. It has the advantage of automatically highlighting when
|
||||
focussed (e.g. gamepad or keyboard navigation).
|
||||
|
||||
1. Change the view mode (top-right) from Fill Screen to Desired
|
||||
* This is because we're fitting inside the container so will only take the space we need
|
||||
1. Right-click the Canvas Panel and Replace With > Vertical Box
|
||||
* We're only going to use a simple vertical menu for this demo
|
||||
1. Drag a Focusable Button from the Palette into the vertical Box
|
||||
1. Style it however you want
|
||||
* In particular, pay attention to the Style entries
|
||||
* The Hovered style will be used for the keyboard/gamepad selected state as well
|
||||
1. Add a child text widget
|
||||
1. Duplicate the button to fill out your menu
|
||||
|
||||
Obviously you can assign click events to each of those buttons to do whatever
|
||||
you want - which could be to launch sub-menus. But first, let's see how to
|
||||
actually get these menus on screen.
|
||||
|
||||
### 4. Set the default focus button
|
||||
|
||||
In this case we want *some* menu button to have the focus as soon as the
|
||||
menu opens, because it's a main menu.
|
||||
|
||||
1. Click on the root of your widget
|
||||
1. In Details, find Focusable Panel > Initial Focus Widget Name
|
||||
1. Type or copy/paste the name of the widget which should have focus on start
|
||||
|
||||
### 5. (Optional) Set input mode, pause etc
|
||||
|
||||
Each MenuBase can do some common things for you, like changing the input mode,
|
||||
pausing the game, or showing / hiding the pointer.
|
||||
|
||||
1. Click on the root of your widget
|
||||
1. In Details, find the Behavior section
|
||||
1. Set "Input Mode Setting" to something other than No Change if you want it to set the input mode
|
||||
1. Do the same for Mouse Pointer Visibility or Game Pause Setting
|
||||
|
||||
|
||||
## Showing a Menu
|
||||
|
||||
To show a menu, you need to do 2 things:
|
||||
|
||||
1. Create the MenuStack and add it to the viewport
|
||||
1. Create the MenuBase and add it to the stack (this adds it as a child, in the MenuContainer)
|
||||
|
||||
Here's an example of doing that in Blueprints:
|
||||
|
||||

|
||||
|
||||
## Adding a Submenu Level
|
||||
|
||||
To progress to a deeper level in the menu, you just push another instance on
|
||||
to the same stack exactly as you did with the first.
|
||||
|
||||
The default behaviour is that the existing top of stack
|
||||
is hidden (but not destroyed, so it keeps its state). You can change that
|
||||
by unchecking the "Hide when Superceded" option on a MenuBase level. Then, the
|
||||
menu will continue to be visible.
|
||||
|
||||
## Backing up
|
||||
|
||||
To go back a level in the menu, call PopMenu on the stack. Doing this from
|
||||
inside the sub-level is very easy, since every MenuBase has a reference to its
|
||||
parent stack:
|
||||
|
||||

|
||||
|
||||
The "Was Cancel" argument is to tell anything waiting on that menu level whether
|
||||
the action that closed the menu level should be considered "OK" or "Cancel";
|
||||
not everything needs this.
|
||||
|
||||
|
||||
## Close Notifications
|
||||
|
||||
You can listen to a menu level having been closed by binding to the OnClose
|
||||
event. That has the "Was Cancel" boolean in case you need to differentiate
|
||||
between OK/Cancel.
|
||||
|
||||
Menu levels are garbage collected so if you keep a reference to them then you'll
|
||||
always have access to their state regardless of whether they're active in the
|
||||
stack right now. So if you need to process some changes in a submenu you can
|
||||
just keep a reference to it and on close, process its contents.
|
||||
|
||||
|
||||
|
||||
|
||||
|
2
doc/OptionWidget.md
Normal file
2
doc/OptionWidget.md
Normal file
@ -0,0 +1,2 @@
|
||||
# Option Widget (OptionWidgetBase)
|
||||
|
@ -30,17 +30,17 @@ Several custom widgets are supplied to assist with some common challenges:
|
||||
and also remembers the last focus widget if you switch away & back
|
||||
without destroying it.
|
||||
|
||||
* [MenuBase](MenuBase.md)
|
||||
* [MenuBase](Menus.md)
|
||||
|
||||
A specialised [FocusablePanel](FocusablePanel.md) which adds the ability
|
||||
to be part of a contextual [MenuStack](MenuStack.md), and which
|
||||
to be part of a contextual [MenuStack](Menus.md), and which
|
||||
as it becomes the top of the stack can automatically grab focus, change game
|
||||
pause state, alter input modes, and change the mouse pointer visibility
|
||||
(all individually optional).
|
||||
|
||||
* [MenuStack](MenuStack.md)
|
||||
* [MenuStack](Menus.md)
|
||||
|
||||
A container for and stack of [MenuBase](MenuBase.md) instances, making it
|
||||
A container for and stack of [MenuBase](Menus.md) instances, making it
|
||||
easy to create multi-level on-screen menus with a simple "back" navigation.
|
||||
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user