#!BPY

""" Registration info for Blender menus: <- these words are ignored
Name: 'Tesselate'
Blender: 232
Group: 'Misc'
Tip: 'Make a wire shape from a faceted shape. Do complex extrusions too .'
"""

#----------------------------------------------
# wire and tesselate project
# jean-michel soler january/october  2000
#                     -> october 2004 
#----------------------------------------------
# Official page :
#   http://jmsoler.free.fr/didacticiel/blender/tutor/python_wireshadows.htm
# Communicate problems or errors on:
#   http://www.zoo-logique.org/3D.Blender/newsportal/thread.php?group=3D.Blender
#---------------------------------------------
#---------------------------------------------
#  changelog : 
#
#           - v 8.8.f :  (1) improvement : split mesh keeps materials and uv
#
#           - v 8.8.i :  (1) improvement : can work on mesh material and armature.
#                        (2) add : multiple undo/redo ,in fact all modifications
#                        (3) improvement : save file with data in the directory of the current blend file
#                        (4) second random option for xy deplacement
#
#           - v 8.8.j :  (1) works in "faked" editmode 
#                        
#---------------------------------------------

import Blender
from Blender import Object
from Blender.Object import *
from Blender import NMesh 
from Blender.NMesh import *
from Blender.Draw import *
from Blender.BGL import *
from Blender.Noise import random

## --------------------------------
## change to your tessel directory
##
## Changer la ligne suivant pour indiquer le repertoire 
## de sauvegarde des parametres
##---------------------------------

dirpath=Blender.sys.dirname(Blender.Get('filename'))
print dirpath.replace('\\','/')+'/'
Tessel_Path=dirpath.replace('\\','/')+'/'
annulation=[]
dopos=-1

SPLITTOTALFACE=4
DIGGER=8
ENVELOPPE=6
CHANFREIN=10

g=random
n_=random

import math
from math import cos, sin, pi, sqrt, acos, asin, atan

fr=    { 'Lang':'Eng',
         'EpXY':"Epaisseur XY : ",
         'EpXY_doc':"Etablit l'epaisseur a partir du bord de la face",
         'EpZ':"Epaisseur Z",
         'EpZ_doc':"indique s'il faut calculer l'epaisseur a partir de la face" ,
         'NgZ':"Neg Z",
         'NgZ_doc':"inverse la direction de la normale",
         'FintTG':"FaceinterneTG",
         'FintTG_doc':"Ajoute une face interne",
         'EpQZ':"Epais Z : ",
         'EpQZ_doc':"Etablit l'epaisseur a partir de la surface de la face dans le sens de la normale",
         'FrgT':"Fragmentation totale, ou par faces selectionnees  ",
         'FrgT_doc':"Effectue l'equivalent de split sur tout le mesh",
         'T1':"Fragmention : explose l'objet courant",
         'T2':"sans effectuer les autres operations.",
         'Act':"Action",
         'iteration':"boucle sur cette valeur. Reset to non at the end of ",
         
         'random_doc':"renvoie une valeur d'epaisseur au hasard entre 0.0 et epaisseur Z" ,
         'random':"Hasard Z" ,
         
         'randomxy_doc':"renvoie une valeur d'epaisseur au hasard entre 0.0 et epaisseur XY" ,
         'randomxy':"R1" ,

         'randomxy2_doc':"renvoie une position au hasard dans le plan de la facette pour chaque nouveau sommet" ,
         'randomxy2':"R2" ,
         
         'random_docneg':"Renvoie la normale en Z soit en positif soit en negatif" ,
         'randomneg':"RandN",
         
         'Select_doc':"Realise les operations uniquement sur les faces selectionnees." ,
         'Select':"Select Faces",
         'UseMatrice_doc':"active l'affichage des options de matrice d'extrusion.",
         'UseMatrice':"Matrice",
         'division':"Division  en :",
         'division_doc':" Division  de l\'axe d\'extrusion en tant de parties",
         
         'recvar':"V",
         'recvar_doc':"Bascule sur une liste manuelle.",

         'MaxRot':"MRot:",
         'MaxRot_doc':"Maximum de rotation possible",
         
         'MaxDec':'MDec',
         'MaxDec_doc':'Limite maximale de decalage en...',
         
           'Sx':"Decalage en x :",
           'Sx_doc':"Decalage en x",
           'Sy':"Decalage en y :",
           'Sy_doc':"Decalage en y",
           'Sz':"Decalage en z :",
           'Sz_doc':"Decalage en z",
         
           'Rx':"Rotation axe x :",
           'Rx_doc':"Rotation axe x",
           'Ry':"Rotation axe y :",
           'Ry_doc':"Rotation axe y",
           'Rz':"Rotation axe z :",
           'Rz_doc':"Rotation axe z",
         
           'Rnz':"Rotation normal z :",
           'Rnz_doc':"Rotation normal z",
           'Rnx':"Rotation normal x :",
           'Rnx_doc':"Rotation normal x",
           'Rny':"Rotation normal y :",
           'Rny_doc':"Rotation normal y",
         
         'Segment_doc':"l\'extrusion apparaitr segmentee" ,
         'Segment':"Segments",
         
         'SaveOrig_doc':"Sauve le mesh original" ,
         'SaveOrig':"Sauve Original",
         
         'Extrude_doc':"Extrude en suivant l\'axe Z de la faceface, or up axis of the normal",
         'Extrude':"Options d\'extrusion sur l'axe Z (up)",
         
         'Extrude_off':"Off",
         
         'V':"Vert",
         'V_doc':"Allignement Vertical des Boutons",
         
         'H':"Horiz",
         'H_doc':"Allignement Horizontal des Boutons",
         
         'rotLocal':"Face",
         'rotLocal_doc':"rotation around Local face axe",
          
         'rotGlobal':"Objet",
         'rotGlobal_doc':"rotation around Local objet axe",
         
         'Chanfrein':"Chanfrein.",
         'Chanfrein_doc':"Calcul du Chanfrein sur l\'ensemble des aretes de l'objet...",
         
         'Digger':" Creux ",
         'Digger_doc':"creuse un sillon en suivant l\'ensemble des aretes de l'objet...",
         
         'NDigger':"N",
         'NDigger_doc':"inverse l\'effet du creux ",
         
         'PDigger':"P",
         'PDigger_doc':"Effet de creux proportionnel",
         
         'Envel':"Enveloppe",
         'Envel_doc':"Enveloppe les arêtes d\'un voile continu",
         
         'Record':"Enregistrer",
         
         'Save':"Sauve",
         'Load':"Charge",
         'SaveAs':"Sauve sous...",
         'SaveMesh':"Sauve le mesh",
         'LoadMenu':"Charge le menu ...",
         
         'Record_doc':"",  
         'Save_doc':"Sauve les parametres actuels",
         'Load_doc':"Charge les parametres a partir du fichier pointé par el menu",
         'SaveAs_doc':"Nom du fichier dans lequel seront enregistrés les parametres.",
         'SaveMesh_doc':"Nom du fichier dans lequel seront enregistrés les parametres.",
         'LoadMenu_doc':"Menu de selection ",
         'Undo_doc':"",
         'Undo':"Undo",
         'Redo_doc':"",
         'Redo':"Redo",

}
 
