NoesisGUI

Noesis Extensions

NoesisGUI implements a wide subset of Microsoft WPF, but it also adds some convenient features on top of it to help designers create even more stunning UI for their games and applications. Some of these features include Text Stroke and Placeholders, Focus Engagement, Element 3D-Transforms and Path Trimming.

To be able to design user interfaces in Blend and include these extensions, a NuGet package is provided in the official repository with the name Noesis.GUI.Extensions. These extensions are available under the NoesisGUIExtensions namespace.

<Grid
  xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  xmlns:noesis="clr-namespace:NoesisGUIExtensions;assembly=Noesis.GUI.Extensions">
</Grid>

Text Extensions

CharacterSpacing

In NoesisGUI we incoporated the CharacterSpacing property defined by UWP text elements. It represents the uniform spacing between characters, in units of 1/1000 of an em.

<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"
  Background="White">
    <TextBlock Text="This text has extra character spacing" FontSize="24" Foreground="Black"
      noesis:Text.CharacterSpacing="200"/>
</Grid>
ExtensionsTutorialImg0.png

Stroke

In NoesisGUI text can be stroked by using the attached properties Text.Stroke and Text.StrokeThickness. The first defines the Brush to fill the stroke, and the latter specifies the width in pixels of the stroke. These properties are inherited down the UI tree.

<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"
  Background="White">
    <TextBlock Text="This text is stroked" FontSize="24" Foreground="LightBlue"
      noesis:Text.Stroke="#B000407F" noesis:Text.StrokeThickness="2.5"/>
</Grid>
ExtensionsTutorialImg1.png

Placeholder

Some controls like TextBox, PasswordBox and ComboBox can show a placeholder text as a hint of their use. Using Text.Placeholder attached property in a control template adds placeholder functionality to the control.

<ControlTemplate x:Key="Template.TextBox" TargetType="TextBox">
  <Grid Background="{TemplateBinding Background}">
    <Border x:Name="Placeholder"
      Padding="{TemplateBinding Padding}"
      Margin="2,0" Visibility="Collapsed">
      <TextBlock Text="{Binding (noesis:Text.Placeholder), RelativeSource={RelativeSource TemplatedParent}}"/>
    </Border>
    <ScrollViewer x:Name="PART_ContentHost" Focusable="False"
      Padding="{TemplateBinding Padding}"
      Foreground="{TemplateBinding Foreground}"/>
  </Grid>
  <ControlTemplate.Triggers>
    <Trigger Property="Text" Value="">
      <Setter Property="Visibility" Value="Visible" TargetName="Placeholder"/>
    </Trigger>
  </ControlTemplate.Triggers>
</ControlTemplate>
<Grid
  xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  xmlns:noesis="clr-namespace:NoesisGUIExtensions;assembly=Noesis.GUI.Extensions">
  <StackPanel HorizontalAlignment="Center" VerticalAlignment="Center">
    <TextBlock Text="Enter your login credentials:"/>
    <TextBox noesis:Text.Placeholder="Username" Width="300" Margin="0,10,0,5"/>
    <PasswordBox noesis:Text.Placeholder="Password" Width="300"/>
  </StackPanel>
</Grid>
ExtensionsTutorialImg2.png

Element Extensions

PPAA

When using Per-Primitive Antialiasing (PPAA) sometimes it is useful to disable it on a specific element or group of elements. This can be done by setting attached property Element.PPAAMode to Disabled. This way you can avoid the minor overlappings on contiguous elements produced by the extruded geometry that PPAA generates. It can also be used to improve performance on elements where PPAA is not necessary, like aligned rectangles. This property is inherited down the UI tree.

