Custom XML Importer Exception "Cannot load non-content file."

Hello everyone,

Solved


Oh lawdy. This was a silly mistake.

In my Writer class I had written such a method:

public override string GetRuntimeReader(TargetPlatform targetPlatform)
{
    return "shmup_monogame.TexturePackerXmlReader, shmup_monogame";
}

which was almost correct. My project was called shmup-monogame, so the correct version is

return "shmup_monogame.TexturePackerXmlReader, shmup-monogame";

I guess the takeaway is, don’t name projects with hyphens. :slightly_smiling:

Original Question


this one has stumped me a little. I followed the Creating custom content importers for the MonoGame Pipeline tutorial to make my own XML format for TextureAtlases. My problem is that MGCB works- it builds my XML and I have double and triple-checked my references. Both projects run with .Net Framework 4.5 (the content pipeline project started with 4.0)

As soon as I try to load my game it crashes with the error Could not load art\uiAtlas asset as a non-content file!

protected override void LoadContent()
{
    // Create a new SpriteBatch, which can be used to draw textures.
    _spriteBatch = new SpriteBatch(GraphicsDevice);

    uiAtlas = Content.Load<TextureAtlas>("art/uiAtlas");
}

I have tried different permutations:

  • putting the file in the base Content directory
  • referencing it fully (“art/uiAtlas.xml”)
  • removing and adding my .dll reference
  • clean rebuilds of my pipeline extension project
  • removing and adding my .xml

Writer:

[ContentTypeWriter]
public class TexturePackerXmlWriter : ContentTypeWriter<TextureAtlas>
{
    protected override void Write(ContentWriter output, TextureAtlas value)
    {
        output.Write(value.SourceFile);
        output.Write(value.Width);
        output.Write(value.Height);
        output.Write(value.TextureRegions.Count);

        foreach (var region in value.TextureRegions)
        {
            output.Write(region.Name);
            output.Write(region.Width);
            output.Write(region.Height);
            output.Write(region.X);
            output.Write(region.Y);
            output.Write(region.PivotX);
            output.Write(region.PivotY);
        }
    }

    public override string GetRuntimeType(TargetPlatform targetPlatform)
    {
        return typeof(TextureAtlas).AssemblyQualifiedName;
    }

    public override string GetRuntimeReader(TargetPlatform targetPlatform)
    {
        return "shmup_monogame.TexturePackerXmlReader, shmup_monogame";
    }
}

Reader:

public class TexturePackerXmlReader : ContentTypeReader<TextureAtlas>
{
    protected override TextureAtlas Read(ContentReader reader, TextureAtlas existingInstance)
    {
        var sourceFile      = reader.ReadString();
        var sourceTexture   = reader.ContentManager.Load<Texture2D>(reader.GetRelativeAssetPath(sourceFile));

        var sourceWidth     = reader.ReadInt32();
        var sourceHeight    = reader.ReadInt32();

        var regionsCount = reader.ReadInt32();
        var regions = new List<TextureRegion>();
        for (var i = 0; i < regionsCount; ++i)
        {
            var name    = reader.ReadString();
            var width   = reader.ReadInt32();
            var height  = reader.ReadInt32();
            var x       = reader.ReadInt32();
            var y       = reader.ReadInt32();
            var pivotX  = reader.ReadDouble();
            var pivotY  = reader.ReadDouble();

            regions.Add(new TextureRegion(name, width, height, x, y, pivotX, pivotY));
        }
    
        return new TextureAtlas(sourceTexture, sourceWidth, sourceHeight, regions);
    }
}

TextureAtlas:

public class TextureAtlas
{
    private readonly Texture2D _source;
    public Texture2D Source => _source;

    private readonly int _width;
    public int Width => _width;

    private readonly int _height;
    public int Height => _height;

    private readonly List<TextureRegion> _regions;
    public List<TextureRegion> TextureRegions => _regions;

    public TextureAtlas(Texture2D source, int width, int height, List<TextureRegion> regions)
    {
        _source = source;
        _width = width;
        _height = height;
        _regions = regions;
    }
}

Building something with the pipeline tool will generate an xnb file. That file should be in your projects output directory so you can load it with a ContentManager. Check if the xnb is in the right directory. Also don’t add the extension when calling Load.

I fixed up someone else’s project earlier today to get XML content building and loading correctly, so I know the process works.

A few things to check

  • Make sure the XNB is copied to the output directory in the location you expect it to be.
  • Make sure your Content.RootDirectory is set correctly.

Also check out the other thread I linked above.

You should also check the inner exception on the load exception as that will usually contain the underlying error.

Hey Jjagg, thanks for the reply! I have checked and I can find the .xnb files in the following locations:

  • shmup-monogame/bin/Windows/x86/Debug/Content/art
  • shmup-monogame\shmup-monogame\Content\bin\Windows\art

This seems alright to me. The files contained therein are:

  • uiAtlas.xnb
  • uiAtlas.xml
  • ui.xnb

Hey KonajuGames, thanks for the reply! In a reply to @Jjagg I mentioned that the output .xnb files were in the correct folders. I’ve taken a look and I set the Content.RootDirectory = "Content" and that looks alright as well. I’ll take an in-depth look at the link you provided and hopefully I can find something that I overlooked.

Hey Andy_E, thanks for the reply! Sorry, my experience with .Net isn’t where it’s supposed to be coming from a JVM background, but I did dig up the inner exception and it seems to be a pretty hefty clue:

"Could not find ContentTypeReader Type. Please ensure the name of the Assembly that contains the Type matches the assembly in the full type name: shmup_monogame.TexturePackerXmlReader, shmup_monogame (shmup_monogame.TexturePackerXmlReader, shmup_monogame)"

I most likely misconfigured the methods in my Writer class and now it can’t find the appropriate Reader. I’ll check the documents and with that I should hopefully be able to solve the problem :slight_smile: