5 Name: 'Metasequoia (.mqo)...'
\r
8 Tooltip: 'Save as Metasequoia MQO File'
\r
10 __author__= 'ousttrue'
\r
11 __url__ = ["http://gunload.web.fc2.com/blender/"]
\r
12 __version__= '0.3 2010/06/06'
\r
14 This script is an exporter to MQO file format.
\r
18 Run this script from "File->Export" menu.
\r
21 0.2 20100518: refactoring.
\r
22 0.3 20100606: integrate 2.4 and 2.5.
\r
26 ###############################################################################
\r
28 ###############################################################################
\r
33 return sys.version_info[0]<3
\r
38 from Blender import Mathutils
\r
47 from bpy.props import *
\r
52 def apply_transform(vec, matrix):
\r
54 xloc, yloc, zloc = matrix[3][0], matrix[3][1], matrix[3][2]
\r
55 return x*matrix[0][0] + y*matrix[1][0] + z*matrix[2][0] + xloc,\
\r
56 x*matrix[0][1] + y*matrix[1][1] + z*matrix[2][1] + yloc,\
\r
57 x*matrix[0][2] + y*matrix[1][2] + z*matrix[2][2] + zloc
\r
59 def convert_to_mqo(vec):
\r
60 return vec.x, vec.z, -vec.y
\r
63 class OutlineNode(object):
\r
64 __slots__=['o', 'children']
\r
65 def __init__(self, o):
\r
70 return "<Node %s>" % self.o
\r
73 class ObjectInfo(object):
\r
74 __slots__=['object', 'depth', 'material_map']
\r
75 def __init__(self, o, depth):
\r
78 self.material_map={}
\r
81 return "<ObjectInfo %d %s>" % (self.depth, self.object)
\r
84 class MqoExporter(object):
\r
85 __slots__=["materials", "objects", 'scale',]
\r
86 def __init__(self, scale):
\r
90 print('scaling', self.scale)
\r
92 def setup(self, scene):
\r
95 for o in scene.objects:
\r
96 object_node_map[o]=OutlineNode(o)
\r
97 for node in object_node_map.values():
\r
99 object_node_map[node.o.parent].children.append(node)
\r
102 root=object_node_map[scene.objects.active]
\r
105 if root.o.type.upper()=='EMPTY':
\r
107 for node in root.children:
\r
112 def __setup(self, node, depth=0):
\r
113 info=ObjectInfo(node.o, depth)
\r
114 self.objects.append(info)
\r
115 if node.o.type.upper()=='MESH':
\r
116 # set material index
\r
117 for i, m in enumerate(node.o.data.materials):
\r
118 info.material_map[i]=self.__getOrAddMaterial(m)
\r
120 for child in node.children:
\r
121 self.__setup(child, depth+1)
\r
123 def __getOrAddMaterial(self, material):
\r
124 for i, m in enumerate(self.materials):
\r
127 index=len(self.materials)
\r
128 self.materials.append(material)
\r
131 def write(self, path, scene):
\r
132 io=bl.Writer(path, 'cp932')
\r
133 self.__write_header(io)
\r
134 self.__write_scene(io)
\r
135 print("Writing MaterialChunk")
\r
136 self.__write_materials(io, os.path.dirname(path))
\r
137 print("Writing ObjectChunk")
\r
138 for info in self.objects:
\r
139 self.__write_object(io, info, scene)
\r
140 io.write("Eof\r\n")
\r
144 def __write_header(self, io):
\r
145 io.write("Metasequoia Document\r\n")
\r
146 io.write("Format Text Ver 1.0\r\n")
\r
149 def __write_scene(self, io):
\r
150 print("Writing SceneChunk")
\r
151 io.write("Scene {\r\n")
\r
154 def __write_materials(self, io, dirname):
\r
156 io.write("Material %d {\r\n" % (len(self.materials)))
\r
157 for m in self.materials:
\r
158 tex, aplane=bl.getTexture(m, dirname)
\r
160 # textureがある場合は下地を白に
\r
161 io.write("\"%s\" shader(3) col(1 1 1 1)" % m.name)
\r
164 io.write(bl.materialToMqo(m))
\r
171 def __write_object(self, io, info, scene):
\r
175 if obj.type.upper()=='MESH' or obj.type.upper()=='EMPTY':
\r
181 ############################################################
\r
183 ############################################################
\r
184 io.write("Object \""+obj.name+"\" {\r\n")
\r
187 io.write("\tdepth %d\r\n" % info.depth)
\r
191 for mod in obj.modifiers:
\r
192 if mod.name.upper()=="MIRROR":
\r
196 io.write("\tmirror 1\r\n")
\r
197 io.write("\tmirror_axis 1\r\n")
\r
199 if obj.type.upper()=='MESH':
\r
200 # duplicate and applyMatrix
\r
201 mesh, dumy=bl.objectDuplicate(scene, obj)
\r
204 io.write("\tvertex %d {\r\n" % len(mesh.verts))
\r
205 for vert in mesh.verts:
\r
206 x, y, z = convert_to_mqo(vert.co)
\r
207 io.write("\t\t%f %f %f\r\n" %
\r
208 (x*self.scale, y*self.scale, z*self.scale)) # rotate to y-up
\r
209 io.write("\t}\r\n")
\r
212 io.write("\tface %d {\r\n" % len(mesh.faces))
\r
213 for i, face in enumerate(mesh.faces):
\r
214 count=bl.faceVertexCount(face)
\r
216 io.write("\t\t%d V(" % count)
\r
218 for j in bl.faceVertices(face):
\r
219 face_list.insert(0, j)
\r
221 for j in face_list:
\r
222 io.write("%d " % j)
\r
225 if len(mesh.materials):
\r
226 io.write(" M(%d)" %
\r
227 info.material_map[bl.faceMaterialIndex(face)])
\r
229 if bl.meshHasUV(mesh) and bl.faceHasUV(mesh, i, face):
\r
232 for uv in bl.faceGetUV(mesh, i, face, count):
\r
233 # reverse vertical value
\r
234 uv_list.insert(0, uv)
\r
237 io.write("%f %f " % (uv[0], 1.0-uv[1]))
\r
240 io.write("\t}\r\n") # end of faces
\r
243 scene.objects.unlink(dumy)
\r
245 io.write("}\r\n") # end of object
\r
248 def __execute(filename, scene, scale=10):
\r
249 exporter=MqoExporter(scale)
\r
250 exporter.setup(scene)
\r
251 exporter.write(filename, scene)
\r
256 def execute_24(filename):
\r
260 filename=filename.decode(bl.INTERNAL_ENCODING)
\r
261 print("mqo exporter: %s" % filename)
\r
263 Blender.Window.WaitCursor(1)
\r
264 t = Blender.sys.time()
\r
266 __execute(filename, Blender.Scene.GetCurrent())
\r
268 print('finished in %.2f seconds' % (Blender.sys.time()-t) )
\r
270 Blender.Window.WaitCursor(0)
\r
273 Blender.Window.FileSelector(
\r
275 'Export Metasequoia MQO',
\r
276 Blender.sys.makename(ext='.mqo'))
\r
280 def execute_25(*args):
\r
284 class EXPORT_OT_mqo(bpy.types.Operator):
\r
285 '''Save a Metasequoia MQO file.'''
\r
286 bl_idname = "export_scene.mqo"
\r
287 bl_label = 'Export MQO'
\r
289 # List of operator properties, the attributes will be assigned
\r
290 # to the class instance from the operator settings before calling.
\r
292 path = StringProperty(
\r
294 description="File path used for exporting the MQO file",
\r
298 filename = StringProperty(
\r
300 description="Name of the file.")
\r
301 directory = StringProperty(
\r
303 description="Directory of the file.")
\r
305 scale = FloatProperty(
\r
307 description="Scale the MQO by this value",
\r
308 min=0.0001, max=1000000.0,
\r
309 soft_min=0.001, soft_max=100.0, default=100.0)
\r
311 check_existing = BoolProperty(
\r
312 name="Check Existing",
\r
313 description="Check and warn on overwriting existing files",
\r
315 options=set('HIDDEN'))
\r
317 def execute(self, context):
\r
319 self.properties.path,
\r
321 self.properties.scale)
\r
324 def invoke(self, context, event):
\r
326 wm.add_fileselect(self)
\r
327 return 'RUNNING_MODAL'
\r
330 def menu_func(self, context):
\r
331 #default_path=bpy.data.filename.replace(".blend", ".mqo")
\r
332 self.layout.operator(
\r
333 EXPORT_OT_mqo.bl_idname,
\r
334 text="Metasequoia (.mqo)")#.path=default_path
\r
337 bpy.types.register(EXPORT_OT_mqo)
\r
338 bpy.types.INFO_MT_file_export.append(menu_func)
\r
341 bpy.types.unregister(EXPORT_OT_mqo)
\r
342 bpy.types.INFO_MT_file_export.remove(menu_func)
\r
344 if __name__ == "__main__":
\r