Visual Studio

avatar

Creating a custom glass listbox with XAML in WFP

by on Saturday, August 8th, 2009, under Computer Programming, Tutorials

WPF XAML Glass ListBox

WPF XAML Glass ListBox

Our next adventure into the Windows Presentation Foundation (WPF) will take us through creating a glass style for a listbox with XAML.  Much of what we will do here is an extension of our first XAML tutorial about creating a glass button.  I you haven’t done that tutorial, I would recommend it as it will explain a lot of the stuff we are doing here.    Our list box requires considerably more effort to change its look because we don’t only style a single control like a button.  We have to style the list box itself, the list box items, the scroll buttons and the “thumb” between them, and build the layout template for the scrollbar.   So, without further ado, lets get started!

Add a new Resource Dictionary to your project and name it “GlassListBox.xaml”.  Now, add the following style for our ListBox inside of your ResourceDictionary tags in the GlassListBox.xaml file.

  <Style x:Key="GlassListBox" TargetType="{x:Type ListBox}">
    <Setter Property="Template">
      <Setter.Value>
        <ControlTemplate TargetType="{x:Type ListBox}">
          <Border BorderBrush="#99FFFFFF" 
                  Background="#88000000" 
                  BorderThickness="4" 
                  CornerRadius="20,20,20,20">
             <ScrollViewer Margin="0" Focusable="false">
                <StackPanel Margin="10" IsItemsHost="True">
                </StackPanel>
              </ScrollViewer>
          </Border>
        </ControlTemplate>
      </Setter.Value>
    </Setter>
  </Style>

This will be the background of our list box that contains everything. We added a ScrollViewer control to allow scrolling when the contents within the control go beyond the controls borders. A StackPanel is then placed inside the scroll viewer and this will be the container that holds any items we bind to the list (items like “Metroid”, “Zelda”, etc. will stack up in the stack panel).

Next, add the following style for the ListBoxItem control just below your ListBox’s closing Style tag (but still inside the ResourceDictionary tags).

  <Style x:Key="{x:Type ListBoxItem}" 
         TargetType="{x:Type ListBoxItem}">
    <Setter Property="Height" Value="66" />
    <Setter Property="Template">
      <Setter.Value>
        <ControlTemplate TargetType="{x:Type ListBoxItem}">
          <Button Name="ListItem" 
                  Style="{DynamicResource GlassButton}" 
                  Width="Auto" 
                  Height="Auto">
            <ContentPresenter Name="listItemContent" 
                              Grid.RowSpan="2" 
                              HorizontalAlignment="Left" 
                              Width="300" 
                              Margin="0,0,0,0" />
          </Button>
        </ControlTemplate>
      </Setter.Value>
    </Setter>
  </Style>

Our list box will contain buttons so a user could scroll through options and click on one to proceed to the next screen. We greatly simplify our code here by calling upon the style we created in the GlassButton XAML tutorial. The last thing we need to add is the ContentPresenter which will display our ListItem text, which in the picture above, is the name of a video game.

NOTE: You may need to manually adjust the ContentPresenter Width to suit your layout needs as I have not found a way to make the list items automatically expand with the control yet. If you know how to do this, please leave a comment so I can update this post and give you creds!

Next, we add in a third style for the scroll up and scroll down buttons in the scroll bar.

  <Style x:Key="ScrollBarLineButton" TargetType="{x:Type RepeatButton}">
    <Setter Property="Focusable" Value="false"/>
    <Setter Property="Template">
      <Setter.Value>
        <ControlTemplate TargetType="{x:Type RepeatButton}">
          <Border x:Name="RepeatButtonBorder" 
                    CornerRadius="14,14,14,14" 
                    BorderThickness="4,4,4,4" 
                    RenderTransformOrigin="0.5,0.5" 
                    BorderBrush="#88FFFFFF">
            <Border Background="#88000000"  
                    CornerRadius="14,14,14,14" 
                    x:Name="background">
              <Grid>
                <Grid.RowDefinitions>
                  <RowDefinition Height="0.4*"/>
                  <RowDefinition Height="0.6*"/>
                </Grid.RowDefinitions>
 
                <Path HorizontalAlignment="Center"
                      Grid.RowSpan="2"
                      VerticalAlignment="Center"
                      Stretch="UniformToFill" 
                      Margin="10,18,10,18"
                      Fill="White" 
                      Data="{Binding Path=Content,
                      RelativeSource={RelativeSource TemplatedParent}}" />
              </Grid>
            </Border>
          </Border>
          <ControlTemplate.Triggers>
            <Trigger Property="IsPressed" Value="true">
              <Setter Property="RenderTransform" 
                      TargetName="RepeatButtonBorder">
                <Setter.Value>
                  <TransformGroup>
                    <ScaleTransform ScaleX="0.9" ScaleY="0.9"/>
                  </TransformGroup>
                </Setter.Value>
              </Setter>
            </Trigger>
          </ControlTemplate.Triggers>
        </ControlTemplate>
      </Setter.Value>
    </Setter>
  </Style>

