XNA Creators Club Online
Page 1 of 1 (8 items)
Sort Posts: Previous Next

ContentProcessor Conundrum

Last post 05-09-2008 12:53 AM by DrDeth. 7 replies.
  • 05-07-2008 6:17 AM

    ContentProcessor Conundrum

    I'm struggling to figure out the 'right' way of working with my custom content. I have an application that allows you to load a texture and then define simple point-based shapes (rectangles, triangles, polygons, etc) on top of that texture. This could be useful for UV mapping someday. The application then writes this data, with a reference to the texture (Texture2D int marked as serializable) to a binary data file. Now, I'm trying to write a ContentImporter and ContentProcessor so that these files can simply be dropped into my Content project and usable in a game.

    The methods to load and save data exist statically on the data class, and are working 100% in the original application, but not in my ContentImporter. I have tried using my static method to load the data, as well as loading it manually - It would seem that the Deserialize method of the BinaryFormatter is returning null.

    // The TImport type
    using TImport = Wrath.Content.TextureShapes;

    // First Method
    public override TImport Import(string filename, ContentImporterContext context)
    {
    TextureShapes shapes = TextureShapes.Load(filename);

    if (shapes == null)
    {
    context.Logger.LogImportantMessage("Cannot import " + filename);
    return null;
    }

    context.AddDependency(shapes.Texture);

    return shapes;
    }

    // Second Method
    public override TImport Import(string filename, ContentImporterContext context)
    {
    TextureShapes shapes = null;
    FileStream file = null;

    try
    {
    file = File.Open(filename, FileMode.Open);
    BinaryFormatter binary = new BinaryFormatter();
    shapes = (TextureShapes)binary.Deserialize(file);
    file.Close();
    }
    catch
    {
    if (file != null)
    file.Close();

    shapes = null;
    }

    if (shapes == null)
    {
    context.Logger.LogImportantMessage("Cannot import " + filename);
    return null;
    }

    context.AddDependency(shapes.Texture);

    return shapes;
    }
    The file is already in a binary format, so I could just load it as usual in my game, but I thought that using the Content Pipeline is a 'better' way to load things in the game.
     
    What am I doing wrong? Is there a better way to do this? Suggestions?
     
    --
    Ruina et Stragos
    XNA SA
    --
  • 05-07-2008 11:58 AM In reply to

    Re: ContentProcessor Conundrum

    That's bizarre - I'm not an expert on the binary serializer in .NET (in fact I don't think I ever used it) but that code looks sane to me.

    I assume the deserialize call is throwing an exception rather than just returning null? (which you are then swallowing with your catch block). It would be useful to know what that exception is.
    XNA Framework Developer - blog - homepage
  • 05-07-2008 3:25 PM In reply to

    Re: ContentProcessor Conundrum

    See! Thats what you get for trying to figure things out after a 16-hour day at work and at 2am. I didnt think of that at the time.

    You were right, Shawn. The deserializing is throwing an exception:

    Error 1 Building content threw SerializationException: Unable to find assembly 'Wrath.Content, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null'.
    at System.Runtime.Serialization.Formatters.Binary.BinaryAssemblyInfo.GetAssembly()
    at System.Runtime.Serialization.Formatters.Binary.ObjectReader.GetType(BinaryAssemblyInfo assemblyInfo, String name)

    My content importer and the data object are both in this assembly. I can select my custom importer and processor in the file properties, but this exception is thrown on build.

    I've tried referencing both the project in the solution or the compiled DLL with the same results.

    I've tried copying the DLL around to various places in the content project directory heirarchy in the hope that it would be magically found during build (a last futile attempt to get it working and better understand where the build is looking for it), but still no luck.

    Note: This is a Windows Forms project based off the WinForms Sample #2, so the content project is 'attached' to the solution as described in that sample.
      

    --
    Ruina et Stragos
    XNA SA
    --
  • 05-07-2008 4:15 PM In reply to

    Re: ContentProcessor Conundrum

    At this point I'm really just guessing: I don't know enough about the binary formatter to give you an accurate diagnosis.

    In .NET, assemblies can be referenced either by assembly name (as in the error message you posted above), or by filename. Judging from this message, the formatter must be looking by assembly name.

    The content pipeline build runs in a temporary worker appdomain. To get an assembly loaded into that domain, you add it as a reference to your content project. We will load the assembly either by assembly name or by filename, depending on whatever format the reference specifies.

    Obviously, your assembly is being loaded into this appdomain - otherwise none of your code from it could be running at all! But it may be getting loaded using a different name to what the formatter is looking for, so it cannot later resolve the assembly reference.

    It's possible you might be able to fix this by manually loading the right assembly yourself before calling the formatter. Alternatively it might help if you gave your assembly a full strong name (at the moment you don't have the public key token filled in).
    XNA Framework Developer - blog - homepage
  • 05-07-2008 5:02 PM In reply to

    Re: ContentProcessor Conundrum

    Shawn Hargreaves:
    Obviously, your assembly is being loaded into this appdomain - otherwise none of your code from it could be running at all! But it may be getting loaded using a different name to what the formatter is looking for, so it cannot later resolve the assembly reference.

    How is this possible when both classes exist in the same assembly? Could this be a problem with different versions of the same assembly? I'm thinking that because the library is added to my game solution as well, its being built again and is therefore one 'version' older than the version used to serialize the content, even though the actual assembly info doesnt change, but I am only having this problem in the content project - different 'versions' load fine in the original project.

    I'm surprised this issue hasnt come up before. Surely others use serialization for their custom file types? Perhaps its specifically the BinaryFormatter? I'll try convert to XML serialization and test if that works, then get back to you.

     

     

    --
    Ruina et Stragos
    XNA SA
    --
  • 05-08-2008 3:46 PM In reply to

    Re: ContentProcessor Conundrum

    Answer

    Shawn, I have some feedback. I figured out that the BinaryFormatter was failing while trying to serialize the generic dictionary class. XML Serialization didnt work out either - also something to do with not being able to convert the dictionary into a meaningful XML structure. This is a problem in .NET, not XNA. I'm sure there's a perfectly good explanation, but one that I'm too tired to investigate right now.

    So, I've gone back to the 'good old days' of writing bytes. Wink

    For base types I use the BitConverter class, and for strings I'm using Encoding.ASCII (though any Encoding class should do, so long as you stick to the same one during Save & Load).

    Its working like a charm now and even compiling the Texture dependency.

     

     

    --
    Ruina et Stragos
    XNA SA
    --
  • 05-08-2008 4:48 PM In reply to

    Re: ContentProcessor Conundrum

    Good to hear you got this working.

    Yeah, dictionaries don't play too well with .NET serialization. The IntermediateSerializer we built into the Content Pipeline does actually handle them properly, but the standard .NET serializer does not.

    You might want to look at the BinaryReader and BinaryWriter classes for your custom saving, btw: those can be nicer to use than BitConverter, and handle the string encoding stuff automatically for you as well.
    XNA Framework Developer - blog - homepage
  • 05-09-2008 12:53 AM In reply to

    Re: ContentProcessor Conundrum

    Thanks Shawn. I'll have a look at those classes.
    --
    Ruina et Stragos
    XNA SA
    --
Page 1 of 1 (8 items) Previous Next