Quantcast
Channel: Active questions tagged xna-4.0 - Game Development Stack Exchange
Viewing all articles
Browse latest Browse all 33

How do you write Texture2DContent and read it as Texture2D in the XNA content pipeline?

$
0
0

I'm trying to create a custom Monogame content pipeline extension that packs a bunch of individual sprites into a single sprite. I need help figuring out how to write and read the texture in the pipeline.

My writer outputs a Texture2DContent (wrapped in SpriteSheetContent model object) that contains a single BitmapContent. My reader then attempts to create a Texture2D from the serialized data, but encounters an exception when setting the data. I cannot make heads or tails of the exception since it's so cryptic.

Where am I going wrong?

Models

public class SpriteSheetContent{    public Texture2DContent Texture { get; } = new Texture2DContent();}public class SpriteSheet{    public Texture2D Texture;}

Processor

    public override SpriteSheetContent Process( SpriteSheetDeclaration declaration, ContentProcessorContext context )    {        var spriteSheetContent = new SpriteSheetContent();        BitmapContent sprite = <omitted code that creates a single bitmap content>;        spriteSheetContent.Texture.Mipmaps.Add( sprite );        return spriteSheetContent;    }

Writer

[ContentTypeWriter]public class SpriteBoxWriter : ContentTypeWriter<SpriteSheetContent>{    protected override void Write( ContentWriter writer, SpriteSheetContent spriteSheetContent )    {        BitmapContent bitmapContent = spriteSheetContent.Texture.Faces[0][0];        bitmapContent.TryGetFormat( out SurfaceFormat format );        writer.Write( (int)format );        writer.Write( bitmapContent.Width );        writer.Write( bitmapContent.Height );        byte[] pixelData = bitmapContent.GetPixelData();        writer.Write( pixelData.Length );        writer.Write( pixelData );    }    public override string GetRuntimeType( TargetPlatform targetPlatform )    {        return typeof( SpriteSheet ).AssemblyQualifiedName;    }    public override string GetRuntimeReader( TargetPlatform targetPlatform )    {        return "Monogame.SpriteBox.SpriteSheetReader, Monogame.SpriteBox";    }}

Reader

public class SpriteSheetReader : ContentTypeReader<SpriteSheet>{    protected override SpriteSheet Read( ContentReader reader, SpriteSheet existingInstance )    {        SpriteSheet spriteSheet = existingInstance == null ? new SpriteSheet() : existingInstance;        var format = (SurfaceFormat)reader.ReadInt32();        int width = reader.ReadInt32();        int height = reader.ReadInt32();        var graphicsDeviceManager = (GraphicsDeviceManager)reader.ContentManager.ServiceProvider.GetService( typeof( IGraphicsDeviceManager ) );        spriteSheet.Texture = new Texture2D( graphicsDeviceManager.GraphicsDevice, width, height, mipmap: false, format: format );        int pixelDataLength = reader.ReadInt32();        byte[] pixelData = reader.ReadBytes( pixelDataLength );        spriteSheet.Texture.SetData( pixelData ); // this line results in the exception        return spriteSheet;    }}

Exception

SharpDX.SharpDXException  HResult=0x80070057  Message=HRESULT: [0x80070057], Module: [General], ApiCode: [E_INVALIDARG/Invalid Arguments], Message: The parameter is incorrect.  Source=SharpDX  StackTrace:   at SharpDX.Result.CheckError()   at SharpDX.Direct3D11.Device.CreateTexture2D(Texture2DDescription& descRef, DataBox[] initialDataRef, Texture2D texture2DOut)   at Microsoft.Xna.Framework.Graphics.Texture2D.CreateTexture()   at Microsoft.Xna.Framework.Graphics.Texture2D.PlatformSetData[T](Int32 level, T[] data, Int32 startIndex, Int32 elementCount)   at Microsoft.Xna.Framework.Graphics.Texture2D.SetData[T](T[] data)   at Monogame.SpriteBox.SpriteSheetReader.ReadTexture(ContentReader reader, SpriteSheet spriteSheet) in D:\Projects\Game Development\Monogame.SpriteBox\SpriteBox\SpriteSheetReader.cs:line 45   at Monogame.SpriteBox.SpriteSheetReader.Read(ContentReader reader, SpriteSheet existingInstance) in D:\Projects\Game Development\Monogame.SpriteBox\SpriteBox\SpriteSheetReader.cs:line 14   at Microsoft.Xna.Framework.Content.ContentTypeReader`1.Read(ContentReader input, Object existingInstance)   at Microsoft.Xna.Framework.Content.ContentReader.InnerReadObject[T](T existingInstance)   at Microsoft.Xna.Framework.Content.ContentReader.ReadObject[T]()   at Microsoft.Xna.Framework.Content.ContentReader.ReadAsset[T]()   at Microsoft.Xna.Framework.Content.ContentManager.ReadAsset[T](String assetName, Action`1 recordDisposableObject)   at Microsoft.Xna.Framework.Content.ContentManager.Load[T](String assetName)   at Game1.Game1.LoadContent() in D:\Projects\Game Development\Monogame.SpriteBox\Game1\Game1.cs:line 48   at Microsoft.Xna.Framework.Game.Initialize()   at Game1.Game1.Initialize() in D:\Projects\Game Development\Monogame.SpriteBox\Game1\Game1.cs:line 35   at Microsoft.Xna.Framework.Game.DoInitialize()   at Microsoft.Xna.Framework.Game.Run(GameRunBehavior runBehavior)   at Microsoft.Xna.Framework.Game.Run()   at Game1.Program.Main() in D:\Projects\Game Development\Monogame.SpriteBox\Game1\Program.cs:line 18

Other approach I've tried already

I thought simply doing writer.WriteObject<Texture2DContent>( spriteSheetContent.Texture ) in the writer, and then doing spriteSheet.Texture = reader.ReadObject<Texture2D>() in the reader would work. However, this results in the same type of exception.

I even came across Monogame's Texture2DWriter and Texture2DReader, but using their examples leads to the same exception.


Viewing all articles
Browse latest Browse all 33

Trending Articles