zoukankan      html  css  js  c++  java
  • xml save Texture2D

    As some of you’ve might seen, I’ve been breaking my head over the following problem for the past few days:

    How do I serialize the class like the following without creating a special ‘intermediate’ struct for each and ever classes

    01
    02
    03
    04
    05
    06
    07
    08
    09
    10
    11
    12
    13
    14
    public class MyData
        {
            [ContentSerializer(SharedResource = true)]
            public Texture2D myTexture;
            public int myInt;
            public string[] myLines;
            public MyData() { } // for deserialization
            public MyData(int myInt, Texture2DProxy myTexture, string[] myLines)
            {
                this.myInt = myInt;
                this.myTexture = myTexture;
                this.myLines = myLines;
            }
        }

    Even though I’ve marked the Texture2D as a shared resource, I still can’t serialize it using the IntermediateSerializer because a Texture2D always has a reference to a GraphicsDevice object, and the IS can’t serialize that.

    Fortunately some helpfull people in #XNA on Efnet (ecosky and flashed, that’s you guys!) told me about proxyclasses, first I was confused and thought they wanted me to write a proxy for every class in my project, but soon they helped me understand that I should write a proxy class for Texture2D. I just had to write a proxy class that can be serialized and that will store the path to texture, so that it can reload itself when deserialized.

    I quickly came up with the following class, very simple but it will suffice for now:

    01
    02
    03
    04
    05
    06
    07
    08
    09
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    public class Texture2DProxy
        {
            public Texture2DProxy(string path)
            {
                LoadTexture(path);
            }
     
            public Texture2DProxy() { }
     
            private void LoadTexture(string path)
            {
                ContentManager content = GameServices.GetService<ContentManager>(); //My own class, see my code snippet, you can also reference a static CM here.
                texture = content.Load<Texture2D>(path);
                this.path = path;
            }
     
            [ContentSerializerIgnore()] //make this is not serialized
            private Texture2D texture;
     
            [ContentSerializerIgnore()]
            public Texture2D Texture
            {
                get
                {
                    if (texture == null)
                    {
                        LoadTexture(path);
                    }
                    return texture;
                }
            }
     
            [ContentSerializer()] //make sure this is, even-though it's a private field.
            private string path;
        }

    Now we just need to replace Texture2D with Texture2DProxy everywhere, and update some code. In the end we can now serialize and deserialize the MyData class like this:

    01
    02
    03
    04
    05
    06
    07
    08
    09
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    public void DoSerialize(MyData myData)
            {
                XmlWriterSettings settings = new XmlWriterSettings();
                settings.Indent = true;
                using (XmlWriter writer = XmlWriter.Create("example.xml", settings))
                {
                    IntermediateSerializer.Serialize(writer, myData, null);
                }
            }
     
            public MyData DoLoad()
            {
                MyData tmp;
                XmlReaderSettings settings = new XmlReaderSettings();
                using(XmlReader reader = XmlReader.Create("example.xml", settings))
                {
                    tmp = IntermediateSerializer.Deserialize<MyData>(reader, null);
                }
     
                return tmp;
            }

    Btw, serializing like this will generate the following XML file:

    01
    02
    03
    04
    05
    06
    07
    08
    09
    10
    11
    12
    13
    14
    15
    16
    17
    18
    <?xml version="1.0" encoding="utf-8"?>
    <XnaContent>
      <Asset Type="XNASerialization.MyData">
        <myTexture>#Resource1</myTexture>
        <myInt>42</myInt>
        <myLines>
          <Item>Two households, both alike in dignity,</Item>
          <Item>In fair Verona, where we lay our scene,</Item>
          <Item>From ancient grudge break to new mutiny,</Item>
          <Item>Where civil blood makes civil hands unclean.</Item>
        </myLines>
      </Asset>
      <Resources>
        <Resource ID="#Resource1" Type="XNASerialization.Texture2DProxy">
          <path>latern</path>
        </Resource>
      </Resources>
    </XnaContent>

    With this problem out of the way, I can now finally start working on a way to save and restore levels in Hollandia. Oh btw, you can ofcourse do the same trick with SoundEffects and Models or anything else for that matter.

  • 相关阅读:
    iOS app版本更新CheckVersion_Swift
    ios插件化开发
    开源框架RSA_Swift
    iOS SKStoreProductViewController的应用
    FMDB的使用
    iOS的MVP设计模式
    iOS UI帧率优化经验
    SKStoreReviewController之程序内评价
    Axure使用chrome插件
    修改每次《创建》项目maven仓库的默认路径
  • 原文地址:https://www.cnblogs.com/alsky/p/2379232.html
Copyright © 2011-2022 走看看