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:

AConversationStage.h



AConversationStage.cpp



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:

AConversationStage.h 



AConversationStage.cpp




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:

 AConversationStage.h



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:

AConversationStage.cpp


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!

Sunday, May 17, 2015

Update ...

Hey, so in the rush to get the last post out, I missed a couple of things. Like getting the Maven project to actually run.

So, I've done that and updated the project to reflect that.  Also, more documentation in the folders (a few more readme.md additions).

Have a good long weekend, folks.

Sunday, April 26, 2015

Long Time, no post. Today we talk about distributed real-time systems, Logging systems and 'The Cloud'

*dusts off the computer monitor, flicks a few switches and the hum of memory banks energizing can be heard in the background*

Good lord, has it been this long since I wrote a blog post? Wow.

Sorry about that folks.

Anyway, I've been doing a lot of things lately that are sort-of game related, but actually a little more mainstream. And I thought I would share it with you guys out there.

So, a little background, for you to get up to speed.

I shipped Dragon Age: Inquisition. I'm immensely proud of what we were able to accomplish on that title. A lot of firsts for me. And an amazing team that I had the luck to work with.

But times change. Family wanted to be back on the west coast. BC in specific. Apparently once it's in your blood, it's there for life.

Anyway, the fine folks at Demonware (demonware.net) were gracious enough to offer me a position there and boy howdy, has it been a learning experience.

One of the things I'm working on is real-time event ingestion. That's not something I'll be talking about here (at least, not for a while), but I would like to talk about a couple of technologies I've come across that might be of interest to the general public, as well as some of the fine folks at Demonware.

So, quick poll - how many people are familiar with metrics and event logging? Show of hands? Yeah, not a lot of my readers would be familiar with that. I was in the same boat. Coming from a game dev background, logging is something you do when you're debugging a build. But 'logging' for me meant 'printf''s all over the place. Or maybe even something a little more fancy in our scripts for manipulation assets.

What if I told you there was something else that you could use, that would persist that data. It's not a deep store, but it's in the 'days' range. What if I told you there were a number of things out there, Open Source that could do that. There are! The one we're going to look at is something called 'Kafka'. It's from Apache (you know, the guys that make that web server thing). You can find it here: http://kafka.apache.org/

No, I'm not going to go into how to install/set it up. That's a topic that already has enough coverage. So go, Google that, do some digging, maybe even set up an instance. I'll wait.

Cool, isn't it? The things we're going to be focusing on here are Kafka Topics and Producers.

Just to re-iterate: A Topic is a container for like messages sent to Kafka. So you could create a topic in Kafka called 'Failed.build.asset' and store a text blob in that message that represented the asset that failed to build, the machine that failed to build it, the time and any error information you wanted to persist. What sends that data to Kafka is called a 'producer'.

And I'm going to show you how to build one in Python.

I've created a git repository here https://github.com/Nuclearfossil/storm-tutorial for those playing along at home. The script is called datapusher.py and you can find it in the python folder.

from kafka.client import KafkaClient
from kafka.producer import SimpleProducer

import time
import random
import logging

logging.basicConfig(level=logging.INFO)

pronouns_possessive = [ "my", "your", "his", "her", ...]
nouns_singular = ["attorney-general", "brother-in-law", ...]
nouns_plural = ["attorneys-general", "brothers-in-law", ...]
verbs_singluar = ["become", "catch", "drink", "drive", ...]
verbs_plural = ["becomes", "catches", "drinks", "drives", ...]
infinitives = ["to make a pie.", "for no apparent reason.", ...]

# Make sure to change 'hostname' below.
broker = "hostname:9092"

logging.info("Connection to Kafka = {0}".format(broker))

client = KafkaClient(broker)
producer = SimpleProducer(client)
index = 0
logging.info("Sending strings")

client.ensure_topic_exists("sentenceTutorial")

while index < 10000:
    index+=1
    sentence = "{0} {1} {2} {3} {4}".format( random.choice(pronouns_possessive),
        random.choice(nouns_singular),
        random.choice(verbs_plural).lower(),
        random.choice(nouns_singular).lower() or random.choice(nouns_plural).lower(),
        random.choice(infinitives))
    producer.send_messages('sentenceTutorial', sentence)
    logging.info("sent {0} of 10000. Message: {1}".format(index, sentence))
    time.sleep(5)

So, aside from a pretty crappy sentence generator (feel free to update it), the meat of the code lives inside the KafkaClient and the SimpleProducer interface. The Broker is Kafka parlance for where the system broker for Kafka lives. The underlying broker technology Kafka uses is Zookeeper (you can look that up). I think I'm going to do an article on that at some point as it's interesting tech as well. For now, think of Zookeeper as a distributed registry (like the registry in Windows) for apps.