Most of this should look familiar if you have completed the GlassButton tutorial with the exception of the type of control used and how we display the controls contents. For the arrow buttons on the scroll bar, we are using a RepeatButton control. The actual contents of the button (the up arrow and down arrow) are set by using the “Path” tag (a control that lets us draw with coordinates, explained in detail later). The data attribute allows us to bind content in the ScrollBar ControlTemplate later. By doing this, we are able to use this same style for both buttons without hard-coding the contents.

Our next style is very simple since this style is designed to be invisible. I’ll explain below 🙂

  <Style x:Key="ScrollBarPageButton" TargetType="{x:Type RepeatButton}">
    <Setter Property="IsTabStop" Value="false"/>
    <Setter Property="Focusable" Value="false"/>
    <Setter Property="Template">
      <Setter.Value>
        <ControlTemplate TargetType="{x:Type RepeatButton}">
          <Border Background="Transparent" />
        </ControlTemplate>
      </Setter.Value>
    </Setter>
  </Style>
Default Page Button

Default Page Button

This style is for the scroll bar page button, which is the area between the line buttons at the top and bottom, and the “thumb” (the button in the middle that you can click and drag). Its the area you click to scroll a page at a time. We want this to be transparent to give the appearance that you are clicking on the scroll bar itself, otherwise, it would appear that there is an actual button there which would be very unusual looking (see graphic on the right for a glimpse of the scroll bar without the transparent page button style applied).

Next, we define a style for the scroll bar thumb (the slider in the middle of the scroll bar).

  <Style x:Key="ScrollBarThumb" TargetType="{x:Type Thumb}">
    <Setter Property="IsTabStop" Value="false"/>
    <Setter Property="Focusable" Value="false"/>
    <Setter Property="Template">
      <Setter.Value>
        <ControlTemplate TargetType="{x:Type Thumb}">
          <Border x:Name="Border" 
                          CornerRadius="14,14,14,14" 
                          BorderThickness="4,4,4,4" 
                          BorderBrush="#88FFFFFF">
            <Border Background="#88000000" 
                    CornerRadius="13,13,13,13" 
                    x:Name="background">
              <Grid>
                <Grid.RowDefinitions>
                  <RowDefinition Height="0.4*"/>
                  <RowDefinition Height="0.6*"/>
                </Grid.RowDefinitions>
 
                <Border Grid.Row="0" CornerRadius="13,13,0,0">
                  <Border.Background>
                    <LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
                      <GradientStop Color="#08FFFFFF" Offset="0"/>
                      <GradientStop Color="#88FFFFFF" Offset="1"/>
                    </LinearGradientBrush>
                  </Border.Background>
                </Border>
 
              </Grid>
            </Border>
          </Border>
        </ControlTemplate>
      </Setter.Value>
    </Setter>
  </Style>

There is nothing new here that haven’t already covered, so lets move on to defining the scroll bar control template.

Our ControlTemplate will define how the scroll bar is built. It defines where the arrow buttons, page buttons, and the thumb controls are positioned, and it also establishes the content of the arrow buttons (the arrow image).

  <ControlTemplate x:Key="VerticalScrollBar" TargetType="{x:Type ScrollBar}">
    <Grid Width="60" >
      <Grid.RowDefinitions>
        <RowDefinition MaxHeight="60"/>
        <RowDefinition Height="0.00001*"/>
        <RowDefinition MaxHeight="60"/>
      </Grid.RowDefinitions>
      <Border Grid.RowSpan="3" CornerRadius="18" Background="#88000000" />
      <RepeatButton Grid.Row="0" 
              Command="ScrollBar.LineUpCommand"
              Style="{StaticResource ScrollBarLineButton}"
              Content="M 0 4 L 8 4 L 4 0 Z" />
      <Track Name="PART_Track" Grid.Row="1" IsDirectionReversed="true">
        <Track.DecreaseRepeatButton>
          <RepeatButton Style="{StaticResource ScrollBarPageButton}" 
                        Command="ScrollBar.PageUpCommand" />
        </Track.DecreaseRepeatButton>
        <Track.Resources>
          <!-- Thumb's minimum height is half of this metric -->
          <sys:Double x:Key="{x:Static 
                              SystemParameters.VerticalScrollBarButtonHeightKey}">
            120
          </sys:Double>
        </Track.Resources>
        <Track.Thumb>
          <Thumb Style="{StaticResource ScrollBarThumb}" />
        </Track.Thumb>
        <Track.IncreaseRepeatButton>
          <RepeatButton Style="{StaticResource ScrollBarPageButton}" 
                        Command="ScrollBar.PageDownCommand" />
        </Track.IncreaseRepeatButton>
      </Track>
      <RepeatButton Grid.Row="3"
              Style="{StaticResource ScrollBarLineButton}"
              Command="ScrollBar.LineDownCommand"
              Content="M 0 0 L 4 4 L 8 0 Z"/>
    </Grid>
  </ControlTemplate>

