/// <summary>
        /// Set the mesh from the specified DataNode.
        /// </summary>

        static public Mesh DeserializeMesh(this DataNode node)
        {
            Mesh mesh = null;
            int  id   = node.Get <int>();

            if (id != 0 && mCachedMeshes.TryGetValue(id, out mesh) && mesh != null)
            {
                return(mesh);
            }

            string name = node.GetChild <string>("name");
            string path = node.GetChild <string>("path");

            if (id == 0)
            {
                id = (path + name).GetHashCode();
                if (mCachedMeshes.TryGetValue(id, out mesh) && mesh != null)
                {
                    return(mesh);
                }
            }

            if (!string.IsNullOrEmpty(path))
            {
                mesh = UnityTools.Load <Mesh>(path, name);
#if UNITY_EDITOR
                if (mesh == null)
                {
                    Debug.LogWarning("Unable to find mesh '" + name + "' in " + path);
                }
#endif
            }
            else
            {
                mesh      = new Mesh();
                mesh.name = name;

                Vector3[] verts = node.GetChild <Vector3[]>("vertices");
                if (verts != null)
                {
                    mesh.vertices = verts;
                }

                Vector3[] normals = node.GetChild <Vector3[]>("normals");
                if (normals != null)
                {
                    mesh.normals = normals;
                }

                Vector2[] uv1 = node.GetChild <Vector2[]>("uv1");
                if (uv1 != null)
                {
                    mesh.uv = uv1;
                }

                Vector2[] uv2 = node.GetChild <Vector2[]>("uv2");
                if (uv2 != null)
                {
                    mesh.uv2 = uv2;
                }

                Vector4[] tangents = node.GetChild <Vector4[]>("tangents");
                if (tangents != null)
                {
                    mesh.tangents = tangents;
                }

                Color32[] colors = node.GetChild <Color32[]>("colors");
                if (colors != null)
                {
                    mesh.colors32 = colors;
                }

                BoneWeight[] weights = node.GetChild <BoneWeight[]>("weights");
                if (weights != null)
                {
                    mesh.boneWeights = weights;
                }

                Matrix4x4[] poses = node.GetChild <Matrix4x4[]>("poses");
                if (poses != null)
                {
                    mesh.bindposes = poses;
                }

                int[] triangles = node.GetChild <int[]>("triangles");
                if (triangles != null)
                {
                    mesh.triangles = triangles;
                }

                mesh.RecalculateBounds();
            }
            mCachedMeshes[id] = mesh;
            return(mesh);
        }
        /// <summary>
        /// Serialize the specified material into its DataNode format.
        /// </summary>

        static public void Serialize(this Material mat, DataNode node, bool serializeTextures)
        {
            if (!mFullSerialization)
            {
                return;
            }

            node.AddChild("name", mat.name);
            string path = UnityTools.LocateResource(mat);

            if (!string.IsNullOrEmpty(path))
            {
                node.AddChild("path", path);
                return;
            }

            Shader s = mat.shader;

            if (s != null)
            {
                node.AddChild("shader", s.name);
#if UNITY_EDITOR
                int props = UnityEditor.ShaderUtil.GetPropertyCount(s);

                for (int b = 0; b < props; ++b)
                {
                    string propName = UnityEditor.ShaderUtil.GetPropertyName(s, b);
                    UnityEditor.ShaderUtil.ShaderPropertyType type = UnityEditor.ShaderUtil.GetPropertyType(s, b);

                    if (type == UnityEditor.ShaderUtil.ShaderPropertyType.Color)
                    {
                        node.AddChild(propName, mat.GetColor(propName));
                    }
                    else if (type == UnityEditor.ShaderUtil.ShaderPropertyType.Vector)
                    {
                        node.AddChild(propName, mat.GetVector(propName));
                    }
                    else if (type == UnityEditor.ShaderUtil.ShaderPropertyType.TexEnv)
                    {
                        Texture tex = mat.GetTexture(propName);

                        if (tex != null)
                        {
                            DataNode sub = new DataNode(propName, tex.GetInstanceID());
                            if (serializeTextures)
                            {
                                tex.Serialize(sub);
                            }
                            sub.AddChild("offset", mat.GetTextureOffset(propName));
                            sub.AddChild("scale", mat.GetTextureScale(propName));
                            node.children.Add(sub);
                        }
                    }
                    else
                    {
                        node.AddChild(propName, mat.GetFloat(propName));
                    }
                }
#endif
            }
        }
        /// <summary>
        /// Deserialize a previously serialized material.
        /// </summary>

        static public Material DeserializeMaterial(this DataNode matNode)
        {
            Material mat = null;
            int      id  = matNode.Get <int>();

            if (mMaterials.TryGetValue(id, out mat) && mat != null)
            {
                return(mat);
            }

            // Try to load this material
            string name = matNode.GetChild <string>("name", "Unnamed");
            string path = matNode.GetChild <string>("path");

            if (id == 0)
            {
                id = (path + name).GetHashCode();
                if (mMaterials.TryGetValue(id, out mat) && mat != null)
                {
                    return(mat);
                }
            }

            if (!string.IsNullOrEmpty(path))
            {
                mat = UnityTools.Load <Material>(path);

                if (mat != null)
                {
                    mMaterials[id] = mat;
                    return(mat);
                }
            }

            // Material can only be created if there is a shader to work with
            string shaderName = matNode.GetChild <string>("shader");
            Shader shader     = Shader.Find(shaderName);

            if (shader == null)
            {
                Debug.LogWarning("Shader '" + shaderName + "' was not found");
                shader = Shader.Find("Diffuse");
            }

            // Create a new material
            mat            = new Material(shader);
            mat.name       = name;
            mMaterials[id] = mat;

            // Restore material properties
            for (int b = 0; b < matNode.children.size; ++b)
            {
                DataNode prop = matNode.children[b];
                if (prop.name == "shader")
                {
                    continue;
                }

                if (prop.children.size != 0)
                {
                    Texture tex = prop.DeserializeTexture();

                    if (tex != null)
                    {
                        mat.SetTexture(prop.name, tex);
                        mat.SetTextureOffset(prop.name, prop.GetChild <Vector2>("offset"));
                        mat.SetTextureScale(prop.name, prop.GetChild <Vector2>("scale", Vector2.one));
                    }
                }
                else if (prop.value is Vector4)
                {
                    mat.SetVector(prop.name, prop.Get <Vector4>());
                }
                else if (prop.value is Color)
                {
                    mat.SetColor(prop.name, prop.Get <Color>());
                }
                else if (prop.value is float || prop.value is int)
                {
                    mat.SetFloat(prop.name, prop.Get <float>());
                }
            }
            return(mat);
        }
 protected virtual void OnSetChannelData(Channel ch, string path, DataNode node)
 {
 }
        /// <summary>
        /// Generic component serialization function. You can add custom serialization
        /// to any component by adding an extension with this signature:
        /// static public void Serialize (this YourComponentType, DataNode);
        /// </summary>

        static public void Serialize(this Component c, DataNode node, Type type = null)
        {
            // The 'enabled' flag should only be written down if the behavior is actually disabled
            Behaviour b = c as Behaviour;

            if (b != null)
            {
                if (!b.enabled)
                {
                    node.AddChild("enabled", b.enabled);
                }
            }
            else
            {
                Collider cd = c as Collider;
                if (cd != null && !cd.enabled)
                {
                    node.AddChild("enabled", cd.enabled);
                }
            }

            // Try custom serialization first
            if (c.Invoke("Serialize", node))
            {
                return;
            }

            GameObject go = c.gameObject;

            if (type == null)
            {
                type = c.GetType();
            }
            MonoBehaviour mb = c as MonoBehaviour;

            if (mb != null)
            {
                // For MonoBehaviours we want to serialize serializable fields
                List <FieldInfo> fields = type.GetSerializableFields();

                for (int f = 0; f < fields.size; ++f)
                {
                    FieldInfo field = fields[f];

                    object val = field.GetValue(c);
                    if (val == null)
                    {
                        continue;
                    }

                    val = EncodeReference(go, val);
                    if (val == null)
                    {
                        continue;
                    }

                    node.AddChild(field.Name, val);
                }
            }
            else
            {
                // Unity components don't have fields, so we should serialize properties instead.
                List <PropertyInfo> props = type.GetSerializableProperties();

                for (int f = 0; f < props.size; ++f)
                {
                    PropertyInfo prop = props[f];

                    if (prop.Name == "name" ||
                        prop.Name == "tag" ||
                        prop.Name == "hideFlags" ||
                        prop.Name == "enabled" ||
                        prop.Name == "material" ||
                        prop.Name == "materials")
                    {
                        continue;
                    }

                    object val = prop.GetValue(c, null);
                    if (val == null)
                    {
                        continue;
                    }

                    val = EncodeReference(go, val);
                    if (val == null)
                    {
                        continue;
                    }

                    node.AddChild(prop.Name, val);
                }
            }
        }
        /// <summary>
        /// Collect all meshes, materials and textures underneath the specified object and serialize them into the DataNode.
        /// </summary>

        static public void SerializeSharedResources(this GameObject go, DataNode node, bool includeInactive = false)
        {
            mFullSerialization = true;

            MeshFilter[]          filters = go.GetComponentsInChildren <MeshFilter>(includeInactive);
            MeshRenderer[]        rens    = go.GetComponentsInChildren <MeshRenderer>(includeInactive);
            SkinnedMeshRenderer[] sks     = go.GetComponentsInChildren <SkinnedMeshRenderer>(includeInactive);

            List <Material> materials = new List <Material>();
            List <Mesh>     meshes    = new List <Mesh>();

            foreach (MeshFilter f in filters)
            {
                Mesh m = f.sharedMesh;
                if (!meshes.Contains(m))
                {
                    meshes.Add(m);
                }
            }

            foreach (SkinnedMeshRenderer sk in sks)
            {
                Mesh m = sk.sharedMesh;
                if (!meshes.Contains(m))
                {
                    meshes.Add(m);
                }

                Material[] mats = sk.sharedMaterials;
                foreach (Material mt in mats)
                {
                    if (!materials.Contains(mt))
                    {
                        materials.Add(mt);
                    }
                }
            }

            foreach (MeshRenderer r in rens)
            {
                Material[] mats = r.sharedMaterials;
                foreach (Material m in mats)
                {
                    if (!materials.Contains(m))
                    {
                        materials.Add(m);
                    }
                }
            }

            if (materials.size == 0 && meshes.size == 0)
            {
                return;
            }

#if UNITY_EDITOR
            List <Texture> textures = new List <Texture>();

            for (int i = 0; i < materials.size; ++i)
            {
                Material mat = materials[i];
                Shader   s   = mat.shader;
                if (s == null)
                {
                    continue;
                }

                string matPath = UnityTools.LocateResource(mat);
                if (!string.IsNullOrEmpty(matPath))
                {
                    continue;
                }

                int props = UnityEditor.ShaderUtil.GetPropertyCount(s);

                for (int b = 0; b < props; ++b)
                {
                    string propName = UnityEditor.ShaderUtil.GetPropertyName(s, b);
                    UnityEditor.ShaderUtil.ShaderPropertyType type = UnityEditor.ShaderUtil.GetPropertyType(s, b);
                    if (type != UnityEditor.ShaderUtil.ShaderPropertyType.TexEnv)
                    {
                        continue;
                    }
                    Texture tex = mat.GetTexture(propName);
                    if (tex != null && !textures.Contains(tex))
                    {
                        textures.Add(tex);
                    }
                }
            }

            for (int i = 0; i < textures.size; ++i)
            {
                Texture tex = textures[i];
                tex.Serialize(node.AddChild("Texture", tex.GetInstanceID()));
            }
#endif

            for (int i = 0; i < materials.size; ++i)
            {
                Material mat = materials[i];
                mat.Serialize(node.AddChild("Material", mat.GetInstanceID()), false);
            }

            for (int i = 0; i < meshes.size; ++i)
            {
                Mesh mesh = meshes[i];
                mesh.Serialize(node.AddChild("Mesh", mesh.GetInstanceID()));
            }
        }
