NoesisGUI
 

🎓 First steps with NoesisGUI and Unreal

unreal.png

This document will guide you through the process of setting up the NoesisGUI Unreal plugin. NoesisGUI entirely replaces Unreal's UI, offering a much more convenient and efficient approach. You will learn how to start editing the samples included in NoesisGUI plugin and how to create new games from scratch. NoesisGUI is deeply integrated with Unreal; XAMLs appear as native resources that directly use assets imported by Unreal like Textures, Fonts, Sounds, and Videos. It is strongly recommended that you read the rest of tutorials to familiarize yourself with the basic concepts of XAML and Noesis architecture. Some knowledge of Unreal Engine is also assumed, but this document attempts to be as thorough as possible.

With the NoesisGUI plugin for Unreal Engine you have all the power of the native NoesisGUI SDK at your disposal. There are a few particularities about the specific use in Unreal that will be explained later, but the bottom line is that everything that can be done with the native SDK will work in Unreal Engine.

We also provide an easy way to allow users to leverage the power of NoesisGUI using Unreal Engine's Blueprints. A mechanism is provided that allows Bindings to Blueprint properties, without having to write a single line of C++ code.

With this approach NoesisGUI will be more accessible for everyone, but at the same time will allow more advanced users to use the native SDK directly, with the complete set of features available to them as in any other platform.

spacer.png

✨ What's new in 4.0

  • Noesis Studio Integration: We deprecated Blend in favor of our new authoring tool, Noesis Studio, which is now fully integrated as a dockable window directly inside Unreal Editor.
  • Ready-to-Inspect Samples: Every sample now comes with a Noesis Studio project ready to be inspected and modified right inside Unreal Editor.
  • Support for Unreal Engine 5.8: Full compatibility and seamless integration with the latest UE 5.8 releases.
  • Improved TAA Support: Enhancements to Temporal Anti-Aliasing (TAA) for World Space UI, ensuring crisper, cleaner 3D UI rendering in motion.
  • All new features included in NoesisGUI 4.0 runtime are also available.

🚀 Quick start

  1. Create an Unreal project (Blueprint or C++).
  2. Install NoesisGUI plugin.
  3. Enable the plugin in your project.
  4. Create a Noesis Studio project to edit your XAML content.
  5. Import your UI assets into Unreal's project.
  6. Set the Application resources to match GlobalResources.xaml specified in Noesis Studio.
  7. Create a View to render a XAML asset.
  8. Click Play to see the UI in action.

📦 Installation

You can download the latest version of the plugin directly from our website. The zip file contains an Unreal project with some samples and the plugin ready to be used.

UnrealTutorialImg1.png

NoesisGUI works with versions of Unreal Engine installed through the Epic Games Launcher as well as those built by yourself from the source code in GitHub. And it can be installed as either an Engine Plugin or a Game Plugin.

Game Plugin

If you want to use it as a Game plugin, so other game projects don't use it, please extract the contents of Plugins/NoesisGUI folder into <ProjectRoot>/Plugins/NoesisGUI, being <ProjectRoot> the directory where you have your .uproject file. This is the recommended approach.

Engine Plugin

If you want to use it as an Engine plugin please extract the contents of Plugins/NoesisGUI folder from the downloaded file into <UERoot>/Engine/Plugins/NoesisGUI. <UERoot> is the directory where you installed the engine from the Epic Games Launcher, or the directory where you cloned the UnrealEngine GitHub repository.

💡 Examples

To help you get started, the downloaded zip file includes an Unreal project equipped with several working examples. These examples are structured as Unreal plugins and can be found within the Plugins/Samples directory of the downloaded zip file.

Each sample provides its own dedicated map level, allowing you to easily open it, hit Play, and experience the user interface firsthand. Furthermore, every example comes with a complete Noesis Studio project. This allows you to launch Noesis Studio directly from the Unreal Editor, where you can inspect the XAML architecture, explore the visual layout, and learn how the interfaces are constructed.

A lot more examples can be found at our GitHub repository.

UnrealTutorialImg2.png

⚙️ Configuring NoesisGUI

At this point the plugin should be ready to use, so we can proceed to enable it and configure some settings for your project.

Run the Unreal Engine editor. You may get a notification on the bottom right corner alerting you that new plugins have been installed. If you don't, open the Plugins dialog from the Edit menu, and select UI from the category list on the left. You can enable the plugin from the right hand panel.

UnrealTutorialImg3.png

You can also do this manually by modifying your Project's .uproject file to add the plugin dependency, like this:

"Plugins": [
   {
      "Name": "NoesisGUI",
      "Enabled": true
   }
]

Noesis Settings

