MRandall

I have an IDrawable (DrawableGameComponent) that I wish to include in a windows/360 game component library for use by other developers or even personal reuse. To make the component more friendly and useful I would like to include some resources that are to be used by default without having to force the end user to not only include the component library, but also include any resources that the component would offer by default. Now under XNA on windows I have already figured this problem out and can embed and access embedded resources. However when my example is moved into a XBox 360 game project the function I rely on under windows, Texture2D.FromFile() is not exposed (I use a resource manifest stream to access the embedded data). I have looked into briefly, ResourceContentManager class but it expects an resx file to be part of the project that will not exist and does not do any resource loading from a stream.

The resource content will be types that are already supported by XNA, so I guess my overall question here is if I can create additive filters/content loaders/contentpipelines in/for each component that may use an embedded resource to load up that resource from the resource manifest stream

The best example as to what I am trying to do would be to embed default set of UI interface images, for a UI component instead of having to make the end user have to add the UI systems default images as well. Another example would be in a FontManager component to offer a default font that the developer can use to make the component useful immediatly out of the box.




Re: XNA Game Studio Express Embedded resources, Xbox 360, and the ContentPipeline.

Eli Tayrien - MSFT

If I'm understanding correctly, you want to distribute an assembly, and nothing else I think that's how resx files work. As far as I know, a .resx file is compiled into the final assembly, which sounds like it will work perfectly for what you want. Put your default resources through the content pipeline in the normal way, and then create a .resx file in your project. Add the compiled .xnb files to the resx. Change the ContentManager to a ResourceContentManager, and you should be good to go.

There's a bit of trickiness around how to create a ResourceManager for the ResourceContentManager, but I can't remember off the top of my head how that works. I think it wants an assembly or something I remember the call System.Assembly.GetExecutingAssembly being useful, but again I don't have the docs in front of me. Hopefully someone else will chime in with more details.





Re: XNA Game Studio Express Embedded resources, Xbox 360, and the ContentPipeline.

MRandall

Yes, I was hoping that I made enough sense to get a constructive answer. I will look into the information you gave must closer. I am keeping an eye on the thread so if there is anyone that can elaborate further I would be very greatfull. Either way, thank you for your reply. I am on my way out for the last minute xmass shopping spree so I may not get back right away, but soon as I run some tests I will have a few more questions which will be later tonight.. Thanks Eli..






Re: XNA Game Studio Express Embedded resources, Xbox 360, and the ContentPipeline.

MRandall

Ok, now that the christmass if over (Merry Christmass btw) I have tried the things that you have mentioned. What it is that I want to do is create a dll that contains an XNA component. The component required an image (Texture2D) resource to operate correctly, and I would like to embed a default image into the DLL so that when a developer adds a referance to my dll they also get the embedded image that the component requires for operation without the end user having to also add an image resource to thier XNA game project.


I have tried what you suggested and was able to compile the DLL, and what seemed to be embedded resources. So that aspect of things appears to work. In the XNA application I am testing this with, if I do a foreach loop over the GetResourceManifestNames() it does indeed show my dll assembly, and the embedded resources, so I am assuming that the resources ARE embedded. However when the DLL code comes to trying to load the resource I get an exception that the resource could not be found. Now what I do in windows is to use the FromFile() method of the Texture2D class to read the resource manifest stream, however this is not exposed on the 360. So basically things look like this, (snipped for the sake of space):


DLL Component Code:


LoadGraphicsContent()

myBatch = new SpriteBatch(this.GraphicsDevice);
myManager = new ContentManager(Game.Services);
ResourceManager rm = new ResourceManager(Assembly.GetExecutingAssembly().GetType());
resourceManager = new ResourceContentManager(Game.Services, rm);

...

Texture2D localText = resourceManager.Load<Texture2D>("myTool.myImage.png"); imageStripArray.Add(0, localText);



