+#!BPY\r
+# coding: utf-8\r
+\r
+"""\r
+Name: 'Metasequoia (.mqo)...'\r
+Blender: 245\r
+Group: 'Export'\r
+Tooltip: 'Save as Metasequoia MQO File'\r
+"""\r
+__author__= 'ousttrue'\r
+__url__ = ["http://gunload.web.fc2.com/blender/"]\r
+__version__= '0.3 2010/06/06'\r
+__bpydoc__ = """\\r
+This script is an exporter to MQO file format.\r
+\r
+Usage:\r
+\r
+Run this script from "File->Export" menu.\r
+\r
+0.1 20080128:\r
+0.2 20100518: refactoring.\r
+0.3 20100606: integrate 2.4 and 2.5.\r
+"""\r
+\r
+\r
+###############################################################################\r
+# import\r
+###############################################################################\r
+import os\r
+import sys\r
+\r
+def isBlender24():\r
+ return sys.version_info[0]<3\r
+\r
+if isBlender24():\r
+ # for 2.4\r
+ import Blender\r
+ from Blender import Mathutils\r
+ import bpy\r
+\r
+ # wrapper\r
+ import bl24 as bl\r
+\r
+else:\r
+ # for 2.5\r
+ import bpy\r
+ from bpy.props import *\r
+\r
+ # wrapper\r
+ import bl25 as bl\r
+\r
+def apply_transform(vec, matrix):\r
+ x, y, z = vec\r
+ xloc, yloc, zloc = matrix[3][0], matrix[3][1], matrix[3][2]\r
+ return x*matrix[0][0] + y*matrix[1][0] + z*matrix[2][0] + xloc,\\r
+ x*matrix[0][1] + y*matrix[1][1] + z*matrix[2][1] + yloc,\\r
+ x*matrix[0][2] + y*matrix[1][2] + z*matrix[2][2] + zloc\r
+\r
+def convert_to_mqo(vec):\r
+ return vec.x, vec.z, -vec.y\r
+\r
+\r
+class OutlineNode(object):\r
+ __slots__=['o', 'children']\r
+ def __init__(self, o):\r
+ self.o=o\r
+ self.children=[]\r
+\r
+ def __str__(self):\r
+ return "<Node %s>" % self.o\r
+\r
+\r
+class ObjectInfo(object):\r
+ __slots__=['object', 'depth', 'material_map']\r
+ def __init__(self, o, depth):\r
+ self.object=o\r
+ self.depth=depth\r
+ self.material_map={}\r
+\r
+ def __str__(self):\r
+ return "<ObjectInfo %d %s>" % (self.depth, self.object)\r
+\r
+\r
+class MqoExporter(object):\r
+ __slots__=["materials", "objects"]\r
+ def __init__(self):\r
+ self.objects=[]\r
+ self.materials=[]\r
+\r
+ def setup(self, scene):\r
+ # 木構造を構築する\r
+ object_node_map={}\r
+ for o in scene.objects:\r
+ object_node_map[o]=OutlineNode(o)\r
+ for node in object_node_map.values():\r
+ if node.o.parent:\r
+ object_node_map[node.o.parent].children.append(node)\r
+\r
+ # ルートを得る\r
+ root=object_node_map[scene.objects.active]\r
+\r
+ # 情報を集める\r
+ if root.o.type.upper()=='EMPTY':\r
+ # depth調整 \r
+ for node in root.children:\r
+ self.__setup(node)\r
+ else:\r
+ self.__setup(root)\r
+\r
+ def __setup(self, node, depth=0):\r
+ info=ObjectInfo(node.o, depth)\r
+ self.objects.append(info)\r
+ if node.o.type.upper()=='MESH':\r
+ # set material index\r
+ for i, m in enumerate(node.o.data.materials):\r
+ info.material_map[i]=self.__getOrAddMaterial(m)\r
+ # recursive\r
+ for child in node.children:\r
+ self.__setup(child, depth+1)\r
+ \r
+ def __getOrAddMaterial(self, material):\r
+ for i, m in enumerate(self.materials):\r
+ if m==material:\r
+ return i\r
+ index=len(self.materials)\r
+ self.materials.append(material)\r
+ return index\r
+\r
+ def write(self, path, scene):\r
+ io=bl.Writer(path, 'cp932')\r
+ self.__write_header(io)\r
+ self.__write_scene(io)\r
+ print("Writing MaterialChunk")\r
+ self.__write_materials(io, os.path.dirname(path))\r
+ print("Writing ObjectChunk")\r
+ for info in self.objects:\r
+ self.__write_object(io, info, scene)\r
+ io.write("Eof\r\n")\r
+ io.flush()\r
+ io.close()\r
+\r
+ def __write_header(self, io):\r
+ io.write("Metasequoia Document\r\n")\r
+ io.write("Format Text Ver 1.0\r\n")\r
+ io.write("\r\n")\r
+\r
+ def __write_scene(self, io):\r
+ print("Writing SceneChunk")\r
+ io.write("Scene {\r\n")\r
+ io.write("}\r\n")\r
+\r
+ def __write_materials(self, io, dirname):\r
+ # each material \r
+ io.write("Material %d {\r\n" % (len(self.materials)))\r
+ for m in self.materials:\r
+ tex, aplane=bl.getTexture(m, dirname)\r
+ if len(tex):\r
+ # textureがある場合は下地を白に\r
+ io.write("\"%s\" shader(3) col(1 1 1 1)" % m.name)\r
+ else:\r
+ # 無い場合はそのまま\r
+ io.write(bl.materialToMqo(m))\r
+ io.write(tex)\r
+ io.write(aplane)\r
+ io.write("\r\n") \r
+ # end of chunk\r
+ io.write("}\r\n") \r
+\r
+ def __write_object(self, io, info, scene):\r
+ print(info)\r
+\r
+ obj=info.object\r
+ if obj.type.upper()!='MESH':\r
+ return\r
+\r
+ # duplicate and applyMatrix\r
+ mesh, dumy=bl.objectDuplicate(scene, obj)\r
+\r
+ ############################################################\r
+ # write\r
+ ############################################################\r
+ io.write("Object \""+obj.name+"\" {\r\n")\r
+\r
+ # depth\r
+ io.write("\tdepth %d\r\n" % info.depth)\r
+\r
+ # mirroring \r
+ isMirrorring=False\r
+ for mod in obj.modifiers:\r
+ if mod.name=="Mirror":\r
+ isMirrorring=True\r
+ break\r
+ if isMirrorring:\r
+ io.write("\tmirror 1\r\n")\r
+ io.write("\tmirror_axis 1\r\n")\r
+\r
+ # vertices\r
+ io.write("\tvertex %d {\r\n" % len(mesh.verts))\r
+ for vert in mesh.verts:\r
+ x, y, z = convert_to_mqo(vert.co)\r
+ io.write("\t\t%f %f %f\r\n" % (x, y, z)) # rotate to y-up\r
+ io.write("\t}\r\n")\r
+\r
+ # faces\r
+ io.write("\tface %d {\r\n" % len(mesh.faces))\r
+ for i, face in enumerate(mesh.faces):\r
+ count=bl.faceVertexCount(face)\r
+ # V\r
+ io.write("\t\t%d V(" % count)\r
+ for j in bl.faceVertices(face):\r
+ io.write("%d " % j)\r
+ io.write(")")\r
+ # mat\r
+ if len(mesh.materials):\r
+ io.write(" M(%d)" % \r
+ info.material_map[bl.faceMaterialIndex(face)])\r
+ # UV\r
+ if bl.meshHasUV(mesh) and bl.faceHasUV(mesh, i, face):\r
+ io.write(" UV(")\r
+ for uv in bl.faceGetUV(mesh, i, face, count):\r
+ # reverse vertical value\r
+ io.write("%f %f " % (uv[0], 1.0-uv[1])) \r
+ io.write(")")\r
+ io.write("\r\n")\r
+ io.write("\t}\r\n") # end of faces\r
+ io.write("}\r\n") # end of object\r
+ ############################################################\r
+\r
+ # 削除する\r
+ scene.objects.unlink(dumy)\r
+\r
+\r
+def __execute(filename, scene, scale):\r
+ exporter=MqoExporter()\r
+ exporter.setup(scene)\r
+ exporter.write(filename, scene)\r
+\r
+\r
+if isBlender24():\r
+ # for 2.4\r
+ def execute_24(filename):\r
+ """\r
+ export mqo.\r
+ """\r
+ filename=filename.decode(bl.INTERNAL_ENCODING)\r
+ print("mqo exporter: %s" % filename)\r
+\r
+ Blender.Window.WaitCursor(1) \r
+ t = Blender.sys.time() \r
+\r
+ __execute(filename, Blender.Scene.GetCurrent(), 1.0)\r
+\r
+ print('finished in %.2f seconds' % (Blender.sys.time()-t) )\r
+ Blender.Redraw()\r
+ Blender.Window.WaitCursor(0) \r
+\r
+ # execute\r
+ Blender.Window.FileSelector(\r
+ execute_24, \r
+ 'Export Metasequoia MQO', \r
+ Blender.sys.makename(ext='.mqo'))\r
+\r
+else:\r
+ # for 2.5\r
+ def execute_25(*args):\r
+ __execute(*args)\r
+\r
+ # operator\r
+ class EXPORT_OT_mqo(bpy.types.Operator):\r
+ '''Save a Metasequoia MQO file.'''\r
+ bl_idname = "export_scene.mqo"\r
+ bl_label = 'Export MQO'\r
+\r
+ # List of operator properties, the attributes will be assigned\r
+ # to the class instance from the operator settings before calling.\r
+\r
+ path = StringProperty(\r
+ name="File Path",\r
+ description="File path used for exporting the MQO file",\r
+ maxlen= 1024,\r
+ default= ""\r
+ )\r
+ filename = StringProperty(\r
+ name="File Name", \r
+ description="Name of the file.")\r
+ directory = StringProperty(\r
+ name="Directory", \r
+ description="Directory of the file.")\r
+\r
+ check_existing = BoolProperty(\r
+ name="Check Existing",\r
+ description="Check and warn on overwriting existing files",\r
+ default=True,\r
+ options=set('HIDDEN'))\r
+\r
+ scale = FloatProperty(\r
+ name="Scale", \r
+ description="Scale the MQO by this value", \r
+ min=0.0001, max=1000000.0, \r
+ soft_min=0.001, soft_max=100.0, default=1.0)\r
+\r
+ def execute(self, context):\r
+ execute_25(\r
+ self.properties.path, \r
+ context.scene, \r
+ self.properties.scale)\r
+ return 'FINISHED'\r
+\r
+ def invoke(self, context, event):\r
+ wm=context.manager\r
+ wm.add_fileselect(self)\r
+ return 'RUNNING_MODAL'\r
+\r
+ # register menu\r
+ def menu_func(self, context): \r
+ default_path=bpy.data.filename.replace(".blend", ".mqo")\r
+ self.layout.operator(\r
+ EXPORT_OT_mqo.bl_idname, \r
+ text="Metasequoia (.mqo)").path=default_path\r
+\r
+ def register():\r
+ bpy.types.register(EXPORT_OT_mqo)\r
+ bpy.types.INFO_MT_file_export.append(menu_func)\r
+\r
+ def unregister():\r
+ bpy.types.unregister(EXPORT_OT_mqo)\r
+ bpy.types.INFO_MT_file_export.remove(menu_func)\r
+\r
+ if __name__ == "__main__":\r
+ register()\r
+\r