public static void RecursivelyTraverseTransform(Transform tra, StringBuilder exportStr, ResourceRecorder resourceRecorder, int indentLevel, SceneStatistics statistics, SceneWarningRecorder warningRecorder) { if (!tra.gameObject.activeInHierarchy) { return; } if (tra.gameObject.GetComponent <DclSceneMeta>()) { return; //skip .dcl } var dclObject = tra.GetComponent <DclObject>() ?? tra.gameObject.AddComponent <DclObject>(); dclObject.dclNodeType = EDclNodeType.entity; var entityName = GetIdentityName(tra.gameObject); if (statistics != null) { statistics.entityCount += 1; } var position = tra.localPosition; var scale = tra.localScale; var rotation = tra.localRotation; if (exportStr != null) { exportStr.AppendFormat(NewEntityWithName, entityName, tra.name); if (tra.parent) { //Set Parent exportStr.AppendFormat(SetParent, entityName, GetIdentityName(tra.parent.gameObject)); } else { //Entity exportStr.AppendFormat(AddEntity, entityName); } //Transform exportStr.AppendFormat(SetTransform, entityName, position.x, position.y, position.z); exportStr.AppendFormat(SetRotation, entityName, rotation.x, rotation.y, rotation.z, rotation.w); exportStr.AppendFormat(SetScale, entityName, scale.x, scale.y, scale.z); } ProcessShape(tra, entityName, exportStr, resourceRecorder, statistics); if (exportStr != null && dclObject.dclNodeType == EDclNodeType.gltf) //reverse 180° along local y-axis because of DCL's special purpose. { rotation = Quaternion.AngleAxis(180, tra.up) * rotation; exportStr.AppendFormat(SetRotation, entityName, rotation.x, rotation.y, rotation.z, rotation.w); } if (dclObject.dclNodeType != EDclNodeType.gltf) { ProcessText(tra, entityName, exportStr, statistics); } if (dclObject.dclNodeType != EDclNodeType.gltf) { ProcessMaterial(tra, false, entityName, resourceRecorder.primitiveMaterialsToExport, exportStr, statistics); if (tra.GetComponent <MeshRenderer>()) { var meshFilter = tra.GetComponent <MeshFilter>(); var meshRenderer = tra.GetComponent <MeshRenderer>(); //Statistics if (statistics != null) { if (meshFilter && meshFilter.sharedMesh) { statistics.triangleCount += meshFilter.sharedMesh.triangles.LongLength / 3; statistics.bodyCount += 1; } var curHeight = meshRenderer.bounds.max.y; if (curHeight > statistics.maxHeight) { statistics.maxHeight = curHeight; } } //Warnings if (warningRecorder != null) { //OutOfLand if (_sceneMeta) { var isOutOfLand = false; var startParcel = SceneUtil.GetParcelCoordinates(meshRenderer.bounds.min); var endParcel = SceneUtil.GetParcelCoordinates(meshRenderer.bounds.max); for (int x = startParcel.x; x <= endParcel.x; x++) { for (int y = startParcel.y; y <= endParcel.y; y++) { if (!_sceneMeta.parcels.Exists(parcel => parcel == new ParcelCoordinates(x, y))) { warningRecorder.OutOfLandWarnings.Add(new SceneWarningRecorder.OutOfLand(meshRenderer)); isOutOfLand = true; break; } } if (isOutOfLand) { break; } } } } } if (exportStr != null) { exportStr.Append('\n'); } // if (tra.GetComponent<DclCustomNode>()) // { // var customNode = tra.GetComponent<DclCustomNode>(); // nodeName = customNode.nodeName; // nodeType = EDclNodeType.CustomNode; //if(customNode.propertyPairs!=null){ // foreach (var propertyPair in customNode.propertyPairs) // { // extraProperties.AppendFormat(" {0}={1}", propertyPair.name, propertyPair.value); // } //} // } // else // { if (dclObject) { //TODO: if (dclObject.visible != true) extraProperties.Append(" visible={false}"); } //GameObjectToNodeTypeDict.Add(tra.gameObject, nodeType); foreach (Transform child in tra) { RecursivelyTraverseTransform(child, exportStr, resourceRecorder, indentLevel + 1, statistics, warningRecorder); } } else { if (statistics != null) { statistics.gltfMaterials.Clear(); } RecursivelyTraverseIntoGLTF(tra, 0, statistics, warningRecorder); if (statistics != null) { statistics.materialCount += statistics.gltfMaterials.Count; } } ProcessAudio(tra, entityName, exportStr); }
public static void RecursivelyTraverseIntoGLTF(Transform tra, int layerUnderGLTFRoot, SceneStatistics statistics, SceneWarningRecorder warningRecorder) { if (!tra.gameObject.activeInHierarchy) { return; } if (tra.gameObject.GetComponent <DclSceneMeta>()) { return; //skip .dcl } var dclObject = tra.GetComponent <DclObject>() ?? tra.gameObject.AddComponent <DclObject>(); if (layerUnderGLTFRoot > 0) { dclObject.dclNodeType = EDclNodeType.ChildOfGLTF; } var position = tra.localPosition; var scale = tra.localScale; var rotation = tra.localRotation; if (tra.GetComponent <MeshRenderer>()) { var meshFilter = tra.GetComponent <MeshFilter>(); var meshRenderer = tra.GetComponent <MeshRenderer>(); //Statistics if (statistics != null) { if (meshFilter && meshFilter.sharedMesh) { statistics.triangleCount += meshFilter.sharedMesh.triangles.LongLength / 3; statistics.bodyCount += 1; } var curHeight = meshRenderer.bounds.max.y; if (curHeight > statistics.maxHeight) { statistics.maxHeight = curHeight; } } //Warnings if (warningRecorder != null) { //OutOfLand if (_sceneMeta) { var isOutOfLand = false; var startParcel = SceneUtil.GetParcelCoordinates(meshRenderer.bounds.min); var endParcel = SceneUtil.GetParcelCoordinates(meshRenderer.bounds.max); for (int x = startParcel.x; x <= endParcel.x; x++) { for (int y = startParcel.y; y <= endParcel.y; y++) { if (!_sceneMeta.parcels.Exists(parcel => parcel == new ParcelCoordinates(x, y))) { warningRecorder.OutOfLandWarnings.Add(new SceneWarningRecorder.OutOfLand(meshRenderer)); isOutOfLand = true; break; } } if (isOutOfLand) { break; } } } } } ProcessMaterial(tra, true, null, statistics.gltfMaterials, null, statistics); foreach (Transform child in tra) { RecursivelyTraverseIntoGLTF(child, layerUnderGLTFRoot + 1, statistics, warningRecorder); } }
public static void RecursivelyTraverseTransform(Transform tra, StringBuilder xmlBuilder, List <GameObject> meshesToExport, int indentLevel, SceneStatistics statistics, SceneWarningRecorder warningRecorder, Dictionary <GameObject, EDclNodeType> gameObjectToNodeTypeDict) { if (!tra.gameObject.activeInHierarchy) { return; } //TODO: Hide empty if (statistics != null) { statistics.entityCount += 1; } string nodeName = null; var nodeType = EDclNodeType._none; var position = tra.localPosition; var scale = tra.localScale; var eulerAngles = tra.localEulerAngles; string pColor = null; //<... color="#4A4A4A" ...> string pMaterial = null; //<... material="#mat01" ...> var extraProperties = new StringBuilder(); //TODO: can be omitted if xmlBuilder == null var dclObject = tra.GetComponent <DclObject>(); if (tra.GetComponent <DclCustomNode>()) { var customNode = tra.GetComponent <DclCustomNode>(); nodeName = customNode.nodeName; nodeType = EDclNodeType.CustomNode; if (customNode.position) { extraProperties.AppendFormat(" position={{{0}}}", Vector3ToJSONString(tra.localPosition)); } if (customNode.rotation) { extraProperties.AppendFormat(" rotation={{{0}}}", Vector3ToJSONString(tra.eulerAngles)); } if (customNode.scale) { extraProperties.AppendFormat(" scale={{{0}}}", Vector3ToJSONString(tra.localScale)); } if (customNode.propertyPairs != null) { foreach (var propertyPair in customNode.propertyPairs) { extraProperties.AppendFormat(" {0}={1}", propertyPair.name, propertyPair.value); } } } else { if (tra.GetComponent <MeshFilter>() && tra.GetComponent <MeshRenderer>()) //Primitives & glTF { if (dclObject) { switch (dclObject.dclPrimitiveType) { case DclPrimitiveType.box: nodeName = "box"; nodeType = EDclNodeType.box; break; case DclPrimitiveType.sphere: nodeName = "sphere"; nodeType = EDclNodeType.sphere; break; case DclPrimitiveType.plane: nodeName = "plane"; nodeType = EDclNodeType.plane; break; case DclPrimitiveType.cylinder: nodeName = "cylinder"; nodeType = EDclNodeType.cylinder; break; case DclPrimitiveType.cone: nodeName = "cone"; nodeType = EDclNodeType.cone; break; } } var meshFilter = tra.GetComponent <MeshFilter>(); if (nodeName != null) { //Primitive //read color/mat var rdrr = tra.GetComponent <MeshRenderer>(); if (rdrr && rdrr.sharedMaterial) { var material = rdrr.sharedMaterial; if (material == PrimitiveHelper.GetDefaultMaterial()) { //not use material // var matColor = rdrr.sharedMaterial.color; // pColor = ToHexString(matColor); } else { //need to export this material if (primitiveMaterialsToExport != null && !primitiveMaterialsToExport.Exists(m => m == material)) { primitiveMaterialsToExport.Add(material); } pMaterial = string.Format("#{0}", material.name); } } //withCollisions if (dclObject) { if (dclObject.dclPrimitiveType != DclPrimitiveType.other) { if (dclObject.withCollision == true) { extraProperties.Append(" withCollisions={true}"); } } } //Statistics if (statistics != null) { switch (dclObject.dclPrimitiveType) { case DclPrimitiveType.box: statistics.triangleCount += 12; break; case DclPrimitiveType.sphere: statistics.triangleCount += 4624; break; case DclPrimitiveType.plane: statistics.triangleCount += 4; break; case DclPrimitiveType.cylinder: statistics.triangleCount += 144; break; case DclPrimitiveType.cone: statistics.triangleCount += 108; break; } statistics.bodyCount += 1; } } else { //GLTF //export as a glTF model if (meshesToExport != null) { meshesToExport.Add(tra.gameObject); } nodeName = "gltf-model"; nodeType = EDclNodeType.gltf; // TODO: delete postion info (by alking) // position = Vector3.zero; // eulerAngles = Vector3.zero; // scale = Vector3.zero; //if tra is a prefab and do not get any change. use the prefab's name //extraProperties.AppendFormat(" src=\"./unity_assets/{0}.gltf\"", tra.name); extraProperties.AppendFormat(" src=\"./unity_assets/{0}.gltf\"", CalcName(tra.gameObject)); //Statistics if (statistics != null) { statistics.triangleCount += meshFilter.sharedMesh.triangles.LongLength / 3; statistics.bodyCount += 1; } if (statistics != null) { Mesh m = meshFilter.sharedMesh; Renderer mr = tra.GetComponent <MeshRenderer> (); if (mr == null) { mr = tra.GetComponent <SkinnedMeshRenderer> (); } var sm = mr.sharedMaterials; for (int i = 0; i < sm.Length; ++i) { Material ma = sm [i]; if (ma != null) { statistics.materialCount += 1; Shader shader = ma.shader; for (int j = 0; j < ShaderUtil.GetPropertyCount(shader); j++) { if (ShaderUtil.GetPropertyType(shader, j) == ShaderUtil.ShaderPropertyType.TexEnv) { Texture texture = ma.GetTexture(ShaderUtil.GetPropertyName(shader, j)); if (texture != null) { statistics.textureCount += 1; } } } } } } } } else if (tra.GetComponent <TextMesh>() && tra.GetComponent <MeshRenderer>()) //TextMesh { nodeName = "text"; nodeType = EDclNodeType.text; var tm = tra.GetComponent <TextMesh>(); extraProperties.AppendFormat(" value=\"{0}\"", tm.text); //scale *= tm.fontSize * 0.5f; //extraProperties.AppendFormat(" fontS=\"{0}\"", 100); pColor = ToHexString(tm.color); var rdrr = tra.GetComponent <MeshRenderer>(); if (rdrr) { var width = rdrr.bounds.size.x * 2 / tra.lossyScale.x; //rdrr.bounds.extents.x*2; var height = rdrr.bounds.size.y * 2 / tra.lossyScale.y; //rdrr.bounds.extents.y * 2; extraProperties.AppendFormat(" width={{{0}}}", width); extraProperties.AppendFormat(" height={{{0}}}", height); } extraProperties.AppendFormat(" fontSize={{{0}}}", tm.fontSize == 0 ? 13f * 38f : tm.fontSize * 38f); switch (tm.anchor) { case TextAnchor.UpperLeft: extraProperties.AppendFormat(" hAlign=\"right\""); extraProperties.AppendFormat(" vAlign=\"bottom\""); break; case TextAnchor.UpperCenter: extraProperties.AppendFormat(" vAlign=\"bottom\""); break; case TextAnchor.UpperRight: extraProperties.AppendFormat(" hAlign=\"left\""); extraProperties.AppendFormat(" vAlign=\"bottom\""); break; case TextAnchor.MiddleLeft: extraProperties.AppendFormat(" hAlign=\"right\""); break; case TextAnchor.MiddleCenter: break; case TextAnchor.MiddleRight: extraProperties.AppendFormat(" hAlign=\"left\""); break; case TextAnchor.LowerLeft: extraProperties.AppendFormat(" hAlign=\"right\""); extraProperties.AppendFormat(" vAlign=\"top\""); break; case TextAnchor.LowerCenter: extraProperties.AppendFormat(" vAlign=\"top\""); break; case TextAnchor.LowerRight: extraProperties.AppendFormat(" hAlign=\"left\""); extraProperties.AppendFormat(" vAlign=\"top\""); break; } } if (tra.GetComponent <MeshRenderer>()) { var meshRenderer = tra.GetComponent <MeshRenderer>(); //Statistics if (statistics != null) { var curHeight = meshRenderer.bounds.max.y; if (curHeight > statistics.maxHeight) { statistics.maxHeight = curHeight; } } //Warnings if (warningRecorder != null) { //OutOfLand if (_sceneMeta) { var isOutOfLand = false; var startParcel = SceneUtil.GetParcelCoordinates(meshRenderer.bounds.min); var endParcel = SceneUtil.GetParcelCoordinates(meshRenderer.bounds.max); for (int x = startParcel.x; x <= endParcel.x; x++) { for (int y = startParcel.y; y <= endParcel.y; y++) { if (!_sceneMeta.parcels.Exists(parcel => parcel == new ParcelCoordinates(x, y))) { warningRecorder.OutOfLandWarnings.Add( new SceneWarningRecorder.OutOfLand(meshRenderer)); isOutOfLand = true; break; } } if (isOutOfLand) { break; } } } } } if (nodeName == null) { nodeName = "entity"; nodeType = EDclNodeType.entity; } if (pColor != null) { extraProperties.AppendFormat(" color=\"{0}\"", pColor); } if (pMaterial != null) { extraProperties.AppendFormat(" material=\"{0}\"", pMaterial); } if (dclObject) { if (dclObject.visible != true) { extraProperties.Append(" visible={false}"); } } } StringBuilder xmlNode = null; StringBuilder xmlNodeTail = null; StringBuilder childrenXmlBuilder = null; if (xmlBuilder != null) { xmlNode = new StringBuilder(); xmlNode.AppendIndent(indentUnit, indentLevel); if (nodeType == EDclNodeType.CustomNode) { xmlNode.AppendFormat("<{0}{1}>", nodeName, extraProperties); } else { xmlNode.AppendFormat("<{0} position={{{1}}} scale={{{2}}} rotation={{{3}}}{4}>", nodeName, Vector3ToJSONString(position), Vector3ToJSONString(scale), Vector3ToJSONString(eulerAngles), extraProperties); } xmlNodeTail = new StringBuilder().AppendFormat("</{0}>\n", nodeName); childrenXmlBuilder = new StringBuilder(); } if (gameObjectToNodeTypeDict != null) { gameObjectToNodeTypeDict.Add(tra.gameObject, nodeType); } if (nodeType != EDclNodeType.gltf) //gltf node will force to pack all its children, so should not traverse into it again. { foreach (Transform child in tra) { RecursivelyTraverseTransform(child, childrenXmlBuilder, meshesToExport, indentLevel + 1, statistics, warningRecorder, gameObjectToNodeTypeDict); } } if (xmlBuilder != null) { if (childrenXmlBuilder.Length > 0) { xmlNode.Append("\n"); xmlNode.Append(childrenXmlBuilder); xmlNode.AppendIndent(indentUnit, indentLevel); } xmlNode.Append(xmlNodeTail); xmlBuilder.Append(xmlNode); } }