Scripts:
authorWillian Padovani Germano <wpgermano@gmail.com>
Sun, 29 Jan 2006 19:17:53 +0000 (19:17 +0000)
committerWillian Padovani Germano <wpgermano@gmail.com>
Sun, 29 Jan 2006 19:17:53 +0000 (19:17 +0000)
The orange -> HEAD merge reverted some scripts to older versions. This only
affected the ones that already existed before the orange branch.
Minor issue, easy to fix.

All in all, kudos to kaito, Hos and others for all the hard work in
bringing (coding, merging) all these changes to the main branch.

37 files changed:
release/scripts/Apply_def.py
release/scripts/Axiscopy.py
release/scripts/DirectX8Exporter.py
release/scripts/ac3d_export.py
release/scripts/ac3d_import.py
release/scripts/bevel_center.py
release/scripts/bpymodules/meshtools.py
release/scripts/bpymodules/svg2obj.py
release/scripts/bvh2arm.py
release/scripts/bvh_export.py
release/scripts/bvh_import.py
release/scripts/console.py
release/scripts/hotkeys.py
release/scripts/lightwave_export.py
release/scripts/lightwave_import.py
release/scripts/nendo_export.py
release/scripts/nendo_import.py
release/scripts/obj_export.py
release/scripts/obj_import.py
release/scripts/off_export.py
release/scripts/off_import.py
release/scripts/radiosity_export.py
release/scripts/radiosity_import.py
release/scripts/raw_export.py
release/scripts/raw_import.py
release/scripts/save_theme.py
release/scripts/skin.py
release/scripts/slp_import.py
release/scripts/tex2uvbaker.py
release/scripts/truespace_export.py
release/scripts/truespace_import.py
release/scripts/uv_export.py
release/scripts/videoscape_export.py
release/scripts/vrml97_export.py
release/scripts/wings_export.py
release/scripts/wings_import.py
release/scripts/x3d_export.py

index bdcae3744ec4a2e6625b582a3b7c1f5ffa7df417..f0e3c029b5015da0ee523a4ee8a7a11f77b78880 100644 (file)
@@ -54,49 +54,55 @@ directly manipulate or export its data.
 #
 # ***** END GPL LICENCE BLOCK *****
 
+
 import Blender
 
 Blender.Window.EditMode(0)
 
+NAME_LENGTH = 19
+PREFIX = "_def"
+PREFIX_LENGTH = len(PREFIX)
+
 ob_list = Blender.Object.GetSelected()
+
+for ob in ob_list:
+       ob.sel = 0
+
+used_names = [ob.name for ob in Blender.Object.Get()]
+used_names.extend(Blender.NMesh.GetNames())
+
+deformedList = []
 for ob in ob_list:
     if ob.getType() == "Mesh":
         name = ob.getName()
-        new_name = name + "_deformed"
+        new_name = "%s_def" % name[:NAME_LENGTH-PREFIX_LENGTH]
         num = 0
         new_mesh = Blender.NMesh.GetRawFromObject(name)
-        mesh = Blender.NMesh.GetRaw(new_name)
-        while mesh:
+        while new_name in used_names:
+            new_name = "%s_def.%.3i" % (name[:NAME_LENGTH-(PREFIX_LENGTH+PREFIX_LENGTH)], num)
             num += 1
-            new_name = name + "_deformed." + "%03i" % num
-            mesh = Blender.NMesh.GetRaw(new_name)
+        
+        used_names.append(new_name)
+        
         new_ob = Blender.NMesh.PutRaw(new_mesh, new_name)
         new_ob.setMatrix(ob.getMatrix())
-        try:
-            new_ob = Blender.Object.Get(new_name)
-            while 1:
-                num += 1
-                new_name = name + "_deformed." + "%03i" % num
-                new_ob = Blender.Object.Get(new_name)
-        except:
-            pass
         new_ob.setName(new_name)
-
+        deformedList.append(new_ob)
+        
+        # Vert groups.
         ob_mesh = ob.getData()
         new_ob_mesh = new_ob.getData()
-
-        # If SubSurf is off on the original, copy the vertex weight
-        if not ob_mesh.getMode() & Blender.NMesh.Modes['SUBSURF']:
-            for vgroupname in ob_mesh.getVertGroupNames():
+        
+        for vgroupname in ob_mesh.getVertGroupNames():
+            new_ob_mesh.addVertGroup(vgroupname)
+            if len(ob_mesh.verts) == len(new_ob_mesh.verts):
                 vlist = ob_mesh.getVertsFromGroup(vgroupname, True)
-                new_ob_mesh.addVertGroup(vgroupname)
-                for vpair in vlist:
-                    new_ob_mesh.assignVertsToGroup(vgroupname, [vpair[0]], vpair[1], 'add')
-        # If it's on, just add the vertex groups
-        else:
-            for vgroupname in ob_mesh.getVertGroupNames():
-                new_ob_mesh.addVertGroup(vgroupname)
-
-        new_ob_mesh.update()
-
-Blender.Window.EditMode(1)
+                try:
+                    for vpair in vlist:
+                        new_ob_mesh.assignVertsToGroup(vgroupname, [vpair[0]], vpair[1], 'add')
+                except:
+                    pass
+
+for ob in deformedList:
+       ob.sel = 1
+deformedList[0].sel = 1 # Keep the same object active.
\ No newline at end of file
index 0a9a411ef08fadfc60b11fd774142850350adb83..a6fa2e8b6276e1cc97cf5b1c823239c997e9709f 100644 (file)
@@ -2,7 +2,7 @@
 
 """ Registration info for Blender menus: <- these words are ignored
 Name: 'Axis Orientation Copy'
-Blender: 233
+Blender: 239
 Group: 'Object'
 Tip: 'Copy the axis orientation of the active object to all selected mesh objects'
 """
@@ -10,7 +10,7 @@ Tip: 'Copy the axis orientation of the active object to all selected mesh object
 __author__ = "A Vanpoucke (xand)"
 __url__ = ("blender", "elysiun",
 "French Blender support forum, http://www.zoo-logique.org/3D.Blender/newsportal/thread.php?group=3D.Blender")
-__version__ = "1.1 11/05/04"
+__version__ = "2 17/12/05"
 
 __bpydoc__ = """\
 This script copies the axis orientation -- X, Y and Z rotations -- of the
@@ -75,7 +75,7 @@ from Blender.Mathutils import *
 
 def applyTransform(mesh,mat):
   for v in mesh.verts:
-      vec = VecMultMat(v.co,mat)
+      vec = v.co*mat
       v.co[0], v.co[1], v.co[2] = vec[0], vec[1], vec[2]
 
 
@@ -87,13 +87,13 @@ lenob=len(oblist)
 error = 0
 for o in oblist[1:]:
     if o.getType() != "Mesh":
-        Draw.PupMenu("ERROR%t|Selected objects must be meshes")
+        Draw.PupMenu("Error: selected objects must be meshes")
         error = 1
 
 if not error:
     if lenob<2:
-        Draw.PupMenu("ERROR%t|You must select at least 2 objects")
-    else :    
+        Draw.PupMenu("Error: you must select at least 2 objects")
+    else :
         source=oblist[0]
         nsource=source.name
         texte="Copy axis orientation from: " + nsource + " ?%t|OK"
@@ -102,9 +102,9 @@ if not error:
 
         for cible in oblist[1:]:
             if source.rot!=cible.rot:
-                rotcible=cible.mat.toEuler().toMatrix()
-                rotsource=source.mat.toEuler().toMatrix()
-                rotsourcet = CopyMat(rotsource)
+                rotcible=cible.mat.rotationPart().toEuler().toMatrix()
+                rotsource=source.mat.rotationPart().toEuler().toMatrix()
+                rotsourcet = Matrix(rotsource)
                 rotsourcet.invert()
                 mat=rotcible*rotsourcet
                 ncible=cible.name
index bfe6ccbdc889b1afcf8bc180bc7cd6841250df07..0bb436ac86ad3937bc164fa78b2febe443b71773 100644 (file)
@@ -1,17 +1,16 @@
 #!BPY
 
 """ Registration info for Blender menus:
-Name: 'DirectX8(.x)...'
-Blender: 239
+Name: 'DirectX(.x)...'
+Blender: 240
 Group: 'Export'
 Submenu: 'Export all the scene' export
 Submenu: 'Export selected obj' exportsel
-Tip: 'Export to DirectX8 text file format format.'
+Tip: 'Export to DirectX text file format format.'
 """
-
 __author__ = "Arben (Ben) Omari"
 __url__ = ("blender", "elysiun", "Author's site, http://www.omariben.too.it")
-__version__ = "1.0"
+__version__ = "2.0"
 
 __bpydoc__ = """\
 This script exports a Blender mesh with armature to DirectX 8's text file
@@ -21,8 +20,8 @@ Notes:<br>
     Check author's site or the elYsiun forum for a new beta version of the
 DX exporter.
 """
-# DirectX8Exporter.py version 1.0
-# Copyright (C) 2003  Arben OMARI -- omariarben@everyday.com 
+# DirectXExporter.py version 2.0
+# Copyright (C) 2006  Arben OMARI -- omariarben@everyday.com 
 #
 # This program is free software; you can redistribute it and/or modify
 # it under the terms of the GNU General Public License as published by
@@ -42,10 +41,17 @@ DX exporter.
 import Blender
 from Blender import Types, Object, NMesh, Material,Armature
 from Blender.Mathutils import *
+import math
 
-global new_bon,mat_flip,index_list
+global mat_flip,index_list,space,bone_list,mat_dict
+bone_list =[]
 index_list = []
-new_bon = {}
+mat_dict = {}
+space = 0
+ANIM = 1
+NORMAL = 1
+TEXCOORDS = 1
+TEXTURE = 1
 mat_flip = Matrix([1, 0, 0, 0], [0, 1, 0, 0], [0, 0, -1, 0], [0, 0, 0, 1])
                
 
@@ -64,6 +70,7 @@ class xExport:
        #Select Scene objects
        #***********************************************
        def SelectObjs(self):
+               global chld_obj
                print "exporting..."
                self.writeHeader()
                for obj in Object.Get():
@@ -154,115 +161,117 @@ class xExport:
        #Export Root Bone
        #***********************************************
        def writeRootBone(self,am_ob,child_obj):
-               global new_bon,mat_flip
-               space = 0
-               arm = am_ob.getData()
-               Blender.Set('curframe',1)
-               mat_ob = mat_flip * am_ob.matrixWorld
-               self.writeArmFrames(mat_ob, "RootFrame", 0)
-               root_bon = arm.getBones()
-               mat_r = self.writeCombineMatrix(root_bon[0])
-               name_r = root_bon[0].getName()
-               new_bon[name_r] = len(root_bon[0].getChildren())
-               self.writeArmFrames(mat_r, name_r, 1)
-               self.writeListOfChildrens(root_bon[0],2,arm)
-               self.file.write("}\n")
-               self.exportMeshArm(arm,am_ob,child_obj)
+               global mat_flip,space,root_bon,mat_ob
+               arms = am_ob.getData()
+               self.writeArmFrames(mat_flip, "RootFrame")
+               for bon in arms.bones.values():
+                       if bon.hasParent():
+                               pass
+                       else:
+                               root_bon = bon
+               space += 1
+               mat_rb = self.writeCombineMatrix(root_bon)
+               mat_r = mat_rb #* am_ob.matrixLocal
+               name_r = root_bon.name
+               name_f = name_r.replace(".","")
+               self.writeArmFrames(mat_r, name_f)
+               bon_c = self.findChildrens(root_bon)
+               self.writeChildren(bon_c)
+               self.file.write("  }\n")
+               self.exportMeshArm(arms,am_ob,child_obj)
                
        #***********************************************
-       #Export Children Bones
+       #Create Children structure
        #***********************************************
-       def writeListOfChildrens(self,bon,space,arm):
-               global  new_bon
-               bon_c = bon.getChildren()
-               Blender.Set('curframe',1)
-               for n in range(len(bon_c)):
-                       name_h = bon_c[n].getName()
-                       chi_h = bon_c[n].getChildren()
-                       new_bon[name_h] = len(chi_h)
-
-               if bon_c == [] :
-                       self.CloseBrackets(bon, new_bon, space, arm.getBones()[0])
+       def writeBon(self,bon):
+               global space
+               mat_r = self.writeCombineMatrix(bon)
+               name_r = bon.name
+               name_f = name_r.replace(".","")
+               self.writeArmFrames(mat_r, name_f)
                
-               for nch in range(len(bon_c)):
-                       mat = self.writeCombineMatrix(bon_c[nch])
-                       name_ch = bon_c[nch].getName()
-                       self.writeArmFrames(mat, name_ch,space)
-                       self.findChildrens(bon_c[nch],space,arm)
                
+       def findChildrens(self,bon):
+               bon_c = bon.children
+               return bon_c
                
-       #***********************************************
-       #Create Children structure
-       #***********************************************
-       def CloseBrackets(self, bon, new_bon, space, root_bon):
+       
+       def writeChildren(self,bon_c):
+               global space,bone_list
+               space += 1
+               if bon_c:
+                       for bo in bon_c:
+                               if bo.name not in bone_list:
+                                       self.writeBon(bo)
+                                       bone_list.append(bo.name)
+                                       bo_c = bo.children 
+                                       self.writeChildren(bo_c)
+                                       self.closeBrackets()
+                               
+                               
+                                       
+       def closeBrackets(self):
+               global space
+               space = space-1
                tab = "  "
-               self.file.write("%s" % (tab * (space -1)))
+               self.file.write("%s" % (tab * space))
                self.file.write("}\n")
-               while bon.hasParent():
-                       if new_bon[bon.getName()] == 0:
-                               pare = bon.getParent()
-                               name_p = pare.getName()
-                               if new_bon[name_p] > 0:
-                                       new_bon[name_p] = new_bon[name_p] - 1
-                               if new_bon[name_p] == 0 and pare != root_bon:
-                                       self.file.write("%s" % (tab * (space-2)))
-                                       self.file.write("}\n")
-                               space = space - 1
-                               bon = pare
-                       else:
-                               break
+               
                
                        
-       #***********************************************
-       #Create Children structure
-       #***********************************************
-       def findChildrens(self,bon_c,space,arm):
-               bon_cc = bon_c
-               space += 1
-               self.writeListOfChildrens(bon_cc,space,arm)
-       
-       
        #***********************************************
        #Offset Matrix
        #***********************************************
        def writeMatrixOffset(self,bon):
-               Blender.Set('curframe',1)
-               mat_b = bon.getRestMatrix()       
-               mat_b.invert() 
+               global  chld_obj
+               Blender.Set('curframe', 1)
+               pose = chld_obj.getPose()
+               pos_b = pose.bones[bon.name]
+               mat_b = pos_b.poseMatrix
+               mat_b.invert()
                return mat_b
 
-
        
-
        #***********************************************
        #Combine Matrix
        #***********************************************
        def writeCombineMatrix(self,bon):
-               Blender.Set('curframe',1)
-               mat_b = bon.getRestMatrix()     
+               global  chld_obj
+               Blender.Set('curframe', 1)
+               pose = chld_obj.getPose()
+               pos_b = pose.bones[bon.name]
+               mat_b = pos_b.poseMatrix
                if bon.hasParent():
-                       pare = bon.getParent()
-                       mat_p = pare.getRestMatrix()
-               else :
+                       pare = bon.parent
+                       pos_p = pose.bones[pare.name]
+                       mat_p = pos_p.poseMatrix
+                       
+               else:
                        mat_p = Matrix([1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1])
                mat_p.invert()
-               mat_rb = mat_b * mat_p
-               return mat_rb
-
+               mat_f = mat_b * mat_p
+               
+               return mat_f
        #***********************************************
        #Combine Matrix
        #***********************************************
-       def writeCombineAnimMatrix(self,bon):
-               
-               mat_b = bon.getRestMatrix()     
+       def writeAnimCombineMatrix(self,bon,fre):
+               global  chld_obj
+               Blender.Set('curframe', fre)
+               pose = chld_obj.getPose()
+               pos_b = pose.bones[bon.name]
+               mat_b = pos_b.poseMatrix
                if bon.hasParent():
-                       pare = bon.getParent()
-                       mat_p = pare.getRestMatrix()
-               else :
+                       pare = bon.parent
+                       pos_p = pose.bones[pare.name]
+                       mat_p = pos_p.poseMatrix
+                       
+               else:
                        mat_p = Matrix([1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1])
                mat_p.invert()
-               mat_rb = mat_b * mat_p
-               return mat_rb
+               mat_f = mat_b * mat_p
+               
+               return mat_f
 
 
 #*********************************************************************************************************************************************
@@ -271,16 +280,23 @@ class xExport:
        #***********************************************
        def writeSkinWeights(self, arm, mesh):
                global index_list
-               
+               v_dict = {}
                Blender.Set('curframe',1)
                self.file.write("  XSkinMeshHeader {\n")
                max_infl = 0
-               for bo in arm.getBones() :
-                       name = bo.getName() 
+               #this part supply the missing getVertexInfluences(index)
+               for v in index_list:
+                               v_dict[v] = []
+               for bo in arm.bones.values() :
+                       name = bo.name
+                       
                        try :
                                vertx_list = mesh.getVertsFromGroup(name,1)
+                               for vn in vertx_list:
+                                       v_dict[vn[0]].append(name)
+                               #---------------------------------------------------
                                for inde in vertx_list :
-                                       vert_infl = mesh.getVertexInfluences(inde[0])
+                                       vert_infl = v_dict[inde[0]]
                                        ln_infl = len(vert_infl)
                                        if ln_infl > max_infl :
                                                max_infl = ln_infl
@@ -288,20 +304,21 @@ class xExport:
                        except:
                                pass
                
-               self.file.write("    %s; \n" % (max_infl))
-               self.file.write("    %s; \n" % (max_infl * 3))
-               self.file.write("    %s; \n" % (len(arm.getBones())))
+               self.file.write("    %d; \n" % (max_infl))
+               self.file.write("    %d; \n" % (max_infl * 3))
+               self.file.write("    %d; \n" % (len(arm.bones.values())))
                self.file.write("  }\n")
                
-               for bo in arm.getBones() :
+               for bo in arm.bones.values() :
                        bo_list = []
                        weight_list = []
-                       name = bo.getName() 
+                       name = bo.name 
+                       f_name = name.replace(".","")
                        try :
                                vert_list = mesh.getVertsFromGroup(name,1)
                                le = 0
                                for indx in vert_list:
-                                       ver_infl = mesh.getVertexInfluences(indx[0])
+                                       ver_infl = v_dict[indx[0]]
                                        len_infl = float(len(ver_infl))
                                        infl = 1 / len_infl
                                        i = -1
@@ -314,28 +331,27 @@ class xExport:
 
 
                                self.file.write("  SkinWeights {\n")
-                               self.file.write('    "%s"; \n' % (name))
-                               self.file.write('     %s; \n' % (le))
+                               self.file.write('    "%s"; \n' % (f_name))
+                               self.file.write('     %d; \n' % (le))
                                count = 0
                                for ind in bo_list :
                                        count += 1
                                        if count == len(bo_list):
-                                               self.file.write("    %s; \n" % (ind))
+                                               self.file.write("    %d; \n" % (ind))
                                        else :
-                                               self.file.write("    %s, \n" % (ind))
+                                               self.file.write("    %d, \n" % (ind))
                                cou = 0
                                for wegh in weight_list :
                                        cou += 1
                                        
                                        if cou == len(weight_list):
-                                               self.file.write("    %s; \n" % (round(wegh,6)))
+                                               self.file.write("    %f; \n" % (round(wegh,6)))
                                        else :
-                                               self.file.write("    %s, \n" % (round(wegh,6)))
+                                               self.file.write("    %f, \n" % (round(wegh,6)))
 
                        
                                matx = self.writeMatrixOffset(bo)
-                       
-                               self.writeOffsFrames(matx, name, 1)
+                               self.writeOffsFrames(matx, name)
                        except :
                                pass
                self.file.write("  }\n")
@@ -344,7 +360,8 @@ class xExport:
        #***********************************************
        # Write Matrices
        #***********************************************
-       def writeArmFrames(self, matx, name, space):
+       def writeArmFrames(self, matx, name):
+               global space
                tab = "  "
                self.file.write("%s" % (tab * space))
                self.file.write("Frame ")  
@@ -352,16 +369,16 @@ class xExport:
                self.file.write("%s" % (tab * space))
                self.file.write("  FrameTransformMatrix {\n")
                self.file.write("%s" % (tab * space))
-               self.file.write("    %s,%s,%s,%s,\n" %
+               self.file.write("    %f,%f,%f,%f,\n" %
                                                        (round(matx[0][0],4),round(matx[0][1],4),round(matx[0][2],4),round(matx[0][3],4)))
                self.file.write("%s" % (tab * space))
-               self.file.write("    %s,%s,%s,%s,\n" %
+               self.file.write("    %f,%f,%f,%f,\n" %
                                                        (round(matx[1][0],4),round(matx[1][1],4),round(matx[1][2],4),round(matx[1][3],4)))
                self.file.write("%s" % (tab * space))   
-               self.file.write("    %s,%s,%s,%s,\n" %
+               self.file.write("    %f,%f,%f,%f,\n" %
                                                        (round(matx[2][0],4),round(matx[2][1],4),round(matx[2][2],4),round(matx[2][3],4)))
                self.file.write("%s" % (tab * space))
-               self.file.write("    %s,%s,%s,%s;;\n" %
+               self.file.write("    %f,%f,%f,%f;;\n" %
                                                        (round(matx[3][0],4),round(matx[3][1],4),round(matx[3][2],4),round(matx[3][3],6)))
                self.file.write("%s" % (tab * space))
                self.file.write("  }\n")
@@ -369,19 +386,20 @@ class xExport:
        #***********************************************
        # Write Matrices
        #***********************************************
-       def writeOffsFrames(self, matx, name, space):
+       def writeOffsFrames(self, matx, name):
+               space = 1
                tab = "  "
                self.file.write("%s" % (tab * space))
-               self.file.write("    %s,%s,%s,%s,\n" %
+               self.file.write("    %f,%f,%f,%f,\n" %
                                                        (round(matx[0][0],4),round(matx[0][1],4),round(matx[0][2],4),round(matx[0][3],4)))
                self.file.write("%s" % (tab * space))
-               self.file.write("    %s,%s,%s,%s,\n" %
+               self.file.write("    %f,%f,%f,%f,\n" %
                                                        (round(matx[1][0],4),round(matx[1][1],4),round(matx[1][2],4),round(matx[1][3],4)))
                self.file.write("%s" % (tab * space))   
-               self.file.write("    %s,%s,%s,%s,\n" %
+               self.file.write("    %f,%f,%f,%f,\n" %
                                                        (round(matx[2][0],4),round(matx[2][1],4),round(matx[2][2],4),round(matx[2][3],4)))
                self.file.write("%s" % (tab * space))
-               self.file.write("    %s,%s,%s,%s;;\n" %
+               self.file.write("    %f,%f,%f,%f;;\n" %
                                                        (round(matx[3][0],4),round(matx[3][1],4),round(matx[3][2],4),round(matx[3][3],6)))
                self.file.write("%s" % (tab * space))
                self.file.write("  }\n")
@@ -445,7 +463,8 @@ template SkinWeights {\n\
                mat_ob.invert()
                mat = mat_arm * mat_ob
                mat.invert()
-               self.writeArmFrames(mat, name.name, 1)
+               name_f = name.name.replace(".","")
+               self.writeArmFrames(mat, name_f)
                mesh = NMesh.GetRawFromObject(name.name)
                self.file.write("Mesh {\n")    
                numface=len(mesh.faces)
@@ -461,8 +480,8 @@ template SkinWeights {\n\
                        for n in range(len(face.v)):
                                index_list.append(face.v[n].index)
                                vec_vert = Vector([face.v[n].co[0], face.v[n].co[1], face.v[n].co[2], 1])
-                               f_vec_vert = VecMultMat(vec_vert, mat)
-                               self.file.write("%s; %s; %s;" % (f_vec_vert[0], f_vec_vert[1], f_vec_vert[2]))
+                               f_vec_vert = vec_vert * mat
+                               self.file.write("%f; %f; %f;" % (round(f_vec_vert[0],4), round(f_vec_vert[1],4), round(f_vec_vert[2],4)))
                                if counter == numface :
                                        if n == len(face.v)-1 :
                                                self.file.write(";\n")
@@ -505,7 +524,8 @@ template SkinWeights {\n\
                global index_list
                #ROTATION
                mat_ob = mat_flip * name.matrixWorld
-               self.writeArmFrames(mat_ob, name.name, 0)
+               name_f = name.name.replace(".","")
+               self.writeArmFrames(mat_ob, name_f)
 
                self.file.write("Mesh {\n")    
                numface=len(mesh.faces)
@@ -589,10 +609,9 @@ template SkinWeights {\n\
                ##MATERIAL NAME
                for mat in Material.Get():
                        self.file.write("  Material")
-                       for a in range(0,len(mat.name)):
-                               if mat.name[a] == ".":
-                                       print "WARNING:the material " + mat.name + " contains '.' within.Many viewers may refuse to read the exported file"
-                       self.file.write(" %s "% (mat.name))
+                       name_m = mat.name
+                       name_f = name_m.replace(".","")
+                       self.file.write(" %s "% (name_f))
                        self.file.write("{\n")
                        self.file.write("    %s; %s; %s;" % (mat.R, mat.G, mat.B))
                        self.file.write("%s;;\n" % (mat.alpha))
@@ -609,7 +628,7 @@ template SkinWeights {\n\
                        self.file.write("    1.0;\n")
                        self.file.write("    1.0; 1.0; 1.0;;\n")
                        self.file.write("    0.0; 0.0; 0.0;;\n")
-                       self.file.write("  TextureFilename {\n")
+                       self.file.write("  TextureFilename {")
                        self.file.write('    "%s" ;'% (mat))
                        self.file.write("  }\n")
                        self.file.write("  }\n") 
@@ -711,47 +730,45 @@ template SkinWeights {\n\
                
                
                
-               
+       
+       
        #***********************************************
        #WRITE ANIMATION KEYS
        #***********************************************
        def writeAnimation(self,arm_ob):
+               global mat_dict
                arm = arm_ob.getData()
                act_list = arm_ob.getAction()
                ip = act_list.getAllChannelIpos()
-               for bon in arm.getBones() :
+               for bon in arm.bones.values() :
                        point_list = []
+                       name = bon.name
+                       name_f = name.replace(".", "")
                        try :
                                ip_bon_channel = ip[bon.name]
                                ip_bon_name = ip_bon_channel.getName()
-                       
+                               
                                ip_bon = Blender.Ipo.Get(ip_bon_name)
                                poi = ip_bon.getCurves()
+                               
                                for po in poi[3].getPoints():
                                        a = po.getPoints()
                                        point_list.append(int(a[0]))
-                               point_list.pop(0) 
-                       
-                       
+                               #point_list.pop(0) 
+                               
                                self.file.write(" Animation { \n")
-                               self.file.write("  {%s}\n" %(bon.getName()))
+                               self.file.write("  {%s}\n" %(name_f))
                                self.file.write("  AnimationKey { \n")
                                self.file.write("   4;\n")
-                               self.file.write("   %s; \n" % (len(point_list)+1))
-
-                               self.file.write("   %s;" % (1))
-                               self.file.write("16;")
-                               mat = self.writeCombineMatrix(bon)
-                               self.writeFrames(mat)
-                               self.file.write(",\n")
+                               self.file.write("   %s; \n" % (len(point_list)))
 
                                for fr in point_list:
+                                       mat = self.writeAnimCombineMatrix(bon,fr)       
+                                       
                                        self.file.write("   %s;" % (fr))
                                        self.file.write("16;")
-                                       Blender.Set('curframe',fr)
                                
-                                       mat_new = self.writeCombineAnimMatrix(bon)
-                                       self.writeFrames(mat_new)
+                                       self.writeFrames(mat)
                                
                                        if fr == point_list[len(point_list)-1]:
                                                self.file.write(";\n")
@@ -864,8 +881,8 @@ arg = __script__['arg']
 
 if arg == 'exportsel':
        fname = Blender.sys.makename(ext = ".x")
-       Blender.Window.FileSelector(my_callback_sel, "Export DirectX8", fname)  
+       Blender.Window.FileSelector(my_callback_sel, "Export DirectX", fname)   
 else:
        fname = Blender.sys.makename(ext = ".x")
-       Blender.Window.FileSelector(my_callback, "Export DirectX8", fname)      
-       
+       Blender.Window.FileSelector(my_callback, "Export DirectX", fname)       
+       
\ No newline at end of file
index b9b7b8e5ae6081bc1a12fb516a3f2bfd77a7a936..ea9ba239003614ee022fe14f5ceea054aad7ce42 100644 (file)
@@ -202,7 +202,8 @@ def transform_verts(verts, m):
        vecs = []
        for v in verts:
                vec = Mathutils.Vector([v[0],v[1],v[2], 1])
-               vecs.append(Mathutils.VecMultMat(vec, m))
+               #vecs.append(Mathutils.VecMultMat(vec, m))
+               vecs.append(vec*m)
        return vecs
 
 # ---
index d2505022adf88a44af67b28e834cf1f042ff7e9f..4dcde65fb4af78a9b17c3abe18d78b89385edba4 100644 (file)
@@ -10,7 +10,7 @@ Tip: 'Import an AC3D (.ac) file.'
 __author__ = "Willian P. Germano"
 __url__ = ("blender", "elysiun", "AC3D's homepage, http://www.ac3d.org",
        "PLib 3d gaming lib, http://plib.sf.net")
-__version__ = "2.36 2005-04-14"
+__version__ = "2.36a 2005-12-04"
 
 __bpydoc__ = """\
 This script imports AC3D models into Blender.
@@ -43,9 +43,9 @@ users can configure (see config options above).
 # $Id$
 #
 # --------------------------------------------------------------------------
-# AC3DImport version 2.36 Apr 14, 2005
+# AC3DImport version 2.36a Dec 04, 2005
 # Program versions: Blender 2.36+ and AC3Db files (means version 0xb)
-# changed: updated to use the Scripts Config Editor facilities
+# changed: fixed a bug: error on 1 vertex "closed" polylines
 # --------------------------------------------------------------------------
 # ***** BEGIN GPL LICENSE BLOCK *****
 #
@@ -366,7 +366,7 @@ class AC3DImport:
                                        faces.append(cut)
                                        face = face[1:]
 
-                               if flaglow == 1:
+                               if flaglow == 1 and faces:
                                        face = [faces[-1][-1], faces[0][0]]
                                        faces.append(face)
 
@@ -498,7 +498,9 @@ class AC3DImport:
                                for vi in range(len(f)):
                                        bface.v.append(mesh.verts[f[vi][0]])
                                        bface.uv.append((f[vi][1][0], f[vi][1][1]))
-                               mesh.faces.append(bface)
+                               #mesh.faces.append(bface)
+                               # quick hack, will switch from NMesh to Mesh later:
+                               if len(bface.v) > 1: mesh.addFace(bface)
 
                        mesh.mode = 0
                        object = Blender.NMesh.PutRaw(mesh)
index 6025cef7f0e11f1e41da9a25e143542dbb005928..1e3fb3c78d742e688d9d07cc240906956070652f 100644 (file)
@@ -2,21 +2,21 @@
 
 """ Registration info for Blender menus
 Name: 'Bevel Center'
-Blender: 236
+Blender: 240
 Group: 'Mesh'
-Tip: 'Bevel selected vertices'
+Tip: 'Bevel selected faces, edges, and vertices'
 """
 
-__author__ = "Loic Berthe"
+__author__ = "Loic BERTHE"
 __url__ = ("blender", "elysiun")
-__version__ = "1.0"
+__version__ = "2.0"
 
 __bpydoc__ = """\
-This script implements vertex bevelling in Blender.
+This script implements vertex and edges bevelling in Blender.
 
 Usage:
 
-Select the mesh you want to work on, enter Edit Mode and select the vertices
+Select the mesh you want to work on, enter Edit Mode and select the edges
 to bevel.  Then run this script from the 3d View's Mesh->Scripts menu.
 
 You can control the thickness of the bevel with the slider -- redefine the
@@ -24,358 +24,295 @@ end points for bigger or smaller ranges.  The thickness can be changed even
 after applying the bevel, as many times as needed.
 
 For an extra smoothing after or instead of direct bevel, set the level of
-recursiveness and use the "Recursive" button.
+recursiveness and use the "Recursive" button. 
+
+This "Recursive" Button, won't work in face select mode, unless you choose
+"faces" in the select mode menu.
 
 Notes:<br>
-    You can undo and redo your steps just like with normal mesh operations in
+       You can undo and redo your steps just like with normal mesh operations in
 Blender.
 """
 
-# $Id$
-#
 ######################################################################
-# Bevel Center v1 for Blender
-#
-# This script lets you bevel the selected vertices and control the
+# Bevel Center v2.0 for Blender
+
+# This script lets you bevel the selected vertices or edges and control the
 # thickness of the bevel
-#
-# (c) 2004 Loïc Berthe (loic.berthe@lilotux.net)
+
+# (c) 2004-2006 Loïc Berthe (loic+blender@lilotux.net)
 # released under Blender Artistic License
-#
+
 ######################################################################
 
 import Blender
-from Blender import NMesh, Window
+from Blender import NMesh, Window, Scene
 from Blender.Draw import *
+from Blender.Mathutils import *
 from Blender.BGL import *
 
-from math import pi, sin, sqrt
-
 ######################################################################
-# Functions to handle the global structures of the script NV, NE and NC
-# which contain informations about the vertices, faces and corners to be
-# created
-
-class Dir:
-       def __init__(self, co):
-               self.co = co
-
-def add_to_NV(old,co,new):
-       dir = Dir(co)
-       #
-       if old in NV.keys():
-               NV[old][dir] = new
-       else:
-               NV[old] = {dir:new}
-
-def is_in_NV(old,co):
-       if old in NV.keys():
-               for dir in NV[old]:
-                       if dir.co == co : return NV[old][dir]
-       #
-       return False
-
-def add_to_NE(old, new):
-       ind1 = old[0].index
-       ind2 = old[1].index
-       if ind1 > ind2:
-               new.reverse()
-               ind1,ind2 = ind2,ind1
-       id = str(ind1)+"_"+str(ind2)
-       if id in NE.keys():
-               [NE[id].append(v) for v in new]
-       else:
-               NE[id] = new
-
-def add_to_NC(old,edge):
-       if old in NC.keys():
-               NC[old].append(edge)
-       else:
-               NC[old] = [edge]
-               
-######################################################################
-# Geometric functions
-               
-def norm(vec):
-       n = sqrt(vec[0]**2+vec[1]**2+vec[2]**2)
-       return [vec[0]/n,vec[1]/n,vec[2]/n]
-
-def parall_coord(old, dir):
-       co = old.co
-       vec = [0.0,0.0,0.0]
-       nco = [0.0,0.0,0.0]
-       #
-       if len(dir) == 1:
-               for i in range(3): vec[i] = dir[0].co[i] - co[i] 
-               vec = norm(vec)
-       #
-       elif len(dir) == 2:
-               vec1 = [0.0,0.0,0.0]
-               vec2 = [0.0,0.0,0.0]
-               for i in range(3):
-                       vec1[i] = dir[0].co[i] - co[i] 
-                       vec2[i] = dir[1].co[i] - co[i] 
-               vec1 = norm(vec1)
-               vec2 = norm(vec2)
-               for i in range(3) : vec[i] = vec1[i]+vec2[i]
-       #
-       for i in range(3): nco[i] = co[i] + dist.val*vec[i]
-       return (nco,vec)
-
-def get_vert(old, dir):
-       """ Look in NV if a vertice corresponding to the vertex old and the
-       direction dir already exists, and create one otherwise""" 
-       (nco, vec) = parall_coord(old, dir)
-       v = is_in_NV(old,vec)
-       if v: return v
-       #
-       v = NMesh.Vert(nco[0],nco[1],nco[2])
-       v.sel = 1
+# Functions to handle the global structures of the script NF, NE and NC
+# which contain informations about faces and corners to be created
+
+global E_selected
+E_selected = NMesh.EdgeFlags['SELECT']
+
+def make_sel_vert(*co):
+       vi= NMesh.Vert(*co)
+       v.sel = 1 
        me.verts.append(v)