ang={   'Lang':'Fra',
         'EpXY':"XY Thickness : ",
         'EpXY_doc':"Set thickness from the Face border.",
         'EpZ':"Set Z Thickness",
         'EpZ_doc':"Set if script use or not the Z thickness.",
         'NgZ':"Neg Z",
         'NgZ_doc':"reverse normal direction",
         'FintTG':"Unset Intern Face",
         'FintTG_doc':"Add (or not) an internal face.",
         'EpQZ':"Z Thickness : ",
         'EpQZ_doc':"Set thickness from the the face in the normal direction.",
         'FrgT':"Set Total Fragmentation or by selected Faces",
         'FrgT_doc':"Eqivalent to split on all the mesh",
         'T1':"Split All Mesh",
         'T2':"without doing the others actions",
         'Act':"Make it",
         'iteration':"loop upon number. Reset to non at the end of ",
         
         'random_doc':"return a random Z tickness",
         'random':"random",
         
         'randomxy_doc':"return a random XY tickness between 0.0 and XY value" ,
         'randomxy':"R1" ,

         'randomxy2_doc':"return a random XY position for each vertex between original vertex position and center of the face" ,
         'randomxy2':"R2" ,
         
         'random_docneg':"return a random direction for normal" ,
         'randomneg':"RandN"  ,
         
         'Select_doc':"Works only on selected faces" ,
         'Select':"Select Faces",
         
           'UseMatrice_doc':" Display extrusion matrix options.",
           'UseMatrice':"Matrix",
           'division':"Div :",
           'division_doc':"",

           'recvar':"V",
           'recvar_doc':"",
        
           'MaxRot':"MRot:",
           'MaxRot_doc':" Maximum possible rotation",
           'MaxDec':'MDec',
           'MaxDec_doc':'Maximum for decalage Limit ...',
         
           'Sx':"Sx :",
           'Sx_doc':"Sx",
           'Sy':"Sy :",
           'Sy_doc':"Sy",
           'Sz':"Sz :",
           'Sz_doc':"Sz",
         
           'Rx':"Rx :",
           'Rx_doc':"Rx",
           'Ry':"Ry :",
           'Ry_doc':"Ry",
           'Rz':"Rz :",
           'Rz_doc':"Rz",
         
           'Rnz':"Rnz :",
           'Rnz_doc':"Rnz",
           'Rnx':"Rnx :",
           'Rnx_doc':"Rnx",
           'Rny':"Rny :",
           'Rny_doc':"Rny",
         
         
         'Segment_doc':"Appear segmented" ,
         'Segment':"Segments",
         
         'SaveOrig_doc':"Save the original mesh " ,
         'SaveOrig':"Save Original",
          
         'Extrude_doc':"Extrude along Z axis of the face, or up axis of the normal",
         'Extrude':"Options to extrude along up axis of each face",
         
         'Extrude_off':"Off",
         
         'V':"Vert",
         'V_doc':"Allignement Vertical des Boutons",
         
         'H':"Horiz",
         'H_doc':"Allignement Horizontal des Boutons",
         
         'rotLocal':"Face",
         'rotLocal_doc':"rotation around Local face axe",
         
         'rotGlobal':"Objet",
         'rotGlobal_doc':"rotation around Local objet axe",
         
         'Chanfrein':"Chanfrein.",
         'Chanfrein_doc':"Calcul du Chanfrein sur l\'ensemble des aretes de l'objet...",
         
         'Digger':"Digger.",
         'Digger_doc':"creuse un sillon en suivant l\'ensemble des aretes de l'objet...",
         
         'NDigger':"N",
         'NDigger_doc':"reverse digger effect ",
         
         'PDigger':"P",
         'PDigger_doc':"Proportionnal digger effect ",
        
         'Envel':"Enveloppe",
         'Envel_doc':"Enveloppe les arêtes d\'un voile continu",
        
         'Record':"Record",   
         'Save':"Save",
         'Load':"Load",
         'SaveAs':"SaveAs :",
         'SaveMesh':"",
         'LoadMenu':"",
        
         'Record_doc':"Recors",  
         'Save_doc':"Save the current parametres ",
         'Load_doc':"Load the parametres from teh pointed file in the menu",
         'SaveAs_doc':"Name of the record file .",
         'SaveMesh_doc':"",
         'LoadMenu_doc':"Selection menu",

         'Undo_doc':"",
         'Undo':"Undo",
         'Redo_doc':"",
         'Redo':"Redo",
        
   }
 
lg=[fr,ang]

liste_des_faces=[]
liste_des_facesbis=[]            
liste_des_sommets={}
liste_dordre_des_sommets={}          
liste_des_facescchanfrein=[]

liste_des_segments=[]
liste_des_faceseg=[]
liste_des_seglink=[]
liste_reverseg=[]

class boutons:
   global Tessel_Path
   def __init__(self):
      self.lang=Create(0)
      
      #epaisseur/largeur de la bande
      #laissee en bordure de la facette
      self.epaisseur=Create(0.95)
      self.RandomXY=Create(0)
      self.RandomXY2=Create(0)
      
      #extrude along normal
      self.Extrude=Create(0)
      
      #distance au plan de la face originale
      #modifie les coordonees des sommets qui
      #limitent la bande
      self.distance=Create(0.95)
      self.RandomDistance=Create(0)
      
      #bouton toggle/booleen pour l'option 
      #"distance"
      self.DistanceTG=Create(0)
      self.maxdistance=Create(2.0)
     
      #bouton toggle/booleen pour l'option 
      #d'inversion de la distance, en standard
      #orientee vers l'exterieur de la facette
      self.DistNegTG=Create(0)
      self.RandomNeg=Create(0)
     
      #bouton toggle/booleen pour l'option 
      #de conservation de la face interne
      self.FaceinterneTG=Create(0)
     
      #bouton toggle/booleen pour l'option 
      #d'eclatement du reseau de facette
      #en facette separee
      self.SplitTotalTG=Create(0)
     
      #bouton toggle/booleen pour l'option 
      #de sauvegarde de l'objet de départ
      self.SaveOriginal=Create(0)
     
      #bouton toggle/booleen pour l'option 
      self.SelectedFacesTG=Create(0)
      self.ReSelectedFacesTG=Create(0)
      self.Chanfrein=Create(0)
     
      self.Digger=Create(0)
      self.NDigger=Create(-1.0)
      self.PDigger=Create(1)
     
      self.Enveloppe=Create(0)
     
     
      #bouton pour le niveau d'iteration
      self.Iteration=Create(1)
     
      #matrice de transformation
      self.matrix={}
     
      self.matrix['use_matrice']=Create(0)
      self.matrix['recursion']=Create(1)
      self.matrix['recvar']=Create(1)
      
      self.matrix['limrec']=Create(10)
      self.matrix['segment']=Create(0)
      self.matrix['maxdec']=Create(0.0)
      self.matrix['maxrot']=Create(180.0)      
      self.matrix['rotGlobal']=Create(0)
     
      self.matrix['Sx']=Create(0.0)
      self.matrix['Sy']=Create(0.0)
      self.matrix['Sz']=Create(0.0)
     
      self.matrix['Rx']=Create(0.0)
      self.matrix['Ry']=Create(0.0)
      self.matrix['Rz']=Create(0.0)
     
      self.matrix['Rnz']=Create(0.0)
      self.matrix['Rnx']=Create(0.0)
      self.matrix['Rny']=Create(0.0)
     
      self.B_allign=Create(0)
     
      self.Record={}
      self.Record['Record']=Create(0)
      self.Record['Save']=Create(0)
      self.Record['Load']=Create(0)
      self.Record['SaveAs']=Create('tessel.tess')
      self.Record['LoadMenu']=Create(0)
      
      self.Record['listeMenu']=''
      
      self.path=Tessel_Path
      self.boutonslist=[]
      
   def prf_dump(self):
         
        n0=dir(self)
        f=open(self.path+self.Record['SaveAs'].val,'w')
        for n in n0:
           #print n0,
           if  (n.find('__')!=0 and n.find('prf_dump')==-1 and n.find('prf_load')==-1 and n.find('prf_save')==-1 and n.find('path')==-1) and n.find('Record')==-1:
               exec """l1=str(type(self.%s))"""%n
               l0=n+';'+l1+'\n'
               f.write(l0)
               exec """f.write(str(self.%s))"""%n
               f.write('\n')
               
        f.close()
         
   def prf_load(self):
      try:
        f=open(self.path+self.Record['SaveAs'].val,'r')
        buffer=f.readlines()
        f.close()
        
        for n in range(0,len(buffer),2):
            var=buffer[n].split(';')
            if var[0] not in self.boutonslist:
               self.boutonslist.append(var[0])
            if buffer[n].find("""<type 'str""")!=-1:
               exec """self.%s='''%s'''"""%(var[0],buffer[n+1][:-1])               
            elif buffer[n].find("""<type 'dict'>""")!=-1:
              exec """provdict=%s"""%buffer[n+1][:-1]
              for d in provdict.keys():
                 l00="""self.%s['%s'].val=%s"""%(var[0],d,provdict[d])
                 exec l00
            elif buffer[n].find("""<type 'Button'>""")!=-1:
                 exec """self.%s.val=%s"""%(var[0],buffer[n+1][:-1])
      except:
          print "no such file."
          
B=boutons()

#accumulateur pour calculer le centre
#du reseau de facette
accu1=[0.0,0.0,0.0]

#accumulateur pour calculer le centre
#la facette
accu2=[0.0,0.0,0.0]

#table pour la position courante de la derniere
#facette et du dernier point dans leur liste 
#respective
dern_long=[0,0]

n=[0.0,0.0,0.0]
n_0=0.0

n0=0
p0=0

a=0
b=0
c=0
d=0

locZ=[0.0,0.0,0.0]
uv=[(0.0,0.0), (1.0,0.0), (1.0,1.0), (0.0,1.0)]

