ACFactory Day 2: ExtendableEnum and XAML Serialization

This is the second part of a series documenting the development of ‘ACFactory’ (ACFabrik in German), an application that generates printable character sheets for the Pen & Paper role playing game Arcane Codex (English page).

You might also want to read Day 1: SealedSun goes WPF.

ExtendableEnum

Talents in Arcane Codex have a number of properties that are best described as enumerations. Unfortunately plain old enumerations are very flat. Translating them (when displayed in a user interface) requires you to wrap each and every appearance in the system. This is why I need a richer enumeration type.

Enter ExtendableEnum, an abstract base class that handles comparison and parsing of enumeration values. An existing enumeration could even be extended by a plug-in, should my application ever implement a plug-in system.

I was, however, confronted with a very annoying problem: type initialisation is lazy. The CLR employs certain “heuristics” to find out when to initialise a type. By default, a type is marked with “beforeFieldInit”, which means that the type is usable before its static fields have been initialised. Of course, static fields are always initialised “just-in-time” when they are accessed. The attribute is not applied when the class contains a static constructor (or class constructor or type initializer). In that case, the type is initialised when one of its members is first accessed.

While this is a pretty good strategy for the “normal” use of types, it might be a problem in XAML-based applications since the ExtendableEnum-parser is used before any of the enumeration values is referenced in code, which in turn means that the corresponding enumeration types had no chance to register their enumeration values with the corresponding registry.

One Solution I have found is the System.Runtime.CompilerServices.RuntimeHelpers.RunClassConstructor method which, well, runs type initializers. I can only hope that the method (which points right into the heart of the CLR) is smart enough not to initialise a type twice. My approach is not perfect as extensions of enumerations are not necessarily included. For a future plug-in system, some sort of InitializeOnLoad attribute could save the plug-in writers day. But my hack works 100% for all non-extended enumerations and that’s enough for milestone 1.

XAML Serialization

Step 1: Make your objects “expressable” in XAML

The “read”-aspect of XAML serialization is much more important as it is an absolute requirement for milestone 1. The tricky thing with XAML is, that you cannot express circular references for plain CLR objects (no DependencyObject). My object model, however, requires two way relationships in some places. For instance: Talents need access to the attributes of “their” hero in order to compute effective talent levels. Now since there has to be a default constructor, the hero reference will be initialised with null, resulting in an invalid state. There is no way to ensure that your object is initialised correctly, as you don’t know when WPF/XAML is “done” with its manipulations.

The only option is to propagate the hero reference down the hero graph once the hero is created, which means that even collections have references to the hero they belong to.

Step 2: Make your objects serialize correctly

Contrary to what people might tell you, XAML Serialization does not come for free. There are severe limitations and not that many customisation options. Here is how I wished I could store my heroes:

<Hero ShortName="Kyle" FullName="Kyle MacDuncan">
    <Hero.Attributes>
        <Attribute Level="8">Strength</Attribute>
        ...
    </Hero.Attributes>
    <Hero.Talents>
        <Talent Level="5">Sword</Talent>
        ...
    </Hero.Talents>
</Hero>

Automatically converting the hero-less Attribute and Talent to their bound equivalents, HeroAttribute and HeroTalent respectively. Interpreting this is one thing. A bit of Voodoo magic and a couple of virgins (read: TypeConverters and the like) would make this work. But as I said, there is no way to tell the XAML serializer to first convert certain values to more serializable equivalents.

So eventually I gave up and implemented  XAML serialization using a pretty nasty hack: All the properties that need processing prior to assignment are loaded off into a xData class (HeroData, TalentData, and so on). This essentially means that I have to implement each non-trivial property at least twice and that extension via plug-ins has become at least twice as difficult. My serialised hero looks like this:

<Hero x:Key="codeHero"
      xmlns="clr-namespace:ACFabrik.Model"
      xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
      ShortName="Kyle" FullName="Kyle Mac Duncan"
      ExperienceTotal="14" ExperienceUsed="12"
      FameTotal="15" FameUsed="10" Encumberment="0" >
    <HeroData LocalLibrary="{wpf:StaticResource defaultLibrary}">
        <HeroData.Attributes>
            <HeroAttribute Level="8" Attribute="Strength" />
            <HeroAttribute Level="7" Attribute="Constitution" />
            ...
        </HeroData.Attributes>
        <HeroData.Talents>
            <HeroTalent Level="7">Alchemy</HeroTalent>
            <HeroTalent Level="8">Attention</HeroTalent>
            ...
        </HeroData.Talents>
    </HeroData>
