2012-01-13 5 views
3

Je construis un éditeur de jeu pour un jeu XNA que je suis en train de construire qui accepterait JPEG/PNG, et sortirait un fichier XNB contenant du contenu Texture2D.Sérialiser Texture2D par programmation dans XNA

J'ai mes serializers personnalisés pour mon etc personnalisé et je suis creusé tout vers le bas en invoquant ContentCompiler utilisant la réflexion etc, entré dans les vrais morceaux sales, et je CAN fait obtenir cette partie de travail pour mes propres formats. Mais je dois maintenant sérialiser au format Regular2 Texture que XNA sait compiler (dans Visual Studio lors de la construction du projet) et charger (dans le jeu avec la méthode Content.Load la plus utilisée.) Je ne veux pas faire ma propre image Lorsque je tente de compiler un Texture2D, il ne me donne pas d'erreur, il crée le fichier XNB, mais le contenu du fichier n'est pas une image, c'est juste 3-4 Ko de surcharge (que je CROYEZ les autres, les propriétés non-image d'un objet Texture2D)

Voici le code que j'utilise pour la compilation:.

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 
     }); 
     } 

    } 

J'ai mes propres processeurs de contenu et ce code fonctionne avec eux parfaitement ce. appelle simplement la méthode Compile du ContentCompiler , mais en utilisant Reflection (comme c'est une classe interne).

Je ne comprends pas pourquoi Texture2D sérialise, mais sans les données bitmap réelles.

Merci, Can.

EDIT Désolé, il ne compile pas Texture2D (il se plaint de référence cyclique de mon GraphicsDevice), si je tente de compiler un objet Bitmap, il compile sans erreur, mais ne sérialise pas les données bitmap réelles)

Répondre

1

Ok, après quelques fouilles et des heures de recherche, j'ai résolu mon problème.

Voici ce qu'il faut faire:

Vous ne pouvez pas sérialiser Texture2D et le charger en arrière. Bien que le chargement soit évidemment fait sans problème (comme nous chargeons Texture2D en utilisant le gestionnaire de contenu dans n'importe quel jeu XNA 2D), nous ne pouvons pas l'enregistrer pour le charger depuis le jeu. Après avoir étudié le problème, j'ai trouvé une classe Texture2DContent (dans le pipeline graphique) que je pensais sérialiser en Texture2D (ce qui s'avère parfaitement correct).

Je viens donc de connecter une nouvelle instance de la classe Texture2DContent, mais je n'ai trouvé aucun moyen de définir ses données sur mon bitmap. Recherche à travers toutes les DLL et les classes de base/dérivées, mais pas moyen. Ensuite, j'ai réalisé une classe TextureImporter qui a une méthode d'import. Il prend un nom de fichier et un ContentImporterContext, qui était une classe compliquée qui avait aussi des constructeurs d'autres classes de deep-inner-working, et je savais juste que je n'étais pas capable d'initialiser correctement celui-ci. J'ai donc essayé de passer null en tant que mon paramètre à la méthode d'importation, en entrant dans le code pour voir mon NullPointerException, mais, bizarrement, cela a fonctionné, et sorti mon fichier. J'ai vérifié le XNB et c'était juste une texture valide. Voici mon code:

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

élément est juste un nom de fichier et AssetWriter fait cela pratiquement (certaines méthodes là-dedans, mais je l'ai collé les ensemble ci-dessous):

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 
     }); 
    } 

Il fonctionne par ici. Le programme transmet tout le nécessaire au compilateur de contenu, et les compilations font le travail.Il gère correctement Texture2DContent et le mappe à une sortie XNB de Texture2D qui peut ensuite être chargée en utilisant la méthode load de contentManager.

+0

Comment puis-je importer TextureImporter dans mes références de projet, pouvez-vous l'expliquer aussi? Merci ! – icaptan

+0

référence l'assembly XNA Content Pipeline. –

+0

Je ne trouve aucune référence à l'assemblage de XnaContentPipeline sur XNA 4.0 où j'essaie de l'ajouter au projet. pouvez-vous donner le nom entier? Merci ! – icaptan

Questions connexes