#coefficients du plan
def  EquationPlan (v1,v2,v3):
    #global a,b,c,d
    X1 =v1.co[0] 
    Y1 =v1.co[1]
    Z1 =v1.co[2]
    X2 =v2.co[0]
    Y2 =v2.co[1] 
    Z2 =v2.co[2] 
    X3 =v3.co[0] 
    Y3 =v3.co[1]
    Z3 =v3.co[2] 
    a  = Y1 * (Z2 - Z3) + Y2 * (Z3 - Z1) + Y3 * (Z1 - Z2)
    b  = -X1 * (Z2 - Z3) + X2 * (Z1 - Z3) - X3 * (Z1 - Z2)
    c  = X1 * (Y2 - Y3) - X2 * (Y1 - Y3) + X3 * (Y1 - Y2)
    #d  = -X1*(Y2*Z3-Y3*Z2)+X2*(Y1*Z3-Y3*Z1)-X3*(Y1*Z2-Y2*Z1)
    norm=(a**2+b**2+c**2)**0.5
    #print norm    
    if norm !=0.0:
       return a/norm,b/norm,c/norm
    else:
       return a,b,c
    ##return a,b,c

		
def doc_segments(me):
        """
        doc_segments :
        segment = [[1, 0], [0, 3], [1, 3], [3, 2], [1, 2], [5, 0], [5, 1], [1, 4], [5, 4]]
        faceseg = [[0, 1, 2], [2, 3, 4], [5, 0, 6], [6, 7, 8]]        
        """
        segment=[]
        faceseg=[]
        linkseg=[]
        reverses=[]        
        for f in me.faces:
                face=[]
                for n in range(len(f.v)-1):
                   s0=[me.verts.index(f.v[n]),
                       me.verts.index(f.v[n+1])]
                   if s0 not in segment:
                       segment.append(s0)
                   face.append(segment.index(s0))
                s2=[me.verts.index(f.v[n+1]),me.verts.index(f.v[0])]
                if s2 not in segment:
                       segment.append(s2)
                face.append(segment.index(s2))
                faceseg.append(face[:])
                
        for n in range(len(segment)):
           linkseg.append([])
                 
        for r in segment:
           t=[r[1],r[0]]
           ok=0
           for n in range(len(segment)):
              if segment[n]==t:
                ok=1 
                reverses.append([segment.index(r),n])
           if ok==0:
                reverses.append([r])
                
        return segment,faceseg,linkseg,reverses

def dist_vect(a,b):
    x=a.co[0]-b.co[0]
    y=a.co[1]-b.co[1]
    z=a.co[2]-b.co[2]
    return (x*x+y*y+z*z)**0.5

def ordonnequad(a,b,c,d):
   d0= [ [dist_vect(a,b),0],
         [dist_vect(a,c),1],
         [dist_vect(a,d),2],
         [dist_vect(b,c),3],
         [dist_vect(b,d),4],
         [dist_vect(c,d),5],
         ]
   d2=[[d0[0][0]+d0[3][0]+d0[5][0]+d0[2][0],0],  ## a,b,c,d
       [d0[0][0]+d0[4][0]+d0[5][0]+d0[1][0],1],  ## a,b,d,c
       [d0[2][0]+d0[4][0]+d0[3][0]+d0[1][0],2]   ## a,d,b,c    
       ]
   d2.sort()
   if d2[0][1]==0:
      return a,b,c,d
   elif d2[0][1]==1:
      return a,b,d,c
   elif d2[0][1]==2:
      return a,d,b,c
   
def centre_facette(face):
                accu2=[0.0,0.0,0.0] 
                lgf1=len(face.v)
                #-------------------------------------------------------
                #boucler sur la liste des vertices>points de chaque face
                #-------------------------------------------------------                
                for v in face.v:
                    for n0 in range(3):
                        accu2[n0]=accu2[n0]+v.co[n0]
                    n0=0
                #-------------------------------------------------------
                #centre geometrique de la facette
                #-------------------------------------------------------                    
                for n0 in range(len(accu2)):
                    accu2[n0]=accu2[n0]/(lgf1*1.0)
                    
                return accu2
            
def calcul_Z_deplacement( face, B, MaxIter):                          
                if B.DistanceTG.val==1.0:
                     dv=face.v
                     #a,b,c = EquationPlan(dv[0],dv[1],dv[2])
                     a,b,c=face.no
                     
                     if not B.RandomDistance.val:
                        g0=1.0
                     else:  
                        g0=g()
                        
                     if B.RandomNeg.val==1.0:
                        n_0= n_()
                        if n_0>=0.5:
                           g0=-g0
                          
                     g0=g0*B.Iteration.val/MaxIter
                         
                     if B.DistNegTG.val:
                           locZ=[-a*B.distance.val*g0,-b*B.distance.val*g0,-c*B.distance.val*g0]
                     else:
                           locZ=[a*B.distance.val*g0,b*B.distance.val*g0,c*B.distance.val*g0]
                         
                else:
                     locZ=[0.0,0.0,0.0]
                     a,b,c=0.0,0.0,0.0
                         
                if B.RandomXY.val==1.0:
                            epais2=B.epaisseur.val*g()
                else:
                            epais2=B.epaisseur.val
                         
                return locZ,epais2,a,b,c

def rotation_aroundxyz(u,v0,w,x,y,z):
    u=u*pi/180.0
    v=v0*pi/180.0
    w=w*pi/180.0   
    if u!=0.0:   ##x-axis:
        y1 = y * cos(u) - z * sin(u)
        z1 = z * cos(u) + y * sin(u)
        z=z1
        y=y1
    if v!=0.0:           ##y-axis:
        z1 = z * cos(v) - x * sin(v)
        x1 = x * cos(v) + z * sin(v)
        z=z1
        x=x1        
    if w!=0.0:   ##z-axis:
        x1 = x * cos(w) - y * sin(w)
        y1 = y * cos(w) + x * sin(w)
        x=x1
        y=y1        
    return x,y,z   


def ArbitraryRotate(p,theta,r):
   q = [0.0,0.0,0.0]     
   costheta = cos(theta*pi/180)
   sintheta = sin(theta*pi/180)
   q[0] += (costheta + (1 - costheta) * r[0] * r[0]) * p[0]
   q[0] += ((1 - costheta) * r[0] * r[1] - r[2] * sintheta) * p[1]
   q[0] += ((1 - costheta) * r[0] * r[2] + r[1] * sintheta) * p[2]
   q[1] += ((1 - costheta) * r[0] * r[1] + r[2] * sintheta) * p[0]
   q[1] += (costheta + (1 - costheta) * r[1] * r[1]) * p[1]
   q[1] += ((1 - costheta) * r[1] * r[2] - r[0] * sintheta) * p[2]
   q[2] += ((1 - costheta) * r[0] * r[2] - r[1] * sintheta) * p[0]
   q[2] += ((1 - costheta) * r[1] * r[2] + r[0] * sintheta) * p[1]
   q[2] += (costheta + (1 - costheta) * r[2] * r[2]) * p[2]
   return q[0],q[1],q[2]

## ---------------------------------
## grands mercis à richie pour son aide 
## sur les deux fonctions suivantes
## ---------------------------------
def pv(a,b,c):
      c[0]=a[1]*b[2]-a[2]*b[1]
      c[1]=a[2]*b[0]-a[0]*b[2]
      c[2]=a[0]*b[1]-a[1]*b[0]
      return c

w=[0.0,0.0,0.0]
axeloc=[]
accu3=[0.0,0.0,0.0]

def rxyn(no):
      if no[0]!=0.0:
            ang=math.atan(no[1]/no[0])+pi/2
            X=[cos(ang),sin(ang),0]
      else:
            X=[0.0,0.0,0.0]
         
      if no[0]<0:
            X[0],X[1]=-X[0],-X[1]
      Y=pv(X,no,w)
      return(X,Y,no)
         
def sommet_connectes(face, n3, dern_long):   
            global liste_des_sommets, liste_dordre_des_sommets             
            if face.v[n3+1].index not in liste_des_sommets.keys():
                 liste_des_sommets[face.v[n3+1].index]=[]
                 liste_dordre_des_sommets[face.v[n3+1].index]=[]                 
            if dern_long[1]+n3+1 not in liste_des_sommets[face.v[n3+1].index]:         
               liste_des_sommets[face.v[n3+1].index].append(dern_long[1]+n3+1)
            if face.v[n3].index not in liste_des_sommets.keys():
                 liste_des_sommets[face.v[n3].index]=[]
                 liste_dordre_des_sommets[face.v[n3].index]=[]
            if dern_long[1]+n3 not in liste_des_sommets[face.v[n3].index]:    
                  liste_des_sommets[face.v[n3].index].append(dern_long[1]+n3)
                  