-       add_to_NV(old,vec,v)
        return v
-                       
-######################################################################
-# Functions to create the differents faces
+
+def make_sel_face(verts):
+       f = NMesh.Face(verts)
+       f.sel = 1
+       me.addFace(f)
+
+def add_to_NV(old,dir,new):
+       if old in NV.keys():            NV[old][dir] = new
+       else:                                      NV[old] = {dir:new}
+
+def get_v(old, *neighbors):
+
+       # compute the direction of the new vert
+       if len(neighbors) == 1 : dir = (neighbors[0].co - old.co).normalize()
+       else : dir = (neighbors[0].co - old.co).normalize() + (neighbors[1].co-old.co).normalize()
+        
+       # look in NV if this vert already exists
+       key = tuple(dir)
+       if old in NV and key in NV[old] : return NV[old][key]
        
-def make_NF():
-       """ Analyse the mesh, sort the faces containing selected vertices and
-       create a liste NF : NF = [[flag, vertlist, old_face]]. Flag describes the
-       topology of the face.""" 
-       #
+       # else, create it 
+       new = old.co + dist.val*dir
+       v = make_sel_vert(new.x,new.y,new.z)
+       add_to_NV(old,key,v)
+       return v
+
+def make_faces():
+       """ Analyse the mesh, make the faces corresponding to selected faces and
+       fill the structures NE and NC """
+
+       # make the differents flags consistent
+       for e in me.edges:
+               if e.flag & E_selected :
+                       e.v1.sel = 1
+                       e.v2.sel = 1
+       
+       NF =[]                    # NF : New faces
        for f in me.faces:
                V = f.v
-               v_sel = [x.sel for x in V]
-               nb_sel = sum(v_sel)
-               if nb_sel == 0 :
-                       pass
-               else:
-                       nb_v = len(V)
-                       #
-                       if nb_v == 4:
-                               #
-                               if nb_sel == 4:
-                                       NF.append([1,V,f])
-                               #
-                               elif nb_sel == 3:
-                                       if v_sel == [0,1,1,1]: V = [V[1],V[2],V[3],V[0]]
-                                       elif v_sel == [1,0,1,1]: V = [V[2],V[3],V[0],V[1]]
-                                       elif v_sel == [1,1,0,1]: V = [V[3],V[0],V[1],V[2]]
-                                       NF.append([2,V,f])
-                               #               
-                               elif nb_sel == 2:
-                                       if v_sel == [1,0,1,0] or v_sel == [0,1,0,1]:
-                                               if      v_sel == [0,1,0,1]: V = [V[1],V[2],V[3],V[0]]
-                                               NF.append([5,[V[0],V[1],V[3]],f])
-                                               NF.append([5,[V[2],V[1],V[3]]])
-                                       else:
-                                               if v_sel == [0,1,1,0]: V = [V[1],V[2],V[3],V[0]]
-                                               elif v_sel == [0,0,1,1]: V = [V[2],V[3],V[0],V[1]]
-                                               elif v_sel == [1,0,0,1]: V = [V[3],V[0],V[1],V[2]]
-                                               NF.append([3,V,f])
-                               #
-                               else:
-                                       if v_sel == [0,1,0,0]: V = [V[1],V[2],V[3],V[0]]
-                                       elif v_sel == [0,0,1,0]: V = [V[2],V[3],V[0],V[1]]
-                                       elif v_sel == [0,0,0,1]: V = [V[3],V[0],V[1],V[2]]
-                                       NF.append([4,V,f])
-                       #
-                       elif nb_v == 3:
-                               #
-                               if nb_sel == 3:
-                                       NF.append([6,V,f])
-                               #
-                               elif nb_sel == 2:
-                                       if v_sel == [0,1,1]: V = [V[1],V[2],V[0]]
-                                       elif v_sel == [1,0,1]: V = [V[2],V[0],V[1]]
-                                       NF.append([7,V,f])
-                               #
-                               else:
-                                       if v_sel == [0,1,0]: V = [V[1],V[2],V[0]]
-                                       elif v_sel == [0,0,1]: V = [V[2],V[0],V[1]]
-                                       NF.append([5,V,f])
+               nV = len(V)
+               enumV = range(nV)
+               E = [me.findEdge(V[i],V[(i+1) % nV]) for i in enumV]
+               Esel = [x.flag & E_selected for x in E]
+               
+               # look for selected vertices and creates a list containing the new vertices
+               newV = V[:] 
+               changes = False
+               for (i,v) in enumerate(V):
+                       if v.sel :
+                               changes = True
+                               if   Esel[i-1] == 0 and Esel[i] == 1 :  newV[i] = get_v(v,V[i-1])
+                               elif Esel[i-1] == 1 and Esel[i] == 0 :  newV[i] = get_v(v,V[(i+1) % nV])
+                               elif Esel[i-1] == 1 and Esel[i] == 1 :  newV[i] = get_v(v,V[i-1],V[(i+1) % nV])
+                               else :                                                            newV[i] = [get_v(v,V[i-1]),get_v(v,V[(i+1) % nV])]
+               
+               if changes:
+                       # determine and store the face to be created
 
-def make_faces():
-       """ Make the new faces according to NF """
-       #
-       for N in NF:
-               cas = N[0]
-               V = N[1]
-               #
-               if cas < 6:
-                       new_v = [0,0,0,0]
-                       if cas == 1:                            # v_sel = [1,1,1,1]
-                               for i in range(-1,3):
-                                       new_v[i] = get_vert(V[i],[V[i-1],V[i+1]])
-                               new_f = NMesh.Face(new_v)
-                               me.faces.append(new_f)
-                               for i in range(-1,3):
-                                       add_to_NE([V[i],V[i+1]],[new_v[i],new_v[i+1]])
-                       #
-                       elif cas == 2:                          # v_sel = [1,1,1,0]
-                               new_v[0] = get_vert(V[0],[V[3]])
-                               new_v[1] = get_vert(V[1],[V[0],V[2]])
-                               new_v[2] = get_vert(V[2],[V[3]])
-                               new_v[3] = V[3]
-                               #
-                               new_f = NMesh.Face(new_v)
-                               me.faces.append(new_f)
-                               #
-                               add_to_NE([V[0],V[1]],[new_v[0],new_v[1]])
-                               add_to_NE([V[1],V[2]],[new_v[1],new_v[2]])
-                       #               
-                       elif cas == 3:                          # v_sel = [1,1,0,0]
-                               new_v[0] = get_vert(V[0],[V[3]])
-                               new_v[1] = get_vert(V[1],[V[2]])
-                               new_v[2] = V[2]
-                               new_v[3] = V[3]
-                               #
-                               new_f = NMesh.Face(new_v)
-                               me.faces.append(new_f)
-                               #
-                               add_to_NE([V[0],V[1]],[new_v[0],new_v[1]])
-                       #
-                       elif cas == 4:                          # v_sel = [1,0,0,0]
-                               new_v[0] = get_vert(V[0],[V[3]])
-                               new_v[1] = get_vert(V[0],[V[1]])
-                               new_v[2] = V[1]
-                               new_v[3] = V[3]
-                               #
-                               new_f = NMesh.Face(new_v)
-                               me.faces.append(new_f)
-                               #
-                               add_to_NC(V[0], new_v[0:2])
-                               #
-                               new_v[0] = V[1]
-                               new_v[1] = V[2]
-                               new_v[2] = V[3]
-                               #
-                               new_f = NMesh.Face(new_v[:3])
-                               me.faces.append(new_f)
-                       #
-                       else:                           # v_sel = [1,0,0]
-                               new_v[0] = get_vert(V[0],[V[2]])
-                               new_v[1] = get_vert(V[0],[V[1]])
-                               new_v[2] = V[1]
-                               new_v[3] = V[2]
-                               #
-                               new_f = NMesh.Face(new_v)
-                               me.faces.append(new_f)
-                               #
-                               add_to_NC(V[0], new_v[0:2])
-               #
-               else:
-                       new_v = [0,0,0]
-                       #
-                       if cas == 6:                            # v_sel = [1,1,1]
-                               for i in range(-1,2):
-                                       new_v[i] = get_vert(V[i],[V[i-1],V[i+1]])
-                               new_f = NMesh.Face(new_v)
-                               me.faces.append(new_f)
-                               for i in range(-1,2):
-                                       add_to_NE([V[i],V[i+1]],[new_v[i],new_v[i+1]])
-                       #
-                       elif cas == 7:                          # v_sel = [1,1,0]
-                               new_v[0] = get_vert(V[0],[V[2]])
-                               new_v[1] = get_vert(V[1],[V[2]])
-                               new_v[2] = V[2]
-                               #
-                               new_f = NMesh.Face(new_v)
-                               me.faces.append(new_f)
-                               add_to_NE([V[0],V[1]],[new_v[0],new_v[1]])
+                       lenV = [len(x) for x in newV]
+                       
+                       if 2 not in lenV :                        
+                               new_f = NMesh.Face(newV)
+                               if sum(Esel) == nV : new_f.sel = 1
+                               NF.append(new_f)
+                               
+                       else :
+                               nb2 = lenV.count(2)
+                               
+                               if nV == 4 :                            # f is a quad
+                                       if nb2 == 1 :
+                                               ind2 = lenV.index(2)
+                                               NF.append(NMesh.Face([newV[ind2-1],newV[ind2][0],newV[ind2][1],newV[ind2-3]]))
+                                               NF.append(NMesh.Face([newV[ind2-1],newV[ind2-2],newV[ind2-3]]))
+                                       
+                                       elif nb2 == 2 :
+                                               # We must know if the tuples are neighbours
+                                               ind2 = ''.join([str(x) for x in lenV+lenV[:1]]).find('22')
+                                               
+                                               if ind2 != -1 :  # They are 
+                                                       NF.append(NMesh.Face([newV[ind2][0],newV[ind2][1],newV[ind2-3][0],newV[ind2-3][1]]))
+                                                       NF.append(NMesh.Face([newV[ind2][0],newV[ind2-1],newV[ind2-2],newV[ind2-3][1]]))
+                                               
+                                               else:                      # They aren't
+                                                       ind2 = lenV.index(2)
+                                                       NF.append(NMesh.Face([newV[ind2][0],newV[ind2][1],newV[ind2-2][0],newV[ind2-2][1]]))
+                                                       NF.append(NMesh.Face([newV[ind2][1],newV[ind2-3],newV[ind2-2][0]]))
+                                                       NF.append(NMesh.Face([newV[ind2][0],newV[ind2-1],newV[ind2-2][1]]))
+                                       
+                                       elif nb2 == 3 :
+                                               ind2 = lenV.index(3)
+                                               NF.append(NMesh.Face([newV[ind2-1][1],newV[ind2],newV[ind2-3][0]]))
+                                               NF.append(NMesh.Face([newV[ind2-1][0],newV[ind2-1][1],newV[ind2-3][0],newV[ind2-3][1]]))
+                                               NF.append(NMesh.Face([newV[ind2-3][1],newV[ind2-2][0],newV[ind2-2][1],newV[ind2-1][0]]))
+                                       
+                                       else:
+                                               if      (newV[0][1].co-newV[3][0].co).length + (newV[1][0].co-newV[2][1].co).length \
+                                                       < (newV[0][0].co-newV[1][1].co).length + (newV[2][0].co-newV[3][1].co).length :
+                                                       ind2 = 0
+                                               else :
+                                                       ind2 = 1
+                                               NF.append(NMesh.Face([newV[ind2-1][0],newV[ind2-1][1],newV[ind2][0],newV[ind2][1]]))
+                                               NF.append(NMesh.Face([newV[ind2][1],newV[ind2-3][0],newV[ind2-2][1],newV[ind2-1][0]]))
+                                               NF.append(NMesh.Face([newV[ind2-3][0],newV[ind2-3][1],newV[ind2-2][0],newV[ind2-2][1]]))
+                               
+                               else :                                    # f is a tri
+                                       if nb2 == 1:
+                                               ind2 = lenV.index(2)
+                                               NF.append(NMesh.Face([newV[ind2-2],newV[ind2-1],newV[ind2][0],newV[ind2][1]]))
+                                       
+                                       elif nb2 == 2:
+                                               ind2 = lenV.index(3)
+                                               NF.append(NMesh.Face([newV[ind2-1][1],newV[ind2],newV[ind2-2][0]]))
+                                               NF.append(NMesh.Face([newV[ind2-2][0],newV[ind2-2][1],newV[ind2-1][0],newV[ind2-1][1]]))
+                                       
+                                       else:
+                                               ind2 = min(((newV[i][1].co-newV[i-1][0].co).length, i) for i in enumV)[1]
+                                               NF.append(NMesh.Face([newV[ind2-1][1],newV[ind2][0],newV[ind2][1],newV[ind2-2][0]]))
+                                               NF.append(NMesh.Face([newV[ind2-2][0],newV[ind2-2][1],newV[ind2-1][0],newV[ind2-1][1]]))
+                               
+                               # Preparing the corners
+                               for i in enumV:
+                                       if lenV[i] == 2 :          NC.setdefault(V[i],[]).append(newV[i])
+                       
+                       old_faces.append(f)
+                       
+                       # Preparing the Edges
+                       for i in enumV:
+                               if Esel[i]:
+                                       verts = [newV[i],newV[(i+1) % nV]]
+                                       if V[i].index > V[(i+1) % nV].index : verts.reverse()
+                                       NE.setdefault(E[i],[]).append(verts)
+       
+       # Create the faces
+       for f in NF: me.addFace(f)
 
 def make_edges():
        """ Make the faces corresponding to selected edges """
-       #
-       for l in NE.values():
-               if len(l) == 4:
-                       f = NMesh.Face([l[0],l[1],l[3],l[2]])
-                       me.faces.append(f)
+
+       for old,new in NE.iteritems() :
+               if len(new) == 1 :                                        # This edge was on a border 
+                       oldv = [old.v1, old.v2]
+                       if old.v1.index < old.v2.index : oldv.reverse()
+                       
+                       make_sel_face(oldv+new[0])
+
+                       me.findEdge(*oldv).flag   |= E_selected
+                       me.findEdge(*new[0]).flag |= E_selected
+
+                       for v in oldv : NV_ext.add(v)
+               
+               else:
+                       make_sel_face(new[0] + new[1][::-1])
+
+                       me.findEdge(*new[0]).flag |= E_selected
+                       me.findEdge(*new[1]).flag |= E_selected
 
 def make_corners():
-       """ Make the faces corresponding to selected corners """
-       #
+       """ Make the faces corresponding to corners """
+
        for v in NV.keys():
                V = NV[v].values()
-               nb_v = len(V)
-               #
-               if nb_v < 3:
-                       pass
-               #
-               elif nb_v == 3:
-                       new_f = NMesh.Face(V)
-                       me.faces.append(new_f)
-               #
+               nV = len(V)
+               
+               if nV == 1:      pass
+               
+               elif nV == 2 :
+                       if v in NV_ext:
+                               make_sel_face(V+[v])
+                               me.findEdge(*V).flag   |= E_selected
+                               
                else:
-                       # We need to know which are the edges around the corner.
-                       # First, we look for the quads surrounding the corner.
-                       q = [NE[id] for id in NE.keys() if str(v.index) in id.split('_')]
-                       #
-                       # We will put the associated edges in the list eed
-                       is_in_v = lambda x:x in V
-                       eed =  [filter(is_in_v, l) for l in q]
-                       #
-                       # We will add the edges coming from faces where only one vertice is selected.
-                       # They are stocked in NC.
-                       if v in NC.keys():
-                               eed = eed+NC[v]
-                       b = eed.pop()
-                       # b will contain the sorted list of vertices
-                       #
-                       while  eed:
-                               for l in eed:
-                                       if l[0] == b[-1]:
-                                               b.append(l[1])
-                                               eed.remove(l)
-                                               break
-                                       elif l[1] == b[-1]:
-                                               b.append(l[0])
-                                               eed.remove(l)
-                                               break
-                       # Now we can create the faces
-                       if nb_v == 4:
-                               new_f = NMesh.Face(b[:4])
-                               me.faces.append(new_f)
-                       #
-                       else:
-                               co = [0.0, 0.0,0.0]
-                               vec = [0.0, 0.0,0.0]
-                               for x in V:
-                                       co[0] += x[0]
-                                       co[1] += x[1]
-                                       co[2] += x[2]
-                               #
-                               for dir in NV[v]:
-                                       vec[0] += dir.co[0]
-                                       vec[1] += dir.co[1]
-                                       vec[2] += dir.co[2]
-                               #
-                               co = [x/nb_v for x in co]
-                               vec = [x/nb_v for x in vec]
-                               center = NMesh.Vert(co[0],co[1],co[2])
-                               center.sel = 1
-                               me.verts.append(center)
-                               add_to_NV(v,vec,center)
-                               #
-                               for k in range(nb_v):
-                                       new_f = NMesh.Face([center, b[k], b[k+1]])
-                                       me.faces.append(new_f)
-               #
+                       if nV == 3 and v not in NV_ext : make_sel_face(V)
+                       
+                       else :
+                               
+                               # We need to know which are the edges around the corner.
+                               # First, we look for the quads surrounding the corner.
+                               eed = []
+                               for old, new in NE.iteritems():
+                                       if v in (old.v1,old.v2) :
+                                               if v.index == min(old.v1.index,old.v2.index) :   ind = 0
+                                               else                                                                             :   ind = 1
+                                               
+                                               if len(new) == 1:          eed.append([v,new[0][ind]])
+                                               else :                            eed.append([new[0][ind],new[1][ind]])
+                               
+                               # We will add the edges coming from faces where only one vertice is selected.
+                               # They are stored in NC.
+                               if v in NC:                                      eed = eed+NC[v]
+
+                               # Now we have to sort these vertices
+                               hc = {}
+                               for (a,b) in eed :
+                                       hc.setdefault(a,[]).append(b)
+                                       hc.setdefault(b,[]).append(a)
+                               
+                               for x0,edges in hc.iteritems():
+                                       if len(edges) == 1 :            break
+                               
+                               b = [x0]                                                # b will contain the sorted list of vertices
+                               
+                               for i in range(len(hc)-1):
+                                       for x in hc[x0] :
+                                               if x not in b :          break
+                                       b.append(x)
+                                       x0 = x
+
+                               b.append(b[0])
+
+                               # Now we can create the faces
+                               if len(b) == 5:                          make_sel_face(b[:4])
+
+                               else:
+                                       New_V = Vector(0.0, 0.0,0.0)
+                                       New_d = [0.0, 0.0,0.0]
+               
+                                       for x in hc.keys():              New_V += x.co
+                                       for dir in NV[v] :
+                                               for i in xrange(3):      New_d[i] += dir[i]
+
+                                       New_V *= 1./len(hc)
+                                       for i in range(3) :              New_d[i] /= nV
+                                       
+                                       center = make_sel_vert(New_V.x,New_V.y,New_V.z)
+                                       add_to_NV(v,tuple(New_d),center)
+
+                                       for k in range(len(b)-1):   make_sel_face([center, b[k], b[k+1]])
+                               
+               if  2 < nV and v in NC :
+                       for edge in NC[v] :                              me.findEdge(*edge).flag   |= E_selected
 
 def clear_old():
        """ Erase old faces and vertices """
-       for F in NF:
-               if len(F) == 3:
-                       me.faces.remove(F[2])
-       #
+
+       for f in old_faces: me.removeFace(f)
+       
        for v in NV.keys():
-               me.verts.remove(v)
+               if v not in NV_ext :  me.verts.remove(v)
+
+       for e in me.edges:
+               if e.flag & E_selected :
+                       e.v1.sel = 1
+                       e.v2.sel = 1
+       
 
 ######################################################################
 # Interface
-#
+
 global dist
-NV = {}
+       
 dist = Create(0.2)
 left = Create(0.0)
 right = Create(1.0)
@@ -393,83 +330,79 @@ def draw():
        global EVENT_NOEVENT, EVENT_BEVEL, EVENT_UPDATE, EVENT_RECURS, EVENT_EXIT
 
        glClear(GL_COLOR_BUFFER_BIT)
-       Button("Bevel",EVENT_BEVEL,10,100,300,25)
-       left=Number('',  EVENT_NOEVENT,10,70,50, 20,left.val,0,right.val,'Set the minimum of the slider')
-       right = Number("",EVENT_NOEVENT,260,70,50,20,right.val,left.val,200,"Set the maximum of the slider")
-       dist=Slider("Thickness ",EVENT_UPDATE,65,70,190,20,dist.val,left.val,right.val,0,"Thickness of the bevel, can be changed even after bevelling")
-       glRasterPos2d(10,40)
+       Button("Bevel",EVENT_BEVEL,10,100,280,25)
+       left=Number('',  EVENT_NOEVENT,10,70,45, 20,left.val,0,right.val,'Set the minimum of the slider')
+       right = Number("",EVENT_NOEVENT,245,70,45,20,right.val,left.val,200,"Set the maximum of the slider")
+       dist=Slider("Thickness  ",EVENT_UPDATE,60,70,180,20,dist.val,left.val,right.val,0, \
+                       "Thickness of the bevel, can be changed even after bevelling")
+       glRasterPos2d(8,40)
        Text('To finish, you can use recursive bevel to smooth it')
-       num=Number('',  EVENT_NOEVENT,10,10,50, 16,num.val,1,100,'Recursion level')
-       Button("Recursive",EVENT_RECURS,65,10,100,16)
-       Button("Exit",EVENT_EXIT,230,10,80,20)
+       num=Number('',  EVENT_NOEVENT,10,10,40, 16,num.val,1,100,'Recursion level')
+       Button("Recursive",EVENT_RECURS,55,10,100,16)
+       Button("Exit",EVENT_EXIT,210,10,80,20)
 
 def event(evt, val):
-       if ((evt == QKEY or evt == ESCKEY) and not val):
-               Exit()
+       if ((evt == QKEY or evt == ESCKEY) and not val): Exit()
 
 def bevent(evt):
-       if evt == EVENT_EXIT :
-               Exit()
-       #
-       elif evt == EVENT_BEVEL:
-               bevel()
-       #
-       elif evt == EVENT_UPDATE:
-               try:
-                       bevel_update()
-               except NameError:
-                       pass
-       #
-       elif evt == EVENT_RECURS:
-               recursive()
+       if evt == EVENT_EXIT            : Exit()
+       elif evt == EVENT_BEVEL  : bevel()
+       elif evt == EVENT_UPDATE        :
+               try: bevel_update()
+               except NameError                : pass
+       elif evt == EVENT_RECURS        : recursive()
 
 Register(draw, event, bevent)
 
 ######################################################################
 def bevel():
        """ The main function, which creates the bevel """
-       global me,NF,NV,NE,NC, old_dist
-       #
-       is_editmode = Window.EditMode()
-       if is_editmode: Window.EditMode(0)
-       objects = Blender.Object.GetSelected() 
-       bev_obj = objects[0]
-       if bev_obj.getType() != "Mesh":
-               PupMenu("ERROR: active object must be a mesh")
+       global me,NV,NV_ext,NE,NC, old_faces,old_dist
+
+       scn = Scene.GetCurrent()
+       ob = scn.getActiveObject() 
+       if ob == None or ob.getType() != 'Mesh': 
+               Draw.PupMenu('ERROR%t|Select a mesh object.')
                return
-       me = NMesh.GetRaw(bev_obj.getData(name_only = True))
-       #
-       NF = []
+       
+       Window.WaitCursor(1) # Change the Cursor
+       
+       is_editmode = Window.EditMode() 
+       if is_editmode: Window.EditMode(0)
+       
+       me = ob.getData()
+
        NV = {}
+       NV_ext = set()
        NE = {}
        NC = {}
-       #
-       make_NF()
+       old_faces = []
+
        make_faces()
        make_edges()
        make_corners()
        clear_old()
-       #
+
        old_dist = dist.val
-       #
+
        me.update(1)
        if is_editmode: Window.EditMode(1)
+       Window.WaitCursor(0)
        Blender.Redraw()
 
 def bevel_update():
        """ Use NV to update the bevel """
-       global dist, old_dist, NV
-       if not NV: return
+       global dist, old_dist
        is_editmode = Window.EditMode()
        if is_editmode: Window.EditMode(0)
        fac = dist.val - old_dist
        old_dist = dist.val
-       #
+
        for old_v in NV.keys():
                for dir in NV[old_v].keys():
                        for i in range(3):
-                               NV[old_v][dir].co[i] += fac*dir.co[i]
-       #
+                               NV[old_v][dir].co[i] += fac*dir[i]
+
        me.update(1)
        if is_editmode: Window.EditMode(1)
        Blender.Redraw()
@@ -477,24 +410,23 @@ def bevel_update():
 def recursive():
        """ Make a recursive bevel... still experimental """
        global dist
-       #
+       from math import pi, sin
+
        if num.val > 1:
                a = pi/4
                ang = []
                for k in range(num.val):
                        ang.append(a)
                        a = (pi+2*a)/4
-               #
+
                l = [2*(1-sin(x))/sin(2*x) for x in ang]
                R = dist.val/sum(l)
                l = [x*R for x in l]
-               #
+
                dist.val = l[0]
                bevel_update()
-               #
+
                for x in l[1:]:
                        dist.val = x
                        bevel()
-       
-# vim:set ts=4 sw=4:
 
index 4ddf6035e594d1aeb794e85994d4035a75676e3f..bf875abf43cb16cbd76a740bb72dda35d56067f1 100644 (file)
@@ -5,12 +5,28 @@
 # | http://www.redrival.com/scorpius                        |
 # | scorpius@netzero.com                                    |
 # | September 28, 2002                                      |
-# | Released under the Blender Artistic Licence (BAL)       |
-# | Import Export Suite v0.5                                |
 # +---------------------------------------------------------+
 # | Common Functions & Global Variables For All IO Modules  |
 # +---------------------------------------------------------+
 
+# ***** BEGIN GPL LICENSE BLOCK *****
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#
+# ***** END GPL LICENCE BLOCK *****
+
 import Blender
 import sys
 
@@ -35,7 +51,16 @@ def append_faces(mesh, faces, facesuv, uvcoords):
        for i in range(len(faces)):
                if not i%100 and show_progress: Blender.Window.DrawProgressBar(float(i)/len(faces), "Generating Faces")
                numfaceverts=len(faces[i])
-               if numfaceverts <= 4:                           # This face is a triangle or quad
+               if numfaceverts == 2: #This is not a face is an edge
+                       if mesh.edges == None:  #first run
+                               mesh.addEdgeData()
+                       #rev_face = revert(cur_face)
+                       i1 = faces[i][0]
+                       i2 = faces[i][1]
+                       ee = mesh.addEdge(mesh.verts[i1],mesh.verts[i2])
+                       ee.flag |= Blender.NMesh.EdgeFlags.EDGEDRAW
+                       ee.flag |= Blender.NMesh.EdgeFlags.EDGERENDER
+               elif numfaceverts in [3,4]:                             # This face is a triangle or quad
                        face = Blender.NMesh.Face()
                        for j in range(numfaceverts):
                                index = faces[i][j]
index 98c6a489b0c6c0b81dc84ed15ccede61a24ef052..2ee133a00ee103e36250b644b301851794e868dc 100644 (file)
@@ -1,8 +1,41 @@
+# -*- coding: latin-1 -*-
 """
-SVG 2 OBJ translater, 0.3.3
-(c) jm soler juillet/novembre 2004-juin 2005, 
-#   released under Blender Artistic Licence 
-    for the Blender 2.37/36/35/34/33 Python Scripts Bundle.
+SVG 2 OBJ translater, 0.4.7
+Copyright (c) jm soler juillet/novembre 2004-janvier 2006, 
+# ---------------------------------------------------------------
+    released under GNU Licence 
+    for the Blender 2.40 Python Scripts Bundle.
+Ce programme est libre, vous pouvez le redistribuer et/ou
+le modifier selon les termes de la Licence Publique Générale GNU
+publiée par la Free Software Foundation (version 2 ou bien toute
+autre version ultérieure choisie par vous).
+
+Ce programme est distribué car potentiellement utile, mais SANS
+AUCUNE GARANTIE, ni explicite ni implicite, y compris les garanties
+de commercialisation ou d'adaptation dans un but spécifique.
+Reportez-vous à la Licence Publique Générale GNU pour plus de détails.
+
+Vous devez avoir reçu une copie de la Licence Publique Générale GNU
+en même temps que ce programme ; si ce n'est pas le cas, écrivez à la
+Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+MA 02111-1307, États-Unis.
+
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA    
+# ---------------------------------------------------------------
+
 #---------------------------------------------------------------------------
 # Page officielle :
 #   http://jmsoler.free.fr/didacticiel/blender/tutor/cpl_import_svg.htm
@@ -40,10 +73,14 @@ Yet done:
    L : absolute line to  
    C : absolute curve to
    S : absolute curve to with only one handle
+   H : absolute horizontal line to  
+   V : absolute vertical line to  
+   
    l : relative line to     2004/08/03
    c : relative curve to    2004/08/03
    s : relative curve to with only one handle  
-
+   h : relative horizontal line to 
+   v : relative vertical line to 
 
    A : courbe_vers_a, 
    V : ligne_tracee_v,
@@ -84,19 +121,70 @@ Changelog:
                     skew               
               - added a test on __name__ to load the script
                 outside from the blender menu  
-      0.3.3 : - controle du contenu des transformation de type matrix 
-      0.3.4 : - restructuration de la lecture des donnes paths (19/06/05) 
+      0.3.3 : - matrix transform content control  
+      0.3.4 : - paths data reading rewritten (19/06/05) 
+      0.3.5 : - test on empty curve  (22/06/05)
+              - removed overlayed points
+      0.3.6 : - rewriting of the bezier point contruction to correct
+                a problem in the connection between L type point and
+                C or S type point         
+      0.3.7 : - code correction for bezier knot in Curveto command when
+                the command close a path
+      0.3.8 : - code was aded to manage quadratic bezier, 
+                Q,q command and T,t commands, as a normal  blender's bezier point 
+              - The last modications does not work with gimp 2.0 svg export . 
+                corrected too .
+      0.3.9 : - Path's A,a  command for ellipse's arc  .
+      0.4.0 : - To speed up the function filtre_DATA was removed and text
+                variables are changed into numeric variables               
+      0.4.1 : - svg, groups and shapes hierarchy  added
+              - now transform properties are computed  using a stack  with all
+                parented groups
+              - removed or replaced useless functions :
+              - skewY, skewX transforms
+              - radians in rotate transform 
+      0.4.2 : - Added functon to translate others shapes in path 
+                    rect, line, polyline, polygon
+       
+      0.4.3 : - various corrections 
+                  text font (id property exported by Adobe Illustrator are between coma)
+                  function  to code  s tag has been  rewritten 
+
+      0.4.4 : - various corrections      
+                to oblige the script to understand a line feed just after 
+                a tag . Rarely encountered problem, but it exits in a svg file
+                format exported by a outliner script for mesh .
+
+      0.4.5 : - update for CVS only, at least blender 2.38 and upper
+                no BezTriple module in older version
+                added a createCURVES function to avoid to use
+                the OBJ format export/import .
+
+                Perhaps problems with cyclic curves . If a closed curve 
+                does not appear closed in blender, enter edit mode select 
+                all  knot with Akey,  do a Hkey to set handle type (without 
+                this the knot are recalculated) , and finally use the Ckey 
+                to close the curve .
+                Should work ... not guaranted .
+
+      0.4.6 : - cyclic flag ...
+
+      0.4.7 : - Management of the svgz files . the complete python or the gzip.py 
+                file is needed .
+                Little improvement of the curve drawing using the createCURVES 
+                function 
 ==================================================================================   
 =================================================================================="""
 
 SHARP_IMPORT=0
 SCALE=1
-scale=1
-DEBUG =#print
+scale_=1
+DEBUG = 0#print
 DEVELOPPEMENT=0
     
 import sys
-from math import cos,sin,tan
+from math import cos,sin,tan, atan2, pi, ceil
+PI=pi
 import Blender
 from Blender import Mathutils
 BLversion=Blender.Get('version')
@@ -139,27 +227,69 @@ os.split=split
 os.join=join
 
 def filtreFICHIER(nom):
-     f=open(nom,'rU')
-     t=f.read()
-     f.close()
+     """
+     Function  filtreFICHIER
+
+     in  : string  nom , filename
+     out : string  t   , if correct filecontaint 
+
+     Lit le contenu du fichier et en fait une pre-analyse 
+     pour savoir s'il merite d'etre traite .
+     """
+     # ----------
+     # 0.4.7 
+     # ----------
+     if nom.upper().find('.SVGZ')!=-1:
+         try :
+             import gzip 
+             tz=gzip.GzipFile(nom)
+             t=tz.read()
+         except:
+             name = "ERROR: fail to import gzip module or gzip error ... "  
+             result = Blender.Draw.PupMenu(name)
+             return "false"
+     else:    
+        f=open(nom,'rU')
+        t=f.read()
+        f.close()
+     # ----------
+     # 0.4.7  : end 
+     # ----------
      
-     t=t.replace('\r','')
-     t=t.replace('\n','')
+     # -----------------
+     #  pre-format ...
+     # -----------------
+     # --------------------
+     # 0.4.4  '\r','' -->  '\r',' ' 
+     #        '\n','' -->  '\n',' ' 
+     #--------------------
+     t=t.replace('\r',' ')
+     t=t.replace('\n',' ')
+     t=t.replace('svg:','')
      
      if t.upper().find('<SVG')==-1 :
          name = "ERROR: invalid or empty file ... "  # if no %xN int is set, indices start from 1
          result = Blender.Draw.PupMenu(name)
          return "false"
-     elif  t.upper().find('<PATH')==-1:
+     else:
+          return t
+
+     """
+     elif  t.upper().find('<PATH')==-1 and\
+           t.upper().find('<RECT')==-1 and\
+           t.upper().find('<LINE')==-1 and\
+           t.upper().find('<POLYLINE')==-1     :
          name = "ERROR: there's no Path in this file ... "  # if no %xN int is set, indices start from 1
          result = Blender.Draw.PupMenu(name)
          return "false"
-     else:
-          return t
+     """
+
 
 #===============================
 # Data
 #===============================
+
+
 #===============================
 # Blender Curve Data
 #===============================