With the plugin enabled, you can configure some NoesisGUI global settings for your project. You can find them by opening the NoesisGUI top menu and selecting Settings. These settings have sensible default values, so if you're unsure about them you can just leave them as they are. Modifying some of these settings will require you to restart the editor for the changes to take effect.

UnrealTutorialImg4.png UnrealTutorialImg5.png

🛠️ Project Setup

The process to set up your project to work with NoesisGUI depends on whether it is a Blueprint-only project or a C++ project.

  • For a Blueprint-only project, enabling the plugin as described above is all you need to do.

  • For a C++ project, there are two additional steps. First, you must add the module dependencies to your project. To do that, simply add the following line to you module's ModuleRules derived class (in your module's .Build.cs file):

    PrivateDependencyModuleNames.AddRange(new string[] { "Noesis", "NoesisRuntime" });
    

    Next, you have to #include the necessary headers for your project. To simplify this we've created a single header file you can include, preferably in your game project's PCH file. Just add the following line:

    #include "NoesisRuntime.h"
    

🎨 Noesis Studio

Noesis Studio is our dedicated authoring environment for designing XAML-based interfaces. It is fully integrated as a dockable window inside Unreal Editor. This seamless workflow allows quick iterations while designing user interfaces, as changes performed in Noesis Studio appear immediately in the Unreal Viewport, even in Play mode.

Note

For getting started with Noesis Studio we recommend reading our Noesis Studio Documentation

To start using Noesis Studio in your Unreal project follow these steps:

  1. Open the NoesisGUI entry from the top menu bar in Unreal Editor, and select New Project.... We recommend creating the Studio project in a dedicated folder outside of your main Content directory, for example, <ProjectRoot>/Assets/UI/. This keeps your source UI design files neatly separated from the assets that Unreal imports automatically.
  2. Create your XAML files inside the Noesis Studio project using the same folder structure you intend to use within your Unreal Content folder. This is done to ensure that relative and absolute paths match perfectly when Unreal tries to load the corresponding assets.
  3. Noesis Studio automatically references the included Noesis Theme assets. These assets provide polished, default styles for all standard UI controls right out of the box, serving as an excellent foundation for creating your own custom game styles.
  4. Now you are ready to set up your UI layout, animations, interactions and states entirely through Noesis Studio's visual tools.

Note

Window root elements are not supported by NoesisGUI in Unreal, as the windowing system is provided by Unreal engine itself. Instead, we recommend using a Page, UserControl, or any Panel class as the root element.

With Noesis Studio integrated, your assets and project structure can be naturally synchronized with Unreal, as explained below.

📂 Assets

At this point you're ready to start using NoesisGUI in your project. The first step is importing your assets. These will consist of XAML files, fonts, images, sounds... After import, your XAML files will appear in Unreal Engine's Content Browser as NoesisXaml assets, while your images will appear as Texture2Ds and fonts as FontFaces.

UnrealTutorialImg6.png

When importing your XAML files, these may contain references to other XAML files, as well as images and fonts, as stated above. These references may be in the form of relative or absolute URIs. When working with absolute URIs in Unreal Engine, these are considered as relative to the Content folder of your game project. Please refer to the document URIs in NoesisGUI for more information.

If you keep your XAML sources separate from your game's assets, you can rely on Unreal Engine's Auto Reimport feature to map source asset directories to folders in the Content browser. This way changes made to source files will be detected and assets automatically reimported into the project, even in Play mode, improving your workflow.

UnrealTutorialImg7.png

Note

Our samples use this approach to keep Studio project and source files separated from Unreal assets in Content.

Plugins

You can also create plugins containing XAMLs, textures or any other assets. To reference those assets you have to specify the plugin Content root in the Uri as if it were the Assembly. For example, if you define a XAML/Styles.xaml dictionary in a plugin called MenuResources, you can reference it from other XAMLs like this:

<ResourceDictionary Source="/MenuResources;component/XAML/Styles.xaml"/>

Blueprint classes and enums defined inside the plugin will be exposed to NoesisGUI using the plugin Content root and the path to the Unreal object as the namespace in the type name. For example, if you define an enum State under the folder Data in a plugin called MenuResources, the type will be exposed to NoesisGUI as MenuResources.Data.State and you can reference it from other XAML files as follows:

<Grid
   xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
   xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
   xmlns:res="clr-namespace:MenuResources.Data;assembly=MenuResources">
   <Border Tag="{x:Static res:State.Active}"/>
</Grid>

User Controls

Before explaining how to create your own user controls in Unreal it is recommended to read first the UserControl tutorial documentation.

As you should know now, a UserControl is composed of a XAML that defines the UI contents of the control, and the class which defines the properties, events and logic of the control. When your user control is created it should load the associated XAML by calling LoadComponent with the path to the XAML asset inside the Content folder of your project or plugin. If the path Uri does not include an assembly, it means the XAML asset should be found in the project Content folder.

