2012-01-13 44 views
3

我正在构建一个将接受JPEG/PNG的XNA游戏的游戏编辑器,并输出其中包含Texture2D内容的XNB文件。在XNA中以编程方式序列化Texture2D

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

这里是我使用的编译代码:

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的编译方法,但使用反射(因为它是一个内部类)。

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

谢谢, 可以。

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

回答

1

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

这里是做什么:

您不能序列的Texture2D并加载它回来。虽然加载显然没有问题(因为我们在任何2D XNA游戏中使用内容管理器加载Texture2D),但我们无法保存它以便从游戏中加载它。在进一步调查问题之后,我发现了一个Texture2DContent类(在图形管道中),我认为它会序列化到Texture2D(事实证明这是完全正确的)。

所以我刚刚挂接了一个Texture2DContent类的新实例,但没有找到将其数据设置到我的位图的方法。搜索所有的DLL和基类/派生类,但没办法。然后我意识到一个具有导入方法的TextureImporter类。它需要一个文件名和一个ContentImporterContext,它是一个复杂的类,它具有来自其他深层内部工作类的构造函数,并且我只知道我无法正确初始化它。所以我试图将null作为参数传递给import方法,在代码中加入以查看我的NullPointerException,但是,奇怪的是,它工作并输出了我的文件。我检查了XNB,它只是一个有效的纹理。这里是我的代码:

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

其中项目只是一个文件名和AssetWriter做到这一点实际上是(一些有方法,但我已经贴在下面他们一起):

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的加载方法加载它。

+0

如何将TextureImporter导入到我的项目引用中,您是否也可以解释它?谢谢 ! – icaptan 2012-03-12 09:14:49

+0

引用XNA内容管道组件。 – 2012-03-24 20:06:24

+0

我无法在XNA 4.0上找到任何对XnaContentPipeline程序集的引用,我尝试将它添加到项目中。你能给出全名吗?谢谢 ! – icaptan 2012-03-24 22:05:56