Beispiel #7
0
        /// <summary>
        /// Set the node's value using its text representation.
        /// Returns whether the child nodes should be processed or not.
        /// </summary>

        bool SetValue(string text, Type type, string[] parts)
        {
            if (type == null || type == typeof(void))
            {
                mValue = null;
            }
            else if (type == typeof(string))
            {
                mValue = text;
            }
            else if (type == typeof(bool))
            {
                bool b = false;
                if (bool.TryParse(text, out b))
                {
                    mValue = b;
                }
            }
            else if (type == typeof(byte))
            {
                byte b;
                if (byte.TryParse(text, out b))
                {
                    mValue = b;
                }
            }
            else if (type == typeof(Int16))
            {
                Int16 b;
                if (Int16.TryParse(text, out b))
                {
                    mValue = b;
                }
            }
            else if (type == typeof(UInt16))
            {
                UInt16 b;
                if (UInt16.TryParse(text, out b))
                {
                    mValue = b;
                }
            }
            else if (type == typeof(Int32))
            {
                Int32 b;
                if (Int32.TryParse(text, out b))
                {
                    mValue = b;
                }
            }
            else if (type == typeof(UInt32))
            {
                UInt32 b;
                if (UInt32.TryParse(text, out b))
                {
                    mValue = b;
                }
            }
            else if (type == typeof(float))
            {
                float b;
                if (float.TryParse(text, NumberStyles.Float, CultureInfo.InvariantCulture, out b))
                {
                    mValue = b;
                }
            }
            else if (type == typeof(double))
            {
                double b;
                if (double.TryParse(text, NumberStyles.Float, CultureInfo.InvariantCulture, out b))
                {
                    mValue = b;
                }
            }
            else if (type == typeof(Vector2))
            {
                if (parts == null)
                {
                    parts = text.Split(',');
                }

                if (parts.Length == 2)
                {
                    Vector2 v;
                    if (float.TryParse(parts[0], NumberStyles.Float, CultureInfo.InvariantCulture, out v.x) &&
                        float.TryParse(parts[1], NumberStyles.Float, CultureInfo.InvariantCulture, out v.y))
                    {
                        mValue = v;
                    }
                }
            }
            else if (type == typeof(Vector3))
            {
                if (parts == null)
                {
                    parts = text.Split(',');
                }

                if (parts.Length == 3)
                {
                    Vector3 v;
                    if (float.TryParse(parts[0], NumberStyles.Float, CultureInfo.InvariantCulture, out v.x) &&
                        float.TryParse(parts[1], NumberStyles.Float, CultureInfo.InvariantCulture, out v.y) &&
                        float.TryParse(parts[2], NumberStyles.Float, CultureInfo.InvariantCulture, out v.z))
                    {
                        mValue = v;
                    }
                }
            }
            else if (type == typeof(Vector4))
            {
                if (parts == null)
                {
                    parts = text.Split(',');
                }

                if (parts.Length == 4)
                {
                    Vector4 v;
                    if (float.TryParse(parts[0], NumberStyles.Float, CultureInfo.InvariantCulture, out v.x) &&
                        float.TryParse(parts[1], NumberStyles.Float, CultureInfo.InvariantCulture, out v.y) &&
                        float.TryParse(parts[2], NumberStyles.Float, CultureInfo.InvariantCulture, out v.z) &&
                        float.TryParse(parts[3], NumberStyles.Float, CultureInfo.InvariantCulture, out v.w))
                    {
                        mValue = v;
                    }
                }
            }
            else if (type == typeof(Quaternion))
            {
                if (parts == null)
                {
                    parts = text.Split(',');
                }

                if (parts.Length == 3)
                {
                    Vector3 v;
                    if (float.TryParse(parts[0], NumberStyles.Float, CultureInfo.InvariantCulture, out v.x) &&
                        float.TryParse(parts[1], NumberStyles.Float, CultureInfo.InvariantCulture, out v.y) &&
                        float.TryParse(parts[2], NumberStyles.Float, CultureInfo.InvariantCulture, out v.z))
                    {
                        mValue = Quaternion.Euler(v);
                    }
                }
                else if (parts.Length == 4)
                {
                    Quaternion v;
                    if (float.TryParse(parts[0], NumberStyles.Float, CultureInfo.InvariantCulture, out v.x) &&
                        float.TryParse(parts[1], NumberStyles.Float, CultureInfo.InvariantCulture, out v.y) &&
                        float.TryParse(parts[2], NumberStyles.Float, CultureInfo.InvariantCulture, out v.z) &&
                        float.TryParse(parts[3], NumberStyles.Float, CultureInfo.InvariantCulture, out v.w))
                    {
                        mValue = v;
                    }
                }
            }
            else if (type == typeof(Color))
            {
                if (parts == null)
                {
                    parts = text.Split(',');
                }

                if (parts.Length == 4)
                {
                    Color v;
                    if (float.TryParse(parts[0], NumberStyles.Float, CultureInfo.InvariantCulture, out v.r) &&
                        float.TryParse(parts[1], NumberStyles.Float, CultureInfo.InvariantCulture, out v.g) &&
                        float.TryParse(parts[2], NumberStyles.Float, CultureInfo.InvariantCulture, out v.b) &&
                        float.TryParse(parts[3], NumberStyles.Float, CultureInfo.InvariantCulture, out v.a))
                    {
                        mValue = v;
                    }
                }
            }
            else if (type == typeof(Rect))
            {
                if (parts == null)
                {
                    parts = text.Split(',');
                }

                if (parts.Length == 4)
                {
                    Vector4 v;
                    if (float.TryParse(parts[0], NumberStyles.Float, CultureInfo.InvariantCulture, out v.x) &&
                        float.TryParse(parts[1], NumberStyles.Float, CultureInfo.InvariantCulture, out v.y) &&
                        float.TryParse(parts[2], NumberStyles.Float, CultureInfo.InvariantCulture, out v.z) &&
                        float.TryParse(parts[3], NumberStyles.Float, CultureInfo.InvariantCulture, out v.w))
                    {
                        mValue = new Rect(v.x, v.y, v.z, v.w);
                    }
                }
            }
            else if (type.Implements(typeof(IDataNodeSerializable)))
            {
                IDataNodeSerializable ds = (IDataNodeSerializable)type.Create();
                ds.Deserialize(this);
                mValue = ds;
                return(false);
            }
            else if (!type.IsSubclassOf(typeof(Component)))
            {
                bool isIList = type.Implements(typeof(System.Collections.IList));
                bool isTList = (!isIList && type.Implements(typeof(TList)));
                mValue = (isTList || isIList) ? type.Create(children.size) : type.Create();

                if (mValue == null)
                {
                    Debug.LogError("Unable to create a " + type);
                    return(true);
                }

                if (isTList)
                {
                    TList list     = mValue as TList;
                    Type  elemType = type.GetGenericArgument();

                    if (elemType != null)
                    {
                        for (int i = 0; i < children.size; ++i)
                        {
                            DataNode child = children[i];

                            if (child.value == null)
                            {
                                child.mValue    = child.name;
                                child.mResolved = false;
                                child.ResolveValue(elemType);
                                list.Add(child.mValue);
                            }
                            else if (child.name == "Add")
                            {
                                child.ResolveValue(elemType);
                                list.Add(child.mValue);
                            }
                            else
                            {
                                Debug.LogWarning("Unexpected node in an array: " + child.name);
                            }
                        }
                        return(false);
                    }
                    else
                    {
                        Debug.LogError("Unable to determine the element type of " + type);
                    }
                }
                else if (isIList)
                {
                    // This is for both List<Type> and Type[] arrays.
                    System.Collections.IList list = mValue as System.Collections.IList;
                    Type elemType = type.GetGenericArgument();
                    if (elemType == null)
                    {
                        elemType = type.GetElementType();
                    }
                    bool fixedSize = (list.Count == children.size);

                    if (elemType != null)
                    {
                        for (int i = 0; i < children.size; ++i)
                        {
                            DataNode child = children[i];

                            if (child.value == null)
                            {
                                child.mValue    = child.name;
                                child.mResolved = false;
                                child.ResolveValue(elemType);
                                if (fixedSize)
                                {
                                    list[i] = child.mValue;
                                }
                                else
                                {
                                    list.Add(child.mValue);
                                }
                            }
                            else if (child.name == "Add")
                            {
                                child.ResolveValue(elemType);
                                if (fixedSize)
                                {
                                    list[i] = child.mValue;
                                }
                                else
                                {
                                    list.Add(child.mValue);
                                }
                            }
                            else
                            {
                                Debug.LogWarning("Unexpected node in an array: " + child.name);
                            }
                        }
                        return(false);
                    }
                    else
                    {
                        Debug.LogError("Unable to determine the element type of " + type);
                    }
                }
                else if (type.IsClass)
                {
                    for (int i = 0; i < children.size; ++i)
                    {
                        DataNode child = children[i];
                        mValue.SetSerializableField(child.name, child.value);
                    }
                    return(false);
                }
                else
                {
                    Debug.LogError("Unhandled type: " + type);
                }
            }
            return(true);
        }