Additionally, you must specify a dependency to the XAML asset within the class reflection block. This is done using AssetDependency metadata inside an #if WITH_EDITORONLY_DATA guard. This ensures that Unreal Editor knows about the associated XAML asset when your UserControl is referenced by another XAML, which is vital for correct asset tracking and packaging.

class NumericUpDown : public Noesis::UserControl
{
public:
   NumericUpDown()
   {
      Noesis::GUI::LoadComponent(this, "UserControls/NumericUpDown.xaml");
   }

   NS_IMPLEMENT_INLINE_REFLECTION(NumericUpDown, "UserControls.NumericUpDown")
   {
     #if WITH_EDITORONLY_DATA
      NsMeta<AssetDependency>("UserControls/NumericUpDown.xaml");
     #endif
   }
};

Next step is to register this class into the component factory, so it could be created when xaml parser finds it in the xaml. This should be done during the module startup.

class UserControlModule : public FDefaultGameModuleImpl
{
   virtual void StartupModule() override
   {
      Noesis::RegisterComponent<UserControls::NumericUpDown>();
   }

   virtual void ShutdownModule() override
   {
      Noesis::UnregisterComponent<UserControls::NumericUpDown>();
   }
};

IMPLEMENT_MODULE(UserControlModule, UserControlModule);

Then you can reference this user control in any other XAML using a prefix that maps the namespace specified in the reflection:

<Grid
   xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
   xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
   xmlns:local="clr-namespace:UserControls">
   <local:NumericUpDown />
</Grid>

Blueprints

Asset paths are important when referencing Blueprint types in your XAML. The following XAML references the type TicTacToe.State, which can be an enumeration defined in Blueprint instead of native code.

<Grid
   xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
   xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
   xmlns:local="clr-namespace:TicTacToe">
   <Grid.Style>
      <Style TargetType="Grid">
         <Setter Property="Background" Value="Blue"/>
         <Style.Triggers>
            <DataTrigger Binding="{Binding State}" Value="{x:Static local:State.Player1}">
               <Setter Property="Background" Value="Red"/>
            </DataTrigger>
         </Style.Triggers>
      </Style>
   </Grid.Style>
</Grid>

To register Blueprint types defined in project's Content folder we use the path to the asset as its namespace, so State Blueprint class should be created as /Game/TicTacToe/State in Unreal in order to be found by NoesisGUI when previous XAML gets parsed.

As mentioned before, Blueprint types defined in a plugin will also include the plugin's Content root in addition of the path as part of the namespace.

Note

Unreal native types, registered in Unreal's reflection as /Script/Module.Type, are exposed to Noesis as Module.Type. You have to take this into account when referencing those types in XAML.

Materials

NoesisGUI supports the use of custom shaders in two scenarios, Effects which apply a post-processing shader to any element of the UI tree, and Brushes which define how elements can be filled or stroked. In Unreal you can directly use Materials for this purpose. As mentioned before for Blueprint types, the path to the Material asset will be used to expose the type to Noesis and how you should reference it in the XAML file.

In case you want to create an Effect you have to define the Material Domain as Post Process. Material parameters will automatically be exposed as properties that can be set or even animated from the XAML. The types of parameters supported and their correspondence to NoesisGUI types is the following:

Unreal Parameter Type NoesisGUI Type
Scalar float
Vector Noesis::Color / Noesis::Point4D
Texture Noesis::BitmapSource

Note

For each Vector parameter, 2 properties are exposed to XAML: one as Color, with sRGB values; and another as a Point4D, with linear values (named with _Linear suffix).

UnrealTutorialImg21.png
<Grid
   xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
   xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
   xmlns:local="clr-namespace:CustomEffects">
   <Grid>
      <Grid.Effect>
         <local:ChromaticAberrationEffect Amount="10">
      <Grid.Effect>
      <Image Source="Background.jpg"/>
      <TextBlock Text="Effects Sample" HorizontalAlignment="Center" VerticalAlignment="Center"/>
   </Grid>
</Grid>

In order to use a Material as a Brush you have to define the Domain as User Interface. Same as before, the material parameters can be modified in the XAML file.

UnrealTutorialImg22.png
<Grid
   xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
   xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
   xmlns:noesis="clr-namespace:NoesisGUIExtensions;assembly=Noesis.GUI.Extensions"
   xmlns:local="clr-namespace:CustomBrushes">
   <Rectangle Width="400" Height="200">
      <Rectangle.Fill>
         <ImageBrush ImageSource="Background.jpg">
            <noesis:Brush.Shader>
               <local:NoiseBrush Color="Gold"/>
            </noesis:Brush.Shader>
         </ImageBrush>
      </Rectangle.Fill>
   </Rectangle>
</Grid>

Textures