@@ -172,16 +302,20 @@ class Bez:
       def __init__(self):
            self.co=[]
            self.ha=[0,0]
-           
+           self.tag=''
+
 class ITEM:
       def __init__(self):
-               self.type        =  typBEZIER3D,        
+               self.type        =  typBEZIER3D        
                self.pntsUV      =  [0,0]              
                self.resolUV     =  [32,0]            
                self.orderUV     =  [0,0]             
                self.flagUV      =  [0,0]              
                self.Origine     =  [0.0,0.0]
                self.beziers_knot = []
+               self.fill=0
+               self.closed=0
+               self.color=[0.0,0.0,0.0]
 
 class COURBE:
       def __init__(self):
@@ -222,7 +356,7 @@ def test_egalitedespositions(f1,f2):
 
 
 def Open_GEOfile(dir,nom):
-    global SCALE,BOUNDINGBOX, scale
+    global SCALE,BOUNDINGBOX, scale_
     if BLversion>=233:
        Blender.Load(dir+nom+'OOO.obj', 1)
        BO=Blender.Object.Get()
@@ -231,7 +365,7 @@ def Open_GEOfile(dir,nom):
        BO[-1].RotZ=3.1416
        BO[-1].RotX=3.1416/2.0
        
-       if scale==1:
+       if scale_==1:
           BO[-1].LocY+=BOUNDINGBOX['rec'][3]
        else:
          BO[-1].LocY+=BOUNDINGBOX['rec'][3]/SCALE
@@ -242,14 +376,14 @@ def Open_GEOfile(dir,nom):
        print "Not yet implemented"
 
 def create_GEOtext(courbes):
-    global SCALE, B, BOUNDINGBOX,scale
-    r=BOUNDINGBOX['rec']
+    global SCALE, B, BOUNDINGBOX,scale_
 
-    if scale==1:
+    r=BOUNDINGBOX['rec']
+    if scale_==1:
        SCALE=1.0
-    elif scale==2:
+    elif scale_==2:
        SCALE=r[2]-r[0]
-    elif scale==3:
+    elif scale_==3:
        SCALE=r[3]-r[1]
  
     t=[]
@@ -284,211 +418,535 @@ def save_GEOfile(dir,nom,t):
      f.writelines(t)
      f.close()
 
+#--------------------
+# 0.4.5 : for blender cvs 2.38 ....
+#--------------------
+def createCURVES(courbes):
+    global SCALE, B, BOUNDINGBOX,scale_
+    from Blender import Curve, Object, Scene, BezTriple
+
+    r=BOUNDINGBOX['rec']
+    if scale_==1:
+       SCALE=1.0
+    elif scale_==2:
+       SCALE=r[2]-r[0]
+    elif scale_==3:
+       SCALE=r[3]-r[1]
+
+    [o.select(0) for o in Object.Get()]
+    for I in courbes.ITEM:
+        c = Curve.New()
+        # ----------
+        # 0.4.7 
+        # ----------
+        c.setResolu(24)  
+        scene = Scene.getCurrent()
+        ob = Object.New('Curve')
+        ob.link(c)
+        scene.link(ob)
+        ob.select(1)
+        bzn=0
+        #for b in courbes.ITEM[I].beziers_knot:
+        for k2 in range(0,len(courbes.ITEM[I].beziers_knot)):
+            bz=ajustement(courbes.ITEM[I].beziers_knot[k2], SCALE)
+            #bz=k1
+            if bzn==0:
+              cp1 =  bz[4],bz[5],0.0 , bz[0],bz[1],0.0, bz[2],bz[3],0.0, 
+              beztriple1 = BezTriple.New(cp1)
+              bez = c.appendNurb(beztriple1)
+              
+              bzn = 1
+            else:
+              cp2 =  bz[4],bz[5],0.0 , bz[0],bz[1],0.0, bz[2],bz[3],0.0
+              beztriple2 = BezTriple.New(cp2)
+              bez.append(beztriple2)
+
+        if courbes.ITEM[I].flagUV[0]==1 :
+          #--------------------
+          # 0.4.6 : cyclic flag ...
+          #--------------------
+           bez.flagU += 1
+           
 
-def filtre_DATA(c,D,n):
-    global DEBUG,TAGcourbe
-    #print 'c',c,'D',D,'n',n
-    l=[] 
-    if len(c[0])==1 and D[c[1]+1].find(',')!=-1:
-        for n2 in range(1,n+1): 
-           ld=D[c[1]+n2].split(',')
-           for l_ in ld: 
-               l.append(l_)
-               
-    elif len(c[0])==1 and D[c[1]+2][0] not in  TAGcourbe:
-        for n2 in range(1,n*2+1):
-           l.append(D[c[1]+n2])
-        if DEBUG==1 : print l 
-
-    return l
 
 #=====================================================================
 #=====      SVG format   :  DEBUT             =========================
 #=====================================================================
+#--------------------
+# 0.4.2
+#--------------------
+OTHERSSHAPES=['rect','line', 'polyline', 'polygon','circle','ellipse']
+
+#--------------------
+# 0.4.2
+#--------------------
+def rect(prp):
+  D=[]
+  if 'x' not in prp.keys(): x=0.0
+  else : x=float(prp['x'])
+  if 'y' not in prp.keys(): y=0.0
+  else : y=float(prp['y'])
+               
+  height=float(prp['height'])
+  width=float(prp['width'])
+       
+  """
+   normal rect
+
+   x,y 
+                  h1       
+       *----------*
+       |          |
+       |          | 
+       |          |
+       *----------* v1
+       h2
+  """
+  if 'rx' not in prp.keys() or 'rx' not in prp.keys(): 
+     exec   """D=['M','%s','%s','h','%s','v','%s','h','%s','z']"""%(x,y,width,height,-width)   
+  else :
+     rx=float(prp['rx'])
+     if 'ry' not in prp.keys()  : 
+           ry=float(prp['rx'])
+     else :    ry=float(prp['ry'])
+     if 'rx' in prp.keys() and prp['rx']<0.0: rx*=-1
+     if 'ry' in prp.keys() and prp['ry']<0.0: ry*=-1
+       
+     """
+   rounded corner
+      
+   x,y     M         h1       
+       ---*----------*  
+         /            \  
+        /              \
+    v2 *                * c1
+       |                |
+       |                |   
+       |                |
+    c3 *                * v2
+        \              /
+         \            /   
+          *----------*  
+          h2         c2
+     """
+     exec   """D=['M','%s','%s',
+                  'h','%s',
+                  'c','%s','%s','%s','%s','%s','%s',
+                  'v','%s',
+                  'c','%s','%s','%s','%s','%s','%s',
+                  'h','%s',
+                  'c','%s','%s','%s','%s','%s','%s',
+                  'v','%s',
+                  'c','%s','%s','%s','%s','%s','%s',
+                  'z']"""%(x+rx,y,
+                           width-2*rx,
+                           rx,0.0,rx,ry,rx,ry,
+                            height-ry,
+                           0.0,ry,-rx,ry,-rx,ry,
+                           -width+2*rx,
+                           -rx,0.0,-rx,-ry,-rx,-ry,
+                           -height+ry,
+                           0.0,0.0,0.0,-ry,rx,-ry
+ )     
+                       
+  return D
+
+#--------------------
+# 0.4.2
+#--------------------
+def circle(prp):
+   if 'cx' not in prp.keys(): cx=0.0   
+   else : cx =float(prp['cx'])
+   if 'cy' not in prp.keys(): cy=0.0
+   else : cy =float(prp['cy'])
+   r = float(prp['r'])
+   exec """D=['M','%s','%s',                  
+              'C','%s','%s','%s','%s','%s','%s',
+              'C','%s','%s','%s','%s','%s','%s',
+              'C','%s','%s','%s','%s','%s','%s',
+              'C','%s','%s','%s','%s','%s','%s',
+              'Z']"""%( 
+                      cx,cy+r, 
+                      cx-r,cy+r*0.552, cx-0.552*r,cy+r, cx,cy+r,
+                      cx+r*0.552,cy+r, cx+r,cy+r*0.552, cx+r,cy,
+                      cx+r,cy-r*0.552,  cx+r*0.552,cy-r,   cx,cy-r,
+                      cx-r*0.552,cy-r, cx-r,cy-r*0.552, cx-r,cy
+                      )
+   return D 
+   
+#--------------------
+# 0.4.2
+#--------------------
+def ellipse(prp):
+   if 'cx' not in prp.keys(): cx=0.0   
+   else : cx =float(prp['cx'])
+   if 'cy' not in prp.keys(): cy=0.0
+   else : cy =float(prp['cy'])
+   ry = float(prp['rx'])
+   rx = float(prp['ry'])
+
+   exec """D=['M','%s','%s',                  
+              'C','%s','%s','%s','%s','%s','%s',
+              'C','%s','%s','%s','%s','%s','%s',
+              'C','%s','%s','%s','%s','%s','%s',
+              'C','%s','%s','%s','%s','%s','%s',
+              'Z']"""%( 
+                      cx,cy+rx, 
+                      cx-ry,cy+rx*0.552, cx-0.552*ry,cy+rx, cx,cy+rx,
+                      cx+ry*0.552,cy+rx, cx+ry,cy+rx*0.552, cx+ry,cy,
+                      cx+ry,cy-rx*0.552,  cx+ry*0.552,cy-rx,   cx,cy-rx,
+                      cx-ry*0.552,cy-rx, cx-ry,cy-rx*0.552, cx-ry,cy
+                      )
+   return D 
+#--------------------
+# 0.4.2
+#--------------------
+def line(prp):
+  exec   """D=['M','%s','%s',
+                  'L','%s','%s']"""%(prp['x1'],prp['y1'], prp['x2'],prp['y2'])
+  return D
+#--------------------
+# 0.4.2
+#--------------------    
+def polyline(prp):
+ if 'points' in  prp.keys():
+    #print prp['points']
+    points=prp['points'].split(' ')
+    #print points
+    np=0
+    for p in points:
+     if p!='':
+        p=p.split(',')
+        if np==0:
+           exec "D=['M','%s','%s']"%(p[0],p[1])
+           np+=1
+        else: 
+           exec """D.append('L');D.append('%s');D.append('%s')"""%(p[0],p[1])
+    #print D
+    return D
+ else:
+    return []
+
+#--------------------
+# 0.4.2
+#--------------------  
+def polygon(prp):
+    D=polyline(prp)
+    if D!=[]:
+        D.append('Z')
+    return D
 
-def contruit_SYMETRIC(l):
-    L=[float(l[0]), float(l[1]),
-       float(l[2]),float(l[3])]
-    X=L[0]-(L[2]-L[0])
-    Y=L[1]-(L[3]-L[1])
-    l =[l[0],l[1],"%4s"%X,"%4s"%Y,l[2],l[3]]   
-    return l
-
-def mouvement_vers(c, D, n0,CP):
+    
+#--------------------
+# 0.3.9
+#--------------------
+def calc_arc (cpx,cpy, rx, ry,  ang, fa , fs , x, y) :
+    rx=abs(rx)
+    ry=abs(ry)
+    px=abs((cos(ang)*(cpx-x)+sin(ang)*(cpy-y))*0.5)**2.0
+    py=abs((cos(ang)*(cpy-y)-sin(ang)*(cpx-x))*0.5)**2.0
+    pl=px/(rx**2.0)+py/(ry**2.0 )
+    if pl>1.0:
+        pl=pl**0.5;rx*=pl;ry*=pl
+    x0=(cos(ang)/rx)*cpx+(sin(ang)/rx)*cpy
+    y0=(-sin(ang)/ry)*cpx+(cos(ang)/ry)*cpy
+    x1=(cos(ang)/rx)*x+(sin(ang)/rx)*y
+    y1=(-sin(ang)/ry)*x+(cos(ang)/ ry)*y    
+    d=(x1-x0)*(x1-x0)+(y1-y0)*(y1-y0)  
+    if abs(d)>0.0 :sq=1.0/d-0.25
+    else: sq=-0.25
+    if sq<0.0 :sq=0.0
+    sf=sq**0.5
+    if fs==fa :sf=-sf
+    xc=0.5*(x0+x1)-sf*(y1-y0)
+    yc=0.5*(y0+y1)+sf*(x1-x0)
+    ang_0=atan2(y0-yc,x0-xc)
+    ang_1=atan2(y1-yc,x1-xc)
+    ang_arc=ang_1-ang_0;
+    if (ang_arc < 0.0 and fs==1) :
+        ang_arc += 2.0 * PI
+    elif (ang_arc>0.0 and fs==0) :
+        ang_arc-=2.0*PI
+    n_segs=int(ceil(abs(ang_arc*2.0/(PI*0.5+0.001))))
+    P=[]
+    for i in range(n_segs):
+        ang0=ang_0+i*ang_arc/n_segs
+        ang1=ang_0+(i+1)*ang_arc/n_segs
+        ang_demi=0.25*(ang1-ang0)
+        t=2.66666*sin(ang_demi)*sin(ang_demi)/sin(ang_demi*2.0)
+        x1=xc+cos(ang0)-t*sin(ang0)
+        y1=yc+sin(ang0)+t*cos(ang0)
+        x2=xc+cos(ang1)
+        y2=yc+sin(ang1)
+        x3=x2+t*sin(ang1)
+        y3=y2-t*cos(ang1)
+        P.append([[(cos(ang)*rx)*x1+(-sin(ang)*ry)*y1,
+               (sin(ang)*rx)*x1+(cos(ang)*ry)*y1],
+              [(cos(ang)*rx)*x3+(-sin(ang)*ry)*y3,
+               (sin(ang)*rx)*x3+(cos(ang)*ry)*y3],
+              [(cos(ang)*rx)*x2+(-sin(ang)*ry)*y2,
+               (sin(ang)*rx)*x2+(cos(ang)*ry)*y2]])
+    return P
+
+
+#--------------------
+# 0.3.9
+#--------------------
+def courbe_vers_a(c,D,n0,CP):  #A,a
+    global SCALE
+
+    l=[float(D[c[1]+1]),float(D[c[1]+2]),float(D[c[1]+3]),
+        int(D[c[1]+4]),int(D[c[1]+5]),float(D[c[1]+6]),float(D[c[1]+7])]
+    if c[0]=='a':
+       l[5]=l[5] + CP[0]
+       l[6]=l[6] + CP[1]
+
+    B=Bez()
+    B.co=[ CP[0], CP[1], CP[0], CP[1], CP[0], CP[1] ]             
+    B.ha=[0,0]
+    B.tag=c[0]
+    POINTS= calc_arc (CP[0],CP[1], 
+                      l[0], l[1], l[2]*(PI / 180.0),
+                      l[3], l[4], 
+                      l[5], l[6] )
+
+    if DEBUG == 1  : print POINTS
+    
+    for p in POINTS :
+        B=Bez()
+        B.co=[ p[2][0],p[2][1], p[0][0],p[0][1], p[1][0],p[1][1]]             
+        B.ha=[0,0]
+        B.tag=c[0]
+        BP=courbes.ITEM[n0].beziers_knot[-1]
+        BP.co[2]=B.co[2]
+        BP.co[3]=B.co[3]
+        courbes.ITEM[n0].beziers_knot.append(B)
+           
+    BP=courbes.ITEM[n0].beziers_knot[-1]
+    BP.co[2]=BP.co[0]
+    BP.co[3]=BP.co[1]
+
+    CP=[l[5], l[6]]
+    return  courbes,n0,CP    
+
+def mouvement_vers(c, D, n0,CP, proprietes):
     global DEBUG,TAGcourbe
-    #print 'c',c,'D[c[1]+1]',D[c[1]+1]
 
-    l=filtre_DATA(c,D,1)
-    #print 'l',l
+    #l=filtre_DATA(c,D,2)
+    l=[float(D[c[1]+1]),float(D[c[1]+2])]
+
+    if c[0]=='m':
+       l=[l[0]+CP[0],
+           l[1] + CP[1]]
+
     if n0 in courbes.ITEM.keys():
        n0+=1
-    #
-    #   CP=[l[0],l[1]]        
-    #else:
-    #   CP=[l[0],l[1]] 
-    CP=[l[0],l[1]] 
 
+    CP=[l[0],l[1]] 
     courbes.ITEM[n0]=ITEM() 
     courbes.ITEM[n0].Origine=[l[0],l[1]] 
 
+    proprietes['n'].append(n0)
+    #print 'prop et item',proprietes['n'], courbes.ITEM.keys()
+
     B=Bez()
     B.co=[CP[0],CP[1],CP[0],CP[1],CP[0],CP[1]]
     B.ha=[0,0]
-    
+    B.tag=c[0]
     courbes.ITEM[n0].beziers_knot.append(B)
-    if DEBUG==1: print courbes.ITEM[n0], CP
     
+    if DEBUG==1: print courbes.ITEM[n0], CP    
 
     return  courbes,n0,CP     
     
 def boucle_z(c,D,n0,CP): #Z,z
     #print c, 'close'
-    courbes.ITEM[n0].flagUV[0]=1 
+    #print courbes.ITEM[n0].beziers_knot
+    courbes.ITEM[n0].flagUV[0]=1
+    #print 'len(courbes.ITEM[n0].beziers_knot)',len(courbes.ITEM[n0].beziers_knot)
+    if len(courbes.ITEM[n0].beziers_knot)>1:
+        BP=courbes.ITEM[n0].beziers_knot[-1]
+        BP0=courbes.ITEM[n0].beziers_knot[0]
+        if BP.tag in ['c','C','s','S']: 
+           BP.co[2]=BP0.co[2]  #4-5 point prec
+           BP.co[3]=BP0.co[3]
+           del courbes.ITEM[n0].beziers_knot[0]
+    else:
+     del courbes.ITEM[n0]
+
+     n0-=1 
     return  courbes,n0,CP    
-   
-def courbe_vers_s(c,D,n0,CP):  #S,s
-    l=filtre_DATA(c,D,2) 
-    if c[0]=='s':
-       l=["%4s"%(float(l[0])+float(CP[0])),
-          "%4s"%(float(l[1])+float(CP[1])),
-          "%4s"%(float(l[2])+float(CP[0])),
-          "%4s"%(float(l[3])+float(CP[1]))]
-    l=contruit_SYMETRIC(l)    
+
+def courbe_vers_q(c,D,n0,CP):  #Q,q
+    l=[float(D[c[1]+1]),float(D[c[1]+2]),float(D[c[1]+3]),float(D[c[1]+4])]
+    if c[0]=='q':
+       l=[l[0]+CP[0], l[1]+CP[1], l[2]+CP[0], l[3]+CP[1]]
+    B=Bez()
+    B.co=[l[2],  l[3],  l[2],  l[3], l[0], l[1]] #plus toucher au 2-3
+    B.ha=[0,0]
+    B.tag=c[0]
+    BP=courbes.ITEM[n0].beziers_knot[-1]
+    BP.co[2]=BP.co[0]
+    BP.co[3]=BP.co[1]
+    courbes.ITEM[n0].beziers_knot.append(B)
+    if DEBUG==1: print B.co,BP.co
+
+    CP=[l[2],l[3]]
+    if DEBUG==1:
+       pass 
+    if len(D)>c[1]+5 and D[c[1]+5] not in TAGcourbe :
+        c[1]+=4
+        courbe_vers_q(c, D, n0,CP)
+    return  courbes,n0,CP          
+
+def courbe_vers_t(c,D,n0,CP):  #T,t 
+    l=[float(D[c[1]+1]),float(D[c[1]+2])]
+    if c[0]=='t':
+       l=[l[0]+CP[0], l[1]+CP[1]]
+          
     B=Bez()
-    B.co=[l[4],l[5],l[2],l[3],l[0],l[1]] #plus toucher au 2-3
+    B.co=[l[0], l[1], l[0], l[1], l[0], l[1]] #plus toucher au 2-3
     B.ha=[0,0]
+    B.tag=c[0]
 
     BP=courbes.ITEM[n0].beziers_knot[-1]
-    BP.co[2]=l[2]  #4-5 point prec
-    BP.co[3]=l[3]
+
+    l0=contruit_SYMETRIC([BP.co[0],BP.co[1],BP.co[4],BP.co[5]])
+
+    if BP.tag in ['q','Q','t','T','m','M']:
+       BP.co[2]=l0[2]
+       BP.co[3]=l0[3]
 
     courbes.ITEM[n0].beziers_knot.append(B)
     if DEBUG==1: print B.co,BP.co
-    CP=[l[4],l[5]]    
-
-    if len(D)<c[1]+3 and D[c[1]+3] not in TAGcourbe :
-        c[1]+=2
-        courbe_vers_c(c, D, n0,CP)
-    return  courbes,n0,CP
 
-def courbe_vers_a(c,D,n0,CP):  #A
-    #print c
+    CP=[l[0],l[1]]
+    if len(D)>c[1]+3 and D[c[1]+3] not in TAGcourbe :
+        c[1]+=4
+        courbe_vers_t(c, D, n0,CP)    
     return  courbes,n0,CP     
 
-def courbe_vers_q(c,D,n0,CP):  #Q
-    #print c
-    return  courbes,n0,CP     
+#--------------------
+# 0.4.3 : rewritten
+#--------------------
+def contruit_SYMETRIC(l):
+    X=l[2]-(l[0]-l[2])
+    Y=l[3]-(l[1]-l[3])
+    return X,Y
 
-def courbe_vers_t(c,D,n0,CP):  #T
-    return  courbes,n0,CP     
+def courbe_vers_s(c,D,n0,CP):  #S,s
+    l=[float(D[c[1]+1]),
+       float(D[c[1]+2]),
+       float(D[c[1]+3]),
+       float(D[c[1]+4])]
+    if c[0]=='s':
+       l=[l[0]+CP[0], l[1]+CP[1], 
+          l[2]+CP[0], l[3]+CP[1]]
+    B=Bez()
+    B.co=[l[2],l[3],l[2],l[3],l[0],l[1]] #plus toucher au 2-3
+    B.ha=[0,0]
+    B.tag=c[0]
+    BP=courbes.ITEM[n0].beziers_knot[-1]
+    #--------------------
+    # 0.4.3
+    #--------------------
+    BP.co[2],BP.co[3]=contruit_SYMETRIC([BP.co[4],BP.co[5],BP.co[0],BP.co[1]])
+    courbes.ITEM[n0].beziers_knot.append(B)
+    if DEBUG==1: print B.co,BP.co
+    #--------------------
+    # 0.4.3
+    #--------------------      
+    CP=[l[2],l[3]]    
+    if len(D)>c[1]+5 and D[c[1]+5] not in TAGcourbe :
+        c[1]+=4
+        courbe_vers_c(c, D, n0,CP)       
+    return  courbes,n0,CP
        
 def courbe_vers_c(c, D, n0,CP): #c,C
-
-    l=filtre_DATA(c,D,3) 
-
-    print '\n','l',l, 'c',c,'CP', CP
-
+    l=[float(D[c[1]+1]),float(D[c[1]+2]),float(D[c[1]+3]),
+       float(D[c[1]+4]),float(D[c[1]+5]),float(D[c[1]+6])]
     if c[0]=='c':
-       l=["%4s"%(float(l[0])+float(CP[0])),
-          "%4s"%(float(l[1])+float(CP[1])),
-          "%4s"%(float(l[2])+float(CP[0])),
-          "%4s"%(float(l[3])+float(CP[1])),
-          "%4s"%(float(l[4])+float(CP[0])),
-          "%4s"%(float(l[5])+float(CP[1]))]
-
-    #print l
-   
+       l=[l[0]+CP[0],
+          l[1]+CP[1],
+          l[2]+CP[0],
+          l[3]+CP[1],
+          l[4]+CP[0],
+          l[5]+CP[1]]
     B=Bez()
     B.co=[l[4],
           l[5],
-          l[0],
-          l[1],
+          l[4],
+          l[5],
           l[2],
           l[3]] #plus toucher au 2-3
-
     B.ha=[0,0]
-
+    B.tag=c[0]
     BP=courbes.ITEM[n0].beziers_knot[-1]
-
     BP.co[2]=l[0]
     BP.co[3]=l[1]
-
     courbes.ITEM[n0].beziers_knot.append(B)
     if DEBUG==1: print B.co,BP.co
-
     CP=[l[4],l[5]]
-    if DEBUG==1:
-       pass #print 'D[c[1]]', D[c[1]], c
-       #print D
-    if len(D)<c[1]+4 and D[c[1]+4] not in TAGcourbe :
-        c[1]+=3
+    if len(D)>c[1]+7 and D[c[1]+7] not in TAGcourbe :
+        c[1]+=6
         courbe_vers_c(c, D, n0,CP)
-
     return  courbes,n0,CP
     
     
 def ligne_tracee_l(c, D, n0,CP): #L,l
-    #print c
-    
-    l=filtre_DATA(c,D,1)
+    l=[float(D[c[1]+1]),float(D[c[1]+2])]
     if c[0]=='l':
-       l=["%4s"%(float(l[0])+float(CP[0])),
-          "%4s"%(float(l[1])+float(CP[1]))]
-
+       l=[l[0]+CP[0],
+          l[1]+CP[1]]
     B=Bez()
     B.co=[l[0],l[1],l[0],l[1],l[0],l[1]]
     B.ha=[0,0]
+    B.tag=c[0]
+    BP=courbes.ITEM[n0].beziers_knot[-1]
+    if BP.tag in ['c','C','s','S','m','M']:
+       BP.co[2]=B.co[4]
+       BP.co[3]=B.co[5]
     courbes.ITEM[n0].beziers_knot.append(B)    
-
-    CP=[l[0],l[1]]
-
-    if len(D)<c[1]+2 and D[c[1]+2] not in TAGcourbe :
-        c[1]+=1
+    CP=[B.co[0],B.co[1]]
+    if len(D)>c[1]+3 and D[c[1]+3] not in TAGcourbe :
+        c[1]+=2
         ligne_tracee_l(c, D, n0,CP) #L
-            
     return  courbes,n0,CP    
     
     
 def ligne_tracee_h(c,D,n0,CP): #H,h
-    #print '|',c[0],'|',len(c[0]),'  --> ',CP[0]
-    #print   'D   :',D,' \n CP  :', CP 
     if c[0]=='h':
-       l=["%4s"%(float(D[c[1]+1])+float(CP[0])),"%4s"%float(CP[1])]
+       l=[float(D[c[1]+1])+float(CP[0]),CP[1]]
     else:
-       l=["%4s"%float(D[c[1]+1]),"%4s"%float(CP[1])]        
+       l=[float(D[c[1]+1]),CP[1]]
     B=Bez()
     B.co=[l[0],l[1],l[0],l[1],l[0],l[1]]
     B.ha=[0,0]
+    B.tag=c[0]
+    BP=courbes.ITEM[n0].beziers_knot[-1]
+    if BP.tag in ['c','C','s','S','m','M']:
+        BP.co[2]=B.co[4]
+        BP.co[3]=B.co[5]
     courbes.ITEM[n0].beziers_knot.append(B)    
-
     CP=[l[0],l[1]]
-    #print 'CP', CP    
     return  courbes,n0,CP    
 
-def ligne_tracee_v(c,D,n0,CP): #V, v
-    #l=filtre_DATA(c,D,0)
-    
+def ligne_tracee_v(c,D,n0,CP): #V, v    
     if c[0]=='v':
-       l=["%4s"%float(CP[0]),
-          "%4s"%(float(D[c[1]+1])+float(CP[1]))]
-       #print '|',c[0],'|', len(c[0]) ,'  --> ',CP
+       l=[CP[0], float(D[c[1]+1])+CP[1]]
     else:
-       l=["%4s"%float(CP[0]),
-          "%4s"%float(D[c[1]+1])]        
-       #print '|',c[0],'|', len(c[0]) ,'  --> ',CP
-
+       l=[CP[0], float(D[c[1]+1])]               
     B=Bez()
     B.co=[l[0],l[1],l[0],l[1],l[0],l[1]]
     B.ha=[0,0]
+    B.tag=c[0]
+    BP=courbes.ITEM[n0].beziers_knot[-1]
+    if BP.tag in ['c','C','s','S','m','M']:
+        BP.co[2]=B.co[4]
+        BP.co[3]=B.co[5]
     courbes.ITEM[n0].beziers_knot.append(B)    
-
     CP=[l[0],l[1]]