<Grid
  xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  xmlns:noesis="clr-namespace:NoesisGUIExtensions;assembly=Noesis.GUI.Extensions">
  <Grid noesis:Element.PPAAMode="Disabled">
    <Grid.ColumnDefinitions>
      <ColumnDefinition Width="55"/>
      <ColumnDefinition Width="*"/>
      <ColumnDefinition Width="8"/>
    </Grid.ColumnDefinitions>
    <Grid.RowDefinitions>
      <RowDefinition Height="25"/>
      <RowDefinition Height="*"/>
      <RowDefinition Height="32"/>
    </Grid.RowDefinitions>
    <Rectangle Grid.Row="0" Grid.Column="0" Fill="{StaticResource TopLeftImage}"/>
    <Rectangle Grid.Row="0" Grid.Column="1" Fill="{StaticResource TopImage}"/>
    <Rectangle Grid.Row="0" Grid.Column="2" Fill="{StaticResource TopRightImage}"/>
    <Rectangle Grid.Row="1" Grid.Column="0" Fill="{StaticResource CenterLeftImage}"/>
    <Rectangle Grid.Row="1" Grid.Column="1" Fill="{StaticResource CenterImage}"/>
    <Rectangle Grid.Row="1" Grid.Column="2" Fill="{StaticResource CenterRightImage}"/>
    <Rectangle Grid.Row="2" Grid.Column="0" Fill="{StaticResource BottomLeftImage}"/>
    <Rectangle Grid.Row="2" Grid.Column="1" Fill="{StaticResource BottomImage}"/>
    <Rectangle Grid.Row="2" Grid.Column="2" Fill="{StaticResource BottomRightImage}"/>
  </Grid>
</Grid>
ExtensionsTutorialImg3.png

In other situations is desirable to modify the extrusion parameters of PPAA to get a better antialiasing. This can be done by setting Element.PPAAIn and Element.PPAAOut properties on the selected elements. These properties are inherited down the UI tree.

<Grid
  xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  xmlns:noesis="clr-namespace:NoesisGUIExtensions;assembly=Noesis.GUI.Extensions">
  <Rectangle Fill="Black" Width="100" Height="100"
    noesis:Element.PPAAIn="1" noesis:Element.PPAAOut="1">
    <Rectangle.RenderTransform>
      <RotateTransform Angle="60"/>
    </Rectangle.RenderTransform>
  </Rectangle>
</Grid>

Transform3D

NoesisGUI provides 3-D transformations to UI elements trough the attached property Element.Transform3D. Two types of 3-D transform objects are available: CompositeTransform3D and MatrixTransform3D.

<Grid
  xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  xmlns:noesis="clr-namespace:NoesisGUIExtensions;assembly=Noesis.GUI.Extensions">
  <StackPanel Orientation="Horizontal">
    <Rectangle Fill="Black" Width="100" Height="100">
      <noesis:Element.Transform3D>
        <noesis:CompositeTransform3D RotationY="30" CenterX="50"/>
      </noesis:Element.Transform3D>
    </Rectangle>
    <Rectangle Fill="Black" Width="100" Height="100">
      <noesis:Element.Transform3D>
        <noesis:MatrixTransform3D Matrix="{Binding Transform}"/>
      </noesis:Element.Transform3D>
    </Rectangle>
  </StackPanel>
</Grid>
ExtensionsTutorialImg4.png

Focus Engagement

To ensure that applications are usable and accessible through Gamepads it is necessary to handle focus on some controls in a particular way, otherwise focus could get 'trapped' within a control. Focus engagement tries to resolve this situation.

The attached property Element.IsFocusEngagementEnabled can be set on a control to enable focus engagement. By default focus engagement is enabled on the following controls: Slider, TextBox, PasswordBox, and ComboBox. This means that when one of those controls receives focus, user has to press 'Accept' button to activate it and interact with it, and press 'Cancel' button to exit from focus engagement. Attached property Element.IsFocusEngaged indicates if the control has focus engaged or not, and can be used to show a visual cue in its template to help users identify that state.

<ControlTemplate x:Key="TextBoxTemplate" TargetType="TextBox">
  <Grid>
    <Border Background="{TemplateBinding Background}">
      <ScrollViewer x:Name="PART_ContentHost"/>
    <Border>
    <Border x:Name="FocusBd" BorderBrush="{StaticResource FocusedBrush}"
      BorderThickness="2" Visibility="Collapsed"/>
  </Grid>
  <ControlTemplate.Triggers>
    <Trigger Property="noesis:Element.IsFocusEngaged" Value="True">
      <Setter Property="Visibility" Value="Visible" TargetName="FocusBd"/>
    </Trigger>
  </ControlTemplate.Triggers>
