Tuesday, December 31, 2013

REGARDING THE FUTURE OF C# ...

I'll be out of office for a few days and before I go let me post some words about the features I'd like to see implemented in upcoming versions of C# (btw, on my return I'll be posting again about The APE).

A couple of weeks ago on "This Week On Channel 9" series there was a reference to Mads Torgensen's presentation in London regarding "The Future of C#", announcing new features that could probably get implemented in C# 6.0.

So, in this post, let me explain some of the features that I hope they implement in C# in the short/middlle run:

1. LLVM-Like Compiler For Native Code


I talked about this many times, but I think it's a perfect time to mention it again.

So far, if you want to compile MSIL to native code at once, you can use a tool called NGen, which creates a native image of the code for the machine where compilation is being done. The problem with this tool is that its main purpose is to reduce startup times. Meaning? You won't get optimized bits for the whole code; just for the blocks first executed when the program starts.

Imho, we need more ... in this relatively new world of app marketplaces it'd be really handy to count on a model where you can deliver optimized native bits to the device/console/machine where the app would be downloaded and installed, don't you think?

Picture it like this: say you create an app/game with C# for the XBox One (using portable assemblies or not) and compile your source code to MSIL. Since the hardware of the console is the same in terms of main components (processor, memory, etc.) then why not compiling the whole MSIL code to native bits optimized for the Xbone console at once? (either on your side or on MSFT servers' one)

With a LLVM-Like compiler this could be achieved and extended to other platforms. But wait a minute! Isn't it what MSFT is doing for WP8? It sounds like it. But wait a minute, again! Isn't it something like the AOT compilation that can be found in the Mono Framework? If the latter gives optimized bits for whole assemblies per platform then it is!

In fact, many sources mentioned the so colled "Project N", which would be used to speed up Windows 8.1 apps. What is more, a few sources also mention that MSFT is working in a common compiler for C++/C#. I hope it also brings a more performing way to do interop stuff with C++.

True or not, this is a "must have" in order to end the C++/C# perf discussion!

2. "Single Instruction, Multiple Data" (SIMD)


In modern HW architecture, SIMD has become a standard when you want to boost performance in specific operations, in particular, ("vectorized") mathematic ones.

As a mather of fact, C++ counts with DirectXMath libraries (based on the formerly called XnaMath ones) which do implement SIMD, but unfortunately do not support C#.

Again, SIMD is already present in the Mono Framework for Math operations, so why not adding it to the .NET Framework once and for all?

I hope MSFT listen to us ...

3. Extension Properties


We have extension methods, so this is a corolary of it. Today, you can only implement getters (and setters) like this:

   public static string NameToDisplayGetter (this IPerson person)
   {
      ...
   }

Then, why not having something like this?

   public static string NameToDisplay: IPerson person
   {
      get { ... } // You could also add a setter, if needed.
   }

Of course that the syntax in the example above may vary, so I guess you get the idea here. There are several use cases where a feature like this could come handy, including MVVM or plain INotifyPropertyChanged ones.

4. Generic Enum Contraints


Generics is one of my favorite .NET features. There's lot of things that can be achieved through it but it has still room for improvement.

One of the things to improve are constraints. So far, when dealing with types of software elements, we have only two: class and struct. So, what about enums?

Currently, if you want to mimic an enum constraint you will have to write something like ...

   public void OperationX(TEnum myEnum)
      where TEnum: struct, IComparable, IFormattable, IConvertible ... and so on so forth.
   {
      … usual stuff …
   }

... and also, given that you are dealing with a subset of elements that approximate to an enum, you need to check whether and enum has been passed, generally throwing an exception if not:

    if (!typeof(TEnum).IsEnum)
   {
      throw new ArgumentException("The passed type is not an enum");
   }

Why not simplify it to something like this?

   public void OperationX(TEnum myEnum)
      where TEnum: enum
   {
      … usual stuff …
   }

Not only it makes sense, but also would simplify things a lot as well as open a wide range of handy operations and extension methods.

5. NumericValueType Base Class


.NET's CLR treats structs in a special way, even though they have a base class: ValueType.

I'll not be explaining here the characteristics of built-in primitives and structs; instead, I'll ask the following question: in the current version of C# can we achieve something like this ...?

   TNumeric Calculate(TNumeric number1, TNumeric number2, TNumeric number3)
     where TNumeric: struct
   {
       return number1 + number2 * number3;
   }

The answer: not without proper casts. So, a life changer for this type of situations would be to add a specification of ValueType that enjoys the benefits of structs and also supports basic math operations without any kind of wizardry: NumericValueType.

With that class and a new reserved word like, say, "numeric", "number" or "primitive", we could write generic operations and extension methods with a syntax as simplier as:

   TNumeric Calculate(TNumeric number1, TNumeric number2, TNumeric number3)
     where TNumeric: numeric
   {
       return number1 + number2 * number3;
   }

