<?xml version="1.0" encoding="utf-8"?><?xml-stylesheet type='text/xsl' href='http://badcorporatelogo.spaces.live.com/mmm2008-07-24_12.50/rsspretty.aspx?rssquery=en-US;http%3a%2f%2fbadcorporatelogo.spaces.live.com%2fcategory%2fXNA%2bGame%2bStudio%2ffeed.rss' version='1.0'?><rss version="2.0" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:msn="http://schemas.microsoft.com/msn/spaces/2005/rss" xmlns:live="http://schemas.microsoft.com/live/spaces/2006/rss" xmlns:dcterms="http://purl.org/dc/terms/" xmlns:cf="http://www.microsoft.com/schemas/rss/core/2005" xmlns:wfw="http://wellformedweb.org/CommentAPI/"><channel><title>BadCorporateLogo: XNA Game Studio</title><description /><link>http://badcorporatelogo.spaces.live.com/?_c11_BlogPart_BlogPart=blogview&amp;_c=BlogPart&amp;partqs=catXNA%2bGame%2bStudio</link><language>en-US</language><pubDate>Mon, 06 Oct 2008 01:13:06 GMT</pubDate><lastBuildDate>Mon, 06 Oct 2008 01:13:06 GMT</lastBuildDate><generator>Microsoft Spaces v1.1</generator><docs>http://www.rssboard.org/rss-specification</docs><ttl>60</ttl><cf:parentRSS>http://badcorporatelogo.spaces.live.com/blog/feed.rss</cf:parentRSS><live:type>blogcategory</live:type><live:identity><live:id>4894130425169106705</live:id><live:alias>badcorporatelogo</live:alias></live:identity><cf:listinfo><cf:group ns="http://schemas.microsoft.com/live/spaces/2006/rss" element="typelabel" label="Type" /><cf:group ns="http://schemas.microsoft.com/live/spaces/2006/rss" element="tag" label="Tag" /><cf:group element="category" label="Category" /><cf:sort element="pubDate" label="Date" data-type="date" default="true" /><cf:sort element="title" label="Title" data-type="string" /><cf:sort ns="http://purl.org/rss/1.0/modules/slash/" element="comments" label="Comments" data-type="number" /></cf:listinfo><item><title>Making a Designer of Your Own - An Imperfect Example</title><link>http://badcorporatelogo.spaces.live.com/Blog/cns!43EB71B104A2D711!328.entry</link><description>&lt;p&gt;Months ago, I started a little project that was supposed to be a diversion from my day job. My day job is building XNA Game Studio... And my project was an experiment to make programming with XNA Game Studio easier. I admit that I'm not very good at creating diversions for myself. &lt;p&gt;Anyway, after a couple nights of playing with samples from the XNA Creators Club Online web site, I had integrated the MenuScreen class into Visual Studio's designer framework. The result was being able to double-click a code file in a game project, and have a game menu open up in a document window. I added support for dragging-and-dropping menu items from the Toolbox, and editing properties in the Properties Window. It demonstrated some exciting possibilities, but at that point was only barely functional. &lt;p&gt;After posting some initial screenshots to my blog, I discovered that, although I'm terrible at distracting myself from work, I am pretty good at finding interesting things to work on. My blog traffic exploded by two orders of magnitude, and I received a number of requests for source code. &lt;p&gt;I'm pretty certain that my source code isn't self-explanatory. The designer I built is a customization for an existing framework, and the vast majority of the functionality isn't in my source. Anyone who understands enough of the framework to see how my source code works doesn't need the source code in the first place. So instead of answering requests with code, I started to explain the framework I was integrating into. &lt;p&gt;I'm finally at the point where further explanation will be easier to follow with a working example. For that reason, I've put my prototype project on &lt;a href="http://www.codeplex.com/"&gt;CodePlex&lt;/a&gt;. The project doesn't build a ready-to-use designer. The design-time experience is runnable, but not usable. It's got tons of potential, and I'm going to continue working on it, but at this point, it's far from perfect. &lt;p&gt;My CodePlex project is called &lt;a href="http://www.codeplex.com/ferpect"&gt;ferpect&lt;/a&gt;. If you are interested in building designer support for your own libraries, then I encourage you to take a look at it, and join the discussion if you'd like to request specific features be added for your reference. &lt;p&gt;&lt;a href="http://www.codeplex.com/ferpect"&gt;Ferpect Game Component Model&lt;/a&gt; &lt;p&gt;I'm really looking forward to continuing my work on this project. Now that the fundamentals are out of the way, I think being able to review changesets and associated check-in comments will cut down on the amount of explanation required for new features and concepts. &lt;p&gt;That's all for now!&lt;img src="http://c.services.spaces.live.com/CollectionWebService/c.gif?cid=4894130425169106705&amp;page=RSS%3a+Making+a+Designer+of+Your+Own+-+An+Imperfect+Example&amp;referrer=" width="1px" height="1px" border="0" alt=""&gt;&lt;img style="position:absolute" alt="" width="0px" height="0px" src="http://c.live.com/c.gif?NC=31263&amp;amp;NA=1149&amp;amp;PI=73329&amp;amp;RF=&amp;amp;DI=3919&amp;amp;PS=85545&amp;amp;TP=badcorporatelogo.spaces.live.com&amp;amp;GT1=badcorporatelogo"&gt;</description><comments>http://badcorporatelogo.spaces.live.com/Blog/cns!43EB71B104A2D711!328.entry#comment</comments><guid isPermaLink="true">http://badcorporatelogo.spaces.live.com/Blog/cns!43EB71B104A2D711!328.entry</guid><pubDate>Mon, 06 Oct 2008 01:13:06 GMT</pubDate><slash:comments>0</slash:comments><msn:type>blogentry</msn:type><live:type>blogentry</live:type><live:typelabel>Blog entry</live:typelabel><wfw:commentRss>http://badcorporatelogo.spaces.live.com/blog/cns!43EB71B104A2D711!328/comments/feed.rss</wfw:commentRss><wfw:comment>http://badcorporatelogo.spaces.live.com/Blog/cns!43EB71B104A2D711!328.entry#comment</wfw:comment><dcterms:modified>2008-10-06T01:13:06Z</dcterms:modified></item><item><title>Making a Designer of Your Own - Mixing and Folding</title><link>http://badcorporatelogo.spaces.live.com/Blog/cns!43EB71B104A2D711!323.entry</link><description>&lt;p&gt;For those of you who are waiting for my next article on creating a designer for XNA Framework game components, here it is! I've been working on creating a CodePlex project for the sample source code, but this turned out to be more work than I first imagined. I took a few shortcuts when I initially created my little designer, and for the code to work on other people's machines, I had to implement a bunch of additional features (no more hard-coded paths or pre-compiled assets!). &lt;p&gt;Anyway, as I continue to get that all prepared, I was forced to fix a few bugs in my designer serializer. I'd forgotten how some of my own code worked, so it took a bit of debugging before I figured out what was going on and how to fix it. Certainly there will be more bugs, so I decided to write about how serialization works -- both for my own benefit, and for others. &lt;h4&gt;What The Heck is Serialization?&lt;/h4&gt; &lt;p&gt;In the managed designer infrastructure, serialization is the process of converting objects into source code, and deserialization is the process of converting source code into objects. In general, serialization is easier than deserialization, but both are quite complicated. Fortunately, the managed designer infrastructure provides an extensible serialization implementation based on &lt;a href="http://msdn.microsoft.com/en-us/library/650ax5cx.aspx"&gt;CodeDom&lt;/a&gt;. The key word there is &amp;quot;extensible,&amp;quot; because it means we can rely on the standard behavior most of the time, and then customize things when we need to. &lt;p&gt;For convenience in the following description, let me introduce the term &lt;em&gt;serialization manager &lt;/em&gt;as the part of the designer infrastructure that coordinates serialization and deserialization. &lt;p&gt;To deserialize an object from source code, the serialization manager invokes a parser to convert the source code from a file into its CodeDom representation. The CodeDom represents a type declaration and its initialization method. The serialization manager reflects on the base type to retrieve its &lt;a href="http://msdn.microsoft.com/en-us/library/system.componentmodel.design.serialization.designerserializerattribute.aspx"&gt;DesignerSerializer&lt;/a&gt; attributes, which identify the specific CodeDom serializers to use. Then the serialization manager will instantiate the appropriate serializer and invoke its Deserialize method. &lt;p&gt;There are two kinds of serializers: &lt;a href="http://msdn.microsoft.com/en-us/library/system.componentmodel.design.serialization.typecodedomserializer.aspx"&gt;TypeCodeDomSerializer&lt;/a&gt; and &lt;a href="http://msdn.microsoft.com/en-us/library/system.componentmodel.design.serialization.codedomserializer.aspx"&gt;CodeDomSerializer&lt;/a&gt;. The first is for serializing/deserializing a type declaration. The second is for serializing/deserializing statements. To deserialize an object from code, you need both kinds of serializers. &lt;p&gt;This is a good time for an example. &lt;p&gt;Let's say that I have the following code in a file called MenuScreen1.cs: &lt;div&gt;&lt;pre&gt;&lt;span&gt;   1:  &lt;/span&gt;&lt;span&gt;public&lt;/span&gt; &lt;span&gt;class&lt;/span&gt; MenuScreen1 : MenuScreen&lt;/pre&gt;&lt;pre&gt;&lt;span&gt;   2:  &lt;/span&gt;{&lt;/pre&gt;&lt;pre&gt;&lt;span&gt;   3:  &lt;/span&gt;    &lt;span&gt;private&lt;/span&gt; ToggleMenuItem toggleMenuItem1;&lt;/pre&gt;&lt;pre&gt;&lt;span&gt;   4:  &lt;/span&gt; &lt;/pre&gt;&lt;pre&gt;&lt;span&gt;   5:  &lt;/span&gt;    &lt;span&gt;public&lt;/span&gt; MenuScreen1()&lt;/pre&gt;&lt;pre&gt;&lt;span&gt;   6:  &lt;/span&gt;    {&lt;/pre&gt;&lt;pre&gt;&lt;span&gt;   7:  &lt;/span&gt;        &lt;span&gt;this&lt;/span&gt;.InitializeComponent();&lt;/pre&gt;&lt;pre&gt;&lt;span&gt;   8:  &lt;/span&gt;    }&lt;/pre&gt;&lt;pre&gt;&lt;span&gt;   9:  &lt;/span&gt; &lt;/pre&gt;&lt;pre&gt;&lt;span&gt;  10:  &lt;/span&gt;    &lt;span&gt;private&lt;/span&gt; &lt;span&gt;void&lt;/span&gt; InitializeComponent()&lt;/pre&gt;&lt;pre&gt;&lt;span&gt;  11:  &lt;/span&gt;    {&lt;/pre&gt;&lt;pre&gt;&lt;span&gt;  12:  &lt;/span&gt;        &lt;span&gt;this&lt;/span&gt;.toggleMenuItem1 = &lt;span&gt;new&lt;/span&gt; Ferpect.GameState.MenuItems.ToggleMenuItem();&lt;/pre&gt;&lt;pre&gt;&lt;span&gt;  13:  &lt;/span&gt;        &lt;span&gt;// &lt;/span&gt;&lt;/pre&gt;&lt;pre&gt;&lt;span&gt;  14:  &lt;/span&gt;        &lt;span&gt;// toggleMenuItem1&lt;/span&gt;&lt;/pre&gt;&lt;pre&gt;&lt;span&gt;  15:  &lt;/span&gt;        &lt;span&gt;// &lt;/span&gt;&lt;/pre&gt;&lt;pre&gt;&lt;span&gt;  16:  &lt;/span&gt;        &lt;span&gt;this&lt;/span&gt;.toggleMenuItem1.Label = &lt;span&gt;&amp;quot;Sound&amp;quot;&lt;/span&gt;;&lt;/pre&gt;&lt;pre&gt;&lt;span&gt;  17:  &lt;/span&gt;        &lt;span&gt;this&lt;/span&gt;.toggleMenuItem1.ToggleValue = &lt;span&gt;true&lt;/span&gt;;&lt;/pre&gt;&lt;pre&gt;&lt;span&gt;  18:  &lt;/span&gt;        &lt;span&gt;// &lt;/span&gt;&lt;/pre&gt;&lt;pre&gt;&lt;span&gt;  19:  &lt;/span&gt;        &lt;span&gt;// MainMenuScreen&lt;/span&gt;&lt;/pre&gt;&lt;pre&gt;&lt;span&gt;  20:  &lt;/span&gt;        &lt;span&gt;// &lt;/span&gt;&lt;/pre&gt;&lt;pre&gt;&lt;span&gt;  21:  &lt;/span&gt;        &lt;span&gt;this&lt;/span&gt;.MenuItems.Add(&lt;span&gt;this&lt;/span&gt;.toggleMenuItem1);&lt;/pre&gt;&lt;pre&gt;&lt;span&gt;  22:  &lt;/span&gt;        &lt;span&gt;this&lt;/span&gt;.Text = &lt;span&gt;&amp;quot;Options&amp;quot;&lt;/span&gt;;&lt;/pre&gt;&lt;pre&gt;&lt;span&gt;  23:  &lt;/span&gt;    }&lt;/pre&gt;&lt;pre&gt;&lt;span&gt;  24:  &lt;/span&gt;}&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;When the parser reads this file and converts it to its CodeDom representation, it ignores all properties and methods in the class &lt;em&gt;except&lt;/em&gt; the InitializeComponent method. The resulting CodeDom is a CodeTypeDeclaration with fields and one method containing a statement collection.
&lt;p&gt;After parsing, the serialization manager needs to get the serializers for the base type of the class being deserialized. By inspecting the CodeTypeDeclaration, the serialization manager will determine the base class is MenuScreen (as seen on line 1). It then uses &lt;a href="http://msdn.microsoft.com/en-us/library/system.componentmodel.design.ityperesolutionservice.aspx"&gt;ITypeResolutionService&lt;/a&gt; to get a &lt;a href="http://msdn.microsoft.com/en-us/library/system.type.aspx"&gt;Type&lt;/a&gt; instance for MenuScreen, and then uses &lt;a href="http://msdn.microsoft.com/en-us/library/system.componentmodel.typedescriptor.aspx"&gt;TypeDescriptor&lt;/a&gt; to get its DesignerSerializer attributes. If the base type doesn't have any DesignerSerializer attributes, the serialization manager continues searching up its inheritance chain until it finds a base type that identifies a TypeCodeDomSerializer.
&lt;p&gt;After finding the type serializer for MenuScreen, the serialization manager will instantiate the serializer and invoke its Deserialize method, passing it the CodeTypeDeclaration for MenuScreen1. The standard TypeCodeDomSerializer will look at the base type in the CodeTypeDeclaration, MenuScreen, and instantiate it.
&lt;p&gt;This very first object is returned to the serialization manager and placed on the design surface. Since it's the first component on the design surface, it becomes the root component, and its name is the name of the type being deserialized, MenuScreen1. The serialization manager then adds MenuScreen1 to its name table.
&lt;p&gt;At this point, MenuScreen1 is only partly deserialized. After adding the root component to its name table, the serialization manager begins to interpret the code statements in the InitializeComponent method. The InitializeComponent method contains statements that are sorted into groups according to the object reference on the left-hand side.
&lt;p&gt;That is, all the statements referencing &amp;quot;toggleMenuItem1&amp;quot; are grouped together, and so are the statements referencing &amp;quot;MenuScreen1&amp;quot;. Each member variable is added to the name table, then for each one, the serialization manager retrieves the CodeDomSerializer for the member variable's type, and uses it to deserialize that member's assignment statements. The last step is to retrieve the CodeDomSerializer for MenuScreen, and use it to deserialize the remaining assignment statements for MenuScreen1.
&lt;p&gt;If there is an assignment statement that references another member variable on the right-hand-side, the serialization manager is used to resolve the name. If the object hasn't been added to the name table yet, then the serialization manager will immediately deserialize the named component's statements so that it can return the instance.
&lt;p&gt;In the example above, toggleMenuItem1 will be deserialized into a ToggleMenuItem instance, and that instance's Label and ToggleValue properties will be initialized to &amp;quot;Sound&amp;quot; and true, respectively.
&lt;p&gt;When MenuScreen1's statements are deserialized, you can see there is a reference to toggleMenuItem1 on line 21. The serializer will resolve this reference by asking the serialization manager for an object with that name. Since toggleMenuItem1 is already deserialized at that point, it is returned, and then can be used to be added to the MenuItems collection.
&lt;p&gt;When the deserialization is complete, the design surface shows a MenuScreen instance that has been initialized exactly like the code in the MenuScreen1.cs file.
&lt;p&gt;Serialization is similar, but works in the opposite direction. The root component is serialized into a type declaration, then each of the other components on the design surface becomes a member variable plus some initialization statements, and finally the root component's initialization statements are generated.
&lt;p&gt;The statements usually are generated into the InitializeComponent method, because that's the only method that will be parsed during deserialization. A designer isn't going to be much use if it can't round-trip from objects to code and back again.
&lt;p&gt;The code file, MenuScreen1.cs may contain other code written by the user. For example, the user may add event handlers. After serializing the design surface to CodeDom, the CodeDom is turned into source code by a code generator. That source code is then strategically inserted into the source file to completely replace existing methods with the same names.
&lt;h4&gt;Skillful Substitution Explained&lt;/h4&gt;
&lt;p&gt;In my last post on designers, I said the following:
&lt;blockquote&gt;
&lt;p&gt;Every experienced cook knows how to substitute certain ingredients for others. However, it takes a certain amount of skill and know-how to still end up with a palatable result. (I'm really determined to keep this cooking analogy going...)&lt;/blockquote&gt;
&lt;p&gt;The reason I started to write this whole series in the first place was to explain how to re-use the existing Windows Forms designer for XNA Framework game components. The problem with trying to use the Windows Forms designer is that it only works with Windows Forms Control classes, and our XNA Framework game components are not Controls.
&lt;p&gt;As I discussed in previoius posts, it is possible to implement a Windows Forms Control that will create an XNA Framework graphics device and draw an XNA Framework game component. Following my example above, let's imagine that MenuScreen is an XNA Framework game component. To be able to design this component in the Windows Forms designer, I need to deserialize MenuScreen into a Control that can draw a MenuScreen component (let's call that a MenuScreenControl).
&lt;p&gt;I need several things for this. First, I need to put an attribute on MenuScreen to point to a custom type serializer. The type serializer is responsible for deserializing the CodeTypeDeclaration into an object instance. With a very small amount of code, it's possible to create a custom TypeCodeDomSerializer that simply modifies the CodeTypeDeclaration it is given so it looks like MenuScreen1 derives from MenuScreenControl, and then passes it along to the TypeCodeDomSerializer for MenuScreenControl.
&lt;p&gt;The MenuScreenControl instance will use ICustomTypeDescriptor to make it look like a MenuScreen instance when viewed through reflection (design-time reflection is always done with TypeDescriptor). Since serialization uses TypeDescriptor, we don't need to modify the TypeCodeDomSerializer's serialization step -- because the ICustomTypeDescriptor implementation fools the serializer into thinking it's serializing a MenuScreen instance.
&lt;p&gt;The MenuScreenControl implementation is pretty straightforward. It is just a GraphicsDeviceControl with ICustomTypeDescriptor. Since it needs to draw a MenuScreen instance, it makes sense to instantiate one of those and store it in a member variable. Then the ICustomTypeDescriptor implementation just needs to invoke TypeDescriptor on the MenuScreen instance.
&lt;p&gt;Note: There is a bit of futzing required to make the properties work properly in the Properties Window, but I'll explain that another time.
&lt;p&gt;The last thing required is a custom CodeDomSerializer, also identified by an attribute on MenuScreen. This one is required to acquire the CodeDomSerializer of a standard Component, and then just delegate its Serialize method to that instance. The reason for this is because the initialization statements are generated by the CodeDomSerializer, and the standard serializer for a Control will generate additional statements for Control layout that won't compile when applied to a game component.
&lt;h4&gt;Wrapping Up the Leftovers&lt;/h4&gt;
&lt;p&gt;At this point, you're probably thinking, &amp;quot;How many times can this guy write 'serializer' in one post?&amp;quot; I don't blame you. But if you stuck through all this, then you're probably starting to see how extensible the designer framework really is, and how finding the right extensibility points is the key to re-using code and saving yourself a truck load of work.&lt;img src="http://c.services.spaces.live.com/CollectionWebService/c.gif?cid=4894130425169106705&amp;page=RSS%3a+Making+a+Designer+of+Your+Own+-+Mixing+and+Folding&amp;referrer=" width="1px" height="1px" border="0" alt=""&gt;&lt;img style="position:absolute" alt="" width="0px" height="0px" src="http://c.live.com/c.gif?NC=31263&amp;amp;NA=1149&amp;amp;PI=73329&amp;amp;RF=&amp;amp;DI=3919&amp;amp;PS=85545&amp;amp;TP=badcorporatelogo.spaces.live.com&amp;amp;GT1=badcorporatelogo"&gt;</description><comments>http://badcorporatelogo.spaces.live.com/Blog/cns!43EB71B104A2D711!323.entry#comment</comments><guid isPermaLink="true">http://badcorporatelogo.spaces.live.com/Blog/cns!43EB71B104A2D711!323.entry</guid><pubDate>Sun, 28 Sep 2008 09:23:51 GMT</pubDate><slash:comments>0</slash:comments><msn:type>blogentry</msn:type><live:type>blogentry</live:type><live:typelabel>Blog entry</live:typelabel><wfw:commentRss>http://badcorporatelogo.spaces.live.com/blog/cns!43EB71B104A2D711!323/comments/feed.rss</wfw:commentRss><wfw:comment>http://badcorporatelogo.spaces.live.com/Blog/cns!43EB71B104A2D711!323.entry#comment</wfw:comment><dcterms:modified>2008-09-28T09:23:51Z</dcterms:modified></item><item><title>Debugging Zune Games in XGS 3.0</title><link>http://badcorporatelogo.spaces.live.com/Blog/cns!43EB71B104A2D711!321.entry</link><description>&lt;p&gt;If you've been using XNA Game Studio to develop games for Zune, you're probably familiar with the following debug output: &lt;blockquote&gt; &lt;p&gt;The thread 0x1234 has exited with code 0 (0x0).&lt;/blockquote&gt; &lt;p&gt;This message gets spit into the Output Window while debugging, about once per second, if not more. It shows up so frequently, in fact, that it makes it very hard to see any other output at all! &lt;p&gt;Since it's pretty rare that you're actually interested in these thread exit messages, seeing them can get quite aggravating. That's why I'm posting this to explain how to suppress these messages from the debug output. &lt;p&gt;While debugging, right-click on the Output Window, and uncheck &amp;quot;Thread Exit Messages&amp;quot;. Done! Now you can use the Output Window again! &lt;p&gt;&lt;a href="http://byfiles.storage.msn.com/y1ptpTOaOh3kBCVDb7Y5paDpilsRkVvvsxlqd6SQjnwf-fbvDZIfk2ld0y1D-GdCegQ?PARTNER=WRITER"&gt;&lt;img style="border-right:0px;border-top:0px;border-left:0px;border-bottom:0px" height=244 alt=image src="http://byfiles.storage.msn.com/y1plGBh5okfIPl1mZUlovjf4i6mb-UK6-1Y0d6dMXot83oW6da9WRABYyCI8Ds6t-9gfLOjnnyjvxE?PARTNER=WRITER" width=164 border=0&gt;&lt;/a&gt;&lt;img src="http://c.services.spaces.live.com/CollectionWebService/c.gif?cid=4894130425169106705&amp;page=RSS%3a+Debugging+Zune+Games+in+XGS+3.0&amp;referrer=" width="1px" height="1px" border="0" alt=""&gt;&lt;img style="position:absolute" alt="" width="0px" height="0px" src="http://c.live.com/c.gif?NC=31263&amp;amp;NA=1149&amp;amp;PI=73329&amp;amp;RF=&amp;amp;DI=3919&amp;amp;PS=85545&amp;amp;TP=badcorporatelogo.spaces.live.com&amp;amp;GT1=badcorporatelogo"&gt;</description><comments>http://badcorporatelogo.spaces.live.com/Blog/cns!43EB71B104A2D711!321.entry#comment</comments><guid isPermaLink="true">http://badcorporatelogo.spaces.live.com/Blog/cns!43EB71B104A2D711!321.entry</guid><pubDate>Thu, 18 Sep 2008 04:38:27 GMT</pubDate><slash:comments>0</slash:comments><msn:type>blogentry</msn:type><live:type>blogentry</live:type><live:typelabel>Blog entry</live:typelabel><wfw:commentRss>http://badcorporatelogo.spaces.live.com/blog/cns!43EB71B104A2D711!321/comments/feed.rss</wfw:commentRss><wfw:comment>http://badcorporatelogo.spaces.live.com/Blog/cns!43EB71B104A2D711!321.entry#comment</wfw:comment><dcterms:modified>2008-09-18T04:38:27Z</dcterms:modified></item><item><title>Making a Designer of Your Own - Soup Stock</title><link>http://badcorporatelogo.spaces.live.com/Blog/cns!43EB71B104A2D711!314.entry</link><description>&lt;p&gt;In my last couple posts, I've been explaining concepts needed to customize the managed designer infrastructure in Visual Studio. I've been forced to put this project aside for quite a while on account of being too busy with other things... But this weekend I really need to think about something other than work for a while. Despite &lt;a href="http://blogs.msdn.com/shawnhar/archive/2008/05/14/stephen-scares-me.aspx"&gt;Shawn&lt;/a&gt; thinking I'm nuts for having the same hobby as my work, the important thing for me is that I work on &lt;em&gt;different &lt;/em&gt;problems. Thinking about my own programming problems doesn't involve quite the stress as thinking about programming problems for work. 
&lt;p&gt;Anyway, I've been using the analogy of learning to cook as the theme of my blog posts. In this post, I'm going to describe a set of base classes that we can re-use for nearly any type of designable component. In cooking terms, it'll be like creating a &lt;a href="http://en.wikipedia.org/wiki/Soup_stock"&gt;soup stock&lt;/a&gt;. It forms the basis of many dishes, and each one can be uniquely characterized by adding different elements! 
&lt;h3&gt;The Concept&lt;/h3&gt;
&lt;p&gt;I want to create a visual designer for an XNA Framework drawable component, so the first thing I need is a way to render it in a Visual Studio editor. When I first thought about this, two things came to mind. First, there is already a designer for Windows Forms Controls. Second, the Creators Club Online web site has a sample showing how to render XNA Framework graphics classes in a Windows Form Control. 
&lt;p&gt;At this point, it almost seems like there's nothing left to do! On the other hand, I don't really want a Windows Forms Control in my game because Windows Forms is not supported on either Xbox 360 or Zune. I would prefer to keep the code in my game libraries platform-neutral, so I can use the same components no matter what platform I'm targeting. Hmm... 
&lt;p&gt;I really want a designable XNA Framework game component that doesn't derive from Control, but creates a Control in the design surface when opened in design view. Furthermore, I want to edit the component's properties instead of the Control's properties. Sounds difficult -- and it is -- but applying the right ingredients to a powerful stock will result in exactly the secret sauce I'm after. 
&lt;p&gt;For now, let's focus on building the right stock. Later, I'll explain the &lt;a href="http://en.wikipedia.org/wiki/Switcheroo"&gt;switcheroo&lt;/a&gt;. 
&lt;h3&gt;The Prep&lt;/h3&gt;
&lt;p&gt;The sample (&lt;a href="http://creators.xna.com/en-us/sample/winforms_series1"&gt;here&lt;/a&gt;) provides source code for GraphicsDeviceControl, a Windows Forms Control that renders XNA Framework content. It's trivial to derive from this existing class and override the Draw method to draw whatever XNA Framework content that I want. That means it's trivial to make a designable Control that uses the XNA Framework to render itself. 
&lt;p&gt;To get started, we need to prepare a couple things. First, I'd like a base class for my designable components. The XNA Framework's &lt;a href="http://msdn.microsoft.com/en-us/library/microsoft.xna.framework.drawablegamecomponent.aspx"&gt;DrawableGameComponent&lt;/a&gt; isn't suitable as a base for my designable components because it requires a &lt;a href="http://msdn.microsoft.com/en-us/library/microsoft.xna.framework.game.aspx"&gt;Game&lt;/a&gt; class instance to be provided to its constructor. At design-time, we're not going to have a Game instance, so we wouldn't be able to instantiate and use it. We also would like the base class to derive from &lt;a href="http://msdn.microsoft.com/en-us/library/system.componentmodel.component.aspx"&gt;Component&lt;/a&gt; so that Visual Studio recognizes it as designable (at some point, we're going to need this, even if I haven't explained how it will work yet). 
&lt;p&gt;To start, we need two classes: the first will derive from GraphicsDeviceControl, and the second will be a modified version of DrawableGameComponent. 
&lt;table cellspacing=0 cellpadding=2 width=705 border=1&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td valign=top width=199&gt;&lt;strong&gt;Class&lt;/strong&gt; 
&lt;td valign=top width=504&gt;&lt;strong&gt;Description&lt;/strong&gt; 
&lt;tr&gt;
&lt;td valign=top width=201&gt;ViewControl&amp;lt;TComponent&amp;gt; 
&lt;td valign=top width=502&gt;Derives from GraphicsDeviceControl, the control from the sample I mentioned earlier. It instantiates TComponent, which must implement IComponent, IDrawable, and IGameComponent. This control's Draw method will clear the device and invoke Draw on the TComponent instance. ViewControl&amp;lt;&amp;gt; is intended to provide the design-time view for TComponent, so it will also include logic to draw at a fixed timestep so that it doesn't monopolize the IDE's CPU usage. 
&lt;tr&gt;
&lt;td valign=top width=203&gt;ViewComponent 
&lt;td valign=top width=501&gt;A base implementation of IComponent, IDrawable, and IGameComponent. It is very similar to DrawableGameComponent from the XNA Framework, but differs in that it doesn't depend on a Game class being passed to its constructor.&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;To create a specific designable component, I'll need to introduce more classes. However, each specific designable component can re-use these same base classes. We'll look at examples another time. 
&lt;h3&gt;The Code&lt;/h3&gt;
&lt;p&gt;I put the code files below on my skydrive, with links below. 
&lt;p&gt;Some of the code files are copied or derived from samples that were made available under the &lt;a href="http://cid-43eb71b104a2d711.skydrive.live.com/self.aspx/XNA Game Studio 2.0/Microsoft Permissive License.rtf"&gt;Microsoft Permissive License&lt;/a&gt; (Ms-PL). In accordance with the license, my derivative source can only be made available under the same license. Be sure to read it before looking at any of the code files! 
&lt;p&gt;For your convenience, I'll note the source of the original code file and a summary of the changes I've made (at least those I remember). 
&lt;table cellspacing=0 cellpadding=2 width=700 border=1&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td valign=top width=208&gt;File 
&lt;td valign=top width=490&gt;Description 
&lt;tr&gt;
&lt;td valign=top width=213&gt;&lt;a href="http://cid-43eb71b104a2d711.skydrive.live.com/self.aspx/XNA Game Studio 2.0/Soup Stock Samples/GraphicsDeviceService.cs"&gt;GraphicsDeviceService.cs&lt;/a&gt; 
&lt;td valign=top width=486&gt;
&lt;ul&gt;
&lt;li&gt;Originally from the &lt;a href="http://creators.xna.com/en-us/sample/winforms_series1"&gt;WinForms sample&lt;/a&gt;. 
&lt;li&gt;There were two &lt;a href="http://msdn.microsoft.com/en-us/library/system.threading.interlocked.aspx"&gt;Interlocked&lt;/a&gt; references in this class that worried me. Use of Interlocked implies it should be thread-safe - &lt;strike&gt;but if that's the case, the sample code contains several bugs! I fixed the race conditions in AddRef/Release just in case, but there are more I didn't fix.&lt;/strike&gt; [Edit: Oops! It turns out there wasn't a race condition there at all! The class is not intended to be thread-safe in general, except for the particular case of handling a finalizer thread, which it was doing correctly.]&lt;/ul&gt;
&lt;tr&gt;
&lt;td valign=top width=217&gt;&lt;a href="http://cid-43eb71b104a2d711.skydrive.live.com/self.aspx/XNA Game Studio 2.0/Soup Stock Samples/GraphicsDeviceControl.cs"&gt;GraphicsDeviceControl.cs&lt;/a&gt; 
&lt;td valign=top width=483&gt;
&lt;ul&gt;
&lt;li&gt;Originally from the &lt;a href="http://creators.xna.com/en-us/sample/winforms_series1"&gt;WinForms sample&lt;/a&gt;. 
&lt;li&gt;Removed the &amp;quot;if (!DesignMode)&amp;quot; condition from OnCreateControl. The whole purpose of this control is to render our graphics at design-time! :-) 
&lt;li&gt;Switched to using the .NET Framework's &lt;a href="http://msdn.microsoft.com/en-us/library/system.componentmodel.design.servicecontainer(VS.80).aspx"&gt;ServiceContainer&lt;/a&gt; rather than the one defined in the sample (which does the same thing).&lt;/ul&gt;
&lt;tr&gt;
&lt;td valign=top width=217&gt;&lt;a href="http://cid-43eb71b104a2d711.skydrive.live.com/self.aspx/XNA Game Studio 2.0/Soup Stock Samples/ViewComponent.cs"&gt;ViewComponent.cs&lt;/a&gt; 
&lt;td valign=top width=483&gt;This is the base class I want to use for my designable objects. It derives from Component to tie into the designer infrastructure. It also implements &lt;a href="http://msdn.microsoft.com/en-us/library/microsoft.xna.framework.idrawable_members.aspx"&gt;IDrawable&lt;/a&gt;, &lt;a href="http://msdn.microsoft.com/en-us/library/microsoft.xna.framework.igamecomponent_members.aspx"&gt;IGameComponent&lt;/a&gt;, and &lt;a href="http://msdn.microsoft.com/en-us/library/microsoft.xna.framework.iupdateable_members.aspx"&gt;IUpdateable&lt;/a&gt;. These interfaces are implemented so that the specific components you create from this base class can be plugged into any XNA Framework game in a standard way.&lt;br&gt;&lt;br&gt;There is an obvious problem with IGameComponent in that its &lt;a href="http://msdn.microsoft.com/en-us/library/microsoft.xna.framework.igamecomponent.initialize.aspx"&gt;Initialize&lt;/a&gt; method doesn't take any arguments. It's nearly useless as an interface without providing an IServiceProvider instance, because for every object implementing it, you need to define some custom mechanism outside of the interface to connect the object to its environment. To work around this problem, ViewComponent uses a ContentManager property named Content. This property must be set before Initialize is called so that the object can query its environment through the ContentManager's ServiceProvider property.&lt;br&gt;&lt;br&gt;The rest of the events, properties, and methods are implemented as simply as they can be. Attributes are used to provide standard design-time metadata. 
&lt;tr&gt;
&lt;td valign=top width=217&gt;&lt;a href="http://cid-43eb71b104a2d711.skydrive.live.com/self.aspx/XNA Game Studio 2.0/Soup Stock Samples/ViewControl.cs"&gt;ViewControl.cs&lt;/a&gt; 
&lt;td valign=top width=483&gt;This is the control that will draw our components at design-time. It has to serve about the same purpose as the Game class in a game program, which is to provide a graphics device and other services, and to invoke the XNA Framework interface methods at the appropriate time.&lt;br&gt;&lt;br&gt;My view control is quite simple at the moment (it will evolve in the next post). It uses a Stopwatch instance to invalidate the control every 16 milliseconds (max). The Draw method is then overridden to clear the graphics device and draw the ViewComponent specified as the generic type argument.&lt;br&gt;&lt;br&gt;Although I said that the ViewControl is supposed to replace the Game, you might have noticed that this class doesn't actually invoke Initialize or Update on the ViewComponent. That's partly because the decision to invoke Update will depend on the specific ViewComponent instance, so it should be implemented in the specific class that derives from ViewControl&amp;lt;T&amp;gt;. Another reason is because we haven't looked at how to create a ContentManager that can be used at design-time. Invoking Initialize without a ContentManager will not succeed if the ViewComponent needs to load any content.&lt;/tbody&gt;&lt;/table&gt;
&lt;h3&gt;Next Steps&lt;/h3&gt;
&lt;p&gt;We've gathered up the primary ingredients, but it's pretty clear we can't just throw them in a bowl and set the mixer on high. We have a ViewControl class that is supposed to draw the ViewComponent, but we don't have a way to get the user experience we need. What we want is to be able to add types in a project that derive from a specific ViewComponent, and have that show up in the designer when you double-click the file. 
&lt;p&gt;So, for example, let's say we have this specific ViewComponent: 
&lt;blockquote&gt;
&lt;p&gt;public class MenuScreen : ViewComponent 
&lt;p&gt;{ 
&lt;p&gt;}&lt;/blockquote&gt;
&lt;p&gt;We want to be able to define new classes in our projects like this: 
&lt;blockquote&gt;
&lt;p&gt;public class MenuScreen1 : MenuScreen 
&lt;p&gt;{ 
&lt;p&gt;}&lt;/blockquote&gt;
&lt;p&gt;...And then have MenuScreen appear in the designer when the code file is opened in design view. 
&lt;p&gt;As I described in a previous post, the designer infrastructure will instantiate the base class of the designable component. We already know that MenuScreen is a ViewComponent, so it relies on its host to provide a graphics device and to tell it when to draw. 
&lt;p&gt;To be able to draw the MenuScreen, we need another class: 
&lt;blockquote&gt;
&lt;p&gt;public class MenuScreenControl : ViewControl&amp;lt;MenuScreen&amp;gt; 
&lt;p&gt;{ 
&lt;p&gt;}&lt;/blockquote&gt;
&lt;p&gt;We don't want this control to show up anywhere in the project where MenuScreen1 is defined, but we do want it to be instantiated in the designer in place of MenuScreen. The magic trick to this is customizing MenuScreen's designer serializer. 
&lt;p&gt;For detailed information on designer serialization, refer to &lt;a href="http://msdn.microsoft.com/en-us/library/ms171834.aspx"&gt;Designer Serialization Overview&lt;/a&gt;. 
&lt;p&gt;When you try to open a code file in design view, the designer infrastructure looks at the base type of the class to see if it inherits from Component. If it does, it then looks to see if the class has a designer serializer. If the type doesn't specify one, the serializer is inherited from its base class. By default, every designable component will use the Component's designer serializer. The job of the serializer is to instantiate the component from its serialized state (or to deserialize it). 
&lt;p&gt;The designer serialization is based on &lt;a href="http://msdn.microsoft.com/en-us/library/system.codedom.aspx"&gt;CodeDom&lt;/a&gt;, so the serializer is passed a CodeDom definition of the base class from the code file, and is asked to deserialize it. Naturally, the default serializer simply instantiates the type specified in the &lt;a href="http://msdn.microsoft.com/en-us/library/system.codedom.codetypedeclaration.aspx"&gt;CodeTypeDeclaration&lt;/a&gt; passed to it. 
&lt;p&gt;By providing a custom designer serializer, we can customize the deserialization step. You might have already guessed that by doing this, we can instantiate a MenuScreenControl in place of the MenuScreen component specified in the CodeTypeDeclaration! 
&lt;h3&gt;Skillful Substitution&lt;/h3&gt;
&lt;p&gt;Every experienced cook knows how to substitute certain ingredients for others. However, it takes a certain amount of skill and know-how to still end up with a palatable result. (I'm really determined to keep this cooking analogy going...) 
&lt;p&gt;In our designer, it's not enough to just instantiate a MenuScreenControl in place of a MenuScreen. When looking at the design surface, it'll be exactly what a user might expect, but as soon as the user tries working with it, the illusion will fall apart! The Properties Window is going to reveal that the class is a MenuScreenControl instance, and it won't have the MenuScreen's properties. It's like we're trying to pass off &lt;a href="http://en.wikipedia.org/wiki/Tofurkey"&gt;tofurkey&lt;/a&gt; for the real thing at Thanksgiving dinner! Nobody who's ever had real turkey before is going to be fooled! 
&lt;p&gt;More design-time tricks are needed, and this time, &lt;a href="http://msdn.microsoft.com/en-us/library/system.componentmodel.icustomtypedescriptor.aspx"&gt;ICustomTypeDescriptor&lt;/a&gt; is our secret ingredient. By implementing ICustomTypeDescriptor on our MenuScreenControl, we can make it appear to be an instance of MenuScreen. We can give it the same type name, the same properties, the same attributes. The best part is that if we do it right, we'll even fool the MenuScreenControl's serializer into generating code for a MenuScreen. That means no more serializer customization! 
&lt;p&gt;To pull off the ICustomTypeDescriptor implementation, a few helper classes are needed. They aren't very complicated, but it'll be easier to just show them off with a sample. 
&lt;p&gt;Next time, I'll provide a working sample and explain how to set it up properly. Proper set up is essential to avoid common pitfalls in designer debugging. After that, I'll start to introduce some neat feature ideas specifically for XNA Framework projects.&lt;img src="http://c.services.spaces.live.com/CollectionWebService/c.gif?cid=4894130425169106705&amp;page=RSS%3a+Making+a+Designer+of+Your+Own+-+Soup+Stock&amp;referrer=" width="1px" height="1px" border="0" alt=""&gt;&lt;img style="position:absolute" alt="" width="0px" height="0px" src="http://c.live.com/c.gif?NC=31263&amp;amp;NA=1149&amp;amp;PI=73329&amp;amp;RF=&amp;amp;DI=3919&amp;amp;PS=85545&amp;amp;TP=badcorporatelogo.spaces.live.com&amp;amp;GT1=badcorporatelogo"&gt;</description><comments>http://badcorporatelogo.spaces.live.com/Blog/cns!43EB71B104A2D711!314.entry#comment</comments><guid isPermaLink="true">http://badcorporatelogo.spaces.live.com/Blog/cns!43EB71B104A2D711!314.entry</guid><pubDate>Sun, 27 Jul 2008 20:56:37 GMT</pubDate><slash:comments>0</slash:comments><msn:type>blogentry</msn:type><live:type>blogentry</live:type><live:typelabel>Blog entry</live:typelabel><wfw:commentRss>http://badcorporatelogo.spaces.live.com/blog/cns!43EB71B104A2D711!314/comments/feed.rss</wfw:commentRss><wfw:comment>http://badcorporatelogo.spaces.live.com/Blog/cns!43EB71B104A2D711!314.entry#comment</wfw:comment><dcterms:modified>2008-07-29T04:33:06Z</dcterms:modified></item><item><title>Compelling Design-Time Experiences in an XNA Game Studio-Based Designer</title><link>http://badcorporatelogo.spaces.live.com/Blog/cns!43EB71B104A2D711!265.entry</link><description>&lt;p&gt;The other week, I started playing around with building a designer for &lt;a href="http://badcorporatelogo.spaces.live.com/blog/cns!43EB71B104A2D711!253.entry"&gt;Game State Management&lt;/a&gt;. It wasn't long before I had something working -- mainly because I leveraged a lot of existing code in the .NET Framework. The screen shots I showed previously are the result -- a design surface that can interact with the Toolbox and Properties Window. This is sufficient to quickly add menu items, edit their appearance, and even generate event handlers for input events. &lt;p&gt;I was pretty excited about it and that's why I posted to my blog. Unfortunately, the MenuScreen and MenuEntry classes in the Game State Management sample weren't intended to be designable. They didn't have many interesting properties or events, so the designer could only save you from writing a couple lines of code before you had to drop back to source view and type the rest of your program with a &lt;em&gt;keyboard&lt;/em&gt;. Gross! ;-P &lt;p&gt;Last week, I thought about how I often navigate menu screens in games -- selecting a menu item to activate another menu screen, then canceling back to the previous screen, and so forth. To build a navigation system without writing any code, I needed a way to specify what the next screen from within the designer. &lt;p&gt;What I came up with was a property of type System.Type, which could only be set to a type that derives from GameScreen (the base class for all screens). I implemented a navigation item that, when selected, would activate a new instance of the specified GameScreen type and begin a transition to it. That was pretty easy, except for the idea of someone trying to edit the System.Type property in the Properties Window. &lt;p&gt;You can customize the design-time behavior of properties by using a &lt;a href="http://msdn.microsoft.com/en-us/library/system.componentmodel.typeconverter.aspx"&gt;TypeConverter&lt;/a&gt;, that you can associate with the property by using a &lt;a href="http://msdn.microsoft.com/en-us/library/system.componentmodel.typeconverterattribute.aspx"&gt;TypeConverterAttribute&lt;/a&gt;. My custom TypeConverter class uses &lt;a href="http://msdn.microsoft.com/en-us/library/system.componentmodel.design.itypediscoveryservice.aspx"&gt;ITypeDiscoveryService&lt;/a&gt; to enumerate all the available GameScreen types in the project and list them in a combobox for easy selection. This new ability to select a screen type in the designer makes it possible to build fancy menus with pop-ups and structured navigation without writing any code. After that, it was a snap to add another navigation item that could both specify the next screen, as well as a second screen to animate during lengthy, asynchronous content loads. &lt;p&gt;More recently, I thought about how I'd like to customize the appearance of a menu. I'd like to do things like customize the menu's font, or create background screens by selecting textures. I actually would like to be able to create a whole 2D scene out of sprites on non-menu screens, or to display sprites when menu items are activated... But first things first. &lt;p&gt;A compelling design-time experience for any of this would require the designer to know about the content built by a project. If the menu had a Font property, you'd want the Properties Window to let you choose from a list of SpriteFont items in your project. Then, for a &lt;em&gt;really&lt;/em&gt; good design-time experience, you'd want the designer to actually &lt;em&gt;use&lt;/em&gt; that SpriteFont when rendering the design surface. &lt;p&gt;The way I picture that working would be to have a string property for the Font, which specifies the asset name of the SpriteFont. The TypeConverter for this property would enumerate the SpriteFont items from the project, and then the menu would load the asset by name during initialization. &lt;p&gt;The hard part, unfortunately, is figuring out what SpriteFonts are available in the project at design time. &lt;p&gt;Tonight, I believe I've solve this problem. &lt;p&gt;&lt;a href="http://rxdrja.bay.livefilestore.com/y1poZxlZcsmKwji2P6xdJTj2rIr8yFvui9d-9fP_wNIrj911Gpzus8TUeh9fMFxh5PPG62HqC96UjbILIKQ3J_zeA?PARTNER=WRITER"&gt;&lt;img style="border-right:0px;border-top:0px;border-left:0px;border-bottom:0px" height=133 alt=image src="http://by1.storage.msn.com/y1p49FnH5vGVi7cwNHUjuiTt55Jp3tTycWw2BKKoPaYajD9olfIf49yRSOlRwMEq7JhKtWB_GXjC4Yxo5qFG_F5NlVST5IwcodG?PARTNER=WRITER" width=244 border=0&gt;&lt;/a&gt;  &lt;p&gt;This figure shows a SpriteFont property added to the MenuScreen which lists available SpriteFonts from the content project at design-time. It doesn't yet use that font for rendering the design surface, but that's the next logical step. &lt;p&gt;Writing a TypeConverter to be aware of the content items was tricky and required very specific domain knowledge of Visual Studio and the &lt;a href="http://msdn.microsoft.com/en-us/library/ms973820.aspx"&gt;managed designer infrastructure&lt;/a&gt;, but didn't take a lot of code. I'm still implementing everything in Visual C# Express 2005, and am able to run it and debug it without installing any packages or add-ins into the IDE. I also do not have the VS SDK installed on my laptop. To be honest, I'm a bit surprised at how much you can do without the VS SDK! &lt;p&gt;Being able to enumerate content from within the designer opens the door to all kinds of interesting scenarios! I'm looking forward to thinking about it some more! (I'm always looking forward to having free time!) :-)&lt;img src="http://c.services.spaces.live.com/CollectionWebService/c.gif?cid=4894130425169106705&amp;page=RSS%3a+Compelling+Design-Time+Experiences+in+an+XNA+Game+Studio-Based+Designer&amp;referrer=" width="1px" height="1px" border="0" alt=""&gt;&lt;img style="position:absolute" alt="" width="0px" height="0px" src="http://c.live.com/c.gif?NC=31263&amp;amp;NA=1149&amp;amp;PI=73329&amp;amp;RF=&amp;amp;DI=3919&amp;amp;PS=85545&amp;amp;TP=badcorporatelogo.spaces.live.com&amp;amp;GT1=badcorporatelogo"&gt;</description><comments>http://badcorporatelogo.spaces.live.com/Blog/cns!43EB71B104A2D711!265.entry#comment</comments><guid isPermaLink="true">http://badcorporatelogo.spaces.live.com/Blog/cns!43EB71B104A2D711!265.entry</guid><pubDate>Tue, 27 May 2008 08:16:51 GMT</pubDate><slash:comments>0</slash:comments><msn:type>blogentry</msn:type><live:type>blogentry</live:type><live:typelabel>Blog entry</live:typelabel><wfw:commentRss>http://badcorporatelogo.spaces.live.com/blog/cns!43EB71B104A2D711!265/comments/feed.rss</wfw:commentRss><wfw:comment>http://badcorporatelogo.spaces.live.com/Blog/cns!43EB71B104A2D711!265.entry#comment</wfw:comment><dcterms:modified>2008-05-27T08:16:51Z</dcterms:modified></item><item><title>Game State Management for N00bs Like Me</title><link>http://badcorporatelogo.spaces.live.com/Blog/cns!43EB71B104A2D711!253.entry</link><description>&lt;p&gt;Last week, I finished writing a design document that I'd been working on for about a month. The design review meeting seemed to go well -- at least, I think it did. There were a lot of nodding heads around the room as I presented my design, and I like to think they were nodding in approval. The alternative is that they were nodding off to sleep, but I'm going to assume that wasn't it. :-) &lt;p&gt;Anyway, after so long working on the same thing, I decided to take a look at something new and different this past weekend. I installed XNA Game Studio 2.0 and VC# 2005 Express Edition on my laptop at home and started to poke around at some samples. I downloaded &lt;a href="http://www.nazspace.com/wp/2008/02/11/template-game-state-management/"&gt;Nazeeh's Game State Management project template&lt;/a&gt; -- something that I consider to be a terrific example of what a starter kit should really be -- and created a project from it. &lt;p&gt;For those of you who are not familiar with this template, I'll briefly describe it. It creates a project for a game that has a couple menu screens, and an animated loading screen to entertain people while larger screens (aka, game levels) load asynchronously in the background. It is a slick starting point for just about any game. &lt;p&gt;I ran the project and put breakpoints in a few places to see how things were being invoked to get a better understanding of the code. Then I modified a few things and found it was reasonably easy to make changes and customize the screens. &lt;p&gt;For those of you who don't know me, my background is in tools. I make the programs that make it easier to develop games with the XNA Framework, but I don't work on the XNA Framework libraries, and I hardly know anything about game programming. So when I looked at the sample code and saw how easy it was to customize the game state, the first thing I thought of was, &amp;quot;That's pretty cool -- but I can make this easier!&amp;quot; &lt;p&gt;The funny thing about things being easy is that they are usually easy to automate. Building menus, changing properties, handling input events... Hmm, where have I seen that before? &lt;p&gt;Instead of playing around with XNA Game Studio to finally learn about game programming, I decided to build a designer for Game State Management! :-) &lt;p&gt;Tonight, I have a working menu designer. I used the &lt;a href="http://creators.xna.com/Headlines/developmentaspx/archive/2007/01/01/WinForms-Series-1_3A00_--Graphics-Device.aspx"&gt;WinFormsGraphicsDevice sample&lt;/a&gt; to create a design surface that actually draws the menu screen as menu items are added to it, and updates in real-time as properties are edited. To design a menu, I just need to declare a class that derives from my MenuScreen type, then double-click on the code file, and up pops the designer! &lt;p&gt;I only have two types of menu items to play with at the moment -- a counter and a toggle. There is a lot of work to do before it would be suitable for general use, but I'm excited about the possibilities. The samples provided a big head-start! &lt;p&gt;Here's a series of screen shots to show you what I'm talking about. &lt;p&gt;&lt;a href="http://rxdrja.bay.livefilestore.com/y1poZxlZcsmKwhfjIYkWq8nINgrIDBiqG_skSOWGEAlHUSJv69zV6vjmAxHYgf92I6SOdIjNYGmn22scR-pBkFlUw?PARTNER=WRITER"&gt;&lt;img style="border-right:0px;border-top:0px;border-left:0px;border-bottom:0px" height=165 alt=image src="http://by1.storage.msn.com/y1p49FnH5vGVi7vnqM0BPXVOfVm4-Isi18lZyihWxH648L_9nn5iK-XVjFayJKNAgFI0rML4Kz-nk6y2I-M13m04gMvDJWhRi3w?PARTNER=WRITER" width=244 border=0&gt;&lt;/a&gt;  &lt;p&gt;Figure 1 - Shows the code required to get started (an obvious template candidate). The context menu provides a &amp;quot;View Designer&amp;quot; command to open the designer. Double-clicking the code file in Solution Explorer works just as well. &lt;p&gt;&lt;a href="http://rxdrja.bay.livefilestore.com/y1p7jJzD1bA9nvnEcmRk2AQFSYsTuQS_ISki2Dl_M9fE1XbcsCajdTy1SBKv9kXOnkfoGJ_tElX21SCcuSm3Dg5B1bvDZ7KF2TK?PARTNER=WRITER"&gt;&lt;img style="border-right:0px;border-top:0px;border-left:0px;border-bottom:0px" height=149 alt=image src="http://by1.storage.msn.com/y1p49FnH5vGVi4WA2uxkIXn6nYqfVovpVWmY7JfOda72kbdYJC629j9bhaEGYKF7VExBUWdjIJrteOaCGuxElEgAYQpOZtMvsae?PARTNER=WRITER" width=244 border=0&gt;&lt;/a&gt;  &lt;p&gt;Figure 2 - The initial design view. This is an XNA GraphicsDevice cleared to CornflowerBlue and rendering a menu with no items. &lt;p&gt;&lt;a href="http://rxdrja.bay.livefilestore.com/y1p7jJzD1bA9nsqmaxTuvFGIk2wgclaBiQ_2Ew7ghCthPTg6cbcObb2Pd3F_wVAZm8C1ipGbgYz8tHm8ylLXeNwuAHdhA9qmZDJ?PARTNER=WRITER"&gt;&lt;img style="border-right:0px;border-top:0px;border-left:0px;border-bottom:0px" height=149 alt=image src="http://by1.storage.msn.com/y1p49FnH5vGVi72R07azDyB1dFcGmlk1eo-WCbHYVa2rjzmTL0QPqMZ58Xt5A-5HFW4pFTPNzYB3olTuh4I3UMOgUn9RR3ANTij?PARTNER=WRITER" width=244 border=0&gt;&lt;/a&gt;  &lt;p&gt;Figure 3 - Shows the menu after editing the Title property, then adding a ToggleMenuItem and editing its label and name. &lt;p&gt;&lt;a href="http://rxdrja.bay.livefilestore.com/y1p7jJzD1bA9ntybEd1QP1-E5KaJTxn1mfJypFqh6GEiGgwEosr0QKN7Ub9w87a81qwegi0LBEtDmK2VIdlueL7Pt8WKcBNhTZx?PARTNER=WRITER"&gt;&lt;img style="border-right:0px;border-top:0px;border-left:0px;border-bottom:0px" height=151 alt=image src="http://by1.storage.msn.com/y1p49FnH5vGVi6G0F_tXeGmuzRDNv77xcCQ9mRkGJ14WhZfYQomeP88svXM7qA5uWia73kNoaK8BCNDn5KltOSK0ERcQ6j2FgTC?PARTNER=WRITER" width=244 border=0&gt;&lt;/a&gt;  &lt;p&gt;Figure 4 - Back to code view to see what the designer generated. &lt;p&gt;It might not look like much today, but it kept me busy for the past four evenings and was kind of fun! My goal really is to make it easier to get going right away. When I've worked through all the kinks enough to share the designer, I'll blog about how the designer works. &lt;p&gt;Now it's time for bed!&lt;img src="http://c.services.spaces.live.com/CollectionWebService/c.gif?cid=4894130425169106705&amp;page=RSS%3a+Game+State+Management+for+N00bs+Like+Me&amp;referrer=" width="1px" height="1px" border="0" alt=""&gt;&lt;img style="position:absolute" alt="" width="0px" height="0px" src="http://c.live.com/c.gif?NC=31263&amp;amp;NA=1149&amp;amp;PI=73329&amp;amp;RF=&amp;amp;DI=3919&amp;amp;PS=85545&amp;amp;TP=badcorporatelogo.spaces.live.com&amp;amp;GT1=badcorporatelogo"&gt;</description><comments>http://badcorporatelogo.spaces.live.com/Blog/cns!43EB71B104A2D711!253.entry#comment</comments><guid isPermaLink="true">http://badcorporatelogo.spaces.live.com/Blog/cns!43EB71B104A2D711!253.entry</guid><pubDate>Wed, 14 May 2008 09:01:53 GMT</pubDate><slash:comments>0</slash:comments><msn:type>blogentry</msn:type><live:type>blogentry</live:type><live:typelabel>Blog entry</live:typelabel><wfw:commentRss>http://badcorporatelogo.spaces.live.com/blog/cns!43EB71B104A2D711!253/comments/feed.rss</wfw:commentRss><wfw:comment>http://badcorporatelogo.spaces.live.com/Blog/cns!43EB71B104A2D711!253.entry#comment</wfw:comment><dcterms:modified>2008-05-14T09:01:53Z</dcterms:modified></item><item><title>Game Studio and Visual Studio 2008</title><link>http://badcorporatelogo.spaces.live.com/Blog/cns!43EB71B104A2D711!244.entry</link><description>&lt;p&gt;Last December, we released XNA Game Studio 2.0 with support for Visual Studio 2005. This was a big step up from having Visual C# Express support only -- but since it was hot on the heels of the Visual Studio 2008 release, some people were still disappointed. People were excited to get VS 2008, and they were excited to get XGS 2.0 -- but they wouldn't work together! &lt;p&gt;In and around Microsoft, we have a pretty big community of XGS enthusiasts. Some of them have backgrounds in tools development, including Visual Studio extensibility. Those people knew that the extensibility model for VS 2008 was completely backwards-compatible with VS 2005 (or at least it is advertised to be). So why couldn't XGS 2.0 install into VS 2008? &lt;p&gt;There were inevitable questions about whether XGS 2.0 could be made to work in VS 2008. Not the naive questions about whether you could compile code against the XNA Framework -- but whether you could get the project system to install into it, use the Content Pipeline, and debug Xbox 360 games. In January, we gave it a shot and it didn't work. It turned out there was a backwards-compatibility bug in VS 2008 that prevented content projects from loading into the IDE. It was a tiny bug with a trivial fix, but one that had to be made by in Visual Studio itself. &lt;p&gt;As a result of finding this bug, word got out that XGS 2.0 didn't support VS 2008 because it was blocked by a compatibility issue that will be fixed in VS 2008 SP1. When we released our CTP this week, someone asked me how we did it -- because weren't we blocked by the same bug that blocked XGS 2.0? &lt;p&gt;I'd like to set the record straight on that, because we were never blocked by a compatibility issue. &lt;p&gt;The incompatibility makes for a convenient excuse, but it’s not the reason we didn’t support VS 2008 in XGS 2.0. Our test team was overburdened even as it was for the XGS 2.0 release. There was absolutely no way we could have delivered support for two versions of VS, even if we’d wanted to. We knew that from the beginning, and originally &lt;a href="http://blogs.msdn.com/joen/archive/2007/04/10/which-visual-studio-version-will-you-use.aspx"&gt;JoeN&lt;/a&gt; and I pushed to make the one version be VS 2008. In the end, our leadership vetoed our proposal and chose VS 2005. That decision was made around April -- eight months before the release of XGS 2.0! &lt;p&gt;We put our heads down and committed to the task at hand -- shipping on VS 2005. &lt;p&gt;It wasn't until after VS 2008 had shipped and after XGS 2.0 had shipped that we finally looked at VS 2008. We found and identified the compatibility bug within an hour of getting the XGS 2.0 bits installed into VS 2008. So to be completely honest, if we’d had &lt;i&gt;any&lt;/i&gt; intention of supporting VS 2008, we would have easily caught this bug before the Orcas release. Its impact on our projects was obvious, and the fix is trivial. If we’d even bothered to try our stuff in VS 2008 before it shipped, that bug would no longer exist. &lt;p&gt;Letting people believe that a bug is the reason we don't support VS 2008 is like saying, “Hey, it wasn't not our fault – blame the VS team!” But in fact it is entirely our own responsibility. Whether everyone understands it or not, we &lt;i&gt;decided&lt;/i&gt; not to support VS 2008. &lt;p&gt;I feel pretty strongly now that we made the right choice -- even though I was opposed to it at the time of the decision. If you don't agree, I happen to have good news for you... We're supporting VS 2008 in XGS 3.0! &lt;p&gt;The &lt;a href="http://blogs.msdn.com/xna/archive/2008/05/07/announcing-xna-game-studio-3-0-community-technical-preview-ctp.aspx"&gt;XGS 3.0 CTP&lt;/a&gt; was released this week to preview our addition of support for Zune, and the CTP targets VS 2008! With this release, you can develop games for Zune from either VS 2008 Standard (or higher) or VC# 2008 Express Edition! &lt;img src="http://c.services.spaces.live.com/CollectionWebService/c.gif?cid=4894130425169106705&amp;page=RSS%3a+Game+Studio+and+Visual+Studio+2008&amp;referrer=" width="1px" height="1px" border="0" alt=""&gt;&lt;img style="position:absolute" alt="" width="0px" height="0px" src="http://c.live.com/c.gif?NC=31263&amp;amp;NA=1149&amp;amp;PI=73329&amp;amp;RF=&amp;amp;DI=3919&amp;amp;PS=85545&amp;amp;TP=badcorporatelogo.spaces.live.com&amp;amp;GT1=badcorporatelogo"&gt;</description><comments>http://badcorporatelogo.spaces.live.com/Blog/cns!43EB71B104A2D711!244.entry#comment</comments><guid isPermaLink="true">http://badcorporatelogo.spaces.live.com/Blog/cns!43EB71B104A2D711!244.entry</guid><pubDate>Fri, 09 May 2008 07:11:26 GMT</pubDate><slash:comments>0</slash:comments><msn:type>blogentry</msn:type><live:type>blogentry</live:type><live:typelabel>Blog entry</live:typelabel><wfw:commentRss>http://badcorporatelogo.spaces.live.com/blog/cns!43EB71B104A2D711!244/comments/feed.rss</wfw:commentRss><wfw:comment>http://badcorporatelogo.spaces.live.com/Blog/cns!43EB71B104A2D711!244.entry#comment</wfw:comment><dcterms:modified>2008-05-09T07:11:26Z</dcterms:modified></item><item><title>Extending VS 2005 to Improve Cross-Platform Development</title><link>http://badcorporatelogo.spaces.live.com/Blog/cns!43EB71B104A2D711!235.entry</link><description>&lt;p&gt;Last time I wrote, I had an idea to create an add-in to simplify the view of the solution when developing cross-platform games in XNA Game Studio 2.0. I spent an evening messing with automatically creating and hiding solution folders, but quickly came to the conclusion that simplifying the view was going to be harder than I thought. I've put it aside for a while, and started on something else... 
&lt;p&gt;I wrote an add-in that detects when you add a new file to a code project, and then adds that same file to its cross-platform counterpart. Likewise, the add-in also handles renaming files. In this post, I'm going to discuss how I did it, and what its limitations are. If you don't care about the details, but you want to try the add-in, you can skip directly to the download after considering the disclaimer at the end of this post (&lt;a href="http://cid-43eb71b104a2d711.skydrive.live.com/self.aspx/XNA Game Studio 2.0/Add-Ins"&gt;click to see my Add-Ins&lt;/a&gt;). 
&lt;h4&gt;&lt;/h4&gt;
&lt;h4&gt;Detecting Cross-Platform Projects&lt;/h4&gt;
&lt;p&gt;In XGS 2.0, there is an association between projects created from the &amp;quot;Create Copy of Project...&amp;quot; command and the original. Unfortunately, we didn't expose that association to the automation model, so you can't detect it in macros or add-ins. However, project copies share the same source code. For the vast majority of games, that means cross-platform projects have the same GuidAttribute, defined in the shared AssemblyInfo.cs file. The GUID specified in this attribute is accessible to the automation model, and so it's possible to identify project pairs in a macro by enumerating all projects in a solution and looking for any with a matching assembly GUID. 
&lt;h4&gt;Handling ProjectEvents.ItemAdded&lt;/h4&gt;
&lt;p&gt;One thing that gave me trouble was adding empty folders to the project. The code I used for files worked well for folders created in the project root directory, but had strange side-effects when new folders are created under existing folders. In the end, I decided to skip empty folders altogether. There doesn't seem to be any real drawback to this, because empty folders aren't really interesting to a project in the first place. If you later add a file to the empty folder, the paired project will get the new file in the right place, including any folders. 
&lt;p&gt;I was actually surprised at how well the handler worked! It magically handles multi-file dependent items like UserControls and Components. (Not that you will want to add those to your Xbox 360 projects, but I was still surprised they preserve the dependency!) Likewise, I was pleased to see that including an entire folder with multiple files into a project was handled correctly. Not bad for a couple hours of absent-minded coding while watching TV! 
&lt;h4&gt;Handling ProjectEvents.ItemRenamed&lt;/h4&gt;
&lt;p&gt;Handling the item renamed event was a bit trickier than I first imagined. The event handler receives a reference to the item that was renamed, as well as the item's old name. To rename the item in another project, you can use the item reference to get the full path, then use the old name (not a full path) to recreate the item's old full path. Then you can search for the old item in other projects, remove it, and add the new item (re-using the item added event handler). 
&lt;p&gt;Unlike the item added event, the item renamed event does not fire for folder items. Instead, you get the event for any file items under that folder. This is a problem, because you can't reconstruct the old path name from the information given to the event handler. In such a case, the new file name and the old file name are the same, and the old path isn't specified. 
&lt;p&gt;To handle folder renaming as well as possible, my add-in will add all the files from under the new path to the cross-platform projects. The old items will still be there, but the files they reference no longer exist. When you later try to build the project, those files will be unresolved and will give you errors. To fix this, just delete the items from your project. 
&lt;h4&gt;Installing the Add-In&lt;/h4&gt;
&lt;p&gt;You can download and install the add-in from my &lt;a href="http://cid-43eb71b104a2d711.skydrive.live.com/self.aspx/XNA Game Studio 2.0/Add-Ins"&gt;XNA Game Studio 2.0\Add-Ins&lt;/a&gt; folder. For now there is only one add-in there, but I might eventually add more. The one described in this post is called &lt;strong&gt;RighteousTool.Xgs.2.0.AddIns.ProjectSync.vsi&lt;/strong&gt;. 
&lt;p&gt;Be advised that &lt;strong&gt;Visual C# 2005 Express Edition &lt;/strong&gt;does not support add-ins or macros. You'll need to have &lt;strong&gt;Visual Studio 2005 &lt;/strong&gt;in order to install it. 
&lt;h4&gt;Disclaimer&lt;/h4&gt;
&lt;p&gt;The add-in referenced by this post is provided by the author as-is and without warranty, either express or implied. Downloading, installing, and using the add-in must be done at your own risk.&lt;img src="http://c.services.spaces.live.com/CollectionWebService/c.gif?cid=4894130425169106705&amp;page=RSS%3a+Extending+VS+2005+to+Improve+Cross-Platform+Development&amp;referrer=" width="1px" height="1px" border="0" alt=""&gt;&lt;img style="position:absolute" alt="" width="0px" height="0px" src="http://c.live.com/c.gif?NC=31263&amp;amp;NA=1149&amp;amp;PI=73329&amp;amp;RF=&amp;amp;DI=3919&amp;amp;PS=85545&amp;amp;TP=badcorporatelogo.spaces.live.com&amp;amp;GT1=badcorporatelogo"&gt;</description><comments>http://badcorporatelogo.spaces.live.com/Blog/cns!43EB71B104A2D711!235.entry#comment</comments><guid isPermaLink="true">http://badcorporatelogo.spaces.live.com/Blog/cns!43EB71B104A2D711!235.entry</guid><pubDate>Sun, 06 Apr 2008 22:51:16 GMT</pubDate><slash:comments>0</slash:comments><msn:type>blogentry</msn:type><live:type>blogentry</live:type><live:typelabel>Blog entry</live:typelabel><wfw:commentRss>http://badcorporatelogo.spaces.live.com/blog/cns!43EB71B104A2D711!235/comments/feed.rss</wfw:commentRss><wfw:comment>http://badcorporatelogo.spaces.live.com/Blog/cns!43EB71B104A2D711!235.entry#comment</wfw:comment><dcterms:modified>2008-04-21T22:31:46Z</dcterms:modified></item><item><title>Dreaming of a Cross-Platform Utopia</title><link>http://badcorporatelogo.spaces.live.com/Blog/cns!43EB71B104A2D711!220.entry</link><description>&lt;p&gt;My wife has been sick the whole week, and this morning I woke up with watery eyes and clogged sinuses. I went to work anyway, though, because when I close my office door, I can sometimes go a whole day without talking to anybody. So I went to work and started to work on getting the cross-platform project command to show up in the right place for Zune projects. I could feel the pressure building in my head. My ears popped, and I started to feel like I was underwater. This feeling was very distracting, and my mind wandered... It was then I started to think about &lt;a href="http://msdn2.microsoft.com/en-us/library/haytww03(VS.80).aspx"&gt;Solution Folders&lt;/a&gt; (yes, even my daydreams are about Visual Studio extensibility)! &lt;p&gt;Before I describe my daydream, let me enlighten you about Solution Folders and what they mean to cross-platform development in XNA Game Studio... &lt;p&gt;Solution Folders provide a convenient way to organize a solution with many projects. If you have a game with several library projects, then going cross-platform doesn't add much overhead in the way of files (one extra file per project), but it can sure make a mess of the Solution Explorer! That's where Solution Folders can shine. &lt;p&gt;Let's say I have a medium-sized project, with separate libraries for physics, animation, and some kind of high-level game engine. Throw in a couple custom processors, and it might look something like this: &lt;p&gt;&lt;a href="http://byfiles.storage.msn.com/y1pDl-u-7dR2WRfBV6o0Ggy09tfM62brWJ00CSqYNPic7T6QtlEA83GBeAkdZ-UbzYWN3bu1YhdhaA?PARTNER=WRITER"&gt;&lt;img style="border-top-width:0px;border-left-width:0px;border-bottom-width:0px;border-right-width:0px" height=161 alt=image src="http://byfiles.storage.msn.com/y1pDl-u-7dR2WSDN1PKNt4ALkXpqQjCg3EqDkwSguk6otEI-noDDUjiggbBVvgSBD9O3LtlMd3xeOI?PARTNER=WRITER" width=244 border=0&gt;&lt;/a&gt;  &lt;p&gt;If I run the &lt;strong&gt;Create Copy of Project for Xbox 360&lt;/strong&gt; command on &lt;strong&gt;EpiphanyGame&lt;/strong&gt;, I'll end up with this: &lt;p&gt;&lt;a href="http://byfiles.storage.msn.com/y1pDl-u-7dR2WTqLQ1l30DqsCW0_gRpN1CD2L0-6V4C9wlCEn0Es3fSMi_oKW2U8ulvDl_carqwsUs?PARTNER=WRITER"&gt;&lt;img style="border-top-width:0px;border-left-width:0px;border-bottom-width:0px;border-right-width:0px" height=225 alt=image src="http://byfiles.storage.msn.com/y1pDl-u-7dR2WR9zVbiEdYvgWNYHGUTmW0AzVHZxCxFIMtZVWVr2ccYTPSnSGS20YvDm4jmpp4SlXY?PARTNER=WRITER" width=244 border=0&gt;&lt;/a&gt;  &lt;p&gt;Woah! Ten projects is starting to look complicated! As you can see, all the new projects are named &amp;quot;Xbox 360 Copy of ...&amp;quot;. The prefix has caused all the Xbox 360 projects to be sorted together at the bottom, which is somewhat convenient. But if I wanted to rename them (which I normally do), then I'd lose that organization... &lt;p&gt;&lt;a href="http://byfiles.storage.msn.com/y1pDl-u-7dR2WRlYsOVbr-qTeVnDk4qw_oJCtqc4vTaz8e8-_fMHify7rGcnV-c254RpgO0yATTwmg?PARTNER=WRITER"&gt;&lt;img style="border-top-width:0px;border-left-width:0px;border-bottom-width:0px;border-right-width:0px" height=229 alt=image src="http://byfiles.storage.msn.com/y1pDl-u-7dR2WQV3r9Muie5nNdAXiufF9lkrGupHu1mkrs6HkZDHftVBrxwUKSWrwPjXwRcqwNe-Og?PARTNER=WRITER" width=244 border=0&gt;&lt;/a&gt;  &lt;p&gt;Bleah! If I don't keep these projects collapsed, how am I going to find anything?! :-P &lt;p&gt;One answer is to create some Solution Folders. If I create one for Windows, one for Xbox 360, and one for Content Pipeline, then I can organize my solution thusly... &lt;p&gt;&lt;a href="http://byfiles.storage.msn.com/y1pDl-u-7dR2WRYz7CCl8d01kpDFFHTc_PRUEqkCH9y2_agVHy6G402hPDVTw2_t4C4APVi8R7fKzA?PARTNER=WRITER"&gt;&lt;img style="border-top-width:0px;border-left-width:0px;border-bottom-width:0px;border-right-width:0px" height=244 alt=image src="http://byfiles.storage.msn.com/y1pDl-u-7dR2WS1ar9vPGGyv92EgBzzf97JCwJHY7MxAYM1-3r8hrr7L72oI-p33eFCahZF4IjEBBg?PARTNER=WRITER" width=221 border=0&gt;&lt;/a&gt;  &lt;p&gt;The solution folders let me organize the projects by platform, and it's easy to collapse them so the projects for the platform I'm not working on don't get in the way. Okay, now back to my clogged-sinus-induced daydream... &lt;p&gt;I started to wonder what it would be like if these solution folders were created automatically. Maybe the folder for the platform you're not working on could be collapsed automatically, too. I thought that might be neat. Not too elegant, but maybe it would work for some people. I mean, if the cross-platform copies of the projects could automatically stay in sync with the originals, then you would hardly ever need to switch from one to another. Then I wondered if they could be hidden altogether. I found the answer &lt;a href="http://blogs.msdn.com/saraford/archive/2008/02/22/did-you-know-you-can-use-solution-folders-to-hide-projects-157.aspx"&gt;here&lt;/a&gt;. That's cool, I thought, I wonder how we could use that...? &lt;p&gt;At some point, I realized I'd been staring at the same syntax error in the code window for thirty minutes, and I'd written only about four lines of new code all morning. So I went home. &lt;p&gt;After I got home, I turned on my trusty laptop and spent ten minutes writing a VS macro. The macro looked at the active solution configuration's platform name, and hid any solution folders that didn't match. The first attempt showed a big flaw in that logic, since the default platform name is &amp;quot;Mixed Platforms&amp;quot;. I added a special case for that. Then I added another special case to ignore any solution folder that wasn't a valid platform name. For a mere half-hour of VB programming, it worked pretty good. &lt;p&gt;I searched around to find an event to trigger the macro when the active configuration changed, but I wasn't able to find one. Unfortunately, that means I'll need to write an add-in to make it work. When I feel a bit better, I think I'll do that!&lt;img src="http://c.services.spaces.live.com/CollectionWebService/c.gif?cid=4894130425169106705&amp;page=RSS%3a+Dreaming+of+a+Cross-Platform+Utopia&amp;referrer=" width="1px" height="1px" border="0" alt=""&gt;&lt;img style="position:absolute" alt="" width="0px" height="0px" src="http://c.live.com/c.gif?NC=31263&amp;amp;NA=1149&amp;amp;PI=73329&amp;amp;RF=&amp;amp;DI=3919&amp;amp;PS=85545&amp;amp;TP=badcorporatelogo.spaces.live.com&amp;amp;GT1=badcorporatelogo"&gt;</description><comments>http://badcorporatelogo.spaces.live.com/Blog/cns!43EB71B104A2D711!220.entry#comment</comments><guid isPermaLink="true">http://badcorporatelogo.spaces.live.com/Blog/cns!43EB71B104A2D711!220.entry</guid><pubDate>Sat, 29 Mar 2008 03:13:05 GMT</pubDate><slash:comments>2</slash:comments><msn:type>blogentry</msn:type><live:type>blogentry</live:type><live:typelabel>Blog entry</live:typelabel><wfw:commentRss>http://badcorporatelogo.spaces.live.com/blog/cns!43EB71B104A2D711!220/comments/feed.rss</wfw:commentRss><wfw:comment>http://badcorporatelogo.spaces.live.com/Blog/cns!43EB71B104A2D711!220.entry#comment</wfw:comment><dcterms:modified>2008-03-29T03:13:05Z</dcterms:modified></item><item><title>Feature Requests from Cannibals in the Caribbean</title><link>http://badcorporatelogo.spaces.live.com/Blog/cns!43EB71B104A2D711!209.entry</link><description>&lt;p&gt;I've recently returned from the 3rd Annual Conference for Game Development in Computer Science Education (&lt;a href="http://www.microsoft4me.com/faculty/events/adgd2008/"&gt;GDCSE&lt;/a&gt;). Oddly enough, I went to this conference primarily for vacation! It sounds a lot less odd when you realize that the conference was held on a cruise ship floating around the Caribbean! I really enjoyed it, even though I wasn't able to use my laptop while snorkeling... ;-) &lt;p&gt;Although I primarily focused on enjoying the beautiful weather and luxurious surroundings with my wife, I did mingle with the conference attendees during dinner and other social events. I was really surprised at how many conference attendees were already using the XNA Framework and XNA Game Studio in their schools. When I asked for feedback, most people said that our recent announcements for v3.0 addressed their primary asks. In particular, the ability to publish games. They see it as a great way to motivate students to complete course projects! &lt;p&gt;One evening, I met three guys from &lt;a href="http://www.cannibalgamestudios.com/index.html"&gt;Cannibal Game Studios&lt;/a&gt;. Their company makes a game engine that they license to schools for educational purposes. They described their primary goal as ease-of-use, to maximize productivity. They said that the XNA Framework and XNA Game Studio was a natural fit (an earlier version of their engine was built on Managed DirectX). &lt;p&gt;The guys from Cannibal Game Studios took advantage of the opportunity to give me product feedback. There were two main feature requests/criticisms that they made: &lt;ol&gt; &lt;li&gt;Configure a single asset in the Content project to be processed more than once by the Content Pipeline. &lt;li&gt;Use a single project to handle multiple platforms.&lt;/ol&gt; &lt;p&gt;This is really great feedback! Unfortunately, I'm never allowed to promise anything, no matter how much I want to do it. I think they thought I was not really interested. :-( &lt;p&gt;Well, I actually think the first feature is really compelling! The second, unfortunately, probably isn't going to happen very soon. &lt;p&gt;Initially, I asked them to elaborate on why they'd want to process an asset more than once. They used &lt;a href="http://en.wikipedia.org/wiki/COLLADA"&gt;COLLADA&lt;/a&gt; files as an example. In COLLADA files, there can be several kinds of data, like geometry, animation, and physics. In a lot of games or game engines, it makes sense to store the different kinds of data in different objects. Likewise, when processing the data, it makes sense to process geometry, animation, and physics separately. The XNA Game Studio Content Pipeline makes this hard because, for a single COLLADA file, you have to import everything all at once! You can process the data separately, but before you can do that, you need to aggregate your various data processors by writing a mega-processor that splits up the data and farms out the work to more targeted processors. This is something they feel should be handled by the Content Pipeline. Or, at least it should be &lt;em&gt;way &lt;/em&gt;easier. I completely agree! This is definitely going on the long list of features to consider adding in a future version... &lt;p&gt;The second big thing they wanted is the ability to develop for multiple platforms in a single project. We actually wanted that in XNA Game Studio Express 1.0, and we got as far as implementing it halfway. Then, while planning for version 2.0, we realized that we'd never have enough time to complete it between one version and the next. At least, not without putting a bunch of restrictions on what you can do in an XNA Game project. The problem is that there are things that make sense in a Windows project that don't make sense in an Xbox 360 project. The same goes for Zune projects, for that matter. (Yes, we've had Zune on our minds for quite some time.) When developing for different platforms, the IDE needs to behave differently, and developers may want to work with different kinds of project items. Changing the project system to make all of these features conditional is a great deal of work -- work that we don't need to do if we let each platform have its own project. &lt;p&gt;That's why we have the multi-project system that I described in several earlier posts. It was a lot easier to develop a system to convert a project from one platform to another. Although this didn't lead to an ideal development experience, it was something we could do in a short amount of time, and it was something we could improve on in subsequent releases. &lt;p&gt;In the multi-project scenario, I think there are three main difficulties: &lt;ol&gt; &lt;li&gt;Keeping the two projects in synch when adding, renaming, or removing items. &lt;li&gt;The Solution Explorer makes it look like there are two copies of everything, and it gets hard to manage bigger projects when you see two of everything. &lt;li&gt;Although I mentioned working with &lt;em&gt;two &lt;/em&gt;of everything, we will add Zune support in XGS 3.0, and probably more platforms at some point in the future. The complexity of working with multiple platforms will grow with the number of platforms, forcing you to have three of everything, or four, etc.&lt;/ol&gt; &lt;p&gt;To address the first big problem, we're going to look at automatically synchronizing projects that have been created with our cross-platform wizard. I think the default behavior should assume you want the projects as similar as possible, but would give you the option of excluding items from a specific project when it doesn't belong. &lt;p&gt;To address the second big problem, I've been thinking about customizing the view in the Solution Explorer. When you clone a project, you don't get two copies of everything -- but each file is &lt;em&gt;represented &lt;/em&gt;twice in the Solution Explorer. If we were to hide the projects that are inactive, I think the cross-platform development experience would be a lot more like having one project for all platforms. That is, assuming we synchronize them automatically as discussed above. &lt;p&gt;The third issue is a problem of scalability. It basically means that the first two problems will get worse if we don't address them. However, I think the scalability problem goes away if we can both synchronize the multiple projects automatically, and present a smarter view of the solution. &lt;p&gt;If you're interested in the XNA Game Studio development experience, send me your feedback. What new feature would you like to see? What are you trying to do that you find difficult? Leave a comment or send me a message. Better yet, file the request on &lt;a href="https://connect.microsoft.com/feedback/CreateFeedbackForm.aspx?FeedbackFormConfigurationID=885&amp;amp;FeedbackType=1&amp;amp;SiteID=226"&gt;Connect&lt;/a&gt; (don't forget to &lt;a href="https://connect.microsoft.com/feedback/Search.aspx?SiteID=226"&gt;search&lt;/a&gt; for an existing request first)!&lt;img src="http://c.services.spaces.live.com/CollectionWebService/c.gif?cid=4894130425169106705&amp;page=RSS%3a+Feature+Requests+from+Cannibals+in+the+Caribbean&amp;referrer=" width="1px" height="1px" border="0" alt=""&gt;&lt;img style="position:absolute" alt="" width="0px" height="0px" src="http://c.live.com/c.gif?NC=31263&amp;amp;NA=1149&amp;amp;PI=73329&amp;amp;RF=&amp;amp;DI=3919&amp;amp;PS=85545&amp;amp;TP=badcorporatelogo.spaces.live.com&amp;amp;GT1=badcorporatelogo"&gt;</description><comments>http://badcorporatelogo.spaces.live.com/Blog/cns!43EB71B104A2D711!209.entry#comment</comments><guid isPermaLink="true">http://badcorporatelogo.spaces.live.com/Blog/cns!43EB71B104A2D711!209.entry</guid><pubDate>Sun, 09 Mar 2008 17:43:46 GMT</pubDate><slash:comments>0</slash:comments><msn:type>blogentry</msn:type><live:type>blogentry</live:type><live:typelabel>Blog entry</live:typelabel><wfw:commentRss>http://badcorporatelogo.spaces.live.com/blog/cns!43EB71B104A2D711!209/comments/feed.rss</wfw:commentRss><wfw:comment>http://badcorporatelogo.spaces.live.com/Blog/cns!43EB71B104A2D711!209.entry#comment</wfw:comment><dcterms:modified>2008-03-09T17:43:46Z</dcterms:modified></item><item><title>Keeping Cross-Platform Game Projects Synchronized</title><link>http://badcorporatelogo.spaces.live.com/Blog/cns!43EB71B104A2D711!198.entry</link><description>&lt;p&gt;In my last post, &lt;a title="http://badcorporatelogo.spaces.live.com/blog/cns!43EB71B104A2D711!197.entry" href="http://badcorporatelogo.spaces.live.com/blog/cns!43EB71B104A2D711!197.entry"&gt;Introducing Cross-Platform Development with XNA Game Studio 2.0&lt;/a&gt;, I showed how a new command in XGS 2.0 will create a copy of your project for Xbox 360 (or Windows, if you start with an Xbox 360 project). I also explained that when you do this, the only new file created is the project file (.csproj), since the files it contains are the same files as the original project (they are shared). The resulting solution has two projects, but on disk there is only one directory and only one copy of each file. &lt;p&gt;Working with this kind of solution has a few catches. In particular, you have to take care when you manipulate the files that are shared between the projects. That means any time you add, remove, rename, or move files in one project, you'll probably have to do a quick, manual fix-up in the other. The good news is that future versions of XNA Game Studio can make these actions automatic. The bad news is that the current version does not. :-( &lt;p&gt;Here's a quick-reference chart of file operations to be careful with: &lt;table cellspacing=0 cellpadding=2 width=400 border=1&gt; &lt;tbody&gt; &lt;tr&gt; &lt;td valign=top width=139&gt; &lt;h5&gt;Operation&lt;/h5&gt; &lt;td valign=top width=145&gt; &lt;h5&gt;Problem&lt;/h5&gt; &lt;td valign=top width=114&gt; &lt;h5&gt;Quick Solution&lt;/h5&gt; &lt;tr&gt; &lt;td valign=top width=139&gt;Add new item/folder &lt;td valign=top width=145&gt;File is not added to the other copy of the project. &lt;td valign=top width=114&gt;In Solution Explorer, click and drag the file into the other project. &lt;tr&gt; &lt;td valign=top width=139&gt;Remove an item/folder &lt;td valign=top width=145&gt;Item is not removed from the other project. Depending on what you intended, this might be desirable. &lt;td valign=top width=114&gt;If you want to remove it from the other project, just repeat the same command on the other project. &lt;tr&gt; &lt;td valign=top width=139&gt;Delete an item/folder &lt;td valign=top width=145&gt;The item will be deleted from disk, even if it is still being used by the other project. &lt;td valign=top width=114&gt;If you don't want to delete the item from both projects, use the Remove command instead. &lt;tr&gt; &lt;td valign=top width=139&gt;Rename an item/folder &lt;td valign=top width=145&gt;The other project will be unaware of the rename. When you compile, the old file name will not be found. &lt;td valign=top width=114&gt;Exclude the unresolved item from the other project, then add the renamed item to it. &lt;tr&gt; &lt;td valign=top width=139&gt;Move an item/folder &lt;td valign=top width=156&gt;Similar to renaming, the other project will be unaware of the move, and the old item name won't be found. &lt;td valign=top width=146&gt;Exclude the unresolved item from the other project, then add the moved item to it.&lt;/tbody&gt;&lt;/table&gt; &lt;p&gt;Each project maintains a list of its items, both files and folders, in its project file (.csproj). In XGS 2.0, we didn't have enough time to implement automatic support for these scenarios. However, when a project is copied using our wizard, a marker is placed in the project to identify the relationship between the original and its copy. That marker means that a future version of XGS can start handling these things automatically. &lt;p&gt;Another feature of XNA Game Studio 2.0 is the nested content project. When you create a new game or game library project, it contains a special &amp;quot;Content&amp;quot; folder for your game's digital content. This special folder is not really a folder at all -- it's another project that compiles game assets with the &lt;a href="http://msdn2.microsoft.com/en-us/library/bb203887.aspx"&gt;XNA Game Studio Content Pipeline&lt;/a&gt;. &lt;p&gt;&lt;img src="http://byfiles.storage.msn.com/y1pDl-u-7dR2WS4LteC5XoODBJN1OjraUj5IQKBzbDj6_1qLtCUOzbKWI40K6E0_XnqRnQHNMrQNag?PARTNER=WRITER"&gt; &lt;p&gt;When you use the built-in &amp;quot;Create Copy of &amp;lt;Project&amp;gt; for &amp;lt;Other Platform&amp;gt;&amp;quot; command, the new project will contain the very same Content sub-project, much like it contains the very same code files. The cool thing about having both projects share the same Content sub-project is that when you make changes in the Content project, you don't have to synchronize them in the other platform's copy. There isn't another copy of the Content project, so any changes automatically affect both platforms. &lt;p&gt;The benefit of this behavior becomes more clear as you start to add more and more content to your game. Even medium-sized games can easily grow to have a couple thousand content items, so the less manual synchronization you have to do, the better. &lt;p&gt;As well, we introduced the ability to configure &lt;a href="http://msdn2.microsoft.com/en-us/library/bb975255.aspx"&gt;Processor Parameters&lt;/a&gt; on individual content items. For example, there is a parameter to change the scale of your models, and one to set the transparent color of your sprites. Imagine if you had to set these in two places. If you forgot to change it in the second project, then you might end up with strange bugs like a model that is scaled wrong on Xbox 360 but not on Windows. Trying to figure out what went wrong would be a real pain! &lt;p&gt;One thing you can't do in XGS 2.0 is add a content item to a Content project and have it be platform-specific. Each code project has exactly one nested Content project, and all copies of the same code project share the same Content sub-project. In the future, we want to add the ability to add additional Content sub-projects to a game, and let you decide whether to share them or not (again, like code files). That way, you'd be able to share the majority of your content from Xbox 360 and Windows, but you'd also be able to add an additional, non-shared project to each of the code projects for platform-specific assets. Say, like title screens with different logos, or different input options for console/PC. &lt;p&gt;For the most part, it's no big deal if you just add everything to both projects, but if you have a lot of content that is platform-specific, then it could be important to you to reduce the overall size of the game. &lt;h3&gt;Making Improvements in XNA Game Studio 3.0&lt;/h3&gt; &lt;p&gt;In XGS 3.0, we'll be &lt;a href="http://blogs.msdn.com/xna/archive/2008/02/20/announcing-xna-game-studio-3-0-and-zune.aspx"&gt;adding support for Zune&lt;/a&gt;. I suspect that means more people will start working cross-platform, and it also means you may start creating three copies of the same project instead of just two. With three copies of each project, manual synchronization will make working cross-platform a lot more tedious. &lt;p&gt;Right now, the XNA Community Game Platform team is prioritizing features for the XGS 3.0 and planning out who will work on what. If you're interested in doing cross-platform development, and you want us to invest time in making the experience better, please post a comment here, or start a thread in the &lt;a href="http://forums.xna.com/"&gt;creators.xna.com forums&lt;/a&gt;, or &lt;a href="http://creators.xna.com/Feedback.aspx"&gt;send us feedback&lt;/a&gt; to ask us to make cross-platform development easier. The more demand there is, the more likely we are to assign resources to fix the problems. &lt;p&gt;Be sure to let us know what features you want the most -- which ones do you currently have problems with, and which new features would you like to see added.&lt;img src="http://c.services.spaces.live.com/CollectionWebService/c.gif?cid=4894130425169106705&amp;page=RSS%3a+Keeping+Cross-Platform+Game+Projects+Synchronized&amp;referrer=" width="1px" height="1px" border="0" alt=""&gt;&lt;img style="position:absolute" alt="" width="0px" height="0px" src="http://c.live.com/c.gif?NC=31263&amp;amp;NA=1149&amp;amp;PI=73329&amp;amp;RF=&amp;amp;DI=3919&amp;amp;PS=85545&amp;amp;TP=badcorporatelogo.spaces.live.com&amp;amp;GT1=badcorporatelogo"&gt;</description><comments>http://badcorporatelogo.spaces.live.com/Blog/cns!43EB71B104A2D711!198.entry#comment</comments><guid isPermaLink="true">http://badcorporatelogo.spaces.live.com/Blog/cns!43EB71B104A2D711!198.entry</guid><pubDate>Sun, 24 Feb 2008 19:13:15 GMT</pubDate><slash:comments>0</slash:comments><msn:type>blogentry</msn:type><live:type>blogentry</live:type><live:typelabel>Blog entry</live:typelabel><wfw:commentRss>http://badcorporatelogo.spaces.live.com/blog/cns!43EB71B104A2D711!198/comments/feed.rss</wfw:commentRss><wfw:comment>http://badcorporatelogo.spaces.live.com/Blog/cns!43EB71B104A2D711!198.entry#comment</wfw:comment><dcterms:modified>2008-02-24T19:13:15Z</dcterms:modified></item><item><title>Introducing Cross-Platform Development with XNA Game Studio 2.0</title><link>http://badcorporatelogo.spaces.live.com/Blog/cns!43EB71B104A2D711!197.entry</link><description>&lt;p&gt;XNA Game Studio (XGS) provides development tools for building games with C#, and the XNA Framework provides a platform to run them on. One really cool feature of the XNA Framework is that it is available for both Windows and Xbox 360. Source code written against the XNA Framework is portable, meaning that the same source code can be compiled for either Windows or Xbox 360. Unfortunately, standard C# projects in Visual Studio don't make it easy for one project to target multiple platforms, so XGS 2.0 introduced a couple new features to smooth things over. &lt;p&gt;This article is an introduction to cross-platform programming in XGS 2.0. In future versions of XGS, we'll be adding support for more platforms (eg, Zune in XGS 3.0!). That will make it even more important to understand cross-platform development. &lt;p&gt;First off, most of the XNA Framework API is cross-platform (something like 99%). That means you almost don't have to do &lt;em&gt;anything &lt;/em&gt;to make your source code portable to either Windows or Xbox 360. Whichever platform you started writing your game for, basically the exact same source code can be used for the other. That's the premise behind the &lt;strong&gt;Create Copy of &amp;lt;Project&amp;gt; for &amp;lt;Other Platform&amp;gt; &lt;/strong&gt;command. This command can be found on the &lt;strong&gt;Project&lt;/strong&gt; menu, and also the project context menu. &lt;p&gt;&lt;a href="http://byfiles.storage.msn.com/y1pDl-u-7dR2WR_0T5licOQf9XFR9VCOuZ-KFj0BbTRtDWw6-cqRFYUBeq_P0qCHt08iJ_0HrAsr9Q?PARTNER=WRITER"&gt;&lt;img style="border-top-width:0px;border-left-width:0px;border-bottom-width:0px;border-right-width:0px" height=216 alt=image src="http://byfiles.storage.msn.com/y1pDl-u-7dR2WR6i1jyj7VBITXVDiMpCghsK2EqdCsGYYdP0TvSUJ-WCLeoUp5aj4SdcJTvwZOQxxg?PARTNER=WRITER" width=244 border=0&gt;&lt;/a&gt;  &lt;p&gt;I don't like using &amp;quot;create copy of&amp;quot; as the name of a command, so for the rest of this article, I'm going to call it the &lt;strong&gt;Clone Project &lt;/strong&gt;command. &lt;p&gt;When you start with a Windows game and clone the project for Xbox 360, the command creates a whole new project and adds it to your solution. The figure below illustrates the outcome. &lt;p&gt;&lt;a href="http://byfiles.storage.msn.com/y1pDl-u-7dR2WSAJ8_SxNQwvHm-Ophe-EFNWz9LAJPBP1j3O4aMlkEs9Yys6ikl5kEg6D4VlNnUSCI?PARTNER=WRITER"&gt;&lt;img style="border-top-width:0px;border-left-width:0px;border-bottom-width:0px;border-right-width:0px" height=244 alt=image src="http://byfiles.storage.msn.com/y1pDl-u-7dR2WREYGk2X3G_-fdo8zWEt2fNl6ISyssn3wfdnnFfNu3yhy9ZJQ5B1p77yldPSE-FkMM?PARTNER=WRITER" width=187 border=0&gt;&lt;/a&gt;  &lt;p&gt;This view of the solution suggests that there are two copies of everything. That isn't really the case. The Solution Explorer provides a hierarchical view of the solution and its projects. While there are two projects shown, and each has an item called Game1.cs, it is actually the &lt;em&gt;same &lt;/em&gt;Game1.cs file in both projects. That is, the one file belongs to two projects. &lt;p&gt;Ultimately, the entire cloned project is really only one file. No matter how many items you have in your game project, cloning the project will always create exactly &lt;strong&gt;one &lt;/strong&gt;new file. Ever. &lt;p&gt;At this point you might be wondering why you'd want another project if all the source files are the same anyway. Well, the primary reason is that there are more than just files in the project. Each project has a &lt;strong&gt;References &lt;/strong&gt;node (represented by an expandable gray folder-like icon). If you expand the &lt;strong&gt;References &lt;/strong&gt;node, you'll see the list of assembly references used to build the code in the project. The assemblies referenced are different for the different platforms, and that's the primary thing that distinguishes the output of a Windows project from that of an Xbox 360 project. &lt;p&gt;Another difference is that the Windows game targets the .NET Framework 2.0, while the Xbox 360 game targets a custom version of the .NET Compact Framework (NetCF) 3.5. For the most part, the NetCF Base Class Library (BCL) is a subset of the .NET Framework BCL. That means the types in the NetCF BCL are almost always exactly the same as what's in the .NET Framework BCL, except when they're not there at all. &lt;p&gt;For that reason, there are features you can use in a Windows project that you can't use in an Xbox 360 project. As an example, you could add a &lt;strong&gt;Web Reference &lt;/strong&gt;from your Windows game to a web service. There is no support for web services on the Xbox 360, in part because the base classes are missing from the NetCF BCL, and in part because Xbox 360 games aren't allowed to connect to non-Xbox LIVE endpoints. &lt;p&gt;If you try to clone a Windows project with web references, the files will be removed from the Xbox 360 project. This means your new project won't compile initially, but at least the Error List will tell you where you need to fix up your code. Fixing the code usually means conditionally-compiling the parts that are platform-specific. Xbox 360 projects define the preprocessor symbols XBOX and XBOX360 by default for your cross-platform coding convenience. &lt;p&gt;One thing to note when editing code in a file shared by two projects is that you'll get &lt;a href="http://msdn2.microsoft.com/en-us/library/hcw1s69b(VS.80).aspx"&gt;Intellisense&lt;/a&gt; for the project that opened it. That means if you double-click the file under the Windows project to open it, the editor will give you syntax highlighting and statement completion that matches your Windows project settings. To switch the Intellisense to match your Xbox 360 project settings, including syntax highlighting on conditionally-compiled blocks of code, just close the file and reopen it from under the Xbox 360 project. &lt;blockquote&gt; &lt;p&gt;&lt;strong&gt;Tip: &lt;/strong&gt;Since the classes available for Xbox 360 projects are generally a subset of the ones available for Windows, you're less likely to write non-portable code if you always open the files from the Xbox 360 project.&lt;/blockquote&gt; &lt;p&gt;Another feature that isn't supported in Xbox 360 projects is Windows Forms. The System.Windows.Forms.dll assembly isn't part of the BCL for Xbox 360, so you can't use Forms in your Xbox 360 games. However, there are times when you might want to use Windows Forms in a Windows version of your game. As an example, you might want a custom form to display an error message if someone tries to run your game on a Windows machine without adequate shader support. &lt;p&gt;For Forms and Controls, you can't just conditionally-compile the entire class because of the code-behind file (a designer-generated file). Windows Forms use partial classes and tool-generated code that you can't edit by hand. So to remove these types from your Xbox 360 game project, you need to &lt;strong&gt;Remove &lt;/strong&gt;the code files from your Xbox 360 project (use the &lt;strong&gt;Remove &lt;/strong&gt;command, not &lt;strong&gt;Delete&lt;/strong&gt;), and then conditionally-compile any code that references the type. &lt;blockquote&gt; &lt;p&gt;&lt;strong&gt;Tip: &lt;/strong&gt;Deleting files is dangerous! Remember that even if the file belongs to more than one project, there is only one physical file. If you &lt;strong&gt;Delete&lt;/strong&gt; it, it will be unavailable to all projects! By contrast, the &lt;strong&gt;Remove &lt;/strong&gt;command will remove a file from the project without deleting it.&lt;/blockquote&gt; &lt;p&gt;Well, that's enough to get you started. Next time, I'll write about adding new files, renaming files, and working with Content projects. &lt;p&gt;Cheers!&lt;img src="http://c.services.spaces.live.com/CollectionWebService/c.gif?cid=4894130425169106705&amp;page=RSS%3a+Introducing+Cross-Platform+Development+with+XNA+Game+Studio+2.0&amp;referrer=" width="1px" height="1px" border="0" alt=""&gt;&lt;img style="position:absolute" alt="" width="0px" height="0px" src="http://c.live.com/c.gif?NC=31263&amp;amp;NA=1149&amp;amp;PI=73329&amp;amp;RF=&amp;amp;DI=3919&amp;amp;PS=85545&amp;amp;TP=badcorporatelogo.spaces.live.com&amp;amp;GT1=badcorporatelogo"&gt;</description><comments>http://badcorporatelogo.spaces.live.com/Blog/cns!43EB71B104A2D711!197.entry#comment</comments><guid isPermaLink="true">http://badcorporatelogo.spaces.live.com/Blog/cns!43EB71B104A2D711!197.entry</guid><pubDate>Fri, 22 Feb 2008 06:31:17 GMT</pubDate><slash:comments>0</slash:comments><msn:type>blogentry</msn:type><live:type>blogentry</live:type><live:typelabel>Blog entry</live:typelabel><wfw:commentRss>http://badcorporatelogo.spaces.live.com/blog/cns!43EB71B104A2D711!197/comments/feed.rss</wfw:commentRss><wfw:comment>http://badcorporatelogo.spaces.live.com/Blog/cns!43EB71B104A2D711!197.entry#comment</wfw:comment><dcterms:modified>2008-02-22T06:31:17Z</dcterms:modified></item><item><title>Shameless Self-Promotion</title><link>http://badcorporatelogo.spaces.live.com/Blog/cns!43EB71B104A2D711!187.entry</link><description>&lt;p&gt;My coworker, Nazeeh, writes a much slicker blog than I do. He's started a series of interviews with the XNA Community Game Platform team (the team that makes XNA Game Studio and the XNA Framework). It just so happens that I'm on that team, and last week, Nazeeh focused his attention on me! Check it out! &lt;p&gt;&lt;a title="http://www.nazspace.com/wp/2008/02/03/team-interview-stephen-styrchak/" href="http://www.nazspace.com/wp/2008/02/03/team-interview-stephen-styrchak/"&gt;http://www.nazspace.com/wp/2008/02/03/team-interview-stephen-styrchak/&lt;/a&gt;&lt;img src="http://c.services.spaces.live.com/CollectionWebService/c.gif?cid=4894130425169106705&amp;page=RSS%3a+Shameless+Self-Promotion&amp;referrer=" width="1px" height="1px" border="0" alt=""&gt;&lt;img style="position:absolute" alt="" width="0px" height="0px" src="http://c.live.com/c.gif?NC=31263&amp;amp;NA=1149&amp;amp;PI=73329&amp;amp;RF=&amp;amp;DI=3919&amp;amp;PS=85545&amp;amp;TP=badcorporatelogo.spaces.live.com&amp;amp;GT1=badcorporatelogo"&gt;</description><comments>http://badcorporatelogo.spaces.live.com/Blog/cns!43EB71B104A2D711!187.entry#comment</comments><guid isPermaLink="true">http://badcorporatelogo.spaces.live.com/Blog/cns!43EB71B104A2D711!187.entry</guid><pubDate>Wed, 06 Feb 2008 06:07:52 GMT</pubDate><slash:comments>0</slash:comments><msn:type>blogentry</msn:type><live:type>blogentry</live:type><live:typelabel>Blog entry</live:typelabel><wfw:commentRss>http://badcorporatelogo.spaces.live.com/blog/cns!43EB71B104A2D711!187/comments/feed.rss</wfw:commentRss><wfw:comment>http://badcorporatelogo.spaces.live.com/Blog/cns!43EB71B104A2D711!187.entry#comment</wfw:comment><dcterms:modified>2008-02-06T06:07:52Z</dcterms:modified></item><item><title>Debugging Custom Content Pipeline Extensions (Part 3)</title><link>http://badcorporatelogo.spaces.live.com/Blog/cns!43EB71B104A2D711!169.entry</link><description>&lt;p&gt;If you've ever used Debug.Launch() to debug a custom Content Pipeline extension in XNA Game Studio 2.0, this post is for you. If you've ever wanted to just press &lt;strong&gt;F5&lt;/strong&gt; and be able to debug your content builds, you're in luck! I've finished a project template that allows integrated debugging of the Content Pipeline from Visual Studio or Visual C# Express. &lt;p&gt;I've uploaded the template to my SkyDrive. Click the download link to get your own copy! &lt;p&gt;&lt;a href="http://cid-43eb71b104a2d711.skydrive.live.com/self.aspx/XNA Game Studio 2.0/debugtemplate.vsi"&gt;Download debugtemplate.vsi&lt;/a&gt; &lt;p&gt;The file is a Visual Studio Installer (.vsi) file, and it will install the template into your XNA Game Studio 2.0 project template folder as long as you already have XGS 2.0 installed. Please note that I did not sign the file, so you will get a warning when you install it. Install it at your own risk. &lt;p&gt;Once you create a project from the template, a readme file will open up to explain how to use it. Let me know what you think. If it's useful, maybe it'll get rolled into the next version of XGS.&lt;img src="http://c.services.spaces.live.com/CollectionWebService/c.gif?cid=4894130425169106705&amp;page=RSS%3a+Debugging+Custom+Content+Pipeline+Extensions+(Part+3)&amp;referrer=" width="1px" height="1px" border="0" alt=""&gt;&lt;img style="position:absolute" alt="" width="0px" height="0px" src="http://c.live.com/c.gif?NC=31263&amp;amp;NA=1149&amp;amp;PI=73329&amp;amp;RF=&amp;amp;DI=3919&amp;amp;PS=85545&amp;amp;TP=badcorporatelogo.spaces.live.com&amp;amp;GT1=badcorporatelogo"&gt;</description><comments>http://badcorporatelogo.spaces.live.com/Blog/cns!43EB71B104A2D711!169.entry#comment</comments><guid isPermaLink="true">http://badcorporatelogo.spaces.live.com/Blog/cns!43EB71B104A2D711!169.entry</guid><pubDate>Fri, 25 Jan 2008 09:57:19 GMT</pubDate><slash:comments>0</slash:comments><msn:type>blogentry</msn:type><live:type>blogentry</live:type><live:typelabel>Blog entry</live:typelabel><wfw:commentRss>http://badcorporatelogo.spaces.live.com/blog/cns!43EB71B104A2D711!169/comments/feed.rss</wfw:commentRss><wfw:comment>http://badcorporatelogo.spaces.live.com/Blog/cns!43EB71B104A2D711!169.entry#comment</wfw:comment><dcterms:modified>2008-01-25T09:57:53Z</dcterms:modified></item><item><title>Debugging Custom Content Pipeline Extensions (Part 2)</title><link>http://badcorporatelogo.spaces.live.com/Blog/cns!43EB71B104A2D711!166.entry</link><description>&lt;p&gt;In my previous post, I described what happens when you press &lt;strong&gt;F5&lt;/strong&gt; to debug a game project, and explained why you can't debug your Content Pipeline Extension Library projects that way. However, I also described many ways in which &lt;strong&gt;F5&lt;/strong&gt; actions can be customized. By tweaking the settings in just the right ways, it turns out that you &lt;em&gt;can&lt;/em&gt; debug your Content Pipeline Extension Library projects in the IDE. Here's how you do it... &lt;p&gt;XNA Game Studio (XGS) 2.0 projects use a nested Content project to build content. If you look at your project directory in Explorer, you'll find a file called &lt;strong&gt;content.contentproj&lt;/strong&gt;. That's the MSBuild project that builds all your content. &lt;p&gt;If you want to debug custom components that you use to extend the Content Pipeline, it's as easy as debugging msbuild.exe while it builds the &lt;strong&gt;content.contentproj&lt;/strong&gt; project file. In &lt;strong&gt;Visual Studio 2005&lt;/strong&gt; (VS), you can accomplish this by changing your &lt;strong&gt;Startup Project&lt;/strong&gt; to launch an external program (msbuild.exe) and pass it the path to your content.contentproj file as a command-line argument (this is described in the XGS documentation, near the bottom of this page on &lt;a href="http://msdn2.microsoft.com/en-us/library/bb447754.aspx"&gt;How To: Write a Custom Importer and Processor&lt;/a&gt;). The problem, however, is that it's still difficult to set up, and the options described aren't available in &lt;strong&gt;Visual C# 2005 Express Edition&lt;/strong&gt; (VCSExpress). &lt;p&gt;It turns out that although there is no user interface to change the startup program in VCSExpress, the ability to launch and debug another application is still there. If you want to have a C# &lt;strong&gt;Startup Project&lt;/strong&gt; launch msbuild.exe when you start debugging, all you need to do is add the following XML to its .csproj file (after the &amp;lt;Import&amp;gt; element near the bottom is a good spot). &lt;table cellspacing=0 cellpadding=2 width=400 border=0&gt; &lt;tbody&gt; &lt;tr&gt; &lt;td valign=top width=400&gt;&amp;lt;PropertyGroup&amp;gt;&lt;br&gt;  &amp;lt;StartAction&amp;gt;Program&amp;lt;/StartAction&amp;gt;&lt;br&gt;  &amp;lt;StartProgram&amp;gt;$(MSBuildBinPath)\msbuild.exe&amp;lt;/StartProgram&amp;gt;&lt;br&gt;  &amp;lt;StartWorkingDirectory&amp;gt;$(ProjectDir)&amp;lt;/StartWorkingDirectory&amp;gt;&lt;br&gt;&amp;lt;/PropertyGroup&amp;gt;&lt;/tbody&gt;&lt;/table&gt; &lt;p&gt;If you want to debug your Content Pipeline components, then you need to add another property, StartArguments, to specify the .contentproj to build, the platform to build it for (Xbox 360 or Windows), and the configuration to build (Debug or Release). &lt;p&gt;It can get a bit long, but to do it right, you need something like this...  &lt;table cellspacing=0 cellpadding=2 width=400 border=0&gt; &lt;tbody&gt; &lt;tr&gt; &lt;td valign=top width=400&gt;&amp;lt;StartArguments&amp;gt;&amp;quot;Content\Content.contentproj&amp;quot; /p:Configuration=&amp;quot;$(Configuration)&amp;quot; /p:Platform=&amp;quot;$(Platform)&amp;quot; /p:XnaPlatform=&amp;quot;$(XnaPlatform)&amp;quot; /p:ParentProjectDir=&amp;quot;$(ProjectDir)&amp;quot;&amp;lt;/StartArguments&amp;gt; &lt;/tbody&gt;&lt;/table&gt; &lt;p&gt;If you add these properties to your game project (or game library project), it will launch and debug msbuild.exe as it builds the project's content using the Content Pipeline. That will let you hit breakpoints in your Content Pipeline Extension Library project after hitting &lt;strong&gt;F5&lt;/strong&gt;. &lt;p&gt;The caveat to all this is that it's tedious. It's also a bit dangerous to edit the XML project files directly, because if you don't know exactly what you're doing, you can end up with a project that won't load, and no idea how to fix it! &lt;p&gt;One way to make this super convenient and risk-free would be to have a project template to create projects already configured to debug the Content Pipeline! Well, stay tuned! That will be my next post...&lt;img src="http://c.services.spaces.live.com/CollectionWebService/c.gif?cid=4894130425169106705&amp;page=RSS%3a+Debugging+Custom+Content+Pipeline+Extensions+(Part+2)&amp;referrer=" width="1px" height="1px" border="0" alt=""&gt;&lt;img style="position:absolute" alt="" width="0px" height="0px" src="http://c.live.com/c.gif?NC=31263&amp;amp;NA=1149&amp;amp;PI=73329&amp;amp;RF=&amp;amp;DI=3919&amp;amp;PS=85545&amp;amp;TP=badcorporatelogo.spaces.live.com&amp;amp;GT1=badcorporatelogo"&gt;</description><comments>http://badcorporatelogo.spaces.live.com/Blog/cns!43EB71B104A2D711!166.entry#comment</comments><guid isPermaLink="true">http://badcorporatelogo.spaces.live.com/Blog/cns!43EB71B104A2D711!166.entry</guid><pubDate>Wed, 23 Jan 2008 07:08:38 GMT</pubDate><slash:comments>0</slash:comments><msn:type>blogentry</msn:type><live:type>blogentry</live:type><live:typelabel>Blog entry</live:typelabel><wfw:commentRss>http://badcorporatelogo.spaces.live.com/blog/cns!43EB71B104A2D711!166/comments/feed.rss</wfw:commentRss><wfw:comment>http://badcorporatelogo.spaces.live.com/Blog/cns!43EB71B104A2D711!166.entry#comment</wfw:comment><dcterms:modified>2008-01-23T07:11:26Z</dcterms:modified></item><item><title>Debugging Custom Content Pipeline Extensions (Part 1)</title><link>http://badcorporatelogo.spaces.live.com/Blog/cns!43EB71B104A2D711!165.entry</link><description>&lt;p&gt;The &lt;strong&gt;XNA Framework Content Pipeline&lt;/strong&gt; (Content Pipeline) is a customizable tool included in &lt;strong&gt;XNA Game Studio&lt;/strong&gt; (XGS) for preparing digital content to be used in your games. The XNA Team Blog has an entry &lt;a href="http://blogs.msdn.com/xna/archive/2006/08/29/730168.aspx"&gt;here&lt;/a&gt; that describes the Content Pipeline, and there are several tutorials and samples on the &lt;a href="http://creators.xna.com/"&gt;XNA Creators Club Online&lt;/a&gt; web site that explain how to extend the Content Pipeline with your own custom content importers and processors. Although it is easy to add custom extensions, many people find it difficult to debug their custom components as they develop them. In this post, I'm going to explain what makes them so hard to debug, and later I'll provide instructions on how to set up your &lt;strong&gt;Visual Studio&lt;/strong&gt; or &lt;strong&gt;Visual C# Express&lt;/strong&gt; development environment to make debugging them as easy as pressing &lt;strong&gt;F5&lt;/strong&gt;. &lt;table cellspacing=0 cellpadding=2 width=400 border=0&gt; &lt;tbody&gt; &lt;tr&gt; &lt;td valign=top width=400&gt;&lt;strong&gt;Warning:&lt;/strong&gt; This is not a tutorial.&lt;/tbody&gt;&lt;/table&gt; &lt;p&gt;A number of people have asked me why they can't hit breakpoints or stop on exceptions in their Content Pipeline Extension Library projects when they debug a game project that uses it. To me, this is a bit like asking why a car doesn't fly when you drive it to the airport. It's hard to answer in a way that will lead to understanding, because I don't know why anyone would expect such a thing. Even though your trip involves flying, you don't fly during every part of the trip. Maybe it's best to start at the beginning. &lt;p&gt;The &lt;strong&gt;Start Debugging&lt;/strong&gt; command does a lot of things. In most cases, developers don't need to know or think about what those things are, because the end result is usually what they want: they get to debug their code. When that doesn't happen, it helps to know what is expected before trying to identify what went wrong. &lt;p&gt;When you press &lt;strong&gt;F5&lt;/strong&gt; in Visual Studio (the common shortcut for &lt;strong&gt;Start Debugging&lt;/strong&gt;), the following things happen: &lt;ol&gt; &lt;li&gt;The IDE determines whether any files need to be saved, and takes the appropriate action. &lt;li&gt;The IDE determines which projects to build, as well as which project configuration to build. &lt;li&gt;The IDE chooses an order in which to build the projects, based on the project dependencies. &lt;li&gt;The IDE builds each project selected in step 2, individually for its selected configuration, in the order computed in step 3. &lt;li&gt;The IDE determines which projects to deploy (this applies to Xbox 360 projects, but not Windows projects). &lt;li&gt;The IDE deploys all projects that were identified in step 5. &lt;li&gt;The IDE determines which programs to start. &lt;li&gt;The IDE launches each program identified in step 7, with the debugger attached.&lt;/ol&gt; &lt;p&gt;There are a number of ways this can be customized. &lt;ul&gt; &lt;li&gt;Step 1: The default is to save all files, but you can change the behavior in Tools Options. &lt;li&gt;Step 2: The default is to build all projects with a project configuration that matches the active solution configuration, but this can be customized in many ways. &lt;ul&gt; &lt;li&gt;Configuration Manager allows you to edit solution configurations, which are lists of projects and configurations to be built when the solution configuration is active. &lt;li&gt;There is also a command that will limit the solution build to only the &lt;strong&gt;Startup Project &lt;/strong&gt;and its dependencies. &lt;li&gt;There is an option to prompt to build deployable projects that are out of date, but otherwise not selected to be built.&lt;/ul&gt; &lt;li&gt;Step 3: Project dependencies are usually determined by project-to-project references, but you can add additional dependencies using the Project Dependencies dialog box. This information is stored in the solution file. &lt;li&gt;Step 4: See steps 2 and 3. &lt;li&gt;Step 5: You can customize which projects to deploy by editing solution configurations in Configuration Manager, and by changing the active solution configuration. &lt;li&gt;Step 6: See step 5. &lt;li&gt;Step 7: The default is to have only one startup project for a solution, but there is an option to have multiple startup projects in one solution. &lt;ul&gt; &lt;li&gt;A startup project can be configured to launch its output EXE, if it is an EXE project. &lt;li&gt;A startup project can also be configured to launch another application (option not available in VC# Express).&lt;/ul&gt; &lt;li&gt;Step 8: The IDE will start all startup projects and attach the debugger to each one so that you debug them all simultaneously. (Many developers do not realize that you can debug more than one application at once with the same IDE.)&lt;/ul&gt; &lt;p&gt;Okay, now that I've given a summary of what F5 does, let's study a particular example to see why breakpoints in a Content Pipeline Extension Library project are never hit. &lt;p&gt;Let's consider the &lt;a href="http://creators.xna.com/Headlines/developmentaspx/archive/2007/01/01/Custom-Model-Importer-Sample.aspx"&gt;Custom Model Importer Sample&lt;/a&gt; from the Creators Club Online web site. &lt;p&gt;In this sample solution, there are two projects: one Windows Game (2.0) project, called ObjImporterGameWindows, and one Content Pipeline Extension Library (2.0) project, called ObjImporter. &lt;p&gt;&lt;a href="http://by1.storage.msn.com/y1p49FnH5vGVi7POvNp4tXusyRBvvFcVBJmSAPuxNvLcOCjJhvagNUs-WL4ELlW1jY0fgywXexLMfcqyOfH3MF_08vmpiuJjtZx?PARTNER=WRITER"&gt;&lt;img style="border-right:0px;border-top:0px;border-left:0px;border-bottom:0px" height=227 alt=image src="http://by1.storage.msn.com/y1p49FnH5vGVi6nAFazLtmVClZ3h0rqMqrl9CYIAJu_ywt5zmgvK70yGjVx_3NN9OOW2cjjk8VKmlj50Ylzoa1ZlAYHqVi4CMlC?PARTNER=WRITER" width=244 border=0&gt;&lt;/a&gt;  &lt;p&gt;When I load this sample project and press F5, the following things are going to happen: &lt;ol&gt; &lt;li&gt;No files are dirty, so nothing needs to be saved. &lt;li&gt;The active solution configuration is &amp;quot;Debug|x86&amp;quot;, and that solution configuration says that both ObjImporter and ObjImporterGameWindows should be built using their respective &amp;quot;Debug|x86&amp;quot; project configurations. &lt;li&gt;ObjImporter is determined to build first, since ObjImporterGameWindows has an indirect dependency on it through its nested Content project. &lt;li&gt;The projects are built: &lt;ol&gt; &lt;li&gt;ObjImporter is built for &amp;quot;Debug|x86&amp;quot;, producing ObjImporter.dll. &lt;li&gt;ObjImporterGameWindows is built for &amp;quot;Debug|x86&amp;quot; &lt;ol&gt; &lt;li&gt;Before the code is built, ObjImporterGameWindows forces the Content subproject to build. &lt;li&gt;When the Content subproject builds, the Content Pipeline loads the ObjImporter.dll from step 4.2.1 and uses it to build the Tank.obj model. &lt;li&gt;After the Content subproject is finished building, the code in ObjImporterGameWindows is built, producing ObjImporterGameWindows.exe.&lt;/ol&gt;&lt;/ol&gt; &lt;li&gt;No projects are deployable. &lt;li&gt;Deployment is skipped. &lt;li&gt;ObjImporterGameWindows is the startup project, so ObjImporterGameWindows.exe is that application to start. &lt;li&gt;The IDE launches ObjImporterGameWindows.exe under the debugger.&lt;/ol&gt; &lt;p&gt;Now that we've covered the whole &lt;strong&gt;Start Debugging&lt;/strong&gt; process in detail, it's a lot easier to answer the original question, &amp;quot;Why don't I hit breakpoints in my Content Pipeline Extension Library project when I press &lt;strong&gt;F5&lt;/strong&gt;?&amp;quot; &lt;p&gt;&lt;strong&gt;Answer: &lt;/strong&gt;Debugging doesn't start until step 8, but the ObjImporter.dll library is loaded up and executed in step 4. &lt;p&gt;When you start debugging in the IDE, you aren't going to hit breakpoints just because they are set. You will only hit them if you debug a process that loads the corresponding binary, and the debugger can find symbols (.pdb file) that says a loaded binary came from that source file. &lt;p&gt;In the case of a Windows game, you don't start debugging until after the game EXE has been built. By that time, the Content Pipeline is already done its work. Since the breakpoints correspond to ObjImporter.dll, you won't ever hit them this way. &lt;p&gt;If you want to debug the ObjImporter.dll as it runs in the Content Pipeline, you need to debug something other than your game project. In my next post, I'll explain how to set up a solution so that &lt;strong&gt;F5&lt;/strong&gt; will debug the Content Pipeline instead of your game.&lt;img src="http://c.services.spaces.live.com/CollectionWebService/c.gif?cid=4894130425169106705&amp;page=RSS%3a+Debugging+Custom+Content+Pipeline+Extensions+(Part+1)&amp;referrer=" width="1px" height="1px" border="0" alt=""&gt;&lt;img style="position:absolute" alt="" width="0px" height="0px" src="http://c.live.com/c.gif?NC=31263&amp;amp;NA=1149&amp;amp;PI=73329&amp;amp;RF=&amp;amp;DI=3919&amp;amp;PS=85545&amp;amp;TP=badcorporatelogo.spaces.live.com&amp;amp;GT1=badcorporatelogo"&gt;</description><comments>http://badcorporatelogo.spaces.live.com/Blog/cns!43EB71B104A2D711!165.entry#comment</comments><guid isPermaLink="true">http://badcorporatelogo.spaces.live.com/Blog/cns!43EB71B104A2D711!165.entry</guid><pubDate>Sat, 19 Jan 2008 21:36:27 GMT</pubDate><slash:comments>0</slash:comments><msn:type>blogentry</msn:type><live:type>blogentry</live:type><live:typelabel>Blog entry</live:typelabel><wfw:commentRss>http://badcorporatelogo.spaces.live.com/blog/cns!43EB71B104A2D711!165/comments/feed.rss</wfw:commentRss><wfw:comment>http://badcorporatelogo.spaces.live.com/Blog/cns!43EB71B104A2D711!165.entry#comment</wfw:comment><dcterms:modified>2008-01-19T21:39:57Z</dcterms:modified></item></channel></rss>