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
23 0.4 20100626: refactoring.
\r
30 return sys.version_info[0]<3
\r
35 from Blender import Mathutils
\r
41 def materialToMqo(m):
\r
42 return "\"%s\" shader(3) col(%f %f %f %f)" % (
\r
43 m.name, m.rgbCol[0], m.rgbCol[1], m.rgbCol[2], m.alpha)
\r
48 from bpy.props import *
\r
53 def materialToMqo(m):
\r
54 return "\"%s\" shader(3) col(%f %f %f %f)" % (
\r
56 m.diffuse_color[0], m.diffuse_color[1], m.diffuse_color[2],
\r
59 def apply_transform(vec, matrix):
\r
61 xloc, yloc, zloc = matrix[3][0], matrix[3][1], matrix[3][2]
\r
62 return x*matrix[0][0] + y*matrix[1][0] + z*matrix[2][0] + xloc,\
\r
63 x*matrix[0][1] + y*matrix[1][1] + z*matrix[2][1] + yloc,\
\r
64 x*matrix[0][2] + y*matrix[1][2] + z*matrix[2][2] + zloc
\r
66 def convert_to_mqo(vec):
\r
67 return vec.x, vec.z, -vec.y
\r
70 class OutlineNode(object):
\r
71 __slots__=['o', 'children']
\r
72 def __init__(self, o):
\r
77 return "<Node %s>" % self.o
\r
80 class ObjectInfo(object):
\r
81 __slots__=['object', 'depth', 'material_map']
\r
82 def __init__(self, o, depth):
\r
85 self.material_map={}
\r
88 return "<ObjectInfo %d %s>" % (self.depth, self.object)
\r
91 class MqoExporter(object):
\r
92 __slots__=["materials", "objects", 'scale',]
\r
93 def __init__(self, scale):
\r
98 def setup(self, scene):
\r
101 for o in scene.objects:
\r
102 object_node_map[o]=OutlineNode(o)
\r
103 for node in object_node_map.values():
\r
105 object_node_map[node.o.parent].children.append(node)
\r
108 root=object_node_map[scene.objects.active]
\r
111 if root.o.type.upper()=='EMPTY':
\r
113 for node in root.children:
\r
118 def __setup(self, node, depth=0):
\r
119 info=ObjectInfo(node.o, depth)
\r
120 self.objects.append(info)
\r
121 if node.o.type.upper()=='MESH':
\r
122 # set material index
\r
123 for i, m in enumerate(node.o.data.materials):
\r
124 info.material_map[i]=self.__getOrAddMaterial(m)
\r
126 for child in node.children:
\r
127 self.__setup(child, depth+1)
\r
129 def __getOrAddMaterial(self, material):
\r
130 for i, m in enumerate(self.materials):
\r
133 index=len(self.materials)
\r
134 self.materials.append(material)
\r
137 def write(self, path):
\r
138 io=bl.Writer(path, 'cp932')
\r
139 self.__write_header(io)
\r
140 self.__write_scene(io)
\r
141 print("Writing MaterialChunk")
\r
142 self.__write_materials(io, os.path.dirname(path))
\r
143 print("Writing ObjectChunk")
\r
144 for info in self.objects:
\r
145 self.__write_object(io, info)
\r
146 io.write("Eof\r\n")
\r
150 def __write_header(self, io):
\r
151 io.write("Metasequoia Document\r\n")
\r
152 io.write("Format Text Ver 1.0\r\n")
\r
155 def __write_scene(self, io):
\r
156 print("Writing SceneChunk")
\r
157 io.write("Scene {\r\n")
\r
160 def __write_materials(self, io, dirname):
\r
162 io.write("Material %d {\r\n" % (len(self.materials)))
\r
163 for m in self.materials:
\r
164 io.write(materialToMqo(m))
\r
165 # ToDo separated alpha texture
\r
166 for filename in bl.material.eachTexturePath(m):
\r
167 if len(dirname)>0 and filename.startswith(dirname):
\r
169 filename=filename[len(dirname)+1:]
\r
170 io.write(" tex(\"%s\")" % filename)
\r
176 def __write_object(self, io, info):
\r
180 if obj.type.upper()=='MESH' or obj.type.upper()=='EMPTY':
\r
186 ############################################################
\r
188 ############################################################
\r
189 io.write("Object \""+obj.name+"\" {\r\n")
\r
192 io.write("\tdepth %d\r\n" % info.depth)
\r
194 if bl.modifier.hasType(obj, 'MIRROR'):
\r
195 io.write("\tmirror 1\r\n")
\r
196 io.write("\tmirror_axis 1\r\n")
\r
198 if obj.type.upper()=='MESH':
\r
199 # duplicate and applyMatrix
\r
200 mesh, dumy=bl.object.duplicate(obj)
\r
203 io.write("\tvertex %d {\r\n" % len(mesh.verts))
\r
204 for vert in mesh.verts:
\r
205 x, y, z = convert_to_mqo(vert.co)
\r
206 io.write("\t\t%f %f %f\r\n" %
\r
207 (x*self.scale, y*self.scale, z*self.scale)) # rotate to y-up
\r
208 io.write("\t}\r\n")
\r
211 io.write("\tface %d {\r\n" % len(mesh.faces))
\r
212 for i, face in enumerate(mesh.faces):
\r
213 count=bl.face.getVertexCount(face)
\r
215 io.write("\t\t%d V(" % count)
\r
216 for j in reversed(bl.face.getVertices(face)):
\r
217 io.write("%d " % j)
\r
220 if len(mesh.materials):
\r
221 io.write(" M(%d)" %
\r
222 info.material_map[bl.face.getMaterialIndex(face)])
\r
224 if bl.mesh.hasUV(mesh) and bl.mesh.hasFaceUV(mesh, i, face):
\r
226 for uv in reversed(bl.mesh.getFaceUV(mesh, i, face, count)):
\r
227 # reverse vertical value
\r
228 io.write("%f %f " % (uv[0], 1.0-uv[1]))
\r
231 io.write("\t}\r\n") # end of faces
\r
234 bl.object.delete(dumy)
\r
236 io.write("}\r\n") # end of object
\r
239 def __execute(filename, scene, scale=10):
\r
240 if not scene.objects.active:
\r
241 bl.message('no active object !')
\r
244 exporter=MqoExporter(scale)
\r
245 exporter.setup(scene)
\r
246 exporter.write(filename)
\r
251 def execute_24(filename):
\r
252 scene=Blender.Scene.GetCurrent()
\r
253 bl.initialize('mqo_export', scene)
\r
255 filename.decode(bl.INTERNAL_ENCODING),
\r
260 Blender.Window.FileSelector(
\r
262 'Export Metasequoia MQO',
\r
263 Blender.sys.makename(ext='.mqo'))
\r
267 def execute_25(path, scene, scale):
\r
268 bl.initialize('mqo_export', scene)
\r
269 __execute(path, scene, scale)
\r
273 class EXPORT_OT_mqo(bpy.types.Operator):
\r
274 '''Save a Metasequoia MQO file.'''
\r
275 bl_idname = "export_scene.mqo"
\r
276 bl_label = 'Export MQO'
\r
278 # List of operator properties, the attributes will be assigned
\r
279 # to the class instance from the operator settings before calling.
\r
281 path = StringProperty(
\r
283 description="File path used for exporting the MQO file",
\r
287 filename = StringProperty(
\r
289 description="Name of the file.")
\r
290 directory = StringProperty(
\r
292 description="Directory of the file.")
\r
294 scale = FloatProperty(
\r
296 description="Scale the MQO by this value",
\r
297 min=0.0001, max=1000000.0,
\r
298 soft_min=0.001, soft_max=100.0, default=10.0)
\r
300 check_existing = BoolProperty(
\r
301 name="Check Existing",
\r
302 description="Check and warn on overwriting existing files",
\r
304 options=set('HIDDEN'))
\r
306 def execute(self, context):
\r
308 self.properties.path,
\r
310 self.properties.scale)
\r
313 def invoke(self, context, event):
\r
315 wm.add_fileselect(self)
\r
316 return 'RUNNING_MODAL'
\r
319 def menu_func(self, context):
\r
320 #default_path=bpy.data.filename.replace(".blend", ".mqo")
\r
321 self.layout.operator(
\r
322 EXPORT_OT_mqo.bl_idname,
\r
323 text="Metasequoia (.mqo)")#.path=default_path
\r
326 bpy.types.register(EXPORT_OT_mqo)
\r
327 bpy.types.INFO_MT_file_export.append(menu_func)
\r
330 bpy.types.unregister(EXPORT_OT_mqo)
\r
331 bpy.types.INFO_MT_file_export.remove(menu_func)
\r
333 if __name__ == "__main__":
\r