How about declaring new type of numbers? Easy ...

   public numeric Percentage
   {
      … usual stuff …
   }

... or ...

   public numeric Half
   {
      … usual stuff …
   }

No need to specify "struct" since "numeric" would be a value type that supports basic math operations (that we would need to implement when we declare the type, maybe, by overriding some base operations), and so in common scenarios there would be no need to cast values to do math.

6. Declaration of Static Operations On Interfaces


Put simply: having the possibility of declaring static operations when writing interfaces; like this:

   public interface IMyInterface
   {
      static void DoStaticOp();

      static bool IsThisTrue { get; }

      ... instance properties and operations ...
   }

This presents a challenge to both, polymorphic rules and abstract declarations, that is, at a "static" level. But as usual, with the proper rationale and care when modifying the language specs, it could be achieved. Maybe, many of you would be asking: "why bother?" but believe me when I say that I happened to meet situations where static operations on intefaces would have come really handy.

Well, this is it for today. What would you guys like to see implemented in C# 6 and beyond? Comments are welcome.

See ya when I get back,
~Pete

Thursday, December 19, 2013

THE ASSET PIPELINE EDITOR - PART 6

After a short break to do some marketing about the APE (sigh!), it's time to resume posting so the turn goes to a couple of recent additions I implemented into the core functionality:
  • "Direct" build (what?), and
  • Asset Packagers (oh yeah, baby!)
These features have been requested by some of you, so here they are ...

Direct Builds


In part 4 of the series I mentioned that there were two actions when compiling assets, the first one was "build" and the second one "copy/move", and the way to indicate whether to copy or move assets was by (un)checking the following checkbox:


Well, as a corollary of the command-line tool "APEBuild", a new third option may take place: direct build. Now you can indicate the APE to compile assets directly on the output folder instead of doing it on the "local" folder. In short, it's a way to reduce steps. No need for move or copy.



So, you will have three options from now on: "Copy Assets", "Move Assets" and "Direct Build". Needless to say that the "Default Copy Action" field ("Copy Always", "Copy If Newer" and "None") will be only enabled when "Direct Build" is disabled and that this feature can also be used with APEBuild.

In the picture above, if you look at it carefully, you will have a preview of what I'll talk next ...

Asset Packagers


Throughout the years, as a moderator in the creators' forums, I read many questions regarding the possibility of zipping your whole content folders. Recently, it has been brought to my attention (thanks again Javier) that some authorware offers the possibility of compressing all output into a single zip file.

Guess what? Now you can also do it with the APE!

How come? Simple ... you create your own packager (where you can use any of the compression techniques available in .NET 4.5, use third-party libraries or add your-own compressor) and when you plug it into the APE, the latter will show it as an option on the General Settings tab:


By default, as usual, there is a "pass-through" packager built-in, named "No Packaging", which we can use for the cases where no zipping is required. 

So, when you create/load a solution, its panel will look like this:



We can then select the packer along with the writer to set as the default one for the solution (which of course, can be overriden per project). But that is not it ...


The picture above shows a new field to set in the Project Settings tab: "Pack To". By default, that field will initially equal the path assigned to the "Copy To" field, that is, the output path.  But you can change it, in case you need to have a different target directory for the zipped file.

This opens a new set of possibilities since selecting a packager won't disabled copy/move operations, and vice versa. So, if you decide to copy assets and also create one huge compressed files for the whole structure, you can set a different path for the packed files and presto! Do you want just the packed files? No problem, set either the direct build or activate copy/move actions with "None", and you will only get the zipped file.

As I say, you can build, build+copy/move, build+package, build+copy/move+package, direct build, direct build + package. Pick the right combination for your project's need.

Please notice that the packaging action is meant to apply to a whole structure of assets and not to each asset individually; in other words, alike assets writers -which affect each raw file individually as part of the import/export process even though they are applied per project, asset packagers affect a structure of folders and asset files per project. Say you have a folder named "Content" with all the asset files built in the last execution of the command, then this folder is the one the packager will take as a reference to create and output the compressed file (or the compressed files you decide to output).


Last but not least, the "Writers" tab has been renamed to "Output Providers" given the fact that it now includes a configuration panel for packagers, where you can select the packager to use per compilation profile and configure its properties, if any is available.

In the example above, no packaging is set for the Windows target platform and the "Debug" compilation profile. Plus, since this default packager is a pass-thorugh one, there are no public properties you can tweak.

And again, this feature is automatically included in APEBuild!

To sum up ...


With these two additions, the APE now covers several use cases: from usual ones to the weirdest! Thus, I am eager to see what you guys come up with when the first released version of the APE gets launched ...

Btw, I continue working on this handy solution as we speak, so new and exciting features are added on a daily basis.

We are close to start the campaign at IndieGoGo so I hope you stick around!!!

'till next post,
~Pete

Friday, December 13, 2013

THE ASSET PIPELINE EDITOR - PART 5