When the code above is executed in the testing application there is an exception on the "TextTure2D localText = resourceManager.Load<Texture2D>("myTool.myImage.png");" line. I have tried a number of things, from using the resource name, from using resx to embed the images, I have tried fully qualified resource manifest paths, like myTool.Resource.myImage.png, etc... I have tried the friendly name etc.

It seems that the only way to embed a resource into an XNA application is to allow access to load from a stream and bring Texture2D.FromFile() to the xb360 as so far this has been the only way I can get it to work through windows.

If im doing something wrong let me know. Starting to frustrate me as it seemed to be so easy in windows, and I would like to provide the same level of service in a xb360 component as well as a windows component.




Re: XNA Game Studio Express Embedded resources, Xbox 360, and the ContentPipeline.

groundh0g

It's a little lame, but you could store the embedded image data in a custom format (just width, height, and ARGB values), then create the image at runtime.

AFAIK, When you use the ResourceContentManager.Load, it will always load from disk. Ditto for Texture2D.FromFile. So all of the variations of the resource name you were using were trying to map to a location on your drive -- and will always fail.

// load the following data from your custom, embedded resouce data
int width, height;
uint[] data;

// create a new texture (these settings will likely need to be tweaked)
Texture2D tex = new Texture2D(
graphics.GraphicsDevice,
width,
height,
1,
ResourceUsage.SoftwareProcessing,
SurfaceFormat.Depth32 );

// update the bytes that make up the real texture
tex.SetData<uint>(data);

Performance isn't optimial here, but this should be fine for load-time (fine for your purposes).

(disclaimer: untested code, this assumes that you can load embeded data on both platforms, which the docs seem to confirm).

If this works, and you don't want to code the embeded data by hand, it would be trivial to write a tool to do it for you. Use the Bitmap class, and get a Graphics object from that. Draw your image onto the Graphics object, flush the Graphics object, then inspect the bitmap to get your dimensions and bits.






Re: XNA Game Studio Express Embedded resources, Xbox 360, and the ContentPipeline.

groundh0g

I just re-read Eli's (from Microsoft) post. That sounds interesting. I don't know how hard it would be to get to work, but your reply was still referencing ".png". Eli suggested that you use the post-imported, post-processed version of your resource (the ".xnb") which can be found somewhere under your bin directory after you build your project.

At least you have another option. Maybe one of these two will work for you. :P






Re: XNA Game Studio Express Embedded resources, Xbox 360, and the ContentPipeline.

Shawn Hargreaves - MSFT

Embedding the compiled XNB will definately work: this is a scenario we tested quite thoroughly for making redistributable components. Here are the steps:
  • Add your source asset to the project
  • Build it using the content pipeline
  • Add a resource (.resx) file to the project
  • Add the .xnb version of your asset (which will be in the bin directory) to the resx file
  • At runtime, create a ResourceContentManager. The constructor will want a ResourceManager instance: you can get this from the Resources class that C# Express will automatically generate out of your .resx file (it's a static property, I think called Resources.ResourceManager)





Re: XNA Game Studio Express Embedded resources, Xbox 360, and the ContentPipeline.

groundh0g

Shawn, thanks for the details!

I have a follow-up question, though. If the ".xnb" format is undocumented and subject to change, is there any risk that your embeded resources may be unreadable after some future update

I assume that future versions of the 360 XNA launcher would have to support old ".xnb" files regardless, since the same would apply to resources that have already been deployed to the hard drive. What's less clear is whether there would be a special case for data loaded from the ".resx". Can you comment

Thanks.






Re: XNA Game Studio Express Embedded resources, Xbox 360, and the ContentPipeline.

Shawn Hargreaves - MSFT

You don't need to worry about that.

If we ever change the details of the XNB format, we'll either keep both new and old versions supported in parallel, or perhaps use a totally different version of the launcher for games compiled using newer versions of the framework.

Fear not, we won't (barring gross stupidity, of course, which I hope we'll be able to avoid :-) ever release a version of the launcher that just breaks all your old games!