Images used inside XAMLs generate a dependency to the corresponding Unreal texture asset. The texture imported by Unreal is directly consumed by NoesisGUI. This means that all settings available under Texture properties are respected.

If your images include alpha, make sure:

  • You have Premultiply Alpha checked in NoesisGUI editor settings
UnrealTutorialImg35.png
  • You have marked the Texture with Set Premultiply Alpha in the asset context menu
UnrealTutorialImg36.png

Note

All textures referenced by a XAML are automatically marked with 'Set Premultiply Alpha' when the XAML is imported

Sprites

NoesisGUI supports Sprite images exposed in Blueprint view models, which can be consumed by any ImageSource property in XAML using data-binding.

<Image Source="{Binding Item.Icon}"/>
UnrealTutorialImg26.png

Rive

Rive assets (.riv) are supported by NoesisGUI since 3.2. These assets are consumed by our RiveControl which offers state machine input values and triggers. There is an example included in the package fully created with Rive.

UnrealTutorialImg33.png

🔲 Views

Now that you have your assets imported into the game, you have to create a View for it. The easiest way is by right-clicking on any xaml asset and select Add to Viewport. This will create and configure a View automatically, and add it to current Level map so you can rapidly see the UI rendered in the viewport when playing.

UnrealTutorialImg8.png

A NoesisView is also an Unreal Engine UMG Widget. This means that you can use it wherever a native UMG Widget is used, so if you're familiar with Unreal Engine's UMG system it will be very simple to get up and running with NoesisGUI. Please, refer to the document Creating Widgets for information about how to manually add a NoesisView to your viewport and how to handle input. Because a NoesisView is also an UMG Widget it means you can also create 3D UI elements by using a Widget Component. Please, refer to the document Widget Components for more information.

Double-clicking the View asset will open the familiar Blueprint Class editor. Press the Class Settings button on the top toolbar to edit the View properties.

UnrealTutorialImg9.png

The most important of all is the XAML property. Here you'll reference the NoesisXaml for which you want to create the View. Enable PPAA allows you to enable per-primitive antialiasing in case you're not using multisampling on your main render target. Tessellation Quality lets you select the degree of subdivision for your path geometry. Remember to compile and save your NoesisView before using it.

UnrealTutorialImg10.png

The following Level Blueprint will render the View in the screen.

UnrealTutorialImg11.png

🌍 World Space UI

The user interface can also be rendered directly in 3D, without using render to texture. This is the recommend way if you want the UI to be occluded by objects in the 3D scene, or if you want the best quality in Virtual Reality.

You can have several UIs floating in the space. Each one attached to an Actor by using the new NoesisWorldUI component.

UnrealTutorialImg31.png

The following properties are exposed in the component:

  • Xaml: The UI placed in the Actor position.
  • Scale: Allows scaling UI pixels to scene units.
  • Offset: Adjust UI position relative to the Actor.
  • Center: If enabled centers the UI in the Actor position.

Note

There is an example in the plugin project, World Space UI, showing how to setup a basic scene with 3D UI.

UnrealTutorialImg32.png

With Noesis 4.0, enhancements to Temporal Anti-Aliasing (TAA) ensure World Space UI renders cleanly and remains crisp even when moving. If you are using Unreal Engine 5.7 or greater, you can enable velocity support to take full advantage of the latest TAA improvements by adding the following to your project's DefaultEngine.ini file:

[/Script/Engine.RendererSettings]
r.Velocity.TemporalResponsiveness.Supported=1

🎮 Gamepad

Our plugin provides input action assets for the gamepad and a default mapping context ready to be used in your project.

UnrealTutorialImg29.png

New mapping contexts can be created and assigned to the player controller to customize interactions with the gamepad.

UnrealTutorialImg30.png

Note

You must Enable Actions in the View asset to allow controlling the UI using the gamepad.

🖱️ Input Actions

Enhanced Input Actions

Enhanced Input Actions allow Unreal users to use more advanced input features, like complex input handling or runtime control remapping.

UnrealTutorialImg28.png

NoesisGUI provides an EnhancedInputActionTrigger to use these actions directly in XAML. The Action property expects an Uri pointing to an input action asset in the project:

<Grid
  xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
  xmlns:b="http://schemas.microsoft.com/xaml/behaviors"
  xmlns:noesis="clr-namespace:NoesisGUIExtensions">
    <b:Interaction.Triggers>
      <noesis:EnhancedInputActionTrigger Action="/InputActions/Fire" TriggerEvent="Triggered">
        <b:ChangePropertyAction TargetName="rect" PropertyName="Fill" Value="Red"/>
      </noesis:EnhancedInputActionTrigger>
    </b:Interaction.Triggers>
    <Rectangle x:Name="rect" Fill="Transparent"/>
 </Grid>