Our ScrollBar control template uses a grid with 3 cells. The first contains the “scroll up” RepeatButton, the second cell contains a Track control for page scrolling and the thumb control, and the third cell contains the scroll down RepeatButton. Take a look at the first RepeatButton defined in the grid, the scroll up button, and I will explain the three attributes we are setting:

  1. Style: The style we defined earlier as ScrollBarLineButton
  2. Command: ScrollBar.LineUpCommand tells the control that when we click this button, it should scroll the list up by the amount set in the “SmallChange” property of the control
  3. Path Markup Example

    Path Markup Example

  4. Content: M 0 4 L 8 4 L 4 0 Z will display an up arrow. I know what you are thinking… What the?!? Well, this is actually drawing a shape using XAML path markup! The letters M, L, and Z will define a starting point (M), create a line to the next point (L), and end the drawing by connecting the current point to the starting point (Z). So, we are starting our drawing for the up arrow with M at coordinate 0,4 (M 0 4), then we draw a line to coordinate 8,4 (L 8 4), followed by a line to coordinate 4,0 (L 4 0), and finally we close up the shape (Z). If you would like to learn more about XAML Path Markup, take a look at this MSDN article:
    XAML Path Markup Syntax

You might remember in our style for the ScrollBarLineButton, we set the Data attribute to use a “RelativeSource” of the TemplatedParent’s Content to supply the control content. This is fulfilled by the Content attribute we just assigned.

In the second cell, we define a Track element with three parts. A page up button, the thumb, and a page down button. Remember that the style we use for the page up and page down buttons is simply a transparent style so that you don’t see an actual button. The command attribute tells the control what it should do when each button is clicked, and the rest this control should be pretty self explanatory.

In the third cell, we define the scroll down button. Again, nothing new here that we didn’t discuss with the scroll up button.

Finally, we define the style that lays out the ScrollBar onto the ListBox control.

  <Style x:Key="{x:Type ScrollBar}" TargetType="{x:Type ScrollBar}">
    <Setter Property="OverridesDefaultStyle" Value="true"/>
    <Style.Triggers>
      <Trigger Property="Orientation" Value="Vertical">
        <Setter Property="Width" Value="60"/>
        <Setter Property="Height" Value="Auto" />
        <Setter Property="Template" Value="{StaticResource VerticalScrollBar}" />
      </Trigger>
    </Style.Triggers>
  </Style>

This should all be pretty self explanatory as well :).

To use the control, you will need to add a reference into your App.xaml file so the program knows about the control. Inside of the <ResourceDictionary.MergedDictionaries> tags, just add the following line:

<ResourceDictionary Source="GlassListBox.xaml"/>

That’s it, your GlassListBox is ready to be used. Just add it to your form and roll. But remember, you might need to manually adjust the ListBoxItem width as I had mentioned above.

You can download this project here!

Tags: , , , , ,

Saturday, August 8th, 2009 Computer Programming, Tutorials 5 Comments
avatar

Creating custom glass buttons with XAML in WPF

by on Monday, May 4th, 2009, under Computer Programming, Tutorials

WPF XAML Glass Button

Glass Button

Today, we are going to take a look at how one would create a custom style for a WPF (Windows Presentation Foundation) button control. We will change the bland default button into a glass button! When working with the Windows Presentation Foundation to style a button, we simply create an XAML document to hold the style, and then we will apply the style within the form designer (much like how CSS styles are applied to HTML elements). So, lets get started! 🙂

Create a resource dictionary in your WPF Application project by right-clicking on your project in the Solution Explorer, and choosing Add -> New Item.  Select Resource dictionary and name it GlassButton.xaml

wpf-xaml-create-a-resource-dictionary

In the newly created resource dictionary, we will define a Style that we can apply to our buttons to change the way they look.  Initially, your GlassButton.xaml file will have only the following code:

<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
 
</ResourceDictionary>

We want to add a Style element so that we can change the properties of our control:

