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"]
\r
90 def setup(self, scene):
\r
93 for o in scene.objects:
\r
94 object_node_map[o]=OutlineNode(o)
\r
95 for node in object_node_map.values():
\r
97 object_node_map[node.o.parent].children.append(node)
\r
100 root=object_node_map[scene.objects.active]
\r
103 if root.o.type.upper()=='EMPTY':
\r
105 for node in root.children:
\r
110 def __setup(self, node, depth=0):
\r
111 info=ObjectInfo(node.o, depth)
\r
112 self.objects.append(info)
\r
113 if node.o.type.upper()=='MESH':
\r
114 # set material index
\r
115 for i, m in enumerate(node.o.data.materials):
\r
116 info.material_map[i]=self.__getOrAddMaterial(m)
\r
118 for child in node.children:
\r
119 self.__setup(child, depth+1)
\r
121 def __getOrAddMaterial(self, material):
\r
122 for i, m in enumerate(self.materials):
\r
125 index=len(self.materials)
\r
126 self.materials.append(material)
\r
129 def write(self, path, scene):
\r
130 io=bl.Writer(path, 'cp932')
\r
131 self.__write_header(io)
\r
132 self.__write_scene(io)
\r
133 print("Writing MaterialChunk")
\r
134 self.__write_materials(io, os.path.dirname(path))
\r
135 print("Writing ObjectChunk")
\r
136 for info in self.objects:
\r
137 self.__write_object(io, info, scene)
\r
138 io.write("Eof\r\n")
\r
142 def __write_header(self, io):
\r
143 io.write("Metasequoia Document\r\n")
\r
144 io.write("Format Text Ver 1.0\r\n")
\r
147 def __write_scene(self, io):
\r
148 print("Writing SceneChunk")
\r
149 io.write("Scene {\r\n")
\r
152 def __write_materials(self, io, dirname):
\r
154 io.write("Material %d {\r\n" % (len(self.materials)))
\r
155 for m in self.materials:
\r
156 tex, aplane=bl.getTexture(m, dirname)
\r
158 # textureがある場合は下地を白に
\r
159 io.write("\"%s\" shader(3) col(1 1 1 1)" % m.name)
\r
162 io.write(bl.materialToMqo(m))
\r
169 def __write_object(self, io, info, scene):
\r
173 if obj.type.upper()!='MESH':
\r
176 # duplicate and applyMatrix
\r
177 mesh, dumy=bl.objectDuplicate(scene, obj)
\r
179 ############################################################
\r
181 ############################################################
\r
182 io.write("Object \""+obj.name+"\" {\r\n")
\r
185 io.write("\tdepth %d\r\n" % info.depth)
\r
189 for mod in obj.modifiers:
\r
190 if mod.name=="Mirror":
\r
194 io.write("\tmirror 1\r\n")
\r
195 io.write("\tmirror_axis 1\r\n")
\r
198 io.write("\tvertex %d {\r\n" % len(mesh.verts))
\r
199 for vert in mesh.verts:
\r
200 x, y, z = convert_to_mqo(vert.co)
\r
201 io.write("\t\t%f %f %f\r\n" % (x, y, z)) # rotate to y-up
\r
202 io.write("\t}\r\n")
\r
205 io.write("\tface %d {\r\n" % len(mesh.faces))
\r
206 for i, face in enumerate(mesh.faces):
\r
207 count=bl.faceVertexCount(face)
\r
209 io.write("\t\t%d V(" % count)
\r
210 for j in bl.faceVertices(face):
\r
211 io.write("%d " % j)
\r
214 if len(mesh.materials):
\r
215 io.write(" M(%d)" %
\r
216 info.material_map[bl.faceMaterialIndex(face)])
\r
218 if bl.meshHasUV(mesh) and bl.faceHasUV(mesh, i, face):
\r
220 for uv in bl.faceGetUV(mesh, i, face, count):
\r
221 # reverse vertical value
\r
222 io.write("%f %f " % (uv[0], 1.0-uv[1]))
\r
225 io.write("\t}\r\n") # end of faces
\r
226 io.write("}\r\n") # end of object
\r
227 ############################################################
\r
230 scene.objects.unlink(dumy)
\r
233 def __execute(filename, scene, scale):
\r
234 exporter=MqoExporter()
\r
235 exporter.setup(scene)
\r
236 exporter.write(filename, scene)
\r
241 def execute_24(filename):
\r
245 filename=filename.decode(bl.INTERNAL_ENCODING)
\r
246 print("mqo exporter: %s" % filename)
\r
248 Blender.Window.WaitCursor(1)
\r
249 t = Blender.sys.time()
\r
251 __execute(filename, Blender.Scene.GetCurrent(), 1.0)
\r
253 print('finished in %.2f seconds' % (Blender.sys.time()-t) )
\r
255 Blender.Window.WaitCursor(0)
\r
258 Blender.Window.FileSelector(
\r
260 'Export Metasequoia MQO',
\r
261 Blender.sys.makename(ext='.mqo'))
\r
265 def execute_25(*args):
\r
269 class EXPORT_OT_mqo(bpy.types.Operator):
\r
270 '''Save a Metasequoia MQO file.'''
\r
271 bl_idname = "export_scene.mqo"
\r
272 bl_label = 'Export MQO'
\r
274 # List of operator properties, the attributes will be assigned
\r
275 # to the class instance from the operator settings before calling.
\r
277 path = StringProperty(
\r
279 description="File path used for exporting the MQO file",
\r
283 filename = StringProperty(
\r
285 description="Name of the file.")
\r
286 directory = StringProperty(
\r
288 description="Directory of the file.")
\r
290 check_existing = BoolProperty(
\r
291 name="Check Existing",
\r
292 description="Check and warn on overwriting existing files",
\r
294 options=set('HIDDEN'))
\r
296 scale = FloatProperty(
\r
298 description="Scale the MQO by this value",
\r
299 min=0.0001, max=1000000.0,
\r
300 soft_min=0.001, soft_max=100.0, default=1.0)
\r
302 def execute(self, context):
\r
304 self.properties.path,
\r
306 self.properties.scale)
\r
309 def invoke(self, context, event):
\r
311 wm.add_fileselect(self)
\r
312 return 'RUNNING_MODAL'
\r
315 def menu_func(self, context):
\r
316 default_path=bpy.data.filename.replace(".blend", ".mqo")
\r
317 self.layout.operator(
\r
318 EXPORT_OT_mqo.bl_idname,
\r
319 text="Metasequoia (.mqo)").path=default_path
\r
322 bpy.types.register(EXPORT_OT_mqo)
\r
323 bpy.types.INFO_MT_file_export.append(menu_func)
\r
326 bpy.types.unregister(EXPORT_OT_mqo)
\r
327 bpy.types.INFO_MT_file_export.remove(menu_func)
\r
329 if __name__ == "__main__":
\r