Legacy Input Actions

Unreal's Input Actions can be used directly in XAML as interactivity triggers.

UnrealTutorialImg27.png

NoesisGUI defined the InputActionTrigger extension for that purpose. It will allow the UI designer to execute any interactivity action in response to an Unreal's Input Action: invoke a command, launch a storyboard, play a sound...

<Grid
  xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
  xmlns:b="http://schemas.microsoft.com/xaml/behaviors"
  xmlns:noesis="clr-namespace:NoesisGUIExtensions">
    <b:Interaction.Triggers>
      <noesis:InputActionTrigger Action="Fire" Type="Pressed" Consume="False">
        <b:ChangePropertyAction TargetName="rect" PropertyName="Fill" Value="Red"/>
      </noesis:InputActionTrigger>
    </b:Interaction.Triggers>
    <Rectangle x:Name="rect" Fill="Transparent"/>
</Grid>

🔗 Property Binding

One of the most powerful features of NoesisGUI is the support for a Model-View-ViewModel pattern through Data Binding. This is made even more powerful in Unreal Engine by combining it with the graphical scripting capabilities provided by Blueprints.

When you create a NoesisView for a NoesisXaml and you create a Widget from it, the instantiated object itself is set as the Data Context. You can also override this behaviour by calling the function Set Data Context on the NoesisView itself and specifying a different Unreal Engine Object.

Whether you decide to use the NoesisView or any other Object as the Data Context, you can define properties that can be bound to your XAML, as described in the aforementioned document. You can define a property in two ways:

  • As a variable. The name of the property for binding purposes will be the name of the variable. In C++, properties should be defined with the BlueprintReadWrite/BlueprintReadOnly attributes to be visible by the binding system:

    UPROPERTY(BlueprintReadWrite)
    int32 NumBots;
    
