public UnityComponent GetUnityComponent(Component component, Func <Scene, Component, UnityComponent> creator_callback) { UnityComponent result = null; if (component != null && !unityComponents.TryGetValue(component, out result)) { result = creator_callback(this, component); unityComponents[component] = result; } return(result); }
private static UnityComponent FromUnityCreator(Scene scene, Component component) { UnityComponent result = new UnityComponent(); result.type = component.GetType(); result.CreateBackend(); if (component is ISerializationCallbackReceiver) { ((ISerializationCallbackReceiver)component).OnBeforeSerialize(); } result.backend.FromUnity(scene, component, result.type); return(result); }
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); } } }
public static Node FromAssimp(Module.Import.Assimp.Context context, aiScene scene, aiNode assimp_node) { // Create new node object Node node = new Node(); // Get node ID node.id = context.id++; // Get node name node.name = Assimp.Convert.Name(assimp_node.mName, "node"); // Get node metadata using (aiMetadata meta = assimp_node.mMetaData) { UnityComponent metadata = UnityComponent.FromAssimpMetadata(meta); if (metadata != null) { node.components = new UnityComponent[] { metadata }; } } // Parse children recursively using (aiNodeArray children = assimp_node.Children) { uint children_size = children.Size(); if (children_size > 0) { node.children = new Node[children_size]; for (uint i = 0; i < children_size; i++) { aiNode child = children.Get(i); // ParseNode must dispose of the given node afterward // We must use a proxy method for saving the result into the array because the index i is captured by the lambda otherwise and it's value is indefinite across multiple threads. context.threads.ExecAndSaveToArray(node.children, (int)i, () => FromAssimp(context, scene, child)); } } } // Parse meshes associated to this node using (aiUIntArray meshes = assimp_node.Meshes) { uint meshes_size = meshes.Size(); if (meshes_size > 0) { int global_meshes_size = (int)scene.Meshes.Size(); node.meshes = new GraphicMesh[meshes_size]; for (uint j = 0; j < meshes_size; j++) { node.meshes[j] = new GraphicMesh(); if (j < global_meshes_size) { uint mesh_index = meshes.Get(j); node.meshes[j].meshIndex = (int)mesh_index; } } } } // Get the transform of this node using (aiVector3D position = new aiVector3D()) { using (aiVector3D scaling = new aiVector3D()) { using (aiQuaternion rotation = new aiQuaternion()) { assimp_node.mTransformation.Decompose(scaling, rotation, position); node.position = Assimp.Convert.AssimpToUnity.Vector3(position); node.rotation = Assimp.Convert.AssimpToUnity.Quaternion(rotation); node.scale = Assimp.Convert.AssimpToUnity.Vector3(scaling); } } } // We must dispose of the given parameter to avoid memory leaks assimp_node.Dispose(); context.progress.Update(ASSIMP_PROGRESS_FACTOR); return(node); }
public static UnityComponent FromAssimpMetadata(aiMetadata meta) { UnityComponent metadata = null; if (meta != null && meta.Keys != null) { uint size = meta.Keys.Size(); if (meta.Values != null && meta.Values.Size() == size) { if (size > 0) { Dictionary <string, object> storage = new Dictionary <string, object>(); for (uint i = 0; i < size; ++i) { using (aiString key = meta.Keys.Get(i)) { using (aiMetadataEntry entry = meta.Values.Get(i)) { object value = null; switch (entry.mType) { case aiMetadataType.AI_BOOL: value = entry.GetBool(); break; case aiMetadataType.AI_INT32: value = entry.GetInt32(); break; case aiMetadataType.AI_UINT64: value = entry.GetUInt64(); break; case aiMetadataType.AI_FLOAT: value = entry.GetFloat(); break; case aiMetadataType.AI_DOUBLE: value = entry.GetDouble(); break; case aiMetadataType.AI_AISTRING: value = entry.GetString().C_Str(); break; case aiMetadataType.AI_AIVECTOR3D: value = Assimp.Convert.AssimpToUnity.Vector3(entry.GetVector3D()); break; } storage.Add(key.C_Str(), value); } } } metadata = new UnityComponent { type = typeof(Metadata) }; metadata.CreateBackend(); AssimpMetadataSerializationContext context = new AssimpMetadataSerializationContext(metadata.type, storage); ((BackendBinarySerializable)metadata.backend).serialized = Module.Import.Binary.serializer.Serialize(context.Callback); } } else { Debug.LogError("The number of metadata keys and values does not match."); } } return(metadata); }