Beispiel #8
0
        /// <summary>
        /// Load a game object prefab at the specified path. This is equivalent to Resources.Load, but it will
        /// also consider DataNode-exported binary assets as well, automatically loading them as if they were
        /// regular prefabs.
        /// </summary>

        static public GameObject LoadPrefab(string path)
        {
            if (string.IsNullOrEmpty(path))
            {
                return(null);
            }
            if (!Application.isPlaying)
            {
                return(Resources.Load(path, typeof(GameObject)) as GameObject);
            }

            GameObject prefab = null;

            if (mPrefabRoot == null)
            {
                GameObject go = new GameObject("Prefabs");
                Object.DontDestroyOnLoad(go);
                mPrefabRoot = go.transform;
                mPrefabs.Clear();
            }

            // Try to get it from cache
            if (mPrefabs.TryGetValue(path, out prefab))
            {
                return(prefab);
            }

            if (prefab == null)
            {
                // Load it from resources as a Game Object
                prefab = Resources.Load(path, typeof(GameObject)) as GameObject;

                if (prefab == null)
                {
                    // Load it from resources as a binary asset
                    byte[] bytes = UnityTools.LoadBinary(path);

                    if (bytes != null)
                    {
                        // Parse the DataNode hierarchy
                        DataNode data = DataNode.Read(bytes);

                        if (data != null)
                        {
                            // Instantiate and immediately disable the object
                            prefab = data.Instantiate();

                            if (prefab != null)
                            {
                                mPrefabs.Add(path, prefab);
                                Object.DontDestroyOnLoad(prefab);
                                prefab.transform.parent = mPrefabRoot;
                                prefab.SetActive(false);
                                return(prefab);
                            }
                        }
                    }
                }
            }

            if (prefab == null)
            {
#if UNITY_EDITOR
                Debug.LogError("[TNet] Attempting to create a game object that can't be found in the Resources folder: [" + path + "]");
#endif
                prefab = GetDummyObject();
            }

            mPrefabs.Add(path, prefab);
            return(prefab);
        }
        /// <summary>
        /// Serialize this game object into a DataNode.
        /// Note that the prefab references can only be resolved if serialized from within the Unity Editor.
        /// You can instantiate this game object directly from DataNode format by using DataNode.Instantiate().
        /// Ideal usage: save a game object hierarchy into a file. Serializing a game object will also serialize its
        /// mesh data, making it possible to export entire 3D models. Any references to prefabs or materials located
        /// in the Resources folder will be kept as references and their hierarchy won't be serialized.
        /// </summary>

        static public DataNode Serialize(this GameObject go, bool fullHierarchy = true, bool isRootNode = true)
        {
            DataNode root = new DataNode(go.name, go.GetInstanceID());

            // Save a reference to a prefab, if there is one
            string prefab = UnityTools.LocateResource(go, !isRootNode);

            if (!string.IsNullOrEmpty(prefab))
            {
                root.AddChild("prefab", prefab);
            }

            // Save the transform and the object's layer
            Transform trans = go.transform;

            root.AddChild("position", trans.localPosition);
            root.AddChild("rotation", trans.localEulerAngles);
            root.AddChild("scale", trans.localScale);

            int layer = go.layer;

            if (layer != 0)
            {
                root.AddChild("layer", go.layer);
            }

            // If this was a prefab instance, don't do anything else
            if (!string.IsNullOrEmpty(prefab))
            {
                return(root);
            }

            // Collect all meshes
            if (isRootNode)
            {
                DataNode child = new DataNode("Resources");
#if UNITY_EDITOR
                go.SerializeSharedResources(child, UnityEditor.PrefabUtility.GetPrefabType(go) == UnityEditor.PrefabType.Prefab);
#else
                go.SerializeSharedResources(child);
#endif
                if (child.children.size != 0)
                {
                    root.children.Add(child);
                }
                mFullSerialization = false;
            }

            Component[] comps    = go.GetComponents <Component>();
            DataNode    compRoot = null;

            for (int i = 0, imax = comps.Length; i < imax; ++i)
            {
                Component c = comps[i];

                System.Type type = c.GetType();
                if (type == typeof(Transform))
                {
                    continue;
                }

                if (compRoot == null)
                {
                    compRoot = root.AddChild("Components");
                }
                DataNode child = compRoot.AddChild(Serialization.TypeToName(type), c.GetInstanceID());
                c.Serialize(child, type);
            }

            if (fullHierarchy && trans.childCount > 0)
            {
                DataNode children = root.AddChild("Children");

                for (int i = 0, imax = trans.childCount; i < imax; ++i)
                {
                    GameObject child = trans.GetChild(i).gameObject;
                    if (child.activeInHierarchy)
                    {
                        children.children.Add(child.Serialize(true, false));
                    }
                }
            }
            if (isRootNode)
            {
                mFullSerialization = true;
            }
            return(root);
        }
