OSDN Git Service

implement createMaterials.
[meshio/meshio.git] / swig / blender / mqo_import.py
1 #!BPY\r
2 # coding: utf-8\r
3 """ \r
4 Name: 'Metasequoia(.mqo)...'\r
5 Blender: 245\r
6 Group: 'Import'\r
7 Tooltip: 'Import from Metasequoia file format (.mqo)'\r
8 """\r
9 __author__=['ousttrue']\r
10 __url__ = ["http://gunload.web.fc2.com/blender/"]\r
11 __version__= '0.6 2010/05/05'\r
12 __bpydoc__= '''\\r
13 \r
14 MQO Importer\r
15 \r
16 This script imports a mqo into Blender for editing.\r
17 \r
18 0.2 20080123: update.\r
19 0.3 20091125: modify for linux.\r
20 0.4 20100310: rewrite.\r
21 0.5 20100311: create armature from mikoto bone.\r
22 0.6 20100505: C extension.\r
23 0.7 20100606: integrate 2.4 and 2.5.\r
24 '''\r
25 \r
26 \r
27 ###############################################################################\r
28 # import\r
29 ###############################################################################\r
30 import os\r
31 import sys\r
32 import math\r
33 \r
34 # C extension\r
35 from meshio import mqo\r
36 \r
37 def isBlender24():\r
38     return sys.version_info[0]<3\r
39 \r
40 if isBlender24():\r
41     # for 2.4\r
42     import Blender\r
43     from Blender import Mathutils\r
44     import bpy\r
45 \r
46     # wrapper\r
47     import bl24 as bl\r
48 else:\r
49     # for 2.5\r
50     import bpy\r
51     from bpy.props import *\r
52 \r
53     # wrapper\r
54     import bl25 as bl\r
55 \r
56 \r
57 ###############################################################################\r
58 # implement\r
59 ###############################################################################\r
60 def has_mikoto(mqo):\r
61     return False\r
62 \r
63 if isBlender24():\r
64     def create_objects(scene, mqo, root, materials, imageMap=None, scale=None):\r
65         """\r
66         create blender mesh objects.\r
67         """\r
68         # store hierarchy\r
69         stack=[root]    \r
70 \r
71         objects=[]\r
72         for o in mqo.objects:\r
73             #print "%s:v(%d),f(%d)" % (o.name, len(o.vertices), len(o.faces))\r
74             # create mesh\r
75             mesh = Blender.Mesh.New()\r
76             mesh_object=scene.objects.new(mesh, o.name.encode('utf-8'))\r
77 \r
78             # add hierarchy\r
79             stack_depth=len(stack)-1\r
80             print(o.depth, stack_depth)\r
81             if o.depth<stack_depth:\r
82                 for i in range(stack_depth-o.depth):\r
83                     stack.pop()\r
84             stack[-1].makeParent([mesh_object])\r
85             stack.append(mesh_object)\r
86 \r
87             if o.name.startswith('sdef'):\r
88                 # add sdef object\r
89                 objects.append(mesh_object)\r
90             elif o.name.startswith('anchor'):\r
91                 #print("hide %s" % o.name)\r
92                 #mesh_object.restrictDisplay=False\r
93                 mesh_object.layers=[2]\r
94             elif o.name.startswith('bone'):\r
95                 mesh_object.layers=[2]\r
96 \r
97             # add vertices\r
98             mesh.verts.extend(Mathutils.Vector(0, 0, 0)) # dummy\r
99             mesh.verts.extend([(v.x, -v.z, v.y) for v in o.vertices])\r
100             # add faces\r
101             mesh_faces=[]\r
102             for face in o.faces:\r
103                 face_indices=[]\r
104                 for i in xrange(face.index_count):\r
105                     face_indices.append(face.getIndex(i)+1)\r
106                 mesh_faces.append(face_indices)\r
107             #new_faces=mesh.faces.extend([face.indices for face in o.faces], \r
108             new_faces=mesh.faces.extend(mesh_faces,\r
109                     #ignoreDups=True, \r
110                     indexList=True)\r
111             mesh.update()\r
112             \r
113             # gather used materials\r
114             usedMaterials = {}\r
115             if new_faces:\r
116                 for i in new_faces:\r
117                     if type(i) is int:\r
118                         usedMaterials[o.faces[i].material_index]=True\r
119 \r
120             # blender limits 16 materials per mesh\r
121             # separate mesh ?\r
122             for i, material_index in enumerate(usedMaterials.keys()):\r
123                 if i>=16:\r
124                     print("over 16 materials!")\r
125                     break\r
126                 mesh.materials+=[materials[material_index]]\r
127                 usedMaterials[material_index]=i\r
128             \r
129             # set face params\r
130             for i, f in enumerate(o.faces):       \r
131                 if not type(new_faces[i]) is int:\r
132                     continue\r
133 \r
134                 face=mesh.faces[new_faces[i]]\r
135 \r
136                 uv_array=[]\r
137                 for i in xrange(f.index_count):\r
138                     uv_array.append(Blender.Mathutils.Vector(\r
139                         f.getUV(i).x, \r
140                         1.0-f.getUV(i).y)\r
141                         )\r
142                 try:\r
143                     face.uv=uv_array\r
144                 except Exception as msg:\r
145                     #print msg\r
146                     #print face.index, uv_array\r
147                     pass\r
148             \r
149                 if f.material_index in usedMaterials:\r
150                     face.mat = usedMaterials[f.material_index]\r
151 \r
152                 face.smooth = 1\r
153 \r
154             # rmeove dummy 0 vertex\r
155             mesh.verts.delete(0)\r
156                 \r
157             mesh.mode |= Blender.Mesh.Modes.AUTOSMOOTH\r
158             mesh.maxSmoothAngle = int(o.smoothing)\r
159             mesh.smooth()\r
160             mesh.calcNormals()\r
161             mesh.flipNormals()\r
162             mesh.update()\r
163 \r
164             # mirror modifier\r
165             if o.mirror:\r
166                 mod=mesh_object.modifiers.append(Blender.Modifier.Types.MIRROR)\r
167 \r
168         return objects\r
169 \r
170 \r
171     class MikotoBone(object):\r
172         __slots__=[\r
173                 'name',\r
174                 'iHead', 'iTail', 'iUp',\r
175                 'vHead', 'vTail', 'vUp',\r
176                 'parent', 'isFloating',\r
177                 'children',\r
178                 ]\r
179         def __init__(self, face=None, vertices=None, materials=None):\r
180             self.parent=None\r
181             self.isFloating=False\r
182             self.children=[]\r
183             if not face:\r
184                 self.name='root'\r
185                 return\r
186 \r
187             self.name=materials[face.material_index].name.encode('utf-8')\r
188 \r
189             i0=face.indices[0]\r
190             i1=face.indices[1]\r
191             i2=face.indices[2]\r
192             v0=vertices[i0]\r
193             v1=vertices[i1]\r
194             v2=vertices[i2]\r
195             e01=v1-v0\r
196             e12=v2-v1\r
197             e20=v0-v2\r
198             sqNorm0=e01.getSqNorm()\r
199             sqNorm1=e12.getSqNorm()\r
200             sqNorm2=e20.getSqNorm()\r
201             if sqNorm0>sqNorm1:\r
202                 if sqNorm1>sqNorm2:\r
203                     # e01 > e12 > e20\r
204                     self.iHead=i2\r
205                     self.iTail=i1\r
206                     self.iUp=i0\r
207                 else:\r
208                     if sqNorm0>sqNorm2:\r
209                         # e01 > e20 > e12\r
210                         self.iHead=i2\r
211                         self.iTail=i0\r
212                         self.iUp=i1\r
213                     else:\r
214                         # e20 > e01 > e12\r
215                         self.iHead=i1\r
216                         self.iTail=i0\r
217                         self.iUp=i2\r
218             else:\r
219                 # 0 < 1\r
220                 if sqNorm1<sqNorm2:\r
221                     # e20 > e12 > e01\r
222                     self.iHead=i1\r
223                     self.iTail=i2\r
224                     self.iUp=i0\r
225                 else:\r
226                     if sqNorm0<sqNorm2:\r
227                         # e12 > e20 > e01\r
228                         self.iHead=i0\r
229                         self.iTail=i2\r
230                         self.iUp=i1\r
231                     else:\r
232                         # e12 > e01 > e20\r
233                         self.iHead=i0\r
234                         self.iTail=i1\r
235                         self.iUp=i2\r
236             self.vHead=vertices[self.iHead]\r
237             self.vTail=vertices[self.iTail]\r
238             self.vUp=vertices[self.iUp]\r
239 \r
240             if self.name.endswith('[]'):\r
241                 basename=self.name[0:-2]\r
242                 # expand LR name\r
243                 if self.vTail.x>0:\r
244                     self.name="%s_L" % basename\r
245                 else:\r
246                     self.name="%s_R" % basename\r
247 \r
248 \r
249         def setParent(self, parent, floating=False):\r
250             if floating:\r
251                 self.isFloating=True\r
252             self.parent=parent\r
253             parent.children.append(self)\r
254 \r
255         def printTree(self, indent=''):\r
256             print("%s%s" % (indent, self.name))\r
257             for child in self.children:\r
258                 child.printTree(indent+'  ')\r
259 \r
260 \r
261     def build_armature(armature, mikotoBone, parent=None):\r
262         """\r
263         create a armature bone.\r
264         """\r
265         bone = Armature.Editbone()\r
266         bone.name = mikotoBone.name.encode('utf-8')\r
267         armature.bones[bone.name] = bone\r
268 \r
269         bone.head = Mathutils.Vector(*mikotoBone.vHead.to_a())\r
270         bone.tail = Mathutils.Vector(*mikotoBone.vTail.to_a())\r
271         if parent:\r
272             bone.parent=parent\r
273             if mikotoBone.isFloating:\r
274                 pass\r
275             else:\r
276                 bone.options=[Armature.CONNECTED]\r
277 \r
278         for child in mikotoBone.children:\r
279             build_armature(armature, child, bone)\r
280 \r
281 \r
282     def create_armature(scene, mqo):\r
283         """\r
284         create armature\r
285         """\r
286         boneObject=None\r
287         for o in mqo.objects:\r
288             if o.name.startswith('bone'):\r
289                 boneObject=o\r
290                 break\r
291         if not boneObject:\r
292             return\r
293 \r
294         tailMap={}\r
295         for f in boneObject.faces:\r
296             if f.index_count!=3:\r
297                 print("invalid index_count: %d" % f.index_count)\r
298                 continue\r
299             b=MikotoBone(f, boneObject.vertices, mqo.materials)\r
300             tailMap[b.iTail]=b\r
301 \r
302         #################### \r
303         # build mikoto bone tree\r
304         #################### \r
305         mikotoRoot=MikotoBone()\r
306 \r
307         for b in tailMap.values():\r
308             # each bone has unique parent or is root bone.\r
309             if b.iHead in tailMap:\r
310                 b.setParent(tailMap[b.iHead])\r
311             else: \r
312                 isFloating=False\r
313                 for e in boneObject.edges:\r
314                     if  b.iHead==e.indices[0]:\r
315                         # floating bone\r
316                         if e.indices[1] in tailMap:\r
317                             b.setParent(tailMap[e.indices[1]], True)\r
318                             isFloating=True\r
319                             break\r
320                     elif b.iHead==e.indices[1]:\r
321                         # floating bone\r
322                         if e.indices[0] in tailMap:\r
323                             b.setParent(tailMap[e.indices[0]], True)\r
324                             isFloating=True\r
325                             break\r
326                 if isFloating:\r
327                     continue\r
328 \r
329                 # no parent bone\r
330                 b.setParent(mikotoRoot, True)\r
331 \r
332         if len(mikotoRoot.children)==0:\r
333             print("no root bone")\r
334             return\r
335 \r
336         if len(mikotoRoot.children)==1:\r
337             # single root\r
338             mikotoRoot=mikotoRoot.children[0]\r
339             mikotoRoot.parent=None\r
340         else:\r
341             mikotoRoot.vHead=Vector3(0, 10, 0)\r
342             mikotoRoot.vTail=Vector3(0, 0, 0)\r
343 \r
344         #################### \r
345         # create armature\r
346         #################### \r
347         armature = Armature.New()\r
348         # link to object\r
349         armature_object = scene.objects.new(armature)\r
350         # create action\r
351         act = Armature.NLA.NewAction()\r
352         act.setActive(armature_object)\r
353         # set XRAY\r
354         armature_object.drawMode |= Object.DrawModes.XRAY\r
355         # armature settings\r
356         armature.drawType = Armature.OCTAHEDRON\r
357         armature.envelopes = False\r
358         armature.vertexGroups = True\r
359         armature.mirrorEdit = True\r
360         armature.drawNames=True\r
361 \r
362         # edit bones\r
363         armature.makeEditable()\r
364         build_armature(armature, mikotoRoot)\r
365         armature.update()\r
366 \r
367         return armature_object\r
368             \r
369 \r
370     class TrianglePlane(object):\r
371         """\r
372         mikoto方式ボーンのアンカーウェイト計算用。\r
373         (不完全)\r
374         """\r
375         __slots__=['normal', \r
376                 'v0', 'v1', 'v2',\r
377                 ]\r
378         def __init__(self, v0, v1, v2):\r
379             self.v0=v0\r
380             self.v1=v1\r
381             self.v2=v2\r
382 \r
383         def isInsideXY(self, p):\r
384             v0=Vector2(self.v0.x, self.v0.y)\r
385             v1=Vector2(self.v1.x, self.v1.y)\r
386             v2=Vector2(self.v2.x, self.v2.y)\r
387             e01=v1-v0\r
388             e12=v2-v1\r
389             e20=v0-v2\r
390             c0=Vector2.cross(e01, p-v0)\r
391             c1=Vector2.cross(e12, p-v1)\r
392             c2=Vector2.cross(e20, p-v2)\r
393             if c0>=0 and c1>=0 and c2>=0:\r
394                 return True\r
395             if c0<=0 and c1<=0 and c2<=0:\r
396                 return True\r
397 \r
398         def isInsideYZ(self, p):\r
399             v0=Vector2(self.v0.y, self.v0.z)\r
400             v1=Vector2(self.v1.y, self.v1.z)\r
401             v2=Vector2(self.v2.y, self.v2.z)\r
402             e01=v1-v0\r
403             e12=v2-v1\r
404             e20=v0-v2\r
405             c0=Vector2.cross(e01, p-v0)\r
406             c1=Vector2.cross(e12, p-v1)\r
407             c2=Vector2.cross(e20, p-v2)\r
408             if c0>=0 and c1>=0 and c2>=0:\r
409                 return True\r
410             if c0<=0 and c1<=0 and c2<=0:\r
411                 return True\r
412 \r
413         def isInsideZX(self, p):\r
414             v0=Vector2(self.v0.z, self.v0.x)\r
415             v1=Vector2(self.v1.z, self.v1.x)\r
416             v2=Vector2(self.v2.z, self.v2.x)\r
417             e01=v1-v0\r
418             e12=v2-v1\r
419             e20=v0-v2\r
420             c0=Vector2.cross(e01, p-v0)\r
421             c1=Vector2.cross(e12, p-v1)\r
422             c2=Vector2.cross(e20, p-v2)\r
423             if c0>=0 and c1>=0 and c2>=0:\r
424                 return True\r
425             if c0<=0 and c1<=0 and c2<=0:\r
426                 return True\r
427 \r
428 \r
429     class MikotoAnchor(object):\r
430         """\r
431         mikoto方式スケルトンのアンカー。\r
432         """\r
433         __slots__=[\r
434                 "triangles", "bbox",\r
435                 ]\r
436         def __init__(self):\r
437             self.triangles=[]\r
438             self.bbox=None\r
439 \r
440         def push(self, face, vertices):\r
441             if face.index_count==3:\r
442                 self.triangles.append(TrianglePlane(\r
443                     vertices[face.indices[0]],\r
444                     vertices[face.indices[1]],\r
445                     vertices[face.indices[2]]\r
446                     ))\r
447             elif face.index_count==4:\r
448                 self.triangles.append(TrianglePlane(\r
449                     vertices[face.indices[0]],\r
450                     vertices[face.indices[1]],\r
451                     vertices[face.indices[2]]\r
452                     ))\r
453                 self.triangles.append(TrianglePlane(\r
454                     vertices[face.indices[2]],\r
455                     vertices[face.indices[3]],\r
456                     vertices[face.indices[0]]\r
457                     ))\r
458             # bounding box\r
459             if not self.bbox:\r
460                 self.bbox=BoundingBox(vertices[face.indices[0]])\r
461             for i in face.indices:\r
462                 self.bbox.expand(vertices[i])\r
463 \r
464 \r
465         def calcWeight(self, v):\r
466             if not self.bbox.isInside(v):\r
467                 return 0\r
468 \r
469             if self.anyXY(v.x, v.y) and self.anyYZ(v.y, v.z) and self.anyZX(v.z, v.x):\r
470                 return 1.0\r
471             else:\r
472                 return 0\r
473             \r
474         def anyXY(self, x, y):\r
475             for t in self.triangles:\r
476                 if t.isInsideXY(Vector2(x, y)):\r
477                     return True\r
478             return False\r
479 \r
480         def anyYZ(self, y, z):\r
481             for t in self.triangles:\r
482                 if t.isInsideYZ(Vector2(y, z)):\r
483                     return True\r
484             return False\r
485 \r
486         def anyZX(self, z, x):\r
487             for t in self.triangles:\r
488                 if t.isInsideZX(Vector2(z, x)):\r
489                     return True\r
490             return False\r
491 \r
492 \r
493     def create_bone_weight(scene, mqo, armature_object, objects):\r
494         """\r
495         create mikoto bone weight.\r
496         """\r
497         anchorMap={}\r
498         # setup mikoto anchors\r
499         for o in mqo.objects:\r
500             if o.name.startswith("anchor"):\r
501                 for f in o.faces:\r
502                     name=mqo.materials[f.material_index].name\r
503                     if name.endswith('[]'):\r
504                         basename=name[0:-2]\r
505                         v=o.vertices[f.indices[0]]\r
506                         if(v.x>0):\r
507                             # L\r
508                             name_L=basename+'_L'\r
509                             if not name_L in anchorMap:\r
510                                 anchorMap[name_L]=MikotoAnchor()\r
511                             anchorMap[name_L].push(f, o.vertices)\r
512                         elif(v.x<0):\r
513                             # R\r
514                             name_R=basename+'_R'\r
515                             if not name_R in anchorMap:\r
516                                 anchorMap[name_R]=MikotoAnchor()\r
517                             anchorMap[name_R].push(f, o.vertices)\r
518                         else:\r
519                             print("no side", v)\r
520                     else:\r
521                         if not name in anchorMap:\r
522                             anchorMap[name]=MikotoAnchor()\r
523                         anchorMap[name].push(f, o.vertices)\r
524 \r
525         for o in objects:\r
526             # add armature modifier\r
527             mod=o.modifiers.append(Modifier.Types.ARMATURE)\r
528             mod[Modifier.Settings.OBJECT] = armature_object\r
529             mod[Modifier.Settings.ENVELOPES] = False\r
530             o.makeDisplayList()\r
531             # create vertex group\r
532             mesh=o.getData(mesh=True)\r
533             for name in anchorMap.keys():\r
534                 mesh.addVertGroup(name)\r
535             mesh.update()\r
536                      \r
537         # assing vertices to vertex group\r
538         for o in objects:\r
539             mesh=o.getData(mesh=True)\r
540             for i, mvert in enumerate(mesh.verts):\r
541                 hasWeight=False\r
542                 for name, anchor in anchorMap.items():\r
543                     weight=anchor.calcWeight(mvert.co)\r
544                     if weight>0:\r
545                         mesh.assignVertsToGroup(\r
546                                 name, [i], weight, Mesh.AssignModes.ADD)\r
547                         hasWeight=True\r
548                 if not hasWeight:\r
549                     # debug orphan vertex\r
550                     print('orphan', mvert)\r
551             mesh.update()\r
552         \r
553 \r
554 \r
555 else:\r
556     def create_objects(scene, mqo, parent, materials, imageMap, scale):\r
557         for o in mqo.objects:\r
558 \r
559             # create mesh\r
560             mesh=bpy.data.meshes.new("Mesh")\r
561             meshObject= bpy.data.objects.new(o.getName(), mesh)\r
562             scene.objects.link(meshObject)\r
563             meshObject.parent=parent\r
564 \r
565             # count triangle and quadrangle\r
566             faceCount=0\r
567             for f in o.faces:\r
568                 if f.index_count==3 or f.index_count==4:\r
569                     faceCount+=1\r
570             mesh.add_geometry(len(o.vertices), 0, faceCount)\r
571 \r
572             # add vertex\r
573             unpackedVertices=[]\r
574             for v in o.vertices:\r
575                 # convert right-handed y-up to right-handed z-up\r
576                 unpackedVertices.extend(\r
577                         (scale*v.x, scale*-v.z, scale*v.y))\r
578             mesh.verts.foreach_set("co", unpackedVertices)\r
579 \r
580             # add face\r
581             unpackedFaces = []\r
582             usedMaterial=set()\r
583 \r
584             def getFace(f):\r
585                 face = []\r
586                 for i in range(f.index_count):\r
587                     face.append(f.getIndex(i))\r
588                 return face\r
589 \r
590             for f in o.faces:\r
591                 face=getFace(f)\r
592                 if len(face) != 3 and len(face) != 4:\r
593                     print("{0} vertices in face.".format(len(face)))\r
594                     continue\r
595 \r
596                 if len(face) == 4:\r
597                     if face[3] == 0:\r
598                         # rotate indices if the 4th is 0\r
599                         face = [face[3], face[0], face[1], face[2]]\r
600                 elif len(face) == 3:\r
601                     if face[2] == 0:\r
602                         # rotate indices if the 3rd is 0\r
603                         face = [face[2], face[0], face[1], 0]\r
604                     else:\r
605                         face.append(0)\r
606 \r
607                 unpackedFaces.extend(face)\r
608                 usedMaterial.add(f.material_index)\r
609             try:\r
610                 mesh.faces.foreach_set("verts_raw", unpackedFaces)\r
611             except:\r
612                 #print([getFace(f) for f in o.faces])\r
613                 print("fail to mesh.faces.foreach_set")\r
614                 return\r
615 \r
616             # add material\r
617             meshMaterialMap={}\r
618             materialIndex=0\r
619             for i in usedMaterial:\r
620                 mesh.add_material(materials[i])\r
621                 meshMaterialMap[i]=materialIndex\r
622                 materialIndex+=1\r
623 \r
624             # each face\r
625             mesh.add_uv_texture()\r
626             for mqo_face, blender_face, uv_face in zip(\r
627                     o.faces, mesh.faces, mesh.uv_textures[0].data):\r
628                 if mqo_face.index_count<3:\r
629                     continue\r
630                 blender_face.material_index=meshMaterialMap[mqo_face.material_index]\r
631                 if mqo_face.index_count>=3:\r
632                     uv_face.uv1=[mqo_face.getUV(0).x, 1.0-mqo_face.getUV(0).y]\r
633                     uv_face.uv2=[mqo_face.getUV(1).x, 1.0-mqo_face.getUV(1).y]\r
634                     uv_face.uv3=[mqo_face.getUV(2).x, 1.0-mqo_face.getUV(2).y]\r
635                     if mqo_face.index_count==4:\r
636                         uv_face.uv4=[\r
637                                 mqo_face.getUV(3).x, 1.0-mqo_face.getUV(3).y]\r
638                 if materials[mqo_face.material_index] in imageMap:\r
639                     uv_face.image=imageMap[mqo_face.material_index]\r
640                     uv_face.tex=True\r
641 \r
642             mesh.update()\r
643 \r
644 \r
645 def __createMaterials(scene, mqo, directory):\r
646     """\r
647     create blender materials and renturn material list.\r
648     """\r
649     materials = []\r
650     textureMap={}\r
651     imageMap={}\r
652     if len(mqo.materials)>0:\r
653         for material_index, m in enumerate(mqo.materials):\r
654             # material\r
655             material=bl.createMaterial(m)\r
656             materials.append(material)\r
657             # texture\r
658             texture_name=m.getTexture()\r
659             if texture_name!='':\r
660                 if texture_name in textureMap:\r
661                     texture=textureMap[texture_name]\r
662                 else:\r
663                     # load texture image\r
664                     if os.path.isabs(texture_name):\r
665                         # absolute\r
666                         path = texture_name\r
667                     else:\r
668                         # relative\r
669                         path = os.path.join(directory, texture_name)\r
670                     # texture\r
671                     if os.path.exists(path):\r
672                         print("create texture:", path)\r
673                         texture, image=bl.createTexture(path)\r
674                         textureMap[texture_name]=texture\r
675                         imageMap[material_index]=image\r
676                     else:\r
677                         print("%s not exits" % path)\r
678                         continue\r
679                 bl.materialAddTexture(material, texture)\r
680     else:\r
681         # default material\r
682         pass\r
683     return materials, imageMap\r
684 \r
685 \r
686 def __execute(filename, scene, scale=1.0):\r
687     # parse file\r
688     io=mqo.IO()\r
689     if not io.read(filename):\r
690         print("fail to load",filename)\r
691         return\r
692 \r
693     # create materials\r
694     materials, imageMap=__createMaterials(scene, io, os.path.dirname(filename))\r
695 \r
696     # create objects\r
697     root=bl.createEmptyObject(scene, os.path.basename(filename))\r
698     objects=create_objects(scene, io, root, materials, imageMap, scale)\r
699 \r
700     if has_mikoto(io):\r
701         # create mikoto bone\r
702         armature_object=create_armature(scene, io)\r
703         if armature_object:\r
704             root.makeParent([armature_object])\r
705 \r
706             # create bone weight\r
707             create_bone_weight(scene, io, armature_object, objects)\r
708 \r
709  \r
710 ###############################################################################\r
711 # register\r
712 ###############################################################################\r
713 if isBlender24():\r
714     def execute_24(filename):\r
715         """\r
716         import a mqo file.\r
717         """\r
718         filename=filename.decode(bl.INTERNAL_ENCODING)\r
719         print("##start mqo_import.py##")\r
720         print(bl.INTERNAL_ENCODING, bl.FS_ENCODING)\r
721         print("parse mqo file: %s" % (filename))\r
722 \r
723         Blender.Window.WaitCursor(1) \r
724         t = Blender.sys.time() \r
725 \r
726         # execute\r
727         scene = Blender.Scene.GetCurrent()\r
728         __execute(filename, scene)\r
729         scene.update(0)\r
730 \r
731         print('finished in %.2f seconds' % (Blender.sys.time()-t))\r
732         print('')\r
733         Blender.Redraw()\r
734         Blender.Window.WaitCursor(0) \r
735 \r
736     # for 2.4\r
737     # execute\r
738     Blender.Window.FileSelector(execute_24, 'Import MQO', '*.mqo')\r
739 else:\r
740     def execute_25(filename, context, scale):\r
741         """\r
742         import a mqo file.\r
743         """\r
744         __execute(filename, context.scene, scale)\r
745 \r
746     # for 2.5\r
747     # import operator\r
748     class IMPORT_OT_mqo(bpy.types.Operator):\r
749         '''Import from Metasequoia file format (.mqo)'''\r
750         bl_idname = "import_scene.mqo"\r
751         bl_label = 'Import MQO'\r
752 \r
753         # List of operator properties, the attributes will be assigned\r
754         # to the class instance from the operator settings before calling.\r
755 \r
756         path = StringProperty(\r
757                 name="File Path", \r
758                 description="File path used for importing the MQO file", \r
759                 maxlen= 1024, default= "")\r
760         filename = StringProperty(\r
761                 name="File Name", \r
762                 description="Name of the file.")\r
763         directory = StringProperty(\r
764                 name="Directory", \r
765                 description="Directory of the file.")\r
766 \r
767         scale = FloatProperty(\r
768                 name="Scale", \r
769                 description="Scale the MQO by this value", \r
770                 min=0.0001, max=1000000.0, \r
771                 soft_min=0.001, soft_max=100.0, default=1.0)\r
772 \r
773         def execute(self, context):\r
774             execute_25(self.properties.path, context, self.properties.scale)\r
775             return 'FINISHED'\r
776 \r
777         def invoke(self, context, event):\r
778             wm=context.manager\r
779             wm.add_fileselect(self)\r
780             return 'RUNNING_MODAL'\r
781 \r
782 \r
783     # register menu\r
784     def menu_func(self, context): \r
785         self.layout.operator(IMPORT_OT_mqo.bl_idname, \r
786                 text="Metasequoia (.mqo)")\r
787 \r
788     def register():\r
789         bpy.types.register(IMPORT_OT_mqo)\r
790         bpy.types.INFO_MT_file_import.append(menu_func)\r
791 \r
792     def unregister():\r
793         bpy.types.unregister(IMPORT_OT_mqo)\r
794         bpy.types.INFO_MT_file_import.remove(menu_func)\r
795 \r
796     if __name__=="__main__":\r
797         register()\r
798 \r