def ordre_des_sommets(s1,f1,f0):
           global liste_des_sommets, liste_dordre_des_sommets
           liste_dordre_des_sommets[s1].append([liste_des_sommets[s1].index(f0),liste_des_sommets[s1].index(f1)])
           
def creation_facette(n1,me,me2,face,accu2,epais2,locZ,liste_des_facesbis,a,b,c,recursion):
                global axeloc, B, liste_des_sommets, liste_dordre_des_sommets
                global liste_des_segments, liste_des_faceseg,liste_des_seglink
                global liste_reverseg, liste_des_facescchanfrein
                
                limite=0.0001
                 
                #calculer la position
                if B.matrix['use_matrice'].val==0:
                   for v in face.v:

                       if B.RandomXY2.val==1.0:
                          g1=g()
                          g0=[g1,g1,1.0]
                       else:
                          g0=[1.0]*3
                          
                       #appel de la methode d'ajout de point
                       v1= Blender.NMesh.Vert(0.0, 0.0, 0.0)
                       for n0 in range(len(accu2)):                        
                              v1.co[n0]=(v.co[n0]-accu2[n0])*g0[0]*epais2+accu2[n0]+locZ[n0]
                                                     
                       #ajouter le point à la liste
                       me.verts.append(v1)
                       me2.verts.append(v1)
                else:
                   #creation de nouveaux points à l'interieur de la facette
                   m=[[B.matrix['Sx'].val,B.matrix['Sy'].val,B.matrix['Sz'].val],
                      [B.matrix['Rx'].val,B.matrix['Ry'].val,B.matrix['Rz'].val],
                      [B.matrix['Rnz'].val, B.matrix['Rnx'].val,B.matrix['Rny'].val]]   

                   abc=[a,b,c]

                   coeff=1.0/B.matrix['recursion'].val

                   #print coeff
                   rz= coeff*m[2][0]                   
                   rx= coeff*m[2][1]
                   ry= coeff*m[2][2]
                   
                   u= coeff*m[1][0]
                   v0= coeff*m[1][1]
                   w= coeff*m[1][2]
                   
                   #print recursion
                   if recursion==B.matrix['recursion'].val-1 or  B.matrix['recursion'].val==1:
                         axeloc=rxyn(abc)                   
                     
                   for v in face.v:
                       #appel de la methode d'ajout de point
                       v1= Blender.NMesh.Vert(0.0, 0.0, 0.0)
                       if B.RandomXY2.val==1.0:
                          g1=g()
                          g0=[g1,g1,1.0]
                       else:
                          g0=[1.0]*3
                       for n0 in range(len(accu2)):
                            v1.co[n0]=(v.co[n0]-accu2[n0])*g0[n0]*epais2 

                             
                       if B.matrix['rotGlobal'].val==1:
                           accu3[0], accu3[1], accu3[2] = rotation_aroundxyz(u,v0,w,accu2[0], accu2[1], accu2[2])
                          
                       if abs(m[2][0])>=limite:
                          v1.co[0],v1.co[1],v1.co[2]=ArbitraryRotate([v1.co[0],v1.co[1],v1.co[2]],rz,abc)
                          
                       if abs(m[2][1])>=limite or abs(m[2][2])>=limite:
                          v1.co[0],v1.co[1],v1.co[2]=ArbitraryRotate([v1.co[0],v1.co[1],v1.co[2]],rx,axeloc[0])
                          v1.co[0],v1.co[1],v1.co[2]=ArbitraryRotate([v1.co[0],v1.co[1],v1.co[2]],ry,axeloc[1])
                          
                       #v1.co[0],v1.co[1],v1.co[2]
                       
                       if B.matrix['rotGlobal'].val==0:
                           v1.co[0],v1.co[1],v1.co[2]=rotation_aroundxyz(u,v0,w,v1.co[0],v1.co[1],v1.co[2])
                           for n0 in range(len(accu2)):                              
                               v1.co[n0]=v1.co[n0]+accu2[n0]+(locZ[n0]+m[0][n0])*coeff
                       else: 
                          v1.co[0],v1.co[1],v1.co[2]=rotation_aroundxyz(u*2.0,v0*2.0,w*2.0,v1.co[0],v1.co[1],v1.co[2])
                          for n0 in range(len(accu2)):                              
                               v1.co[n0]=v1.co[n0]+accu3[n0]+(locZ[n0]+m[0][n0])*coeff
                               
                       #ajouter le point à la liste
                       me.verts.append(v1)
                       me2.verts.append(v1)
                       
                n0=0
                       
                #ne pas depasser la fin de la liste des points de cette facette
                n2=len(face.v)
                
                #ajouter une face
                f1= Blender.NMesh.Face()
                f1.mat=face.mat
 
                #cette face est composée des sommets normaux
                f1.v.append(face.v[n2-1])
                f1.v.append(face.v[0])  
               
                #et des nouveaux sommet ajouté
                f1.v.append(me.verts[dern_long[1]])
                f1.v.append(me.verts[dern_long[1]+n2-1])

                if B.SelectedFacesTG.val==1 or me.hasFaceUV()==1:
                   try: 
                      f1.image=face.image  
                      if len(face.uv)!=0:
                         if len(f1.v)==len(face.v):
                            f1.uv=face.uv[:]
                         elif f1.uv > len(face.v):
                            f1.uv=uv[0:len(f1.v)]
                            for nuv in range(len(face.uv)):
                                 f1.uv[nuv]=face.uv[nuv]
                         elif f1.uv < len(face.v):
                            f1.uv=face.uv[0:len(f1.v)]
                      else:
                          f1.uv=uv[0:len(f1.v)]
                   except:     
                      f1.uv=uv[0:len(f1.v)]
                   f1.flag=1
                   f1.col=face.col[:]              
                                
                # le segment qui contrôle le chanfrein est donc
                # sur la face normale                               
                me2.faces.append(f1)                 
                liste_des_facesbis.append(len(me2.faces)-1)
                  
                if B.Chanfrein.val==1 or B.Enveloppe.val==1:
                            fz= [face.v[n2-1].index, face.v[0].index]
                            if  fz in liste_des_segments:
                               liste_des_seglink[liste_des_segments.index(fz)].append([len(me2.faces)-1,  dern_long[1],dern_long[1]+n2-1])
                 
                #boucler sur les points de cette facette
                for n3 in range(n2-1):
                    #creation des facettes supplémentaires 
                    f1= Blender.NMesh.Face()
                    
                    f1.mat=face.mat
                    f1.col=face.col              
     
                    f1.v.append(face.v[n3])
                    f1.v.append(face.v[n3+1])
                         
                    f1.v.append(me.verts[dern_long[1]+n3+1])
                    f1.v.append(me.verts[dern_long[1]+n3])
                    
                    if B.SelectedFacesTG.val==1 or me.hasFaceUV()==1:
                       try: 
                          f1.image=face.image  
                          if len(face.uv)!=0:
                             if len(f1.v)==len(face.v):
                                f1.uv=face.uv[:]
                             elif f1.uv > len(face.v):
                                f1.uv=uv[0:len(f1.v)]
                                for nuv in range(len(face.uv)):
                                     f1.uv[nuv]=face.uv[nuv]
                             elif f1.uv < len(face.v):
                                f1.uv=face.uv[0:len(f1.v)]
                          else:
                              f1.uv=uv[0:len(f1.v)]
                       except:     
                          f1.uv=uv[0:len(f1.v)]
                       f1.flag=1
                       f1.col=face.col[:]              
                     
                    if (n3==0) and B.matrix['use_matrice'].val==0: 
                        me2.faces[n1]=f1
                        if me2.faces.index(f1) not in liste_des_facesbis:
                           liste_des_facesbis.append(me2.faces.index(f1))
                    else:
                        me2.faces.append(f1)                         
                        liste_des_facesbis.append(len(me2.faces)-1)
                         
                    if B.Digger.val==1 or B.Chanfrein.val==1 or B.Enveloppe.val==1:
                       sommet_connectes(face, n3, dern_long)                      
                         
                    if B.Chanfrein.val==1 or B.Enveloppe.val==1:
                            fz= [face.v[n3].index, face.v[n3+1].index]
                            if  fz in liste_des_segments:
                               liste_des_seglink[liste_des_segments.index(fz)].append([me2.faces.index(f1),dern_long[1]+n3+1, dern_long[1]+n3])
                try:
                   if  B.matrix['segment'].val==0:
                       del  me2.faces[me2.faces.index(face)]
                except:
                    pass
                  
                return n2
                     
