5 Name: 'Metasequoia (.mqo)...'
8 Tooltip: 'Save as Metasequoia MQO File'
10 __author__= 'ousttrue'
11 __url__ = ["http://gunload.web.fc2.com/blender/"]
14 This script is an exporter to MQO file format.
18 Run this script from "File->Export" menu.
21 0.2 20100518: refactoring.
22 0.3 20100606: integrate 2.4 and 2.5.
23 0.4 20100626: refactoring.
24 0.5 20100710: add [apply_modifier] option(2.5 only).
25 0.6 20100714: remove shape_key when apply_modifier. fix material.
26 2.0 20100724: update for Blender2.53.
27 2.1 20101005: update for Blender2.54.
28 2.2 20101228: update for Blender2.55.
29 2.4 20110429: update for Blender2.57b.
33 'category': 'Import/Export',
34 'name': 'Export: Metasequioa Model Format (.mqo)',
38 'location': 'File > Export',
39 'description': 'Export to the Metasequioa Model Format (.mqo)',
40 'warning': '', # used for warning icon and text in addons panel
41 'wiki_url': 'http://sourceforge.jp/projects/meshio/wiki/FrontPage',
42 'tracker_url': 'http://sourceforge.jp/ticket/newticket.php?group_id=5081',
49 return sys.version_info[0]<3
52 class MQOMaterial(object):
54 'name', 'shader', 'r', 'g', 'b', 'a',
57 def __init__(self, name, shader=3):
69 return "\"%s\" shader(%d) col(%f %f %f %f) dif(%f) amb(%f) emi(%f)" % (
70 self.name, self.shader, self.r, self.g, self.b, self.a,
71 self.dif, self.amb, self.emi
78 from Blender import Mathutils
85 material=MQOMaterial(m.name, 3)
86 material.r=m.rgbCol[0]
87 material.g=m.rgbCol[1]
88 material.b=m.rgbCol[2]
100 material=MQOMaterial(m.name, 3)
101 material.r=m.diffuse_color[0]
102 material.g=m.diffuse_color[1]
103 material.b=m.diffuse_color[2]
105 material.amb=m.ambient
109 def apply_transform(vec, matrix):
111 xloc, yloc, zloc = matrix[3][0], matrix[3][1], matrix[3][2]
112 return x*matrix[0][0] + y*matrix[1][0] + z*matrix[2][0] + xloc,\
113 x*matrix[0][1] + y*matrix[1][1] + z*matrix[2][1] + yloc,\
114 x*matrix[0][2] + y*matrix[1][2] + z*matrix[2][2] + zloc
116 def convert_to_mqo(vec):
117 return vec.x, vec.z, -vec.y
120 class OutlineNode(object):
121 __slots__=['o', 'children']
122 def __init__(self, o):
127 return "<Node %s>" % self.o
130 class ObjectInfo(object):
131 __slots__=['object', 'depth', 'material_map']
132 def __init__(self, o, depth):
138 return "<ObjectInfo %d %s>" % (self.depth, self.object)
141 class MqoExporter(object):
142 __slots__=["materials", "objects", 'scale', 'apply_modifier',]
143 def __init__(self, scale, apply_modifier):
147 self.apply_modifier=apply_modifier
149 def setup(self, scene):
152 for o in scene.objects:
153 object_node_map[o]=OutlineNode(o)
154 for node in object_node_map.values():
156 object_node_map[node.o.parent].children.append(node)
159 root=object_node_map[scene.objects.active]
162 if root.o.type.upper()=='EMPTY':
164 for node in root.children:
169 def __setup(self, node, depth=0):
170 info=ObjectInfo(node.o, depth)
171 self.objects.append(info)
172 if node.o.type.upper()=='MESH':
174 for i, m in enumerate(node.o.data.materials):
175 info.material_map[i]=self.__getOrAddMaterial(m)
177 for child in node.children:
178 self.__setup(child, depth+1)
180 def __getOrAddMaterial(self, material):
181 for i, m in enumerate(self.materials):
184 index=len(self.materials)
185 self.materials.append(material)
188 def write(self, path):
189 bl.message("open: "+path)
190 io=bl.Writer(path, 'cp932')
191 self.__write_header(io)
192 self.__write_scene(io)
193 print("Writing MaterialChunk")
194 self.__write_materials(io, os.path.dirname(path))
195 print("Writing ObjectChunk")
196 for info in self.objects:
197 self.__write_object(io, info)
202 def __write_header(self, io):
203 io.write("Metasequoia Document\r\n")
204 io.write("Format Text Ver 1.0\r\n")
207 def __write_scene(self, io):
208 print("Writing SceneChunk")
209 io.write("Scene {\r\n")
212 def __write_materials(self, io, dirname):
214 io.write("Material %d {\r\n" % (len(self.materials)))
215 for m in self.materials:
216 io.write(str(materialToMqo(m)))
217 # ToDo separated alpha texture
218 for filename in bl.material.eachTexturePath(m):
219 if len(dirname)>0 and filename.startswith(dirname):
221 filename=filename[len(dirname)+1:]
222 io.write(" tex(\"%s\")" % filename)
228 def __write_object(self, io, info):
232 if obj.type.upper()=='MESH' or obj.type.upper()=='EMPTY':
238 io.write("Object \""+obj.name+"\" {\r\n")
241 io.write("\tdepth %d\r\n" % info.depth)
244 if not self.apply_modifier:
245 if bl.modifier.hasType(obj, 'MIRROR'):
246 io.write("\tmirror 1\r\n")
247 io.write("\tmirror_axis 1\r\n")
249 if obj.type.upper()=='MESH':
250 # duplicate and applyMatrix
251 copyMesh, copyObj=bl.object.duplicate(obj)
253 copyObj.scale=obj.scale
254 bpy.ops.object.scale_apply()
255 copyObj.rotation_euler=obj.rotation_euler
256 bpy.ops.object.rotation_apply()
257 copyObj.location=obj.location
258 bpy.ops.object.location_apply()
260 if self.apply_modifier:
262 while bl.object.hasShapeKey(copyObj):
263 bpy.ops.object.shape_key_remove()
264 for m in [m for m in copyObj.modifiers]:
265 if m.type=='SOLIDFY':
267 elif m.type=='ARMATURE':
268 bpy.ops.object.modifier_apply(modifier=m.name)
269 elif m.type=='MIRROR':
270 bpy.ops.object.modifier_apply(modifier=m.name)
274 self.__write_mesh(io, copyMesh, info.material_map)
275 bl.object.delete(copyObj)
277 io.write("}\r\n") # end of object
279 def __write_mesh(self, io, mesh, material_map):
281 io.write("\tvertex %d {\r\n" % len(mesh.verts))
282 for vert in mesh.verts:
283 x, y, z = convert_to_mqo(vert.co)
284 io.write("\t\t%f %f %f\r\n" %
285 (x*self.scale, y*self.scale, z*self.scale)) # rotate to y-up
289 io.write("\tface %d {\r\n" % len(mesh.faces))
290 for i, face in enumerate(mesh.faces):
291 count=bl.face.getVertexCount(face)
293 io.write("\t\t%d V(" % count)
294 for j in reversed(bl.face.getVertices(face)):
298 if len(mesh.materials):
300 material_map[bl.face.getMaterialIndex(face)])
302 if bl.mesh.hasUV(mesh) and bl.mesh.hasFaceUV(mesh, i, face):
304 for uv in reversed(bl.mesh.getFaceUV(mesh, i, face, count)):
305 # reverse vertical value
306 io.write("%f %f " % (uv[0], 1.0-uv[1]))
309 io.write("\t}\r\n") # end of faces
312 def __execute(filename, scene, scale=10, apply_modifier=False):
313 if scene.objects.active:
314 exporter=MqoExporter(scale, apply_modifier)
315 exporter.setup(scene)
316 exporter.write(filename)
318 bl.message('no active object !')