<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
  <Style x:Key="GlassButton" TargetType="{x:Type Button}">
    <Setter Property="FontSize" Value="42" />
    <Setter Property="Foreground" Value="White" />
    <Setter Property="Template">
      <Setter.Value>
        <ControlTemplate TargetType="{x:Type Button}">
 
        </ControlTemplate>
      </Setter.Value>
    </Setter>
  </Style>
</ResourceDictionary>

The styles “x:Key” attribute is what we will use to identify the style later when we apply it to a button control. The “TargetType” attribute declares what type of control our style will be used for, and in our case, it is the button. At this point, we have a couple of default properties setup for our control; the font is enlarged and the foreground color is changed to white. Next, we need to change the template property for the control to make it look like a glass button. You will notice that this property is structured a little bit differently. That is because we are defining the template inline and this requires the creation of a complex object, the ControlTemplate.

<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
  <Style x:Key="GlassButton" TargetType="{x:Type Button}">
    <Setter Property="FontSize" Value="42" />
    <Setter Property="Foreground" Value="White" />
    <Setter Property="Template">
      <Setter.Value>
        <ControlTemplate TargetType="{x:Type Button}">
          <Border x:Name="ButtonBorder" 
                  CornerRadius="25" 
                  BorderThickness="4" 
                  Background="#AA000000"  
                  BorderBrush="#99FFFFFF"
                  RenderTransformOrigin="0.5,0.5">
              <ContentPresenter x:Name="ButtonContentPresenter"
                                VerticalAlignment="Center"  
                                HorizontalAlignment="Center"/>
          </Border>
        </ControlTemplate>
      </Setter.Value>
    </Setter>
  </Style>
</ResourceDictionary>

Now that we have the template declared, lets walk through what we did. First, we laid out the main border and the tinted background of the button by using a “Border” element. We gave the button border a name (used later) and we also gave our button rounded corners by setting the CornerRadius to 25 units on each corner. You could also set the radius unit of each individual corner by specifying “25,25,25,25” which will define the top-left radius and continue clockwise around to the other corners.

Note that I said units and not pixels. One of the benefits of the Windows Presentation Foundation is it will display graphics based on the dpi setting of your device. For example, if your dpi settings are correct in your OS, a button that is 1″ wide on a 15″ screen running at 1024×768 would also be exactly 1″ wide on a 20″ screen running at 1024×768. If the controls were pixel based, the first button would be 1″ wide and the later button would be about 1 1/3″ wide.

