Scintillating Snippets: Programatically Adding Content To A Content Project

One of the tools I made for my current project is a model editor.  Basically it can import in .fbx or .x models, and then you can apply my custom effects, set parameters, set textures, and then save it using my custom model format I named “.jsm” (it’s just XML…don’t tell anyone!).  Anyway one of the neat features I wanted it to have was the ability to add a model to my game’s Content project so that you wouldn’t have to manually do it through Visual Studio.  And since the Content Pipeline uses MSBuild, this is easy to do:

// Load up the content project
Engine.GlobalEngine.BinPath = System.Runtime.InteropServices.RuntimeEnvironment.GetRuntimeDirectory();
Project contentProject = new Project();
contentProject.Load(projectFileName);

// Add it
BuildItem newItem = contentProject.AddNewItem("Compile", "Models\\" + modelName + ".fbx");
newItem.SetMetadata("Link", "Models\\" + modelName + ".fbx");
newItem.SetMetadata("Name", modelName);
newItem.SetMetadata("Importer", "FbxImporter");
newItem.SetMetadata("Processor", "ModelProcessor");

// Save it
contentProject.Save(projectFileName);

This is of course the generic version and not the actual code I used, but you get the idea.  The “projectFileName” string should contain a path to your Content.contentproj file in your Content subfolder.  “modelName” would just be a name for your model, minus the extension.    What’s going on is pretty simple:  I load up the Content project using the Engine and Project classes found in Microsoft.Build.BuildEngine.  Then I create a new BuildItem for the model, which I add to the Project.   When I create the BuildItem, the string I send to the constructor contains the path to the model file relative to the .contentproj file.  The first bit of metadata specifies that I want to add the file as a link, not as a copy.  The string specifies how the file shows up in the project hierarchy (AKA, how it will show up when you expand the Content node in Visual Studio).  The second bit of metadata is just a name associated with the file.  Then the third specifies the ContentImporter to use, and the fourth specifies the ContentProcessor to use.

Deferred Cascaded Shadow Maps

For my next sample I was planning on extending my deferred shadow maps sample to implement cascaded shadow maps.  I got an email asking about how to make the sample look decent with large viewing distances which is exactly the problem CSM’s solve.  So I decided to bump up my plans a little early and get the code up and running.  It’ll be a while before I get the write-up finished, but until then feel free to play around with code (PC and 360 projects included).