</Hero>

The HeroData node defines a new attribute: “LocalLibrary”. It is used to map the talent names (and possibly others) to their definition in an external library. This way multiple heroes can share the same talents. LocalLibrary is only required when heroes are loaded as part of XAML resources, i.e. when you don’t have control over the XamlReader.Load method.

The result is a bit more verbose and not that beautiful.

Well, at least it will yield good compression ratios (the “<Hero”-prefix…).

Next Steps

On the data side, the next question to answer is how the file formats look exactly. While I now have the basic capability to serialize my objects to streams, I need to come up with concrete formats for heroes and libraries.

Also, I need to start thinking about the general UI concept. Printing in WPF works via Visuals, so I literally get previewing for free. I therefore include a very basic UI (preview + print button) in the requirements for milestone 1.

ACFactory Day 1: SealedSun goes WPF

This is the first part of a series documenting the development of ‘ACFactory’ (ACFabrik in German), an application that generates printable character sheets for the Pen & Paper role playing game Arcane Codex (English page).

Before I explain why I chose to implement ACFactory in WPF, let me quickly sketch the application’s functionality planned for the first iteration:

  • Read a hero definition from a human-writeable text file
  • Print a sheet that lists all the talents known by a hero

Note that having a graphical UI is explicitly not a requirement for the first iteration. It is not the first character sheet generator I’m writing. The Heldenfabrik (Hero factory, not released) project for instance uses the Prexonite scripting engine to define a DSL used to specify heroes and the same GDI+ based rendering framework (read: bunch-a-classes) as the DSA calendar generator (DSA Kalendergenerator) to generate an almost-A4-sized png. Needless to say, that it was very painful to hard code all the spacings and layout characteristics. I needed something that supported me in designing fixed-page layouts. One solution would have been to write a custom rendering engine that would be tailored to the special needs of fitting content of variable size onto a fixed page. I even went so far as to prototype a possible architecture in F#, only find out that

  1. It is really hard to express complex object models in F# due to the lack of forward declarations.
  2. It is a lot of work to implement automated layout.

So what are the alternatives? What publicly available layout engines exist out there? One obvious answer is XHTML+CSS. XHTML documents are relatively easy to generate (System.Xml.Linq aka LINQ to XML or XLINQ), well understood and can be printed by modern browsers. The problem: XHTML documents are inherently digital and thus optimised for variable sizes. Also the final look depends on the layout engine (read: browser) used to display the document. I don’t even want to talk about the horror that printing from a browser is.

Living in a .NET 3.5 environment I could no longer ignore our little newcomer to the graphical user interface world: Windows Presentation Foundation (WPF). We all suspected, that this user interface framework has more to offer than a ridiculously unpronounceable name and fancy 3D graphics. It comes with layout features web designers can only dream about (one word: Grid). So what’s the catch apart from acknowledging that WPF might be cool?

A friggin’ steep learning curve. You can learn C# without a book if you’ve already worked with the .NET framework (via, say, VB.NET). You can learn CSS, XML, XPath, XSLT without a book given good online tutorials. But WPF is so complex, that it would take you months to harvest even basic knowledge of WPF from blogs and tutorials all over the net.

Windows Presentation Foundation Unleashed (WPF) (Paperback)Since I want to finish the project within 7 days, this was not an option (also, I’m a very impatient person). I needed a book. There were two books recommended all over the internet (Applications = Code + Markup by Charles Petzold) and Windows Presentation Foundation Unleashed by Adam Nathan. Based on the customer reviews I decided to buy the latter (the fact that this one was printed in colour made the decision much easier :-) ).