def  Face_interne(n2,me,me2,liste_des_facesbis,dern_long,f):
                #------------------
                # boucler sur les points de cette facette
                # pour obturer l'ouverture restante
                #-------------------
                global B,liste_des_facescchanfrein
                if B.FaceinterneTG.val:
                   f1= Blender.NMesh.Face()  

                   f1.mat=f.mat


                   for n3 in range(n2):
                       #creation des facettes supplémentaires 
                       f1.v.append(me.verts[dern_long[1]+n3])

                   if B.SelectedFacesTG.val==1 or me.hasFaceUV()==1:
                    try: 
                      f1.image=face.image  
                      if len(face.uv)!=0:
                         if len(f1.v)==len(face.v):
                            f1.uv=face.uv[:]
                         elif f1.uv > len(face.v):
                            f1.uv=uv[0:len(f1.v)]
                            for nuv in range(len(face.uv)):
                                 f1.uv[nuv]=face.uv[nuv]
                         elif f1.uv < len(face.v):
                            f1.uv=face.uv[0:len(f1.v)]
                      else:
                          f1.uv=uv[0:len(f1.v)]
                    except:     
                        f1.uv=uv[0:len(f1.v)]
                    f1.flag=1
                    f1.col=f.col[:]
                   
                   me2.faces.append(f1)
                   liste_des_facesbis.append(len(me2.faces)-1)
                   liste_des_facescchanfrein.append(len(me2.faces)-1)                   

                dern_long[1]=len(me.verts)
                face=me2.faces[len(me2.faces)-1]                   
                return dern_long, face
            

def creation_recursive(recursion,
                       face,
                        me,
                        me2,
                        n1,
                        B,
                        a,b,c,
                        n2,
                        dern_long,
                        MaxIter
                       ):
                          
        global liste_des_segments, liste_des_faceseg, liste_des_seglink
        global liste_reverseg, liste_des_facescchanfrein
        
        if  B.matrix['use_matrice'].val==1: 
           if recursion==1:
                accu2=centre_facette(face)
                locZ,epais2,a,b,c= calcul_Z_deplacement( face,B,MaxIter)
                n2=creation_facette(n1,me,me2,face,accu2,epais2,locZ,liste_des_facesbis,a,b,c,recursion)
                dern_long,face=Face_interne(n2, me,me2,liste_des_facesbis,dern_long,face)                
           else:
                recursion-=1
                accu2=centre_facette(face)
                locZ,epais2,a,b,c= calcul_Z_deplacement( face, B, MaxIter )                
                n2=creation_facette(n1,me,me2,face,accu2,epais2,locZ,liste_des_facesbis,a,b,c,recursion)
                dern_long,face=Face_interne(n2, me,me2,liste_des_facesbis,dern_long,face )                
                creation_recursive( recursion, face, me, me2, n1, B, a,b,c, n2, dern_long, MaxIter )
        else:
                accu2=centre_facette(face)
                locZ,epais2,a,b,c= calcul_Z_deplacement( face, B,  MaxIter )
                n2=creation_facette(n1,me,me2,face,accu2,epais2,locZ,liste_des_facesbis,a,b,c,recursion)
                dern_long,face=Face_interne(n2, me,me2,liste_des_facesbis,dern_long,face)

def connectNewMesh(mesh,Ozero,dopos):
          global annulation
          name=Ozero.getData().name

          print 'connectNewMesh : etat 1  ',annulation,dopos
          
          if Ozero.getType()!='Mesh':
               name = "problem : you are trying to add a  mesh to a non compatible object: %s!"%Ozero.getType()
               result = Blender.Draw.PupMenu(name) 
               return
            
          if name not in annulation:
                 if dopos==-1: 
                     annulation.append(name)
                 else:
                    try:
                       annulation.insert(dopos,name)
                    except:
                       annulation.insert(0,name)
                       dopos=len(annulation)-1
                       
          if Ozero.getData().name!=mesh.name:             
             Ozero.link(mesh) 
             Ozero.makeDisplayList()
          
          print 'connectNewMesh : etat 2 ',annulation,dopos
          return dopos 

def doAction(dopos,Ozero,un):
          global annulation
          #print 'Ozero',Ozero
          if len(annulation)>0:
              if dopos==-1:
                 dopos=len(annulation)-1
              else:   
                 dopos=dopos-un
                 
              if dopos>=len(annulation)-1:
                   dopos=len(annulation)-1
              mesh=NMesh.GetRaw(annulation[dopos])
              Ozero.link(mesh) 
              Ozero.makeDisplayList()
              print 'should connect mesh : ', mesh.name
              print 'annulation, dopos : ',annulation, dopos
              Blender.Redraw()
              return dopos
          print 'annulation, dopos : ',annulation, dopos
    
    
def tesselateUndo(dopos,Ozero,un):
          global annulation
          print 'undo : '
          dopos=doAction(dopos,Ozero,un)
          return dopos
        
   
