/// <summary> /// Serialize the entire mesh into the specified DataNode. /// </summary> static public void Serialize(this Mesh mesh, DataNode node) { if (!mFullSerialization) { return; } node.AddChild("name", mesh.name); string path = UnityTools.LocateResource(mesh); if (!string.IsNullOrEmpty(path)) { node.AddChild("path", path); return; } Add(node, "vertices", mesh.vertices); Add(node, "normals", mesh.normals); Add(node, "uv1", mesh.uv); Add(node, "uv2", mesh.uv2); Add(node, "tangents", mesh.tangents); Add(node, "colors", mesh.colors32); Add(node, "weights", mesh.boneWeights); Add(node, "poses", mesh.bindposes); Add(node, "triangles", mesh.triangles); }
public virtual void Serialize(DataNode node) { node.AddChild("min", min); node.AddChild("max", max); node.AddChild("rate", rate); node.AddChild("value", value); node.AddChild("time", mTimestamp); }
/// <summary> /// Serialize the specified renderer into its DataNode format. /// </summary> static void SerializeRenderer(Renderer ren, DataNode root) { #if UNITY_4_3 || UNITY_4_5 || UNITY_4_6 || UNITY_4_7 root.AddChild("castShadows", ren.castShadows); if (ren.lightProbeAnchor != null) { root.AddChild("probeAnchor", ren.gameObject.ReferenceToString(ren.lightProbeAnchor)); } #else var sm = ren.shadowCastingMode; if (sm == UnityEngine.Rendering.ShadowCastingMode.Off) { root.AddChild("castShadows", false); } else if (sm == UnityEngine.Rendering.ShadowCastingMode.On) { root.AddChild("castShadows", true); } else { root.AddChild("shadowCasting", ren.shadowCastingMode); } root.AddChild("reflectionProbes", ren.reflectionProbeUsage); if (ren.probeAnchor != null) { root.AddChild("probeAnchor", ren.gameObject.ReferenceToString(ren.probeAnchor)); } #endif root.AddChild("receiveShadows", ren.receiveShadows); root.AddChild("useLightProbes", ren.useLightProbes); Material[] mats = ren.sharedMaterials; if (mats == null || mats.Length == 0) { return; } DataNode matNode = root.AddChild("Materials", mats.Length); for (int i = 0; i < mats.Length; ++i) { Material mat = mats[i]; if (mat != null) { DataNode node = matNode.AddChild("Material", mat.GetInstanceID()); mat.Serialize(node); } } }
static void Add(DataNode node, string name, System.Array obj) { if (obj != null && obj.Length > 0) { node.AddChild(name, obj); } }
/// <summary> /// Serialize the specified renderer into its DataNode format. /// </summary> static void Serialize(this SkinnedMeshRenderer ren, DataNode root) { Transform[] bones = ren.bones; string[] boneList = new string[bones.Length]; for (int i = 0; i < bones.Length; ++i) { boneList[i] = ren.gameObject.ReferenceToString(bones[i]); } root.AddChild("root", ren.gameObject.ReferenceToString(ren.rootBone)); root.AddChild("bones", boneList); Mesh sm = ren.sharedMesh; if (sm != null) { DataNode sub = root.AddChild("Mesh", sm.GetInstanceID()); if (mFullSerialization) { sm.Serialize(sub); } } root.AddChild("quality", ren.quality); root.AddChild("offscreen", ren.updateWhenOffscreen); root.AddChild("center", ren.localBounds.center); root.AddChild("size", ren.localBounds.size); SerializeRenderer(ren, root); }
/// <summary> /// Serialize the Mesh Filter component. /// </summary> static public void Serialize(this MeshFilter filter, DataNode data) { Mesh sm = filter.sharedMesh; if (sm != null) { DataNode child = data.AddChild("Mesh", sm.GetInstanceID()); sm.Serialize(child); } }
/// <summary> /// Rigidbody class has a lot of properties that don't need to be serialized. /// </summary> static public void Serialize(this Rigidbody rb, DataNode node) { node.AddChild("mass", rb.mass); node.AddChild("drag", rb.drag); node.AddChild("angularDrag", rb.angularDrag); node.AddChild("interpolation", rb.interpolation); node.AddChild("collisionDetectionMode", rb.collisionDetectionMode); node.AddChild("isKinematic", rb.isKinematic); node.AddChild("useGravity", rb.useGravity); }
/// <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("\\", "/"); string[] 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) { if (obj == null) { break; } parent = node; node = node.AddChild(names[index]); ++index; } } if (obj == null) { if (parent != null) { parent.RemoveChild(names[index - 1]); } return(parent); } } } if (obj is DataNode) { DataNode other = (obj as DataNode); node.value = other.value; node.children.Clear(); for (int i = 0; i < other.children.size; ++i) { node.children.Add(other.children[i].Clone()); } } else { node.value = obj; } return(node); }
/// <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())); } }
/// <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 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> /// 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> /// Camera serialization skips a bunch of values such as "layerCullDistances", "stereoSeparation", and more. /// </summary> static public void Serialize(this Camera cam, DataNode node) { node.AddChild("clearFlags", cam.clearFlags); node.AddChild("backgroundColor", cam.backgroundColor); node.AddChild("cullingMask", cam.cullingMask); node.AddChild("orthographic", cam.orthographic); node.AddChild("orthographicSize", cam.orthographicSize); node.AddChild("fieldOfView", cam.fieldOfView); node.AddChild("nearClipPlane", cam.nearClipPlane); node.AddChild("farClipPlane", cam.farClipPlane); node.AddChild("rect", cam.rect); node.AddChild("depth", cam.depth); node.AddChild("renderingPath", cam.renderingPath); node.AddChild("useOcclusionCulling", cam.useOcclusionCulling); node.AddChild("hdr", cam.hdr); }
/// <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); }