We push a message into a Kafka topic "sentenceTutorial" via the send_messages() method. We're not limited to sending one message at a time to Kafka, but they do have to be on the same topic.

So, what's in Kafka now? In the topic "sentenceTutorial" there will be a new string pushed once every 5 seconds. Kafka has lots of ways of printing out what's in the topic, so read up on kafka_console_consumer.

Alright. Now we have something putting content into Kafka. Now we want to consume that data. And by consume, I mean read. What we write doesn't actually remove content from Kafka. That data will naturally expire based on a sliding window defined in the Kafka setup.

So, this is where Apache Storm comes into the mix. There are a bunch of other real time systems available, but Storm has the longest legs on it. That and so far, it's been the most reliable.

So, in the java folder of the storm-tutorial repo, I have a stand-alone storm project that will also (I think) work in a clustered environment.

I'll leave it as an exercise for the reader to examine the pom.xml file to see how I've set up the project for Maven. It's as simple and straight-forward as you can make a Maven project.

Now for the actual code. This will end up being a starter point for more tutorials, so it's best to start off simple. This is nothing more than a main class with a single class for doing the processing.

So, what does Storm 'do'? From the Apache Storm website:
Apache Storm is a free and open source distributed realtime computation system. Storm makes it easy to reliably process unbounded streams of data, doing for realtime processing what Hadoop did for batch processing. Storm is simple, can be used with any programming language, and is a lot of fun to use!

You need to have a cluster set up for doing any distributed processing, but we can simulate that on a single machine (and we can also debug it better).

How does it work? It's essentially a network topology that defines data 'Spouts' and process 'Bolts' that transform the data. You use the topology framework to define the network of these Spouts and bolts.

Here's an example from the repo:

// The TopologyBuilder is what defines the topology for the storm
// processing 'network'
TopologyBuilder builder = new TopologyBuilder();

// This next section defines the configuration information for the Kafka
// spout.
GlobalPartitionInformation hostsAndPartition = new GlobalPartitionInformation();

// Make sure to change 'hostname' below
hostsAndPartition.addPartition(0, new Broker("hostname", 9092));
BrokerHosts brokerHosts = new StaticHosts(hostsAndPartition);
SpoutConfig config = new SpoutConfig(brokerHosts, "sentenceTutorial", "/demonwaretutorial", "987654321");

// defining a scheme here does some default data transformation.
// if we don't define it, the data comes across as raw binary.
config.scheme = new SchemeAsMultiScheme(new StringScheme());

// This is where we define a spout in our topology
builder.setSpout("spout", new KafkaSpout(config), 1);

// This is were we define our bolt in the topology and what data it receives
builder.setBolt("print", new PrinterBolt(), 1).shuffleGrouping("spout");

What we're left with, defined in the builder instance is a topology that takes data from the Kafka spout "spout" and feeds that data into a 'PrinterBolt' bolt.

Note the 'StringScheme' that is bound to the config.scheme. In essence, this does some preliminary data transformation of the data. I'll dig into that in a later tutorial as well (as I'm still figuring it out).

That PrinterBolt looks like this:

public static class PrinterBolt extends BaseBasicBolt {
    static Logger logger = Logger.getLogger(PrinterBolt.class);
    /**
     * This execute method reads the data ingested by the spout and simply
     * logs it.
     * It's a very straightforward bolt.
     *
     * @param input
     * @param collector
     */
    @Override
    public void execute(Tuple input, BasicOutputCollector collector) {
        String msg = input.getString(0);
        logger.info(String.format("Received message: %s", msg));
    }
    /**
     * Currently this does nothing.
     * @param declarer
     */
    @Override
    public void declareOutputFields(OutputFieldsDeclarer declarer) {
    }
}

I recommend stepping through the execute method to see what is in the Tuple that is passed in. The long and short of it is, it's a map of objects and in this case, we're getting the first string in that map.

One last thing. In the main function, we also do this:

if (args != null && args.length > 0) {
    // So, if we're in here, we're running the topology on a cluster.
    conf.setNumWorkers(3);
    StormSubmitter.submitTopologyWithProgressBar(args[0], conf, builder.createTopology());
}
else {
    // if we're here, we're running stand-alone.
    conf.setMaxTaskParallelism(3);
    LocalCluster cluster = new LocalCluster();
    cluster.submitTopology("tutorial01", conf, builder.createTopology());
    Thread.sleep(100000);
    cluster.killTopology("tutorial01");
    cluster.shutdown();
}