</ControlTemplate>

Gesture Events

The following Gesture events are taken from UWP:

<Grid
  xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  xmlns:noesis="clr-namespace:NoesisGUIExtensions;assembly=Noesis.GUI.Extensions"
  noesis:IsRightTapEnabled="True"
  noesis:RightTapped="RootGrid_RightTapped">
</Grid>

Path Extensions

Trimming

Creating Vector Animations usually requires to render only part of a path. This can be achieved sometimes with clipping, but not always. Path trimming is a feature that allows to specify which section of a path will be displayed. NoesisGUI defines attached properties Path.TrimStart, Path.TrimEnd and Path.TrimOffset that can be set on any Shape element for that purpose.

<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"
  Background="White">
  <Grid.Resources>
    <Storyboard x:Key="anim" RepeatBehavior="Forever">
      <DoubleAnimation Storyboard.TargetName="circle"
        Storyboard.TargetProperty="(noesis:Path.TrimOffset)"
        To="1"/>
      <DoubleAnimation Storyboard.TargetName="circle"
        Storyboard.TargetProperty="(noesis:Path.TrimStart)"
        To="0.25" Duration="0:0:0.5" AutoReverse="True"/>
    </Storyboard>
  </Grid.Resources>
  <Grid.Triggers>
    <EventTrigger RoutedEvent="FrameworkElement.Loaded">
      <BeginStoryboard Storyboard="{StaticResource anim}"/>
    </EventTrigger>
  </Grid.Triggers>
  <Ellipse x:Name="circle" Width="200" Height="200"
    Stroke="Black" StrokeThickness="20" StrokeStartLineCap="Round"
    noesis:Path.TrimStart="0" noesis:Path.TrimEnd="0.5"/>
</Grid>

Interactivity Extensions

Styles

Behaviors architecture allows UI designers to add functionality to the interface using only XAML. NoesisGUI implements almost all behaviors and triggers provided by Blend, but they cannot be specified within Styles because default Interaction Behaviors and Triggers are read-only properties in WPF. To address that limitation we extended this architecture with a couple of attached properties, StyleInteraction Behaviors and Triggers, that can be set in a style Setter.

<Grid
  xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
  xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
  xmlns:ei="http://schemas.microsoft.com/expression/2010/interactions"
  xmlns:noesis="clr-namespace:NoesisGUIExtensions;assembly=Noesis.GUI.Extensions">
    <Grid.Resources>
      <Style TargetType="Button" BasedOn="{StaticResource {x:Type Button}}">
        <Setter Property="noesis:StyleInteraction.Triggers">
          <Setter.Value>
            <noesis:StyleTriggerCollection>
              <i:EventTrigger EventName="Click">
                <ei:PlaySoundAction Source="buttonClick.wav"/>
              </i:EventTrigger>
            </noesis:StyleTriggerCollection>
          </Setter.Value>
        </Setter>
        <Setter Property="noesis:StyleInteraction.Behaviors">
          <Setter.Value>
            <noesis:StyleBehaviorCollection>
              <ei:MouseDragElementBehavior/>
            </noesis:StyleBehaviorCollection>
          </Setter.Value>
        </Setter>
      </Style>
    </Grid.Resources>
    <StackPanel HorizontalAlignment="Center" VerticalAlignment="Center">
      <Button Content="Start"/>
      <Button Content="Options"/>
      <Button Content="Exit"/>
    </StackPanel>
</Grid>

Triggers

To allow users to perform actions in response to gamepad input NoesisGUI provides GamepadTrigger .

<UserControl
  xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
  xmlns:ei="http://schemas.microsoft.com/expression/2010/interactions"
  xmlns:noesis="clr-namespace:NoesisGUIExtensions;assembly=Noesis.GUI.Extensions">
  <i:Interaction.Triggers>
    <noesis:GamepadTrigger FiredOn="ButtonDown" Button="Cancel">
      <i:InvokeCommandAction Command="{Binding ExitCommand}" />
    </noesis:GamepadTrigger>
  <i:Interaction.Triggers>
</UserControl>

