Saturday, September 03, 2016

Back to WPF

Hello Dorks!

Lots of changes recently. Seems that the one thing in life that's constant for me is change. I've moved on to a new gig (working at Blackbird Interactive, for those keeping score) doing tools stuffs. This means I'm back in the world of WPF. And lots of trying to remember stuff from over 2 years ago.

So, I thought I'd share (and maybe get some recommendations from other WPF gurus out there).

One of the things I've been working with lately is ComboBoxes. Lots of fun stuff going on there. The current thing I've been working on is how to have the drop down list in a combo box be different from the actual data that the combo box is bound to.

For example, let's say we have a class that represents an item in a list:

And then, let's say we have a completely different class, which contains an ID:

The question is, how do we bind the dropdown list with a list of Items but also have the ability to populate a bound Asset?

Here's what I've come up with (and by no stretch is it perfect):

So, what have I done? Let's walk through it, step by step:

  1. Created the list that's going to populate the drop down list. That's the elements list.
  2. Set the comboBox's ItemsSource to that list. This is nothing more than the data store for the contents of the dropdown list.
  3. Set the comboBox's SelectedValuePath to the Name property in the Item class. If we don't do this, the combo box has no way of determining what it should use to display in the drop down, and defaults to the ToString() method (and thus giving us the class name). We use Name here, because it gives us something more user friendly (hopefully).
  4. Set the comboBox's selected value 'path'. This is nothing more than telling the combo box that we are interested in getting it ID property in the selected Item in the drop down. It's also used to select the right item in the list box (we only have to set the SelectedValue to the ID, rather than iterate through the list ourself).
  5. We set the SelectedValue to the ID we want to show selected.
  6. We set the Tag property on the combo box to the actual object we want bound to this combo box. We'll use that Tag later to populate our value.
  7. We set the callback for handling a selection changed operation.

A number of steps, yes. But all fairly straightforward. Next we need some code to handle setting the value bound to the combo box. That's in the OnSelectionChanged method.
  1. We get the bound ComboBox, Asset bound to the ComboBox and the selected Item.
  2. Now that we have our data, we set the asset's ID.

I probably could migrate OnSelectionChanged to a lambda function to simplify, but for now, I want to keep this as clean as possible.

If you want to try this yourself, I've pushed the code up to github. Feel free to peruse and comment here:

Monday, May 23, 2016

Learnings in UE4

Back at it again folks.

Hey loyal (and not so loyal) readers!

This time, I've been meaning to do some work in Unreal Engine 4. I've wanted to much around in that playground for ages and this May long weekend, I thought I'd take a stab at it again.

And man, has it *ever* been a long time since I've been in this ecosystem. I've forgotten a lot. So I'm going to use this blog as kind of a dumping ground for things I've re-learned or learned anew.

So, what I'm trying to do, out of the gate, is fairly ambitious, so we'll see how far we get. Something near and dear to my heart is conversations systems, so I think I'm going to try and take a stab at building something along the lines of a conversation system you'd find in a Telltale game.

So here's the high-level goals:\
  1. Create something that allows for rapid generation of a conversation - from pre-vis all the way through to final, production ready conversations.
  2. Make it multi-user friendly. This is a big part of the workflow. A writer should be able to use it as well as an editor and the cinematic composer. We should also be able to track the state of these conversations along the way.
  3. Allow for localization.

That's not all going to happen at once; this will take a long time to flesh out along the way.

Anyway, let's get started.

One of the things that we're going to need is a 'stage' onto which the conversation actors are going to be able to deliver their lines. This isn't actually a physical stage, but a container for everything you'd need for a conversation. Of course, we'll need the actors who deliver their lines, but you need other things, like cameras, sequencers for animation playback (if necessary) as well as an audio streaming system for line playback and subtitles.

So, off into the land of Unreal Engine we go!

Setting the stage!

It's been a very long time since I've written any Unreal code, and I have next to no experience in UE4. That's kind of what this project is about, to be honest. So, as an upfront warning, there will no doubt be a number of problems with what I create today. So expect a fair number of changes as we go.

The class hierarchy in UE4 is fairly complex, so expect to spend a fair bit of time digging through the code, and tutorials to get a feeling for the engine. But, in all honesty, all modern engines have a fair bit of complexity to them, so this isn't unexpected.