In this part of the series I'll answer some of the questions that some of you've been asking me lately, in particular:

  • Does the APE watch source files?
  • Is there a command-line version of it? And
  • Why not publish it as open-source?
I attempted to give brief answers to a couple of them in this thread at GameDev, and also by email to the guys behind the WaveEngine, but I think they deserve a post here with further details.

So, let's begin ...

Does the APE watch source files?


To aswer this question, I need to explain what happens when a new solution is created and saved.

Basically, after saving a solution you will find the following structure on disk:

   + Root Path
      + [Solution's Name] folder
         - [SolutionFileName].fps
         + "Sources" folder
             - sourcefile1
             ...
             - sourcefileN
         + "Projects" folder
            + [Platform1's Name] folder
                - [ProjectFileName1].fpp
               + "Builds" folder
                  + [Profile1] folder
                     - output.fpb
                    + Content folder
             ...
            + [PlatformN's Name] folder
                - [ProjectFileNameN].fpp
               + "Builds" folder
                  + [Profile1] folder
                     - output.fpb
                    + Content folder

The APE creates a folder named "Sources" which will be used as a "local" repository for the whole solution. Within it, you will only find files (no folders). Thus, when you add a new file to any of your projects, the APE will copy that source file to the respository and create the corresponding raw file to the strcuture of your solution.

Following this rationale there is no need to dynamically watch file changes. Why? Simple, if you manually change one of the source files directly then the next time you build content that source file will be used to build assets provided it complies with the condition indicated for building: Always|New|None.

In other words, the APE watch changes over an existing source file only at the moment that new builds are requested. If a project is marked as "Build Always" then no matter what, all included raw files will generate a new asset file. If a project is marked as "Build If New" then only raw files with new source files assigned will end up having a new asset file. Finally, "None" will exclude the project from the build process.

Now, there was a second part in the question posted on GameDev's forum with had to do more with the processing-side of things than with what I've explained above.

The APE will NOT replace production tools like Photoshop, Sound Forge, and so on so forth. So you will need to create your source files there: jpegs, wavs, mov, etc.

What the APE provides is a way to indicate how to process source files to get the file format you need for your games. In case the built-in import/write units or the ones provided later on by me and or any other user are not useful to you, then you can implement your own with full control over them.

So, if you guys want to implement a processor that converts WAVs into OGGs, you can go ahead and do it with ease. What about resizing a texture? Sure. What else? Everything you can imagine of that can be achieved by setting parameters on a property grid.

For example, for the case of XNA'ers, in part 4 of the series I showed a processor with many features that pre-multiply alpha, resize textures, change formats and so on.

So to sum up this part of the question, to create source files you will need to use production tools. But to import them to your games with as asset files with given format, you can use the APE.

Is there a command-line version of it?


Yes, there is! And it's name is "APEBuild" (thanks Javier for suggesting the name!).

When I designed the APE I took into consideration server-side-like use cases. As a matter of fact, it resulted as a corolary when I develop the base test assembly for import/write units (please refer to part 1 to see an image of it).

In the current state of this command-like tool, only two actions can be executed: either you build an entire solution or only a set of projects. Let's have a look of the structure ...


The picture above shows what you get when execute the tool with no parameters (and also with wrong parameters).

So, if you want to build a solution, just execute the tool with one parameter: the path to the solution file. And if you want to build some of the projects in the solution, then add "p:" as an argument, followed by the names of the target platforms, separated by a comma. See the example in that picture.

Now, there are a few restrictions: first, the solution filename must always end with ".fps"; second, the tool will handle trimmed versions of the platforms' names; third, all passed platforms must exist in the solution or the tool won't execute; and fourth, when you pass a relative path to the solution, the path to the folder where APEBuild is located will be considered the root folder in order to build the absolute path.

So, when we execute the command for the entire solution we have been using as an example on the series, this is the result for a successful build:


And when you execute the command for a couple of pojects, the result would be the following:


You will also get messages in case of warnings and exceptions:


The above picture shows a warning indicating that an import unit that should have been plugged into the tool as an add-on is missing. However, since it's not used during the build process, the latter runs normally.

So, it is important to remember that:

1. Before executing the command you will need to check that all the import/write units are present in the corresponding folders associated to APEBuild (as you would also do with the APE's editor), and

2. When you commit source files, you will also need to commit the updated versions of the APE's solution/project files to the server or otherwise you won't get the results you were most-likely looking for.

There are some features I'd like to add in future versions like, say, verbosity control (that is, the level of detail you get as output), but the tool gets the job done in its current state, what is really handy!

Why not publish it as open-source?


I'd have prefered to address this question more close to the campaign's launch date, but since a few of you've asked this question recently, I decided to answer it now.

But before moving forward, I'd like to state that I will neither argue nor open a discussion regarding whether open source is good or bad business-wise, since that depends on factors whose relevance may vary per person (yes, "YMMV") and therefore not only does it lay beyond the scope of this post but also I don't feel like pursuing a Phyrric Victory.

Instead, I'll be posting a few words explaining my decision to publish it as a commercial tool in the near future -that is, provided the campaign at IndieGoGo succeeds.

Honestly, I haven't decided yet the price for a license but I intend to license the APE per seat per platform per major version. Yes, if you buy one license at launch, you will be able to use it for the whole v1.x! No annual subscriptions, no different versions for indies/pros, no complications to anyone.

Now, although the price is not yet decided, believe me when I say that it will be low and even lower for those of you who decide to contribute to the campaign at IndieGoGo. I'm an indie, so I know what it feels not being able to afford licenses from time to time. So during the campaign it'd be like going out with some folks to a movie theatre, say, on Friday's night.

So, why this decision?

First, open souce is difficult to keep alive in time. You need to coordinate efforts, check contributor's code, handle branches, even maybe, at some point and to some extent, include contributors into the decision-making process.

But that is not it, most of the people in the team would likely have daytime jobs, so development of updates to the tool would be done during the night provided the is some spare time left. Going to college? Does your job demand most of your productive time? Have a wife/husband? How about some kids? Then, you know the drill ...

It's not a surprise that many open source APIs and tools eventually follow the commercial route, or that their owners publish a letter indicating why the cannot continue working on it or that updates will slow down. It's completely understandable! There's lot of time, effort and even money put into it, and even though donations could be received, the latter eventually end up being not enough to even cover costs of production. Not to mention, costs of living.

So, instead of trying the open source route first to then follow the commercial one, I prefer to skip that part and commercialize licenses of the APE from square one. Succeeding in this task will assure the continuation of the tool since I will dedicate, not my spare time, but my production one to make it happen. And if I fail I'll continue to use it as is for inhouse projects. No hard feelings.

I have one more thing to add in this respect as an example: the guys behind the Mono Framework started the project as a non-profitable endeavour. But then, they realized that in order to continue offering the products they loved to develop, a change in course was imminent. For many, this could have been a change in principles but for me it was a wise decision. Today, they're successfully runnning Xamarin, they're growing strong and their products are a must have for every serious dev that want to port .NET-based apps/games to many platforms. And even MSFT recognizes it!

Btw, regarding XNA's Content Pipeline: it was freely available as long as you didn't want to develop games for the XBox 360 (and then, the Windows Phone). Otherwise, you had to pay an annual subscription for the Creators' Club and a registration fee for the Windows Phone (both now unified).

So to wrap up this third question, before using the word "disappointing" -given the fact that it won't be open source, please give the APE an opportunity to show off its key features and wait for the campaign at IndieGoGo. You won't be dissapointed!

Ok, this is it for this part of the series. Hope you all come back for the upcoming part 6 next week.

See ya next time,
~Pete

PS: btw, I recommend you to have a look at Xamarin's subsciption plans if you haven't yet!

Wednesday, December 11, 2013

THE ASSET PIPELINE EDITOR - PART 4

On part 3 of the series, I talked about some of the features related to solutions and projects. So now it's time for me to refer to another key feature of the editor: building assets.

The picture below shows the last state of the solution we were using as an example for the series:


Let me remind you that the raw files named "bkgClouds" were bound to different source files: one sized 640x400 texels and another sized 320x200 texels.

Since the APE does not come bundled with any import/write units other than the pass-through ones, y clicking in one of the raw files we'll get the following view on the raw file tab:


Thus, as you can see, the pass-through importer is assigned by default to all the raw files in the solution. This default importer has no properties we can modify since all it does is to copy the source file associated to each raw file to the destination folder without any kind of processing/formatting.

However, there is one property that I'd like to highlight here that I didn't mention on my previous posts, and that is the checkbox named "Build Asset ?". If you have been following the series then you'll likely remember that for solutions and projects you could indicate the actions to execute for building and copying/moving, right? Well, this checkbox allows us to override those settings for a specific raw file, so if we unmark it, no build/copy actions will be applied to that raw file.

In fact, if you carefully look at the first screenshot above corresponding to the solution tree, you will notice a checkbox beside some of the nodes. By checking/unchecking that control not only we can include/exclude a raw file for build/copy actions but also the nodes of an entire folder or container. And yes, when you save solutions and projects, this selections are also persisted. Nice!

Now, how can we build an entire solution or a specific project? Glad you asked. Please take a look at the picture below and follow the numbers:


First, for each project at a time, check the Project tab and select the corresponding values for each field. In particular for this example, we need to set the build/copy actions and indicate the correct path to copy/move the asset files. For now, we disregard the Group Id field and the writers grid since we have only one writer we can use at this moment and thus we have no use for the former.

Second, we indicate which nodes among the containers, folders and raw files must be included in or excluded from the build process by checking/unchecking the respective checkbox.

Third, we select the correct writer for the project ("Default Writer") for the compilation profile to use ("Debug", as shown in the picture above).

Fourth, we select whether to build the entire solution (that is to say, all projects) or one project (the one shown in the Project tab). Also, we indicate the target compilation profile (the one that corresponds to your game's executing assemby, as compiled in Visual Studio, Xamarin Studio, Eclipse, Netbeans or other).

Having done that, we also need to indicate for the solution whether we want our asset files copied or moved to their final location ...


Then, we are ready to go. So all we need to do is compile the solution or project by clicking the "Build" button (the arrow in green).


You can also build the solution or project using menu options, "F5" for the entire solution or "Control + F5" for the selected project.

Now, what result shall we obtain for our example? To see that, we pick one of the projects in the solution explorer and open its folder with the "Open In Explorer" menu option, say, the iPhone.


You will get as an asset file a copy of the image sized 320x200 texels. And believe me when I say that if we built the entire solution (or only the Windows project) we also get the image sized 640x400 texels as an asset file located in the path corresponding to the Windows project.

But this isn't all we get as the picture below shows:


The Ape mantains a repository on the corresponding path for our solution, but is also moves/copy the obtained files with the correct path structure to the location you specify as an output folder, adjusted for the corresponding compilation profile. Since we said we wanted all our asset copied, the "local" repository keeps a copy of all asset files. Otherwise, no local copies would exist.

Again, when we compile the solution we also obtain the asset for non selected projects -provided they are alos marked for build + copy/move actions.

Now, when your game expects a file with a specific format (other than public ones like png, jpg, wav, wmv, and so on so forth) and or a specific file extension, then the above example is not useful for you. Therefore, for the following example I'll use a Texture2D importer and a XNA-like writer for a Monogame project. But please remember that you can use the APE for any game engine not related to XNA/Monogame, provided that the corresponding import/write units are plugged into the editor.

So, allow me to introduce you to a nice feature that the APE has: clean solution/project.



Both operations are similar, being the only difference that cleaning the solution will clear the content of all projects. This operations must be used with caution since they will delete the entire content of the folders indicated in the corresponding lines and not only raw files and nested folders. So before pressing start we should check that the paths are right. You can always cancel the operation by clicking the cancel button or by closing the window -in case you need to. And you can indicate whether to clean one folder (the local folder or the output folder), both folders or none. This is indeed a handy and powerful feature, don't you think?

Ok, after cleaning the solution and adding the corresponding import/write units to the editor we are now able to reload our solution and once we get it, we need to get something like this:


In order to get it, first we need to select the only raw file we have on the Windows Project. Then, we need to select the category "Textures" (1) and finally select the importer named "Xna Texture Importer" (2), which in this case is selected by default. As you can see we get some information about the importer and, in this case, a couple of read-only properties ("Group Id" and "Is Source File Also Copied ?").

As a result of the above we can now realize in practice how the Group Id field on the Project tab can be used (3): a value of zero indicates that we want to target XNA/Monogame's HiDef profile and a value above it the Reach profile.

If we expand the panel with the properties for the 2D Texture Processor we'll get:


I won't explain each of the fields you see there. Some of them are similar to what we had on XNA's CP GUI but there are some additional ones -which I believe speak for them-selves. All I can say is that this is not a mock-up; in fact, it's a real processor in alpha stage currently consuming WPF's bindings for WIC. During the campaign at IndieGoGo I'll give more details about this.

After tweaking some of the parameters, let's have a look at the formatter:


Nothing to do here. The "Xna Binary Formatter" will give the proper format to the asset data but with one difference for those of us accustomed to XNA's CP (given the way I've implemented these import/write units): the XNA's header for the asset file is not included as part of the format. That will be added by the writer later on. Needless to say that you can design your import/write units so that the formatter includes the header instead of the writer, which is fantastic given that it shows how flexible the APE really is!!!

Ok then, and please again follow the numbers, before proceeding to compile the texture asset for the Windows project we'll need to get something like ...


First, we select the Window project.

Second, we need to set the proper writer for the compilation profile we are going to use (in this case, for "Debug").

Third, we need to select the "Normal" compression mode on the Writers panel instead of the "Automatic" one that is shown in the picture above. Why? Because I haven't implemented yet the so called LZX compression -which is a real pain, believe me- or any other compression for the writer.

I'd like to add a side note here: do you notice the data displayed on the writer panel for the Xna Writer? (default, version, etc.) In particular check the following three: "Writes checksum", "Requires password", "Encodes Data". These fields if marked as "Yes" indicate that the writer May or May Not do the associated task (depending on whether is activated manually/automatically as implemented by us), like calculating an writing an MD5/SHA checksum somewhere into the asset file, adding password protection and or encoding/encrypting the asset file. And if marked as "No" then the writer does not support that action.

Fourth, and this is really important: we need to save the solution!!! (this is required to apply changes)

Fifth, we need to indicate that we're going to build only a project (the selected one) for the "Debug" compilation profile.

Finally, build the assets by pressing the corresponding menu option, button or keyboard shortcut ("Control + F5"), being the result in the local repository the following:


This is a well-formatted xnb file with pre-multiplied alpha, a mip-mapped chain and its top-most texture resized to the nearest power-of-two value for 640x400 texels (I leave the answer to the latter as homework for you). Since this asset file is not LZX-compressed, its size on disk is rather high. Again, a copy of this file is located on the output folder that the XNA/Monogame solution uses.

Finally, if we run the game's solution with a line like the following within the method of the LoadContent operation ...


   this.texture = this.Content.Load<Texture2D>("textures/backgrounds/bkgClouds");
      

... and the corresponding one on the Draw method, as shown in the trailer for the APE, we'll get something like this on a WindowsGL-targeted game using Monogame (and please don't ask me "why do you need mipmaps for this example?"):


Enough said!

In the following parts we'll be getting into more technical stuff.

Cheers!
~Pete

Tuesday, December 10, 2013

THE ASSET PIPELINE EDITOR - PART 3

On part 2 of the series, I talked about some basic features of the APE, so it's time to show how to change the structure of a project and populate it with some raw files, that is, before starting to build assets.

I could begin this post by telling you how to create a new solution from scratch, but instead, I'll show you a nice small feature the editor has that allows you to open recent solutions, which spares you from having to use the Open Solution menu option ("Control + O") and browse folders until you locate the solution file.

Recent Solution List

Do you notice the small red (almost transparent) cross beside the only entry in the list of recent solutions? If you press it, you will be prompted to confirm entry's removal from the list. The cool thing is that APE does not need to restart in order to refresh the list. Ditto for "Clear All ..." option.

Once the solution is loaded we can start modifying the tree structure to meet the needs for our game. This is how the solution looks like so far:

The Solution So Far

Let's add a couple of nested folders to the Windows_Own container by selecting the "Add Folder" menu option (or clicking "Control + Shift + F") twice. Now our solution looks like this:


By default, folders will be created with the name "folder_<#>", so let's renamed them with a meaningful word (by double-clicking the node):


Better, right? But wait a minute! What if we want to have a similar structure on the default container? All you have to do is open a context menu for the node you want to copy (right-click over "textures") and you will be presented with this:

\
You have two options there: either you move or copy the node and all of its content to another non-nested location; in this case, to the Windows_Default container. Note: if you try to move or copy the "images" folder into the "backgrounds" folder the operation will fail.

Since we want to replicate the structure, we then select the copy option. Then, by opening the context menu fro the default container we will get the following:


By pressing paste, the new structure for our solution will look like this:


It's important to mention here than we could have obtained the same result by using drag'n'drop. Yes! Dragging the textures folder and dropping it onto the default container would have been allowed. In fact, when you drag'n'drop nodes in the solution explorer, the APE asks us what we want to do with them: move, copy or cancel.

Also, it's worth mentioning that, in this case, we could have copied the whole content of the self container ("Windows_Own") by using the context menu for the container. That is also allowed. The difference is that in this case the container it-self won't be moved or copied, just its child nodes.

Now, let's add some raw files. Shall we?

There are three ways to add raw files to containers or folders: (a) you select the container/folder and then use the "Add Raw File" menu option/button (or press "Control + Shift + R"), (b) you select the container/folder, open the context menu for it and click on the  "Add Raw File" option, or (c) you use drag'n'drop (you can import raw files into your solution by dragging them from the explorer and dropping them onto the container/folder).

In the picture below, you can see how to use the context menu for the target folder.


One important feature to mention here is that you can import more than one file at a time (batching) with any of the three ways the editor offers, including drag'n'drop.

For the example, we just added a nice cloud background to the backgrounds folder:


The picture above shows a lot of new information about the editor:

1. The name given to the added raw file is its filename (without the extension, if any). This is true provided that the name does not exist in the same "relative" location of the solution's structure, or else it will be renamed to "file_<#>".

2. On the container tab, the editor will show you the proper previewer for the file (remember that if none is found it will just show the system icon for it).

3. A new tab gets enabled: "Raw File". Here is were you tweak import settings for the raw file. The APE will try to assign an importer to it based on the file extension, giving priority to the importers marked as default (more on this on later posts).

4. The source file is copied into the "Sources" folder for the solution. This folder works as a repository for the entire solution, so you cannot have two source files co-existing with the same name on the folder since one of them will be replaced. This has nothing to do with the names you give to the nodes on the solution explorer (you can have two nodes with the same name in different "relative" locations on the solution tree).

In order to change the name of the raw file we could do it in the same way as before by double clicking on the node, but in this case we will use the "Name" field on the raw file tab and rename the node to "bkgClouds".

Now, before showing you how the structure of the solution currently looks like, let's add a new project for, say, the iPhone platform. And here it is ...


As you can see the default containers on both projects have the same exact structure; however, the self containers are different. In effect, that is the purpose of self containers.

Although the "bkgClouds" raw file is present in both default containers, it is treated as a deep copy; so mirror operations are bound only to add/remove/copy/move. For properties, like importer, processor and formatter-like settings, each node is independent, so you can have one set of settings for the raw file for the iPhone and a different set its sibbling on Windows. Really great!

Now, what if you want to import two different source files but keeping them under the same raw file on different projects? Let me translate it with an example ... say that you want to replace the source image for bkgClouds but only on the iPhone project with a lower_res version, well ... yes, you can! How? Simple. Look at the picture below:


On the Raw File tab there is field named "File" with a button labeled "..." (marked all in red), which shows the location to the source file in the solution. When you click on the button you can browse your folders until you get the file you desire.


In this case, we'll select the 320x200 texels version of the cloud image for the iPhone platform to get this window:


The APE will prompt us to confirm the operation and also it'll let us delete the existing source file if needed. Since this is not the case, given that we need both of them (one for Windows and the new one for iPhone) we let this checkbox unmarked.


Once the operation completes, the image previewer for the "bkgClouds" raw file on the iPhone project will show the new information. Now we have two different source files for the same logical name. And therefore, after building assets, when you load the "bkgClouds" texture on your game, you will get the 640x400 version on Windows and the 320x200 on the iPhone. No need to add "_640x400" or "_320x200" to the load operation.

Let's have a look at our solution's Source folder:

As you can see, the respository has both source files for the same raw file. And I guess that you now fully understand the difference between "source" and "raw"" file (if not, the former is the actual file and the latter its representation on the solution's tree).

Ok, before finishing this post, let me show you one more relevant feature the APE offers. For this task, say that you accidentally messed with the Source folder and deleted one of the images; for instance, the one ending in _640x400. What would happen? Well, when you re-open the editor, you will see the following:


The APE is indicating you that the solution is corrupted and also marks the path to the offending raw file. To fix it, you can either manually copy+paste the source file to the Sources folder or you can use the Raw File tab -as we did before- by clicking the "..." button beside the "File" field and browsing to the location of the source file.

In order to valdiate the solution you have to options, either you save, close and re-open the solution (in which case the APE will warn you that you are attempting to save a corrupt solution) or use the validate menu option ("Control + Shift + V") ...


Having finished the validation processed, the editor will look like this:


So, we can now safely continue to work normally with our solution and save it whenever we want.

Btw, you can browse to the folder where you solution is located by using the "Open In Explorer" menu item (ditto for projects) ...


And you'll get to ...


Do you notice the icon on "MySolution"? When the editor is closed you can open it and also load the solution by clicking its file. Indeed. The APE will open and load the solution for you.

Ok guys, this is all for this post. On my next post we'll talk about building assets.

See ya!
~Pete

Monday, December 09, 2013

THE ASSET PIPELINE EDITOR - PART 2

Continuing with the second part of the series, and before writing about technical stuff (the coding side), let me introduce you to the editor it-self.

When the Ape starts, the editor looks like the picture below:

Main Window

By default, the only tab that is enabled is the one named "General", where you can configure general settings to control the editor's behavior. There are a few options that speak for them-selves, like "Automatic check for updates", so I will refer to others which I believe deserve a few words since they will affect each solution/project created in a cascade manner:

1. Default Main Folder: every time you create a new solution, this is the folder that will be shown by default on the Folder dialog. Think of it as the directory that will hold your solutions and projects.

2. Default Root Folder: for every project created, this is the relative root folder assigned by default to each container. For those like me who come from XNA-based games, this is usally set to "content".

3. Default Build Action: this is the action to execute when building assets from raw files in solutions/projects, which can be "Build Always", "Build If Newer" and "Do Not Build".

4. Default Copy Action: this is the action to execute when copying assets after a build action finishes on a project, which can be "Copy Always", "Copy If Newer" and "Do Not Copy". You will see later that this also refers to "moving assets".

5. Available Platforms: this is the platforms that a solution can support and you can add/remove custom platforms to the ones provided by default. The one marked with an asterisk "(*)" indicates the project that will be automatically added when a new solution is created.

6. Default Writers Per Profile: this control has two purposes; you can add/remove/modify custom compilation profiles as well as the write units assigned by default to each and every one of them; again, the compilation profile marked with an asterisk "(*)" indicates the one that will be selected by default when a new solution is created.

Add Compilation Profile Window

When you add a new profile, you can set its name, the relative folder where assets will copy/move when built, and the default write unit for it. We'll get to the concept of a write unit on a later post.

7.  Default Importers Per Category: every import unit corresponds to a category (that you can set when creating the importer), so what you can define here is which will be the default importer for each category. When you add a raw file, the editor will find the category it fits in and from there it will try to assign the default importer; if no importer is found, it will move to a default category and importer (pass through).

Note: both, import and write units are plugged into to the APE as add-ons, so when you execute the tool, the editor will automatically create the collection of available import and write units.

8. Save/Reload Settings: when you change general settings you have to options: either you save the settings for future use or you reoad settings previously saved; if no settings are found (or saved settings get corrputed) the APE will generate and save default settings for you.

Now, what are Solutions and Projects?

A solution is the root node in the APE's logical tree which will directly hold projects as its child nodes. In other words, is the root node that will contain asset projects.

A project is the node that will contain the structure that will be used to build assets for a specific target platform. You can have as many projects you want on a solution but only one per target platform.

When you build a solution, all the project it contains will be built (unless you specify not to build one or more projects). Conversely, when you execute the build action on a specific project, the other will remain intact.

In order to create a new solution, you can open the "File" menu and select the "New Solution" option, click on the "New Solution" icon on the main tool bar, or press "Control + Shift + N".

New Solution Window

When you do that, a pop-ip window will prompt you to enter specific information like the name to give to your new solution, the folder where the solution file will be saved, whether a subfolder with the name you enter must be created or not and the "Output folder".

The latter is quite important since it indicates the path to the root folder where all assets generated for the default project will be copied or moved. It works like this, say you have a Visual Studio solution for a game you are developing (or a repository for the assets, not the raw files- to be used); you browse to this path, you select it, and from there the APE will append at build time the relative folders corresponding to the selected compilation profile as well as to each container, when it corresponds.

The initial structure of a solution is the following:

Initial Structure Of A Solution

Being the only project created the one that corresponds to the target platform inidicated as the default one on the general settings.

As you can see in the picture above there are two more nodes that are created by default within the project: the initial containers ending in "_Default" and "_Own".

The former holds raw files shared with all projects. Thus, when you add a new raw file to that container, a new node will be also added to the default containers in all remaining projects, with the same name.

And the latter holds raw files assigned only to that project. So, this container is where you put raw files that you don't want to share with other projects.

Now, there is a third type of container: partial containers (to which I also refer sometimes as "shared" containers).

Add New Shared Container

Say that you have three projects in the solution (Windows, XBoxOne, PS4) and you want to share content on the first two (Windows and XBoxOne); well, in order to do that you create a partial container for the windows project, add the XBox One platform and presto!

To add more projects to your solution you either select the "Add Project" item on the "Solution" menu, you click the "Create Project" button or press "Control + Shift + P".

Add Project To Solution

Again, you will be prompted to specify the output folder for the new project.

Ok, moving on ...

When you create or load a new solution, you will see that other tabs will get enabled: "Solution", "Project" and "Container".

Many options in the Solution tab are similar to the ones found in the General tab; in fact, this is where you start to benefit from the cascade approach given that you have the possibility to override the default values given to each "shared" option.

Solution Tab

But there is one more relevant option you can set for a solution: "Move Assets". The only explanation I will post for now is that when you build assets, the APE save them on a specific repository for each project and then, copy or moves each asset to its final destination folder (the one located in the output folder for a project).

For projects, the logic is the same as before, tweak parameters to override default values coming from the solution or general settings.

Project Tab

Here you can also indicate:

1. Group Id: even though you can set different behaviors per platform, you can also indicate affinity among specific platforms in order to set the course of action for import/write units. For instance, for XNA-based projects, and id of zero ("0") would mean a "HiDef" profile meanwhile one ("1") or above would mean "Reach" profile.

2. Copy To: remember that for new solutions you had to sepcify the output folder for the initial project? Well, you will have to do the same for the new project. So, each project can have its own output path, which is strongly recommended so that you avoid the risk of overwriting asset files.

3. Default Writers: not only you can override the values that come from the solution or general settings, but also you can change the folder that will be added to the output path when building assets for a specific compilation profile (like Debug, Release, etc.).

Regarding the Container tab, there is no much you can do there other than change the root folder, which is initially set to its default value (usually, "Content").

Container Tab

For default and self containers, names cannot be changed. For partial containers, you can set a different name, and you will also get a list of the projects it shares content with.

There is another tab that is also activated when a solution is created or loaded ("Writers") but I will refer to it on my next post.

Before reaching the end of this part, I would like to refer to the search tool, which you can use when you want to find nodes in the solution that start with a specific character or group of characters ("Control+F").

Search Tool

The beauty of this control is that you can do a new search recursively, that is, on top a previous search. So if you first search for "Windows" and then for "myImage", you will get all the nodes (and its children) that start with "myImage" within the nodes that start with "Windows". By the way, the top-most node (the solution) is not considered for this feature, so the result it would have been the same if you had entered "my" instead of "myImage".

By pressing the "Reset Search" button or "Control+Alt+F" the whole solution is again displayed on the explorer.

This is a powerful tool and I'm planing to extend it with additional features in the middle run.

Well, that's it for now. On part 3 I will talk about adding raw files, compiling projects and a few more useful features available on the APE.

Stay tuned,
~Pete