private string ComputeHash(Scene scene, Transform trans) { Binary.Buffer buffer = Module.Import.Binary.serializer.GetBuffer(5 * 1024); // Start with 5 Ko buffer uint written = 0; foreach (Component component in trans.GetComponents <Component>()) { if (SerializedComponent(component)) { written += Module.Import.Binary.serializer.ToBytes(ref buffer, written, UnityComponent.FromUnity(scene, component)); } } uint size = (uint)System.Text.Encoding.UTF8.GetByteCount(name); size += 2 * Binary.Size(Binary.SupportedTypes.UNITY_VECTOR3); size += Binary.Size(Binary.SupportedTypes.UNITY_QUATERNION); Module.Import.Binary.serializer.ResizeBuffer(ref buffer, written + size); written += Module.Import.Binary.serializer.ToBytes(ref buffer, written, trans.name); written += Module.Import.Binary.serializer.ToBytes(ref buffer, written, trans.localPosition); written += Module.Import.Binary.serializer.ToBytes(ref buffer, written, trans.localRotation); written += Module.Import.Binary.serializer.ToBytes(ref buffer, written, trans.localScale); return(Hash.ComputeHash(buffer.Data, 0, (int)written)); }
public static IEnumerator FromUnity(Scene scene, Transform node, Action <Node> callback, Progress progress = null, LinkedList <Transform> meshes_nodes = null) { if (scene != null && node != null && callback != null) { // Create a new node Node current = new Node(); // Handle easy stuff current.id = scene.IdMapping.GetNewId(); current.name = node.name; current.tag = node.tag; current.layer = node.gameObject.layer; current.active = node.gameObject.activeSelf; current.hideFlags = node.gameObject.hideFlags; current.position = node.localPosition; current.rotation = node.localRotation; current.scale = node.localScale; // Update mapping scene.IdMapping.Add(node.gameObject, current.id); // Handle components current.components = node.gameObject.GetComponents <Component>() .Where(SerializedComponent) .Select(c => UnityComponent.FromUnity(scene, c)) .ToArray(); // Handle meshes and materials List <GraphicMesh> graphic_meshes = new List <GraphicMesh>(); FromUnityMeshAndMaterials(scene, node, ref graphic_meshes); if (meshes_nodes != null) { foreach (Transform t in meshes_nodes) { FromUnityMeshAndMaterials(scene, t, ref graphic_meshes); } } if (graphic_meshes.Count > 0) { current.meshes = graphic_meshes.ToArray(); } // Handle children if (node.childCount > 0) { Dictionary <string, LinkedList <Transform> > children_sorted = new Dictionary <string, LinkedList <Transform> >(); // Group all children by hash, i.e. same name, transform, components and metadata foreach (Transform child in node) { LinkedList <Transform> group; string hash = current.ComputeHash(scene, child); if (!children_sorted.TryGetValue(hash, out group)) { group = new LinkedList <Transform>(); children_sorted.Add(hash, group); } group.AddLast(child); } List <Node> children_nodes = new List <Node>(children_sorted.Count); foreach (KeyValuePair <string, LinkedList <Transform> > pair in children_sorted) { // For each hash, check how many children have a descendancy int child_count = pair.Value.Count(t => t.childCount > 0); // Only one with descendancy ? The nodes must be grouped as they are only different meshes of the original unique node if (child_count <= 1) { Transform main_child = null; // No families at all ? Select the first one of the meshes to serve as the main one if (child_count <= 0 || pair.Value.First.Value.childCount > 0) { main_child = pair.Value.First.Value; pair.Value.RemoveFirst(); } else // Main child is not he first one. We need to manually search for it. { LinkedListNode <Transform> list_node = pair.Value.First; LinkedListNode <Transform> list_end = pair.Value.Last; while (list_node.Value.childCount <= 0 && list_node != list_end) { list_node = list_node.Next; } if (list_node.Value.childCount > 0) { main_child = list_node.Value; pair.Value.Remove(list_node); } } if (main_child != null) { pair.Value.Remove(main_child); IEnumerator it_progress = FromUnity(scene, main_child, children_nodes.Add, progress, pair.Value); while (it_progress.MoveNext()) { yield return(it_progress.Current); } } } else // Many families ? We don't have sufficient information to group the nodes together { foreach (Transform child in pair.Value) { IEnumerator it = FromUnity(scene, child, children_nodes.Add, progress); while (it.MoveNext()) { yield return(it.Current); } } } // Yield between each children nodes yield return(null); } if (children_nodes.Count > 0) { current.children = children_nodes.ToArray(); } } callback(current); if (progress != null) { progress.Update(1); } } }