-#!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
-0.4 20100626: refactoring.\r
-0.5 20100710: add [apply_modifier] option(2.5 only).\r
-"""\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
- def materialToMqo(m):\r
- return "\"%s\" shader(3) col(%f %f %f %f)" % (\r
- m.name, m.rgbCol[0], m.rgbCol[1], m.rgbCol[2], m.alpha)\r
-\r
-else:\r
- # for 2.5\r
- import bpy\r
-\r
- # wrapper\r
- import bl25 as bl\r
-\r
- def materialToMqo(m):\r
- return "\"%s\" shader(3) col(%f %f %f %f)" % (\r
- m.name, \r
- m.diffuse_color[0], m.diffuse_color[1], m.diffuse_color[2], \r
- m.alpha)\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", 'scale', 'apply_modifier',]\r
- def __init__(self, scale, apply_modifier):\r
- self.objects=[]\r
- self.materials=[]\r
- self.scale=scale\r
- self.apply_modifier=apply_modifier\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):\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)\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
- io.write(materialToMqo(m))\r
- # ToDo separated alpha texture\r
- for filename in bl.material.eachTexturePath(m):\r
- if len(dirname)>0 and filename.startswith(dirname):\r
- # 相対パスに変換する\r
- filename=filename[len(dirname)+1:]\r
- io.write(" tex(\"%s\")" % filename)\r
- break\r
- io.write("\r\n") \r
- # end of chunk\r
- io.write("}\r\n") \r
-\r
- def __write_object(self, io, info):\r
- print(info)\r
-\r
- obj=info.object\r
- if obj.type.upper()=='MESH' or obj.type.upper()=='EMPTY':\r
- pass\r
- else:\r
- print(obj.type)\r
- return\r
-\r
- io.write("Object \""+obj.name+"\" {\r\n")\r
-\r
- # depth\r
- io.write("\tdepth %d\r\n" % info.depth)\r
-\r
- # mirror\r
- if not self.apply_modifier:\r
- if bl.modifier.hasType(obj, 'MIRROR'):\r
- io.write("\tmirror 1\r\n")\r
- io.write("\tmirror_axis 1\r\n")\r
-\r
- if obj.type.upper()=='MESH':\r
- # duplicate and applyMatrix\r
- copyMesh, copyObj=bl.object.duplicate(obj)\r
- # apply transform\r
- copyObj.scale=obj.scale\r
- bpy.ops.object.scale_apply()\r
- copyObj.rotation_euler=obj.rotation_euler\r
- bpy.ops.object.rotation_apply()\r
- copyObj.location=obj.location\r
- bpy.ops.object.location_apply()\r
- # apply modifier\r
- if self.apply_modifier:\r
- for m in [m for m in copyObj.modifiers]:\r
- if m.type=='SOLIDFY':\r
- continue\r
- elif m.type=='ARMATURE':\r
- bpy.ops.object.modifier_apply(modifier=m.name)\r
- elif m.type=='MIRROR':\r
- bpy.ops.object.modifier_apply(modifier=m.name)\r
- else:\r
- print(m.type)\r
- # write mesh\r
- self.__write_mesh(io, copyMesh, info.material_map)\r
- bl.object.delete(copyObj)\r
-\r
- io.write("}\r\n") # end of object\r
-\r
- def __write_mesh(self, io, mesh, material_map):\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" % \r
- (x*self.scale, y*self.scale, z*self.scale)) # 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.face.getVertexCount(face)\r
- # V\r
- io.write("\t\t%d V(" % count)\r
- for j in reversed(bl.face.getVertices(face)):\r
- io.write("%d " % j)\r
- io.write(")")\r
- # mat\r
- if len(mesh.materials):\r
- io.write(" M(%d)" % \r
- material_map[bl.face.getMaterialIndex(face)])\r
- # UV\r
- if bl.mesh.hasUV(mesh) and bl.mesh.hasFaceUV(mesh, i, face):\r
- io.write(" UV(")\r
- for uv in reversed(bl.mesh.getFaceUV(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
-\r
-\r
-def __execute(filename, scene, scale=10, apply_modifier=False):\r
- if not scene.objects.active:\r
- bl.message('no active object !')\r
- return\r
-\r
- exporter=MqoExporter(scale, apply_modifier)\r
- exporter.setup(scene)\r
- exporter.write(filename)\r
-\r
-\r
-if isBlender24():\r
- # for 2.4\r
- def execute_24(filename):\r
- scene=Blender.Scene.GetCurrent()\r
- bl.initialize('mqo_export', scene)\r
- __execute(\r
- filename.decode(bl.INTERNAL_ENCODING), \r
- scene, False)\r
- bl.finalize()\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(path, scene, scale, apply_modifier):\r
- bl.initialize('mqo_export', scene)\r
- __execute(path, scene, scale, apply_modifier)\r
- bl.finalize()\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 = bpy.props.StringProperty(\r
- name="File Path",\r
- description="File path used for exporting the MQO file",\r
- maxlen= 1024,\r
- default= ""\r
- )\r
- filename = bpy.props.StringProperty(\r
- name="File Name", \r
- description="Name of the file.")\r
- directory = bpy.props.StringProperty(\r
- name="Directory", \r
- description="Directory of the file.")\r
-\r
- scale = bpy.props.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=10.0)\r
-\r
- apply_modifier = bpy.props.BoolProperty(\r
- name="ApplyModifier", \r
- description="Would apply modifiers", \r
- default=False)\r
-\r
- check_existing = bpy.props.BoolProperty(\r
- name="Check Existing",\r
- description="Check and warn on overwriting existing files",\r
- default=True,\r
- options=set('HIDDEN'))\r
-\r
- def execute(self, context):\r
- execute_25(\r
- self.properties.path, \r
- context.scene, \r
- self.properties.scale,\r
- self.properties.apply_modifier)\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
+#!BPY
+# coding: utf-8
+
+"""
+Name: 'Metasequoia (.mqo)...'
+Blender: 245
+Group: 'Export'
+Tooltip: 'Save as Metasequoia MQO File'
+"""
+__author__= 'ousttrue'
+__url__ = ["http://gunload.web.fc2.com/blender/"]
+__version__= '0.3 2010/06/06'
+__bpydoc__ = """\
+This script is an exporter to MQO file format.
+
+Usage:
+
+Run this script from "File->Export" menu.
+
+0.1 20080128:
+0.2 20100518: refactoring.
+0.3 20100606: integrate 2.4 and 2.5.
+0.4 20100626: refactoring.
+0.5 20100710: add [apply_modifier] option(2.5 only).
+"""
+
+import os
+import sys
+
+def isBlender24():
+ return sys.version_info[0]<3
+
+if isBlender24():
+ # for 2.4
+ import Blender
+ from Blender import Mathutils
+ import bpy
+
+ # wrapper
+ import bl24 as bl
+
+ def materialToMqo(m):
+ return "\"%s\" shader(3) col(%f %f %f %f)" % (
+ m.name, m.rgbCol[0], m.rgbCol[1], m.rgbCol[2], m.alpha)
+
+else:
+ # for 2.5
+ import bpy
+
+ # wrapper
+ import bl25 as bl
+
+ def materialToMqo(m):
+ return "\"%s\" shader(3) col(%f %f %f %f)" % (
+ m.name,
+ m.diffuse_color[0], m.diffuse_color[1], m.diffuse_color[2],
+ m.alpha)
+
+def apply_transform(vec, matrix):
+ x, y, z = vec
+ xloc, yloc, zloc = matrix[3][0], matrix[3][1], matrix[3][2]
+ return x*matrix[0][0] + y*matrix[1][0] + z*matrix[2][0] + xloc,\
+ x*matrix[0][1] + y*matrix[1][1] + z*matrix[2][1] + yloc,\
+ x*matrix[0][2] + y*matrix[1][2] + z*matrix[2][2] + zloc
+
+def convert_to_mqo(vec):
+ return vec.x, vec.z, -vec.y
+
+
+class OutlineNode(object):
+ __slots__=['o', 'children']
+ def __init__(self, o):
+ self.o=o
+ self.children=[]
+
+ def __str__(self):
+ return "<Node %s>" % self.o
+
+
+class ObjectInfo(object):
+ __slots__=['object', 'depth', 'material_map']
+ def __init__(self, o, depth):
+ self.object=o
+ self.depth=depth
+ self.material_map={}
+
+ def __str__(self):
+ return "<ObjectInfo %d %s>" % (self.depth, self.object)
+
+
+class MqoExporter(object):
+ __slots__=["materials", "objects", 'scale', 'apply_modifier',]
+ def __init__(self, scale, apply_modifier):
+ self.objects=[]
+ self.materials=[]
+ self.scale=scale
+ self.apply_modifier=apply_modifier
+
+ def setup(self, scene):
+ # 木構造を構築する
+ object_node_map={}
+ for o in scene.objects:
+ object_node_map[o]=OutlineNode(o)
+ for node in object_node_map.values():
+ if node.o.parent:
+ object_node_map[node.o.parent].children.append(node)
+
+ # ルートを得る
+ root=object_node_map[scene.objects.active]
+
+ # 情報を集める
+ if root.o.type.upper()=='EMPTY':
+ # depth調整
+ for node in root.children:
+ self.__setup(node)
+ else:
+ self.__setup(root)
+
+ def __setup(self, node, depth=0):
+ info=ObjectInfo(node.o, depth)
+ self.objects.append(info)
+ if node.o.type.upper()=='MESH':
+ # set material index
+ for i, m in enumerate(node.o.data.materials):
+ info.material_map[i]=self.__getOrAddMaterial(m)
+ # recursive
+ for child in node.children:
+ self.__setup(child, depth+1)
+
+ def __getOrAddMaterial(self, material):
+ for i, m in enumerate(self.materials):
+ if m==material:
+ return i
+ index=len(self.materials)
+ self.materials.append(material)
+ return index
+
+ def write(self, path):
+ io=bl.Writer(path, 'cp932')
+ self.__write_header(io)
+ self.__write_scene(io)
+ print("Writing MaterialChunk")
+ self.__write_materials(io, os.path.dirname(path))
+ print("Writing ObjectChunk")
+ for info in self.objects:
+ self.__write_object(io, info)
+ io.write("Eof\r\n")
+ io.flush()
+ io.close()
+
+ def __write_header(self, io):
+ io.write("Metasequoia Document\r\n")
+ io.write("Format Text Ver 1.0\r\n")
+ io.write("\r\n")
+
+ def __write_scene(self, io):
+ print("Writing SceneChunk")
+ io.write("Scene {\r\n")
+ io.write("}\r\n")
+
+ def __write_materials(self, io, dirname):
+ # each material
+ io.write("Material %d {\r\n" % (len(self.materials)))
+ for m in self.materials:
+ io.write(materialToMqo(m))
+ # ToDo separated alpha texture
+ for filename in bl.material.eachTexturePath(m):
+ if len(dirname)>0 and filename.startswith(dirname):
+ # 相対パスに変換する
+ filename=filename[len(dirname)+1:]
+ io.write(" tex(\"%s\")" % filename)
+ break
+ io.write("\r\n")
+ # end of chunk
+ io.write("}\r\n")
+
+ def __write_object(self, io, info):
+ print(info)
+
+ obj=info.object
+ if obj.type.upper()=='MESH' or obj.type.upper()=='EMPTY':
+ pass
+ else:
+ print(obj.type)
+ return
+
+ io.write("Object \""+obj.name+"\" {\r\n")
+
+ # depth
+ io.write("\tdepth %d\r\n" % info.depth)
+
+ # mirror
+ if not self.apply_modifier:
+ if bl.modifier.hasType(obj, 'MIRROR'):
+ io.write("\tmirror 1\r\n")
+ io.write("\tmirror_axis 1\r\n")
+
+ if obj.type.upper()=='MESH':
+ # duplicate and applyMatrix
+ copyMesh, copyObj=bl.object.duplicate(obj)
+ # apply transform
+ copyObj.scale=obj.scale
+ bpy.ops.object.scale_apply()
+ copyObj.rotation_euler=obj.rotation_euler
+ bpy.ops.object.rotation_apply()
+ copyObj.location=obj.location
+ bpy.ops.object.location_apply()
+ # apply modifier
+ if self.apply_modifier:
+ for m in [m for m in copyObj.modifiers]:
+ if m.type=='SOLIDFY':
+ continue
+ elif m.type=='ARMATURE':
+ bpy.ops.object.modifier_apply(modifier=m.name)
+ elif m.type=='MIRROR':
+ bpy.ops.object.modifier_apply(modifier=m.name)
+ else:
+ print(m.type)
+ # write mesh
+ self.__write_mesh(io, copyMesh, info.material_map)
+ bl.object.delete(copyObj)
+
+ io.write("}\r\n") # end of object
+
+ def __write_mesh(self, io, mesh, material_map):
+ # vertices
+ io.write("\tvertex %d {\r\n" % len(mesh.verts))
+ for vert in mesh.verts:
+ x, y, z = convert_to_mqo(vert.co)
+ io.write("\t\t%f %f %f\r\n" %
+ (x*self.scale, y*self.scale, z*self.scale)) # rotate to y-up
+ io.write("\t}\r\n")
+
+ # faces
+ io.write("\tface %d {\r\n" % len(mesh.faces))
+ for i, face in enumerate(mesh.faces):
+ count=bl.face.getVertexCount(face)
+ # V
+ io.write("\t\t%d V(" % count)
+ for j in reversed(bl.face.getVertices(face)):
+ io.write("%d " % j)
+ io.write(")")
+ # mat
+ if len(mesh.materials):
+ io.write(" M(%d)" %
+ material_map[bl.face.getMaterialIndex(face)])
+ # UV
+ if bl.mesh.hasUV(mesh) and bl.mesh.hasFaceUV(mesh, i, face):
+ io.write(" UV(")
+ for uv in reversed(bl.mesh.getFaceUV(mesh, i, face, count)):
+ # reverse vertical value
+ io.write("%f %f " % (uv[0], 1.0-uv[1]))
+ io.write(")")
+ io.write("\r\n")
+ io.write("\t}\r\n") # end of faces
+
+
+def __execute(filename, scene, scale=10, apply_modifier=False):
+ if not scene.objects.active:
+ bl.message('no active object !')
+ return
+
+ exporter=MqoExporter(scale, apply_modifier)
+ exporter.setup(scene)
+ exporter.write(filename)
+
+
+if isBlender24():
+ # for 2.4
+ def execute_24(filename):
+ scene=Blender.Scene.GetCurrent()
+ bl.initialize('mqo_export', scene)
+ __execute(
+ filename.decode(bl.INTERNAL_ENCODING),
+ scene, False)
+ bl.finalize()
+
+ # execute
+ Blender.Window.FileSelector(
+ execute_24,
+ 'Export Metasequoia MQO',
+ Blender.sys.makename(ext='.mqo'))
+
+else:
+ # for 2.5
+ def execute_25(path, scene, scale, apply_modifier):
+ bl.initialize('mqo_export', scene)
+ __execute(path, scene, scale, apply_modifier)
+ bl.finalize()
+
+ # operator
+ class EXPORT_OT_mqo(bpy.types.Operator):
+ '''Save a Metasequoia MQO file.'''
+ bl_idname = "export_scene.mqo"
+ bl_label = 'Export MQO'
+
+ # List of operator properties, the attributes will be assigned
+ # to the class instance from the operator settings before calling.
+
+ path = bpy.props.StringProperty(
+ name="File Path",
+ description="File path used for exporting the MQO file",
+ maxlen= 1024,
+ default= ""
+ )
+ filename = bpy.props.StringProperty(
+ name="File Name",
+ description="Name of the file.")
+ directory = bpy.props.StringProperty(
+ name="Directory",
+ description="Directory of the file.")
+
+ scale = bpy.props.FloatProperty(
+ name="Scale",
+ description="Scale the MQO by this value",
+ min=0.0001, max=1000000.0,
+ soft_min=0.001, soft_max=100.0, default=10.0)
+
+ apply_modifier = bpy.props.BoolProperty(
+ name="ApplyModifier",
+ description="Would apply modifiers",
+ default=False)
+
+ check_existing = bpy.props.BoolProperty(
+ name="Check Existing",
+ description="Check and warn on overwriting existing files",
+ default=True,
+ options=set('HIDDEN'))
+
+ def execute(self, context):
+ execute_25(
+ self.properties.path,
+ context.scene,
+ self.properties.scale,
+ self.properties.apply_modifier)
+ return 'FINISHED'
+
+ def invoke(self, context, event):
+ wm=context.manager
+ wm.add_fileselect(self)
+ return 'RUNNING_MODAL'
+
+ # register menu
+ def menu_func(self, context):
+ #default_path=bpy.data.filename.replace(".blend", ".mqo")
+ self.layout.operator(
+ EXPORT_OT_mqo.bl_idname,
+ text="Metasequoia (.mqo)")#.path=default_path
+
+ def register():
+ bpy.types.register(EXPORT_OT_mqo)
+ bpy.types.INFO_MT_file_export.append(menu_func)
+
+ def unregister():
+ bpy.types.unregister(EXPORT_OT_mqo)
+ bpy.types.INFO_MT_file_export.remove(menu_func)
+
+ if __name__ == "__main__":
+ register()
+