Beispiel #10
0
        /// <summary>
        /// Set a node's value given its hierarchical path.
        /// </summary>

        public DataNode SetHierarchy(string path, object obj)
        {
            DataNode node = this;

            if (!string.IsNullOrEmpty(path))
            {
                if (path.IndexOf('\\') == -1 && path.IndexOf('/') == -1)
                {
                    if (obj == null)
                    {
                        RemoveChild(path);
                        return(null);
                    }

                    node = GetChild(path, true);
                }
                else
                {
                    path = path.Replace("\\", "/");
                    var      names  = path.Split('/');
                    DataNode parent = null;
                    int      index  = 0;

                    while (node != null && index < names.Length)
                    {
                        bool found = false;

                        for (int i = 0; i < node.children.size; ++i)
                        {
                            if (node.children[i].name == names[index])
                            {
                                parent = node;
                                node   = node.children[i];
                                ++index;
                                found = true;
                                break;
                            }
                        }

                        if (!found)
                        {
                            // No need to do anything -- the requested path is already missing
                            if (obj == null)
                            {
                                return(parent);
                            }

                            // Add a new node
                            parent = node;
                            node   = node.AddChild(names[index]);
                            ++index;
                        }
                    }

                    if (node != null && obj == null)
                    {
                        parent.RemoveChild(names[index - 1]);
                        return(parent);
                    }
                }
            }

            if (obj is DataNode)
            {
                DataNode other = (obj as DataNode);
                node.value = other.value;
                node.children.Clear();
                node.mCache = null;
                for (int i = 0; i < other.children.size; ++i)
                {
                    node.children.Add(other.children[i].Clone());
                }
            }
            else
            {
                node.value = obj;
            }
            return(node);
        }
Beispiel #11
0
        /// <summary>
        /// Write the values into the stream writer.
        /// </summary>

        static void Write(StreamWriter writer, string name, object value, int tab = 0)
        {
            bool prefix = false;

            if (!string.IsNullOrEmpty(name))
            {
                prefix = true;
                writer.WriteTabs(tab);
                writer.Write(name);
            }
            else if (value != null)
            {
                writer.WriteTabs(tab);
            }

            if (value != null && !writer.WriteObject(value, prefix))
            {
                var type = value.GetType();

                if (value is DataNode)
                {
                    if (prefix)
                    {
                        writer.Write(" = ");
                    }
                    writer.Write("DataNode");
                    writer.Write('\n');
                    var node = (DataNode)value;
                    node.Write(writer, tab + 1);
                    return;
                }

#if !STANDALONE
                if (value is AnimationCurve)
                {
                    var ac  = value as AnimationCurve;
                    var kfs = ac.keys;
                    type = typeof(Vector4[]);
                    var imax = kfs.Length;
                    var vs   = new Vector4[imax];

                    for (int i = 0; i < imax; ++i)
                    {
                        var kf = kfs[i];
                        vs[i] = new Vector4(kf.time, kf.value, kf.inTangent, kf.outTangent);
                    }
                    value = vs;
                }
#endif
                // Save cloth skinning coefficients as a Vector2 array
                if (value is ClothSkinningCoefficient[])
                {
                    var cf = value as ClothSkinningCoefficient[];
                    type = typeof(Vector2[]);
                    var imax = cf.Length;
                    var vs   = new Vector2[imax];

                    for (int i = 0; i < imax; ++i)
                    {
                        vs[i].x = cf[i].maxDistance;
                        vs[i].y = cf[i].collisionSphereDistance;
                    }
                    value = vs;
                }

                if (value is TList)
                {
                    var list = value as TList;

                    if (prefix)
                    {
                        writer.Write(" = ");
                    }
                    writer.Write(Serialization.TypeToName(type));

                    if (list.Count > 0)
                    {
                        for (int i = 0, imax = list.Count; i < imax; ++i)
                        {
                            writer.Write('\n');
                            Write(writer, null, list.Get(i), tab + 1);
                        }
                    }
                    return;
                }

                if (value is System.Collections.IList)
                {
                    var list = value as System.Collections.IList;

                    if (prefix)
                    {
                        writer.Write(" = ");
                    }
                    writer.Write(Serialization.TypeToName(type));

                    if (list.Count > 0)
                    {
                        for (int i = 0, imax = list.Count; i < imax; ++i)
                        {
                            writer.Write('\n');
                            Write(writer, null, list[i], tab + 1);
                        }
                    }
                    return;
                }

                // IDataNodeSerializable interface has serialization functions
                if (value is IDataNodeSerializable)
                {
                    var ser  = value as IDataNodeSerializable;
                    var temp = mTemp;
                    mTemp = null;
                    if (temp == null)
                    {
                        temp = new DataNode();
                    }
                    ser.Serialize(temp);

                    if (prefix)
                    {
                        writer.Write(" = ");
                    }
                    writer.Write(Serialization.TypeToName(type));

                    for (int i = 0; i < temp.children.size; ++i)
                    {
                        var child = temp.children[i];
                        writer.Write('\n');
                        child.Write(writer, tab + 1);
                    }

                    temp.Clear();
                    mTemp = temp;
                    return;
                }

#if REFLECTION_SUPPORT
#if SERIALIZATION_WITHOUT_INTERFACE
                // Try custom serialization first
                if (type.HasDataNodeSerialization())
                {
                    var temp = mTemp;
                    mTemp = null;
                    if (temp == null)
                    {
                        temp = new DataNode();
                    }

                    if (value.Invoke("Serialize", temp))
                    {
                        if (prefix)
                        {
                            writer.Write(" = ");
                        }
                        writer.Write(Serialization.TypeToName(type));

                        for (int i = 0; i < temp.children.size; ++i)
                        {
                            var child = temp.children[i];
                            writer.Write('\n');
                            child.Write(writer, tab + 1);
                        }

                        temp.Clear();
                        mTemp = temp;
                        return;
                    }
                }
#endif

                if (prefix)
                {
                    writer.Write(" = ");
                }
                writer.Write(Serialization.TypeToName(type));
                var fields = type.GetSerializableFields();

                // We have fields to serialize
                for (int i = 0; i < fields.size; ++i)
                {
                    var field = fields[i];
                    var val   = field.GetValue(value);

                    if (val != null)
                    {
                        writer.Write('\n');
                        Write(writer, field.Name, val, tab + 1);
                    }
                }

                if (fields.size == 0 || type.IsDefined(typeof(SerializeProperties), true))
                {
                    // We don't have fields to serialize, but we may have properties
                    var props = type.GetSerializableProperties();

                    if (props.size > 0)
                    {
                        for (int i = 0; i < props.size; ++i)
                        {
                            var    prop = props[i];
                            object val  = prop.GetValue(value, null);

                            if (val != null)
                            {
                                writer.Write('\n');
                                Write(writer, prop.Name, val, tab + 1);
                            }
                        }
                    }
                }
#endif
            }
        }