Behaviors

When an application requires to sort a collection of items it can use NoesisGUI custom CollectionSortBehavior. If it needs to filter a collection of items then it can use the CollectionFilterBehavior. Those behaviors can be combined by chaining the output collection of one to the ItemsSource input collection of the other behavior.

<StackPanel
  xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
  xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
  xmlns:noesis="clr-namespace:NoesisGUIExtensions;assembly=Noesis.GUI.Extensions">
  <i:Interaction.Behaviors>
    <noesis:CollectionFilterBehavior x:Name="FilterBehavior"
      ItemsSource="{Binding Books}"
      Predicate="{Binding BookFilter}" />
    <noesis:CollectionSortBehavior x:Name="SortBehavior"
      ItemsSource="{Binding FilteredItems, ElementName=FilterBehavior}"
      Comparer="{Binding BookComparer}" />
  </i:Interaction.Behaviors>
  <TextBox Text="{Binding SearchText}"/>
  <ListBox ItemsSource="{Binding SortedItems, ElementName=SortBehavior}" />
</StackPanel>

Trigger Actions

When a panel gets loaded, sometimes it is necessary to set the keyboard focus on a specific control. NoesisGUI includes the SetFocusAction to set the focus on the targeted element in response to any interactivity trigger.

<Grid
  xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
  xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
  xmlns:noesis="clr-namespace:NoesisGUIExtensions;assembly=Noesis.GUI.Extensions">
  <i:Interaction.Triggers>
    <i:EventTrigger EventName="Loaded">
      <noesis:SetFocusAction TargetName="UserName"/>
    </i:EventTrigger>
  </i:Interaction.Triggers>
  <TextBox x:Name="UserName" Text="{Binding UserName}"/>
</Grid>

There are situations that need selecting an item in a list when it gets hovered or any other event happens. This can be done using the SelectAction, which sets the Selector.IsSelected property to true when the action gets execeuted.

<Grid
  xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
  xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
  xmlns:noesis="clr-namespace:NoesisGUIExtensions;assembly=Noesis.GUI.Extensions">
  <Grid.Resources>
    <Style TargetType="ListBoxItem" BasedOn="{StaticResource {x:Type ListBoxItem}}">
      <Setter Property="noesis:StyleInteraction.Triggers">
        <Setter.Value>
          <noesis:StyleTriggerCollection>
            <i:EventTrigger EventName="MouseEnter">
              <noesis:SelectAction />
            </i:EventTrigger>
          </noesis:StyleTriggerCollection>
        </Setter.Value>
      </Setter>
    </Style>
  </Grid.Resources>
  <ListBox ItemsSource="{Binding Books}"/>
</Grid>

When a TextBox or PasswordBox gets focus, the default behavior is to just position the caret where mouse was clicked, but sometimes it is preferable to select the whole text. To avoid creating a custom control for just that, NoesisGUI offers the SelectAllAction.

<Grid
  xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
  xmlns:noesis="clr-namespace:NoesisGUIExtensions;assembly=Noesis.GUI.Extensions">
  <TextBox Text="{Binding UserName}">
    <i:Interaction.Triggers>
      <i:EventTrigger EventName="GotKeyboardFocus">
        <noesis:SelectAllAction />
      </i:EventTrigger>
    </i:Interaction.Triggers>
  </TextBox>
</Grid>

Unity Extensions

Xaml Dependencies

In Unity only the assets that are referenced from objects included in the scene are added to the game executable and are then available to load. NoesisXaml asset automatically detects which resources are being used (like resource dictionaries, fonts or images) but there are situations where the application requires other resources to be loaded at runtime (from code for example). For that purpose, Xaml.Dependencies attached property is exposed to explicitly add dependencies.

<UserControl
  xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  xmlns:noesis="clr-namespace:NoesisGUIExtensions">

  <noesis:Xaml.Dependencies>
    <noesis:Dependency Source="Language-en.xaml"/>
    <noesis:Dependency Source="Language-fr.xaml"/>
    <noesis:Dependency Source="Language-jp.xaml"/>
  </noesis:Xaml.Dependencies>

</UserControl>
© 2017 Noesis Technologies