So here I am, roughly in the middle of the book on page 355 at the beginning of chapter 11 about 2D graphics. One thing I noticed was the alarming number of pitfalls or things-to-remember when coding WPF interfaces. Although the majority of the framework builds on predictable and consistent patterns, there are odd edges here and there such as having to use {Binding RelativeSource={RelativeSource …}} for relative sources as opposed to the uniform {Binding Source={RelativeSource …}. Overall I have the feeling that there will be a lot of reinventing-the-wheel involved as WPF is not as complete as it could (should?) be. Sortable ListView out of the box, anyone?

But wait! Didn’t I forget something? Right: Like XHTML, WPF is tailored towards flexible layouts in containers of variable size. Doesn’t this rule WPF out as the layout engine of choice? Nope: WPF was designed to be resolution independent, operating on “virtual” pixels the size of 1/96th of an inch (or device pixels at DPI=96). I can therefore calculate the size of an A4 page at 96 DPI, which is roughly 793.701 pixels times 1122.52 pixels or 3.77953 pixels per millimetre (Beautiful number isn’t it? :-( ).

Next Steps

Before I start designing the character sheet, I want to have my Business Objects (the hero + his/her talents) to be up and running. I need a format that is human-writeable and can be loaded by my application. I’m currently looking into the object serialization aspect of XAML, which I already successfully used to define a serializable library of talents available to heroes.

XAML (aka System.Windows.Markup) knows how to serialize objects that

  • Have a public default constructor (no arguments)
  • Expose their representation in writeable properties

It’s not that adhering to those rules is especially difficult but it is extremely tedious as immutable objects are essentially ruled out. I like to build my objects (classes) like fortresses, using the type system, readonly modifiers and immutablity to reduce the number of ways an object can enter an invalid state. Designing a business model that serializes to XAML therefor means opening all doors to malicious (and/or stupid) users (developers that use my code). I practically live in the library-writer-world and having to write class that expose their representation the way WPF likes it, makes me twitch.

But seeing how elegant XAML maps XML elements to the familiar .NET objects really makes up for the mental pain I am about to go through. You’ll hear from me.

Continue reading on ACFactory Day 2: ExtendableEnum and XAML Serialization

Is Digital Distribution Flawed?

 

Coding Horror: The Sad State of Digital Software Distribution just opened my eyes.

Jeff Atwood writes about prices of digitally distributed software. Have you noticed, that digital versions normally cost as much as the physical ones? Also keep in mind, that the former actually comes with additional value in the form of a DVD box and a manual. Additionally, the digital version is often crippled with DRM, so shouldn’t those actually cost less?

Even worse: Jeff found occasions where the digital version is actually more expensive:

Instead, I find that download options for commercial software are quite rare. Even when the download option is available, you end up paying the same price as retail or even more. Here’s a typical example. I purchased Titan Quest: Gold from Steam about a month ago. I paid $29.95, which is the standard retail box price. But online discounters sell boxed copies of the very same game for $22.90.

Digital Distribution: $29.95
Retail Copy: $22.90

Titan Quest Gold: downloadable version, $29.95
Titan Quest Gold: retail version, $22.90

Selling directly to the consumer via download means bypassing the entire brick and mortar sales chain. This should result in cheaper prices than retail, not the same prices– and it should never result in higher prices. Paying a premium for the privilege of downloading software is complete ripoff, and yet it happens all the time.

Selling digital copies is very profitable as servers are normally cheaper than retail stores. Now imagine what distribution costs, if the publisher actually owns the online shop…

But is all that criticism really justified? Is there a compensation for the missing molecules in digital distribution? Normally, there is: You can (re-)download your games/software whenever you want, wherever you want. I don’t have to worry about scratching or loosing my Dongle (read DVD/CD).

However, this privilege is not necessarily restricted to digital versions. The retail version of Half-Life 2 is nothing more but a license key paired with a copy of the game. Something I really like, as I must confess that I have absolutely no clue where my Half-Life 2 DVD is. At the same time, I don’t really care because I can always get another copy via steam.

There is an additional advantage: I prefer to play games in their "native" language, should I know it, that is. In most cases, this is English, but not all developers / publishers ship multi-language editions of their games. Oblivion being one example.
With Half-Life 2, this was never a concern, as I just downloaded the english version instead of installing the german one from the DVD.

I suspect, though, that there might be a drawback to these privileges. Half-Life 2 resisted falling into the budget sector for over two years, which I think is remarkable. Valve dictated prices via steam and through constantly releasing new bundles, making it actually quite difficult to get Half-Life 2 alone.

Nonetheless, I strongly support Steam as I does not bind me to those fragile DVDs, though I do not normally buy my games via steam due to the lack of a credit card. It doesn’t have to be just Steam. Digital distribution is the future, especially when it comes to fighting piracy. I, however, will refuse to install an utility for each of the major vendors. Now its just Steam and EA Link, but I am sure, more will follow.