Beispiel #12
0
        /// <summary>
        /// Write the values into the stream writer.
        /// </summary>

        static void Write(StreamWriter writer, string name, object value, int tab = 0)
        {
            bool prefix = false;

            if (!string.IsNullOrEmpty(name))
            {
                prefix = true;
                writer.WriteTabs(tab);
                writer.Write(name);
            }
            else if (value != null)
            {
                writer.WriteTabs(tab);
            }

            if (value != null && !writer.WriteObject(value, prefix))
            {
                Type type = value.GetType();

#if !STANDALONE
                if (value is AnimationCurve)
                {
                    AnimationCurve ac  = value as AnimationCurve;
                    Keyframe[]     kfs = ac.keys;

                    type = typeof(Vector4[]);

                    Vector4[] vs = new Vector4[kfs.Length];

                    for (int i = 0, imax = kfs.Length; i < imax; ++i)
                    {
                        Keyframe kf = kfs[i];
                        vs[i] = new Vector4(kf.time, kf.value, kf.inTangent, kf.outTangent);
                    }
                    value = vs;
                }
#endif
                if (value is TList)
                {
                    TList list = value as TList;

                    if (prefix)
                    {
                        writer.Write(" = ");
                    }
                    writer.Write(Serialization.TypeToName(type));

                    if (list.Count > 0)
                    {
                        for (int i = 0, imax = list.Count; i < imax; ++i)
                        {
                            writer.Write('\n');
                            Write(writer, null, list.Get(i), tab + 1);
                        }
                    }
                    return;
                }

                if (value is System.Collections.IList)
                {
                    System.Collections.IList list = value as System.Collections.IList;

                    if (prefix)
                    {
                        writer.Write(" = ");
                    }
                    writer.Write(Serialization.TypeToName(type));

                    if (list.Count > 0)
                    {
                        for (int i = 0, imax = list.Count; i < imax; ++i)
                        {
                            writer.Write('\n');
                            Write(writer, null, list[i], tab + 1);
                        }
                    }
                    return;
                }

                if (value is IDataNodeSerializable)
                {
                    IDataNodeSerializable ser = value as IDataNodeSerializable;
                    DataNode node             = new DataNode();
                    ser.Serialize(node);

                    if (prefix)
                    {
                        writer.Write(" = ");
                    }
                    writer.Write(Serialization.TypeToName(type));

                    for (int i = 0; i < node.children.size; ++i)
                    {
                        DataNode child = node.children[i];
                        writer.Write('\n');
                        child.Write(writer, tab + 1);
                    }
                    return;
                }

#if REFLECTION_SUPPORT
                if (prefix)
                {
                    writer.Write(" = ");
                }
                writer.Write(Serialization.TypeToName(type));
                var fields = type.GetSerializableFields();

                // We have fields to serialize
                for (int i = 0; i < fields.size; ++i)
                {
                    FieldInfo field = fields[i];
                    object    val   = field.GetValue(value);

                    if (val != null)
                    {
                        writer.Write('\n');
                        Write(writer, field.Name, val, tab + 1);
                    }
                }

                if (fields.size == 0 || type.IsDefined(typeof(SerializeProperties), true))
                {
                    // We don't have fields to serialize, but we may have properties
                    var props = type.GetSerializableProperties();

                    if (props.size > 0)
                    {
                        for (int i = 0; i < props.size; ++i)
                        {
                            var    prop = props[i];
                            object val  = prop.GetValue(value, null);

                            if (val != null)
                            {
                                writer.Write('\n');
                                Write(writer, prop.Name, val, tab + 1);
                            }
                        }
                    }
                }
#endif
            }
        }
Beispiel #13
0
        /// <summary>
        /// Process the string values, converting them to proper objects.
        /// Returns whether child nodes should be processed in turn.
        /// </summary>

        public bool ResolveValue(Type type = null)
        {
            if (mValue is string)
            {
                mResolved = true;
                string line = mValue as string;

                // Trim strings wrapped in quotes
                if (type == typeof(string))
                {
                    if (line == "\"\"")
                    {
                        mValue = "";
                    }
                    else
                    {
                        int len = line.Length;
                        if (len > 2 && line[0] == '"' && line[len - 1] == '"')
                        {
                            mValue = line.Substring(1, len - 2);
                        }
                    }
                    return(true);
                }

                // Try to resolve this type as a simple type
                if (Serialization.ReadObject(line, out mValue, type))
                {
                    return(true);
                }

                // This type is either a class or an array
                if (type == null)
                {
                    type = Serialization.NameToType(line);
                }

                if (type == null || type == typeof(void))
                {
                    mValue = null;
                    return(true);
                }
                else if (type.Implements(typeof(IDataNodeSerializable)))
                {
                    IDataNodeSerializable ds = (IDataNodeSerializable)type.Create();
                    ds.Deserialize(this);
                    mValue = ds;
                    return(false);
                }
#if !STANDALONE
                else if (type == typeof(AnimationCurve))
                {
                    if (children.size != 0)
                    {
                        AnimationCurve cv  = new AnimationCurve();
                        Keyframe[]     kfs = new Keyframe[children.size];

                        for (int i = 0; i < children.size; ++i)
                        {
                            DataNode child = children[i];

                            if (child.value == null)
                            {
                                child.mValue    = child.name;
                                child.mResolved = false;
                                child.ResolveValue(typeof(Vector4));

                                Vector4 v = (Vector4)child.mValue;
                                kfs[i] = new Keyframe(v.x, v.y, v.z, v.w);
                            }
                            else
                            {
                                Vector4 v = (Vector4)child.mValue;
                                kfs[i] = new Keyframe(v.x, v.y, v.z, v.w);
                            }
                        }

                        cv.keys = kfs;
                        mValue  = cv;
                        children.Clear();
                    }
                    return(false);
                }
                else if (type == typeof(LayerMask))
                {
                    mValue = (LayerMask)Get <int>();
                }
#endif
                else
#if !STANDALONE
                if (!type.IsSubclassOf(typeof(Component)))
#endif
                {
                    bool isIList = type.Implements(typeof(System.Collections.IList));
                    bool isTList = (!isIList && type.Implements(typeof(TList)));
                    mValue = (isTList || isIList) ? type.Create(children.size) : type.Create();

                    if (mValue == null)
                    {
                        Tools.LogError("Unable to create a " + type);
                        return(true);
                    }

                    if (isTList)
                    {
                        TList list     = mValue as TList;
                        Type  elemType = type.GetGenericArgument();

                        if (elemType != null)
                        {
                            for (int i = 0; i < children.size; ++i)
                            {
                                DataNode child = children[i];

                                if (child.value == null)
                                {
                                    child.mValue    = child.name;
                                    child.mResolved = false;
                                    child.ResolveValue(elemType);
                                    list.Add(child.mValue);
                                }
                                else if (child.name == "Add")
                                {
                                    child.ResolveValue(elemType);
                                    list.Add(child.mValue);
                                }
                                else
                                {
                                    Tools.LogError("Unexpected node in an array: " + child.name);
                                }
                            }
                            return(false);
                        }
                        else
                        {
                            Tools.LogError("Unable to determine the element type of " + type);
                        }
                    }
                    else if (isIList)
                    {
                        // This is for both List<Type> and Type[] arrays.
                        System.Collections.IList list = mValue as System.Collections.IList;
                        Type elemType = type.GetGenericArgument();
                        if (elemType == null)
                        {
                            elemType = type.GetElementType();
                        }
                        bool fixedSize = (list.Count == children.size);

                        if (elemType != null)
                        {
                            for (int i = 0; i < children.size; ++i)
                            {
                                DataNode child = children[i];

                                if (child.value == null)
                                {
                                    child.mValue    = child.name;
                                    child.mResolved = false;
                                    child.ResolveValue(elemType);

                                    if (fixedSize)
                                    {
                                        list[i] = child.mValue;
                                    }
                                    else
                                    {
                                        list.Add(child.mValue);
                                    }
                                }
                                else if (child.name == "Add")
                                {
                                    child.ResolveValue(elemType);
                                    if (fixedSize)
                                    {
                                        list[i] = child.mValue;
                                    }
                                    else
                                    {
                                        list.Add(child.mValue);
                                    }
                                }
                                else
                                {
                                    Tools.LogError("Unexpected node in an array: " + child.name);
                                }
                            }
                            return(false);
                        }
                        else
                        {
                            Tools.LogError("Unable to determine the element type of " + type);
                        }
                    }
                    else
                    {
                        for (int i = 0; i < children.size; ++i)
                        {
                            DataNode child = children[i];
                            mValue.SetFieldOrPropertyValue(child.name, child.value);
                        }
                        return(false);
                    }
                }
                return(true);
            }
            return(true);
        }
 protected virtual void OnSetPlayerData(Player p, string path, DataNode node)
 {
 }
        /// <summary>
        /// Serialize the entire texture into the specified DataNode.
        /// </summary>

        static public void Serialize(this Texture tex, DataNode node)
        {
            if (!mFullSerialization)
            {
                return;
            }

            node.AddChild("name", tex.name);
            string path = UnityTools.LocateResource(tex);

            if (!string.IsNullOrEmpty(path))
            {
                node.AddChild("path", path);
                return;
            }

            if (tex is Texture2D)
            {
                Texture2D t2 = tex as Texture2D;

#if UNITY_EDITOR
                try
                {
                    byte[] bytes = t2.EncodeToPNG();
                    if (bytes != null)
                    {
                        node.AddChild("bytes", bytes);
                    }
                    else
                    {
                        Debug.Log(t2.name + " (" + t2.format + ")", tex);
                    }
                }
                catch (Exception)
                {
                    string assetPath = UnityEditor.AssetDatabase.GetAssetPath(tex);

                    if (!string.IsNullOrEmpty(assetPath))
                    {
                        UnityEditor.TextureImporter ti = UnityEditor.AssetImporter.GetAtPath(assetPath) as UnityEditor.TextureImporter;
                        ti.isReadable = true;
                        UnityEditor.AssetDatabase.ImportAsset(assetPath);
                        byte[] bytes = t2.EncodeToPNG();
                        if (bytes != null)
                        {
                            node.AddChild("bytes", bytes);
                        }
                        else
                        {
                            Debug.Log(t2.name + " (" + t2.format + ")", tex);
                        }
                    }
                }
#else
                node.AddChild("bytes", t2.EncodeToPNG());
#endif
                node.AddChild("filter", (int)t2.filterMode);
                node.AddChild("wrap", (int)t2.wrapMode);
                node.AddChild("af", t2.anisoLevel);
                return;
            }

            Debug.LogWarning("Unable to save a reference to texture '" + tex.name + "' because it's not in the Resources folder.", tex);
        }
        /// <summary>
        /// Serialize the specified renderer into its DataNode format.
        /// </summary>

        static void Serialize(this MeshRenderer ren, DataNode root)
        {
            SerializeRenderer(ren, root);
        }
        /// <summary>
        /// Deserialize the texture that was previously serialized into the DataNode format.
        /// </summary>

        static public Texture DeserializeTexture(this DataNode node)
        {
            // First try the cache
            Texture tex = null;
            int     id  = node.Get <int>();

            if (id != 0 && mTextures.TryGetValue(id, out tex) && tex != null)
            {
                return(tex);
            }

            // If the texture's ID is unknown, make a dummy one and try going through cache again
            string name = node.GetChild <string>("name", "Unnamed");
            string path = node.GetChild <string>("path");

            if (id == 0)
            {
                id = (path + name).GetHashCode();
                if (mTextures.TryGetValue(id, out tex) && tex != null)
                {
                    return(tex);
                }
            }

            // Next try to load the texture
            if (!string.IsNullOrEmpty(path))
            {
                tex = UnityTools.Load <Texture>(path);

                if (tex != null)
                {
                    mTextures[id] = tex;
                    return(tex);
                }
            }

            // Lastly, create a new texture
            Texture2D t2 = new Texture2D(2, 2);

            t2.name = name;

            // Try to load the texture's data
            byte[] bytes = node.GetChild <byte[]>("bytes");

            if (bytes != null)
            {
                t2.LoadImage(bytes);
                t2.filterMode = (FilterMode)node.GetChild <int>("filter", (int)t2.filterMode);
                t2.wrapMode   = (TextureWrapMode)node.GetChild <int>("wrap", (int)t2.wrapMode);
                t2.anisoLevel = node.GetChild <int>("af", t2.anisoLevel);
                t2.Apply();
            }
            else
            {
#if UNITY_EDITOR
                Debug.LogWarning("Creating a dummy texture: " + t2.name, t2);
#endif
                t2.SetPixels(new Color[] { Color.clear, Color.clear, Color.clear, Color.clear });
                t2.Apply();
            }

            // Add it to cache
            tex           = t2;
            mTextures[id] = tex;
            return(tex);
        }
        /// <summary>
        /// Deserialize a previously serialized renderer.
        /// </summary>

        static void Deserialize(this MeshRenderer ren, DataNode data)
        {
            Deserialize((Renderer)ren, data);
        }