#fonction de fractionnement de face
def tesselate(meb,nom,ob, MaxIter):
    global dern_long,n0,p0,n,accu1,accu2, n_,n_0,liste_des_faces
    global liste_des_facesbis, liste_des_sommets, liste_des_segments
    global liste_des_faceseg, liste_des_seglink, liste_dordre_des_sommets
    global liste_reverseg, liste_des_facescchanfrein, dopos

    me2= Blender.NMesh.GetRaw()
    me = Blender.NMesh.GetRaw()
    
    if B.SaveOriginal.val==1:
            Blender.NMesh.PutRaw(meb,'SaveOriginal')
            me=meb 
    else:            
            me=meb
            
    if B.Chanfrein.val==1 or B.Enveloppe.val==1:
                    liste_des_segments,liste_des_faceseg,liste_des_seglink,liste_reverseg=doc_segments(me)    

    if B.SplitTotalTG.val==0 :
            #--------------------
            # copie de la liste des materiaux
            #-------------------- 
            for M in me.materials:
                me2.addMaterial(M)
            #--------------------
            # copie de la liste de sommets
            #-------------------- 
            for v in me.verts:
                v1= Blender.NMesh.Vert(0.0,0.0,0.0)
                v1=v
                me2.verts.append(v1)            
            #--------------------
            # copie de la liste de face
            #--------------------            
            for f in me.faces:
              if len(f.v)>2:
                f1=Blender.NMesh.Face()
                f1=f
                f1.mat=f.mat
                if B.SelectedFacesTG.val==1 or me.hasFaceUV()==1:
                    f1.uv=f.uv[:]
                    f1.flag=0
                    f1.col=f.col
                elif  me.hasVertexColours()==1:
                    f1.uv=uv[0:len(f1.v)]
                    f1.flag=0
                    f1.col=f.col                    
                me2.faces.append(f1)
                
            #------------------------
            #reperer la fin des listes de points et de facettes
            #------------------------    
            dern_long[0]=len(me.faces)
            dern_long[1]=len(me.verts)            
            #------------------------
            #accumulateur pour trouver le centre geometrique du mesh
            #------------------------            
            lgf=len(me.faces)
            #------------------------
            # faire la liste des face à traiter:
            #------------------------
            #  Toutes...
            if B.SelectedFacesTG.val==0:
                liste_des_faces=range(dern_long[0])
            #------------------------
            #... ou seulement celles selectionnees 
            #------------------------
            elif me.hasFaceUV()==1 and liste_des_faces==[]:
                  faces=meb.getSelectedFaces()
                  for f in faces:
                     liste_des_faces.append(meb.faces.index(f)) 
                  #print liste_des_faces
                     
            #------------------------
            # ... ou si on est en train de repeter
            # l'opération plusieurs fois sur la meme
            # serie de faces ce qui justifie l'utilisation de
            # list_des_facebis
            #------------------------
            elif B.SelectedFacesTG.val!=0 and len(liste_des_faces)!=0:      
                for f in liste_des_facesbis:
                     liste_des_faces.append(f)
                #print '...',liste_des_faces,liste_des_facesbis
                liste_des_facesbis=[]
                
            for n1 in liste_des_faces:
                face=me.faces[n1]
                n2=0
                creation_recursive( B.matrix['recursion'].val,  face, me,  me2,   n1, B, a,b,c, n2,  dern_long, MaxIter)
                  
            if B.Digger.val==1:
               accu1=[0.0,0.0,0.0]
               for s in liste_des_sommets.keys():
                  if len(liste_des_sommets[s])>2:
                     if B.PDigger.val==1:
                        for v in liste_des_sommets[s]:
                           for n0 in range(3):
                              accu1[n0]= accu1[n0]+me2.verts[v].co[n0]
                        for n0 in range(3):
                           me2.verts[s].co[n0]+=(me2.verts[s].co[n0]-accu1[n0]/float(len(liste_des_sommets[s])))*B.NDigger.val
                     else:
                        for n0 in range(3):
                           if  B.NDigger.val/abs(B.NDigger.val)>0:
                               me2.verts[s].co[n0]+=me2.verts[s].co[n0]*B.NDigger.val
                           else:
                               me2.verts[s].co[n0]-=me2.verts[s].co[n0]*B.NDigger.val
                     accu1=[0.0,0.0,0.0]
               
            if B.Enveloppe.val==1 or B.Chanfrein.val:
              excludeSlink=[]
              for f in liste_des_seglink:
                 if len(f)>1:
                    f1=NMesh.Face()
                    f1.v.append(me2.verts[f[0][1]])
                    f1.v.append(me2.verts[f[0][2]])
                    f1.v.append(me2.verts[f[1][2]])
                    f1.v.append(me2.verts[f[1][1]])
                    
                    me2.faces.append(f1)
                    liste_des_facescchanfrein.append(me2.faces.index(f1))
                    
                    s1=liste_des_segments[liste_des_seglink.index(f)][1]
                    s2=liste_des_segments[liste_des_seglink.index(f)][0]
                    
                    ordre_des_sommets(s1, f[1][1],f[0][1])
                    ordre_des_sommets(s2, f[0][2],f[1][2])
                    
                    
                 elif len(f)!=0:
                  tlink=liste_des_seglink.index(f)  
                  Slink=liste_reverseg[tlink]
                  if tlink not in excludeSlink :
                    try: 
                      f2=liste_des_seglink[Slink[1]]
                      excludeSlink.append(Slink[1])
                      f1=NMesh.Face()
                      f1.v.append(me2.verts[f[0][1]])
                      f1.v.append(me2.verts[f[0][2]])
                      f1.v.append(me2.verts[f2[0][1]])
                      f1.v.append(me2.verts[f2[0][2]])
                      
                      me2.faces.append(f1)
                      liste_des_facescchanfrein.append(me2.faces.index(f1))
                    
                      s1=liste_des_segments[liste_des_seglink.index(f)][1]
                      s2=liste_des_segments[liste_des_seglink.index(f)][0]
                      
                      ordre_des_sommets(s1, f[0][1],f2[0][2])
                      ordre_des_sommets(s2, f[0][2],f2[0][1])
                    except:
                       pass
                   
              for s in liste_des_sommets.keys():
                    accu1=[0.0,0.0,0.0]
                    for s3 in liste_des_sommets[s]:
                        for n0 in range(3):
                            accu1[n0]+=me2.verts[s3].co[n0]*1.0/float(len(liste_des_sommets[s]))
                            
                    s4=liste_des_sommets[s]
                    
                    if len(s4)>4:
                       v=NMesh.Vert(accu1[0],accu1[1],accu1[2])
                       me2.verts.append(v)
                       for s3 in liste_dordre_des_sommets[s]:
                           f1=NMesh.Face()
                           
                           f1.v.append(me2.verts[s4[s3[1]]])
                           f1.v.append(me2.verts[len(me2.verts)-1])
                           f1.v.append(me2.verts[s4[s3[0]]])
                           
                           try:
                             if me2.verts[s].no[2]/abs(me2.verts[s].no[2])!=f1.no[2]/abs(f1.no[2]):
                                f1.v.reverse()
                           except:
                              pass
                                
                           me2.faces.append(f1)
                           liste_des_facescchanfrein.append(me2.faces.index(f1))
                           
                    elif len(s4)==3:   
                           f1=NMesh.Face()
                           
                           f1.v.append(me2.verts[s4[1]])
                           f1.v.append(me2.verts[s4[2]])
                           f1.v.append(me2.verts[s4[0]])
                              
                           try:
                              if me2.verts[s].no[2]/abs(me2.verts[s].no[2])!=f1.no[2]/abs(f1.no[2]):
                                 f1.v.reverse()
                           except:
                              pass
                           
                           me2.faces.append(f1)
                           liste_des_facescchanfrein.append(me2.faces.index(f1))
                              
                           
                    elif len(s4)==4:
                           a0=me2.verts[s4[0]]
                           b0=me2.verts[s4[1]]
                           c0=me2.verts[s4[2]]
                           d0=me2.verts[s4[3]]
                           
                           a0,b0,c0,d0=ordonnequad(a0,b0,c0,d0)
                           
                           f1=NMesh.Face()
                           f1.v.append(a0)
                           f1.v.append(b0)
                           f1.v.append(c0)
                           f1.v.append(d0)
                           
                           try:  
                             if me2.verts[s].no[2]/abs(me2.verts[s].no[2])!=f1.no[2]/abs(f1.no[2]):
                               f1.v.reverse()
                           except:
                              pass
                           
                           me2.faces.append(f1)
                           liste_des_facescchanfrein.append(me2.faces.index(f1))
                           
              
            if B.Chanfrein.val==1:
                me3=NMesh.GetRaw()
                
                for M in me.materials:
                   me3.addMaterial(M)
                
                index=[]
                
                for f0 in liste_des_facescchanfrein:
                    f=me2.faces[f0]
                    f1=NMesh.Face()

                    f1.mat=f.mat                    
                    
                    
                    for v in f.v:
                       if me2.verts.index(v) not in index:
                          index.append(me2.verts.index(v))
                          v1=NMesh.Vert(v.co[0],v.co[1],v.co[2])
                          me3.verts.append(v1)
                          f1.v.append(me3.verts[-1])
                       else:
                          f1.v.append(me3.verts[index.index(me2.verts.index(v))])
                    f1.uv= f.uv[:]
                    f1.col=f.col[:]
                    
                    me3.faces.append(f1)

                ##print len(index), index
                
               
    #elif B.SplitTotalTG.val==1 and B.SelectedFacesTG.val==0:
    elif B.SplitTotalTG.val==1 :
           for f in me.faces:
                f1=Blender.NMesh.Face()  
                for v in f.v:
                  v1= Blender.NMesh.Vert(v.co[0],v.co[1],v.co[2])
                  if B.SelectedFacesTG.val :
                      v1.sel = 1 - v.sel
                  else :  v1.sel = v.sel
                  me2.verts.append(v1)
                  f1.v.append(me2.verts[len(me2.verts)-1]) 
                me2.faces.append(f1)
                f1.uv= f.uv[:]
                f1.col=f.col[:]
                f1.smooth=f.smooth
                f1.mode=f.mode
                f1.flag=f.flag
                f1.mat=f.mat
                if B.SelectedFacesTG.val :
                   f1.sel = 1 - f.sel
                else :  f1.sel = f.sel
                 
 
    #elif B.SplitTotalTG.val==0 and B.SelectedFacesTG==1:
    #    pass
     
    if BLVERSION>=228:
        me2.mode=meb.mode

    if BLVERSION>=233:
        me2.materials=meb.materials[:]

    if B.Chanfrein.val==1:
       dopos=connectNewMesh(me3,ob,dopos)
    else:
       dopos=connectNewMesh(me2,ob,dopos)
       if B.SplitTotalTG.val==1 and  B.SelectedFacesTG.val :
          ME=Blender.Object.Get(ob.name).getData(mesh=1)
          ME.remDoubles(0.001)
          for f in ME.faces:
            f.sel = 1 - f.sel # 1 becomes 0, 0 becomes 1

def testselect(MaxIter,ob):
    global liste_des_faces,liste_des_facesbis,BLVERSION
    global liste_des_sommets, liste_des_segments
    global liste_des_faceseg, liste_des_seglink, liste_dordre_des_sommets
    global liste_reverseg, liste_des_facescchanfrein
      
    liste_des_faces=[]
    liste_des_facesbis=[]            
    liste_des_sommets={}
    liste_dordre_des_sommets={}          
    liste_des_facescchanfrein=[]
     
    liste_des_segments=[]
    liste_des_faceseg=[]
    liste_des_seglink=[]
    liste_reverseg=[]
     
    ob= Blender.Object.GetSelected()        

    if len(ob)<1:
        return
    elif ob[0].getType()=='Mesh': 
        ob=ob[0]   
    else:
        name = "Are you sure? No mesh selected !!" 
        result = Blender.Draw.PupMenu(name) 
        return

    if BLVERSION>=234: 
       in_editmode= Blender.Window.EditMode()        
       if in_editmode: Blender.Window.EditMode(0)        

    grouplist=[] 
    if BLVERSION==223:
       me=ob.data
       materials=me.mats
    else:
       me=ob.getData()
       materials=me.materials
    nom=me.name              
    if (me==None):
        return
    tesselate(me,nom,ob,MaxIter)
    ob.makeDisplayList()
    if BLVERSION>=234: 
        if in_editmode: Blender.Window.EditMode(1)        