Like the comments say, the first block is for running in a distributed cluster mode. The second part runs it in stand-alone mode.

So, feel free to give the project a go. Make sure you change all the instances of 'hostname' in the code to your Kafka instance to get this running. I'll eventually make this so it's far more configurable for both the Java and Python codebases.

This was a lot. There also isn't a lot of theory in here. I think I'll tackle that in the next blog post.

Enjoy and looking forward to the comments!

Tuesday, January 07, 2014

Useful scripts and hacks

Over the years, I've run into hundreds of little hacks/scripts/nuggets of things that I find useful.  And I have no centralized spot to store/share them.

Time to fix that!  Here, for posterity, is a list of common hacks/scripts/nuggets that I've run into and need to hold on to!

Perforce

 p4 diff -sd //branch | p4 -x -sync -f  ||| looks for missing file in //branch and force syncs them.
 p4 changes -m1 #have                   ||| run from a folder, tells you what the current changelist is.

Actually, I'm going to move these over to gists in github.  Find them here: https://gist.github.com/Nuclearfossil

Sunday, February 17, 2013

Archeology 101

Yesterday I was a little bored, so I started looking for a good ol' fashioned FPS to play. Of course, while digging through older CD's, I came across some old CDIS backups. And, of course, I came across, semesters worth of work. And, for me, work == old, forgotten code.

While I was digging through all that code, I found my OGDF project. It was a gaming framework that I was working on while at CDIS I was going to use for student work, as a baseline for 'hey, here's some framework code that will get you into game programming while avoiding some of the pitfalls of dealing with window resizing, switching to fullscreen/windowed mode ... you know the stuff I'm talking about in this blog now.

Some really interesting ideas in that codebase, that I'm probably going to pull forward.

But, oh my god, some awful, AWFUL ideas in there as well (Yeah, I found the Singleton Hammer1).

Anyway, one of the crazy things that I found in there was a series of articles that I wrote that eventually went on to become the lua series I wrote for Gamedev.net (shameless promotion) and were then published in 'Beginning Game Programming: A gamedev.net collection'.  It's crazy how something I wrote over 10 years ago still has an impact on folks; I still, once in a while, get questions on it.  I always intended on writing more on scripting languages (like using python, or other, alternative languages), but I could never find the time to do that.  And it's something that I don't get to spend enough time on day-to-day to become an expert on the subject.