Beispiel #19
0
        /// <summary>
        /// Write the values into the stream writer.
        /// </summary>

        static void Write(StreamWriter writer, int tab, string name, object value, bool writeType)
        {
            if (string.IsNullOrEmpty(name) && value == null)
            {
                return;
            }

            WriteTabs(writer, tab);

            if (name != null)
            {
                writer.Write(Escape(name));

                if (value == null)
                {
                    writer.Write('\n');
                    return;
                }
            }

            Type type = value.GetType();

            if (type == typeof(string))
            {
                if (name != null)
                {
                    writer.Write(" = \"");
                }
                writer.Write((string)value);
                if (name != null)
                {
                    writer.Write('"');
                }
                writer.Write('\n');
            }
            else if (type == typeof(bool))
            {
                if (name != null)
                {
                    writer.Write(" = ");
                }
                writer.Write((bool)value ? "true" : "false");
                writer.Write('\n');
            }
            else if (type == typeof(Int32) || type == typeof(float) || type == typeof(UInt32) ||
                     type == typeof(byte) || type == typeof(short) || type == typeof(ushort))
            {
                if (name != null)
                {
                    writer.Write(" = ");
                }
                writer.Write(value.ToString());
                writer.Write('\n');
            }
            else if (type == typeof(Vector2))
            {
                Vector2 v = (Vector2)value;
                writer.Write(name != null ? " = (" : "(");
                writer.Write(v.x.ToString(CultureInfo.InvariantCulture));
                writer.Write(", ");
                writer.Write(v.y.ToString(CultureInfo.InvariantCulture));
                writer.Write(")\n");
            }
            else if (type == typeof(Vector3))
            {
                Vector3 v = (Vector3)value;
                writer.Write(name != null ? " = (" : "(");
                writer.Write(v.x.ToString(CultureInfo.InvariantCulture));
                writer.Write(", ");
                writer.Write(v.y.ToString(CultureInfo.InvariantCulture));
                writer.Write(", ");
                writer.Write(v.z.ToString(CultureInfo.InvariantCulture));
                writer.Write(")\n");
            }
            else if (type == typeof(Color))
            {
                Color c = (Color)value;
                writer.Write(name != null ? " = (" : "(");
                writer.Write(c.r.ToString(CultureInfo.InvariantCulture));
                writer.Write(", ");
                writer.Write(c.g.ToString(CultureInfo.InvariantCulture));
                writer.Write(", ");
                writer.Write(c.b.ToString(CultureInfo.InvariantCulture));
                writer.Write(", ");
                writer.Write(c.a.ToString(CultureInfo.InvariantCulture));
                writer.Write(")\n");
            }
            else if (type == typeof(Color32))
            {
                Color32 c = (Color32)value;
                writer.Write(name != null ? " = 0x" : "0x");

                if (c.a == 255)
                {
                    int i = (c.r << 16) | (c.g << 8) | c.b;
                    writer.Write(i.ToString("X6"));
                }
                else
                {
                    int i = (c.r << 24) | (c.g << 16) | (c.b << 8) | c.a;
                    writer.Write(i.ToString("X8"));
                }
                writer.Write('\n');
            }
            else
            {
                if (type == typeof(Vector4))
                {
                    Vector4 v = (Vector4)value;
                    if (name != null)
                    {
                        writer.Write(" = ");
                    }
                    writer.Write(Serialization.TypeToName(type));
                    writer.Write('(');
                    writer.Write(v.x.ToString(CultureInfo.InvariantCulture));
                    writer.Write(", ");
                    writer.Write(v.y.ToString(CultureInfo.InvariantCulture));
                    writer.Write(", ");
                    writer.Write(v.z.ToString(CultureInfo.InvariantCulture));
                    writer.Write(", ");
                    writer.Write(v.w.ToString(CultureInfo.InvariantCulture));
                    writer.Write(")\n");
                }
                else if (type == typeof(Quaternion))
                {
                    Quaternion q = (Quaternion)value;
                    Vector3    v = q.eulerAngles;
                    if (name != null)
                    {
                        writer.Write(" = ");
                    }
                    writer.Write(Serialization.TypeToName(type));
                    writer.Write('(');
                    writer.Write(v.x.ToString(CultureInfo.InvariantCulture));
                    writer.Write(", ");
                    writer.Write(v.y.ToString(CultureInfo.InvariantCulture));
                    writer.Write(", ");
                    writer.Write(v.z.ToString(CultureInfo.InvariantCulture));
                    writer.Write(")\n");
                }
                else if (type == typeof(Rect))
                {
                    Rect r = (Rect)value;
                    if (name != null)
                    {
                        writer.Write(" = ");
                    }
                    writer.Write(Serialization.TypeToName(type));
                    writer.Write('(');
                    writer.Write(r.x.ToString(CultureInfo.InvariantCulture));
                    writer.Write(", ");
                    writer.Write(r.y.ToString(CultureInfo.InvariantCulture));
                    writer.Write(", ");
                    writer.Write(r.width.ToString(CultureInfo.InvariantCulture));
                    writer.Write(", ");
                    writer.Write(r.height.ToString(CultureInfo.InvariantCulture));
                    writer.Write(")\n");
                }
                else if (value is TList)
                {
                    TList list = value as TList;

                    if (name != null)
                    {
                        writer.Write(" = ");
                    }
                    writer.Write(Serialization.TypeToName(type));
                    writer.Write('\n');

                    if (list.Count > 0)
                    {
                        for (int i = 0, imax = list.Count; i < imax; ++i)
                        {
                            Write(writer, tab + 1, null, list.Get(i), false);
                        }
                    }
                }
                else if (value is System.Collections.IList)
                {
                    System.Collections.IList list = value as System.Collections.IList;

                    if (name != null)
                    {
                        writer.Write(" = ");
                    }
                    writer.Write(Serialization.TypeToName(type));
                    writer.Write('\n');

                    if (list.Count > 0)
                    {
                        for (int i = 0, imax = list.Count; i < imax; ++i)
                        {
                            Write(writer, tab + 1, null, list[i], false);
                        }
                    }
                }
                else if (value is IDataNodeSerializable)
                {
                    IDataNodeSerializable ser = value as IDataNodeSerializable;
                    DataNode node             = new DataNode();
                    ser.Serialize(node);

                    if (name != null)
                    {
                        writer.Write(" = ");
                    }
                    writer.Write(Serialization.TypeToName(type));
                    writer.Write('\n');

                    for (int i = 0; i < node.children.size; ++i)
                    {
                        DataNode child = node.children[i];
                        child.Write(writer, tab + 1);
                    }
                }
                else if (value is GameObject)
                {
                    Debug.LogError("It's not possible to save game objects.");
                    writer.Write('\n');
                }
                else if ((value as Component) != null)
                {
                    Debug.LogError("It's not possible to save components.");
                    writer.Write('\n');
                }
                else
                {
                    if (writeType)
                    {
                        if (name != null)
                        {
                            writer.Write(" = ");
                        }
                        writer.Write(Serialization.TypeToName(type));
                    }
                    writer.Write('\n');

#if REFLECTION_SUPPORT
                    List <FieldInfo> fields = type.GetSerializableFields();

                    if (fields.size > 0)
                    {
                        for (int i = 0; i < fields.size; ++i)
                        {
                            FieldInfo field = fields[i];
                            object    val   = field.GetValue(value);
                            if (val != null)
                            {
                                Write(writer, tab + 1, field.Name, val, true);
                            }
                        }
                    }
#endif
                }
            }
        }
        /// <summary>
        /// Serialize the specified material into its DataNode format.
        /// </summary>

        static public void Serialize(this Material mat, DataNode node)
        {
            mat.Serialize(node, true);
        }
