package alternativa.utils { import alternativa.engine3d.*; import alternativa.engine3d.core.Face; import alternativa.engine3d.core.Mesh; import alternativa.engine3d.core.Surface; import alternativa.engine3d.core.Vertex; import alternativa.engine3d.materials.FillMaterial; import alternativa.engine3d.materials.SurfaceMaterial; import alternativa.engine3d.materials.TextureMaterial; import alternativa.engine3d.materials.TextureMaterialPrecision; import alternativa.engine3d.materials.WireMaterial; import alternativa.types.*; import flash.display.BlendMode; import flash.geom.Point; use namespace alternativa3d; use namespace alternativatypes; /** * Утилиты для работы с Mesh-объектами. */ public class MeshUtils { static private var verticesSort:Array = ["x", "y", "z"]; static private var verticesSortOptions:Array = [Array.NUMERIC, Array.NUMERIC, Array.NUMERIC]; /** * Объединение нескольких Mesh-объектов. Объекты, переданные как аргументы метода, не изменяются. * * @param meshes объединяемые объекты класса alternativa.engine3d.core.Mesh * * @return новый Mesh-объект, содержащий результат объединения переданных Mesh-объектов */ static public function uniteMeshes(... meshes):Mesh { var res:Mesh = new Mesh(); var length:uint = meshes.length; var key:*; var vertex:Vertex; var face:Face; var j:uint; for (var i:uint = 0; i < length; i++) { var mesh:Mesh = meshes[i]; var vertices:Map = mesh._vertices.clone(); for (key in vertices) { vertex = vertices[key]; vertices[key] = res.createVertex(vertex.x, vertex.y, vertex.z); } var faces:Map = mesh._faces.clone(); for (key in faces) { face = faces[key]; var faceVertices:Array = new Array().concat(face._vertices); for (j = 0; j < face._verticesCount; j++) { vertex = faceVertices[j]; faceVertices[j] = vertices[vertex.id]; } faces[key] = res.createFace(faceVertices); res.setUVsToFace(face._aUV, face._bUV, face._cUV, faces[key]); } for (key in mesh._surfaces) { var surface:Surface = mesh._surfaces[key]; var surfaceFaces:Array = surface._faces.toArray(); var numFaces:uint = surfaceFaces.length; for (j = 0; j < numFaces; j++) { face = surfaceFaces[j]; surfaceFaces[j] = faces[face.id]; } var newSurface:Surface = res.createSurface(surfaceFaces); newSurface.material = SurfaceMaterial(surface.material.clone()); } } return res; } /** * Слияние вершин Mesh-объекта с одинаковыми координатами. Равенство координат проверяется с учётом погрешности. * * @param mesh объект, вершины которого объединяются * @param threshold погрешность измерения расстояний */ static public function autoWeldVertices(mesh:Mesh, threshold:Number = 0):void { // Получаем список вершин меша и сортируем по координатам var vertices:Array = mesh._vertices.toArray(true); vertices.sortOn(verticesSort, verticesSortOptions); // Поиск вершин с одинаковыми координатами var weld:Map = new Map(true); var vertex:Vertex; var currentVertex:Vertex = vertices[0]; var length:uint = vertices.length; var i:uint; for (i = 1; i < length; i++) { vertex = vertices[i]; if ((currentVertex.x - vertex.x <= threshold) && (currentVertex.x - vertex.x >= -threshold) && (currentVertex.y - vertex.y <= threshold) && (currentVertex.y - vertex.y >= -threshold) && (currentVertex.z - vertex.z <= threshold) && (currentVertex.z - vertex.z >= -threshold)) { weld[vertex] = currentVertex; } else { currentVertex = vertex; } } // Собираем грани объединяемых вершин var faces:Set = new Set(true); var keyVertex:*; var keyFace:*; for (keyVertex in weld) { vertex = keyVertex; for (keyFace in vertex._faces) { faces[keyFace] = true; } } // Заменяем грани for (keyFace in faces) { var face:Face = keyFace; var id:Object = mesh.getFaceId(face); var surface:Surface = face._surface; var aUV:Point = face._aUV; var bUV:Point = face._bUV; var cUV:Point = face._cUV; vertices = new Array().concat(face._vertices); length = vertices.length; for (i = 0; i < length; i++) { vertex = weld[vertices[i]]; if (vertex != null) { vertices[i] = vertex; } } mesh.removeFace(face); face = mesh.createFace(vertices, id); if (surface != null) { surface.addFace(face); } face.aUV = aUV; face.bUV = bUV; face.cUV = cUV; } // Удаляем вершины for (keyVertex in weld) { mesh.removeVertex(keyVertex); } } /** * Объединение соседних граней, образующих плоский выпуклый многоугольник. * * @param mesh объект, грани которого объединяются * @param angleThreshold погрешность измерения углов * @param uvThreshold погрешность измерения UV-координат */ static public function autoWeldFaces(mesh:Mesh, angleThreshold:Number = 0, uvThreshold:Number = 0):void { angleThreshold = Math.cos(angleThreshold); var face:Face; var sibling:Face; var key:*; var i:uint; // Формируем списки граней var faces1:Set = new Set(true); var faces2:Set = new Set(true); // Формируем список нормалей var normals:Map = new Map(true); for each (face in mesh._faces.clone()) { var faceNormal:Point3D = face.normal; if (faceNormal.x != 0 || faceNormal.y != 0 || faceNormal.z != 0) { faces1[face] = true; normals[face] = faceNormal; } else { mesh.removeFace(face); } } // Объединение do { // Флаг объединения var weld:Boolean = false; // Объединяем грани while ((face = faces1.take()) != null) { //var num:uint = face.num; //var vertices:Array = face.vertices; var currentWeld:Boolean = false; // Проверка общих граней по точкам // Проверка общих граней по рёбрам // Перебираем точки грани for (i = 0; (i < face._verticesCount) && !currentWeld; i++) { var faceIndex1:uint = i; var faceIndex2:uint; var siblingIndex1:int; var siblingIndex2:uint; // Перебираем грани текущей точки var vertex:Vertex = face._vertices[faceIndex1]; var vertexFaces:Set = vertex.faces; for (key in vertexFaces) { sibling = key; // Если грань в списке на объединение и в одной поверхности if (faces1[sibling] && face._surface == sibling._surface) { faceIndex2 = (faceIndex1 < face._verticesCount - 1) ? (faceIndex1 + 1) : 0; siblingIndex1 = sibling._vertices.indexOf(face._vertices[faceIndex2]); // Если общее ребро if (siblingIndex1 >= 0) { // Если грани сонаправлены var normal:Point3D = normals[face]; if (Point3D.dot(normal, normals[sibling]) >= angleThreshold) { // Если в точках объединения нет перегибов siblingIndex2 = (siblingIndex1 < sibling._verticesCount - 1) ? (siblingIndex1 + 1) : 0; // Расширяем грани объединения var i1:uint; var i2:uint; while (true) { i1 = (faceIndex1 > 0) ? (faceIndex1 - 1) : (face._verticesCount - 1); i2 = (siblingIndex2 < sibling._verticesCount - 1) ? (siblingIndex2 + 1) : 0; if (face._vertices[i1] == sibling._vertices[i2]) { faceIndex1 = i1; siblingIndex2 = i2; } else { break; } } while (true) { i1 = (faceIndex2 < face._verticesCount - 1) ? (faceIndex2 + 1) : 0; i2 = (siblingIndex1 > 0) ? (siblingIndex1 - 1) : (sibling._verticesCount - 1); if (face._vertices[i1] == sibling._vertices[i2]) { faceIndex2 = i1; siblingIndex1 = i2; } else { break; } } vertex = face._vertices[faceIndex1]; var a:Point3D = vertex.coords; vertex = face._vertices[faceIndex2]; var b:Point3D = vertex.coords; // Считаем первый перегиб vertex = sibling._vertices[(siblingIndex2 < sibling._verticesCount - 1) ? (siblingIndex2 + 1) : 0]; var c:Point3D = vertex.coords; vertex = face._vertices[(faceIndex1 > 0) ? (faceIndex1 - 1) : (face._verticesCount - 1)]; var d:Point3D = vertex.coords; var cx:Number = c.x - a.x; var cy:Number = c.y - a.y; var cz:Number = c.z - a.z; var dx:Number = d.x - a.x; var dy:Number = d.y - a.y; var dz:Number = d.z - a.z; var crossX:Number = cy*dz - cz*dy; var crossY:Number = cz*dx - cx*dz; var crossZ:Number = cx*dy - cy*dx; if (crossX == 0 && crossY == 0 && crossZ == 0) { if (cx*dx + cy*dy + cz*dz > 0) { break; } } var dot:Number = crossX*normal.x + crossY*normal.y + crossZ*normal.z; // Если в первой точке перегиба нет if (dot >= 0) { // Считаем второй перегиб vertex = face._vertices[(faceIndex2 < face._verticesCount - 1) ? (faceIndex2 + 1) : 0]; c = vertex.coords; vertex = sibling._vertices[(siblingIndex1 > 0) ? (siblingIndex1 - 1) : (sibling._verticesCount - 1)]; d = vertex.coords; cx = c.x - b.x; cy = c.y - b.y; cz = c.z - b.z; dx = d.x - b.x; dy = d.y - b.y; dz = d.z - b.z; crossX = cy*dz - cz*dy; crossY = cz*dx - cx*dz; crossZ = cx*dy - cy*dx; if (crossX == 0 && crossY == 0 && crossZ == 0) { if (cx*dx + cy*dy + cz*dz > 0) { break; } } dot = crossX*normal.x + crossY*normal.y + crossZ*normal.z; // Если во второй точке перегиба нет if (dot >= 0) { // Флаг наличия UV у обеих граней var hasUV:Boolean = (face._aUV != null && face._bUV != null && face._cUV != null && sibling._aUV != null && sibling._bUV != null && sibling._cUV != null); if (hasUV || (face._aUV == null && face._bUV == null && face._cUV == null && sibling._aUV == null && sibling._bUV == null && sibling._cUV == null)) { // Если грани имеют UV, проверяем совместимость if (hasUV) { vertex = sibling._vertices[0]; var uv:Point = face.getUVFast(vertex.coords, normal); if ((uv.x - sibling._aUV.x > uvThreshold) || (uv.x - sibling._aUV.x < -uvThreshold) || (uv.y - sibling._aUV.y > uvThreshold) || (uv.y - sibling._aUV.y < -uvThreshold)) { break; } vertex = sibling._vertices[1]; uv = face.getUVFast(vertex.coords, normal); if ((uv.x - sibling._bUV.x > uvThreshold) || (uv.x - sibling._bUV.x < -uvThreshold) || (uv.y - sibling._bUV.y > uvThreshold) || (uv.y - sibling._bUV.y < -uvThreshold)) { break; } vertex = sibling._vertices[2]; uv = face.getUVFast(vertex.coords, normal); if ((uv.x - sibling._cUV.x > uvThreshold) || (uv.x - sibling._cUV.x < -uvThreshold) || (uv.y - sibling._cUV.y > uvThreshold) || (uv.y - sibling._cUV.y < -uvThreshold)) { break; } } // Формируем новую грань var newVertices:Array = new Array(); var n:uint = faceIndex2; do { newVertices.push(face._vertices[n]); n = (n < face._verticesCount - 1) ? (n + 1) : 0; } while (n != faceIndex1); n = siblingIndex2; do { newVertices.push(sibling._vertices[n]); n = (n < sibling._verticesCount - 1) ? (n + 1) : 0; } while (n != siblingIndex1); // Выбираем начальную точку n = getBestBeginVertexIndex(newVertices); for (var m:uint = 0; m < n; m++) { newVertices.push(newVertices.shift()); } // Заменяем грани новой var surface:Surface = face._surface; var newFace:Face = mesh.createFace(newVertices); if (hasUV) { newFace.aUV = face.getUVFast(newVertices[0].coords, normal); newFace.bUV = face.getUVFast(newVertices[1].coords, normal); newFace.cUV = face.getUVFast(newVertices[2].coords, normal); } if (surface != null) { surface.addFace(newFace); } mesh.removeFace(face); mesh.removeFace(sibling); // Обновляем список нормалей delete normals[sibling]; delete normals[face]; normals[newFace] = newFace.normal; // Обновляем списки расчётов delete faces1[sibling]; faces2[newFace] = true; // Помечаем объединение weld = true; currentWeld = true; break; } } } } } } } } // Если не удалось объединить, переносим грань faces2[face] = true; } // Меняем списки var fs:Set = faces1; faces1 = faces2; faces2 = fs; } while (weld); removeIsolatedVertices(mesh); removeUselessVertices(mesh); } /** * Удаление вершин объекта, не принадлежащим ни одной грани. * * @param mesh объект, вершины которого удаляются */ static public function removeIsolatedVertices(mesh:Mesh):void { for each (var vertex:Vertex in mesh._vertices.clone()) { if (vertex._faces.isEmpty()) { mesh.removeVertex(vertex); } } } /** * Удаление вершин объекта, которые во всех своих гранях лежат на отрезке между предыдущей и следующей вершиной. * * @param mesh объект, вершины которого удаляются */ static public function removeUselessVertices(mesh:Mesh):void { var v:Vertex; var key:*; var face:Face; var index:uint; var length:uint; for each (var vertex:Vertex in mesh._vertices.clone()) { var unless:Boolean = true; var indexes:Map = new Map(true); for (key in vertex._faces) { face = key; length = face._vertices.length; index = face._vertices.indexOf(vertex); v = face._vertices[index]; var a:Point3D = v.coords; v = face._vertices[(index < length - 1) ? (index + 1) : 0]; var b:Point3D = v.coords; v = face._vertices[(index > 0) ? (index - 1) : (length - 1)]; var c:Point3D = v.coords; var abx:Number = b.x - a.x; var aby:Number = b.y - a.y; var abz:Number = b.z - a.z; var acx:Number = c.x - a.x; var acy:Number = c.y - a.y; var acz:Number = c.z - a.z; if (aby*acz - abz*acy == 0 && abz*acx - abx*acz == 0 && abx*acy - aby*acx == 0) { indexes[face] = index; } else { unless = false; break; } } if (unless && !indexes.isEmpty()) { // Удаляем for (key in indexes) { var i:uint; face = key; index = indexes[face]; length = face._vertices.length; var newVertices:Array = new Array(); for (i = 0; i < length; i++) { if (i != index) { newVertices.push(face._vertices[i]); } } var n:uint = getBestBeginVertexIndex(newVertices); for (i = 0; i < n; i++) { newVertices.push(newVertices.shift()); } var surface:Surface = face._surface; var newFace:Face = mesh.createFace(newVertices); if (face._aUV != null && face._bUV != null && face._cUV != null) { var normal:Point3D = face.normal; newFace.aUV = face.getUVFast(newVertices[0].coords, normal); newFace.bUV = face.getUVFast(newVertices[1].coords, normal); newFace.cUV = face.getUVFast(newVertices[2].coords, normal); } if (surface != null) { surface.addFace(newFace); } mesh.removeFace(face); } mesh.removeVertex(vertex); } } } /** * Удаление вырожденных граней. * * @param mesh объект, грани которого удаляются */ static public function removeSingularFaces(mesh:Mesh):void { for each (var face:Face in mesh._faces.clone()) { var normal:Point3D = face.normal; if (normal.x == 0 && normal.y == 0 && normal.z == 0) { mesh.removeFace(face); } } } /** * @private * Находит наиболее подходящую первую точку. * @param vertices * @return */ static public function getBestBeginVertexIndex(vertices:Array):uint { var bestIndex:uint = 0; var num:uint = vertices.length; if (num > 3) { var maxCrossLength:Number = 0; var v:Vertex = vertices[num - 1]; var c1:Point3D = v.coords; v = vertices[0]; var c2:Point3D = v.coords; var prevX:Number = c2.x - c1.x; var prevY:Number = c2.y - c1.y; var prevZ:Number = c2.z - c1.z; for (var i:uint = 0; i < num; i++) { c1 = c2; v = vertices[(i < num - 1) ? (i + 1) : 0]; c2 = v.coords; var nextX:Number = c2.x - c1.x; var nextY:Number = c2.y - c1.y; var nextZ:Number = c2.z - c1.z; var crossX:Number = prevY*nextZ - prevZ*nextY; var crossY:Number = prevZ*nextX - prevX*nextZ; var crossZ:Number = prevX*nextY - prevY*nextX; var crossLength:Number = crossX*crossX + crossY*crossY + crossZ*crossZ; if (crossLength > maxCrossLength) { maxCrossLength = crossLength; bestIndex = i; } prevX = nextX; prevY = nextY; prevZ = nextZ; } // Берём предыдущий bestIndex = (bestIndex > 0) ? (bestIndex - 1) : (num - 1); } return bestIndex; } /** * Генерация AS-класса. * * @param mesh объект, на базе которого генерируется класс * @param packageName имя пакета для генерируемого класса * @return AS-класс в текстовом виде */ static public function generateClass(mesh:Mesh, packageName:String = ""):String { var className:String = mesh._name.charAt(0).toUpperCase() + mesh._name.substr(1); var header:String = "package" + ((packageName != "") ? (" " + packageName + " ") : " ") + "{\r\r"; var importSet:Object = new Object(); importSet["alternativa.engine3d.core.Mesh"] = true; var materialSet:Map = new Map(true); var materialName:String; var materialNum:uint = 1; var footer:String = "\t\t}\r\t}\r}"; var classHeader:String = "\tpublic class "+ className + " extends Mesh {\r\r"; var constructor:String = "\t\tpublic function " + className + "() {\r"; constructor += "\t\t\tsuper(\"" + mesh._name +"\");\r\r"; var newLine:Boolean = false; if (mesh.mobility != 0) { constructor += "\t\t\tmobility = " + mesh.mobility +";\r"; newLine = true; } if (mesh.x != 0 && mesh.y != 0 && mesh.z != 0) { importSet["alternativa.types.Point3D"] = true; constructor += "\t\t\tcoords = new Point3D(" + mesh.x + ", " + mesh.y + ", " + mesh.z +");\r"; newLine = true; } else { if (mesh.x != 0) { constructor += "\t\t\tx = " + mesh.x + ";\r"; newLine = true; } if (mesh.y != 0) { constructor += "\t\t\ty = " + mesh.y + ";\r"; newLine = true; } if (mesh.z != 0) { constructor += "\t\t\tz = " + mesh.z + ";\r"; newLine = true; } } if (mesh.rotationX != 0) { constructor += "\t\t\trotationX = " + mesh.rotationX + ";\r"; newLine = true; } if (mesh.rotationY != 0) { constructor += "\t\t\trotationY = " + mesh.rotationY + ";\r"; newLine = true; } if (mesh.rotationZ != 0) { constructor += "\t\t\trotationZ = " + mesh.rotationZ + ";\r"; newLine = true; } if (mesh.scaleX != 1) { constructor += "\t\t\tscaleX = " + mesh.scaleX + ";\r"; newLine = true; } if (mesh.scaleY != 1) { constructor += "\t\t\tscaleY = " + mesh.scaleY + ";\r"; newLine = true; } if (mesh.scaleZ != 1) { constructor += "\t\t\tscaleZ = " + mesh.scaleZ + ";\r"; newLine = true; } constructor += newLine ? "\r" : ""; function idToString(value:*):String { return isNaN(value) ? ("\"" + value + "\"") : value; } function blendModeToString(value:String):String { switch (value) { case BlendMode.ADD: return "BlendMode.ADD"; case BlendMode.ALPHA: return "BlendMode.ALPHA"; case BlendMode.DARKEN: return "BlendMode.DARKEN"; case BlendMode.DIFFERENCE: return "BlendMode.DIFFERENCE"; case BlendMode.ERASE: return "BlendMode.ERASE"; case BlendMode.HARDLIGHT: return "BlendMode.HARDLIGHT"; case BlendMode.INVERT: return "BlendMode.INVERT"; case BlendMode.LAYER: return "BlendMode.LAYER"; case BlendMode.LIGHTEN: return "BlendMode.LIGHTEN"; case BlendMode.MULTIPLY: return "BlendMode.MULTIPLY"; case BlendMode.NORMAL: return "BlendMode.NORMAL"; case BlendMode.OVERLAY: return "BlendMode.OVERLAY"; case BlendMode.SCREEN: return "BlendMode.SCREEN"; case BlendMode.SUBTRACT: return "BlendMode.SUBTRACT"; default: return "BlendMode.NORMAL"; } } function colorToString(value:uint):String { var hex:String = value.toString(16).toUpperCase(); var res:String = "0x"; var len:uint = 6 - hex.length; for (var j:uint = 0; j < len; j++) { res += "0"; } res += hex; return res; } var i:uint; var length:uint; var key:*; var id:String; var face:Face; var surface:Surface; newLine = false; for (id in mesh._vertices) { var vertex:Vertex = mesh._vertices[id]; var coords:Point3D = vertex.coords; constructor += "\t\t\tcreateVertex(" + coords.x + ", " + coords.y + ", " + coords.z + ", " + idToString(id) + ");\r"; newLine = true; } constructor += newLine ? "\r" : ""; newLine = false; for (id in mesh._faces) { face = mesh._faces[id]; length = face._verticesCount; constructor += "\t\t\tcreateFace([" for (i = 0; i < length - 1; i++) { constructor += idToString(mesh.getVertexId(face._vertices[i])) + ", "; } constructor += idToString(mesh.getVertexId(face._vertices[i])) + "], " + idToString(id) + ");\r"; if (face._aUV != null || face._bUV != null || face._cUV != null) { importSet["flash.geom.Point"] = true; constructor += "\t\t\tsetUVsToFace(new Point(" + face._aUV.x + ", " + face._aUV.y + "), new Point(" + face._bUV.x + ", " + face._bUV.y + "), new Point(" + face._cUV.x + ", " + face._cUV.y + "), " + idToString(id) + ");\r"; } newLine = true; } constructor += newLine ? "\r" : ""; for (id in mesh._surfaces) { surface = mesh._surfaces[id]; var facesStr:String = ""; for (key in surface._faces) { facesStr += idToString(mesh.getFaceId(key)) + ", "; } constructor += "\t\t\tcreateSurface([" + facesStr.substr(0, facesStr.length - 2) + "], " + idToString(id) + ");\r"; if (surface.material != null) { var material:String; var defaultAlpha:Boolean = surface.material.alpha == 1; var defaultBlendMode:Boolean = surface.material.blendMode == BlendMode.NORMAL; if (surface.material is WireMaterial) { importSet["alternativa.engine3d.materials.WireMaterial"] = true; var defaultThickness:Boolean = WireMaterial(surface.material).thickness == 0; var defaultColor:Boolean = WireMaterial(surface.material).color == 0; material = "new WireMaterial("; if (!defaultThickness || !defaultColor || !defaultAlpha || !defaultBlendMode) { material += WireMaterial(surface.material).thickness; if (!defaultColor || !defaultAlpha || !defaultBlendMode) { material += ", " + colorToString(WireMaterial(surface.material).color); if (!defaultAlpha || !defaultBlendMode) { material += ", " + surface.material.alpha ; if (!defaultBlendMode) { importSet["flash.display.BlendMode"] = true; material += ", " + blendModeToString(surface.material.blendMode); } } } } } var defaultWireThickness:Boolean; var defaultWireColor:Boolean; if (surface.material is FillMaterial) { importSet["alternativa.engine3d.materials.FillMaterial"] = true; defaultWireThickness = FillMaterial(surface.material).wireThickness < 0; defaultWireColor = FillMaterial(surface.material).wireColor == 0; material = "new FillMaterial(" + colorToString(FillMaterial(surface.material).color); if (!defaultAlpha || !defaultBlendMode || !defaultWireThickness || !defaultWireColor) { material += ", " + surface.material.alpha; if (!defaultBlendMode || !defaultWireThickness || !defaultWireColor) { importSet["flash.display.BlendMode"] = true; material += ", " + blendModeToString(surface.material.blendMode); if (!defaultWireThickness || !defaultWireColor) { material += ", " + FillMaterial(surface.material).wireThickness; if (!defaultWireColor) { material += ", " + colorToString(FillMaterial(surface.material).wireColor); } } } } } if (surface.material is TextureMaterial) { importSet["alternativa.engine3d.materials.TextureMaterial"] = true; var defaultRepeat:Boolean = TextureMaterial(surface.material).repeat; var defaultSmooth:Boolean = !TextureMaterial(surface.material).smooth; defaultWireThickness = TextureMaterial(surface.material).wireThickness < 0; defaultWireColor = TextureMaterial(surface.material).wireColor == 0; var defaultPrecision:Boolean = TextureMaterial(surface.material).precision == TextureMaterialPrecision.MEDIUM; if (TextureMaterial(surface.material).texture == null) { materialName = "null"; } else { importSet["alternativa.types.Texture"] = true; if (materialSet[TextureMaterial(surface.material).texture] == undefined) { materialName = (TextureMaterial(surface.material).texture._name != null) ? TextureMaterial(surface.material).texture._name : "texture" + materialNum++; materialSet[TextureMaterial(surface.material).texture] = materialName; } else { materialName = materialSet[TextureMaterial(surface.material).texture]; } materialName = materialName.split(".")[0]; } material = "new TextureMaterial(" + materialName; if (!defaultAlpha || !defaultRepeat || !defaultSmooth || !defaultBlendMode || !defaultWireThickness || !defaultWireColor || !defaultPrecision) { material += ", " + TextureMaterial(surface.material).alpha; if (!defaultRepeat || !defaultSmooth || !defaultBlendMode || !defaultWireThickness || !defaultWireColor || !defaultPrecision) { material += ", " + TextureMaterial(surface.material).repeat; if (!defaultSmooth || !defaultBlendMode || !defaultWireThickness || !defaultWireColor || !defaultPrecision) { material += ", " + TextureMaterial(surface.material).smooth; if (!defaultBlendMode || !defaultWireThickness || !defaultWireColor || !defaultPrecision) { importSet["flash.display.BlendMode"] = true; material += ", " + blendModeToString(surface.material.blendMode); if (!defaultWireThickness || !defaultWireColor || !defaultPrecision) { material += ", " + TextureMaterial(surface.material).wireThickness; if (!defaultWireColor || !defaultPrecision) { material += ", " + colorToString(TextureMaterial(surface.material).wireColor); if (!defaultPrecision) { material += ", " + TextureMaterial(surface.material).precision; } } } } } } } } constructor += "\t\t\tsetMaterialToSurface(" + material + "), " + idToString(id) + ");\r"; } } var imports:String = ""; newLine = false; var importArray:Array = new Array(); for (key in importSet) { importArray.push(key); } importArray.sort(); length = importArray.length; for (i = 0; i < length; i++) { var pack:String = importArray[i]; var current:String = pack.substr(0, pack.indexOf(".")); imports += (current != prev && prev != null) ? "\r" : ""; imports += "\timport " + pack + ";\r"; var prev:String = current; newLine = true; } imports += newLine ? "\r" : ""; var embeds:String = ""; newLine = false; for each (materialName in materialSet) { var materialClassName:String = materialName.split(".")[0]; var materialBmpName:String = materialClassName.charAt(0).toUpperCase() + materialClassName.substr(1); embeds += "\t\t[Embed(source=\"" + materialName + "\")] private static const bmp" + materialBmpName + ":Class;\r"; embeds += "\t\tprivate static const " + materialClassName + ":Texture = new Texture(new bmp" + materialBmpName + "().bitmapData, \"" + materialName + "\");\r"; newLine = true; } embeds += newLine ? "\r" : ""; return header + imports + classHeader + embeds + constructor + footer; } } }