Goal
I'm trying to load a custom class that contains a Texture2D
from an xml file using the default importer (XML Content), with no processor.
Approach
Lots of research online and a lot of dealing with other errors lead me to this XML:
<?xml version="1.0" encoding="utf-16"?>
<XnaContent xmlns:Components="Entities.Components">
<Asset Type="EntitiesContentPipeline.EntityTemplateContent">
<Name>entity name</Name>
<TestTexture>
<Reference>#External1</Reference>
</TestTexture>
</Asset>
<ExternalReferences>
<ExternalReference ID="#External1" TargetType="Microsoft.Xna.Framework.Graphics.Texture2D">C:\Documents and Settings\GDuckett\My Documents\Visual Studio 2010\Projects\Gravitron\Gravitron\Gravitron\bin\x86\Debug\Content\Bullet.xnb</ExternalReference>
</ExternalReferences>
</XnaContent>
Yes, i don't like the hard-coded path either, but if i can get this working without a custom reader and or writer for each type containing a Texture2D
i can live with it.
Below is my content version of the class (used by the pipeline):
[ContentSerializerRuntimeType("Entities.Content.EntityTemplate, Entities")]
public class EntityTemplateContent
{
public string Name;
public ExternalReference<Texture2D> TestTexture;
public EntityTemplateContent()
{
}
}
Below is my runtime version:
public class EntityTemplate
{
public string Name;
public Texture2D TestTexture;
public EntityTemplate()
{
}
}
Problem
If i try and do var test = Content.Load<EntityTemplate>("BulletTemplate");
below is the error i get:
Error loading "Bullet". ContentTypeReader Microsoft.Xna.Framework.Content.Texture2DReader, Microsoft.Xna.Framework.Graphics, Version=4.0.0.0, Culture=neutral, PublicKeyToken=842cf8be1de50553 conflicts with existing handler Microsoft.Xna.Framework.Content.ReflectiveReader`1[[Microsoft.Xna.Framework.Graphics.Texture2D, Microsoft.Xna.Framework.Graphics, Version=4.0.0.0, Culture=neutral, PublicKeyToken=842cf8be1de50553]], Microsoft.Xna.Framework, Version=4.0.0.0, Culture=neutral, PublicKeyToken=842cf8be1de50553 for type Microsoft.Xna.Framework.Graphics.Texture2D.
It looks like the runtime reader found 2 readers for dealing with a Texture2D
asset, the ReflectiveReader<Texture2D>
reader and the Texture2DReader
.
Question
How can i solve this problem, so i end up with an object correctly populated, with the Texture2D
property referencing a loaded texture?
Note: I don't want to add another string property and create a method on my object called LoadContent
or something. I'd like to have Content.Load
be the only thing i need to call.
I also want to avoid writing my own readers / writers for every type that contains a Texture2D
property.
Ideally I want to avoid creating a wrapper class for Texture2D, or a subclass but if there's no alternative then I'm happy for a solution that does this.
The exact error message was caused by having another
Texture2D
field in the content object.The overall problem of getting a reference to a runtime type from an
ExternalReference<T>
in a content type was solved with the below.Currently it's really a proof-of-concept class, as such it works for the classes I've thrown at it so far, but will probably crash with anything more complicated.
It uses reflection to convert any fields or properties of the input that are
ExternalReference<T>
's into built versions of the type requested by creating an appropriate version ofContentProcessorContext.BuildAsset<T,T>
and invoking it. It recurses down the object tree to do the same for references to other objects.