在XNA中以编程方式序列化Texture2D [英] Serialize Texture2D programmatically in XNA

查看:47
本文介绍了在XNA中以编程方式序列化Texture2D的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在为要构建的XNA游戏构建游戏编辑器,该游戏编辑器将接受JPEG/PNG,并输出其中包含Texture2D内容的XNB文件.

I am building a game editor for an XNA game that I'm building that would accept JPEG/PNG, and output a XNB file that has Texture2D content in it.

我有用于自定义等的自定义序列化程序,我正在挖掘所有内容,以使用反射等调用ContentCompiler,进入真正的脏区,然后我 CAN 实际使该部分为我工作自己的格式.但是我现在需要序列化为XNA知道如何编译(在创建项目时在Visual Studio中)和加载(在游戏中使用最常用的Content.Load方法的)常规Texture2D格式.我不想制作自己的图像显然,它的文件格式.当我尝试编译Texture2D时,它没有给我错误,它创建了XNB文件,但是文件内容不是图像数据,只有3-4 KB的开销(我认为是Texture2D对象的其他非图像属性.

I have my custom serializers for my custom etc and I'm dug everything down into invoking ContentCompiler using Reflection etc, gone into the real dirty bits, and I CAN actually get that part working for my own formats. But I now need to serialize to the regular Texture2D format that XNA know how to compile (in Visual Studio when building project) and load (in the game with the most used Content.Load method. I don't want to make my own image file format for this obviously. When I try to compile a Texture2D, it doesn't give me an error, it creates the XNB file, but the file contents are not image data, it's just some 3-4 KBs of overhead (which I think are the other, non-image properties of a Texture2D object).

这是我用于编译的代码:

Here is the code I use for compiling:

    protected void InitializeWriter()
    {
        Type compilerType = typeof(ContentCompiler);
        cc = compilerType.GetConstructors(BindingFlags.NonPublic | BindingFlags.Instance)[0].Invoke(null) as ContentCompiler;
        compileMethod = compilerType.GetMethod("Compile", BindingFlags.NonPublic | BindingFlags.Instance);
    }

    internal void Write(string objectName, string path, object objectToWrite) 
    {
        if (basePath == null)
        {
            throw new InvalidOperationException("The base path to write has not been set.");
        }
        if (cc == null) { InitializeWriter(); }
        string fullPath = Path.Combine(basePath, path, objectName + ".xnb");
        using (FileStream fs = File.Create(fullPath))
        {
            compileMethod.Invoke(cc, new object[]{
            fs, objectToWrite, TargetPlatform.Windows, GraphicsProfile.Reach, false/*true*/, fullPath, fullPath
        });
        }
    }

我有自己的内容处理器,此代码可以完美地与它们协同工作.这只是调用ContentCompiler的Compile方法,但是使用了Reflection(因为它是一个内部类).

I have my own content processors and this code works with them flawlessly. This just calls the ContentCompiler's Compile method, but using Reflection (as it's an internal class).

我不明白为什么Texture2D进行序列化,但是没有实际的位图数据.

I don't understand why Texture2D serializes, but without the actual bitmap data.

编辑抱歉,它不会编译Texture2D(它抱怨我的GraphicsDevice的循环引用),如果我尝试编译一个Bitmap对象,它会编译没有错误,但不会序列化实际的位图数据)

EDIT Sorry, it does NOT compile Texture2D (it complains about cyclic reference of my GraphicsDevice), if I try to compile a Bitmap object, it compiles with no errors but does not serialize the actual bitmap data)

推荐答案

好吧,经过一些研究和数小时的研究,我已经解决了我的问题.

Ok, after some digging and hours of research, I've solved my problem.

这是做什么:

您无法序列化Texture2D并将其加载回.尽管加载显然没有问题(因为我们在任何2D XNA游戏中都使用Content Manager加载Texture2D),但我们无法保存它以便从游戏中加载.经过对该问题的进一步调查,我发现了Texture2DContent类(在图形管道中),我认为该类可以序列化为Texture2D(事实证明是完全正确的).

You can't serialize Texture2D and load it back. Although loading is obviously done with no problem (as we load Texture2D using content manager in any 2D XNA game), we cannot save it for loading it from the game. After further investigation of the issue, I've found a Texture2DContent class (in the graphics pipeline) which I thought would serialize to Texture2D (which turns out to be perfectly correct).

因此,我只是连接了Texture2DContent类的新实例,但是找不到将其数据设置为我的位图的方法.搜索所有DLL和基类/派生类,但没有找到.然后,我实现了具有导入方法的TextureImporter类.它需要一个文件名和一个ContentImporterContext,这是一个复杂的类,它也具有其他深入内部工作的类的构造函数,我只是知道我无法正确地初始化该类.因此,我尝试将null作为参数传递给import方法,进入代码以查看我的NullPointerException,但奇怪的是,它起作用了,并输出了我的文件.我检查了XNB,它只是一个有效的纹理.这是我的代码:

So I just hooked up a new instance of Texture2DContent class, but found no way to set its data to my bitmap. Searched through all the DLLs and base/derived classes but no way. Then I've realized a TextureImporter class which has an import method. It takes a filename and a ContentImporterContext, which was a complicated class which had constructors from other deep-inner-working classes as well, and I just knew I wasn't able to initialize that one correctly. So I tried to pass null as my parameter to the import method, stepping in the code to see my NullPointerException, but, weirdly, it worked, and outputted my file. I checked the XNB and it was just a valid texture. Here is my code:

    TextureImporter importer = new TextureImporter();
    Texture2DContent tc = importer.Import(item, null) as Texture2DContent;
    AssetWriter.Write(item.Substring(item.Replace('\\', '/').LastIndexOf('/') + 1), tc);

其中 item 只是一个文件名,而AssetWriter实际上做到了这一点(那里有一些方法,但是我在下面将它们粘贴到了一起):

where item is just a filename and AssetWriter does this practically (some methods in there but I've pasted them together below):

   Type compilerType = typeof(ContentCompiler);
   cc = compilerType.GetConstructors(BindingFlags.NonPublic | BindingFlags.Instance)[0].Invoke(null) as ContentCompiler;
   compileMethod = compilerType.GetMethod("Compile", BindingFlags.NonPublic | BindingFlags.Instance);
   string fullPath = Path.Combine(basePath, path, objectName + ".xnb");
   using (FileStream fs = File.Create(fullPath))
   {
      compileMethod.Invoke(cc, new object[]{
      fs, objectToWrite, TargetPlatform.Windows, GraphicsProfile.Reach, false/*true*/, fullPath, fullPath
      });
   }

它就是这样工作的.该程序将所需的所有内容传递给内容编译器,然后编译器完成工作.它可以正确处理Texture2DContent并将其映射到Texture2D的XNB输出,然后可以使用contentManager的load方法进行加载.

It just works this way. The program passes everything needed to the content compiler, and the compiles does the job. It handles Texture2DContent correctly and maps it to a XNB output of Texture2D which can then be loaded using contentManager's load method.

这篇关于在XNA中以编程方式序列化Texture2D的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