Next we set the width of all borders to 4 units wide and apply some colors to the element. The colors used are in HTML color format, but there is a twist. XAML colors support an alpha channel (a.k.a. transparency) so the hexadecimal value we use represents the alpha, red, green and blue channels. Since we want our button background to look a little tinted, we will use the color black and make it partially transparent (#AA000000 – In decimal, this is Alpha=170, Red=0, Green=0, Blue=0). We also want the border to be white and partially transparent, so we use #99FFFFFF. The final property we set for the main border element is the RenderTransformOrigin. This is a percent based x,y value that indicates where the control will be pinned down when a transform later changes the control. We will discuss this more later, but for now, set the origin to the center of the control, 0.5, 0.5 (x origin is 50% across, y origin is 50% down).

WPF XAML Flat Glass Button

WPF XAML Flat Glass Button

The “ContentPresenter” element is the last item we add in this step. This element is what will display the text on the face of the button, so we obviously will want this inside the border. All we do here is give it a name for good practice and center the text.

Now you have a simple button style that looks like a flat piece of glass. If you want to use this style now so that you can see what it looks like, skip ahead to the “Applying our style to a control” section.

Now its time to add a little depth to our button and make a reflection on it so it looks curved and shiny. To do this we will update the code as follows:

<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
  <Style x:Key="GlassButton" TargetType="{x:Type Button}">
    <Setter Property="FontSize" Value="42" />
    <Setter Property="Foreground" Value="White" />
    <Setter Property="Template">
      <Setter.Value>
        <ControlTemplate TargetType="{x:Type Button}">
          <Border x:Name="ButtonBorder" 
                  CornerRadius="25" 
                  BorderThickness="4" 
                  Background="#AA000000"  
                  BorderBrush="#99FFFFFF"
                  RenderTransformOrigin="0.5,0.5">
            <Grid>
              <Grid.RowDefinitions>
                <RowDefinition Height="*"/>
                <RowDefinition Height="1.7*"/>
              </Grid.RowDefinitions>
              <Border Grid.Row="0" CornerRadius="23,23,0,0">
                <Border.Background>
                  <LinearGradientBrush StartPoint="0.5,0" EndPoint="0.5,1">
                    <GradientStop Color="#08FFFFFF" Offset="0"/>
                    <GradientStop Color="#88FFFFFF" Offset="1"/>
                  </LinearGradientBrush>
                </Border.Background>
              </Border>
              <ContentPresenter x:Name="ButtonContentPresenter"
                                VerticalAlignment="Center"  
                                HorizontalAlignment="Center" 
                                Grid.RowSpan="2" />
            </Grid>
          </Border>
        </ControlTemplate>
      </Setter.Value>
    </Setter>
  </Style>
</ResourceDictionary>

We have added a Grid element to our style because a Border element can only have one child, but we want a reflection and a content presenter. The grid can have multiple children and it will allow for proper placement of our reflection. The Grid has 2 rows defined, and the only attribute we set for each row is the height. Note the ” * ” in use. What this will do is make sure all rows fill up 100% of the grid. The number in front of the asterisk is a multiplier, so in our case, row 2 is 1.7 times the height of row one. If I had used 2*, the second row would be twice as high as the other row (i.e. 2/3 the height of the grid).

Now we add a border object to simulate the reflection. You can see that we are binding the border to the first row in the grid by setting the Grid.Row attribute to 0, and we are also making the top-left and top-right corners rounded to fit into the outer border. With this border element, we are setting the background property to resemble the reflection, but we don’t use a simple color like we have done in the past. We instead define a LinearGradientBrush to blend from a mostly transparent white to a partially transparent white. The StartPoint and EndPoint attributes of the LinearGradientBrush are percent based x,y coordinates that will determine where the blending starts, ends, and in what direction the blend will occur. Using 0.5,0 will start at the top center, and 0.5,1 will stop at the bottom center of the border object. There are also 2 GradientStops defined here that represent the transparent white and the semi-transparent white colors that the gradient will use. The offset attribute will determine (as a percent based decimal) where the color should occur. For our case, we want the transparent white to occur at the beginning of the gradient, and the semi-transparent white to occur at the end. Imagine if your gradient had 3 colors, you might put them at offsets of 0, 0.5, and 1 to see an equal blend distance between each color.

Finally, we move the content presenter element into the grid object and add the attribute Grid.RowSpan=”2″ so that it can span the entire height of the grid.

Now we have a pretty glass button, but it wouldn’t do much if you were to click on it. We will create a trigger to shrink the button a little bit so it looks like it is depressing when you click on it. Update your code as follows:

<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
  <Style x:Key="GlassButton" TargetType="{x:Type Button}">
    <Setter Property="FontSize" Value="42" />
    <Setter Property="Foreground" Value="White" />
    <Setter Property="Template">
      <Setter.Value>
        <ControlTemplate TargetType="{x:Type Button}">
          <Border x:Name="ButtonBorder" 
                  CornerRadius="25,25,25,25" 
                  BorderThickness="4,4,4,4" 
                  Background="#AA000000"  
                  BorderBrush="#99FFFFFF"
                  RenderTransformOrigin="0.5,0.5">
            <Grid>
              <Grid.RowDefinitions>
                <RowDefinition Height="*"/>
                <RowDefinition Height="1.7*"/>
              </Grid.RowDefinitions>
              <Border Grid.Row="0" CornerRadius="23,23,0,0">
                <Border.Background>
                  <LinearGradientBrush StartPoint="0.5,0" EndPoint="0.5,1">
                    <GradientStop Color="#08FFFFFF" Offset="0"/>
                    <GradientStop Color="#88FFFFFF" Offset="1"/>
                  </LinearGradientBrush>
                </Border.Background>
              </Border>
              <ContentPresenter x:Name="ButtonContentPresenter"
                                VerticalAlignment="Center"  
                                Grid.RowSpan="2" 
                                HorizontalAlignment="Center"/>
            </Grid>
          </Border>
          <ControlTemplate.Triggers>
            <Trigger Property="IsPressed" Value="True">
              <Setter Property="RenderTransform" TargetName="ButtonBorder">
                <Setter.Value>
                  <TransformGroup>
                    <ScaleTransform ScaleX="0.9" ScaleY="0.9"/>
                  </TransformGroup>
                </Setter.Value>
              </Setter>
            </Trigger>
          </ControlTemplate.Triggers>
        </ControlTemplate>
      </Setter.Value>
    </Setter>
  </Style>
</ResourceDictionary>

In this update, we have created a trigger event that will occur when the buttons “IsPressed” property is true. When this occurs, we will apply a RenderTransform to the element named “ButtonBorder”. In our particular case, we are using a ScaleTransform to scale down the size of our button border to 90% when pressed. If you remember correctly, we set a RenderTransformOrigin to the center of the button in a previous code snippet. This will center the transform action so the button will appear to adjust evenly around the edges with the center locked in place. If we did not set this, the button would do all scaling while pinned in the top left corner, and only the right side and the bottom would visibly move. If that doesn’t make sense, just try it and you’ll see what I mean. 😉

Applying our style to a control

To use our GlassButton style, we must now add a resource reference into our App.xaml file. My App.xaml looks like the following; I have only added the <ResourceDictionary Source=”GlassButton.xaml”/> line:

<Application x:Class="Demo.App"
  xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
  StartupUri="Window1.xaml">
  <Application.Resources>
    <ResourceDictionary Source="GlassButton.xaml"/>
  </Application.Resources>
</Application>

Finally, open the XAML code for your window and add a button element with the style attribute set to “{DynamicResource GlassButton}” (note that GlassButton is the x:Key value we set for the style element). In my particular application, the line of code looks like this:

    <Button Style="{DynamicResource GlassButton}" 
            Grid.Column="1" 
            Margin="0,0,18.577,17.148" 
            Name="button1" 
            Height="91.456" 
            VerticalAlignment="Bottom" 
            HorizontalAlignment="Right" 
            Width="207.764">Button</Button>

Now when you run your application, you will have a beautiful glass button!

Tags: , , , , ,

Monday, May 4th, 2009 Computer Programming, Tutorials 7 Comments
avatar

How to quickly test your UT3 mods with nFringe

by on Friday, March 27th, 2009, under Computer Programming, Tutorials

If you are like me, you will quickly get sick of waiting for the game to load only so you can click through a bunch of menus and find out that your mod didn’t work.  Well I have good news!  There are some settings that we can pass into UT3.exe to make it jump right in and show us the results of our work.

Right-click your project in Visual Studio’s ‘Solution Explorer’, and then select ‘Properties’.  Choose the ‘Debug’ tab on the left and make the following changes:

  1. Check the ‘Load map at startup’ box, and then put in the map name of your choice (I personally use WAR-Torlan as this was always my favorite, even in UT2k4).
  2. After your map name, we need to specify some command line options.  We will use the ‘?Mutator=SuperStinger.SuperStinger’ option to load up our mutator*, and also the ‘?quickstart=1’ option so we don’t have to wait for the count down.  So our ‘Load map at startup’ field should read:  WAR-Torlan?Mutator=SuperStinger.SuperStinger?quickstart=1
  3. Check the ‘Disable startup movies’ box so we can bypass all of the advertisements
  4. If you want your input settings to be applied while you test your mods, we need to login to your on-line account.  Under ‘Additional Options’, add the following text replacing ‘your_login’ and ‘your_password’ with your online account information: -login=your_login -password=your_password

*If you don’t know what to supply for your ‘Mutator’ parameter, locate the .ini file for your mutator class in the ‘Solution Explorer’ and open it up.  You will see a line for the class name that you should use, in my case, it looks like this:

ClassName=SuperStinger.SuperStinger

UT3 quick start settings for testing mods

That’s it!  Enjoy… 😀

Tags: , , , , , , , ,

Friday, March 27th, 2009 Computer Programming, Tutorials 1 Comment
avatar

Creating your first Unreal Tournament 3 mutator (The SuperStinger)

by on Thursday, March 26th, 2009, under Computer Programming, Tutorials

In this tutorial, we will walk through creating a new ‘UnrealScript Game Mod’ project using nFringe and Visual Studio 2008.  This tutorial assumes you have a development environment setup and the Unreal Tournament 3 source code downloaded and installed as prescribed in my previous tutorial, setting up Visual Studio 2008 for UnrealScript development with nFringe.  It is also assumed that you know a little bit of Java (or similar C based languages).

For our first mod, were going to take the Stinger (which is like a chain gun) and make it shoot tank shells.  :p

Creating an UnrealScript Game Mod project

Open up Microsoft Visual Studio 2008 from your Start menu and then go to File -> New -> Project.  Select ‘UnrealScript’ for the ‘Project type’, and choose ‘UnrealScript Game Mod’ under ‘Templates’.  Now, give the project and solution a name, lets say ‘SuperStinger’, and then click ‘Ok’.

New UnrealScript Game Mod Project

Once your project is created, you will need to provide some settings to allow Visual Studio to work with the existing source and the game itself.  On the right side of the screen, you will see a ‘Solution Explorer’ with a list of items under it.  Right click on your ‘SuperStinger’ project (2nd item in the list) and go to ‘Properties’.  With the ‘General’ tab selected on the left, select ‘Unreal Tournament 3’ for the ‘Target Game’ and then click ‘Load UCC Defaults’.  This should populate most of the fields with the proper information, leaving only the ‘Reference Source Path’ empty (see below for what this should contain).  If for whatever reason the fields are not populated, they should be filled out as follows:

  • UCC Path: Point this to your UT3.exe file
  • UCC User Path: Point this to your “My Documents\My Games\Unreal Tournament 3\UTGame\” folder
  • UCC Game Prefix: This should contain “UT”
  • Reference Source Path:  If you followed my first tutorial, Setting up Visual Studio 2008 for UnrealScript development with nFringe, this path would point to your “My Documents\My Games\Unreal Tournament 3\UTGame\Src” folder.  Essentially, this should point to your UT3 source code.

Super Stinger Project General Settings

Finally, go to the ‘Debug’ tab on the left and point ‘Start Game Executable’ to your UT3.exe file.  This path should be the same as the ‘UCC Path’ on the ‘General’ tab.

At this point, you may want to stray off and read my tutorial on how to quickly test your UT3 mods with nFringe.  This will offer up some time saving settings you can apply here, but it is not necessary.

That’s ALMOST it!  There is one last little step that needs to be done before we hop into the code, and that is to save everything and then reload the solution (File -> Close Solution, then File -> Recent Projects -> …\SuperStinger.sln).  We do this to work around what I assume is a bug in nFringe.  If you try to build your solution prior to reloading it, you will get the following error:

The “Ucc” task was not given a value for the required parameter “UccPath”.

NOTE:  If you want to use Visual Studio’s ‘Class View’ window with the UT3 Source,  you will need to open one of the files in ‘Reference Source’ folder before the ‘Class View’ will populate.

Making the Super Stinger

Lets right click on the SuperStinger project again, and point to Add -> New Item.  Select ‘UT3 Weapon’ for the template, and give it the name ‘UTWeap_SuperStinger’.  Click ‘Add’.

Add New UT3 Weapon ClassNow, in the ‘Solution Explorer’ on the right, you will see a few new files.  Open up the UTWeap_SuperStinger.uc file by simply double-clicking on it.  Inside, you will find the following code:

class UTWeap_SuperStinger extends UTWeap_Enforcer;
 
DefaultProperties
{
}

The first thing I want you to notice is the DefaultProperties section.  This section allows to set the properties that our base class will use, and this is where we will be making our changes to the Stinger.  But first, it looks like our new weapon is inheriting off of the puny Enforcer.  Well, since we want to make a killer gun based off of the Stinger, we will change this to inherit from ‘UTWeap_Stinger’.

Now, this isn’t simply a guess for what to inherit off of.  If you want to see a list of the weapon classes available, all you need to do is expand the ‘Reference Source’ folder in your solution explorer, and then expand the ‘UTGame’ package.  All of the hand-held weapons are prefixed with ‘UTWeap_…’, so just scroll down until you get to that section and you will see the options that we can use for our base class.  In fact, go ahead and open up the UTWeap_Stinger class. 🙂  You will notice that the Stinger class is inheriting off of the UTWeapon class, and that class is holding all of the properties we want to reset.  If you want to look at the contents of the UTWeapon class, just right click on UTWeapon, and then click ‘Go To Definition’.  This will open up the class without you having to go find it in the solution explorer manually (though if you wanted to, its only a few items down the list from the Stinger class).

Anyway, go back to the Stinger class, scroll down to the bottom and take a look at the DefaultProperties section.  This is much of what makes the Stinger, well, a Stinger.  You will see that the weapon has a series of arrays for firing ammunition.

FiringStatesArray(0)=WeaponWindUp
WeaponFireTypes(0)=EWFT_InstantHit
FireInterval(0)=+0.1
WarmupShots(0)=5
WindDownTime(0)=0.27
Spread(0)=0.0675
InstantHitDamage(0)=14
InstantHitDamageTypes(0)=class'UTDmgType_StingerBullet'
ShotCost(1)=2
 
FiringStatesArray(1)=WeaponFiring
WeaponFireTypes(1)=EWFT_Projectile
WeaponProjectiles(1)=class'UTProj_StingerShard'
WarmupShots(1)=1
FireInterval(1)=+0.28
WindDownTime(1)=0.33

The ‘0’ index is used for the primary fire, and the ‘1’ index is the secondary fire, however in the Stinger’s case, the primary fire uses an EWFT_InstantHit WeaponFireType, not a Projectile.  I can tell from looking at the secondary fire that available projectile classes will be prefixed with ‘UTProj_…’, and looking through my file list in the ‘Solution Explorer’, I find ‘UTProj_TankShell.uc’. 😀

Lets go back to our UTWeap_SuperStinger class now armed with this information.  We’ll update what the class inherits off of and then change the default secondary fire WeaponProjectile class.  Our class should now look like this:

class UTWeap_SuperStinger extends UTWeap_Stinger;
 
DefaultProperties
{
    // Heheheheheheh...  We make things go boom!
    WeaponProjectiles(1)=class'UTProj_TankShell'
}

Setting up our mutator

Now, in your ‘Solution Explorer’ on the right, find the SuperStinger.uc file and open it up.  This is our mutator class that the game will use to include the SuperStinger.  In here you will see the following code:

class SuperStinger extends UTMutator;
 
function InitMutator( string Options, out string ErrorMessage )
{
    super.InitMutator( options, ErrorMessage );
}
 
function bool CheckReplacement( Actor Other )
{
    // return true to keep this actor
    return true;
}
 
DefaultProperties
{
}

So, as you can see, our default class is inheriting the UTMutator and we have a couple functions set up.  InitMutator will run when the mutator initializes, and this is where we will make the SuperStinger a part of the game.  CheckReplacement gets fired as the player “picks up” items in the game, and I believe for many other things that we are not concerned with at this point.  We will use this to make sure the player doesn’t pick up something much less cool (like the puny Enforcer) and replace our SuperStinger with it.  Take a look at the UPDATED code below and review the comments to understand what we are doing.

class SuperStinger extends UTMutator;
 
function InitMutator( string Options, out string ErrorMessage )
{
    // Make sure the game does not hold a null reference
    if(UTGame(WorldInfo.Game) != none)
    {
        // Insert our new SuperStinger Class into the first inventory slot
        // so that we start out with one instead of the puny Enforcer
        UTGame(WorldInfo.Game).DefaultInventory[0] = class'UTWeap_SuperStinger';
    }
    super.InitMutator( options, ErrorMessage );
}
 
function bool CheckReplacement( Actor Other )
{
    // See if the player has picked up the puny Enforcer
    if(Other.IsA('UTWeap_Enforcer'))
    {
        // Looks like the pickup was an Enforcer...  We'll replace it with our
        // shiny new SuperStinger so it doesn't take over the awesome gun
        // in the inventory
        ReplaceWith(Other, "UTWeap_SuperStinger");
    }
    // return true to keep this actor
    return true;
}
 
DefaultProperties
{
}

Now, save everything!  Finally, from the menu’s at the top of your window, click Debug -> Start Debugging.  When the game starts, look at the bottom of your screen (after selecting your map) for a “Mutators” button.  Click that, and you should see your ‘SuperStinger Mutator’ in the list.

Happy hunting, and try not to kill yourself too much 🙂

Tags: , , , , , , ,

Thursday, March 26th, 2009 Computer Programming, Tutorials 22 Comments
avatar

Setting up Visual Studio 2008 for UnrealScript development with nFringe

by on Thursday, March 26th, 2009, under Computer Programming, Tutorials

If you want to start writing mods for Unreal Tournament 3, this series of tutorials will cover everything you need to get you going.  Today, I am going to walk you through installing all of the software you need so you can begin working on your first mod.  All of the software we will use is free (as in beer) for non-commercial use, so the only thing you need to buy is Unreal Tournament 3 (UT3). 🙂

Required Software

First, install UT3 and upgrade it to the patch you wish to develop for.   To get the latest patch (recommended), go to UnrealTournament3.com and look for their downloads section.  You should easily be able to find the latest patch there.  I am using patch 4 (aka 1.4, aka UT3 v2.0) so if you want to use the same version that this tutorial uses, you can download it here.

If you don’t have Visual Studio 2008 installed, or if you only have the Express Edition of Visual Studio 2008, you will need to download and install the Visual Studio 2008 Shell.

Now we need to download and install the .NET Framework 3.5 (this step may not be required; look for “Microsoft .NET Framework 3.5” in Add/Remove Programs to determine if you need it).

Next, download and install nFringe from PixelMineGames.com. You can probably get the latest release and follow through my other tutorials just fine, though this tutorial uses version 1.0.19395.0

Finally, you will need to get the source code for Unreal Tournament 3 that matches your patch. You can download the latest patch source from EpicGames.com (look for the downloads section about half-way down on the page). Extract the ‘Src’ folder from your download into “My Documents\My Games\Unreal Tournament 3\UTGame\”. For example, in patch 4, the rar contains the folder “UT3ScriptSource_1.4\Development\Src\…” with a bunch of stuff under it.  Put that folder into your UTGame folder so that you end up with “My Documents\My Games\Unreal Tournament 3\UTGame\Src\…”.
NOTE: If you cannot open the download, try using WinRAR

Start Modding!

You are now ready to create your first project and begin hammering out some serious mods.  You may also want to check out my tutorial on creating your first Unreal Tournament 3 mutator (the SuperStinger).

Happy fragging! 😀

Tags: , , , , , , ,

Thursday, March 26th, 2009 Computer Programming, Tutorials No Comments