-    #print 'CP', CP
-    return  courbes,n0,CP    
-
-def boucle_tracee_z(c,D,n0,CP): #Z
-    #print c
-    #CP=[]
     return  courbes,n0,CP    
      
 Actions=   {     "C" : courbe_vers_c,
@@ -517,81 +975,8 @@ Actions=   {     "C" : courbe_vers_c,
 TAGcourbe=Actions.keys()
 TAGtransform=['M','L','C','S','H','V','T','Q']
 tagTRANSFORM=0
-
-def get_content(val,t0):
-    t=t0[:] 
-    if t.find(' '+val+'="')!=-1:
-       t=t[t.find(' '+val+'="')+len(' '+val+'="'):]
-       val=t[:t.find('"')]
-       t=t[t.find('"'):]
-       return t0,val
-    else:
-       return t0,0
-
-def get_tag(val,t):
-    t=t[t.find('<'+val):]
-    val=t[:t.find('>')+1]
-    t=t[t.find('>')+1:]    
-    if DEBUG==3 : print t[:10], val
-    return t,val
-
-def get_data(val,t):
-    t=t[t.find('<'+val):]
-    val=t[:t.find('</'+val+'>')]
-    t=t[t.find('</'+val+'>')+3+len(val):]
-    if DEBUG==3 : print t[:10], val
-    return t,val
-    
-def get_val(val,t):
-    d=""
-    #print t
-    for l in t:
-        if l.find(val+'="')!=-1:
-            #print 'l', l
-            # 0.2.7 : - correction for inskape 0.40 cvs  SVG
-            l=l.replace('>','')
-            # 0.2.7 : -- end 
-            d=l[l[:-1].rfind('"')+1:-1]
-            #print 'd', d   
-            for nn in d:
-                if '0123456789.'.find(nn)==-1:
-                     d=d.replace(nn,"")
-                     #print d
-            d=float(d)
-            break
-        #else:
-        #  print l
-        d=0.0 
-    return d
-
-
-
-def get_BOUNDBOX(BOUNDINGBOX,SVG,viewbox):
-    if viewbox==0:
-        h=get_val('height',SVG)
-        if DEBUG==1 : print 'h : ',h
-        w=get_val('width',SVG)
-        if DEBUG==1 : print 'w :',w
-        BOUNDINGBOX['rec']=[0.0,0.0,w,h]
-        r=BOUNDINGBOX['rec']
-        BOUNDINGBOX['coef']=w/h       
-    else:
-        viewbox=viewbox.split()
-        BOUNDINGBOX['rec']=[float(viewbox[0]),float(viewbox[1]),float(viewbox[2]),float(viewbox[3])]
-        r=BOUNDINGBOX['rec']
-        BOUNDINGBOX['coef']=(r[2]-r[0])/(r[3]-r[1])       
-
-    return BOUNDINGBOX
-
-# 0.2.8 : - correction for inskape 0.40 cvs  SVG
-def repack_DATA2(DATA):   
-    for d in Actions.keys():
-        DATA=DATA.replace(d,d+' ')
-    return DATA    
-
-
 def wash_DATA(ndata):
-   print 'ndata', ndata, len(ndata)
    if ndata!='':
        while ndata[0]==' ': 
            ndata=ndata[1:]
@@ -599,17 +984,21 @@ def wash_DATA(ndata):
            ndata=ndata[:-1]
        if ndata[0]==',':ndata=ndata[1:]
        if ndata[-1]==',':ndata=ndata[:-1]
-       if ndata.find('-')!=-1 and ndata[ndata.find('-')-1] not in [' ',' ']:
+       #--------------------
+       # 0.4.0 : 'e'
+       #--------------------
+       if ndata.find('-')!=-1 and ndata[ndata.find('-')-1] not in [' ', ',', 'e']:
           ndata=ndata.replace('-',',-')
        ndata=ndata.replace(',,',',')    
        ndata=ndata.replace(' ',',')
        ndata=ndata.split(',')
        for n in ndata :
-          if n=='' : ndata.remove(n)
+          if n=='' : ndata.remove(n)   
    return ndata
-         
-       
-# 0.3.4 : - restructuration de la lecture des donnes paths
+
+#--------------------             
+# 0.3.4 : - reading data rewrittten
+#--------------------
 def list_DATA(DATA):
     """
     cette fonction doit retourner une liste proposant
@@ -618,238 +1007,304 @@ def list_DATA(DATA):
     Par exemple :
     d="'M0,14.0 z" devient ['M','0.0','14.0','z'] 
     """
-    while DATA.count('  ')!=0 :
-        DATA=DATA.replace('  ',' ')
-
     tagplace=[]
-    DATA=DATA.replace('\n','')
-
     for d in Actions.keys():
         b1=0
         b2=len(DATA)
         while DATA.find(d,b1,b2)!=-1 :
-            #print d, b1 
             tagplace.append(DATA.find(d,b1,b2))
             b1=DATA.find(d,b1,b2)+1
     tagplace.sort()
     tpn=range(len(tagplace)-1)
-    DATA2=[]
-
-    for t in tpn: 
-             
-       DATA2.append(DATA[tagplace[t]:tagplace[t]+1])    
-       print DATA2[-1]
-
-       ndata=DATA[tagplace[t]+1:tagplace[t+1]]
-       if DATA2[-1] not in ['z','Z'] :
+    #--------------------
+    # 0.3.5 :: short data,only one tag
+    #--------------------
+    if len(tagplace)-1>0:
+       DATA2=[]
+       for t in tpn: 
+          DATA2.append(DATA[tagplace[t]:tagplace[t]+1])    
+          ndata=DATA[tagplace[t]+1:tagplace[t+1]]
+          if DATA2[-1] not in ['z','Z'] :
+             ndata=wash_DATA(ndata)
+             for n in ndata : DATA2.append(n)       
+       DATA2.append(DATA[tagplace[t+1]:tagplace[t+1]+1])   
+       if DATA2[-1] not in ['z','Z'] and len(DATA)-1>=tagplace[t+1]+1:
+          ndata=DATA[tagplace[t+1]+1:-1]
           ndata=wash_DATA(ndata)
           for n in ndata : DATA2.append(n)
-       
-    DATA2.append(DATA[tagplace[t+1]:tagplace[t+1]+1])   
-       
-    print DATA2[-1]
-       
-    if DATA2[-1] not in ['z','Z'] and len(DATA)-1>=tagplace[t+1]+1:
-       ndata=DATA[tagplace[t+1]+1:-1]
-       ndata=wash_DATA(ndata)
-       for n in ndata : DATA2.append(n)
-
+    else:
+        #--------------------  
+        # 0.3.5 : short data,only one tag
+        #--------------------
+        DATA2=[]
+        DATA2.append(DATA[tagplace[0]:tagplace[0]+1])
+        ndata=DATA[tagplace[0]+1:]
+        ndata=wash_DATA(ndata)
+        for n in ndata : DATA2.append(n)
     return DATA2    
 
-
 # 0.3
-def translate(tx,ty):
+def translate(tx=None,ty=None):
     return [1, 0, tx], [0, 1, ty],[0,0,1]
-
 # 0.3.2
-def scale(sx,sy):
+def scale(sx=None,sy=None):
+    if sy==None: sy=sx
     return [sx, 0, 0], [0, sy, 0],[0,0,1]
-# 0.3.2
+# 0.4.1 : transslate a in radians
 def rotate(a):
-    return [cos(a), -sin(a), 0], [sin(a), cos(a),0],[0,0,1]
+    return [cos(a*3.1416/90.0), -sin(a*3.1416/90.0), 0], [sin(a*3.1416/90.0), cos(a*3.1416/90.0),0],[0,0,1]
 # 0.3.2
 def skewX(a):
     return [1, tan(a), 0], [0, 1, 0],[0,0,1]
-# 0.3.2
-def skewX(a):
+# 0.4.1
+def skewY(a):
     return [1, 0, 0], [tan(a), 1 , 0],[0,0,1]
 # 0.3.2
 def matrix(a,b,c,d,e,f):
-    return [a,b,e],[c,d,f],[0,0,1]
+    return [a,c,e],[b,d,f],[0,0,1]
 
-# 0.3.3
-def controle_CONTENU(val,t):
+# 0.4.2 : rewritten 
+def control_CONTAINT(txt):
     """
-    une matrice peut s'ecrire : matrix(a,b,c,d,e,f) ou matrix(a b c d e f)
+    les descriptions de transformation peuvent être seules ou plusieurs et
+    les séparateurs peuvent avoir été oubliés
     """
-    if val.find('matrix') and t.find(val+'(')!=-1 and t.find(val+',')==-1:
-       t0=t[t.find(val+'(')+len(val+'('):]
-       t0=t0[:t0.find(')')]
-       val=t0[:]
-       while val.find('  ')!=-1:
-           val=val.replace('  ',' ')
-       val=val.replace(' ',',')
-       t=t.replace(t0,val)
-       return val
-    else:
-       return -1
-
-# 0.3    
-def get_TRANSFORM(STRING):
-    STRING,TRANSFORM=get_content('transform',STRING)
-    #print 'TRANSFORM 1 :', TRANSFORM
-    for t in ['translate','scale','rotate','matrix','skewX','skewY'] :
-       if TRANSFORM.find(t)!=-1 and TRANSFORM.count('(')==1:
-         #print 'TRANSFORM 2 :', TRANSFORM
-         print ' getcontent ', t,' ',controle_CONTENU(t,TRANSFORM)
-         exec "a,b,c=%s;T=Mathutils.Matrix(a,b,c)"%TRANSFORM       
-    return  T
-
-# 0.3
-def G_move(l,a,t):
-    if a==0:
-        v=Mathutils.Vector([float(l[0]),float(l[1]),1.0])
-        v=Mathutils.MatMultVec(t, v)
-        return str(v[0]),str(v[1])
-    else :
-       #print 'l', l ,'t', t, 'a', a
-       l=l.split(',')
-       v=Mathutils.Vector([float(l[0]),float(l[1]),1.0])
-       v=Mathutils.MatMultVec(t, v)            
-       return str(v[0])+','+str(v[1])
-    
-# 0.3    
-def transform_DATA(D1,TRANSFORM):   
-    for cell in range(len(D1)):
-        if D1[cell] in TAGtransform:
-           if D1[cell+1].find(',')==-1:       
-                if D1[cell] in ['C', 'S','Q', 'M','L','T',]: #2 valeurs
-                    D1[cell+1],D1[cell+2]=G_move([D1[cell+1],D1[cell+2]],0,TRANSFORM)
-                    if D1[cell] in ['C', 'S','Q'] :
-                       D1[cell+3],D1[cell+4]=G_move([D1[cell+3],D1[cell+4]],0,TRANSFORM)
-                       if D1[cell] in ['C']:
-                          D1[cell+5],D1[cell+6]=G_move([D1[cell+5],D1[cell+6]],0,TRANSFORM)
-           else :
-                if D1[cell] == 'C': #6 valeurs
-                    D1[cell+1]=G_move(D1[cell+1],-1,TRANSFORM)
-                    D1[cell+2]=G_move(D1[cell+2],-1,TRANSFORM)
-                    D1[cell+3]=G_move(D1[cell+3],-1,TRANSFORM)
-                elif D1[cell] in ['M','L','T']: #2 valeurs
-                    D1[cell+1]=G_move(D1[cell+1],-1,TRANSFORM)
-                elif D1[cell] == ['S','Q']: #4 valeurs
-                    D1[cell+1]=G_move(D1[cell+1],-1,TRANSFORM)
-                    D1[cell+2]=G_move(D1[cell+2],-1,TRANSFORM)
-           if D1[cell] == 'H': #1 valeurs x
-                n=0
-                D1[cell+1]=G_move(D1[cell+1],0,TRANSFORM)
-           elif D1[cell] == 'V': #1 valeurs y
-                n=0
-                D1[cell+1]=G_move(D1[cell+1],1,TRANSFORM)
-    return D1            
-                
-def format_PATH(t,TRANSFORM):
-    global tagTRANSFORM
-    
-    t,PATH=get_tag('path',t)
-
-    if PATH.find(' transform="')!=-1:
-       TRANSFORM2=get_TRANSFORM(PATH)
-       # 0.3.3
-       TRANSFORM=TRANSFORM*TRANSFORM2
-       #TRANSFORM[1]+=TRANSFORM2[1]
-       tagTRANSFORM+=1
-       
-    if PATH.find(' id="')!=-1:
-       PATH,ID=get_content('id',PATH)
-       #print 'ident = ', ID
-
-    if PATH.find(' STROKE="')!=-1:
-       PATH,ID=get_content('stroke',PATH)
-       #print 'path stroke = ', ID
-
-    if PATH.find(' stroke-width="')!=-1:
-       PATH,ID=get_content('stroke-width',PATH)
-       #print 'path stroke-width = ', ID
-
-    if PATH.find(' d="')!=-1:
-       PATH,D=get_content('d',PATH)
-    D=list_DATA(D)
-
-    if  tagTRANSFORM in [1,2] : D=transform_DATA(D,TRANSFORM)
-    return t,D
-
+    t0=0
+    tlist=[]
+    while txt.count(')',t0)>0:
+        t1=txt.find(')',t0)
+        nt0=txt[t0:t1+1]
+        t2=nt0[nt0.find('(')+1:-1]
+        val=nt0[:nt0.find('(')]
+        while t2.find('  ')!=-1:
+                 t2=t2.replace('  ',' ')
+        t2=t2.replace(' ',',')
+        if t2.find('e'):
+              t3=t2.split(',')
+              t2='' 
+              for t in t3 :
+                   t=str(float(t)) 
+              t2=str(t3).replace(']','').replace('[','').replace('\'','')
+        if val=='rotate' :
+           t3=t2.split(',')
+           if len(t3)==3:
+              tlist.append('translate('+t3[1]+','+t3[2]+')')
+              tlist.append('rotate('+t3[0]+')')
+              tlist.append('translate(-'+t3[1]+',-'+t3[2]+')')
+        else:
+              tlist.append(val+'('+t2+')')
+        t0=t1+1
+    return tlist
+
+# 0.4.1 : apply transform stack
+def courbe_TRANSFORM(Courbe,proprietes):
+    # 1/ deplier le STACK
+    #   créer une matrice pour chaque transformation    
+    ST=[]
+    #print proprietes['stack'] 
+    for st in proprietes['stack'] :
+        if st and  type(st)==list:
+          for t in st:
+               exec "a,b,c=%s;T=Mathutils.Matrix(a,b,c)"%control_CONTAINT(t)[0]
+               ST.append(T)
+        elif st :
+           exec "a,b,c=%s;T=Mathutils.Matrix(a,b,c)"%control_CONTAINT(st)[0]
+           ST.append(T)              
+    if 'transform' in proprietes.keys():
+        for trans in control_CONTAINT(proprietes['transform']):
+           exec """a,b,c=%s;T=Mathutils.Matrix(a,b,c)"""%trans
+           ST.append(T)
+           #print ST
+    ST.reverse()
+    for n in proprietes['n']:
+     if n in Courbe.keys():
+        for bez0 in Courbe[n].beziers_knot:
+          bez=bez0.co
+          for b in [0,2,4]:
+              for t in ST:
+                 v=Mathutils.Vector([bez[b],bez[b+1],1.0])
+                 #v=Mathutils.MatMultVec(t, v)
+                 v=t * v
+                 bez[b]=v[0]
+                 bez[b+1]=v[1]          
+
+def filtre(d):
+    for nn in d:
+       if '0123456789.'.find(nn)==-1:
+          d=d.replace(nn,"")
+    return d
 
+def get_BOUNDBOX(BOUNDINGBOX,SVG):
+    if 'viewbox' not in SVG.keys():
+        h=float(filtre(SVG['height']))
+        if DEBUG==1 : print 'h : ',h
+        w=float(filtre(SVG['width']))
+        if DEBUG==1 : print 'w :',w
+        BOUNDINGBOX['rec']=[0.0,0.0,w,h]
+        r=BOUNDINGBOX['rec']
+        BOUNDINGBOX['coef']=w/h       
+    else:
+        viewbox=SVG['viewbox'].split()
+        BOUNDINGBOX['rec']=[float(viewbox[0]),float(viewbox[1]),float(viewbox[2]),float(viewbox[3])]
+        r=BOUNDINGBOX['rec']
+        BOUNDINGBOX['coef']=(r[2]-r[0])/(r[3]-r[1])       
+    return BOUNDINGBOX
 
+# 0.4.1 : attributs ex : 'id=', 'transform=', 'd=' ...
+def collecte_ATTRIBUTS(data):
+    data=data.replace('  ',' ')
+    ELEM={'TYPE':data[1:data.find(' ')]}
+    t1=len(data)
+    t2=0
+    ct=data.count('="')
+    while ct>0:
+        t0=data.find('="',t2)
+        t2=data.find(' ',t2)+1
+        id=data[t2:t0]
+        t2=data.find('"',t0+2)
+        if id!='d':
+           exec "ELEM[id]=\"\"\"%s\"\"\""%(data[t0+2:t2].replace('\\','/'))
+        else:
+              exec "ELEM[id]=[%s,%s]"%(t0+2,t2) 
+        ct=data.count('="',t2)
+    return ELEM
+
+# --------------------------------------------
+# 0.4.1 : to avoid to use sax and ths xml  
+#         tools of the complete python
+# --------------------------------------------
+def contruit_HIERARCHIE(t):
+    global CP, courbes, SCALE, DEBUG, BOUNDINGBOX, scale_, tagTRANSFORM
+    TRANSFORM=0
+    t=t.replace('\t',' ')
+    while t.find('  ')!=-1:
+          t=t.replace('  ',' ')
+    n0=0      
+    t0=t1=0
+    baliste=[]
+    balisetype=['?','?','/','/','!','!']
+    BALISES=['D',  #DECL_TEXTE',
+             'D',  #DECL_TEXTE',
+             'F',  #FERMANTE',
+             'E',  #ELEM_VIDE',
+             'd',  #DOC',
+             'R',  #REMARQUES',
+             'C',  #CONTENU',
+             'O'   #OUVRANTE'
+             ]
+    STACK=[]
+    while t1<len(t) and t0>-1:
+      t0=t.find('<',t0)
+      t1=t.find('>',t0)
+      ouvrante=0
+      #--------------------
+      # 0.4.4 , add 'else:' and 'break' to the 'if' statement
+      #--------------------
+      if t0>-1 and t1>-1:
+          if t[t0+1] in balisetype:
+             b=balisetype.index(t[t0+1])
+             if t[t0+2]=='-': 
+               b=balisetype.index(t[t0+1])+1
+             balise=BALISES[b]
+             if b==2:
+                 parent=STACK.pop(-1)
+                 if parent!=None and TRANSFORM>0:
+                     TRANSFORM-=1
+          elif t[t1-1] in balisetype:
+            balise=BALISES[balisetype.index(t[t1-1])+1]
+          else:
+            t2=t.find(' ',t0)  
+            if t2>t1: t2=t1
+            ouvrante=1
+            NOM=t[t0+1:t2]
+            if t.find('</'+NOM)>-1:
+               balise=BALISES[-1]
+            else:
+               balise=BALISES[-2]
+          if balise=='E' or balise=='O':
+             proprietes=collecte_ATTRIBUTS(t[t0:t1+ouvrante])
+             if  balise=='O' and 'transform' in proprietes.keys():
+                 STACK.append(proprietes['transform'])
+                 TRANSFORM+=1   
+             elif balise=='O' : 
+                 STACK.append(None)
+             proprietes['stack']=STACK[:]
+             D=[] 
+             if proprietes['TYPE'] in ['path'] and (proprietes['d'][1]-proprietes['d'][0]>1):
+                 D=list_DATA(t[proprietes['d'][0]+t0:proprietes['d'][1]+t0])
+             elif proprietes['TYPE'] in OTHERSSHAPES:
+                 exec "D=%s(proprietes)"% proprietes['TYPE']
+             if len(D)>0:
+                 cursor=0
+                 proprietes['n']=[]
+                 for cell in D: 
+                   if DEBUG==2 : print 'cell : ',cell ,' --'                   
+                   if len(cell)>=1 and cell[0] in TAGcourbe:
+                       prop=''
+                       if cell[0] in ['m','M']: 
+                                    prop=',proprietes'
+                       exec """courbes,n0,CP=Actions[cell]([cell,cursor], D, n0,CP%s)"""%prop
+                   cursor+=1
+                 if TRANSFORM>0 or 'transform' in proprietes.keys() :
+                     courbe_TRANSFORM(courbes.ITEM,proprietes)
+             elif proprietes['TYPE'] in ['svg'] :
+                   BOUNDINGBOX = get_BOUNDBOX(BOUNDINGBOX,proprietes)          
+      else:
+         #--------------------
+         # 0.4.4 
+         #--------------------
+         break
+      t1+=1
+      t0=t1             
                         
 def scan_FILE(nom):
-  global CP, courbes, SCALE, DEBUG, BOUNDINGBOX, scale, tagTRANSFORM
+  global CP, courbes, SCALE, DEBUG, BOUNDINGBOX, scale_, tagTRANSFORM
   dir,name=split(nom)
   name=name.split('.')
-  n0=0
   result=0
-  
   t=filtreFICHIER(nom)
-  
   if t!='false':
+     Blender.Window.EditMode(0)
      if not SHARP_IMPORT:
          warning = "Select Size : %t| As is %x1 | Scale on Height %x2| Scale on Width %x3" 
-         scale = Blender.Draw.PupMenu(warning)
-     npat=0
-     l=0
-     do=0
-     t,SVG=get_tag('svg',t)
-
-     SVG,viewbox=get_content('viewBox',SVG)
-
-     SVG=SVG.split(' ')
-     if DEBUG==1 : print SVG
-     if viewbox==0:
-          BOUNDINGBOX = get_BOUNDBOX(BOUNDINGBOX,SVG,0)
-     else:
-          BOUNDINGBOX = get_BOUNDBOX(BOUNDINGBOX,SVG,viewbox)
-          
-     while t.find('<g')!=-1:
-         t,G=get_data('g',t)
-         TRANSFORM=Mathutils.Matrix([1.0,0.0,0.0],[0.0,1.0,0.0],[0,0,1])
-         tagTRANSFORM=0
-         if G.find(' transform="')!=-1:  
-            TRANSFORM=get_TRANSFORM(G)
-            tagTRANSFORM=1
-            
-         while G.find('path')!=-1: 
-            G,D=format_PATH(G,TRANSFORM)
-            #print D
-            cursor=0
-            for cell in D: 
-              if DEBUG==2 : print 'cell : ',cell ,' --'                   
-              if len(cell)>=1 and cell[0] in TAGcourbe:
-                   courbes,n0,CP=Actions[cell]([cell,cursor], D, n0,CP)            
-              cursor+=1
-              
-     # 0.3.1
-     while t.find('path')!=-1:
-            TRANSFORM=Mathutils.Matrix([1.0,0.0,0.0],[0.0,1.0,0.0],[0,0,1])
-            t,D=format_PATH(t,TRANSFORM)
-            cursor=0
-            for cell in D: 
-              if DEBUG==2 : print 'cell : ',cell ,' --'                   
-              if len(cell)>=1 and cell[0] in TAGcourbe:
-                   courbes,n0,CP=Actions[cell]([cell,cursor], D, n0,CP)            
-              cursor+=1
-
+         scale_ = Blender.Draw.PupMenu(warning)
+     # 0.4.1 : to avoid to use sax and the xml  
+     #         tools of the complete python
+     contruit_HIERARCHIE(t)
+     r=BOUNDINGBOX['rec']
+     if scale_==1:
+        SCALE=1.0
+     elif scale==2:
+        SCALE=r[2]-r[0]
+     elif scale_==3:
+        SCALE=r[3]-r[1]
   courbes.number_of_items=len(courbes.ITEM.keys())
-
   for k in courbes.ITEM.keys():
      courbes.ITEM[k].pntsUV[0] =len(courbes.ITEM[k].beziers_knot)
 
-  if courbes.number_of_items>0:
+  #--------------------
+  # 0.4.5
+  #--------------------
+  CVS=2
+  if BLversion>=238 : 
+     warning = "CVS version you can import as : %t| Blender internal, experimental ? %x1 |  Old proofed method, import using Blender OBJ format  %x2" 
+     CVS=Blender.Draw.PupMenu(warning)
+
+  if courbes.number_of_items>0 and CVS==2:
      if len(PATTERN.keys() )>0:
         if DEBUG == 3 : print len(PATTERN.keys() )
      t=create_GEOtext(courbes)
      save_GEOfile(dir,name[0],t)
      Open_GEOfile(dir,name[0])
+
+  elif courbes.number_of_items>0 and CVS==1 :
+          #--------------------
+     # 0.4.5
+     #--------------------
+          createCURVES(courbes)
+       
   else:
-      pass
+     pass      
     
 def  ajustement(v,s):
      
@@ -868,4 +1323,4 @@ def fonctionSELECT(nom):
     scan_FILE(nom)
 
 if __name__=='__main__':
-   Blender.Window.FileSelector (fonctionSELECT, 'SELECT a .SVG FILE')
+   Blender.Window.FileSelector (fonctionSELECT, 'SELECT a .SVG FILE')
\ No newline at end of file
index ec04f59d60f3db74d0458ffed2303a9b965d7b4d..e4430cdad965d41d210df61f74e261937cd0fb65 100644 (file)
@@ -1,40 +1,60 @@
 #!BPY
 """
-Name: 'BVH Empties to Armature'
-Blender: 237
+Name: 'Empties to Armature'
+Blender: 241
 Group: 'Animation'
-Tooltip: 'Create Armature from Empties created by BVH importer'
+Tooltip: 'Create Armature from a parented-empties chain'
 """
-__author__ = " Jean-Baptiste PERIN (jb_perin(at)yahoo.fr)"
+__author__ = " Jean-Baptiste PERIN (jb_perin(at)yahoo.fr) with valuable help from Vincent BILLET "
 __url__ = ("blender", "elysiun",
-"BVH 2 ARMATURE, http://www.zoo-logique.org/3D.Blender/index.php3?zoo=dld&rep=zip ",
+"BVH 2 ARMATURE, http://perso.wanadoo.fr/jb.perin/",
 "Communicate problems and errors, http://www.zoo-logique.org/3D.Blender/newsportal/thread.php?group=3D.Blender") 
 
-__version__ = "2.2"
+__version__ = "2.42"
 
-__bpydoc__ = """ BVH2ARM.py v2.2
+__bpydoc__ = """ BVH2ARM.py 
 
 Script for generating armature on BVH empties.
 
-This script generates an armature and make bones
-follow empties created by Blender BVH import script.
+This script generates an armature upon an empty-made parented chain, 
+and make the armature follow the empties 
+
 Usage:<br>
  - Import a bvh in Blender (File->Import->BVH);<br>
- - Launch this script (Alt-P);<br>
+ - Rotate some empties to match your model and insert Rot key for them. <br>
+ - Select the root empty of the hierarchical chain.<br>
+ - Launch this script ;<br>
  - Set up variables:<br>
-   "hipbonename": the name of the main bone;<br>
+   "hipbonename": the name of the main bone (automatically set to the selected empty).<br>
    "startframe":  the first frame of your anim;<br>
    "endframe":  the last frame of your anim;<br>
-   "decimation": the frequency (in number of frame) to which the armature is updated;<br>
-   "scale" to size the created armature.<br>
- - Press "Create Armature".
+   "decimation": the frequency (in number of frame) to which the armature's pos is updated;<br>
+- Press "Create Armature".
+Notes: <br>
+- The start frame configuration is used as the rest pose for the armature.<br>
+- If the armature already exists when script is launched, the current armature is re-used.
 """
-
-#----------------------------------------------
-# (c) Jean-Baptiste PERIN  june 2005, released under Blender Artistic Licence
-#    for the Blender 2.34-2.36 Python Scripts Bundle.
-#----------------------------------------------
+# -------------------------------------------------------------------------- 
+# BVH2ARM.py 
+# -------------------------------------------------------------------------- 
+# ***** BEGIN GPL LICENSE BLOCK ***** 
+# 
+# This program is free software; you can redistribute it and/or 
+# modify it under the terms of the GNU General Public License 
+# as published by the Free Software Foundation; either version 2 
+# of the License, or (at your option) any later version. 
+# 
+# This program is distributed in the hope that it will be useful, 
+# but WITHOUT ANY WARRANTY; without even the implied warranty of 
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the 
+# GNU General Public License for more details. 
+# 
+# You should have received a copy of the GNU General Public License 
+# along with this program; if not, write to the Free Software Foundation, 
+# Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA. 
+# 
+# ***** END GPL LICENCE BLOCK ***** 
+# -------------------------------------------------------------------------- 
 
 
 
@@ -50,6 +70,9 @@ dicEmptyChild={}
 dicBoneRestInvEmpRest={}
 dicEmpRestInvBoneRest={}
 restFrame = 1
+bonerest={}
+emprest={}
+emp2bone={}
 
 ########################################################################
 #
@@ -111,8 +134,8 @@ def getEmpty(name):
                        p = o
        return p
 
-def getChild(emp, emp_list):
-       return dicEmptyChild[emp.getName()]
+##def getChild(emp, emp_list):
+##     return dicEmptyChild[emp.getName()]
 
 
 #########
@@ -206,32 +229,6 @@ def GetOrCreateCurve(ipo, curvename):
 #
 ########################################################################
 
-def computeRootQuat2(empty, bone):
-
-       M1=dicBoneRestInvEmpRest[bone.getName()].rotationPart()
-       M2=dicEmpRestInvBoneRest[bone.getName()].rotationPart()
-       emprot = empty.getMatrix('worldspace').rotationPart()
-       emprot.transpose()
-       mat = M1*emprot*M2
-       mat.transpose()
-       return (mat.toQuat())
-
-       #emprest = dicEmptiesRestMatrix[empty.getName()].rotationPart()
-       #invemprest= dicEmptiesRestMatrix[empty.getName()].rotationPart()
-       ##invemprest= emprest
-       ##invemprest.invert()
-       ##invemprest= dicEmptiesInvRestMatrix[empty.getName()].rotationPart()
-       #emprot = empty.getMatrix('worldspace').rotationPart()
-       #bonerest = dicBoneRestMatrix[bone.getName()].rotationPart()
-       #invbonerest = dicBoneRestMatrix[bone.getName()].rotationPart()
-       #invbonerest.invert()
-       #T2=emprot*invemprest
-       #T2.transpose()
-       #mat = bonerest*invemprest*T2*emprest*invbonerest
-       #mat.transpose()
-       #return (mat.toQuat())
-
-
 
 
 #########
@@ -239,27 +236,6 @@ def computeRootQuat2(empty, bone):
 # in  : 
 # out : 
 #########
-def computeRootPos(empty, bone):
-       vec = computeScaledPos(empty.getMatrix('worldspace').translationPart()) - dicBoneRestMatrix[bone.getName()].translationPart()
-       mat = dicBoneRestMatrix[bone.getName()].rotationPart()
-       vec2 =  Mathutils.MatMultVec (mat, vec)
-       return vec2
-
-
-def computeRelativePos(empty,bone):
-       vec = computeScaledPos(empty.getMatrix('worldspace').translationPart()) - dicBoneRestMatrix[bone.getName()].translationPart()
-       rootempty = getEmpty(hipbonename)
-       vec3 = computeScaledPos(rootempty.getMatrix('worldspace').translationPart())
-       mat = dicBoneRestMatrix[bone.getName()].rotationPart()
-       vec2 =  Mathutils.MatMultVec (mat, vec-vec3)
-       return vec2
-
-
- #########
-# Cette fonction 
-# in  : 
-# out : 
-#########
 def computeScaledPos(vec):
        global scalef
        vec2 = Mathutils.Vector([vec[0]*scalef, vec[1]*scalef, vec[2]*scalef])
@@ -277,31 +253,28 @@ def computeScaledPos(vec):
 # out : 
 #########
 def createBone (armature, empty, bone, empties):
+        global bonerest, emprest
        children = getChildren(empty, empties)
-       for ch in children:
+       if len(children) != 0:
+         for ch in children:
                if len(children) >= 2:
                        bonename = empty.getName()[1:len(empty.getName())]+'_'+ch.getName()[1:len(ch.getName())]
                else :
                        bonename = empty.getName()[1:len(empty.getName())]
-               b=Blender.Armature.Bone.New(bonename)
-               b.setHead(computeScaledPos(empty.getMatrix('worldspace').translationPart()))
-               b.setTail(computeScaledPos(ch.getMatrix('worldspace').translationPart()))
-               #b.setParent(bone)
-               matrice = empty.getMatrix('worldspace')
-               invmatrice = empty.getMatrix('worldspace')
-               invmatrice.invert()
-               invmatricet=empty.getMatrix('worldspace')
-               invmatricet.invert()
-               invmatricet.transpose()
-               dicEmptiesRestMatrix[empty.getName()] = matrice
-               dicEmptiesInvRestMatrix[empty.getName()] = invmatrice
-               armature.addBone(b)
-               invbonerest=b.getRestMatrix()
-               invbonerest.invert()
-               dicBoneRestMatrix[b.getName()] = b.getRestMatrix()
-               dicBoneRestInvEmpRest[b.getName()]=b.getRestMatrix()*invmatrice*invmatricet
-               dicEmpRestInvBoneRest[b.getName()]=matrice*invbonerest
-               dicBone[b.getName()]=b
+               print "creating Bone %s"%(bonename)
+               b=Blender.Armature.Editbone()
+               b.head = (computeScaledPos(empty.getMatrix('worldspace').translationPart()))
+               b.tail = (computeScaledPos(ch.getMatrix('worldspace').translationPart()))
+               b.parent = bone
+               # armature.makeEditable()  should already be editable????
+               armature.bones[bonename] = b
+               #print b.matrix
+               bonerest[bonename]=Blender.Mathutils.Matrix(b.matrix).resize4x4()
+               emprest[empty.getName()]=Blender.Mathutils.Matrix(empty.getMatrix('localspace')).resize4x4()
+               #M = Blender.Mathutils.Matrix(emprest[empty.getName()])
+               #emp2bone[bonename] =  Blender.Mathutils.Matrix(M.invert().rotationPart()*bonerest[bonename].rotationPart()).resize4x4()
+               #print emp2bone[bonename].rotationPart().toEuler()
+               dicBone[b.name]=b
                createBone(armature, ch, b, empties)
 
 #########
@@ -310,13 +283,12 @@ def createBone (armature, empty, bone, empties):
 # out : 
 #########
 def f_createBone (armData, empty, bone, empties):
-       bones = armData.getBones()
-
+       bones = armData.bones.values()
        def getBone(bonename):
                bone = None
                for b in bones:
                        #print b.getName()
-                       if b.getName() == bonename:
+                       if b.name == bonename:
                                bone = b
                return bone
 
@@ -328,56 +300,41 @@ def f_createBone (armData, empty, bone, empties):
                        bonename = empty.getName()[1:len(empty.getName())]
                #b=Blender.Armature.Bone.New(bonename)
                b=getBone(bonename)
-               #b.setHead(empty.getMatrix('worldspace').translationPart())
-               #b.setTail(ch.getMatrix('worldspace').translationPart())
-               #b.setParent(bone)
-               matrice = empty.getMatrix('worldspace')
-               invmatrice = empty.getMatrix('worldspace')
-               invmatrice.invert()
-               invmatricet=empty.getMatrix('worldspace')
-               invmatricet.invert()
-               invmatricet.transpose()
-               dicEmptiesRestMatrix[empty.getName()] = matrice
-               dicEmptiesInvRestMatrix[empty.getName()] = invmatrice
-               #armature.addBone(b)
-               invbonerest=b.getRestMatrix()
-               invbonerest.invert()
-               dicBoneRestMatrix[b.getName()] = b.getRestMatrix()
-               dicBoneRestInvEmpRest[b.getName()]=b.getRestMatrix()*invmatrice*invmatricet
-               dicEmpRestInvBoneRest[b.getName()]=matrice*invbonerest
-               dicBone[b.getName()]=b
+               b.head = (computeScaledPos(empty.getMatrix('worldspace').translationPart()))
+               b.tail = (computeScaledPos(ch.getMatrix('worldspace').translationPart()))
+               b.parent = bone
+               bonerest[bonename]=Blender.Mathutils.Matrix(b.matrix).resize4x4()
+               emprest[empty.getName()]=Blender.Mathutils.Matrix(empty.getMatrix('localspace')).resize4x4()
+               dicBone[b.name]=b
                #print "Ajout de ", b.getName(),"  au dictionnaire"
                f_createBone(armData, ch, b, empties)
        
-
 #########
 # Cette fonction fabrique une arma
 # in  : 
 # out : 
 #########
-def createArmature (rootEmpty, empties):
-       armData=Blender.Armature.New('monArmature')
+def createArmature (armObj, rootEmpty, empties):
+        global bonerest, emprest
+       armData=Blender.Armature.Armature('monArmature')
        children = getChildren(rootEmpty, empties)
+       armObj.link(armData)
+       armData.makeEditable()
        for ch in children:
-               b=Blender.Armature.Bone.New(rootEmpty.getName()[1:len(rootEmpty.getName())] + ch.getName()[1:len(ch.getName())])
-               b.setHead(computeScaledPos(rootEmpty.getMatrix('worldspace').translationPart()))
-               b.setTail(computeScaledPos(ch.getMatrix('worldspace').translationPart()))
-               armData.addBone(b)
-               matrice = ch.getMatrix('worldspace')
-               invmatrice = ch.getMatrix('worldspace')
-               invmatrice.invert()
-               invmatricet=ch.getMatrix('worldspace')
-               invmatricet.invert()
-               invmatricet.transpose()
-               dicEmptiesRestMatrix[rootEmpty.getName()] = matrice
-               dicEmptiesInvRestMatrix[rootEmpty.getName()] = invmatrice
-               invbonerest=b.getRestMatrix()
-               invbonerest.invert()
-               dicBoneRestMatrix[b.getName()] = b.getRestMatrix()
-               dicBoneRestInvEmpRest[b.getName()]=b.getRestMatrix()*invmatrice*invmatricet
-               dicEmpRestInvBoneRest[b.getName()]=matrice*invbonerest
-               dicBone[b.getName()]=b
+               b=Blender.Armature.Editbone()
+               bonename = rootEmpty.getName()[1:len(rootEmpty.getName())] + ch.getName()[1:len(ch.getName())]
+               print "creating Bone %s"%(bonename)
+
+               #print b, dir([b])
+               b.head=(computeScaledPos(rootEmpty.getMatrix('worldspace').translationPart()))
+               b.tail=(computeScaledPos(ch.getMatrix('worldspace').translationPart()))
+               
+               bonerest[bonename]=Blender.Mathutils.Matrix(b.matrix).resize4x4()
+               emprest[rootEmpty.getName()]=Blender.Mathutils.Matrix(rootEmpty.getMatrix('localspace')).resize4x4()
+               armData.bones[bonename] = b
+               dicBone[b.name]=b
                createBone(armData, ch, b, empties)
+       armData.update()
        return armData
 
 
@@ -388,37 +345,27 @@ def createArmature (rootEmpty, empties):
 # out : 
 #########
 def f_createArmature (rootEmpty, empties, armData):
-       bones = armData.getBones()
+       armData.makeEditable()
+       bones = armData.bones.values()
 
        def getBone(bonename):
                bone = None
                for b in bones:
                        #print b.getName()
-                       if b.getName() == bonename:
+                       if b.name == bonename:
                                bone = b
                return bone
 
        children = getChildren(rootEmpty, empties)
        for ch in children:
                b=getBone(rootEmpty.getName()[1:len(rootEmpty.getName())] + ch.getName()[1:len(ch.getName())])
-               matrice = ch.getMatrix('worldspace')
-               invmatrice = ch.getMatrix('worldspace')
-               invmatrice.invert()
-               invmatricet=ch.getMatrix('worldspace')
-               invmatricet.invert()
-               invmatricet.transpose()
-               dicEmptiesRestMatrix[rootEmpty.getName()] = matrice
-               dicEmptiesInvRestMatrix[rootEmpty.getName()] = invmatrice
-               invbonerest=b.getRestMatrix()
-               invbonerest.invert()
-               dicBoneRestMatrix[b.getName()] = b.getRestMatrix()
-               dicBoneRestInvEmpRest[b.getName()]=b.getRestMatrix()*invmatrice*invmatricet
-               dicEmpRestInvBoneRest[b.getName()]=matrice*invbonerest
-               dicBone[b.getName()]=b
+               dicBone[b.name]=b
                #print "Ajout de ", b.getName(),"  au dictionnaire"
-               
+               bonerest[b.name]=Blender.Mathutils.Matrix(b.matrix).resize4x4()
+               emprest[rootEmpty.getName()]=Blender.Mathutils.Matrix(rootEmpty.getMatrix('localspace')).resize4x4()
                f_createBone(armData, ch, b, empties)
 
+       armData.update()
 
 
 #########
@@ -426,20 +373,34 @@ def f_createArmature (rootEmpty, empties, armData):
 # in  : 
 # out : 
 #########
-def moveBones(armature, empty, empties):
+def moveBones(larmature, empty, empties):
+        #print "move bones"
+        global bonerest, emprest
        children = dicEmptyChild[empty.getName()]
+       thepose = larmature.getPose()
        for ch in children:
                if len(children) >= 2:
                        bonename = empty.getName()[1:len(empty.getName())]+'_'+ch.getName()[1:len(ch.getName())]
                else :
                        bonename = empty.getName()[1:len(empty.getName())]
-               bone = dicBone[bonename]
-               #bone.setLoc(computeRootPos(empty,bone))
-               bone.setLoc(computeRelativePos(empty,bone))
-               bone.setQuat(computeRootQuat2(empty,bone))
-               chch = dicEmptyChild[ch.getName()]
+               thebone = thepose.bones[bonename]
+               trMatrix = empty.getMatrix('localspace')
+               bonerestmat = Blender.Mathutils.Matrix(bonerest[bonename])
+               invbonerestmat = Blender.Mathutils.Matrix(bonerest[bonename])
+               invbonerestmat.invert()
+               trMatrix[3][0] = 0.0
+               trMatrix[3][1] = 0.0
+               trMatrix[3][2] = 0.0
+               invemprestmat = Blender.Mathutils.Matrix(emprest[empty.getName()].rotationPart()).resize4x4()
+               invemprestmat.invert()
+               emprestmat = Blender.Mathutils.Matrix(emprest[empty.getName()].rotationPart()).resize4x4()
+               thebone.localMatrix = bonerestmat* invemprestmat *trMatrix * invbonerestmat 
+                thepose.update()
+                thebone.insertKey(larmature, Blender.Get('curframe'), [Blender.Object.Pose.ROT, Blender.Object.Pose.LOC])
+                thepose.update()
+                chch = dicEmptyChild[ch.getName()]
                if len(chch) >= 1:
-                       moveBones(armature, ch, empties)
+                       moveBones(larmature, ch, empties)
 
 
 #########
@@ -447,26 +408,20 @@ def moveBones(armature, empty, empties):
 # in  : 
 # out : 
 #########
-def moveArmature (armature, empties):
+def moveArmature (larmature, empties):
+        global bonerest, emprest
+        #print "move armature"
+        thepose = larmature.getPose()
+        #armature.makeEditable()
        root = Blender.Object.Get(hipbonename)
        children = dicEmptyChild[hipbonename]
        for ch in children:
                b=dicBone[hipbonename[1:len(hipbonename)] + ch.getName()[1:len(ch.getName())]]
-               #b.setLoc(computeRootPos(root, b))
-               b.setLoc([0.0, 0.0, 0.0])
-               b.setQuat(computeRootQuat2(root, b))
-               moveBones(armature, ch, empties)
+               
+               moveBones(larmature, ch, empties)
+       #armature.update()
 
 
-def eraseIPO (objectname):
-       object = Blender.Object.Get(objectname)
-       lIpo = object.getIpo()
-       if lIpo != None:
-               nbCurves = lIpo.getNcurves()
-               for i in range(nbCurves):
-                       nbBezPoints = lIpo.getNBezPoints(i)
-                       for j in range(nbBezPoints):
-                               lIpo.delBezPoint(i)
 
 
 ########################################################################
@@ -512,7 +467,7 @@ def Main():
 
        lesEmpties = getEmpties()
        #print dicEmptyChild    
-
+       print "creating armature"
        #armData = createArmature(em0, lesEmpties)
        objects = Blender.Object.Get()
        if 'OBArmature' in map(names,objects):
@@ -523,15 +478,16 @@ def Main():
                #print armData.getBones()
                f_createArmature(em0, lesEmpties, armData)
        else:
-               armData= createArmature(em0, lesEmpties)
                armObj=Blender.Object.New('Armature', 'OBArmature')
-               armObj.link(armData)
+               armData= createArmature(armObj, em0, lesEmpties)
+               #armObj.link(armData)
                scn = Blender.Scene.getCurrent()
                scn.link (armObj)
 
                print 'OBArmature'+' was created'
        #return myobj
+       print emprest
+       armData.drawType = Blender.Armature.STICK 
        ##-----------
        ## Creation de l'ipo de l'armature
        ##-----------
@@ -540,7 +496,11 @@ def Main():
        curvX =  GetOrCreateCurve(lipo, 'LocX')
        curvY =  GetOrCreateCurve(lipo, 'LocY')
        curvZ =  GetOrCreateCurve(lipo, 'LocZ')
+       curvrX =  GetOrCreateCurve(lipo, 'RotX')
+       curvrY =  GetOrCreateCurve(lipo, 'RotY')
+       curvrZ =  GetOrCreateCurve(lipo, 'RotZ')
 
+       print "animating armature"
 
        #armData.drawAxes(1)
        #armData.drawNames(1)
@@ -549,13 +509,16 @@ def Main():
 
        Blender.Redraw()
 
+        action = Blender.Armature.NLA.NewAction()
+        action.setActive(armObj)
+
+
+
        ##-----------
        ## Enregistrement de la position  de l'armature
        ##-----------
 
-       bones = armData.getBones()
-       for bo in bones:
-               bo.setPose([Blender.Armature.Bone.ROT, Blender.Armature.Bone.LOC]) 
+       bones = armData.bones.values()
 
        curvX.addBezier((Blender.Get("curframe"), getEmpty(hipbonename).getMatrix('worldspace').translationPart()[0]*scalef))
        curvY.addBezier((Blender.Get("curframe"), getEmpty(hipbonename).getMatrix('worldspace').translationPart()[1]*scalef))
@@ -566,6 +529,12 @@ def Main():
        curvY.setExtrapolation('Constant')
        curvZ.setInterpolation('Linear')
        curvZ.setExtrapolation('Constant')
+       curvrX.setInterpolation('Linear')
+       curvrX.setExtrapolation('Constant')
+       curvrY.setInterpolation('Linear')
+       curvrY.setExtrapolation('Constant')
+       curvrZ.setInterpolation('Linear')
+       curvrZ.setExtrapolation('Constant')
 
        Blender.Redraw()
 
@@ -576,18 +545,19 @@ def Main():
                ## Positionnement des os
                ##-----------
 
-               moveArmature(armData, lesEmpties)
+               moveArmature(armObj, lesEmpties)
 
 
                ##-----------
                ## Enregistrement de la position  de l'armature
                ##-----------
 
-               for bo in bones:
-                       bo.setPose([Blender.Armature.Bone.ROT, Blender.Armature.Bone.LOC]) 
                curvX.addBezier((Blender.Get("curframe"), (getEmpty(hipbonename).getMatrix('worldspace').translationPart()[0])*scalef))
                curvY.addBezier((Blender.Get("curframe"), (getEmpty(hipbonename).getMatrix('worldspace').translationPart()[1])*scalef))
                curvZ.addBezier((Blender.Get("curframe"), (getEmpty(hipbonename).getMatrix('worldspace').translationPart()[2])*scalef))
+               curvrX.addBezier((Blender.Get("curframe"), (getEmpty(hipbonename).getMatrix('worldspace').rotationPart().toEuler()[0])*scalef/10))
+               curvrY.addBezier((Blender.Get("curframe"), (getEmpty(hipbonename).getMatrix('worldspace').rotationPart().toEuler()[1])*scalef/10))
+               curvrZ.addBezier((Blender.Get("curframe"), (getEmpty(hipbonename).getMatrix('worldspace').rotationPart().toEuler()[2])*scalef/10))
 
                ##-----------
                ## Passage a la frame suivante
@@ -596,6 +566,12 @@ def Main():
                print num_frame
                Blender.Set("curframe", num_frame)
 
+       curvX.Recalc()
+       curvY.Recalc()
+       curvZ.Recalc()
+       curvrX.Recalc()
+       curvrY.Recalc()
+       curvrZ.Recalc()
        Blender.Set("curframe",startframe)
        Blender.Redraw()
 
@@ -627,26 +603,35 @@ def button_event(evt):
        global endframe, startframe, insertionframe, hipbonename, framedecimation , scalef
        if evt==1:
                startframe = SFrame2.val
-               insertionframe = IFrame.val
+               insertionframe = 100 #IFrame.val
                endframe =  EFrame.val
                hipbonename = HBName.val
                framedecimation = FrameDecimation.val
-               scalef= eval(str(ScaleF.val))
+               scalef= 1.0 #eval(str(ScaleF.val))
                #print "scalef = ", scalef
                if startframe>=endframe:
                        Msg = 'Start frame must be lower than End frame'
+                        error_txt = "Error|Start frame must be lower than End frame"
+                        Blender.Draw.PupMenu(error_txt)
                else:
                        ob = getEmpty(hipbonename)
                        if (ob!=None): 
                                if ob.getParent()!=None:
                                        Msg = 'Empty '+hipbonename+ ' is not a root bone.'
+                                        error_txt = "Error|Empty %s is not a root bone"%hipbonename
+                                        Blender.Draw.PupMenu(error_txt)
                                else:  
                                        if (0.0 > scalef):
                                                Msg = 'Scale factor must be greater than 0'
+                                               error_txt = "Error|Scale factor must be greater than 0"
+                                               Blender.Draw.PupMenu(error_txt)
                                        else:
                                                #Blender.Draw.Exit()
                                                Main()
+                               #Main()
                        else:
+                                error_txt = "Error|Empty %s not found"%hipbonename
+                                Blender.Draw.PupMenu(error_txt)
                                Msg = 'Empty '+ hipbonename+ ' not found'
                                
                #Blender.Draw.Redraw(1)
@@ -655,6 +640,9 @@ def button_event(evt):
                ob = getEmpty(hipbonename)
                if (ob!=None): 
                        if ob.getParent()!=None:
+                                error_txt = "Error|Empty %s is not a root bone"%hipbonename
+                                Blender.Draw.PupMenu(error_txt)
+
                                Msg = 'Empty '+hipbonename+ ' is not a root bone.'
                        else:  
                                #Blender.Draw.Exit()
@@ -671,15 +659,17 @@ def GUI():
        Blender.BGL.glClear(Blender.BGL.GL_COLOR_BUFFER_BIT)
        Blender.BGL.glColor3f(1,1,1)
        Blender.BGL.glRasterPos2i(20,200)
-       Blender.Draw.Text ("BVH 2 ARMATURE v2.2 by Jean-Baptiste PERIN", 'normal')
-       HBName = Blender.Draw.String("HipBoneName: ", 0, 20, 175, 250, 20, '_Hips', 100)
+       selobj = Blender.Object.GetSelected()
+       if len(selobj) == 1 and type (selobj[0]) == Blender.Types.ObjectType:
+               hipname = selobj[0].getName()
+       else:
+               hipname = '_Hips'
+       Blender.Draw.Text ("BVH 2 ARMATURE v%s by %s"%(__version__, __author__), 'normal')
+       HBName = Blender.Draw.String("HipBoneName: ", 0, 20, 175, 250, 20, hipname, 100)
        SFrame2 = Blender.Draw.Number("Startframe: ", 0, 20, 150, 250, 20, 1, 1,3000,"Start frame of anim")
        EFrame = Blender.Draw.Number("Endframe: ", 0, 20, 125, 250, 20, Blender.Get("endframe"), 1,3000,"Last frame of anim")
-       #IFrame = Blender.Draw.Number("Insertionframe: ", 0, 20, 100, 250, 20, Blender.Get("staframe"), 1,3000,"")
-       FrameDecimation = Blender.Draw.Number("FrameDecimation: ", 0, 20, 75, 250, 20,5, 1,10,'number of frame to skip between two action keys')
-       ScaleF = Blender.Draw.Number("Scale: ", 0, 20, 50, 250, 20, 1.0, 0.0, 10.0,  'Scale Factor')
+       FrameDecimation = Blender.Draw.Number("FrameDecimation: ", 0, 20, 75, 250, 20,1, 1,10,'number of frame to skip between two action keys')
        Blender.Draw.Toggle("Create Armature", 1, 20, 10, 100, 20, 0, "Create Armature")
-       #Blender.Draw.Toggle("Remove Empties", 2, 200, 10, 100, 20, 0, "Remove Empties")
        Blender.BGL.glRasterPos2i(20,40)
        Blender.Draw.Text (Msg, 'normal')
 
index 84425626cee63eb0fb235436a5f4ed95d267c698..7c6ac4c7e3613c53e475c8a04a1259e1a76680a9 100644 (file)
@@ -9,7 +9,7 @@ Tip: 'Export a (.bvh) motion capture file'
 
 __author__ = "Campbell Barton"
 __url__ = ("blender", "elysiun")
-__version__ = "1.0 03/30/04"
+__version__ = "1.1 12/16/05"
 
 __bpydoc__ = """\
 This script exports animation data to BVH motion capture file format.
@@ -30,12 +30,11 @@ Notes:<br>
 # BVH Export script 1.0 by Campbell Barton      #
 # Copyright MetaVR 30/03/2004,                  #
 # if you have any questions about this script   #
-# email me ideasman@linuxmail.org               #
-#                                               #
+# email me cbarton@metavr.com                   #
 #===============================================#
 
 # -------------------------------------------------------------------------- 
-# BVH Export v0.9 by Campbell Barton (AKA Ideasman) 
+# BVH Export v1.1 by Campbell Barton (AKA Ideasman) 
 # -------------------------------------------------------------------------- 
 # ***** BEGIN GPL LICENSE BLOCK ***** 
 # 
@@ -46,12 +45,12 @@ Notes:<br>
 # 
 # This program is distributed in the hope that it will be useful, 
 # but WITHOUT ANY WARRANTY; without even the implied warranty of 
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the 
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 
 # GNU General Public License for more details. 
 # 
 # You should have received a copy of the GNU General Public License 
 # along with this program; if not, write to the Free Software Foundation, 
-# Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA. 
+# Inc., 59 Temple Place - Suite 330, Boston, MA        02111-1307, USA. 
 # 
 # ***** END GPL LICENCE BLOCK ***** 
 # -------------------------------------------------------------------------- 
@@ -59,348 +58,328 @@ Notes:<br>
 import Blender
 from Blender import Scene, Object
 import math
+time = Blender.sys.time
 from math import *
 
 # Get the current scene.
 scn = Scene.GetCurrent()
 context = scn.getRenderingContext()
 
-frameRate = 0.3333 # 0.04 = 25fps
-scale = 1
+frameRate = 1.0/context.framesPerSec() # 0.04 = 25fps
+scale = 1.0
 
-indent = '  ' # 2 space indent per object
+indent = '\t' # 2 space indent per object
 prefixDelimiter = '_'
 
 # Vars used in eular rotation funtcion
 RAD_TO_DEG = 180.0/3.14159265359
-
+DEG_TO_RAD = math.pi/180.0
 
 
 #====================================================#
 # Search for children of this object and return them #
 #====================================================#
 def getChildren(parent):
-  children = [] # We'll assume none.
-  for child in Object.Get():
-    if child.getParent() == Object.Get(parent):
-      children.append( child.getName() )
-  return children
+       children = [] # We'll assume none.
+       for child in Object.Get():
+               if child.parent == parent:
+                       children.append( child )
+       return children
 
 #====================================================#
-# MESSY BUT WORKS: Make a string that shows the      #
-# hierarchy as a list and then eval it               #
+# MESSY BUT WORKS: Make a string that shows the                        #
+# hierarchy as a list and then eval it                                                  #
 #====================================================#
 def getHierarchy(root, hierarchy):
-  hierarchy = hierarchy + '["' + root + '",'
-  for child in getChildren(root):
-    hierarchy = getHierarchy(child, hierarchy)
-  hierarchy += '],' 
-  return hierarchy
+       hierarchy = '%s["%s",' % (hierarchy, root.name)
+       for child in getChildren(root):
+               hierarchy = getHierarchy(child, hierarchy)
+       hierarchy = '%s],' % hierarchy
+       return hierarchy
 
 
 #====================================================#
-# Strips the prefix off the name before writing      #
+# Strips the prefix off the name before writing                        #
 #====================================================#
 def stripName(name): # name is a string
-  
-  # WARNING!!! Special case for a custom RIG for output
-  # for MetaVR's HPX compatable RIG.
-  print 'stripname', name[0:10]
-  if name[0:10] == 'Transform(':
-    name = name[10:]
-    while name[-1] != ')':
-      name = name[0:-1]
-      print name
-    name = name[:-1]
-  
-  
-  return name[1+name.find(prefixDelimiter): ]
-  
-
-#====================================================#
-# Return a 6 deciaml point floating point value      #
-# as a string that dosent have any python chars      #
-#====================================================#  
-def saneFloat(float):
-  #return '%(float)b' % vars()  # 6 fp as house.hqx
-  return str('%f' % float) + ' '
-
-
+       
+       # WARNING!!! Special case for a custom RIG for output
+       # for MetaVR's HPX compatable RIG.
+       # print 'stripname', name[0:10]
+       if name.lower().startswith('transform('):
+               name = name[10:].split(prefixDelimiter)[0]
+       return name.split('_')[0]
+       
 
 #====================================================#
 # Recieves an object name, gets all the data for that#
 # node from blender and returns it for formatting    #
 # and writing to a file.                             #
 #====================================================#
-def getNodeData(nodeName):  
-  Object.Get(nodeName)
-  # Get real location  
-  offset = Object.Get(nodeName).getLocation()
-  offset = (offset[0]*scale, offset[1]*scale, offset[2]*scale,)
-  
-  #=========================#
-  # Test for X/Y/Z IPO's    #
-  #=========================#
-  obipo = Object.Get(nodeName).getIpo()
-  
-  # IF we dont have an IPO then dont check the curves.
-  # This was added to catch end nodes that never have an IPO, only an offset.
-  if obipo == None: 
-    xloc=yloc=zloc=xrot=yrot=zrot = 0
-  
-  else: # Do have an IPO, checkout which curves are in use.
-    # Assume the rot's/loc's exist until proven they dont
-    xloc=yloc=zloc=xrot=yrot=zrot = 1
-    if obipo.getCurve('LocX') == None:
-      xloc = 0
-    if obipo.getCurve('LocY') == None:
-      yloc = 0
-    if obipo.getCurve('LocZ') == None:
-      zloc = 0
-      
-    # Now for the rotations, Because of the conversion of rotation coords
-    # if there is one rotation er need to store all 3
-    if obipo.getCurve('RotX') == None and \
-    obipo.getCurve('RotY') == None and \
-    obipo.getCurve('RotZ') == None:
-      xrot=yrot=zrot = 0
-  
-  # DUMMY channels xloc, yloc, zloc, xrot, yrot, zrot
-  # [<bool>, <bool>, <bool>, <bool>, <bool>, <bool>]
-  channels = [xloc, yloc, zloc, xrot, yrot, zrot]
-  
-  return offset, channels
+def getNodeData(nodeOb):       
+       ob = nodeOb
+       obipo = ob.getIpo()
+       # Get real location     
+       offset = [o*scale for o in ob.getLocation()]
+       
+       #=========================#
+       # Test for X/Y/Z IPO's          #
+       #=========================#
+       
+       # IF we dont have an IPO then dont check the curves.
+       # This was added to catch end nodes that never have an IPO, only an offset.
+       
+       # DUMMY channels xloc, yloc, zloc, xrot, yrot, zrot
+       # [<bool>, <bool>, <bool>, <bool>, <bool>, <bool>]
+       channels = [0,0,0,0,0,0] # xloc,yloc,zloc,xrot,yrot,zrot
+       if obipo != None: # Do have an IPO, checkout which curves are in use.
+               # Assume the rot's/loc's dont exist until they proven they do.
+               if obipo.getCurve('LocX') != None:
+                       channels[0] = 1
+               if obipo.getCurve('LocY') != None:
+                       channels[1] = 1
+               if obipo.getCurve('LocZ') != None:
+                       channels[2] = 1
+                       
+               # Now for the rotations, Because of the conversion of rotation coords
+               # if there is one rotation er need to store all 3
+               if obipo.getCurve('RotX') != None or \
+               obipo.getCurve('RotY') != None or \
+               obipo.getCurve('RotZ') != None:
+                       channels[3] = channels[4] = channels[5] = 1
+       #print ob, channels
+       return offset, channels
 
 
 #====================================================#
-# Return the BVH hierarchy to a file from a list     #
+# Writes the BVH hierarchy to a file                 #
 # hierarchy: is a list of the empty hierarcht        #
-# bvhHierarchy: a string, in the bvh format to write #
 # level: how many levels we are down the tree,       #
 # ...used for indenting                              #
 # Also gathers channelList , so we know the order to #
-# write  the motiondata in                           #
+# write        the motiondata in                            #
 #====================================================#
-def hierarchy2bvh(hierarchy, bvhHierarchy, level, channelList, nodeObjectList):
-  nodeName = hierarchy[0]
-  
-  # Add object to nodeObjectList
-  nodeObjectList.append(Object.Get(nodeName))
-  
-  #============#
-  # JOINT NAME #
-  #============# 
-  bvhHierarchy += level * indent
-  if level == 0:
-    # Add object to nodeObjectList
-    nodeObjectList.append(Object.Get(nodeName))
-    bvhHierarchy+= 'ROOT '
-    bvhHierarchy += stripName(nodeName) + '\n'
-  # If this is the last object in the list then we
-  # dont bother withwriting its real name, use "End Site" instead
-  elif len(hierarchy) == 1:
-    bvhHierarchy+= 'End Site\n'
-  # Ok This is a normal joint
-  else:
-    # Add object to nodeObjectList
-    nodeObjectList.append(Object.Get(nodeName))
-    bvhHierarchy+= 'JOINT '
-    bvhHierarchy += stripName(nodeName) + '\n'
-  #================#
-  # END JOINT NAME #
-  #================# 
-
-  # Indent again, this line is just for the brackets
-  bvhHierarchy += level * indent + '{' + '\n'
-
-  # Indent
-  level += 1   
-  
-  #================================================#
-  # Data for writing to a file offset and channels #
-  #================================================#
-  offset, channels = getNodeData(nodeName)
-  
-  #============#
-  # Offset     #
-  #============# 
-  bvhHierarchy += level * indent + 'OFFSET ' + saneFloat(scale * offset[0]) + ' '  + saneFloat(scale * offset[1]) + ' ' + saneFloat(scale * offset[2]) + '\n'
-  
-  #============#
-  # Channels   #
-  #============# 
-  if len(hierarchy) != 1:
-    # Channels, remember who is where so when we write motiondata
-    bvhHierarchy += level * indent + 'CHANNELS '
-    # Count the channels
-    chCount = 0
-    for chn in channels:
-      chCount += chn
-    bvhHierarchy += str(chCount) + ' '
-    if channels[0]:
-      bvhHierarchy += 'Xposition '
-      channelList.append([len(nodeObjectList)-1, 0])
-    if channels[1]:
-      bvhHierarchy += 'Yposition '
-      channelList.append([len(nodeObjectList)-1, 1])
-    if channels[2]:
-      bvhHierarchy += 'Zposition '
-      channelList.append([len(nodeObjectList)-1, 2])
-    if channels[5]:
-      bvhHierarchy += 'Zrotation '
-      channelList.append([len(nodeObjectList)-1, 5])
-    if channels[3]:
-      bvhHierarchy += 'Xrotation '
-      channelList.append([len(nodeObjectList)-1, 3])
-    if channels[4]:
-      bvhHierarchy += 'Yrotation '
-      channelList.append([len(nodeObjectList)-1, 4])
-    
-    bvhHierarchy += '\n'
-
-  # Loop through children if any and run this function (recursively)
-  for hierarchyIdx in range(len(hierarchy)-1):
-    bvhHierarchy, level, channelList, nodeObjectList = hierarchy2bvh(hierarchy[hierarchyIdx+1], bvhHierarchy, level, channelList, nodeObjectList)
-  # Unindent
-  level -= 1
-  bvhHierarchy += level * indent + '}' + '\n'
-  
-  return bvhHierarchy, level, channelList, nodeObjectList
+def hierarchy2bvh(file, hierarchy, level, channelList, nodeObjectList):
+       nodeName = hierarchy[0]
+       ob = Object.Get(nodeName)
+       '''
+       obipo = ob.getIpo()
+       if obipo != None:
+               obcurves = obipo.getCurves()
+       else:
+               obcurves = None
+       '''
+       #============#
+       # JOINT NAME #
+       #============# 
+       file.write(level * indent)
+       if level == 0:
+               # Add object to nodeObjectList
+               #nodeObjectList.append( (ob, obipo, obcurves) )
+               nodeObjectList.append( ob )
+               file.write( 'ROOT %s\n' % stripName(nodeName) )
+       # If this is the last object in the list then we
+       # dont bother withwriting its real name, use "End Site" instead
+       elif len(hierarchy) == 1:
+               file.write( 'End Site\n' )
+       # Ok This is a normal joint
+       else:
+               # Add object to nodeObjectList
+               #nodeObjectList.append((ob, obipo, obcurves))
+               nodeObjectList.append( ob )
+               file.write( 'JOINT %s\n' % stripName(nodeName) )
+       #================#
+       # END JOINT NAME #
+       #================#
+       
+       # Indent again, this line is just for the brackets
+       file.write( '%s{\n' % (level * indent) )
+
+       # Indent
+       level += 1
+       
+       #================================================#
+       # Data for writing to a file offset and channels #
+       #================================================#
+       offset, channels = getNodeData(ob)
+       
+       #============#
+       # Offset     #
+       #============# 
+       file.write( '%sOFFSET %.6f %.6f %.6f\n' %\
+       (level*indent, scale*offset[0], scale*offset[1], scale*offset[2]) )
+       
+       #============#
+       # Channels   #
+       #============# 
+       if len(hierarchy) != 1:
+               # Channels, remember who is where so when we write motiondata
+               file.write('%sCHANNELS %i ' % (level*indent, len([c for c in channels if c ==1]) ))
+               if channels[0]:
+                       file.write('Xposition ')
+                       channelList.append([len(nodeObjectList)-1, 0])
+               if channels[1]:
+                       file.write('Yposition ')
+                       channelList.append([len(nodeObjectList)-1, 1])
+               if channels[2]:
+                       file.write('Zposition ')
+                       channelList.append([len(nodeObjectList)-1, 2])
+               if channels[5]:
+                       file.write('Zrotation ')
+                       channelList.append([len(nodeObjectList)-1, 5])
+               if channels[3]:
+                       file.write('Xrotation ')
+                       channelList.append([len(nodeObjectList)-1, 3])
+               if channels[4]:
+                       file.write('Yrotation ')
+                       channelList.append([len(nodeObjectList)-1, 4])
+               file.write('\n')
+
+       # Loop through children if any and run this function (recursively)
+       for hierarchyIdx in range(len(hierarchy)-1):
+               level = hierarchy2bvh(file, hierarchy[hierarchyIdx+1], level, channelList, nodeObjectList)
+       # Unindent
+       level -= 1
+       file.write('%s}\n' % (level * indent))
+       
+       return level
 
 # added by Ben Batt 30/3/2004 to make the exported rotations correct
 def ZYXToZXY(x, y, z):
-  '''
-  Converts a set of Euler rotations (x, y, z) (which are intended to be
-  applied in z, y, x order) into a set which are intended to be applied in
-  z, x, y order (the order expected by .bvh files)
-  '''
-  A,B = cos(x),sin(x)
-  C,D = cos(y),sin(y)
-  E,F = cos(z),sin(z)
-
-  x = asin(-B*C)
-  y = atan2(D, A*C)
-  z = atan2(-B*D*E + A*F, B*D*F + A*E)
-
-  # this seems to be necessary - not sure why (right/left-handed coordinates?)
-  x = -x
-  return x*RAD_TO_DEG, y*RAD_TO_DEG, z*RAD_TO_DEG
-
-
-
-def getIpoLocation(object, frame):
-  x =  y = z = 0 
-  obipo = object.getIpo()
-  for i in range(object.getIpo().getNcurves()):
-    if obipo.getCurves()[i].getName() =='LocX':
-      x = object.getIpo().EvaluateCurveOn(i,frame)
-    elif obipo.getCurves()[i].getName() =='LocY':
-      y = object.getIpo().EvaluateCurveOn(i,frame)
-    elif obipo.getCurves()[i].getName() =='LocZ':
-      z = object.getIpo().EvaluateCurveOn(i,frame)
-  return x, y, z
-
+       '''
+       Converts a set of Euler rotations (x, y, z) (which are intended to be
+       applied in z, y, x order, into a set which are intended to be applied in
+       z, x, y order (the order expected by .bvh files)
+       '''
+       A,B = cos(x),sin(x)
+       C,D = cos(y),sin(y)
+       E,F = cos(z),sin(z)
+
+       x = asin(-B*C)
+       y = atan2(D, A*C)
+       z = atan2(-B*D*E + A*F, B*D*F + A*E)
+
+       # this seems to be necessary - not sure why (right/left-handed coordinates?)
+       # x = -x # x is negative, see below.
+       return -x*RAD_TO_DEG, y*RAD_TO_DEG, z*RAD_TO_DEG
+
+
+''' # UNUSED, JUST GET OBJECT LOC/ROT
+def getIpoLocation(object, obipo, curves, frame):
+       x =     y = z = rx = ry = rz =0
+       if obipo:
+               for i in range(obipo.getNcurves()):
+                       if curves[i].getName() =='LocX':
+                               x = obipo.EvaluateCurveOn(i,frame)
+                       elif curves[i].getName() =='LocY':
+                               y = obipo.EvaluateCurveOn(i,frame)
+                       elif curves[i].getName() =='LocZ':
+                               z = obipo.EvaluateCurveOn(i,frame)
+                       elif curves[i].getName() =='RotX':
+                               rx = obipo.EvaluateCurveOn(i,frame)
+                       elif curves[i].getName() =='RotY':
+                               ry = obipo.EvaluateCurveOn(i,frame)
+                       elif curves[i].getName() =='RotZ':
+                               rz = obipo.EvaluateCurveOn(i,frame)
+       return x, y, z, rx*10*DEG_TO_RAD, ry*10*DEG_TO_RAD, rz*10*DEG_TO_RAD
+'''
 
 #====================================================#
 # Return the BVH motion for the spesified frame      #
 # hierarchy: is a list of the empty hierarcht        #
-# bvhHierarchy: a string, in the bvh format to write #
 # level: how many levels we are down the tree,       #
 # ...used for indenting                              #
 #====================================================#
-def motion2bvh(frame, chennelList, nodeObjectList):
-  
-  motionData = '' # We'll append the frames to the string.
-  
-  for chIdx in chennelList:
-    ob = nodeObjectList[chIdx[0]]
-    chType = chIdx[1]
-    
-    # Get object rotation
-    x, y, z = ob.getEuler()
-    
-    # Convert the rotation from ZYX order to ZXY order
-    x, y, z = ZYXToZXY(x, y, z)
-     
-    
-    # Using regular Locations stuffs upIPO locations stuffs up
-    # Get IPO locations instead
-    xloc, yloc, zloc = getIpoLocation(ob, frame)
-
-    # WARNING non standard Location
-    xloc, zloc, yloc = -xloc, yloc, zloc
-    
-
-    if chType == 0:
-      motionData += saneFloat(scale * (xloc))
-    if chType == 1:
-      motionData += saneFloat(scale * (yloc))
-    if chType == 2:
-      motionData += saneFloat(scale * (zloc))      
-    if chType == 3:
-      motionData += saneFloat(x)
-    if chType == 4:
-      motionData += saneFloat(y)
-    if chType == 5:
-      motionData += saneFloat(z)
-    
-    motionData += ' '
-     
-  motionData += '\n'
-  return motionData
+def motion2bvh(file, frame, chennelList, nodeObjectList):      
+       for chIdx in chennelList:
+               #ob, obipo, obcurves = nodeObjectList[chIdx[0]]
+               ob = nodeObjectList[chIdx[0]]
+               chType = chIdx[1]
+               
+               # Get object rotation
+               x, y, z = ob.getEuler()
+               
+               # Convert the rotation from ZYX order to ZXY order
+               x, y, z = ZYXToZXY(x, y, z)
+               
+               # Location
+               xloc, yloc, zloc = ob.matrixLocal[3][:3]
+               
+               # Using regular Locations stuffs upIPO locations stuffs up
+               # Get IPO locations instead
+               #xloc, yloc, zloc, x, y, z = getIpoLocation(ob, obipo, obcurves, frame)
+               # Convert the rotation from ZYX order to ZXY order
+               #x, y, z = ZYXToZXY(x, y, z)
+               
+               
+               # WARNING non standard Location
+               # xloc, zloc, yloc = -xloc, yloc, zloc
+               
+               if chType == 0:
+                       file.write('%.6f ' % (scale * xloc))
+               if chType == 1:
+                       file.write('%.6f ' % (scale * yloc))
+               if chType == 2:
+                       file.write('%.6f ' % (scale * zloc))
+               if chType == 3:
+                       file.write('%.6f ' % x)
+               if chType == 4:
+                       file.write('%.6f ' % y)
+               if chType == 5:
+                       file.write('%.6f ' % z)
+       file.write('\n')
+       
 
 def saveBVH(filename):
-
-  if filename.find('.bvh', -4) <= 0: filename += '.bvh' # for safety
-
-  # Here we store a serialized list of blender objects as they appier
-  # in the hierarchy, this is refred to when writing motiondata
-  nodeObjectList = []
-  
-  # In this list we store a 2 values for each node
-  # 1) An index pointing to a blender object
-  # in objectList
-  # 2) The type if channel x/y/z rot:x/y/z - Use 0-5 to indicate this
-  chennelList = []
-  
-  print ''
-  print 'BVH  1.0 by Campbell Barton (Ideasman) - ideasman@linuxmail.org'
-  
-  # Get the active object and recursively traverse its kids to build
-  # the BVH hierarchy, then eval the string to make a hierarchy list.
-  hierarchy = eval(getHierarchy(Object.GetSelected()[0].getName(),''))[0] # somhow this returns a tuple with one list in it.
-  
-  # Put all data in the file we have selected file.
-  file = open(filename, "w")
-  file.write('HIERARCHY\n') # all bvh files have this on the first line
-  
-  # Write the whole hirarchy to a list
-  bvhHierarchy, level, chennelList, nodeObjectList = hierarchy2bvh(hierarchy, '', 0, chennelList, nodeObjectList)
-  file.write( bvhHierarchy ) # Rwite the var fileBlock to the output.
-  bvhHierarchy = None # Save a tit bit of memory
-  
-  #====================================================#
-  # MOTION: Loop through the frames ande write out     #
-  # the motion data for each                           #
-  #====================================================#
-  # Do some basic motion file header stuff
-  file.write('MOTION\n')
-  file.write( 'Frames: ' + str(1 + context.endFrame() - context.startFrame()) + '\n'  )
-  file.write( 'Frame Time: ' + saneFloat(frameRate) + '\n'  ) 
-  
-  #print 'WARNING- exact frames might be stuffed up- inclusive whatever, do some tests later on.'
-  frames = range(context.startFrame(), context.endFrame()+1)
-  print 'exporting ' + str(len(frames)) + ' of motion...'
-  
-  for frame in frames:
-    context.currentFrame(frame)
-    scn.update(1) # Update locations so we can write the new locations
-    #Blender.Window.RedrawAll() # causes crash
-    
-    file.write(  motion2bvh(frame, chennelList, nodeObjectList)  )
-     
-  file.write('\n') # newline
-  file.close()
-  print 'done'
-  
+       t = time()
+       if not filename.lower().endswith('.bvh'):
+               filename += '.bvh' # for safety
+       
+       # Here we store a serialized list of blender objects as they appier
+       # in the hierarchy, this is refred to when writing motiondata
+       nodeObjectList = []
+       
+       # In this list we store a 2 values for each node
+       # 1) An index pointing to a blender object
+       # in objectList
+       # 2) The type if channel x/y/z rot:x/y/z - Use 0-5 to indicate this
+       chennelList = []
+       
+       print '\nBVH  1.1 by Campbell Barton (Ideasman) - cbarton@metavr.com'
+       
+       # Get the active object and recursively traverse its kids to build
+       # the BVH hierarchy, then eval the string to make a hierarchy list.
+       hierarchy = eval(getHierarchy(scn.getActiveObject(),''))[0] # somhow this returns a tuple with one list in it.
+       
+       # Put all data in the file we have selected file.
+       file = open(filename, "w")
+       file.write('HIERARCHY\n') # all bvh files have this on the first line
+       
+       # Write the whole hirarchy to a list
+       level = 0 # Indenting level, start with no indent
+       level = hierarchy2bvh(file, hierarchy, level, chennelList, nodeObjectList)
+       
+       #====================================================#
+       # MOTION: Loop through the frames ande write out     #
+       # the motion data for each                           #
+       #====================================================#
+       # Do some basic motion file header stuff
+       file.write( 'MOTION\n' )
+       file.write( 'Frames: %i\n'      % ( 1 + context.endFrame() - context.startFrame() ) )
+       file.write( 'Frame Time: %.6f\n' % frameRate )
+       
+       frames = range(context.startFrame()+1, context.endFrame()+1)
+       print 'exporting %i of motion...' % len(frames)
+       
+       for frame in frames:
+               context.currentFrame(frame)
+               scn.update(1) # Update locations so we can write the new locations. This is the SLOW part.
+               # Blender.Window.RedrawAll() # Debugging.
+               
+               motion2bvh(file, frame, chennelList, nodeObjectList) # Write the motion to a file.
+       
+       file.write('\n') # newline
+       file.close()
+       print '...Done in %.4f seconds.' % (time()-t)
+       
 Blender.Window.FileSelector(saveBVH, 'Export BVH')
index 17ce01c0cabc871001c9d1b19a5c3d736c3601ef..05f40f018dc71af8ba678816eb70908bba8362ab 100644 (file)
@@ -2,14 +2,14 @@
 
 """
 Name: 'Motion Capture (.bvh)...'
-Blender: 236
+Blender: 239
 Group: 'Import'
 Tip: 'Import a (.bvh) motion capture file'
 """
 
 __author__ = "Campbell Barton"
-__url__ = ("blender", "elysiun", "http://jmsoler.free.fr/util/blenderfile/py/bvh_import.py")
-__version__ = "1.0.2 04/12/28"
+__url__ = ("blender", "elysiun")
+__version__ = "1.0.4 05/12/04"
 
 __bpydoc__ = """\
 This script imports BVH motion capture data to Blender.
@@ -21,32 +21,52 @@ Missing:<br>
 Known issues:<br>
 
 Notes:<br>
-   Jean-Michel Soler improved importer to support Poser 3.01 files;<br>
-   Jean-Baptiste Perin wrote a script to create an armature out of the
+        Jean-Michel Soler improved importer to support Poser 3.01 files;<br>
+        Jean-Baptiste Perin wrote a script to create an armature out of the
 Empties created by this importer, it's in the Scripts window -> Scripts -> Animation menu.
 """
 
 # $Id$
 #
 
+#===============================================#
+# BVH Import script 1.05 patched by Campbell    #
+# Modified to use Mathutils for matrix math,    #
+# Fixed possible joint naming bug,              #
+# Imports BVH's with bad EOF gracefully         #
+# Fixed duplicate joint names, make them unique #
+# Use \r as well as \n for newlines             #
+# Added suppot for nodes with 0 motion channels #
+# Rotation IPOs never cross more then 180d      #
+#    fixes sub frame tweening and time scaling  #
+# 5x overall speedup.                           #
+# 06/12/2005,                                   #      
+#===============================================#
+
+#===============================================#
+# BVH Import script 1.04 patched by jms         #
+# Small modif for blender 2.40                  #
+# 04/12/2005,                                   #      
+#===============================================#
+
 #===============================================#
 # BVH Import script 1.03 patched by Campbell    #
 # Small optimizations and scale input           #
-# 01/01/2005,                                   #  
+# 01/01/2005,                                   #      
 #===============================================#
 
 #===============================================#
 # BVH Import script 1.02 patched by Jm Soler    #
-# to the Poser 3.01 bvh file                    # 
-# 28/12/2004,                                   #  
+# to the Poser 3.01 bvh file                    #
+# 28/12/2004,                                   #      
 #===============================================#
 
 #===============================================#
 # BVH Import script 1.0 by Campbell Barton      #
 # 25/03/2004, euler rotation code taken from    #
 # Reevan Mckay's BVH import script v1.1         #
-# if you have any questions about this script   #
-# email me ideasman@linuxmail.org               #
+# if you have any questions about this scrip.   #
+# email me cbarton@metavr.com                   #
 #===============================================#
 
 #===============================================#
@@ -57,7 +77,7 @@ Empties created by this importer, it's in the Scripts window -> Scripts -> Anima
 #===============================================#
 
 # -------------------------------------------------------------------------- 
-# BVH Import v0.9 by Campbell Barton (AKA Ideasman) 
+# BVH Import v1.05 by Campbell Barton (AKA Ideasman) 
 # -------------------------------------------------------------------------- 
 # ***** BEGIN GPL LICENSE BLOCK ***** 
 # 
@@ -68,457 +88,410 @@ Empties created by this importer, it's in the Scripts window -> Scripts -> Anima
 # 
 # This program is distributed in the hope that it will be useful, 
 # but WITHOUT ANY WARRANTY; without even the implied warranty of 
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the 
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 
 # GNU General Public License for more details. 
 # 
 # You should have received a copy of the GNU General Public License 
 # along with this program; if not, write to the Free Software Foundation, 
-# Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA. 
+# Inc., 59 Temple Place - Suite 330, Boston, MA        02111-1307, USA. 
 # 
 # ***** END GPL LICENCE BLOCK ***** 
 # -------------------------------------------------------------------------- 
 
-
-import string
-import math
 import Blender
 from Blender import Window, Object, Scene, Ipo, Draw
 from Blender.Scene import Render
 
 
-# # PSYCO IS CRASHING ON MY SYSTEM
-# # Attempt to load psyco, speed things up
-# try:
-#   print 'using psyco to speed up BVH importing'
-#   import psyco
-#   psyco.full()
-#  
-# except:
-#   print 'psyco is not present on this system'
-
-# Default scale
-scale = 0.01
-
-# Update as we load?
-debug = 0
-
-# Get the current scene.
-scn = Scene.GetCurrent()
-context = scn.getRenderingContext()
-
-# Here we store the Ipo curves in the order they load.
-channelCurves = []
-
-# Object list
-# We need this so we can loop through the objects and edit there IPO's 
-# Chenging there rotation to EULER rotation
-objectList = []
-
-def getScale():
-       return Draw.PupFloatInput('BVH Scale: ', 0.01, 0.001, 10.0, 0.1, 3)
-
-def MAT(m):
-       if len(m) == 3:
-               return Blender.Mathutils.Matrix(m[0], m[1], m[2])
-       elif len(m) == 4:
-               return Blender.Mathutils.Matrix(m[0], m[1], m[2], m[3])
-
-
-
-#===============================================#
-# eulerRotation: converts X, Y, Z rotation      #
-# to eular Rotation. This entire function       #
-# is copied from Reevan Mckay's BVH script      #
-#===============================================#
-# Vars used in eular rotation funtcion
-DEG_TO_RAD = math.pi/180.0
-RAD_TO_DEG = 180.0/math.pi
-PI=3.14159
-
-def eulerRotate(x,y,z): 
-  #=================================
-  def RVMatMult3 (mat1,mat2):
-  #=================================
-    mat3=[[0.0,0.0,0.0],[0.0,0.0,0.0],[0.0,0.0,0.0]]
-    for i in range(3):
-      for k in range(3):
-        for j in range(3):
-          mat3[i][k]=mat3[i][k]+mat1[i][j]*mat2[j][k]
-    return mat3
-  
-  
-  #=================================
-  def  RVAxisAngleToMat3 (rot4):
-  #    Takes a direction vector and
-  #    a rotation (in rads) and
-  #    returns the rotation matrix.
-  #    Graphics Gems I p. 466:
-  #=================================
-    mat3=[[0.0,0.0,0.0],[0.0,0.0,0.0],[0.0,0.0,0.0]]
-    if math.fabs(rot4[3])>0.01:
-      s=math.sin(rot4[3])
-      c=math.cos(rot4[3])
-      t=1.0-math.cos(rot4[3])
-    else:
-      s=rot4[3]
-      c=1.0
-      t=0.0
-
-    x=rot4[0]; y=rot4[1]; z=rot4[2]
-    
-    mat3[0][0]=t*x*x+c
-    mat3[0][1]=t*x*y+s*z
-    mat3[0][2]=t*x*z-s*y 
-    
-    mat3[1][0]=t*x*y-s*z
-    mat3[1][1]=t*y*y+c
-    mat3[1][2]=t*y*z+s*x
-    
-    mat3[2][0]=t*x*z+s*y
-    mat3[2][1]=t*y*z-s*x
-    mat3[2][2]=t*z*z+c
-    
-    return mat3
-  eul = [x,y,z]
-  
-  for jj in range(3):
-    while eul[jj] < 0:
-      eul[jj] = eul[jj] + 360.0
-    while eul[jj] >= 360.0:
-      eul[jj] = eul[jj] - 360.0
-
-  eul[0] = eul[0]*DEG_TO_RAD
-  eul[1] = eul[1]*DEG_TO_RAD
-  eul[2] = eul[2]*DEG_TO_RAD
-  
-  xmat=RVAxisAngleToMat3([1,0,0,eul[0]])
-  ymat=RVAxisAngleToMat3([0,1,0,eul[1]])
-  zmat=RVAxisAngleToMat3([0,0,1,eul[2]])
-  
-  mat=[[1.0,0.0,0.0],[0.0,1.0,0.0],[0.0,0.0,1.0]]  
-  
-  # Standard BVH multiplication order
-  mat=RVMatMult3 (zmat,mat)
-  mat=RVMatMult3 (xmat,mat)
-  mat=RVMatMult3 (ymat,mat)
-  
-  
-  '''
-  # Screwy Animation Master BVH multiplcation order
-  mat=RVMatMult3 (ymat,mat)
-  mat=RVMatMult3 (xmat,mat)
-  mat=RVMatMult3 (zmat,mat)
-  '''
-  mat = MAT(mat)
-  
-  eul = mat.toEuler()
-  x =- eul[0]/-10
-  y =- eul[1]/-10
-  z =- eul[2]/-10
-  
-  return x, y, z # Returm euler roration values.
-
-
-
-#===============================================#
-# makeJoint: Here we use the node data          #
-# from the BVA file to create an empty          #
-#===============================================#
-def makeJoint(name, parent, prefix, offset, channels):
-  global scale
-  # Make Empty, with the prefix in front of the name
-  ob = Object.New('Empty', prefix + name) # New object, ob is shorter and nicer to use.
-  scn.link(ob) # place the object in the current scene
-  
-  # Offset Empty
-  ob.setLocation(offset[0]*scale, offset[1]*scale, offset[2]*scale)
-
-  # Make me a child of another empty.
-  # Vale of None will make the empty a root node (no parent)
-  if parent[-1] != None:
-    obParent = Object.Get(prefix + parent[-1]) # We use this a bit so refrence it here.
-    obParent.makeParent([ob], 0, 1) #ojbs, noninverse, 1 = not fast.
-
-  # Add Ipo's for necessary channels
-  newIpo = Ipo.New('Object', prefix + name)
-  ob.setIpo(newIpo)
-  for channelType in channels:
-    if channelType == 'Xposition':
-      newIpo.addCurve('LocX')
-      newIpo.getCurve('LocX').setInterpolation('Linear')
-    if channelType == 'Yposition':
-      newIpo.addCurve('LocY')
-      newIpo.getCurve('LocY').setInterpolation('Linear')
-    if channelType == 'Zposition':
-      newIpo.addCurve('LocZ')
-      newIpo.getCurve('LocZ').setInterpolation('Linear')
-
-    if channelType == 'Zrotation':
-      newIpo.addCurve('RotZ')
-      newIpo.getCurve('RotZ').setInterpolation('Linear')
-    if channelType == 'Yrotation':
-      newIpo.addCurve('RotY')
-      newIpo.getCurve('RotY').setInterpolation('Linear')
-    if channelType == 'Xrotation':
-      newIpo.addCurve('RotX')
-      newIpo.getCurve('RotX').setInterpolation('Linear')
-
-  # Add to object list
-  objectList.append(ob)
-  
-  # Redraw if debugging
-  if debug: Blender.Redraw()
-  
-
-#===============================================#
-# makeEnd: Here we make an end node             #
-# This is needed when adding the last bone      #
-#===============================================#
-def makeEnd(parent, prefix, offset):
-  # Make Empty, with the prefix in front of the name, end nodes have no name so call it its parents name+'_end'
-  ob = Object.New('Empty', prefix + parent[-1] + '_end') # New object, ob is shorter and nicer to use.
-  scn.link(ob)
-  
-  # Dont check for a parent, an end node MUST have a parent
-  obParent = Object.Get(prefix + parent[-1]) # We use this a bit so refrence it here.
-  obParent.makeParent([ob], 0, 1) #ojbs, noninverse, 1 = not fast.
-
-  # Offset Empty
-  ob.setLocation(offset[0]*scale, offset[1]*scale, offset[2]*scale) 
-  
-  # Redraw if debugging
-  if debug: Blender.Redraw()  
-  
-
-
-
-#===============================================#
-# MAIN FUNCTION - All things are done from here #
-#===============================================#
-def loadBVH(filename):
-  global scale
-  print ''
-  print 'BVH Importer 1.0 by Campbell Barton (Ideasman) - ideasman@linuxmail.org'
-  alpha='abcdefghijklmnopqrstuvewxyz'
-  ALPHA=alpha+alpha.upper()
-  ALPHA+=' 0123456789+-{}. '  
-  time1 = Blender.sys.time()
-  tmpScale = getScale()
-  if tmpScale != None:
-    scale = tmpScale
-  
-  # File loading stuff
-  # Open the file for importing
-  file = open(filename, 'r')  
-  fileData = file.readlines()
-  # Make a list of lines
-  lines = []
-  for fileLine in fileData:
-    fileLine=fileLine.replace('..','.')
-    newLine = string.split(fileLine)
-    if newLine != []:
-      t=[]
-      for n in newLine:
-         for n0 in n:
-           if n0 not in ALPHA:
-              n=n.replace(n0,'')  
-         t.append(n)
-      lines.append(t)
-
-    
-  del fileData
-  # End file loading code
-
-  # Call object names with this prefix, mainly for scenes with multiple BVH's - Can imagine most partr names are the same
-  # So in future
-  #prefix = str(len(lines)) + '_'
-  
-  prefix = '_'
-  
-  # Create Hirachy as empties
-  if lines[0][0] == 'HIERARCHY':
-    print 'Importing the BVH Hierarchy for:', filename
-  else:
-    return 'ERROR: This is not a BVH file'
-  
-  # A liniar list of ancestors to keep track of a single objects heratage
-  # at any one time, this is appended and removed, dosent store tree- just a liniar list.
-  # ZERO is a place holder that means we are a root node. (no parents)
-  parent = [None]  
-  
-  #channelList [(<objectName>, [channelType1, channelType2...]),  (<objectName>, [channelType1, channelType2...)]
-  channelList = []
-  channelIndex = -1
-
-  
-
-  lineIdx = 1 # An index for the file.
-  while lineIdx < len(lines) -1:
-    #...
-    if lines[lineIdx][0] == 'ROOT' or lines[lineIdx][0] == 'JOINT':
-      if lines[lineIdx][0] == 'JOINT' and len(lines[lineIdx])>2:
-         for j in range(2,len(lines[lineIdx])) :
-             lines[lineIdx][1]+='_'+lines[lineIdx][j]
-
-      # MAY NEED TO SUPPORT MULTIPLE ROOT's HERE!!!, Still unsure weather multiple roots are possible.??
-
-      print len(parent) * '  ' + 'node:',lines[lineIdx][1],' parent:',parent[-1]
-      print lineIdx
-      name = lines[lineIdx][1]
-      print name,lines[lineIdx+1],lines[lineIdx+2]
-      lineIdx += 2 # Incriment to the next line (Offset)
-      offset = ( float(lines[lineIdx][1]), float(lines[lineIdx][2]), float(lines[lineIdx][3]) )
-      lineIdx += 1 # Incriment to the next line (Channels)
-      
-      # newChannel[Xposition, Yposition, Zposition, Xrotation, Yrotation, Zrotation]
-      # newChannel has Indecies to the motiondata,
-      # -1 refers to the last value that will be added on loading at a value of zero
-      # We'll add a zero value onto the end of the MotionDATA so this is always refers to a value.
-      newChannel = [-1, -1, -1, -1, -1, -1] 
-      for channel in lines[lineIdx][2:]:
-        channelIndex += 1 # So the index points to the right channel
-        if channel == 'Xposition':
-          newChannel[0] = channelIndex
-        elif channel == 'Yposition':
-          newChannel[1] = channelIndex
-        elif channel == 'Zposition':
-          newChannel[2] = channelIndex
-        elif channel == 'Xrotation':
-          newChannel[3] = channelIndex
-        elif channel == 'Yrotation':
-          newChannel[4] = channelIndex
-        elif channel == 'Zrotation':
-          newChannel[5] = channelIndex
-      
-      channelList.append(newChannel)
-      
-      channels = lines[lineIdx][2:]
-      
-      # Call funtion that uses the gatrhered data to make an empty.
-      makeJoint(name, parent, prefix, offset, channels)
-      
-      # If we have another child then we can call ourselves a parent, else 
-      parent.append(name)
-
-    # Account for an end node
-    if lines[lineIdx][0] == 'End' and lines[lineIdx][1] == 'Site': # There is somtimes a name afetr 'End Site' but we will ignore it.
-      lineIdx += 2 # Incriment to the next line (Offset)
-      offset = ( float(lines[lineIdx][1]), float(lines[lineIdx][2]), float(lines[lineIdx][3]) )
-      makeEnd(parent, prefix, offset)
-
-      # Just so we can remove the Parents in a uniform way- End end never has kids
-      # so this is a placeholder
-      parent.append(None)
-
-    if lines[lineIdx] == ['}']:
-      parent = parent[:-1] # Remove the last item
-
-
-    #=============================================#
-    # BVH Structure loaded, Now import motion     #
-    #=============================================#    
-    if lines[lineIdx] == ['MOTION']:
-      print '\nImporting motion data'
-      lineIdx += 3 # Set the cursor to the forst frame
-      
-      #=============================================#
-      # Loop through frames, each line a frame      #
-      #=============================================#      
-      currentFrame = 1
-      print 'frames: ',
-      
-      
-      #=============================================#
-      # Add a ZERO keyframe, this keeps the rig     #
-      # so when we export we know where all the     #
-      # joints start from                           #
-      #=============================================#  
-      obIdx = 0
-      while obIdx < len(objectList) -1:
-        if channelList[obIdx][0] != -1:
-          objectList[obIdx].getIpo().getCurve('LocX').addBezier((currentFrame,0))
-        if channelList[obIdx][1] != -1:
-          objectList[obIdx].getIpo().getCurve('LocY').addBezier((currentFrame,0))
-        if channelList[obIdx][2] != -1:
-          objectList[obIdx].getIpo().getCurve('LocZ').addBezier((currentFrame,0))
-        if channelList[obIdx][3] != '-1' or channelList[obIdx][4] != '-1' or channelList[obIdx][5] != '-1':
-          objectList[obIdx].getIpo().getCurve('RotX').addBezier((currentFrame,0))
-          objectList[obIdx].getIpo().getCurve('RotY').addBezier((currentFrame,0))
-          objectList[obIdx].getIpo().getCurve('RotZ').addBezier((currentFrame,0))
-        obIdx += 1
-      
-      while lineIdx < len(lines):
-        
-        # Exit loop if we are past the motiondata.
-        # Some BVH's have extra tags like 'CONSTRAINTS and MOTIONTAGS'
-        # I dont know what they do and I dont care, they'll be ignored here.
-        if len(lines[lineIdx]) < len(objectList):
-          print '...ending on unknown tags'
-          break
-        
-        
-        currentFrame += 1 # Incriment to next frame
-                
-        #=============================================#
-        # Import motion data and assign it to an IPO  #
-        #=============================================#
-        lines[lineIdx].append('0') # Use this as a dummy var for objects that dont have a rotate channel.
-        obIdx = 0
-        if debug: Blender.Redraw() 
-        while obIdx < len(objectList) -1:
-          if channelList[obIdx][0] != -1:
-            VAL0=lines[lineIdx][channelList[obIdx][0]]  
-            if VAL0.find('.')==-1:
-               VAL0=VAL0[:len(VAL0)-6]+'.'+VAL0[-6:] 
-            objectList[obIdx].getIpo().getCurve('LocX').addBezier((currentFrame, scale * float(VAL0)))
-
-          if channelList[obIdx][1] != -1:
-            VAL1=lines[lineIdx][channelList[obIdx][1]]  
-            if VAL1.find('.')==-1:
-               VAL1=VAL1[:len(VAL1)-6]+'.'+VAL1[-6:] 
-            objectList[obIdx].getIpo().getCurve('LocY').addBezier((currentFrame, scale * float(VAL1)))
-
-          if channelList[obIdx][2] != -1:
-            VAL2=lines[lineIdx][channelList[obIdx][2]]  
-            if VAL2.find('.')==-1:
-               VAL2=VAL2[:len(VAL2)-6]+'.'+VAL2[-6:] 
-            objectList[obIdx].getIpo().getCurve('LocZ').addBezier((currentFrame, scale * float(VAL2)))
-          
-          if channelList[obIdx][3] != '-1' or channelList[obIdx][4] != '-1' or channelList[obIdx][5] != '-1':
-            VAL3=lines[lineIdx][channelList[obIdx][3]]  
-            if VAL3.find('.')==-1:
-               VAL3=VAL3[:len(VAL3)-6]+'.'+VAL3[-6:]
-            VAL4=lines[lineIdx][channelList[obIdx][4]]
-            if VAL4.find('.')==-1:
-               VAL4=VAL4[:len(VAL4)-6]+'.'+VAL4[-6:]
-
-            VAL5=lines[lineIdx][channelList[obIdx][5]] 
-            if VAL5.find('.')==-1:
-               VAL5=VAL5[:len(VAL5)-6]+'.'+VAL5[-6:]
-
-            x, y, z = eulerRotate(float(VAL3), float(VAL4), float(VAL5))
-
-            objectList[obIdx].getIpo().getCurve('RotX').addBezier((currentFrame, x))
-            objectList[obIdx].getIpo().getCurve('RotY').addBezier((currentFrame, y))
-            objectList[obIdx].getIpo().getCurve('RotZ').addBezier((currentFrame, z))
-
-          obIdx += 1
-          # Done importing motion data #
-        
-        # lines[lineIdx] = None # Scrap old motion data, save some memory?
-        lineIdx += 1
-      # We have finished now
-      print currentFrame, 'done.'
-     
-      # No point in looking further, when this loop is done
-      # There is nothine else left to do      
-      print 'Imported ', currentFrame, ' frames'
-      break
-      
-    # Main file loop
-    lineIdx += 1
-  print "bvh import time: ", Blender.sys.time() - time1
-
-Blender.Window.FileSelector(loadBVH, "Import BVH")
+# Attempt to load psyco, speed things up
+try:
+       import psyco
+       psyco.full()    
+       print 'using psyco to speed up BVH importing'
+except:
+       #print 'psyco is not present on this system'
+       pass
+
+
+
+def main():
+       global scale
+       scale = None
+       
+       # Update as we load?
+       debug = 0
+       
+       def getScale():
+               return Draw.PupFloatInput('BVH Scale: ', 0.01, 0.001, 10.0, 0.1, 3)
+       
+       
+       #===============================================#
+       # MAIN FUNCTION - All things are done from here #
+       #===============================================#
+       def loadBVH(filename):
+               global scale
+               print '\nBVH Importer 1.05 by Campbell Barton (Ideasman) - cbarton@metavr.com'
+               
+               objectCurveMapping = {}
+               objectNameMapping = {}
+               objectMotiondataMapping = {}
+               
+               # Here we store the Ipo curves in the order they load.
+               channelCurves = []
+               
+               # Object list
+               # We need this so we can loop through the objects and edit there IPO's 
+               # Chenging there rotation to EULER rotation
+               objectList = []
+               
+               if scale == None:
+                       tempscale = getScale()
+                       if tempscale:
+                               scale = tempscale
+                       else:
+                               scale = 0.01
+               
+               Window.WaitCursor(1)
+               # Unique names, dont reuse any of these names.
+               uniqueObNames = [ob.name for ob in Object.Get()]
+               
+               
+               # FUNCTIONS ====================================#
+               def getUniqueObName(name):
+                       i = 0
+                       newname = name[:min(len(name), 12)] # Concatinate to 12 chars
+                       while newname in uniqueObNames:
+                               newname = name + str(i)
+                               i+=1
+                       return newname
+                       
+               # Change the order rotation is applied.
+               RotationMatrix = Blender.Mathutils.RotationMatrix
+               MATRIX_IDENTITY_3x3 = Blender.Mathutils.Matrix([1.0,0.0,0.0],[0.0,1.0,0.0],[0.0,0.0,1.0])
+               def eulerRotate(x,y,z): 
+                       x,y,z = x%360,y%360,z%360 # Clamp all values between 0 and 360, values outside this raise an error.
+                       xmat = RotationMatrix(x,3,'x')
+                       ymat = RotationMatrix(y,3,'y')
+                       zmat = RotationMatrix(z,3,'z')
+                       # Standard BVH multiplication order, apply the rotation in the order Z,X,Y
+                       return (ymat*(xmat * (zmat * MATRIX_IDENTITY_3x3))).toEuler()
+               
+
+               currentFrame = 1 # Set the initial frame to import all data to.
+               
+               #===============================================#
+               # makeJoint: Here we use the node data          #
+               # from the BVA file to create an empty          #
+               #===============================================#
+               BVH2BLEND_TX_NAME = {'Xposition':'LocX','Yposition':'LocY','Zposition':'LocZ','Xrotation':'RotX','Yrotation':'RotY','Zrotation':'RotZ'}
+               def makeJoint(name, parent, offset, channels):
+                       ob = Object.New('Empty', name) # New object, ob is shorter and nicer to use.
+                       
+                       objectNameMapping[name] = ob
+                       scn.link(ob) # place the object in the current scene
+                       ob.sel = 1
+                       
+                       # Make me a child of another empty.
+                       # Vale of None will make the empty a root node (no parent)
+                       if parent[-1]: # != None
+                               obParent = objectNameMapping[parent[-1]] # We use this a bit so refrence it here.
+                               obParent.makeParent([ob], 1, 0) #ojbs, noninverse, 1 = not fast.
+               
+                       # Offset Empty from BVH's initial joint location.
+                       ob.setLocation(offset[0]*scale, offset[1]*scale, offset[2]*scale)
+               
+                       # Add Ipo's for necessary channels
+                       newIpo = Ipo.New('Object', name)
+                       ob.setIpo(newIpo)
+                       obname = ob.name
+                       for channelType in channels:
+                               channelType = BVH2BLEND_TX_NAME[channelType]
+                               curve = newIpo.addCurve(channelType)
+                               curve.setInterpolation('Linear')
+                               objectCurveMapping[(obname, channelType)] = curve
+               
+                       # Add to object list
+                       objectList.append(ob)
+                       
+                       # Redraw if debugging
+                       if debug: Blender.Redraw()
+                       
+                       
+               #===============================================#
+               # makeEnd: Here we make an end node             #
+               # This is needed when adding the last bone      #
+               #===============================================#
+               def makeEnd(parent, offset):
+                       new_name = parent[-1] + '_end'
+                       ob = Object.New('Empty', new_name) # New object, ob is shorter and nicer to use.
+                       objectNameMapping[new_name] = ob
+                       scn.link(ob)
+                       ob.sel = 1
+                       
+                       # Dont check for a parent, an end node MUST have a parent
+                       obParent = objectNameMapping[parent[-1]] # We use this a bit so refrence it here.
+                       obParent.makeParent([ob], 1, 0) #ojbs, noninverse, 1 = not fast.
+               
+                       # Offset Empty
+                       ob.setLocation(offset[0]*scale, offset[1]*scale, offset[2]*scale) 
+                       
+                       # Redraw if debugging
+                       if debug: Blender.Redraw()
+               # END FUNCTION DEFINITIONS ====================================#
+                       
+               
+               
+               
+               time1 = Blender.sys.time()
+               
+               # Get the current scene.
+               scn = Scene.GetCurrent()
+               #context = scn.getRenderingContext()
+               
+               # DeSelect All
+               for ob in scn.getChildren():
+                       ob.sel = 0
+               
+               # File loading stuff
+               # Open the file for importing
+               file = open(filename, 'r')      
+               
+               # Seperate into a list of lists, each line a list of words.
+               lines = file.readlines()
+               # Non standard carrage returns?
+               if len(lines) == 1:
+                       lines = lines[0].split('\r')
+               
+               # Split by whitespace.
+               lines =[ll for ll in [ [w for w in l.split() if w != '\n' ] for l in lines] if ll]
+               # End file loading code
+       
+               
+               
+               # Create Hirachy as empties
+               if lines[0][0] == 'HIERARCHY':
+                       print 'Importing the BVH Hierarchy for:', filename
+               else:
+                       return 'ERROR: This is not a BVH file'
+               
+               # A liniar list of ancestors to keep track of a single objects heratage
+               # at any one time, this is appended and removed, dosent store tree- just a liniar list.
+               # ZERO is a place holder that means we are a root node. (no parents)
+               parent = [None] 
+               
+               #channelList, sync with objectList:  [[channelType1, channelType2...],  [channelType1, channelType2...)]
+               channelList = []
+               channelIndex = -1
+               
+               lineIdx = 0 # An index for the file.
+               while lineIdx < len(lines) -1:
+                       #...
+                       if lines[lineIdx][0] == 'ROOT' or lines[lineIdx][0] == 'JOINT':
+                               
+                               # Join spaces into 1 word with underscores joining it.
+                               if len(lines[lineIdx]) > 2:
+                                       lines[lineIdx][1] = '_'.join(lines[lineIdx][1:])
+                                       lines[lineIdx] = lines[lineIdx][:2]
+                               
+                               # MAY NEED TO SUPPORT MULTIPLE ROOT's HERE!!!, Still unsure weather multiple roots are possible.??
+                               
+                               # Make sure the names are unique- Object names will match joint names exactly and both will be unique.
+                               name = getUniqueObName(lines[lineIdx][1])
+                               uniqueObNames.append(name)
+                               
+                               print '%snode: %s, parent: %s' % (len(parent) * '  ', name,  parent[-1])
+                               
+                               lineIdx += 2 # Incriment to the next line (Offset)
+                               offset = ( float(lines[lineIdx][1]), float(lines[lineIdx][2]), float(lines[lineIdx][3]) )
+                               lineIdx += 1 # Incriment to the next line (Channels)
+                               
+                               # newChannel[Xposition, Yposition, Zposition, Xrotation, Yrotation, Zrotation]
+                               # newChannel references indecies to the motiondata,
+                               # if not assigned then -1 refers to the last value that will be added on loading at a value of zero, this is appended 
+                               # We'll add a zero value onto the end of the MotionDATA so this is always refers to a value.
+                               newChannel = [-1, -1, -1, -1, -1, -1] 
+                               for channel in lines[lineIdx][2:]:
+                                       channelIndex += 1 # So the index points to the right channel
+                                       if channel == 'Xposition':
+                                               newChannel[0] = channelIndex
+                                       elif channel == 'Yposition':
+                                               newChannel[1] = channelIndex
+                                       elif channel == 'Zposition':
+                                               newChannel[2] = channelIndex
+                                       elif channel == 'Xrotation':
+                                               newChannel[3] = channelIndex
+                                       elif channel == 'Yrotation':
+                                               newChannel[4] = channelIndex
+                                       elif channel == 'Zrotation':
+                                               newChannel[5] = channelIndex
+                               
+                               channelList.append(newChannel)
+                               
+                               channels = lines[lineIdx][2:]
+                               
+                               # Call funtion that uses the gatrhered data to make an empty.
+                               makeJoint(name, parent, offset, channels)
+                               
+                               # If we have another child then we can call ourselves a parent, else 
+                               parent.append(name)
+       
+                       # Account for an end node
+                       if lines[lineIdx][0] == 'End' and lines[lineIdx][1] == 'Site': # There is somtimes a name after 'End Site' but we will ignore it.
+                               lineIdx += 2 # Incriment to the next line (Offset)
+                               offset = ( float(lines[lineIdx][1]), float(lines[lineIdx][2]), float(lines[lineIdx][3]) )
+                               makeEnd(parent, offset)
+                               
+                               # Just so we can remove the Parents in a uniform way- End end never has kids
+                               # so this is a placeholder
+                               parent.append(None)
+                       
+                       if len(lines[lineIdx]) == 1 and lines[lineIdx][0] == '}': # == ['}']
+                               parent.pop() # Remove the last item
+                       
+                       #=============================================#
+                       # BVH Structure loaded, Now import motion     #
+                       #=============================================#         
+                       if len(lines[lineIdx]) == 1 and lines[lineIdx][0] == 'MOTION':
+                               print '\nImporting motion data'
+                               lineIdx += 3 # Set the cursor to the first frame
+                               
+                               #=============================================#
+                               # Add a ZERO keyframe, this keeps the rig     #
+                               # so when we export we know where all the     #
+                               # joints start from                           #
+                               #=============================================#
+                               
+                               for obIdx, ob in enumerate(objectList):
+                                       obname = ob.name
+                                       if channelList[obIdx][0] != -1:
+                                               objectCurveMapping[obname, 'LocX'].addBezier((currentFrame,0))
+                                               objectMotiondataMapping[obname, 'LocX'] = []
+                                       if channelList[obIdx][1] != -1:
+                                               objectCurveMapping[obname, 'LocY'].addBezier((currentFrame,0))
+                                               objectMotiondataMapping[obname, 'LocY'] = []
+                                       if channelList[obIdx][2] != -1:
+                                               objectCurveMapping[obname, 'LocZ'].addBezier((currentFrame,0))
+                                               objectMotiondataMapping[obname, 'LocZ'] = []
+                                       if\
+                                       channelList[obIdx][3] != -1 or\
+                                       channelList[obIdx][4] != -1 or\
+                                       channelList[obIdx][5] != -1:
+                                               objectMotiondataMapping[obname, 'RotX'] = []
+                                               objectMotiondataMapping[obname, 'RotY'] = []
+                                               objectMotiondataMapping[obname, 'RotZ'] = []
+                               
+                               #=============================================#
+                               # Loop through frames, each line a frame      #
+                               #=============================================#                 
+                               MOTION_DATA_LINE_LEN = len(lines[lineIdx])
+                               while lineIdx < len(lines):
+                                       line = lines[lineIdx]
+                                       if MOTION_DATA_LINE_LEN != len(line):
+                                               print 'ERROR: Incomplete motion data on line %i, finishing import.' % lineIdx
+                                               break
+                                               
+                                       # Exit loop if we are past the motiondata.
+                                       # Some BVH's have extra tags like 'CONSTRAINTS and MOTIONTAGS'
+                                       # I dont know what they do and I dont care, they'll be ignored here.
+                                       if len(line) < len(objectList):
+                                               print '...ending on unknown tags'
+                                               break
+                                       
+                                       
+                                       currentFrame += 1 # Incriment to next frame
+                                                                       
+                                       #=============================================#
+                                       # Import motion data and assign it to an IPO    #
+                                       #=============================================#
+                                       line.append(0.0) # Use this as a dummy var for objects that dont have a loc/rotate channel.
+                                       
+                                       if debug: Blender.Redraw() 
+                                       for obIdx, ob in enumerate(objectList):
+                                               obname = ob.name
+                                               obChannel = channelList[obIdx] 
+                                               if channelList[obIdx][0] != -1:
+                                                       objectMotiondataMapping[obname, 'LocX'].append((currentFrame, scale * float(  line[obChannel[0]]  )))
+                                                       
+                                               if channelList[obIdx][1] != -1:
+                                                       objectMotiondataMapping[obname, 'LocY'].append((currentFrame, scale * float(  line[obChannel[1]]         )))
+
+                                               if channelList[obIdx][2] != -1:
+                                                       objectMotiondataMapping[obname, 'LocZ'].append((currentFrame, scale * float(  line[obChannel[2]]  )))
+                                               
+                                               if obChannel[3] != -1 or obChannel[4] != -1 or obChannel[5] != -1:                                              
+                                                       x, y, z = eulerRotate(float( line[obChannel[3]] ), float( line[obChannel[4]] ), float( line[obChannel[5]] ))
+                                                       x,y,z = x/10.0, y/10.0, z/10.0 # For IPO's 36 is 360d
+                                                       motionMappingRotX = objectMotiondataMapping[obname, 'RotX']
+                                                       motionMappingRotY = objectMotiondataMapping[obname, 'RotY']
+                                                       motionMappingRotZ = objectMotiondataMapping[obname, 'RotZ']
+                                                       
+                                                       # Make interpolation not cross between 180d, thjis fixes sub frame interpolation and time scaling.
+                                                       # Will go from (355d to 365d) rather then to (355d to 5d) - inbetween these 2 there will now be a correct interpolation.
+                                                       if len(motionMappingRotX) > 1:
+                                                               while (motionMappingRotX[-1][1] - x) > 18: x+=36
+                                                               while (motionMappingRotX[-1][1] - x) < -18: x-=36
+                                                               
+                                                               while (motionMappingRotY[-1][1] - y) > 18: y+=36
+                                                               while (motionMappingRotY[-1][1] - y) < -18: y-=36
+                                                               
+                                                               while (motionMappingRotZ[-1][1] - z) > 18: z+=36
+                                                               while (motionMappingRotZ[-1][1] - z) < -18: z-=36
+                                                       
+                                                       motionMappingRotX.append((currentFrame, x))
+                                                       motionMappingRotY.append((currentFrame, y))
+                                                       motionMappingRotZ.append((currentFrame, z))
+                                               # Done importing motion data #
+                                       
+                                       lineIdx += 1
+                               
+                               #=======================================#
+                               # Now Write the motion to the IPO's     #
+                               #=======================================#
+                               for key, motion_data in objectMotiondataMapping.iteritems():
+                                       
+                                       # Strip the motion data where all the points have the same falue.
+                                       i = len(motion_data) -2
+                                       while i > 0 and len(motion_data) > 2:
+                                               if motion_data[i][1] == motion_data[i-1][1] == motion_data[i+1][1]:
+                                                       motion_data.pop(i)
+                                               i-=1
+                                       # Done stripping.                                               
+                                       
+                                       obname, tx_type = key
+                                       curve = objectCurveMapping[obname, tx_type]
+                                       for point_data in motion_data:
+                                               curve.addBezier( point_data )
+                               # Imported motion to an IPO
+                               
+                               # No point in looking further, when this loop is done
+                               # There is nothine else left to do                      
+                               break
+                               
+                       # Main file loop
+                       lineIdx += 1
+                       
+               print 'bvh import time for %i frames: %.6f' % (currentFrame, Blender.sys.time() - time1)
+               Window.RedrawAll()
+               Window.WaitCursor(0)
+       
+       Blender.Window.FileSelector(loadBVH, "Import BVH")
+       
+       #=============#
+       # TESTING     #
+       #=============#
+       '''
+       #loadBVH('/metavr/mocap/bvh/boxer.bvh')
+       #loadBVH('/metavr/mocap/bvh/dg-306-g.bvh') # Incompleate EOF
+       #loadBVH('/metavr/mocap/bvh/wa8lk.bvh') # duplicate joint names, \r line endings.
+       #loadBVH('/metavr/mocap/bvh/walk4.bvh') # 0 channels
+       scale  = 0.01
+       import os
+       DIR = '/metavr/mocap/bvh/'
+       for f in os.listdir(DIR):
+               if f.endswith('.bvh'):
+                       s = Scene.New(f)
+                       s.makeCurrent()
+                       loadBVH(DIR + f)
+       '''
+if __name__ == '__main__':
+       main()
\ No newline at end of file
index 4ce58e06e10ed387e6d263949507f6d17129d321..c5d2eb5568e24f9934707b450b1f9e4caf9692c9 100644 (file)
@@ -29,6 +29,26 @@ Usage:<br>
 __author__ = "Campbell Barton AKA Ideasman"
 __url__ = ["http://members.iinet.net.au/~cpbarton/ideasman/", "blender", "elysiun"]
 
+# -------------------------------------------------------------------------- 
+# ***** BEGIN GPL LICENSE BLOCK ***** 
+# 
+# This program is free software; you can redistribute it and/or 
+# modify it under the terms of the GNU General Public License 
+# as published by the Free Software Foundation; either version 2 
+# of the License, or (at your option) any later version. 
+# 
+# This program is distributed in the hope that it will be useful, 
+# but WITHOUT ANY WARRANTY; without even the implied warranty of 
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 
+# GNU General Public License for more details. 
+# 
+# You should have received a copy of the GNU General Public License 
+# along with this program; if not, write to the Free Software Foundation, 
+# Inc., 59 Temple Place - Suite 330, Boston, MA        02111-1307, USA. 
+# 
+# ***** END GPL LICENCE BLOCK ***** 
+# -------------------------------------------------------------------------- 
+
 import Blender
 from Blender import *
 import sys as python_sys
@@ -132,7 +152,7 @@ def unzip(list):
                                this function will fail
        """
        
-       if len(list) == 0: return ()
+       if not list: return ()
        l = []
        for t in range(len(list[0])):
                l.append(map( lambda x,t=t: x[t], list ))
@@ -213,7 +233,7 @@ def rdir(dirString, depth=0):
                        # Dont bother with this data.
                        continue
                
-               if type(dirItem) != type('str'):
+               if type(dirItem) != types.StringType:
                        print dirItem, type(dirItem)
                
                if dirItem not in COLLECTED_VAR_NAMES.keys():
@@ -229,17 +249,17 @@ def rdir(dirString, depth=0):
                #print type(dirItem)
                #if type(dirData) == types.ClassType or \
                #        type(dirData) == types.ModuleType:
-               
-               if type(dirData) != types.StringType and\
-               type(dirData) != types.DictType and\
-               type(dirData) != types.DictionaryType and\
-               type(dirData) != types.FloatType and\
-               type(dirData) != types.IntType and\
-               type(dirData) != types.NoneType and\
-               type(dirData) != types.StringTypes and\
-               type(dirData) != types.TypeType and\
-               type(dirData) != types.TupleType and\
-               type(dirData) != types.BuiltinFunctionType:
+               type_dirData = type(dirData)
+               if type_dirData != types.StringType and\
+               type_dirData != types.DictType and\
+               type_dirData != types.DictionaryType and\
+               type_dirData != types.FloatType and\
+               type_dirData != types.IntType and\
+               type_dirData != types.NoneType and\
+               type_dirData != types.StringTypes and\
+               type_dirData != types.TypeType and\
+               type_dirData != types.TupleType and\
+               type_dirData != types.BuiltinFunctionType:
                        # print type(dirData), dirItem
                        # Dont loop up dirs for strings ints etc.
                        if dirItem not in dirStringSplit:
@@ -519,16 +539,17 @@ def handle_event(evt, val):
                                menuList.sort()
                                
                                choice = PupMenuLess( # Menu for the user to choose the autocompleate
-                               'Choices (Shift for Whole name, Ctrl for Docs)%t|' + # Title Text
+                               'Choices (Shift for local name, Ctrl for Docs)%t|' + # Title Text
                                '|'.join(['%s,  %s' % m for m in menuList])) # Use Absolute names m[0]
                                
                                if choice != -1:
                                        if Window.GetKeyQualifiers() & Window.Qual.CTRL:  # Help
                                                cmdBuffer[-1].cmd = ('help(%s%s) ' % (cmdBuffer[-1].cmd[:cursor - len(editVar)], menuList[choice-1][0]))    
                                        elif Window.GetKeyQualifiers() & Window.Qual.SHIFT:  # Put in the long name
-                                               cmdBuffer[-1].cmd = ('%s%s%s' % (cmdBuffer[-1].cmd[:cursor - len(editVar)], menuList[choice-1][0], cmdBuffer[-1].cmd[cursor:]))    
-                                       else: # Only paste in the Short name
                                                cmdBuffer[-1].cmd = ('%s%s%s' % (cmdBuffer[-1].cmd[:cursor - len(editVar)], menuList[choice-1][1], cmdBuffer[-1].cmd[cursor:]))    
+                                       else: # Only paste in the Short name
+                                               cmdBuffer[-1].cmd = ('%s%s%s' % (cmdBuffer[-1].cmd[:cursor - len(editVar)], menuList[choice-1][0], cmdBuffer[-1].cmd[cursor:]))    
+                                               
                                                
                else:
                        # print 'NO EDITVAR'
@@ -539,11 +560,8 @@ def handle_event(evt, val):
        # Quit from menu only
        #if (evt == Draw.ESCKEY and not val):
        #       Draw.Exit()
-       if evt == Draw.MOUSEX: # AVOID TOO MANY REDRAWS.
-               return
-       elif evt == Draw.MOUSEY:
-               return
-       
+       if evt == Draw.MOUSEX or evt == Draw.MOUSEY: # AVOID TOO MANY REDRAWS.
+               return  
        
        
        global cursor
@@ -805,4 +823,4 @@ cmdBuffer.append(cmdLine(' ', 0, 0))
 def main():
        Draw.Register(draw_gui, handle_event, handle_button_event)
 
-main()
+main()
\ No newline at end of file
index d56951959c3073a1d6e93a00f9f86c973b50b5e3..843664edb05c7823a3bdab73ea1304d6a1184d46 100644 (file)
@@ -11,7 +11,7 @@ __author__ = "Jean-Michel Soler (jms)"
 __url__ = ("blender", "elysiun",
 "Script's homepage, http://jmsoler.free.fr/didacticiel/blender/tutor/cpl_hotkeyscript.htm",
 "Communicate problems and errors, http://www.zoo-logique.org/3D.Blender/newsportal/thread.php?group=3D.Blender")
-__version__ = "10/04/2005"
+__version__ = "12/18/2005"
 
 __bpydoc__ = """\
 This script is a reference about all hotkeys and mouse actions in Blender.
@@ -26,10 +26,9 @@ Notes:<br>
     
 """
 
-# $Id$
 #------------------------
 #  Hotkeys script
-#         jm soler (2003-->10/2004)
+#         jm soler (2003-->12/2005)
 # -----------------------
 # Page officielle :
 #   http://jmsoler.free.fr/didacticiel/blender/tutor/cpl_hotkeyscript.htm
@@ -75,16 +74,17 @@ hotkeys={
 ['Ctrl-,', 'Set Median Point rotation scaling pivot'],
 ['.', 'Set 3D cursor as rotation scaling pivot'],
 ['Ctrl-.', 'Set Individual Object Centers as rotation scaling pivot'],
-['~', 'Display all layers (German keys: ö)'],
-['Shift-~', 'Display all/previous layers (German keys: Shift-ö)'],
+['~', 'Display all layers (German keys: ö,french keyboard: ù)'],
+['Shift-~', 'Display all/previous layers (German keys: Shift-ö, french keyboard: shift-ù)'],
 ['Space', 'Popup menu'],
 ['Space', '3D View: camera selected + fly mode, accept'],
+['Ctrl-Space', 'Manipulator (transform widget) Menu'],
 ['TAB', 'Enter/exit Edit Mode'],
 ['TAB', 'Edit Mode and Numerical Edit (see N key) : move to next input value'],
 ['TAB', 'Sequencer: Edit meta strip'],
 ['TAB', 'IPO: Edit selected'],
-['Ctrl-TAB', 'Enter/exit Pose Mode'],
-['Shift-TAB', 'Enter Object Mode'],
+['Ctrl-TAB', 'ARMATURE : Enter/exit Pose Mode'],
+['Shift-TAB', 'EDIT MODE : Enter Object Mode'],
 ['Ctrl-Open menu /', ''],
 ['Ctrl-Load Image', 'Opens a thumbnail browser instead of file browser for images']
 ],
@@ -97,20 +97,25 @@ hotkeys={
 ['LMB hold down', 'Popup menu'],
 ['LMB hold down drag', 'Gesture'],
 ['Ctrl-LMB', 'IPO: Add key'],
+['Ctrl-LMB', '3D View: OBJECT or EDIT mode, select with the Lasso tool'],
+['Ctrl-LMB', '3D View: ARMATURE EDIT mode, add a new bone to the selected end '],
+['Shift-LMB','MANIPULATOR (transform widget): select the axe to remove in the current transformation ( if there is a problem with small step adjustment, first select the axe or axes with LBM alone)'],
 ['MMB', 'Rotate'],
 ['Ctrl-MMB', 'Zoom view'],
 ['Shift-MMB', 'Move view'],
 ['RMB', 'Select'],
 ['RMB drag', 'Border select circle: subtract from selection'],
 ['RMB hold down', 'Popup menu'],
-['Alt+Ctrl-RMB', 'Edit Mode: Select edge'],
+['Alt-RMB', 'Object Mode :Select but in a displayed list of objects located under the mouse cursor'],
+['Alt-RMB', 'Edit Mode: Select EDGES LOOP '],
+['Alt+Ctrl-RMB', 'Edit Mode: Select FACES LOOP'],      
 ['Alt+Ctrl-RMB', 'UV Image Editor: Select face'],
 ['Shift-RMB', 'Add/subtract to/from selection'],
 ['Wheel', 'Zoom view'],
 ['Transformations:', ''],
 ['Drag+Ctrl', 'Step adjustment'],
-['Drag+Ctrl+Shift', 'Small step adjustment'],
-['Drag+Shift', 'Fine adjustment'],
+['Drag+Ctrl+Shift', 'Small step adjustment (Transform Widget : first select the axe or axes with LBM alone)'],
+['Drag+Shift', 'Fine adjustment (Transform Widget : first select the axe or axes with LBM alone)'],
 ['LMB', 'Confirm transformation'],
 ['MMB', 'Toggle optional transform feature'],
 ['RMB', 'Abort transformation']
@@ -118,33 +123,36 @@ hotkeys={
 
 'F-Keys ':[
 ['F1', 'Open File'],
+['Shift-F1', 'Library Data Select'],
 ['F2', 'Save File'],
+['Shift-F2', 'Export DXF'],
+['Ctrl-F2', 'Save/export in vrml 1.0 format' ],
 ['F3', 'Save image'],
+['Ctrl-F3', 'Save image : dump 3d view'],
+['Ctrl-Shift-F3', 'Save image : dump screen'],
 ['F4', 'Logic Window (may change)'],
-['F5', 'Material Window'],
-['F6', 'Texture Window'],
-['F7', 'Object Window'],
-['F8', 'World Window'],
-['F9', 'Edit Mode Window'],
-['F10', 'Render Window'],
-['F11', 'Recall the last rendered image'],
-['F12', 'Render current Scene'],
-['Ctrl-Shift-F12', 'NLA Editor'],
-['Shift-F1', 'Library Data Select'],
-['Shift-F2', 'Export DXF'],
 ['Shift-F4', 'Object manager Data Select '],
+['F5', 'Material Window'],
 ['Shift-F5', '3D Window'],
+['F6', 'Texture Window'],
 ['Shift-F6', 'IPO Window'],
+['F7', 'Object Window'],
 ['Shift-F7', 'Buttons Window'],
+['F8', 'World Window'],
 ['Shift-F8', 'Video Sequencer Window'],
+['F9', 'Edit Mode Window'],
 ['Shift-F9', 'OOP Window'],
 ['Alt-Shift-F9', 'OutLiner Window'],
+['F10', 'Render Window'],
 ['Shift-F10', 'UV Image Editor'],
+['F11', 'Recall the last rendered image'],
 ['Shift-F11', 'Text Editor'],
+['ctrl-F11', 'replay the last rendered animation'],
+['F12', 'Render current Scene'],
+['Ctrl-F12', 'Render animation'],
+['Ctrl-Shift-F12', 'NLA Editor'],
 ['Shift-F12', 'Action Editor'],
-['Ctrl-F2', 'Save/export in vrml 1.0 format' ],
-['Ctrl-F3', 'Save image : dump 3d view'],
-['Ctrl-Shift-F3', 'Save image : dump screen']
+['Shift-F12', 'Action Editor']
 ],
 
 'Numbers ':[
@@ -152,7 +160,10 @@ hotkeys={
 ['1..2..0-=', 'Edit Mode with Size, Grab, rotate tools : enter value'],
 ['Alt-1..2..0', 'Show layer 11..12..20'],
 ['Shift-1..2..0-=', 'Toggle layer 1..2..12'],
-['Shift-ALT-...', 'Toggle layer 11..12..20']
+['Shift-ALT-...', 'Toggle layer 11..12..20'],
+['Crtl-Shift-ALT-3', 'Edit Mode & Face Mode : Triangle faces'],
+['Crtl-Shift-ALT-4', 'Edit Mode & Face Mode : Quad faces'],
+['Crtl-Shift-ALT-5', 'Edit Mode & Face Mode : Non quad or triangle faces'],
 ],
 
 'Numpad ':[
@@ -167,9 +178,10 @@ hotkeys={
 ['Numpad +', 'In OutLiner window, Expand one level of the  hierarchy'],
 ['Alt-Numpad -', 'Proportional vertex Edit Mode: Decrease range of influence'],
 ['Ctrl-Numpad +', 'Edit Mode: Select Less vertices'],
-['Numpad INS', 'Set Camera view'],
-['Ctrl-Numpad INS', 'Set active object as camera'],
-['Alt-Numbad INS', 'Restore old camera'],
+['Numpad 0', 'Set Camera view'],
+['Ctrl-Numpad 0', 'Set active object as camera'],
+['Alt-Numbad 0', 'Restore old camera'],
+['Ctrl-Alt-Numpad 0', 'Align active camera to view'],
 ['Numpad 1', 'Front view'],
 ['Ctrl-Numpad 1', 'Back view'],
 ['Numpad 3', 'Right view'],
@@ -179,7 +191,9 @@ hotkeys={
 ['Numpad 5', 'Toggle orthogonal/perspective view'],
 ['Numpad 9', 'Redraw view'],
 ['Numpad 4', 'Rotate view left'],
+['ctrl-Shift-Numpad 4', 'Previous Screen'],
 ['Numpad 6', 'Rotate view right'],
+['ctrl-Shift-Numpad 6', 'Next Screen'],
 ['Numpad 8', 'Rotate view up'],
 ['Numpad 2', 'Rotate view down']
 ],
@@ -207,6 +221,7 @@ hotkeys={
 ['Alt-Up', 'Blender in Fullscreen mode'],
 ['Ctrl-Left', 'Previous screen'],
 ['Ctrl-Right', 'Next screen'],
+['Ctrl-Alt-C', 'Object Mode : Add  Constraint'],       
 ['Ctrl-Down', 'Maximize window toggle'],
 ['Ctrl-Up', 'Maximize window toggle'],
 ['Shift-Arrow', 'Toggle first frame/ last frame']
@@ -268,6 +283,12 @@ hotkeys={
 ['EZ', 'Edit Mode: Extrude along Z axis'],
 ['Alt-E', 'Edit Mode: exit Edit Mode'],
 ['Ctrl-E', 'Edit Mode: Edge Specials menu'],
+['Ctrl-E', 'Edit Mode: Edge Specials menu, Mark seams'],
+['Ctrl-E', 'Edit Mode: Edge Specials menu, Clear seams'],
+['Ctrl-E', 'Edit Mode: Edge Specials menu, Rotate Edge CW'],
+['Ctrl-E', 'Edit Mode: Edge Specials menu, Rotate Edge CCW'],
+['Ctrl-E', 'Edit Mode: Edge Specials menu, Loop Cut'],
+['Ctrl-E', 'Edit Mode: Edge Specials menu, Edge Slide'],
 ['Shift-E', 'Edit Mode: SubSurf Edge Sharpness']
 ],
 
@@ -287,6 +308,7 @@ hotkeys={
 ['Alt-G', 'Clear location'],
 ['Shift-ALT-G', 'Remove selected objects from group'],
 ['Ctrl-G', 'Add selected objects to group'],
+['Ctrl-Alt-G', 'MANIPULATOR (transform widget): set in Grab Mode'],
 ['Shift-G', 'Selected Group menu']
 ],
 
@@ -295,11 +317,11 @@ hotkeys={
 ['H', 'Curves: Set handle type'],
 ['H', 'Action editor: Handle type aligned'],
 ['H', 'Action editor: Handle type free'],              
-['Alt-H', 'Show Hidden vertices/faces'],
+['Alt-H', 'Edit Mode : Show Hidden vertices/faces'],
 ['Shift-H', 'Curves: Automatic handle calculation'],
 ['Shift-H', 'Action editor: Handle type auto'],        
-['Shift-H', 'Edit Mode, Hide deselected  vertices/faces'],
-['Ctrl-H', 'Edit Mode, Add a hook on selected points or show the hook menu .']
+['Shift-H', 'Edit Mode : Hide deselected  vertices/faces'],
+['Ctrl-H', 'Edit Mode : Add a hook on selected points or show the hook menu .']
 ],
 
 "I":[ 
@@ -329,7 +351,7 @@ hotkeys={
 
 "L":[ 
 ['L', 'Make local menu'],
-['L', 'Edit mode: Select linked vertices (near mouse pointer)'],
+['L', 'Edit Mode: Select linked vertices (near mouse pointer)'],
 ['L', 'OOPS window: Select linked objects'],
 ['L', 'UV Face Select: Select linked faces'],
 ['Ctrl-L', 'Make links menu (for instance : to scene...)'],
@@ -353,7 +375,7 @@ hotkeys={
 ['N', 'OOPS window: Rename object/linked objects'] ,
 ['Ctrl-N', 'Armature: Recalculate bone roll angles'] ,
 ['Ctrl-N', 'Edit Mode: Recalculate normals to outside'] ,
-['Ctrl-ALT-N', 'Edit Mode: Recalculate normals to inside'] ],
+['Ctrl-Shift-N', 'Edit Mode: Recalculate normals to inside'] ],
 
 "O":[ 
 ['O', 'Edit Mode/UV Image Editor: Toggle proportional vertex editing'],
@@ -365,6 +387,7 @@ hotkeys={
 "P":[ 
 ['P', 'Object Mode: Start realtime engine'],
 ['P', 'Edit mode: Seperate vertices to new object'],
+['shift-P', 'Edit mode: Push-Pull'],
 ['P', 'UV Image Editor: Pin UVs'],
 ['Alt-P', 'Clear parent relationship'],
 ['Alt-P', 'UV Image Editor: Unpin UVs'],
@@ -387,6 +410,7 @@ hotkeys={
 ['RZZ', "Rotate around object's local Z axis"],
 ['Alt-R', 'Clear object rotation'],
 ['Ctrl-R', 'Edit Mode: Knife, cut selected edges, accept left mouse/ cancel right mouse'],
+['Ctrl-Alt-R', 'MANIPULATOR (transform widget): set in Rotate Mode'],
 ['Shift-R', 'Edit Mode: select Face Loop'],
 ['Shift-R', 'Nurbs: Select row'] ],
 
@@ -400,8 +424,11 @@ hotkeys={
 ['SYY', 'Flip around Y axis and show axis'] ,
 ['SZZ', 'Flip around Z axis and show axis'] ,
 ['Alt-S', 'Edit mode: Shrink/fatten (Scale along vertex normals)'] ,
+['Ctrl-Shift-S', 'Edit mode: To Sphere'] ,
+['Ctrl-Alt-Shift-S', 'Edit mode: Shear'] ,
 ['Alt-S', 'Clear object size'] ,
 ['Ctrl-S', 'Edit mode: Shear'] ,
+['Ctrl-Alt-G', 'MANIPULATOR (transform widget): set in Size Mode'],
 ['Shift-S', 'Cursor/Grid snap menu'] ],
 
 "T":[ 
@@ -418,18 +445,18 @@ hotkeys={
 "U":[ 
 ['U', 'Make single user menu (for import completly linked object to another scene  for instance) '] ,
 ['U', '3D View: Make Single user Menu'] ,
-['U', 'Edit Mode: Reload object data from before entering Edit Mode'] ,
 ['U', 'UV Face Select: Automatic UV calculation menu'] ,
 ['U', 'Vertex-/Weightpaint mode: Undo'] ,
 ['Ctrl-U', 'Save current state as user default'],
 ['Shift-U', 'Edit Mode: Redo Menu'],
-['Alt-U', 'Edit Mode: Undo Menu'] ],
+['Alt-U', 'Edit Mode & Object Mode: Undo Menu']],
 
 "V":[ 
 ['V', 'Curves/Nurbs: Vector handle'],
+['V', 'Edit Mode : Rip selected vertices'],
 ['V', 'Vertexpaint mode'],
 ['V', 'UV Image Editor: Stitch UVs'],
-['V', 'Action editor: Vector'],        
+['V', 'Action editor: Vector'],
 ['Alt-V', "Scale object to match image texture's aspect ratio"],
 ['Shift-V', 'Edit mode: Align view to selected vertices'],
 ['Shift-V', 'UV Image Editor: Limited Stitch UVs popup'],
@@ -437,13 +464,37 @@ hotkeys={
 ],
 
 "W":[ 
-['W', 'Object Mode: Boolean operations menu'],
-['W', 'Edit mode: Specials menu'],
+['W', 'Edit Mode: Specials menu'],
+['W', 'Edit Mode: Specials menu, ARMATURE 1 Subdivide'],
+['W', 'Edit Mode: Specials menu, ARMATURE 2 Flip Left-Right Name'],
+['W', 'Edit Mode: Specials menu, CURVE 1 Subdivide'],
+['W', 'Edit Mode: Specials menu, CURVE 2 Swich Direction'],
+['W', 'Edit Mode: Specials menu, MESH 1 Subdivide'],
+['W', 'Edit Mode: Specials menu, MESH 2 Subdivide Multi'],
+['W', 'Edit Mode: Specials menu, MESH 3 Subdivide Multi Fractal'],
+['W', 'Edit Mode: Specials menu, MESH 4 Subdivide Smooth'],
+['W', 'Edit Mode: Specials menu, MESH 5 Merge'],
+['W', 'Edit Mode: Specials menu, MESH 6 Remove Double'],
+['W', 'Edit Mode: Specials menu, MESH 7 Hide'],
+['W', 'Edit Mode: Specials menu, MESH 8 Reveal'],
+['W', 'Edit Mode: Specials menu, MESH 9 Select Swap'],
+['W', 'Edit Mode: Specials menu, MESH 10 Flip Normal'],
+['W', 'Edit Mode: Specials menu, MESH 11 Smooth'],
+['W', 'Edit Mode: Specials menu, MESH 12 Bevel'],
+['W', 'Edit Mode: Specials menu, MESH 13 Set Smooth'],
+['W', 'Edit Mode : Specials menu, MESH 14 Set Solid'],
+['W', 'Object Mode : on MESH objects, Boolean Tools menu'],
+['W', 'Object Mode : on MESH objects, Boolean Tools 1 Intersect'],
+['W', 'Object Mode : on MESH objects, Boolean Tools 2 union'],
+['W', 'Object Mode : on MESH objects, Boolean Tools 3 difference'],
+['W', 'Object Mode : on MESH objects, Boolean Tools 4 Add an intersect Modifier'],
+['W', 'Object Mode : on MESH objects, Boolean Tools 5 Add an union Modifier'],
+['W', 'Object Mode : on MESH objects, Boolean Tools 6 Add a difference Modifier'],
+['W', 'Object mode : on TEXT object, Split characters, a new TEXT object by character in the selected string '],
 ['W', 'UV Image Editor: Weld/Align'],
 ['WX', 'UV Image Editor: Weld/Align X axis'],
 ['WY', 'UV Image Editor: Weld/Align Y axis'],
 ['Ctrl-W', 'Save current file'] ,
-['Ctrl-W', 'Nurbs: Switch direction'] ,
 ['Shift-W', 'Warp/bend selected vertices around cursor'],
 ['alt-W', 'Export in videoscape format']
  ],
@@ -456,13 +507,15 @@ hotkeys={
  ],
 
 "Y":[ 
-['Y', 'Mesh: Split selected vertices/faces from the rest'] ],
+['Y', 'Edit Mode & Mesh : Split selected vertices/faces from the rest'],
+['Ctrl-Y', 'Object Mode : Redo'],
+],
 
 "Z":[ 
 ['Z', 'Render Window: 200% zoom from mouse position'],
 ['Z', 'Switch 3d draw type : solide/ wireframe (see also D)'],
 ['Alt-Z', 'Switch 3d draw type : solid / textured (see also D)'],
-['Ctrl-Z', 'Switch 3d draw type : shaded (see also D)'],
+['Ctrl-Z', 'Object Mode : Undo'],
 ['Shift-Z', 'Switch 3d draw type : shaded / wireframe (see also D)'],
 
 ]}]}
@@ -498,12 +551,15 @@ def searchfor(SEARCHLINE):
                                #print 'k, l : ', k,  l, l[1] 
                                if  l[1].upper().find(SEARCHLINE.upper())!=-1:
                                        FINDLIST.append(l)
+                                       
                elif k == 'Letters ':
                        for l in hotL :
                                for l0 in hotkeys['Letters '][0][l][:-1]:
                                        #print 'k, l : ',l,  k,  l0
                                        if l0[1].upper().find(SEARCHLINE.upper())!=-1:
                                                FINDLIST.append(l0)
+       #print 'FINDLIST',FINDLIST                                      
+       FINDLIST.append(['Find list','Entry'])
        return FINDLIST                 
                        
        
@@ -569,6 +625,7 @@ def draw():
            listed=hot.index(k)
     l=0
     size[3]=size[3]-4
+    
     if hot[listed]!='Letters ' and hot[listed]!='Search ' :
        size[3]=size[3]-8
        SCROLL=size[3]/21
@@ -594,17 +651,19 @@ def draw():
           glRasterPos2f(4+8*15, size[3]-(58+21*l))
           Text('  : '+n[1]) 
           l+=1
+          
     elif hot[listed]=='Search ' :
        r=[0,size[3]-70,
           size[2], size[3]-44]
        trace_rectangle4(r,c2)
        SEARCHLINE=String(' ', LINE, 42, size[3]-68,200,18,SEARCHLINE.val, 256,'')
        if len(FINDED)>0:
-         LEN=len(FINDED)          
-         size[3]=size[3]-8
-         SCROLL=size[3]/21
-         END=-1
-         if SCROLL < len(FINDED):
+        LEN=len(FINDED)           
+        size[3]=size[3]-8
+        SCROLL=size[3]/21
+        END=-1
+        
+        if SCROLL < len(FINDED):
             Button('/\\',up,4,size[3]+8,20,14,'Scroll up') 
             Button('\\/',down,4,size[3]-8,20,14,'Scroll down')            
             if (SCROLL+UP)<len(FINDED):
@@ -612,9 +671,9 @@ def draw():
             else:
                END=-1
                #UP=len(FINDED)-SCROLL
-         else:
-              UP=0         
-         for n in FINDED[UP:END]:
+        else:
+            UP=0         
+        for n in FINDED[UP:END]:
              if l%2==0:
                  r=[0,size[3]-(21*l+66+24),
                      size[2], size[3]-(21*l+43+24)]
@@ -714,4 +773,4 @@ def bevent(evt):
           Blender.Window.Redraw()
 
 
-Register(draw, event, bevent)
+Register(draw, event, bevent)
\ No newline at end of file
index a109acc02c15e0dab5bb2d6901c5139f8ac9bd7d..d3d7099594fc09c07190991bc32fb78527f14e66 100644 (file)
@@ -46,12 +46,27 @@ v5.5 format.
 # | http://www.redrival.com/scorpius                        |
 # | scorpius@netzero.com                                    |
 # | April 21, 2002                                          |
-# | Released under the Blender Artistic Licence (BAL)       |
-# | Import Export Suite v0.5                                |
-# +---------------------------------------------------------+
 # | Read and write LightWave Object File Format (*.lwo)     |
 # +---------------------------------------------------------+
 
+# ***** BEGIN GPL LICENSE BLOCK *****
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#
+# ***** END GPL LICENCE BLOCK *****
+
 import Blender, meshtools
 import struct, chunk, os, cStringIO, time, operator
 
index 8680890b0ced49a5bd3175b24b8b745d9ee7424c..da619fcffb0339bddcc0dba706aa2e35cd4e1dcd 100644 (file)
@@ -1,16 +1,19 @@
 #!BPY
 """
 Name: 'LightWave + Materials (.lwo)...'
-Blender: 237
+Blender: 239
 Group: 'Import'
 Tooltip: 'Import LightWave Object File Format (.lwo)'
 """
 
 __author__ = "Alessandro Pirovano, Anthony D'Agostino (Scorpius)"
 __url__ = ("blender", "elysiun",
-"Author's homepage, http://www.redrival.com/scorpius", "Author's homepage, http://uaraus.altervista.org")
+"Anthony's homepage, http://www.redrival.com/scorpius", "Alessandro's homepage, http://uaraus.altervista.org")
 
-importername = "lwo_import 0.1.16"
+importername = "lwo_import 0.2.2b"
+
+# $Id$
+#
 # +---------------------------------------------------------+
 # | Save your work before and after use.                    |
 # | Please report any useful comment to:                    |
@@ -22,7 +25,6 @@ importername = "lwo_import 0.1.16"
 # | http://www.redrival.com/scorpius                        |
 # | scorpius@netzero.com                                    |
 # | April 21, 2002                                          |
-# | Released under the Blender Artistic Licence (BAL)       |
 # | Import Export Suite v0.5                                |
 # +---------------------------------------------------------+
 # | Read and write LightWave Object File Format (*.lwo)     |
@@ -31,8 +33,36 @@ importername = "lwo_import 0.1.16"
 # | Alessandro Pirovano tweaked starting on March 2005      |
 # | http://uaraus.altervista.org                            |
 # +---------------------------------------------------------+
+# +----------------------------------------------------------
+# | GPL license block
+# |
+# | This program is free software; you can redistribute it and/or modify
+# | it under the terms of the GNU General Public License as published by
+# | the Free Software Foundation; either version 2 of the License, or
+# | (at your option) any later version.
+# |
+# | This program is distributed in the hope that it will be useful,
+# | but WITHOUT ANY WARRANTY; without even the implied warranty of
+# | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# | GNU General Public License for more details.
+# |
+# | You should have received a copy of the GNU General Public License
+# | along with this program; if not, write to the Free Software
+# | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+# +----------------------------------------------------------
 # +---------------------------------------------------------+
 # | Release log:                                            |
+# | 0.2.1 : This code works with Blender 2.40 RC1           |
+# |         modified material mode assignment to deal with  |
+# |         Python API modification                         |
+# |         Changed script license to GNU GPL               |
+# | 0.2.0:  This code works with Blender 2.40a2 or up       |
+# |         Major rewrite to deal with large meshes         |
+# |         - 2 pass file parsing                           |
+# |         - lower memory footprint                        |
+# |           (as long as python gc allows)                 |
+# |         2.40a2 - Removed subsurf settings patches=poly  |
+# |         2.40a2 - Edge generation instead of 2vert faces |
 # | 0.1.16: fixed (try 2) texture offset calculations       |
 # |         added hint on axis mapping                      |
 # |         added hint on texture blending mode             |
@@ -69,11 +99,26 @@ import struct, chunk, os, cStringIO, time, operator, copy
 # ===========================================================
 
 textname = "lwo_log"
+type_list = type(list())
+type_dict = type(dict())
 #uncomment the following line to disable logging facility
-#textname = None                      1
+#textname = None
 
 # ===========================================================
 
+
+# ===========================================================
+# === Make sure it is a string ... deal with strange chars ==
+# ===========================================================
+def safestring(st):
+    myst = ""
+    for ll in xrange(len(st)):
+        if st[ll] < " ":
+            myst += "#"
+        else:
+            myst += st[ll]
+    return myst
+
 class dotext:
 
     _NO = 0    #use internal to class only
@@ -87,7 +132,7 @@ class dotext:
             self.txtobj = None
             return
         tlist = Blender.Text.get()
-        for i in range(len(tlist)):
+        for i in xrange(len(tlist)):
             if (tlist[i].getName()==tname):
                 tlist[i].clear()
                 #print tname, " text object found and cleared!"
@@ -120,14 +165,14 @@ class dotext:
 
     def plist(self, pplist, where = _NO):
         self.pprint ("list:[")
-        for pp in range(len(pplist)):
+        for pp in xrange(len(pplist)):
             self.pprint ("[%d] -> %s" % (pp, pplist[pp]), where)
         self.pprint ("]")
     # end def plist
 
     def pdict(self, pdict, where = _NO):
         self.pprint ("dict:{", where)
-        for pp in pdict.keys():
+        for pp in pdict.iterkeys():
             self.pprint ("[%s] -> %s" % (pp, pdict[pp]), where)
         self.pprint ("}")
     # end def pdict
@@ -135,12 +180,12 @@ class dotext:
     def pprint(self, parg, where = _NO):
         if parg == None:
             self.pstring("_None_", where)
-        elif type(parg) == type ([]):
+        elif type(parg) == type_list:
             self.plist(parg, where)
-        elif type(parg) == type ({}):
+        elif type(parg) == type_dict:
             self.pdict(parg, where)
         else:
-            self.pstring(parg, where)
+            self.pstring(safestring(str(parg)), where)
     # end def pprint
 
     def logcon(self, parg):
@@ -152,6 +197,13 @@ tobj=dotext(textname)
 #uncomment the following line to log all messages on both console and logfile
 #tobj=dotext(textname,dotext.CON)
 
+def rlcopy(ll):
+    if type(ll) != type_list:
+        return ll
+    if ll == []:
+        return []
+    cpy = [rlcopy(ii) for ii in ll]
+    return cpy
 
 # ===========================================================
 # === Main read functions ===================================
@@ -172,7 +224,9 @@ def read(filename):
     start = time.clock()
     file = open(filename, "rb")
 
-    # === LWO header ===
+    editmode = Blender.Window.EditMode()    # are we in edit mode?  If so ...
+    if editmode: Blender.Window.EditMode(0) # leave edit mode before getting the mesh    # === LWO header ===
+
     form_id, form_size, form_type = struct.unpack(">4s1L4s",  file.read(12))
     if (form_type == "LWOB"):
         read_lwob(file, filename)
@@ -193,6 +247,8 @@ def read(filename):
     tobj.pprint ("#####################################################################")
     tobj.logcon (message)
     tobj.logcon ("#####################################################################")
+    if editmode: Blender.Window.EditMode(1)  # optional, just being nice
+
 
 # enddef read
 
@@ -234,6 +290,7 @@ def read_lwo2(file, filename, typ="LWO2"):
 
     dir_part = Blender.sys.dirname(filename)
     fname_part = Blender.sys.basename(filename)
+    ask_weird = 1
 
     #first initialization of data structures
     defaultname = os.path.splitext(fname_part)[0]
@@ -242,17 +299,63 @@ def read_lwo2(file, filename, typ="LWO2"):
     clip_list = []             #clip list: global for the whole file?
     object_index = 0
     object_list = None
+    objspec_list = None
     # init value is: object_list = [[None, {}, [], [], {}, {}, 0, {}, {}]]
     #0 - objname                    #original name
     #1 - obj_dict = {TAG}           #objects created
     #2 - verts = []                 #object vertexes
     #3 - faces = []                 #object faces (associations poly -> vertexes)
     #4 - obj_dim_dict = {TAG}       #tuples size and pos in local object coords - used for NON-UV mappings
-    #5 - polytag_dict = {TAG}       #tag to polygon mapping
+    #5 - polytag_dict = {TAG}       #tag to polygons mapping
     #6 - patch_flag                 #0 = surf; 1 = patch (subdivision surface) - it was the image list
-    #7 - uvcoords_dict = {name}     #uvmap coordinates (mixed mode per face/per vertex)
-    #8 - facesuv_dict = {name}      #uvmap coordinates associations poly -> uv tuples
+    #7 - uvcoords_dict = {name}     #uvmap coordinates (mixed mode per vertex/per face)
+    #8 - facesuv_dict = {name}      #vmad only coordinates associations poly & vertex -> uv tuples
+
+    #pass 1: look in advance for materials
+    tobj.logcon ("#####################################################################")
+    tobj.logcon ("Starting Pass 1: hold on tight")
+    tobj.logcon ("#####################################################################")
+    while 1:
+        try:
+            lwochunk = chunk.Chunk(file)
+        except EOFError:
+            break
+        tobj.pprint(" ")
+        if lwochunk.chunkname == "TAGS":                         # Tags
+            tobj.pprint("---- TAGS")
+            tag_list.extend(read_tags(lwochunk))
+        elif lwochunk.chunkname == "SURF":                         # surfaces
+            tobj.pprint("---- SURF")
+            surf_list.append(read_surfs(lwochunk, surf_list, tag_list))
+        elif lwochunk.chunkname == "CLIP":                         # texture images
+            tobj.pprint("---- CLIP")
+            clip_list.append(read_clip(lwochunk, dir_part))
+            tobj.pprint("read total %s clips up to now" % len(clip_list))
+        else:                                                       # Misc Chunks
+            if ask_weird:
+                ckname = safestring(lwochunk.chunkname)
+                if "#" in ckname:
+                    choice = Blender.Draw.PupMenu("WARNING: file could be corrupted.%t|Import anyway|Give up")
+                    if choice != 1:
+                        tobj.logcon("---- %s: Maybe file corrupted. Terminated by user" % lwochunk.chunkname)
+                        return
+                    ask_weird = 0
+            tobj.pprint("---- %s: skipping (maybe later)" % lwochunk.chunkname)
+            lwochunk.skip()
 
+    #add default material for orphaned faces, if any
+    surf_list.append({'NAME': "_Orphans", 'g_MAT': Blender.Material.New("_Orphans")})
+
+    #pass 2: effectively generate objects
+    tobj.logcon ("#####################################################################")
+    tobj.logcon ("Pass 2: now for the hard part")
+    tobj.logcon ("#####################################################################")
+    file.seek(0)
+    # === LWO header ===
+    form_id, form_size, form_type = struct.unpack(">4s1L4s",  file.read(12))
+    if (form_type != "LWO2"):
+        tobj.logcon ("??? Inconsistent file type: %s" %form_type)
+        return
     while 1:
         try:
             lwochunk = chunk.Chunk(file)
@@ -263,81 +366,69 @@ def read_lwo2(file, filename, typ="LWO2"):
             tobj.pprint("---- LAYR")
             objname = read_layr(lwochunk)
             tobj.pprint(objname)
-            if object_list == None:
-                object_list = [[objname, {}, [], [], {}, {}, 0, {}, {}]]
-            else:
-                object_list.append([objname, {}, [], [], {}, {}, 0, {}, {}])
-                object_index += 1
+            if objspec_list != None: #create the object
+                create_objects(clip_list, objspec_list, surf_list)
+                update_material(clip_list, objspec_list, surf_list) #give it all the object
+            objspec_list = [objname, {}, [], [], {}, {}, 0, {}, {}]
+            object_index += 1
         elif lwochunk.chunkname == "PNTS":                         # Verts
             tobj.pprint("---- PNTS")
             verts = read_verts(lwochunk)
-            object_list[object_index][2] = verts
+            objspec_list[2] = verts
         elif lwochunk.chunkname == "VMAP":                         # MAPS (UV)
             tobj.pprint("---- VMAP")
-            object_list[object_index][7], object_list[object_index][8] = read_vmap(object_list[object_index][7], object_list[object_index][8], object_list[object_index][3], len(object_list[object_index][2]), lwochunk)
+            #objspec_list[7] = read_vmap(objspec_list[7], len(objspec_list[2]), lwochunk)
+            read_vmap(objspec_list[7], len(objspec_list[2]), lwochunk)
         elif lwochunk.chunkname == "VMAD":                         # MAPS (UV) per-face
             tobj.pprint("---- VMAD")
-            object_list[object_index][7], object_list[object_index][8] = read_vmad(object_list[object_index][7], object_list[object_index][8], object_list[object_index][3], len(object_list[object_index][2]), lwochunk)
+            #objspec_list[7], objspec_list[8] = read_vmad(objspec_list[7], objspec_list[8], len(objspec_list[3]), len(objspec_list[2]), lwochunk)
+            read_vmad(objspec_list[7], objspec_list[8], len(objspec_list[3]), len(objspec_list[2]), lwochunk)
         elif lwochunk.chunkname == "POLS": # Faces v6.0
             tobj.pprint("-------- POLS(6)")
             faces, flag = read_faces_6(lwochunk)
             #flag is 0 for regular polygon, 1 for patches (= subsurf), 2 for anything else to be ignored
             if flag<2:
-                if object_list[object_index][3] != []:
-                    object_list.append([object_list[object_index][0],                  #update name
-                                        {},                                            #init
-                                        copy.deepcopy(object_list[object_index][2]),   #same vertexes
-                                        [],                                            #no faces
-                                        {},                                            #no need to copy - filled at runtime
-                                        {},                                            #polygon tagging will follow
-                                        flag,                                          #patch flag
-                                        copy.deepcopy(object_list[object_index][7]),   #same uvcoords
-                                        {}])                                           #no uv mapping
+                if objspec_list[3] != []:
+                    #create immediately the object
+                    create_objects(clip_list, objspec_list, surf_list)
+                    update_material(clip_list, objspec_list, surf_list) #give it all the object
+                    #update with new data
+                    objspec_list = [objspec_list[0],                  #update name
+                                    {},                               #init
+                                    objspec_list[2],                  #same vertexes
+                                    faces,                            #give it the new faces
+                                    {},                               #no need to copy - filled at runtime
+                                    {},                               #polygon tagging will follow
+                                    flag,                             #patch flag
+                                    objspec_list[7],                  #same uvcoords
+                                    {}]                               #no vmad mapping
                     object_index += 1
                 #end if already has a face list
-                #update uv coords mapping if VMAP already encountered
-                for uvname in object_list[object_index][7]:
-                    tobj.pprint("updating uv to face mapping for %s" % uvname)
-                    object_list[object_index][8][uvname] = copy.deepcopy(faces)
-                object_list[object_index][3] = faces
-                objname = object_list[object_index][0]
+                objspec_list[3] = faces
+                objname = objspec_list[0]
                 if objname == None:
                     objname = defaultname
             #end if processing a valid poly type
-        elif lwochunk.chunkname == "TAGS":                         # Tags
-            tobj.pprint("---- TAGS")
-            tag_list.extend(read_tags(lwochunk))
         elif lwochunk.chunkname == "PTAG":                         # PTags
             tobj.pprint("---- PTAG")
             polytag_dict = read_ptags(lwochunk, tag_list)
-            for kk in polytag_dict.keys(): object_list[object_index][5][kk] = polytag_dict[kk]
-        elif lwochunk.chunkname == "SURF":                         # surfaces
-            tobj.pprint("---- SURF")
-            surf_list.append(read_surfs(lwochunk, surf_list, tag_list))
-        elif lwochunk.chunkname == "CLIP":                         # texture images
-            tobj.pprint("---- CLIP")
-            clip_list.append(read_clip(lwochunk))
-            tobj.pprint("read total %s clips" % len(clip_list))
+            for kk, ii in polytag_dict.iteritems(): objspec_list[5][kk] = ii
         else:                                                       # Misc Chunks
-            tobj.pprint("---- %s: skipping" % lwochunk.chunkname)
+            tobj.pprint("---- %s: skipping (definitely!)" % lwochunk.chunkname)
             lwochunk.skip()
         #uncomment here to log data structure as it is built
         #tobj.pprint(object_list)
+    #last object read
+    create_objects(clip_list, objspec_list, surf_list)
+    update_material(clip_list, objspec_list, surf_list) #give it all the object
+    objspec_list = None
+    surf_list = None
+    clip_list = None
+
 
     tobj.pprint ("\n#####################################################################")
-    tobj.pprint("Found %d objects:" % len(object_list))
+    tobj.pprint("Found %d objects:" % object_index)
     tobj.pprint ("#####################################################################")
-    for objspec_list in object_list:
-        tobj.pprint ("\n#===================================================================#")
-        tobj.pprint("Processing Object: %s" % objspec_list[0])
-        tobj.pprint ("#===================================================================#")
-        objspec_list[3], objspec_list[5], objspec_list[8] = recalc_faces(objspec_list[2], objspec_list[3], objspec_list[5], objspec_list[8]) #recalculate faces, polytag_dict and uv_mapping get rid of faces fanning
-
-        create_objects(objspec_list)
-
-        if surf_list != []:
-            create_material(clip_list, surf_list, objspec_list, dir_part) #give it all the object
-    return
 # enddef read_lwo2
 
 
@@ -358,8 +449,8 @@ def read_verts(lwochunk):
     numverts = lwochunk.chunksize/12
     #$verts = []
     verts = [None] * numverts
-    for i in range(numverts):
-        if not i%100 and my_meshtools.show_progress:
+    for i in xrange(numverts):
+        if not i%1000 and my_meshtools.show_progress:
             Blender.Window.DrawProgressBar(float(i)/numverts, "Reading Verts")
         x, y, z = struct.unpack(">fff", data.read(12))
         verts[i] = (x, z, y)
@@ -406,13 +497,18 @@ def read_faces_5(lwochunk):
     faces = []
     i = 0
     while i < lwochunk.chunksize:
-        if not i%100 and my_meshtools.show_progress:
+        if not i%1000 and my_meshtools.show_progress:
            Blender.Window.DrawProgressBar(float(i)/lwochunk.chunksize, "Reading Faces")
+
+        '''
         facev = []
         numfaceverts, = struct.unpack(">H", data.read(2))
-        for j in range(numfaceverts):
+        for j in xrange(numfaceverts):
             index, = struct.unpack(">H", data.read(2))
             facev.append(index)
+        '''
+        numfaceverts, = struct.unpack(">H", data.read(2))
+        facev = [struct.unpack(">H", data.read(2))[0] for j in xrange(numfaceverts)]
         facev.reverse()
         faces.append(facev)
         surfaceindex, = struct.unpack(">H", data.read(2))
@@ -442,46 +538,42 @@ def read_vx(data):
 # ======================
 # === Read uvmapping ===
 # ======================
-def read_vmap(uvcoords_dict, facesuv_dict, faces, maxvertnum, lwochunk):
+def read_vmap(uvcoords_dict, maxvertnum, lwochunk):
     if maxvertnum == 0:
         tobj.pprint ("Found VMAP but no vertexes to map!")
-        return uvcoords_dict, facesuv_dict
+        return uvcoords_dict
     data = cStringIO.StringIO(lwochunk.read())
     map_type = data.read(4)
     if map_type != "TXUV":
         tobj.pprint ("Reading VMAP: No Texture UV map Were Found. Map Type: %s" % map_type)
-        return uvcoords_dict, facesuv_dict
+        return uvcoords_dict
     dimension, = struct.unpack(">H", data.read(2))
     name, i = read_name(data) #i initialized with string lenght + zeros
     tobj.pprint ("TXUV %d %s" % (dimension, name))
-    #my_uv_list = [None] * maxvertnum
-    my_uv_list = [(0.0, 0.0)] * maxvertnum         #more safe to have some default coordinates to associate in any case?
-    while (i < lwochunk.chunksize - 6):            #4+2 header bytes already read
+    #note if there is already a VMAD it will be lost
+    #it is assumed that VMAD will follow the corresponding VMAP
+    try: #if uvcoords_dict.has_key(name):
+        my_uv_dict = uvcoords_dict[name]          #update existing
+    except: #else:
+        my_uv_dict = {}    #start a brand new: this could be made more smart
+    while (i < lwochunk.chunksize - 6):      #4+2 header bytes already read
         vertnum, vnum_size = read_vx(data)
         u, v = struct.unpack(">ff", data.read(8))
         if vertnum >= maxvertnum:
             tobj.pprint ("Hem: more uvmap than vertexes? ignoring uv data for vertex %d" % vertnum)
         else:
-            my_uv_list[vertnum] = (u, v)
+            my_uv_dict[vertnum] = (u, v)
         i += 8 + vnum_size
     #end loop on uv pairs
-    uvcoords_dict[name] = my_uv_list
+    uvcoords_dict[name] = my_uv_dict
     #this is a per-vertex mapping AND the uv tuple is vertex-ordered, so faces_uv is the same as faces
-    if faces == []:
-        tobj.pprint ("no faces read yet! delaying uv to face assignments")
-        facesuv_dict[name] = []
-    else:
-        #deepcopy so we could modify it without actually modify faces
-        tobj.pprint ("faces already present: proceeding with assignments")
-        facesuv_dict[name] = copy.deepcopy(faces)
-    return uvcoords_dict, facesuv_dict
-
+    #return uvcoords_dict
+    return
 
 # ========================
 # === Read uvmapping 2 ===
 # ========================
-def read_vmad(uvcoords_dict, facesuv_dict, faces, maxvertnum, lwochunk):
-    maxfacenum = len(faces)
+def read_vmad(uvcoords_dict, facesuv_dict, maxfacenum, maxvertnum, lwochunk):
     if maxvertnum == 0 or maxfacenum == 0:
         tobj.pprint ("Found VMAD but no vertexes to map!")
         return uvcoords_dict, facesuv_dict
@@ -493,14 +585,13 @@ def read_vmad(uvcoords_dict, facesuv_dict, faces, maxvertnum, lwochunk):
     dimension, = struct.unpack(">H", data.read(2))
     name, i = read_name(data) #i initialized with string lenght + zeros
     tobj.pprint ("TXUV %d %s" % (dimension, name))
-    if uvcoords_dict.has_key(name):
-        my_uv_list = uvcoords_dict[name]          #update existing
-        my_facesuv_list = facesuv_dict[name]
-    else:
-        my_uv_list = [(0.0, 0.0)] * maxvertnum    #start a brand new: this could be made more smart
-        my_facesuv_list = copy.deepcopy(faces)
+    try: #if uvcoords_dict.has_key(name):
+        my_uv_dict = uvcoords_dict[name]          #update existing
+    except: #else:
+        my_uv_dict = {}    #start a brand new: this could be made more smart
+    my_facesuv_list = []
+    newindex = maxvertnum + 10 #why +10? Why not?
     #end variable initialization
-    lastindex = len(my_uv_list) - 1
     while (i < lwochunk.chunksize - 6):  #4+2 header bytes already read
         vertnum, vnum_size = read_vx(data)
         i += vnum_size
@@ -510,18 +601,15 @@ def read_vmad(uvcoords_dict, facesuv_dict, faces, maxvertnum, lwochunk):
         if polynum >= maxfacenum or vertnum >= maxvertnum:
             tobj.pprint ("Hem: more uvmap than vertexes? ignorig uv data for vertex %d" % vertnum)
         else:
-            my_uv_list.append( (u,v) )
-            newindex = len(my_uv_list) - 1
-            for vi in range(len(my_facesuv_list[polynum])): #polynum starting from 1 or from 0?
-                if my_facesuv_list[polynum][vi] == vertnum:
-                    my_facesuv_list[polynum][vi] = newindex
-            #end loop on current face vertexes
+            my_uv_dict[newindex] = (u, v)
+            my_facesuv_list.append([polynum, vertnum, newindex])
+            newindex += 1
         i += 8
     #end loop on uv pairs
-    uvcoords_dict[name] = my_uv_list
+    uvcoords_dict[name] = my_uv_dict
     facesuv_dict[name] = my_facesuv_list
-    tobj.pprint ("updated %d vertexes data" % (newindex-lastindex))
-    return uvcoords_dict, facesuv_dict
+    tobj.pprint ("updated %d vertexes data" % (newindex-maxvertnum-10))
+    return
 
 
 # =================
@@ -558,7 +646,7 @@ def read_ptags(lwochunk, tag_list):
     ptag_dict = {}
     i = 0
     while(i < lwochunk.chunksize-4): #4 bytes polygon type already read
-        if not i%100 and my_meshtools.show_progress:
+        if not i%1000 and my_meshtools.show_progress:
            Blender.Window.DrawProgressBar(float(i)/lwochunk.chunksize, "Reading PTAGS")
         poln, poln_size = read_vx(data)
         i += poln_size
@@ -568,11 +656,12 @@ def read_ptags(lwochunk, tag_list):
             return {}
         i += 2
         tag_key = tag_list[tag_index]
-        if not(ptag_dict.has_key(tag_key)):
-            ptag_dict[tag_list[tag_index]] = [poln]
-        else:
+        try: #if ptag_dict.has_key(tag_key):
             ptag_dict[tag_list[tag_index]].append(poln)
-    for i in ptag_dict.keys():
+        except: #else:
+            ptag_dict[tag_list[tag_index]] = [poln]
+            
+    for i in ptag_dict.iterkeys():
         tobj.pprint ("read %d polygons belonging to TAG %s" % (len(ptag_dict[i]), i))
     return ptag_dict
 
@@ -581,7 +670,9 @@ def read_ptags(lwochunk, tag_list):
 # ==================
 # === Read Clips ===
 # ==================
-def read_clip(lwochunk):
+def read_clip(lwochunk, dir_part):
+# img, IMG, g_IMG refers to blender image objects
+# ima, IMAG, g_IMAG refers to clip dictionary 'ID' entries: refer to blok and surf
     clip_dict = {}
     data = cStringIO.StringIO(lwochunk.read())
     image_index, = struct.unpack(">L", data.read(4))
@@ -616,11 +707,30 @@ def read_clip(lwochunk):
             n, = struct.unpack(">H", data.read(2))
             clip_dict['NEGA'] = n
         else:                                                       # Misc Chunks
-            tobj.pprint("-------- SURF:%s: skipping" % subchunkname)
+            tobj.pprint("-------- CLIP:%s: skipping" % subchunkname)
             discard = data.read(subchunklen)
         i = i + 6 + subchunklen
     #end loop on surf chunks
     tobj.pprint("read image:%s" % clip_dict)
+    if clip_dict.has_key('XREF'):
+        tobj.pprint("Cross-reference: no image pre-allocated.")
+        return clip_dict
+    #look for images
+    img = load_image("",clip_dict['NAME'])
+    if img == None:
+        tobj.pprint (  "***No image %s found: trying LWO file subdir" % clip_dict['NAME'])
+        img = load_image(dir_part,clip_dict['BASENAME'])
+    if img == None:
+        tobj.pprint (  "***No image %s found in directory %s: trying Images subdir" % (clip_dict['BASENAME'], dir_part))
+        img = load_image(dir_part+Blender.sys.sep+"Images",clip_dict['BASENAME'])
+    if img == None:
+        tobj.pprint (  "***No image %s found: trying alternate Images subdir" % clip_dict['BASENAME'])
+        img = load_image(dir_part+Blender.sys.sep+".."+Blender.sys.sep+"Images",clip_dict['BASENAME'])
+    if img == None:
+        tobj.pprint (  "***No image %s found: giving up" % clip_dict['BASENAME'])
+    #lucky we are: we have an image
+    tobj.pprint ("Image pre-allocated.")
+    clip_dict['g_IMG'] = img
     return clip_dict
 
 
@@ -644,7 +754,7 @@ def read_surfblok(subchunkdata):
     tobj.pprint ("---------- IMAP")
     ordinal, i = read_name(data)
     my_dict['ORD'] = ordinal
-    my_dict['g_ORD'] = -1
+    #my_dict['g_ORD'] = -1
     my_dict['ENAB'] = True
     while(i < subchunklen): # ---------left 6------------------------- loop on header parameters
         sub2chunkname, = struct.unpack("4s", data.read(4))
@@ -880,27 +990,32 @@ def read_surfs(lwochunk, surf_list, tag_list):
             rr, uvname = read_surfblok(data.read(subchunklen))
             #paranoia setting: preventing adding an empty dict
             if rr != {}:
-                if not(my_dict.has_key('BLOK')):
-                    my_dict['BLOK'] = [rr]
-                else:
+                try:
                     my_dict['BLOK'].append(rr)
+                except:
+                    my_dict['BLOK'] = [rr]
+
             if uvname != "":
                 my_dict['UVNAME'] = uvname                            #theoretically there could be a number of them: only one used per surf
+            if not(my_dict.has_key('g_IMAG')) and (rr.has_key('CHAN')) and (rr.has_key('OPAC')) and (rr.has_key('IMAG')):
+                if (rr['CHAN'] == 'COLR') and (rr['OPAC'] == 0):
+                    my_dict['g_IMAG'] = rr['IMAG']                 #do not set anything, just save image object for later assignment
             subchunklen = 0 #force ending
         else:                                                       # Misc Chunks
             tobj.pprint("-------- SURF:%s: skipping" % subchunkname)
         if  subchunklen > 0:
             discard = data.read(subchunklen)
     #end loop on surf chunks
-    if my_dict.has_key('BLOK'):
-       my_dict['BLOK'].reverse()
+    try: #if my_dict.has_key('BLOK'):
+       my_dict['BLOK'].reverse() #texture applied in reverse order with respect to reading from lwo
+    except:
+       pass
+    #uncomment this if material pre-allocated by read_surf
+    my_dict['g_MAT'] = Blender.Material.New(my_dict['NAME'])
+    tobj.pprint("-> Material pre-allocated.")
     return my_dict
 
 
-
-
-
-
 # ===========================================================
 # === Generation Routines ===================================
 # ===========================================================
@@ -922,7 +1037,7 @@ def find_ear(normal, list_dict, verts, face):
     mla = 1
     mlb = 2
 
-    for c in range(nv):
+    for c in xrange(nv):
         a = (c+1) % nv; b = (a+1) % nv
 
         if list_dict['P'][a] > 0.0: #we have to start from a convex vertex
@@ -934,7 +1049,7 @@ def find_ear(normal, list_dict, verts, face):
             #tobj.pprint ("   ok, this one passed")
             concave = 0
             concave_inside = 0
-            for xx in range(nv): #looking for concave vertex
+            for xx in xrange(nv): #looking for concave vertex
                 if (list_dict['P'][xx] <= 0.0) and (xx != b) and (xx != c): #cannot be a: it's convex
                     #ok, found concave vertex
                     concave = 1
@@ -1009,12 +1124,12 @@ def reduce_face(verts, face):
         vi = face[mvi]
         list_dict['D'][mvi] = dist_vector(verts[vi_hiend], verts[vi])
     #list of cross products - normals evaluated into vertexes
-    for vi in range(nv):
+    for vi in xrange(nv):
         list_dict['X'][vi] = Blender.Mathutils.CrossVecs(list_dict['D'][vi], list_dict['D'][vi-1])
     my_face_normal = Blender.Mathutils.Vector([list_dict['X'][0][0], list_dict['X'][0][1], list_dict['X'][0][2]])
     #list of dot products
     list_dict['P'][0] = 1.0
-    for vi in range(1, nv):
+    for vi in xrange(1, nv):
         list_dict['P'][vi] = Blender.Mathutils.DotVecs(my_face_normal, list_dict['X'][vi])
     #is there at least one concave vertex?
     #one_concave = reduce(lambda x, y: (x) or (y<=0.0), list_dict['P'], 0)
@@ -1064,63 +1179,37 @@ def reduce_face(verts, face):
 # =========================
 # === Recalculate Faces ===
 # =========================
-# --------- this do the standard face + ptag_dict + uv-map recalc
-def recalc_faces(verts, faces, polytag_dict, facesuv_dict):
-    # init local face list
-    my_faces = []
-    # init local uvface dict
-    my_facesuv = {}
-    for uvname in facesuv_dict:
-        my_facesuv[uvname] = []
-    replaced_faces_dict = {}
-    j = 0
-    if len(faces)==0:
-        return faces, polytag_dict, facesuv_dict
-    for i in range(len(faces)):
-        # i = index that spans on original faces
-        # j = index that spans on new faces
-        if not i%100 and my_meshtools.show_progress: Blender.Window.DrawProgressBar(float(i)/len(faces), "Recalculating faces")
-        numfaceverts=len(faces[i])
-        if numfaceverts < 4:                #This face is a triangle or quad: more strict - it has to be a triangle
-            my_faces.append(faces[i])       #ok, leave it alone ....
-            for uvname in facesuv_dict:
-                my_facesuv[uvname].append(facesuv_dict[uvname][i])
-            replaced_faces_dict[i] = [j]     #.... but change the nuber order of the face
-            j += 1
-        else:                                                # Reduce n-sided convex polygon.
-            meta_faces = reduce_face(verts, faces[i])   # Indices of triangles.
-            this_faces = []                                  # list of triangles poly replacing original face
-            this_faces_index = []
-            for mf in meta_faces:
-                ll = len(mf)
-                if ll == 3: #triangle
-                    this_faces.append([faces[i][mf[0]], faces[i][mf[1]], faces[i][mf[2]]])
-                else:        #quads
-                    this_faces.append([faces[i][mf[0]], faces[i][mf[1]], faces[i][mf[2]], faces[i][mf[3]]])
-                for uvname in facesuv_dict:
-                    if ll == 3:  #triangle
-                        my_facesuv[uvname].append([facesuv_dict[uvname][i][mf[0]], facesuv_dict[uvname][i][mf[1]], facesuv_dict[uvname][i][mf[2]]])
-                    else:        #quads
-                        my_facesuv[uvname].append([facesuv_dict[uvname][i][mf[0]], facesuv_dict[uvname][i][mf[1]], facesuv_dict[uvname][i][mf[2]], facesuv_dict[uvname][i][mf[3]]])
-                this_faces_index.append(j)
-                j +=1
-            my_faces.extend(this_faces)
-            replaced_faces_dict[i] = this_faces_index   #face i substituted by this list of faces
-        #endif on face vertex number
-    #end loop on every face
-    #now we have the new faces list and a dictionary replacement.
-    #going for polygon tagging
-    my_ptag_dict = {}
-    for tag in polytag_dict:                                      #for every tag group
-        my_ptag_dict[tag] = []                                    #rebuild a new entry
-        for poly in polytag_dict[tag]:                            #take every element of old face list
-            my_ptag_dict[tag].extend(replaced_faces_dict[poly])   #substitutes the element of new face list
-    return my_faces, my_ptag_dict, my_facesuv
-
 
-# ========================================
-# === Revert list keeping first vertex ===
-# ========================================
+def get_uvface(complete_list, facenum):
+    # extract from the complete list only vertexes of the desired polygon
+    my_facelist = []
+    for elem in complete_list:
+        if elem[0] == facenum:
+            my_facelist.append(elem)
+    return my_facelist
+
+def get_newindex(polygon_list, vertnum):
+    # extract from the polygon list the new index associated to a vertex
+    if polygon_list == []:
+        return -1
+    for elem in polygon_list:
+        if elem[1] == vertnum:
+            return elem[2]
+    #tobj.pprint("WARNING: expected vertex %s for polygon %s. Polygon_list dump follows" % (vertnum, polygon_list[0][0]))
+    #tobj.pprint(polygon_list)
+    return -1
+
+def get_surf(surf_list, cur_tag):
+    for elem in surf_list:
+        if elem['NAME'] == cur_tag:
+            return elem
+    return {}
+
+
+
+# ==========================================
+# === Revert list (keeping first vertex) ===
+# ==========================================
 def revert (llist):
     #different flavors: the reverse one is the one that works better
     #rhead = [llist[0]]
@@ -1128,59 +1217,202 @@ def revert (llist):
     #rhead.extend(rtail)
     #return rhead
     #--------------
-    rhead=copy.deepcopy(llist)
+    rhead=rlcopy(llist)
     rhead.reverse()
     return rhead
     #--------------
     #return llist
 
+
 # ====================================
 # === Modified Create Blender Mesh ===
 # ====================================
-def my_create_mesh(complete_vertlist, complete_facelist, current_facelist, objname, not_used_faces):
+def my_create_mesh(clip_list, surf, objspec_list, current_facelist, objname, not_used_faces):
     #take the needed faces and update the not-used face list
-    vertex_map = [-1] * len(complete_vertlist)
+    complete_vertlist = objspec_list[2]
+    complete_facelist = objspec_list[3]
+    uvcoords_dict = objspec_list[7]
+    facesuv_dict = objspec_list[8]
+    vertex_map = {} #implementation as dict
     cur_ptag_faces = []
+    cur_ptag_faces_indexes = []
+    maxface = len(complete_facelist)
     for ff in current_facelist:
+        if ff >= maxface:
+            tobj.logcon("Non existent face addressed: Giving up with this object")
+            return None, not_used_faces              #return the created object
         cur_face = complete_facelist[ff]
-        cur_ptag_faces.append(cur_face)
+        cur_ptag_faces_indexes.append(ff)
         if not_used_faces != []: not_used_faces[ff] = -1
-        for vv in cur_face:
-            vertex_map[vv] = 1
-        #end loop on vertex on this face
+        for vv in cur_face: vertex_map[vv] = 1
     #end loop on faces
+    store_edge = 0
+
+    msh = Blender.NMesh.GetRaw()
+    # Name the Object
+    if not my_meshtools.overwrite_mesh_name:
+        objname = my_meshtools.versioned_name(objname)
+    Blender.NMesh.PutRaw(msh, objname)    # Name the Mesh
+    obj = Blender.Object.GetSelected()[0]
+    obj.name=objname
+    # Associate material and mesh properties => from create materials
+    msh = obj.getData()
+    mat_index = len(msh.getMaterials(1))
+    mat = None
+    if surf.has_key('g_MAT'):
+        mat = surf['g_MAT']
+        msh.addMaterial(mat)
+    msh.mode |= Blender.NMesh.Modes.AUTOSMOOTH #smooth it anyway
+    if surf.has_key('SMAN'):
+        #not allowed mixed mode mesh (all the mesh is smoothed and all with the same angle)
+        #only one smoothing angle will be active! => take the max one
+        s = int(surf['SMAN']/3.1415926535897932384626433832795*180.0)     #lwo in radians - blender in degrees
+        if msh.getMaxSmoothAngle() < s: msh.setMaxSmoothAngle(s)
+
+    img = None