1.The Singleton Hammer refers to any new programming/design methodology that people get tunnel vision on ... where if you only have a Hammer, everything looks like a Nail.

    Sunday, January 27, 2013

    Dev Zero - Actually getting that window on the screen - [Part 3]

    The goal this time around is to determine what we need to do in order to get a proper Window on-screen. What does it take to get a window on-screen in the land of Microsoft? Well it breaks down into a couple of API calls:

    • RegisterClassEx() to register the appropriate systems to Windows and to create a message pump to handle the OS events.
    • CreateWindow(), ShowWindow() and UpdateWindow() to actually create and show the window.
    • The actual message pump that handles all the OS events.

    So, where do we put that? Well, a fair bit of it could live in our window.cpp file, as a set of file-global vars and functions. And that would work OK. It's simple and relatively easy to read. Let's try that and see what we end up with.


    What's of note here? Well, there's a couple of things. First off, we don't end up passing into the window class any information about the HINSTANCE. Which we need to be able to register the class. But there's a little trick that works well and allows you to get the instance of the current thread:


    That, with one call, gives us everything we need to instantiate our application. However, it doesn't allow us to properly update.

    If you look at the Window::Update method, you can see that I use PeekMessage(), instead of GetMessage(). This is good, because GetMessage is a blocking call; we don't ever return until we get a message. For a game, that's bad, because we still want our application to process, even if we don't get any OS level events. However, this leaves us with havint to find a way to determine when the application has actually terminated. It's a little harder, because we have to resort to using that global s_ActiveWindow to truly determine if our application is live. But it works. And we end up with our application running and behaving as we would expect!

    This, however could be implemented in a cleaner fashion. In my next post, I'll show you how to do that.

    Note that this time around, I haven't posted any code. Mostly because this isn't a 'good' implementation. But the goal for tonight was to get a live application running (window up and visible). And we've accomplished that.

    Dev Zero - Basic Window framework [Part 1]

    Our next step is to get a proper window framework in place.  What do I mean by 'proper'?
    1. Creating an application should be trivial.  All I should need to do is ask for a window to be created (with some simple parameters), get some result back that allows me to access it.
    2. Register a callback to handle some general-case behaviours
      1. The Window has been resized.
      2. We want to change fullscreen modes (start up fullscreen, switch to windowed).
      3. Have an 'update', giving us a delta time between updates.
    3. Clean up upon closing the window.
    That, essentially, is all that I need.  But it has to happen across multiple platforms.
    So, what do I want this to look like? Pseudo code, to the rescue!


    Yes, I know. Greatly oversimplifying the process, I know. But why shouldn't it be that simple? We can add as many handlers as we need to the Window class to get our functionality.

    With that in mind, let's implement it!

    The very first thing that I want to do is generate that Window class. The problem becomes, how do I end up setting the framework up so that creating an appropriate 'MS Windows' or 'OS X' version is trivial?  The answer, surprisingly enough, is to leave it to the linker.

    Here's the deal.  We're going to define a Window class using a header file.  ALL the implementation details will be in a .CPP file.  One for Windows, one for OS X, one for what ever other platform we're interested in. We leave the details of which one to use up to the linker.  Right now, I'm going to use the development environment to set those, but we should be able to set the linker options for which file to link in via appropriate #pragma options.

    Anyway, what we've done is create a 'window.h' file inside the platform folder (wanton\source\platform). For Windows, we create a 'windows.cpp' file inside the SPECIFIC platform folder (wanton\source\platform\mswin). We then explicitly compile and link that file and voila, we end up with a transparent method of dealing with a very platform specific system. At some point in the near future, when I get an OS X version of this ready, I'll be creating an implementation of that inside the OS X folder (wanton\source\platform\osx).

    This isn't a perfect solution; it requires a lot of work in order to keep up multiple platforms. I can see using some third-party tools for generating the appropriate build files (cmake comes to mind), but you'd need something that allows you a fair degree of customizability in order to exclude folders based on the target platform. Not saying it can't be done (I know it can) but that's outside the scope of this article (for now).

    Anyway, getting back on track, this is what we have:

    platform\window.h


    I won't go into detail about the implementation of the MS Windows version of this class just yet (I haven't written it, TBH). However, you should see that I've got a new #include: delegate.h. This is a cool little library that makes adding delegates to your application fairly easily.

    What is a delegate, you may ask? Most who read my blog already know, but in case you are new, a delegate is functionally equivalent to a Function Pointer in C. But you can use methods in classes, as well as regular function pointers. And this implementation is fast. About as fast as you can get. This is courtesy of the code project: http://www.codeproject.com/Articles/13287/Fast-C-Delegate and it's a great little read. These delegates are going to allow me to create the callbacks that I mentioned earlier. You know, once I get the window class actually working!

    One other thing to mention. In getting ready for making this work across multiple platforms, I've added yet another new file to the project, a build_config.h that allows me to set on a per-platform basis, specific configuration options. Here's the contents of the file:

    build_config.h


    That should look very simple to you, until you note that I define a preprocessor define as either being 'ON' or 'OFF'. Those are defined, currently, inside util.h (until I can find a better place). It's worth it to take a look at it:

    util.h


    I like it. I like it a lot. You can find the original article at http://www.codersnotes.com/notes/easy-preprocessor-defines.
    I don't know if I would call them 'easy preprocessor defines', but I would call them 'sensible preprocessor defines'. The win in readability alone makes it totally worthwhile.

    Now that I have that generated, I've stubbed out the windows implementation. It's totally non-functional, but allows us to do a simple test.

    platform\mswin\window.cpp


    I'll be doing a proper implementation in a bit. But for now, I want to test the 'process' in getting a build actually functional.

    However, at this point in time we actually have enough to allow us to generate an app. Not a fully functional app, but something that will run without crashing. Let's put a pin in it now and actually implement our winmain function.

    wanton.cpp


    If you take the code as it stands right at this instant, with these changes, you end up with a 'functional' application that will start, update and immediately exit. Without showing a window. Yeah, that's useless, I know, but it moves us along into the next phase, which is actually getting a fully functional window on screen.

    However, at this point, I'm going to submit the code, again to have a common reference point along the tutorial.

    As with last time, you can find the code on sourceforge here: https://code.google.com/p/wanton/. HEAD will always be a work in progress. I've put the build from this blog post into R01272013B.

    Starting From Scratch - Dev Zero

    One of the things I hate the most is project set up.  I've talked about that in the past, but I want to revisit it today.  Essentially, since this is a re-start of a lot of pieces that I've done in the past, I want to clear the slate, as it was, and talk about some of the things I've learned over this long, crazy journey that has been my career.
    One thing to be clear on.  I'm not going to be working on the OSX version of this until I have the windows basic framework put to bed.  I just wanted to make that clear from the get-go.
    First things first, let's lay out our project directory structure.  To me, that's a significant issue that needs to be resolved at the beginning of any project. I'm going to follow a fairly common project layout, with some small adjustments.
    Since this is going to run across multiple platforms, I want to ensure that each platform has it's own 'solution' folder.  On Windows, we'll be using Visual Studio (2012 for now, I'll backfill into 2012 later). I suspect on Mac it'll be Xcode.  Linux will undoubtably be makefiles of some sort. So, for lack of a better term, the project is called 'Wanton'. So my folder layout will look something like this:

    I'm a firm believer that one should never check in executables; whatever you submit into you revision control system should be able to rebuild without error.  Continuous Integration servers are great for that. They can submit a numbered build elsewhere that you can grab, if need be.  That and it allows for 'verified builds' to go out to the appropriate groups.
    I went ahead and let Dev Studio create the project for me.  It puts it into it's default layout (which isn't optimal for me).  So that requires a little hand editing.  It's fairly trivial to fix up the issues that are created by hand. It does mean, however, that you've got to touch the .sln and .vcxproj files in order to have everything compile correctly.  And it's a huge pain in the ass, the first time you have to do it.  But setting this up right from the start is a huge time saver later. It also makes setting up other build types (Debug/Release) that much easier once you have a baseline to start with.
    That's it for now.  I've uploaded the current build to google code.  There's currently nothing in there that's 'interesting' aside from how the project is laid out.  You can access it here: https://code.google.com/p/wanton/.  The code relating to this post has been tagged as R01272013.  Please note that Head may not match the contents of this blog post (ergo the associated tag).  If you don't speak SVN, I recommend you pick up TortoiseSVN and read up here: http://tortoisesvn.net/docs/nightly/TortoiseSVN_en/tsvn-dug.html
    That's it for today.  I suspect I'll have the next installment ready to go shortly.  Until then, keep it between the lines.

    -Ash

    Haven't been updating like I should have.

    A couple of reasons for this, I think.  Mostly the new job, but mostly because I don't have a good, *base* set of tools to work with.

    What do I mean by that?

    I hate having to rebuild stuff from scratch.  So I've been searching for stuff to make things 'easier' to code in.  So I'll bounce back and forth bewteen C++ and C#.

    Here's the rub.  All I really want (at this point in time) is a simple windows abstraction layer.  Not 'Microsoft Windows', but a simple Windowing UI.

    To be clear, the API only has to create a window, handle resizing/fullscreen switching and be easy for me to inject an 'onUpdate' function/thread.  Everything else, I'll handle.

    So, unless anyone out there knows of a simple library out there for doing this (C++ or C#, I really don't care), I'm going to end up doing that myself.

    Sunday, January 29, 2012

    Settling into the Edmonton Way of life

    OK, so maybe that's a bit premature.  The house is still a shamble, boxes are everywhere, it's Sunday night at 10:00 but dammit, I have a home office all set up again.

    Those of you that have been following me (probably not many since my last post was ... well, let's just say that it was a while ago) know that I tend to be a bit sporadic in my posts.  I've also said in the past that I'm going to try and be a bit more prolific.  Well, with it being a new year and all that, time to see what I can do.

    So, what's gone on in the last little bit.  I've spent time in Toronto, Canada's answer to New York (apologies to New York), did my bit at Ubisoft Toronto (hey guys!) and I'm now back west-ish in Alberta.  Edmonton to be specific.  Bioware Edmonton, to be very specific.

    See, it's a long tale.  One involving friends from way back (GTez, you know who you are) and several attempts to get me out here over the period of five years.  In all honesty, I was starting to feel a little stagnant and needed a change.

    Edmonton is good.  Surprisingly so.  As in "The family mostly likes it here".  The missus is very surprised at how much she likes it.  Even though we're constantly saying "you know, it's cold, but it's not *that* cold" (trust me, -27 in Toronto is very, VERY different than -27 here).

    From my standpoint, work is very good as well.  No more 4 hour daily commutes.  Seriously.  My daily commute now is under 30 minutes. I have a shockingly large amount of free time on my hands now.

    That's where this blog comes into play.  I now see that I have time again to put towards this little endeavour.  And I think I'm going to run with it.

    I'm going to continue on with my investigation into DX11, but I also think I'm going to play around with some other ideas too.

    So, with that, I hope to see you all soon!  And Happy New Year!