UnrealTutorialImg12.png
  • As a Getter and Setter function pair. The Getter function must have no input parameters and return a single value. You can optionally include a Setter function, which must take exactly one input parameter (matching the Getter's return type) and return nothing. When binding in XAML, the property name will simply be the function's name without the "Get" or "Set" prefix. In C++, ensure both functions are marked with the BlueprintCallable attribute so the binding system can see them:

    UFUNCTION(BlueprintCallable)
    void SetInfiniteAmmo(bool value);
    
    UFUNCTION(BlueprintCallable)
    bool GetInfiniteAmmo() const;
    
UnrealTutorialImg13.png

NOTE

Unreal uses FName for type and propery names. While in the editor FName is case-sensitive, in packaged builds this behavior changes to case-insensitive (WITH_CASE_PRESERVING_NAME defined to WITH_EDITORONLY_DATA). Bindings may stop working because of this. We recommend always using the Unreal naming convention (UpperCamelCase) when you expose type and property names to Noesis.

The following table outlines how standard Unreal Engine variable types map to native NoesisGUI SDK types for data binding. To avoid redundancy, Noesis leverages existing native Unreal types wherever possible rather than creating custom ones.

Unreal NoesisGUI Unreal NoesisGUI
Boolean bool   NoesisThickness Noesis::Thickness
Integer int32_t   NoesisCornerRadius Noesis::CornerRadius
Float float   Timespan Noesis::TimeSpan
String Noesis::String   NoesisDuration Noesis::Duration
Text Noesis::String   NoesisKeyTime Noesis::KeyTime
Color Noesis::Color   Texture2D Noesis::ImageSource
LinearColor Noesis::Color   TextureRenderTarget2D Noesis::ImageSource
Vector2D Noesis::Point   PaperSprite Noesis::ImageSource
Transform Noesis::Transform3   ETextFlowDirection Noesis::FlowDirection
Matrix Noesis::Matrix4   NoesisRive Noesis::Uri
Box2D Noesis::Rect   MediaSource Noesis::Uri
NoesisSize Noesis::Size      

NOTE

Since UE5 float Blueprint variables are represented by double precision numbers (see https://github.com/EpicGames/UnrealEngine/commit/a91395c56cdb5adb2325663ad436cefe130398d2).

So converters code must check for double type when binding to Blueprint float variables:

if (Noesis::Boxing::Unbox<double>(value))
{
  float f = (float)Noesis::Boxing::Unbox<double>(value);
  // ...
}

The plugin also supports custom Blueprint Enums, Structures and Classes. Blueprint Structures and Classes work similarly and they both expose their members as sub-properties. The difference is that Structures are treated as atomic objects, and the performance characteristics are different. We recommend you use Blueprint Classes for long lived objects, and Blueprint Structures for small objects with shorter lifespans that don't require a full Blueprint Class.

We also support Arrays of the aforementioned types, which are exposed as a List to the Binding system.

UPROPERTY(BlueprintReadWrite)
TArray<Color> Colors;

And Maps with string keys to the supported types, which are exposed as a Dictionary to the Binding system.

UPROPERTY(BlueprintReadWrite)
TMap<FString, Color> TeamColors;

Additionally, NoesisGUI supports binding XAML Commands directly to Unreal Blueprint functions. Behind the scenes, Noesis automatically wraps your functions to implement the ICommand interface.

To create a valid Command, you just need to follow these rules:

  • The Execute Function: This is the main action. It must have no return value (void). It can either take no parameters, or exactly one parameter of a compatible type from the table above.
  • The CanExecute Function (Optional): It indicates whether the command is currently enabled or disabled. To do this, define a second function that adds the prefix CanExecute to the original function's name. It must return a bool, and its parameters must match the Execute function exactly.

In C++, remember to mark these functions with the BlueprintCallable attribute so the binding system can detect them:

UFUNCTION(BlueprintCallable)
void JoinGame();

UFUNCTION(BlueprintCallable)
bool CanExecuteJoinGame();
UnrealTutorialImg14.png

Property change notifications

Performance is a key concern of NoesisGUI. For this reason, instead of polling all the data sources for all bound properties in every update, it uses a reactive model in which the user notifies NoesisGUI that a property has changed and the system updates the minimum possible set of its internal structures affected by that change.

In the NoesisGUI Native SDK this is achieved by having your classes implement the Noesis::INotifyPropertyChanged or Noesis::INotifyCollectionChanged interfaces. The typical implementation exposes Set functions that compare the new value with the old and notify any potential listeners if they are different.

Notification in Blueprints

To simplify this in Unreal Engine, we've provided custom nodes that you can use in your Blueprint code that replace the standard Set Property and array operations with custom versions that, additionally notify listeners if necessary. Here's a table with the native Unreal Engine nodes and the corresponding NoesisGUI ones:

Property change notifications

Unreal Engine Node NoesisGUI Node
Set Set w/ NotifyChanged

Array change notifications

Unreal Engine Node NoesisGUI Node
Add (Array) Add w/ NotifyArrayChanged
Add Unique (Array) Add Unique w/ NotifyArrayChanged
Shuffle (Array) Shuffle w/ NotifyArrayChanged
Append Array (Array) Append Array w/ NotifyArrayChanged
Insert (Array) Insert w/ NotifyArrayChanged
Set Array Elem (Array) Set Array Elem w/ NotifyArrayChanged
Remove Index (Array) Remove Index w/ NotifyArrayChanged
Remove Item (Array) Remove Item w/ NotifyArrayChanged
Clear (Array) Clear w/ NotifyArrayChanged
Resize (Array) Resize w/ NotifyArrayChanged

Map change notifications

Unreal Engine Node NoesisGUI Node
Add (Map) Add w/ NotifyMapChanged
Remove (Map) Remove w/ NotifyMapChanged
Clear (Map) Clear w/ NotifyMapChanged
UnrealTutorialImg15.png

Using this function is the most convenient way to notify NoesisGUI of changes in your data. But sometimes it is necessary to manually notify that a property has changed. This is the case, for example, when a property is implemented as a pair of Get/Set functions, that are not bound to a variable and therefore don't allow you to use these nodes. For these situations you can manually call the function NotifyChanged passing the name of the property.

UnrealTutorialImg16.png

The same happens if you are going to perform several actions that will change the contents of an array or map completely, in that case you can call NotifyArrayChanged or NotifyMapChanged at the end of the process to notify only once.

Notifications in C++

When defining your data model in C++ with UObjects, you must manually trigger notifications using specific helper functions.

Properties

  • NoesisNotifyPropertyChanged: Notifies that a standard property value has changed.
void UGameData::SetPlayerName(const FString& value)
{
    if (PlayerName != value)
    {
        PlayerName = value;
        NoesisNotifyPropertyChanged(this, "PlayerName");
    }
}

Commands

  • NoesisNotifyCanExecuteFunctionChanged: Raises the CanExecuteChanged event for a bound Command.
void UGameData::CarryItem(UItem* Item)
{
    CarriedItem = Item;
    NoesisNotifyCanExecuteFunctionChanged(this, "DropItem");
}
void UGameData::DropItem()
{
    CarriedItem = nullptr;
    NoesisNotifyCanExecuteFunctionChanged(this, "DropItem");
}
bool UGameData::CanExecuteDropItem()
{
    return CarriedItem != nullptr;
}

Array Collections

  • NoesisNotifyArrayPropertyPostAdd: Notifies that a new item was added to the end of an array.
void UGameData::AddWeapon(UWeapon* Weapon)
{
    Weapons.Add(Weapon);
    NoesisNotifyArrayPropertyPostAdd(&Weapons);
}
  • NoesisNotifyArrayPropertyPreAppend / PostAppend: Notifies that a range of items is going to be added.
void UGameData::CollectAll(TArray<UItem> Items)
{
    NoesisNotifyArrayPropertyPreAppend(&Inventory);
    Inventory.Append(Items);
    NoesisNotifyArrayPropertyPostAppend(&Inventory);
}
  • NoesisNotifyArrayPropertyPostInsert: Notifies that a new item was inserted at a specific index.
void UGameData::AddWeapon(UWeapon* Weapon, int32 Index)
{
    Weapons.Insert(Weapon, Index);
    NoesisNotifyArrayPropertyPostInsert(&Weapons);
}
  • NoesisNotifyArrayPropertyPreRemove / PostRemove: Notifies that an item is going to be removed from an index.
void UGameData::RemoveWeapon(int32 WeaponIndex)
{
    NoesisNotifyArrayPropertyPreRemove(&Weapons, WeaponIndex);
    Weapons.Remove(WeaponIndex);
    NoesisNotifyArrayPropertyPostRemove(&Weapons, WeaponIndex);
}
  • NoesisNotifyArrayPropertyPreSet / PostSet: Notifies that an item is going to be modified at a specific index.
void UGameData::WearWeapon(UWeapon* Weapon, EWeaponSlot Slot)
{
    NoesisNotifyArrayPropertyPreSet(&Weapons, (int32)Slot);
    Weapons.Set(Weapon, (int32)Slot);
    NoesisNotifyArrayPropertyPostSet(&Weapons, (int32)Slot);
}
  • NoesisNotifyArrayPropertyPostReset: Notifies that the array contents were cleared.
void UGameData::DropAll()
{
    Inventory.Reset();
    NoesisNotifyArrayPropertyPostClear(&Inventory); // Clears the array
}
  • NoesisNotifyArrayPropertyChanged: Notifies that the entire array property has been replaced or changed completely.
void UGameData::DropAll()
{
    Inventory.Reset();
    NoesisNotifyArrayPropertyChanged(this, "Inventory");
}

Map Collections

  • NoesisNotifyMapPropertyPostAdd: Notifies that a new item was added to a map.
void UGameData::WearWeapon(UWeapon* Weapon, const FString& Slot)
{
    Weapons[Slot] = Weapon;
    NoesisNotifyMapPropertyPostAdd(&Weapons, (int32)Slot);
}
  • NoesisNotifyMapPropertyPreRemove / PostRemove: Notifies that an item is going to be removed from a map.
void UGameData::RemoveWeapon(const FString& Slot)
{
    NoesisNotifyMapPropertyPreRemove(&Weapons, Slot);
    Weapons.Remove(Slot);
    NoesisNotifyMapPropertyPostRemove(&Weapons, Slot);
}
  • NoesisNotifyMapPropertyPostReset: Notifies that the map contents were cleared.
void UGameData::DropAll()
{
    Weapons.Reset();
    NoesisNotifyMapPropertyPostReset(&Weapons);
}
  • NoesisNotifyMapPropertyChanged: Notifies that the entire map property has been replaced or changed completely.
void UGameData::DropAll()
{
    Weapons.Reset();
    NoesisNotifyMapPropertyChanged(this, "Weapons");
}

📊 UMG ViewModel

While the Noesis notification nodes and C++ helper functions described above provide the most granular and powerful control over UI updates, NoesisGUI also supports Unreal's standard INotifyFieldValueChanged interface as an alternative option.

This is the mechanism used by the UMG ViewModel plugin introduced in Unreal Engine 5.1. If your project is already heavily utilizing this plugin, you can expose variables to NoesisGUI using Unreal's native field notify system without needing any extra changes.

Notifications in Blueprints

  1. Enable the Model View ViewModel plugin in your project settings.
  2. Create a Blueprint class that inherits from MVVMViewModelBase (or any class implementing the notification interface).
  3. Select the variables you want to expose to the UI.
  4. In the Details panel, enable the Field Notify option.
UnrealTutorialImg37.png

When you modify this variable using a standard Set node, the field notification is broadcasted, and NoesisGUI will automatically detect the change to update the bindings.

Notifications in C++

In C++, you can use the FieldNotify specifier on your UPROPERTIES and UFUNCTIONS. NoesisGUI will automatically subscribe to these notifications when the object is used as a DataContext.

#include "MVVMViewModelBase.h"

UCLASS()
class UMyViewModel : public UMVVMViewModelBase
{
    GENERATED_BODY()

public:
    // Standard property with notification
    UPROPERTY(BlueprintReadWrite, FieldNotify)
    int32 Score;

    // Getter function with notification
    UFUNCTION(BlueprintPure, FieldNotify)
    int32 GetHealth() const
    {
        return Health;
    }

    // Setter using the UE_MVVM macro to trigger the notification
    UFUNCTION(BlueprintCallable)
    void SetHealth(int32 NewHealth)
    {
        if (UE_MVVM_SET_PROPERTY_VALUE(Health, NewHealth))
        {
            // The macro automatically broadcasts the FieldNotify event
            // which NoesisGUI listens to.
        }
    }

private:
    int32 Health;
};

Note

When a Field Notify is triggered for an Array or Map property, NoesisGUI interprets this as a full reset of the collection, which rebuilds it entirely. For optimal performance with collections (such as adding, removing, or inserting specific items), it is strongly recommended to use the specific Noesis Array/Map Nodes or C++ helper functions instead.

⚡ Events

Unreal types can expose events in the form of delegates to Noesis so they can be used by DataEventTrigger.

  • Native classes should define dynamic multicast delegates (declared using the DECLARE_DYNAMIC_MULTICAST_DELEGATE family of macros).
DECLARE_DYNAMIC_MULTICAST_DELEGATE(FNativeDynamicMultiCastDelegate);

UCLASS(BlueprintType, Blueprintable)
class SAMPLESMODULE_API UNativeDataContext : public UObject
{
   GENERATED_BODY()

   UPROPERTY(BlueprintAssignable, BlueprintCallable)
   FNativeDynamicMultiCastDelegate HideWorld;
};
  • Blueprint classes should define Event Dispatchers.
UnrealTutorialImg34.png

🌐 Localization

NoesisGUI allows you to use Unreal native localization system based on FText and StringTables directly in XAML files. There are two approaches depending if you need static or dynamic localized texts.

Markup Extensions

When defining static texts in XAML that need to be localized you can use the following markup extensions:

  • LocTable: Equivalent to using LOCTABLE in C++ code, provides access to a localized text with the given Key in a StringTable. The table Id can be specified as an attached property in any parent container and it will be inherited down the tree, or you can set it locally in the markup extension itself. When using this markup extension we recommend to include the Source text so Noesis Studio can show it in the designer view.

    <Grid
      xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
      xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
      xmlns:noesis="clr-namespace:NoesisGUIExtensions;assembly=Noesis.GUI.Extensions">
      <StackPanel noesis:LocTable.Id="GameTableId">
        <TextBlock Text="{noesis:LocTable 'Hello World!', Key=HelloWorld}"/>
        <TextBlock Text="{noesis:LocTable 'This uses a different table', Key=SampleText, Id=OtherTableId}"/>
      </StackPanel>
    </Grid>
    
  • LocText: Equivalent to using LOCTEXT in C++ code, generates a new FText in a namespace with the given Key. The Namespace can also be specified as an attached property in any parent container and it will be inherited down the tree, or you can set it locally in the markup extension itself. The generated text will be discoverable by Unreal when gathering localized texts in the project if you include XAML assets in the search.

    <Grid
      xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
      xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
      xmlns:noesis="clr-namespace:NoesisGUIExtensions;assembly=Noesis.GUI.Extensions">
      <StackPanel noesis:LocText.Namespace="GameNamespace">
        <TextBlock Text="{noesis:LocText 'Hello World!', Key=HelloWorld}"/>
        <TextBlock Text="{noesis:LocText 'This uses a different namespace', Key=SampleText, Namespace=OtherNamespace}"/>
      </StackPanel>
    </Grid>
    

Bindings

If you need to show localized text in XAML that is dynamic or is formatted from some parameters you can expose FText properties in your DataContext and Noesis will keep track of them to automatically notify when language is changed in Unreal.

UnrealTutorialImg20.png
<Grid
  xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
  <TextBlock Text="{Binding WorldsText}"/>
</Grid>

📈 Performance stats

NoesisGUI main tasks are profiled using Unreal stats system.

The following command shows information about the time spent processing input events, updating the views, and generating the render commands. It also shows the total memory allocated through Noesis:

stat Noesis
UnrealTutorialImg17.png

Inside Unreal's GPU category you can find the time spent rendering Noesis UI:

stat GPU
UnrealTutorialImg18.png

🐛 Logging and debugging

If following the previous steps you still can't see your NoesisGUI interface, the first step would be to take a look at the Output Log window. You can select the verbosity of the output from the plugin settings, as described above. The default setting is Warning, so only warning and error messages will be output to the console.

Additionally logging messages in NoesisGUI have several levels of verbosity. Here is a table with the levels defined by NoesisGUI and how they map to Unreal Engine:

NoesisGUI Verbosity Level Unreal Engine Verbosity
Trace VeryVerbose
Debug Verbose
Info Log
Warning Warning
Error Error

You can filter the NoesisGUI log messages by selecting the LogNoesis category from the Categories drop down list.

UnrealTutorialImg19.png
 
© 2017 Noesis Technologies