Beispiel #21
0
        /// <summary>
        /// Process a single incoming packet. Returns whether we should keep processing packets or not.
        /// </summary>

        bool ProcessPacket(Buffer buffer, IPEndPoint ip)
        {
            mPacketSource = ip;
            BinaryReader reader = buffer.BeginReading();

            if (buffer.size == 0)
            {
                return(true);
            }

            int    packetID = reader.ReadByte();
            Packet response = (Packet)packetID;

#if DEBUG_PACKETS && !STANDALONE
            if (response != Packet.ResponsePing && response != Packet.Broadcast)
            {
                UnityEngine.Debug.Log("Client: " + response + " (" + buffer.size + " bytes) " + ((ip == null) ? "(TCP)" : "(UDP)"));
            }
#endif
            // Verification step must be passed first
            if (response == Packet.ResponseID || mTcp.stage == TcpProtocol.Stage.Verifying)
            {
                if (mTcp.VerifyResponseID(response, reader))
                {
                    mTimeDifference = reader.ReadInt64() - (System.DateTime.UtcNow.Ticks / 10000);

#if !UNITY_WEBPLAYER
                    if (mUdp.isActive)
                    {
                        // If we have a UDP listener active, tell the server
                        BeginSend(Packet.RequestSetUDP).Write((ushort)mUdp.listeningPort);
                        EndSend();
                    }
#endif
                    mCanPing = true;
                    if (onConnect != null)
                    {
                        onConnect(true, null);
                    }
                }
                return(true);
            }

            OnPacket callback;

            if (packetHandlers.TryGetValue((byte)response, out callback) && callback != null)
            {
                callback(response, reader, ip);
                return(true);
            }

            switch (response)
            {
            case Packet.Empty: break;

            case Packet.ForwardToAll:
            case Packet.ForwardToOthers:
            case Packet.ForwardToAllSaved:
            case Packet.ForwardToOthersSaved:
            case Packet.ForwardToHost:
            case Packet.BroadcastAdmin:
            case Packet.Broadcast:
            {
                packetSourceID = reader.ReadInt32();
                int channelID = reader.ReadInt32();
                if (onForwardedPacket != null)
                {
                    onForwardedPacket(channelID, reader);
                }
                break;
            }

            case Packet.ForwardToPlayer:
            {
                packetSourceID = reader.ReadInt32();
                reader.ReadInt32();                 // Skip the target player ID
                int channelID = reader.ReadInt32();
                if (onForwardedPacket != null)
                {
                    onForwardedPacket(channelID, reader);
                }
                break;
            }

            case Packet.ForwardByName:
            {
                packetSourceID = reader.ReadInt32();
                reader.ReadString();                 // Skip the player name
                int channelID = reader.ReadInt32();
                if (onForwardedPacket != null)
                {
                    onForwardedPacket(channelID, reader);
                }
                break;
            }

            case Packet.ResponseSetPlayerData:
            {
                int    pid    = reader.ReadInt32();
                Player target = GetPlayer(pid);

                if (target != null)
                {
                    string   path = reader.ReadString();
                    DataNode node = target.Set(path, reader.ReadObject());
                    if (onSetPlayerData != null)
                    {
                        onSetPlayerData(target, path, node);
                    }
                }
                else
                {
                    UnityEngine.Debug.LogError("Not found: " + pid);
                }
                break;
            }

            case Packet.ResponsePing:
            {
                int ping = (int)(mMyTime - mPingTime);

                if (ip != null)
                {
                    if (onPing != null && ip != null)
                    {
                        onPing(ip, ping);
                    }
                }
                else
                {
                    mCanPing = true;
                    mPing    = ping;
                }
                break;
            }

            case Packet.ResponseSetUDP:
            {
#if !UNITY_WEBPLAYER
                // The server has a new port for UDP traffic
                ushort port = reader.ReadUInt16();

                if (port != 0 && mTcp.tcpEndPoint != null)
                {
                    IPAddress ipa = new IPAddress(mTcp.tcpEndPoint.Address.GetAddressBytes());
                    mServerUdpEndPoint = new IPEndPoint(ipa, port);

                    // Send the first UDP packet to the server
                    if (mUdp.isActive)
                    {
                        mBuffer = Buffer.Create();
                        mBuffer.BeginPacket(Packet.RequestActivateUDP).Write(playerID);
                        mBuffer.EndPacket();
                        mUdp.Send(mBuffer, mServerUdpEndPoint);
                        mBuffer.Recycle();
                        mBuffer = null;
                    }
                }
                else
                {
                    mServerUdpEndPoint = null;
                }
#endif
                break;
            }

            case Packet.ResponseJoiningChannel:
            {
                int     channelID = reader.ReadInt32();
                int     count     = reader.ReadInt16();
                Channel ch        = GetChannel(channelID, true);

                for (int i = 0; i < count; ++i)
                {
                    int    pid = reader.ReadInt32();
                    Player p   = GetPlayer(pid, true);

                    if (reader.ReadBoolean())
                    {
                        p.name     = reader.ReadString();
                        p.dataNode = reader.ReadDataNode();
                    }
                    ch.players.Add(p);
                }
                break;
            }

            case Packet.ResponseLoadLevel:
            {
                // Purposely return after loading a level, ensuring that all future callbacks happen after loading
                int    channelID = reader.ReadInt32();
                string scene     = reader.ReadString();
                if (onLoadLevel != null)
                {
                    onLoadLevel(channelID, scene);
                }
                return(false);
            }

            case Packet.ResponsePlayerJoined:
            {
                int channelID = reader.ReadInt32();

                Channel ch = GetChannel(channelID);

                if (ch != null)
                {
                    Player p = GetPlayer(reader.ReadInt32(), true);

                    if (reader.ReadBoolean())
                    {
                        p.name     = reader.ReadString();
                        p.dataNode = reader.ReadDataNode();
                    }

                    ch.players.Add(p);
                    if (onPlayerJoin != null)
                    {
                        onPlayerJoin(channelID, p);
                    }
                }
                break;
            }

            case Packet.ResponsePlayerLeft:
            {
                int channelID = reader.ReadInt32();
                int playerID  = reader.ReadInt32();

                Channel ch = GetChannel(channelID);

                if (ch != null)
                {
                    Player p = ch.GetPlayer(playerID);
                    ch.players.Remove(p);
                    RebuildPlayerDictionary();
                    if (onPlayerLeave != null)
                    {
                        onPlayerLeave(channelID, p);
                    }
                }
                break;
            }

            case Packet.ResponseSetHost:
            {
                int channelID = reader.ReadInt32();
                int hostID    = reader.ReadInt32();

                for (int i = 0; i < mChannels.size; ++i)
                {
                    Channel ch = mChannels[i];

                    if (ch.id == channelID)
                    {
                        ch.host = GetPlayer(hostID);
                        if (onHostChanged != null)
                        {
                            onHostChanged(ch);
                        }
                        break;
                    }
                }
                break;
            }

            case Packet.ResponseSetChannelData:
            {
                int     channelID = reader.ReadInt32();
                Channel ch        = GetChannel(channelID);

                if (ch != null)
                {
                    string   path = reader.ReadString();
                    DataNode node = ch.Set(path, reader.ReadObject());
                    if (onSetChannelData != null)
                    {
                        onSetChannelData(ch, path, node);
                    }
                }
                break;
            }

            case Packet.ResponseJoinChannel:
            {
                int    channelID = reader.ReadInt32();
                bool   success   = reader.ReadBoolean();
                string msg       = success ? null : reader.ReadString();

                // mJoining can contain -2 and -1 when joining random channels
                if (!mJoining.Remove(channelID))
                {
                    for (int i = 0; i < mJoining.size; ++i)
                    {
                        int id = mJoining[i];

                        if (id < 0)
                        {
                            mJoining.RemoveAt(i);
                            break;
                        }
                    }
                }
#if UNITY_EDITOR
                if (!success)
                {
                    UnityEngine.Debug.LogError("ResponseJoinChannel: " + success + ", " + msg);
                }
#endif
                if (onJoinChannel != null)
                {
                    onJoinChannel(channelID, success, msg);
                }
                break;
            }

            case Packet.ResponseLeaveChannel:
            {
                int channelID = reader.ReadInt32();

                for (int i = 0; i < mChannels.size; ++i)
                {
                    Channel ch = mChannels[i];

                    if (ch.id == channelID)
                    {
                        mChannels.RemoveAt(i);
                        break;
                    }
                }

                RebuildPlayerDictionary();
                if (onLeaveChannel != null)
                {
                    onLeaveChannel(channelID);
                }

                // Purposely exit after receiving a "left channel" notification so that other packets get handled in the next frame.
                return(false);
            }

            case Packet.ResponseRenamePlayer:
            {
                Player p       = GetPlayer(reader.ReadInt32());
                string oldName = p.name;
                if (p != null)
                {
                    p.name = reader.ReadString();
                }
                if (onRenamePlayer != null)
                {
                    onRenamePlayer(p, oldName);
                }
                break;
            }

            case Packet.ResponseCreateObject:
            {
                if (onCreate != null)
                {
                    int  playerID  = reader.ReadInt32();
                    int  channelID = reader.ReadInt32();
                    uint objID     = reader.ReadUInt32();
                    onCreate(channelID, playerID, objID, reader);
                }
                break;
            }

            case Packet.ResponseDestroyObject:
            {
                if (onDestroy != null)
                {
                    int channelID = reader.ReadInt32();
                    int count     = reader.ReadUInt16();

                    for (int i = 0; i < count; ++i)
                    {
                        uint val = reader.ReadUInt32();
                        onDestroy(channelID, val);
                    }
                }
                break;
            }

            case Packet.ResponseTransferObject:
            {
                if (onTransfer != null)
                {
                    int  from = reader.ReadInt32();
                    int  to   = reader.ReadInt32();
                    uint id0  = reader.ReadUInt32();
                    uint id1  = reader.ReadUInt32();
                    onTransfer(from, to, id0, id1);
                }
                break;
            }

            case Packet.Error:
            {
                string err = reader.ReadString();
                if (onError != null)
                {
                    onError(err);
                }
                if (mTcp.stage != TcpProtocol.Stage.Connected && onConnect != null)
                {
                    onConnect(false, err);
                }
                break;
            }

            case Packet.Disconnect:
            {
                if (onLeaveChannel != null)
                {
                    while (mChannels.size > 0)
                    {
                        int     index = mChannels.size - 1;
                        Channel ch    = mChannels[index];
                        mChannels.RemoveAt(index);
                        onLeaveChannel(ch.id);
                    }
                }

                mChannels.Clear();
                mGetChannelsCallbacks.Clear();
                mDictionary.Clear();
                mTcp.Close(false);
                mLoadFiles.Clear();
                mGetFiles.Clear();
                mJoining.Clear();
                mIsAdmin = false;

                if (mLocalServer != null)
                {
                    mLocalServer.localClient = null;
                    mLocalServer             = null;
                }

                if (onDisconnect != null)
                {
                    onDisconnect();
                }
                mConfig = new DataNode("Version", Player.version);
                break;
            }

            case Packet.ResponseGetFileList:
            {
                string   filename = reader.ReadString();
                int      size     = reader.ReadInt32();
                string[] files    = null;

                if (size > 0)
                {
                    files = new string[size];
                    for (int i = 0; i < size; ++i)
                    {
                        files[i] = reader.ReadString();
                    }
                }

                OnGetFiles cb = null;
                if (mGetFiles.TryGetValue(filename, out cb))
                {
                    mGetFiles.Remove(filename);
                }

                if (cb != null)
                {
                    try
                    {
                        cb(filename, files);
                    }
#if UNITY_EDITOR
                    catch (System.Exception ex)
                    {
                        Debug.LogError(ex.Message + ex.StackTrace);
                    }
#else
                    catch (System.Exception) {}
#endif
                }
                break;
            }

            case Packet.ResponseLoadFile:
            {
                string     filename = reader.ReadString();
                int        size     = reader.ReadInt32();
                byte[]     data     = reader.ReadBytes(size);
                OnLoadFile cb       = null;

                if (mLoadFiles.TryGetValue(filename, out cb))
                {
                    mLoadFiles.Remove(filename);
                }

                if (cb != null)
                {
                    try
                    {
                        cb(filename, data);
                    }
#if UNITY_EDITOR
                    catch (System.Exception ex)
                    {
                        Debug.LogError(ex.Message + ex.StackTrace);
                    }
#else
                    catch (System.Exception) {}
#endif
                }
                break;
            }

            case Packet.ResponseVerifyAdmin:
            {
                int    pid = reader.ReadInt32();
                Player p   = GetPlayer(pid);
                if (p == player)
                {
                    mIsAdmin = true;
                }
                if (onSetAdmin != null)
                {
                    onSetAdmin(p);
                }
                break;
            }

            case Packet.ResponseSetServerData:
            {
                string path = reader.ReadString();
                object obj  = reader.ReadObject();

                if (obj != null)
                {
                    DataNode node = mConfig.SetHierarchy(path, obj);
                    if (onSetServerData != null)
                    {
                        onSetServerData(path, node);
                    }
                }
                else
                {
                    DataNode node = mConfig.RemoveHierarchy(path);
                    if (onSetServerData != null)
                    {
                        onSetServerData(path, node);
                    }
                }
                break;
            }

            case Packet.ResponseChannelList:
            {
                if (mGetChannelsCallbacks.Count != 0)
                {
                    OnGetChannels       cb       = mGetChannelsCallbacks.Dequeue();
                    List <Channel.Info> channels = new List <Channel.Info>();
                    int count = reader.ReadInt32();

                    for (int i = 0; i < count; ++i)
                    {
                        Channel.Info info = new Channel.Info();
                        info.id           = reader.ReadInt32();
                        info.players      = reader.ReadUInt16();
                        info.limit        = reader.ReadUInt16();
                        info.hasPassword  = reader.ReadBoolean();
                        info.isPersistent = reader.ReadBoolean();
                        info.level        = reader.ReadString();
                        info.data         = reader.ReadDataNode();
                        channels.Add(info);
                    }

                    if (cb != null)
                    {
                        cb(channels);
                    }
                }
                break;
            }

            case Packet.ResponseLockChannel:
            {
                int     channelID = reader.ReadInt32();
                bool    isLocked  = reader.ReadBoolean();
                Channel ch        = GetChannel(channelID);
                if (ch != null)
                {
                    ch.isLocked = isLocked;
                }
                if (onLockChannel != null)
                {
                    onLockChannel(channelID, isLocked);
                }
                break;
            }
            }
            return(true);
        }
 protected virtual void OnSetServerData(string path, DataNode node)
 {
 }