My previous post Custom UserWidget control for UMG, UE4 treated about creating custom UserWidget with a TextButton as an example. Styling should be next big step in creating a universal control component for UMG. In this article I will show you how to accurately control this UserWidget’s states visual feedback.
What will you gain?
Here are several pros that you get using proposed approach.
Unified layout style
Creating a custom control with customized style allows for fast layout building which is consistent with the rest of the application.
More polished control (potentially)
Taking care of style in a single custom control motivates to make it more polished as you are doing it only once.
Having controls using the same style helps to modify it later. A simple change in the control’s UserWidget modifies the look of control in the whole application! The same thing concerns repairing a bug when project is in advanced state.
Discovery of fantastic (and free) assets pack
This solution uses a monolytic #GameUI Essentials assets pack. It was released initially for free and hopefully it still is as you are reading this article.
A basic knowledge about UE4 and UMG would be desirable. C++ code will be used but one should make it through using information inside this article.
This tutorial was created in UnrealEngine 4.12.5. You can obtain UE4 from official website.
Microsoft Visual Studio
We will use the code very sparingly but it is a must in this solution so you need to obtain free Visual Studio 2015 Community Edition from here.
You will need a Windows 7 or higher (this solution uses Windows 10).
This solution is based on project from previous article Custom UserWidget control for UMG, UE4 and it can be dowloaded from here. You will need to run the TextButtonTest.uproject file and later compile the code to prepare the game to be run.
The complete project from this article can be downloaded from here.
Any PC capable of running UE4 will be suitable.
Downloading base project
Now run the TextButtonTest.uproject and click OK if it asks to recompile the project. Finally it should open a default untitled map. Open SimpleMap from the Content Browser and we are good to go.
Open the BP_TextButtonWidget Blueprint. This is the UserWidget control that we will style in the following sections.
Getting required assets
To style our TextButton UserWidget control we need to style the Button and the Text and later react on their state changes so they respond accordingly. Explicitly we need following assets:
Background for Normal, Hovered and Pressed state. We will use the gameui-menus_v1-1 assets pack from monolytic #GameUI Essentials.
A suitable font. We will use the Montserrat font, so we are consistent with the assets pack for Button.
Downloading monolytic #GameUI Essentials assets pack
On the next screen input your email and click Get.
This should forward you to the order receipt, where you need to click View product button.
Finally, you’ll access the download page. Please download the gameui-menus_v1-1 assets pack.
Extract the downloaded archive somewhere where you’ll have an easy access to. I do not advise putting them in the project folder. We will put there only the assets that we use.
Finally you should end up with folder consisting of following folders and files:
Downloading Montserrat font
The Montserrat font can be downloaded from here. Open the link and click Download OTF.
Extract the archive in a suitable location, but not in the Unreal Engine project itself. You should get the following files:
Creating UE4 assets
Getting raw images and fonts is only a first step of creating a style for our TextButton. The next thing it to make a UE4 assets out of them, so we can use them in the UserWidget.
The effect that we want to achieve is showcased on the 01_mainMenu_1.jpg image. If you open it you can see how we would like it to look at the end of article.
TextButton in normal state should have black background and white text.
TextButton in hovered and clicked state should have white background and black text.
Creating TextButton background assets
Open the yourlocation\gameui-menus_v1-1\01_mainMenu_1_assets folder. Image shown in 01_mainMenu_1.jpg was chopped to usable slices. We need the menu_1_clear.png and the menu_2_clear.png.
Select those files and drag them to the Unreal Editor’s Content folder. Unreal Engine will automatically convert them to usable assets.
Now rename the menu_1_clear asset to textbutton_background_white and menu_2_clear to textbutton_background_black. Click Save afterwards.
Creating TextButton font asset
This will be a little more tricky than the background assets. Click RMB (Right Mouse Button) in the Content folder and select User Interface -> Font.
Rename the asset to Montserrat and open it.
We need to add a Regular Font to the Font Family (types of font – Regular, Bold, Italic, etc). Click Add Font button, rename it to Regular and click the Folder icon. Next, navigate to the montserrat folder and select Montserrat-Regular.otf.
This is the only font that we need for our TextButton. You can enhance the Composite Font to support bigger Font Family. Save changes and close the window.
Altering the style of TextButton
Now we have all required assets to alter the style of TextButton. Let’s start with the Button.
Altering style of Button Widget
Open BP_TextButtonWidget and select the Button from Hierarchy window. In the Details panel open the Appearence -> Style menu. You can find there the Normal, Hovered, Pressed and Disabled states.
We will omit the Disabled state and focus on the other 3.
Expand the Normal menu and select an textbutton_background_black in the Image field. The Button preview will change accordingly.
Now repeat the process with Hovered and Pressed states, but using the textbutton_background_white asset and save changes.
Test run the game
Let’s test run the game now.
As we can see, changing Button’s background colors already altered it’s usage in UserWidget using the TextButton control. When the Button is not bothered it displays the Normal state.
Let’s Hover on the Button.
Button responded accordingly changing it’s background to white asset. The problem is that we can’t see Text now, because it’s color is always set to white.
For completion let’s click the Button.
Button responded accordingly setting the background to white asset. We also got the TextButton Clicked! text printed on the screen.
Let us take care of the TextButton’s Text Widget now.
Altering style of Text Widget
In our Text Widget we would like to change the color and the font of printed text. Color must be changed dynamically based on the Button’s state.
Changing Text Font
Changing font is easy, as it will not change on Button’s state.
Open the BP_TextButtonWidget’s Designer and select Text in Hierarchy window. In the Details panel find the Appearance -> Font field and change it from default Roboto to our Montserrat asset.
Text’s font on the preview will change accordingly.
Changing Text Color
Changing Text color needs additional logic because we need to react on the Button’s state so Text color is always in contrast to it.
Creating Blueprint logic
Switch to Graph and add 2 variables:
- TextButtonHoveredTextColor and
Both of them need to be of Type Slate Color. Compile Blueprint and set the Default Values for new variables: black for Hovered and white for Unhovered.
Let us also create 2 corresponding functions:
- ChangeTextColorOnButtonHover and
Open ChangeTextColorOnButtonHover, drag TextBlock_0 and pick get. Do the same for TextButtonHoveredTextColor. Next, drag a connection form TextBlock_0 and pick a Set Color and Opacity node. Connect ChangeTextColorOnButtonHover to new node’s In Color and Opacity field and drag Exec from the function input to that node.
Repeat the process with ChangeTextColorOnButtonUnhover function, but use the TextButtonUnhoveredTextColor variable.
Now go to the Designer, select Button and create the OnHovered and OnUnhovered nodes.
Go to the EventGraph and add an execution connection from OnHovered node to ChangeTextColorOnButtonHover function and from OnUnhovered node to ChangeTextColorOnButtonUnhover function.
Let’s test run the game.
At first glance we can see that the font has changed. Also text color in contrast to the button’s background as it should. Let’s try to hover over it.
Everything looks as we planned. Button’s state changed to Hover and so is the Button’s background. Our logic reacted on the OnHovered event and changed the color of text to black.
Let’s click it.
Responded as we wanted. Button and Text Widget’s are still in contrast.
Let’s leave the Button.
Our logic responded to the Unhovered event and changed the Text color back to white.
So are we finished? Unfortunately not. Let’s click the Button and drag the clicked cursor outside the Button.
Our logic is broken! We unhovered the Button so the Text changed it’s color to white, but Button is now in the Clicked state as we didn’t stop pressing LMB (Left Mouse Button).
We need to address this problem.
Altering Blueprint logic to address the Unhovered Pressed Button problem
To resolve this issue we need to respond to another 2 events of a Button – OnPressed and OnReleased. Go to BP_TextButtonWidget, select Button from Hierarchy window and add both mentioned events.
Now we need to add a boolean variable named IsButtonPressed that has default value of false.
On the EventGraph connect the OnPressed event to setting the IsButtonPressed value to true and the OnReleased event to setting the IsButtonPressed value to false.
Last thing is to alter the ChangeTextColorOnButtonUnhover funtion so it will know when to change the Text color according to the IsButtonPressed value.
After the ChangeTextColorOnButtonUnhover input place a Branch node with an input being the IsButtonPressed variable. Disconnect the True exec connection if it is connected and connect the False to Set Color and Opacity node.
That should do it! Let’s test it out.
Click the Button and drag it the mouse out of it without letting go the LMB.
Looks good, now release the LMB.
Everything works! This concludes the styling process.
Note! How is it possible that Text changed the color from black to white after releasing button in the unHovered state? It should be left in the black state because we omitted the changing color on the onUnhovered event. Well it turns out that after releasing the Button in the unHovered state, UE4 calls unHovered event once again! This way our ChangeTextColorOnButtonUnhover function is called twice but changes the color only when we know that the IsButtonPressed is false. I don't know if this feature is not a bug, so this solution may need to be altered once Epic changes this behavior.
Styling a UserWidget control requires to take care of various Widget’s states so the UserWidget works and looks consistently. A good thing is that it only needs to be done once, which helps to couple the integration problems to simple solutions in opposition to Blueprint Spaghetti when taking care of every Widget’s problem in a single UserWidget.
Designing a responsive screen based on UserWidget
If having custom UserWidget controls helps to build another UserWidget, then it’s time to address the problem of creating such a UserWidget screen. I will show you how to recreate the Main Menu from the #GameUI Essentials assets pack.
Creating a Screen Management System
The more screens to be managed the bigger the problem with coping with the logic. I will show you how to address this problem, where a single HUD takes care about managing screens being UserWidgets without them knowing anything about each others existence.