Fire up the editor in UE4 and create a new, C++ project based off the 'Third Person' template. You could use any other, but for the type of game I'm thinking of, that one makes the most sense. Once you've done that, you'll want to add a new C++ class; do this under the 'File->New C++ Class' menu.

There's a number of options here and I'll investigate more later, but for now, let's just stick with the 'Actor'. Eventually we'll also look into the Actor Component, but I don't see getting at that this time around.

The class I'm creating is called AConversationStage (following the UE4 class naming convention). It's intended use is as a origin 'locator' for the conversation (or cinematic) that you can move and all the actors will move with. This is invaluable is something in the level changes and you want to change where the conversation takes place.

For the most part, anything that you interact with in UE4 is derived off an AActor class (there are others and eventually we'll look at them). So that's where we'll start.

Go ahead an create the class. You can find the newly created classes in the Content Browser. It looks like this:

So, once created, you can right-click on the new actor and select 'edit' - you'll then open up the Visual Studio (or Xcode) project with the code ready to go.

Here's what we have at this point:



That's able to compile now. Don't actually try to compile it via Visual Studio/Xcode - go back to the Unreal Editor and select the compile button (between the build and play buttons)

Now you can drag that class into your scene. Go ahead and do it.

You don't see anything, right?  Yeah, that's normal. However, if you look at the world outliner, you should see and entry for 'AConversationStage1'. Here's what it looks like:

So, it's important to note that right now there's nothing in this actor. Nothing to render, no real attributes, no real data.  Let's start by creating a visual for this object that we can actually select.

How that works is you need a 'RootComponent'. That's a representation of this object in the world. RootComponents are an instance of a USceneComponent. So what's that? It's essentially a class that defines a transformation (location, rotation, scale) and supports 'attachments'. More on the attachments bits later. UE4 USceneComponent Reference

OK, so how do we display something in-editor? You add a scene component! So, we're looking for anything derived off a USceneComponent class (look in the UnrealEngine\Engine\Source\Runtime\Engine\Classes\Components folder for some examples).  I decided to choose the UBoxComponent as a test. Thus we end up with the following code:



Compile again. Now drag the actor into the scene and now you see a wireframe outline of a box with the standard control widget:
Left-click somewhere else, so that the ConversationStageActor isn't selected anymore:

That's just to reiterate that the widget isn't part of the object.

Now select the CoinversationStageActor again by clicking on it in the editor.

Not even remotely easy, is it? Like, dangerously hard to select.  Let's fix that by actually making the scene object used to represent the object an actual static mesh.

First off, crack open your favourite 3D modelling package and create a mesh about 10x10 across (it doesn't have to be very tall). Save it as an FBX and import it into the engine. For now, just save it into your game project (later, we'll make this a plugin). I've stored mine into the Content/Geometry/Meshes folder and called it 'stage'.  At any point in time, you can right click on the asset in the Content Browser and select 'Copy Reference' to get a fully qualified reference to that object; we'll need that later. Please note! If you do not have a static mesh imported for the visual representation of this mesh, you will not see the object in editor!

Next, we have to create a scene object that represents that mesh. That's where the UStaticMeshComponent comes into play. From it, we can get a bunch of geomtry information from it, including collision information.

Anyway, for the object, we need to add said UStaticMeshComponent. So let's modify our class to contain one:


As you can see, all we've done is add a new private member for the stage, which is a UStaticMeshComponent. We keep this around so we can reference it (and we will).

To create it:


And with that, when you drag an conversation stage over now, you get this:

Try re-selecting that again; notice how much easier it is now? That's a huge improvement.

OK, so to talk about the code for a bit. First, notice that we create a static StageMeshAsset. That just means that we only incur creating the object once, not each time we re-instantiate the class. It also means that it's loaded into memory all the time, so you want that asset to be as lightweight as possible.

Secondly, we've actually named this subobject 'm_StageVisualComponent' as part of the CreateDefaultSubobject. This is part of UE4's internal bookkeeping (I believe we can search the loaded scene components for these and get a list, but I have to investigate that later).

Thirdly, we set the static mesh for the instance of the m_StageVisualComponent to the Object that was loaded into the StageMeshAsset. This is just a reference to that object, not a new instance (and duplicate geometry) - Static Meshes, FTW.

So, why all that?

The transformation on the m_StageVisualComponent (and thus the root component) will be used to drive the  offsets for the additional components we're going to add later. eg, the cameras, stage marks for actors, and anything else we want to add.

Exciting times!