def draw():
    global B, liste_des_sommets,ob
     
    size=Buffer(GL_FLOAT, 4)
    glGetFloatv(GL_SCISSOR_BOX, size)
    size= size.list

    for s in [0,1,2,3]: size[s]=int(size[s])
    
    ligne=18
     
    glColor3f(0.7, 0.7, 0.7)
    glClear(GL_COLOR_BUFFER_BIT)
    glColor3f(0.1, 0.1, 0.15)
    glRasterPos2f(20, size[3]-ligne)
    Text("Fragmentation et Extrusion")

    glRasterPos2f(20, size[3]-ligne*2)
    Text("J-m Soler,  jan-Oct 2000-May 2004")
    l=int(B.lang.val)
     
    ligne=20

    Button(lg[l]['Undo'], 11, 25+GetStringWidth("J-m Soler,  jan-Oct 2000-May 2004"), size[3]-ligne*2,40, 18)
    Button(lg[l]['Redo'], 12, 70+GetStringWidth("J-m Soler,  jan-Oct 2000-May 2004"), size[3]-ligne*2,40, 18)

    B.Enveloppe=Toggle(lg[l]['Envel'], ENVELOPPE, 150, size[3]-ligne*10, 65, 18, B.Enveloppe.val, lg[l]['Envel_doc'])    
    B.Chanfrein=Toggle(lg[l]['Chanfrein'], CHANFREIN, 212, size[3]-ligne*10, 65, 18, B.Chanfrein.val, lg[l]['Chanfrein_doc'])
     
    #boutons de sortie
    Button("Exit", 1, 20, size[3]-ligne*10, 60, 18)
      
    #bouton de cration de la forme
    Button(lg[l]['Act'], 3, 85, size[3]-ligne*10, 60, 18)
     
    B.lang           = Toggle( lg[l]['Lang'],     2, 172, size[3]-ligne,  44, 18, B.lang.val )
    B.SaveOriginal   = Toggle( lg[l]['SaveOrig'], 2, 218, size[3]-ligne, 105, 18, B.SaveOriginal.val ,lg[l]['SaveOrig_doc'] )
    B.epaisseur      = Slider( lg[l]['EpXY'],     2,  20, size[3]-ligne*3 , 260, 18, B.epaisseur.val, 0.0, 2.0, 0,lg[l]['EpXY_doc'])
    B.RandomXY       = Toggle( lg[l]['randomxy'], 2, 280, size[3]-ligne*3 ,  20, 18, B.RandomXY.val, lg[l]['randomxy_doc'])
    B.RandomXY2       = Toggle( lg[l]['randomxy2'], 2, 300, size[3]-ligne*3 ,  20, 18, B.RandomXY2.val, lg[l]['randomxy2_doc'])
     
     
    if B.B_allign.val==1.0:
        H=310
        V=10
        L=1.7
        L2=1.15
        L3=1.27
    else:
        H=0
        V=0
        L=1.0
        L2,L3=1,1
     
    if B.matrix['use_matrice'].val==1:
       B.matrix['use_matrice'] = Toggle(lg[l]['UseMatrice'], 5, 330-H, size[3]-ligne*(1+V),  85, 18, B.matrix['use_matrice'].val, lg[l]['UseMatrice_doc'])   
       if B.matrix['recvar'].val==1:
          B.matrix['recvar'] = Toggle(lg[l]['recvar'], 5, 330-H+200, size[3]-ligne*(2+V),  22, 18, B.matrix['recvar'].val, lg[l]['recvar_doc'])   
          B.matrix['recursion']   = Slider(lg[l]['division'],   5, 330-H, size[3]-ligne*(2+V), 199, 18, B.matrix['recursion'].val,1,B.matrix['limrec'].val,0, lg[l]['division_doc'])
          B.matrix['limrec']      = Number('',                  5, 330+225-H, size[3]-ligne*(2+V),  80, 18, B.matrix['limrec'].val,10,100,lg[l]['division_doc'])
       else:
          B.matrix['recvar'] = Toggle(lg[l]['recvar'], 5, 330-H, size[3]-ligne*(2+V),  22, 18, B.matrix['recvar'].val, lg[l]['recvar_doc'])   
       
       B.matrix['maxdec']   =    Number('',     5, 330+98+60-H, size[3]-ligne*(1+V),   73, 18, B.matrix['maxdec'].val,1.0,1000.0, lg[l]['MaxDec_doc'])              
       B.matrix['maxrot']   =    Number('',     5, 562-H, size[3]-ligne*(1+V),   73, 18, B.matrix['maxrot'].val,180.0,4800.0, lg[l]['MaxRot'])
       
     
       B.matrix['segment']     = Toggle(lg[l]['Segment'],    5, 330+93-H, size[3]-ligne*(1+V),  60, 18, B.matrix['segment'].val, lg[l]['Segment_doc'])  
     
       B.matrix['Sx']          = Slider(lg[l]['Sx'],         5, 330-H, size[3]-ligne*(3+V), 306, 18, B.matrix['Sx'].val,-B.matrix['maxdec'].val,B.matrix['maxdec'].val,0, lg[l]['Rx_doc'])
       B.matrix['Sy']          = Slider(lg[l]['Sy'],         5, 330-H, size[3]-ligne*(4+V), 306, 18, B.matrix['Sy'].val,-B.matrix['maxdec'].val,B.matrix['maxdec'].val,0, lg[l]['Ry_doc'])
       B.matrix['Sz']          = Slider(lg[l]['Sz'],         5, 330-H, size[3]-ligne*(5+V), 306, 18, B.matrix['Sz'].val,-B.matrix['maxdec'].val,B.matrix['maxdec'].val,0, lg[l]['Rz_doc'])
     
       if B.matrix['rotGlobal'].val==0:
           B.matrix['rotGlobal']     = Toggle(lg[l]['rotLocal'],    5, 330+262-H, size[3]-ligne*(8+V),  44, 58, B.matrix['rotGlobal'].val, lg[l]['rotLocal_doc'])  
       else:
           B.matrix['rotGlobal']     = Toggle(lg[l]['rotGlobal'],    5, 330+262-H, size[3]-ligne*(8+V),  44, 58, B.matrix['rotGlobal'].val, lg[l]['rotGlobal_doc'])  
     
       B.matrix['Rx']          = Slider(lg[l]['Rx'],         5, 330-H, size[3]-ligne*(6+V), 260, 18, B.matrix['Rx'].val,-B.matrix['maxrot'].val,B.matrix['maxrot'].val,0, lg[l]['Rx_doc'])       
       B.matrix['Ry']          = Slider(lg[l]['Ry'],         5, 330-H, size[3]-ligne*(7+V) , 260, 18, B.matrix['Ry'].val,-B.matrix['maxrot'].val,B.matrix['maxrot'].val,0, lg[l]['Ry_doc'])
       B.matrix['Rz']          = Slider(lg[l]['Rz'],         5, 330-H, size[3]-ligne*(8+V), 260, 18, B.matrix['Rz'].val,-B.matrix['maxrot'].val,B.matrix['maxrot'].val,0, lg[l]['Rz_doc'])
     
       B.matrix['Rnz']         = Slider(lg[l]['Rnz'],        5, 330-H, size[3]-ligne*(9 +V), 306, 18, B.matrix['Rnz'].val,-B.matrix['maxrot'].val,B.matrix['maxrot'].val,0, lg[l]['Rnz_doc'])       
       B.matrix['Rnx']         = Slider(lg[l]['Rnx'],        5, 330-H, size[3]-ligne*(10+V), 306, 18, B.matrix['Rnx'].val,-B.matrix['maxrot'].val,B.matrix['maxrot'].val,0, lg[l]['Rnx_doc'])       
       B.matrix['Rny']         = Slider(lg[l]['Rny'],        5, 330-H, size[3]-ligne*(11+V), 306, 18, B.matrix['Rny'].val,-B.matrix['maxrot'].val,B.matrix['maxrot'].val,0, lg[l]['Rny_doc'])       
     
       B.Extrude.val=1
       B.DistanceTG.val =1
       B.FaceinterneTG.val=1
       
       
    else:
       B.matrix['use_matrice']=Toggle(lg[l]['UseMatrice'], 5, 330, size[3]-ligne*10, 60, 198, B.matrix['use_matrice'].val, lg[l]['UseMatrice_doc'])
       
    if B.Extrude.val==1:
        B.DistanceTG     = Toggle( lg[l]['EpZ'],        2,  50, size[3]-ligne*5, 80,  18, B.DistanceTG.val, lg[l]['EpZ_doc'])
        B.distance       = Slider( lg[l]['EpQZ'],       2,  50, size[3]-ligne*4, 220, 18, B.distance.val, 0.001, B.maxdistance.val ,0,lg[l]['EpQZ_doc'])
        B.maxdistance    = Number( '',                  2, 270, size[3]-ligne*4, 50,  18, B.maxdistance.val, 0.01, 200.0, lg[l]['EpQZ_doc'])
        B.RandomDistance = Toggle( lg[l]['random'],     2, 130, size[3]-ligne*5, 60,  18, B.RandomDistance.val, lg[l]['random_doc'])
        B.RandomNeg      = Toggle( lg[l]['randomneg'],  2, 210, size[3]-ligne*5, 60,  18, B.RandomNeg.val, lg[l]['random_docneg'])
        B.DistNegTG      = Toggle( lg[l]['NgZ'],        2, 270, size[3]-ligne*5, 50,  18, B.DistNegTG.val, lg[l]['NgZ_doc'])
        B.Extrude        = Toggle( lg[l]['Extrude_off'],5,  20, size[3]-ligne*5, 28,  38, B.Extrude.val, lg[l]['Extrude_doc'])
    else:
        B.Extrude        = Toggle( lg[l]['Extrude'],    5,  20, size[3]-ligne*5, 300, 40, B.Extrude.val, lg[l]['Extrude_doc'])
        B.DistanceTG.val=0
        
    B.FaceinterneTG      = Toggle( lg[l]['FintTG'],     5,  20, size[3]-ligne*6, 150, 18, B.FaceinterneTG.val, lg[l]['FintTG_doc'])
    B.SelectedFacesTG    = Toggle( lg[l]['Select'],     5, 170, size[3]-ligne*6, 150, 18, B.SelectedFacesTG.val, lg[l]['Select_doc'])
      
    if B.Chanfrein.val ==1 or B.Enveloppe.val==1:
       B.Iteration.val=1
    B.Iteration = Number("Iteration: ", 2, 20, size[3]-ligne*9, 300, 18, B.Iteration.val,0,8,lg[l]['iteration'] )
     
    if B.Digger.val==1:
       B.Digger=Toggle(lg[l]['Digger'], DIGGER, 20, size[3]-(ligne*7), 50, 18, B.Digger.val, lg[l]['Digger_doc'])
       B.PDigger=Toggle(lg[l]['PDigger'], DIGGER, 72, size[3]-(ligne*7), 18, 18, B.PDigger.val, lg[l]['PDigger_doc'])
        
       B.NDigger=Slider( lg[l]['NDigger'],DIGGER,  92, size[3]-(ligne*7), 208, 18, B.NDigger.val, -2.0, 2.0 ,0,lg[l]['NDigger_doc'])
       
    else:
       B.Digger=Toggle(lg[l]['Digger'], DIGGER, 20, size[3]-(ligne*7), 300, 18, B.Digger.val, lg[l]['Digger_doc'])
       
    if B.matrix['use_matrice'].val==1:
       if B.B_allign.val==1.0:   
          Hr=ligne*(12+V)
       else:
          Hr=ligne*(11+V)
          
          
    else:
          Hr=ligne*11
     
    if B.Record['Record'].val==1:
       
       B.Record['Record']=Toggle(lg[l]['Record'], 7, 20, size[3]-Hr, 80, 18, B.Record['Record'].val, lg[l]['Record_doc'])
       B.Record['SaveAs']=String(lg[l]['SaveAs'], 7, 100, size[3]-Hr, 220, 18,B.Record['SaveAs'].val,256,lg[l]['SaveAs_doc'])
       B.Record['Save']=Button(lg[l]['Save'], 9, 20, size[3]-Hr-(ligne), 150, 18, lg[l]['Save_doc'])
       B.Record['Load']=Button(lg[l]['Load'], 10, 170, size[3]-Hr-(ligne), 150, 18, lg[l]['Load_doc'])
       
    else:
       B.Record['Record']=Toggle(lg[l]['Record'], 7, 20, size[3]-Hr, 300, 18, B.Record['Record'].val, lg[l]['Record_doc'])       
      
    B.SplitTotalTG = Toggle(lg[l]['FrgT'],SPLITTOTALFACE , 20, size[3]-ligne*8, 300, 18, B.SplitTotalTG.val, lg[l]['FrgT_doc'])
     
     
    #bouton de cration de la forme
    if B.B_allign.val==1.0:
       B.B_allign=Toggle(lg[l]['V'], 5, 280, size[3]-ligne*10, 40, 18, B.B_allign.val, lg[l]['V_doc'])
    else:
       B.B_allign=Toggle(lg[l]['H'], 5, 280, size[3]-ligne*10, 40, 18, B.B_allign.val, lg[l]['H_doc'])    

def event(evt, val):    
    if (evt== QKEY and not val): Exit()

def bevent(evt):
    global B, liste_des_sommets,ob,dopos
      
    if   (evt== 1):
        Exit()
         
    elif (evt== 3):
       liste_des_sommets={}
         
       liste_des_faces=[]
       liste_des_facesbis=[]
       MaxIter= B.Iteration.val
          
       while B.Iteration.val!=0:
            testselect(MaxIter,ob)
            B.Iteration.val=B.Iteration.val-1
            
       B.Iteration.val=1
       Blender.Window.Redraw()
         
    elif evt in [SPLITTOTALFACE,CHANFREIN, ENVELOPPE,DIGGER]:
         
       B.DistanceTG.val =0
       
       if (evt== SPLITTOTALFACE) or (evt== CHANFREIN):
          B.FaceinterneTG.val=1
          B.Enveloppe.val=0
          B.Extrude.val=0          
          B.Digger.val=0

       elif (evt== ENVELOPPE):
          B.Chanfrein.val=0
          B.FaceinterneTG.val=0
          B.Digger.val=0
          
       elif  (evt== DIGGER):
          B.Chanfrein.val=0
          B.FaceinterneTG.val=1
          B.Enveloppe.val=0
          
       if (evt!= SPLITTOTALFACE) : B.SelectedFacesTG.val=0
       B.Iteration.val=1
       B.matrix['use_matrice'].val=0
         
       Blender.Window.Redraw()
         
    elif (evt==5) or (evt==2):
        if B.matrix['use_matrice'].val==1 or B.Extrude.val==1:
           B.Chanfrein.val=0
           B.Enveloppe.val=0
           B.Digger.val=0
           if B.Extrude.val==1:
              B.DistanceTG.val =1             
        Blender.Window.Redraw()

    elif (evt==9):
       B.prf_dump()
       Blender.Window.Redraw()
    elif (evt==10):
       B.prf_load()
       Blender.Window.Redraw()
    elif (evt==7):
       Blender.Window.Redraw()
    elif (evt==11):
       try:
          if BLVERSION>=234: 
             in_editmode = Blender.Window.EditMode()
             if in_editmode: Blender.Window.EditMode(0) 
          dopos=tesselateUndo(dopos,ob,1)
          if BLVERSION>=234: 
             if in_editmode: Blender.Window.EditMode(1) 
       except:
          name = "problem : no possible Undo !! " 
          result = Blender.Draw.PupMenu(name)
         
    elif (evt==12):
       try:
          if BLVERSION>=234: 
             in_editmode = Blender.Window.EditMode()
             if in_editmode: Blender.Window.EditMode(0) 
          dopos=tesselateUndo(dopos,ob,-1)
          if BLVERSION>=234:  
            if in_editmode: Blender.Window.EditMode(1) 
       except:
          name = "problem : no possible Redo !! "
          result = Blender.Draw.PupMenu(name)
       
BLVERSION=Blender.Get('version')

#try:
ob= Blender.Object.GetSelected()
if not ob and ob.getType()!='Mesh':
	ob=None
	name = "problem : no selected object  ." 
	result = Blender.Draw.PupMenu(name)
else:
	ob=ob[0] 
	if BLVERSION>=234: 
		in_editmode = Blender.Window.EditMode()
		if in_editmode: Blender.Window.EditMode(0) 
	connectNewMesh(ob.getData(),ob,dopos)
	if BLVERSION>=234: 
		if in_editmode: Blender.Window.EditMode(1)     

Register(draw, event, bevent)
