diff options
author | Willian Padovani Germano <wpgermano@gmail.com> | 2004-06-07 05:34:15 +0400 |
---|---|---|
committer | Willian Padovani Germano <wpgermano@gmail.com> | 2004-06-07 05:34:15 +0400 |
commit | b82be27659f19b2916e0744a881ef7659f232ade (patch) | |
tree | 8fd59e27a0a346d28df1c8f522d13df4c1548dc6 | |
parent | 372636c116b30adf8494bc035e1d6521e519fcd4 (diff) |
Bundled scripts:
-starting updates and new additions for Blender 2.34:
Some of the new scripts require Python modules not builtin with Blender, so you either need a full Python install or the needed extra modules. This is an ongoing work, there should be more scripts, better testing and also proper ways to tell users they don't have all expected modules. It's expected that Win users won't need full Python installs, since we can provide a minimal zip with the needed modules from 2.34 on.
Thanks to Anthony D'Agostino (scorpius), Jean-Michel Soler (jms) and Campbell Barton (Cam / ideasman) for donating the scripts now added / updated.
BPython:
-added two new script menu groups: Tools and Utils. We still need to find places elsewhere in the gui where the groups can be put.
30 files changed, 4319 insertions, 206 deletions
diff --git a/release/scripts/UVpaint05.py b/release/scripts/UVpaint05.py new file mode 100644 index 00000000000..b994be23871 --- /dev/null +++ b/release/scripts/UVpaint05.py @@ -0,0 +1,442 @@ +#!BPY +""" Registration info for Blender menus: <- these words are ignored +Name: 'UVpainter' +Blender: 232 +Group: 'UV' +Tip: 'Use vertex paint color value to fill uvmapping.' +""" + +#---------------------------------------------- +# uvpainter script (c) 04/2004 jean-michel soler +# http://jmsoler.free.fr/util/blenderfile/py/UVpaint05.zip +# this script is released under GPL licence +# for the Blender 2.33 scripts distribution +#---------------------------------------------- +#---------------------------------------------- +# Official page : +# http://jmsoler.free.fr/didacticiel/blender/tutor/cpl_uvpainting.htm +# Communicate problems and errors on: +# http://www.zoo-logique.org/3D.Blender/newsportal/thread.php?group=3D.Blender +#---------------------------------------------- +# Page officielle : +# http://jmsoler.free.fr/didacticiel/blender/tutor/cpl_uvpainting.htm +# Communiquer les problemes et erreurs sur: +# http://www.zoo-logique.org/3D.Blender/newsportal/thread.php?group=3D.Blender +#--------------------------------------------- +# ce script est proposé sous licence GPL pour etre associe +# a la distribution de Blender 2.33 et suivant +#---------------------------------------------- + +import Blender +from Blender.Draw import * +from Blender.BGL import * +from Blender.NMesh import * + +try: + import nt + os=nt +except: + import posix + os=posix + +def exist(path): + try: + pth=os.stat(Blender.sys.dirname(path)) + except: + return 0 + return 1 + +loc0= Blender.sys.dirname(Blender.Get ("filename")) +loc2=loc0+Blender.sys.dirsep+'test00.tga' + +glCr=glRasterPos2d +glCl3=glColor3f +glCl4=glColor4f +glRct=glRectf + +xlimit=0 +selmatlist=[] + +def triangle(a,b,c): + glBegin(GL_TRIANGLES); + glColor3f(a[2],a[3],a[4]) + glVertex2f(a[0],a[1]); + glColor3f(b[2],b[3],b[4]) + glVertex2f(b[0],b[1]); + glColor3f(c[2],c[3],c[4]) + glVertex2f(c[0],c[1]); + glEnd(); + +def Ltriangle(a,b,c): + glBegin(GL_LINES); + glColor3f(1.0,1.0,1.0) + glVertex2f(a[0],a[1]); + glVertex2f(b[0],b[1]); + glVertex2f(c[0],c[1]); + glEnd(); + +def carre(a,b,c,d): + triangle(a,b,c) + triangle(a,c,d) + +def Lcarre(a,b,c,d): + glBegin(GL_LINES); + glColor3f(1.0,1.0,1.0) + glVertex2f(a[0],a[1]); + glVertex2f(b[0],b[1]); + glVertex2f(c[0],c[1]); + glVertex2f(d[0],d[1]); + glEnd(); + + + +def transface(f,x,y): + global xlimit + + + + a=[0,0,0.0, 0.0,0.0,0.0] + b=[0,0,0.0, 0.0,0.0,0.0] + c=[0,0,0.0, 0.0,0.0,0.0] + d=[0,0,0.0, 0.0,0.0,0.0] + + if len(f.v)>=3: + a[0]=int(f.uv[0][0]*x) + a[1]=int(f.uv[0][1]*y) + + if a[0]>xlimit: + xlimit=a[0] + + a[2]=f.col[0].r/255.0 + a[3]=f.col[0].g/255.0 + a[4]=f.col[0].b/255.0 + + c[0]=int(f.uv[2][0]*x) + c[1]=int(f.uv[2][1]*y) + + if c[0]>xlimit: + xlimit=c[0] + + c[2]=f.col[2].r/255.0 + c[3]=f.col[2].g/255.0 + c[4]=f.col[2].b/255.0 + + + b[0]=int(f.uv[1][0]*x) + b[1]=int(f.uv[1][1]*y) + + if b[0]>xlimit: + xlimit=b[0] + + b[2]=f.col[1].r/255.0 + b[3]=f.col[1].g/255.0 + b[4]=f.col[1].b/255.0 + + + if len(f.v)==4: + d[0]=int(f.uv[3][0]*x) + d[1]=int(f.uv[3][1]*y) + + if d[0]>xlimit: + xlimit=d[0] + + d[2]=f.col[3].r/255.0 + d[3]=f.col[3].g/255.0 + d[4]=f.col[3].b/255.0 + else: + d=0 + + + #print a,b,c + return a,b,c,d + + +def extract_faces(me,MENU): + global TMATList, selmatlist + if MENU==2: + listf=[] + for f in me.faces: + if f.mat in selmatlist: + listf.append(f) + return listf + +def affiche_mesh(ME,x,y): + global LINE,xlimit,MMENU,XLIMIT,xwin,xlimit + + if ME.getType()=='Mesh': + me=GetRaw(ME.getData().name) + + if MMENU.val==1: + se=me.faces + + elif MMENU.val==3: + se=me.getSelectedFaces() + + elif MMENU.val==2: + se=extract_faces(me,2) + + xlimit=0 + for f in se: + a,b,c,d=transface(f,x,y) + if len(f.v)==4: + triangle(a,b,c) + triangle(a,c,d) + elif len(f.v)==3: + triangle(a,b,c) + + if LINE.val==1: + for f in se: + a,b,c,d=transface(f,x,y) + if len(f.v)==4: + Lcarre(a,b,c,d) + elif len(f.v)==3: + Ltriangle(a,b,c) + + if XLIMIT.val==0: + Lcarre([1,1],[1,y-2],[xlimit+2,y-2],[xlimit+2,1]) + else: + Lcarre([1,1],[1,y-2],[xwin-2,y-2],[xwin-2,1]) + + + +def write_tgafile(loc2,bitmap,width,height,profondeur): + + f=open(loc2,'wb') + Origine_en_haut_a_gauche=32 + Origine_en_bas_a_gauche=0 + Data_Type_2=2 + RVB=profondeur*8 + RVBA=32 + entete0=[] + for t in range(18): + entete0.append(chr(0)) + + entete0[2]=chr(Data_Type_2) + entete0[13]=chr(width/256) + entete0[12]=chr(width % 256) + entete0[15]=chr(height/256) + entete0[14]=chr(height % 256) + entete0[16]=chr(RVB) + entete0[17]=chr(Origine_en_bas_a_gauche) + + #Origine_en_haut_a_gauche + + for t in entete0: + f.write(t) + + for t in bitmap: + + for c in [2,1,0,3]: + #print t[c]%256 + f.write(chr(t[c]*2)) + f.close() + + +def save(x0,y0,dx,dy): + im = Buffer(GL_BYTE,[dx*(dy+1),4]) + glReadPixels(x0,y0,dx,dy,GL_RGBA, GL_BYTE,im); + print len(im), dx*dy, dx, dy, len(im)/dy + write_tgafile(loc2,im,dx,dy+1,4) + +def DOCMat_list(TMATList,ME): + me=Blender.NMesh.GetRaw(ME.getData().name) + if len(me.materials)!=0: + n=0 + for mat in me.materials: + TMATList[1][n][0]=mat.R + TMATList[1][n][1]=mat.G + TMATList[1][n][2]=mat.B + n+=1 + TMATList[0]=n + else: + TMATList[0]=0 + return TMATList + +def SELMat_list(): + global TMATList,selmatlist + Me=Blender.Object.GetSelected() + if Me!=[]: + if Me[0].getType()=='Mesh': + TMATList=DOCMat_list(TMATList,Me[0]) + selmatlist=[] + for TMat in TMATList[2]: + if TMat.val==1.0: + selmatlist.append(TMATList[2].index(TMat)) + ERROR=0 + else: + ERROR=1 + TextERROR='Selected Object is not a mesh.' + else: + ERROR=1 + TextERROR='No Selected Object.' + +def DOCBONEMENU(TBONEMENU): + pass + +# ---------- +# uvpaint1 +# ---------- +NSIZE=Create(1.0) +# ---------- +# uvpaint2 +# ---------- +LINE=Create(0) +# ---------- +# uvpaint3 +# ---------- +TEXT=Create(loc2) +# ---------- +# uvpaint4 +# ---------- +TMENU="MODE MENU %t|All %x1|Material %x2|Selected %x3" + +# coming soon : "|Bone %x4", perhaps in uvpainter v0.5 + +MMENU=Create(3) +TDOCMat = Create(0) +# ---------- +TMATList= [0,[],[]] +for t in range(16): + TMATList[1].append([0.0,0.0,0.0]) + TMATList[2].append(Create(0)) +# ---------- +TDOCMat = Create(1) +# ---------- +TBONEMENU= Create(1) +# ---------- + +XLIMIT=Create(0) + +y=0 +x=0 +x0=0 +y0=0 +xwin=0 + +n0=32 + +def draw(): + global NSIZE,LINE,x0,y0,y,x,TEXT,MMENU,TDOCMat + global XLIMIT,selmatlist,xwin + + 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]) + + n0=32 + x0=size[0] + y0=size[1] + + x=size[2] + y=size[3] + + xwin=x + ywin=y + + + glClear(GL_COLOR_BUFFER_BIT) + + glShadeModel(GL_SMOOTH) + SelecMESH=Blender.Object.GetSelected() + if SelecMESH!=[]: + if SelecMESH[0].getType()=='Mesh': + affiche_mesh(SelecMESH[0],int(y*NSIZE.val),int(y*NSIZE.val-n0-2)) + + glColor3f(0.0,0.0,0.0) + glRectf(4,size[3],555,size[3]-32 ) + + glColor3f(1.0,1.0,1.0) + + glRasterPos2f(8, size[3]-13) + Text("uvpainter v0.5") + + glRasterPos2f(8, size[3]-28) + Text("Jm Soler, 05/2004") + + Button("ReDraw" ,16 ,290-118+61 ,size[3]-30 ,60 ,13) + Button("Exit" ,1 ,250-122+63 ,size[3]-30 ,38 ,13) + Button("Save" ,6 ,250-16+61 ,size[3]-30 ,40 ,13) + + NSIZE= Slider("Sc:",4 ,290-118+61 ,size[3]-15 , 102, 13, NSIZE.val, 0.1,1.5,0,"SIZE.") + LINE=Toggle("line", 5 ,250-122+63 ,size[3]-15 , 38, 13, LINE.val, "Draw lines") + + glRasterPos2f(250-130 ,size[3]-13,) + Text("Mode") + + MMENU= Menu(TMENU ,2 ,250-130, size[3]-30, 63, 13, MMENU.val, "MODE menu.") + + if MMENU.val==1 or MMENU.val==3: + glRasterPos2f( 250-16+61+42+80,size[3]-13) + if XLIMIT.val: + xl=xwin + else: + xl=xlimit + + Text("x :"+"%d"%(xl+2)) + + glRasterPos2f(250-16+61+42+65*2,size[3]-13) + Text("y :"+"%d"%(y-n0+1)) + + TEXT=String("to:", 7 , 278+61 ,size[3]-28 , 213, 13, TEXT.val, 256, "Draw lines") + if XLIMIT.val==1: + limit='winlimit' + else: + limit='maxXlimit' + XLIMIT=Toggle(limit, 9 , 250-16+61+42 ,size[3]-15 , 60, 13, XLIMIT.val, "to save picture from x max uv limit, or x window max limit") + + if MMENU.val==2: + TDOCMat=Toggle("doc" ,24,250-130+35 ,size[3]-13 , 28, 13, TDOCMat.val) + if TDOCMat.val==1: + SELMat_list() + for t in range(TMATList[0]): + glCl3(TMATList[1][t][0], + TMATList[1][t][1], + TMATList[1][t][2]) + glRct((293-16+61)+t*20, + size[3]-13, + (293-16+61)+t*20+20, + size[3]-30,) + TMATList[2][t]=Toggle("%s"%t , 32+t ,(293-16+61)+t*20 ,size[3]-13 ,20 , 13,TMATList[2][t].val) + + + +def event(evt, val): + if (evt== QKEY and not val): Exit() + +def bevent(evt): + global LINE,NSIZE,n0,x0,y0,y,TEXT, loc2 + global TMATList, selmatlist, TDOCMat,XLIMIT + global xlimit + + if (evt== 1): + Exit() + + elif (evt== 16): + pass + + elif (evt== 4): + ng=NSIZE.val + + elif (evt== 6): + if XLIMIT.val==1: + xi=xwin + else: + xi=xlimit + + save(x0,y0,xi+2,int(y*NSIZE.val-n0)) + + elif (evt== 7): + if exist(TEXT.val): + loc2=TEXT.val + else: + TEXT.val=loc2 + + elif (evt== 24) or (evt in [32,33,34,35,36,37,38,39,40,41,42,43,44]): + SELMat_list() + + + Blender.Redraw() + +Register(draw, event, bevent) diff --git a/release/scripts/ac3d_export.py b/release/scripts/ac3d_export.py index 6a464767c4c..04da0d38cab 100644 --- a/release/scripts/ac3d_export.py +++ b/release/scripts/ac3d_export.py @@ -16,7 +16,7 @@ Tip: 'Export to AC3D (.ac) format.' # -------------------------------------------------------------------------- # ***** BEGIN GPL LICENSE BLOCK ***** # -# Copyright (C) 2004: Willian P. Germano, wgermano@ig.com.br +# Copyright (C) 2004: Willian P. Germano, wgermano _at_ ig.com.br # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License diff --git a/release/scripts/ac3d_import.py b/release/scripts/ac3d_import.py index 3e3d08a1155..3dc8af7ad2c 100644 --- a/release/scripts/ac3d_import.py +++ b/release/scripts/ac3d_import.py @@ -13,7 +13,7 @@ Tip: 'Import an AC3D (.ac) file.' # -------------------------------------------------------------------------- # ***** BEGIN GPL LICENSE BLOCK ***** # -# Copyright (C) 2004: Willian P. Germano, wgermano@ig.com.br +# Copyright (C) 2004: Willian P. Germano, wgermano _at_ ig.com.br # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License diff --git a/release/scripts/disp_paint233f.py b/release/scripts/disp_paint233f.py new file mode 100644 index 00000000000..cf60f4ecfae --- /dev/null +++ b/release/scripts/disp_paint233f.py @@ -0,0 +1,329 @@ +#!BPY + +""" Registration info for Blender menus: <- these words are ignored +Name: 'Dispaint' +Blender: 233 +Group: 'Modifiers' +Tip: 'use vertex paint color value to modify shape displacing vertices along normal.' +""" + +#---------------------------------------------- +# jm soler, displacement paint 03/2002 - > 05/2004: disp_paintf +#---------------------------------------------- +# Official page : +# http://jmsoler.free.fr/didacticiel/blender/tutor/cpl_displacementpainting.htm +#---------------------------------------------- +# Communicate problems and errors on: +# http://www.zoo-logique.org/3D.Blender/newsportal/thread.php?group=3D.Blender +#--------------------------------------------- +# this script is released under GPL licence +# for the Blender 2.33 scripts package +#---------------------------------------------- +# Page officielle : +# http://jmsoler.free.fr/didacticiel/blender/tutor/cpl_displacementpainting.htm +# Communiquer les problemes et erreurs sur: +# http://www.zoo-logique.org/3D.Blender/newsportal/thread.php?group=3D.Blender +#--------------------------------------------- +# ce script est proposé sous licence GPL pour etre associe +# a la distribution de Blender 2.33 +#---------------------------------------------- + +import Blender +from Blender import * +from Blender.Draw import * +from Blender.BGL import * + + +# niveau du deplacement +ng=0.5 + +# profondeur des couleurs primaires rgb +maxcol=255.0*3 + +# limitation de la zone de travail sur le +# le materiau numer mat du tableau d'indices +# des materiaux. Par defaut mat =-1 ce qui signifie +# que toute la surface est traitee +mat=[] +vindex=[] +ORIName='' +NEWName='' +ERROR=0 +TextERROR='' + +def copy_transform(ozero,Obis): + Obis.setSize(ozero.getSize()); + Obis.setEuler(ozero.getEuler()); + Obis.setLocation(ozero.getLocation()) + return Obis + +def traite_face(f): + global vindexm + if ORIENTMenu.val==1: + for z in range(len(f.v)): + c=0.0 + if vindex[f.v[z].index]!=0: + c=float(f.col[z].r+f.col[z].b+f.col[z].g)/maxcol*ng/vindex[f.v[z].index] + else: + c=0 + + f.v[z].co[0]=f.v[z].co[0]+f.v[z].no[0]*c + f.v[z].co[1]=f.v[z].co[1]+f.v[z].no[1]*c + f.v[z].co[2]=f.v[z].co[2]+f.v[z].no[2]*c + + if ORIENTMenu.val==2: + for z in range(len(f.v)): + c=0.0 + if vindex[f.v[z].index]!=0: + c=float(f.col[z].r+f.col[z].b+f.col[z].g)/maxcol*ng/vindex[f.v[z].index] + else: + c=0 + for t in range(3): + if TAXEList[1][t].val==1: + f.v[z].co[t]=f.v[z].co[t]+c + + +def paint(): + global MODEMenu, vindex,ng, mat, ORIName, NEWName + + Me=Object.GetSelected() + if Me!=[]: + if Me[0].getType()=='Mesh': + + vindex=[] + ORIName=Me[0].getData().name + me=NMesh.GetRaw(Me[0].getData().name) + + name='new.002' + + for m in me.verts: + vindex.append(0) + + for f in me.faces: + for v in f.v: + if MODEMenu.val!=2: + if MODEMenu.val==1: + vindex[v.index]+=1 + else: + if v.sel==1: + vindex[v.index]+=1 + else: + #print mat + if f.mat in mat: + vindex[v.index]+=1 + + for f in me.faces: + if MODEMenu.val==2: + if f.mat in mat: + traite_face(f) + else: + traite_face(f) + + NMesh.PutRaw(me,name) + + if name!=Object.GetSelected()[0].getData().name: + obj=Object.Get() + for o in obj: + if o.getType()=='Mesh': + if o.getData().name==name: + o.makeDisplayList() + + o=copy_transform(Me[0],o) + """ + o.setEuler(Me[0].getEuler()) + o.setLocation(Me[0].getLocation()) + """ + + else: + Me[0].makeDisplayList() + +def NEWMEcreation(name): + nomdelobjet=""; objnumber=-1; namelist=[] + obj=Object.Get() + + for ozero in obj: + if ozero.getType()=='Mesh': + namelist.append(ozero.getData().name) + if ozero.getData().name==name: + objnumber=obj.index(ozero) + + if objnumber!=-1: + ozero=obj[objnumber] + nomdelobjet=ozero.getName() + Mesh=Blender.NMesh.GetRawFromObject(nomdelobjet) + + n=0; name2=name[:];ok=0 + + while ok==0: + for n0 in namelist: + if n0.find(name2)==0: + ok=0;name2=name[0:name.find('.')+1]+'%s'%(n+1) + else: ok=1 + n+=1 + Mesh.name=name2 + Obis = Blender.NMesh.PutRaw(Mesh,name2) + copy_transform(ozero,Obis) + Obis.makeDisplayList() + +def DOCMat_list(TMATList): + global mat + Me=Object.GetSelected() + if Me!=[]: + if Me[0].getType()=='Mesh': + me=NMesh.GetRaw(Me[0].getData().name) + if len(me.materials)!=0: + n=0 + for mat in me.materials: + TMATList[1][n][0]=mat.R + TMATList[1][n][1]=mat.G + TMATList[1][n][2]=mat.B + n+=1 + TMATList[0]=n + else: + TMATList[0]=0 + return TMATList + +MOname = "MODE MENU %t|Normal %x1|Material %x2|Selected %x3" +ORname = "ORIENT MENU %t|From Normal %x1|Local Axes %x2" + +MODEMenu = Create(1) +ORIENTMenu = Create(1) +NSIZE = Create(1.0) +TDOCMat = Create(0) +NRepeat = Create(1) + +TMATList= [0,[],[]] + +for t in range(16): + TMATList[1].append([0.0,0.0,0.0]) + TMATList[2].append(Create(0)) + +TAXEList=[['X','Y','Z'],[]] +for t in range(3): + TAXEList[1].append(Create(0)) + +glCr=glRasterPos2d +glCl3=glColor3f +glCl4=glColor4f +glRct=glRectf + + + +def draw(): + global MODEMenu, NSIZE, TDOCMat,TMATList, TAXEList + global mat, ORIName, NEWName, ORIENTMenu + global NRepeat, ERROR, TextERROR + + 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]) + + glClear(GL_COLOR_BUFFER_BIT) + + glColor3f(0.0,0.0,0.0) + glRectf(4,size[3],534,size[3]-32 ) + + glColor3f(1.0,1.0,1.0) + glRasterPos2f(20, size[3]-15) + Text("Script Python de displacement paintingt") + + glRasterPos2f(20, size[3]-28) + Text("Jean-michel Soler, avril 2004") + + + n0=70 + n1=55 + + Button("Create" ,17 ,5 ,size[3]-n0+16 ,60 ,20) + Button("Action" ,16 ,5 ,size[3]-n0-4 ,60 ,20) + Button("Exit" ,1 ,5 ,size[3]-n0-24 ,60 ,20) + + NRepeat=Number("repeat" ,5 ,5 ,size[3]-n0-50 ,75 ,20, NRepeat.val,1,10) + + glColor3f(0.0,0.0,0.0) + glRasterPos2f(80 ,size[3]-n0+24) + Text("MODE") + + MODEMenu= Menu(MOname, 2 ,80 ,size[3]-n0 ,100,20, MODEMenu.val, "MODE menu.") + + if MODEMenu.val==2: + TDOCMat=Toggle("Doc Mat" ,24 ,180 ,size[3]-n0 ,60 ,20,TDOCMat.val) + if TDOCMat.val==1: + #print TMATList + for t in range(TMATList[0]): + glCl3(TMATList[1][t][0], + TMATList[1][t][1], + TMATList[1][t][2]) + glRct(80+t*40, + size[3]-n0-60, + 80+t*40+40, + size[3]-n0-60+40) + TMATList[2][t]=Toggle("%s"%t , 32+t ,80+t*40+5 ,size[3]-n0-50 ,30 , 20,TMATList[2][t].val) + glColor3f(1.0,0.3,0.0) + glRasterPos2f(80+40+5 ,size[3]-n0-80) + if ERROR==1: + Text('Last error : '+TextERROR) + else: + Text('Last error : ') + + glColor3f(0.0,0.0,0.0) + glRasterPos2f(240 ,size[3]-n0+24) + Text("ORIENTATION") + + ORIENTMenu= Menu(ORname, 3 ,240 ,size[3]-n0 ,100,20, ORIENTMenu.val, "MODE menu.") + if ORIENTMenu.val>1: + for t in range(3): + TAXEList[1][t]=Toggle("%s"%TAXEList[0][t], + 40+t, + 240+100+t*30 , size[3]-n0 ,30 , 20, + TAXEList[1][t].val) + + NSIZE= Slider("Disp Size", 4 ,80 ,size[3]-n0-20 ,260,20, NSIZE.val, -4.0,+4.0,0,"SIZE.") + + + + +def event(evt, val): + if (evt== QKEY and not val): Exit() + +def bevent(evt): + global MODEMenu, NSIZE, ng, TMATList + global mat, ORIENTMenu, NRepeat, TAXEList + global ERROR,TextERROR + + if (evt== 1): + Exit() + + + elif (evt== 16): + for n in range(NRepeat.val): + paint() + + elif (evt== 4): + ng=NSIZE.val + + elif (evt== 24) or (evt in [32,33,34,35,36,37,38,39,40,41,42,43,44]): + Me=Object.GetSelected() + if Me!=[]: + if Me[0].getType()=='Mesh': + TMATList=DOCMat_list(TMATList) + mat=[] + for TMat in TMATList[2]: + if TMat.val==1.0: + mat.append(TMATList[2].index(TMat)) + ERROR=0 + else: + ERROR=1 + TextERROR='Selected Object is not a mesh.' + else: + ERROR=1 + TextERROR='No Selected Object.' + + elif (evt== 17): + NEWMEcreation('new.002') + + Blender.Redraw() + +Register(draw, event, bevent) diff --git a/release/scripts/fixfromarmature.py b/release/scripts/fixfromarmature.py new file mode 100644 index 00000000000..564e56ff66e --- /dev/null +++ b/release/scripts/fixfromarmature.py @@ -0,0 +1,37 @@ +#!BPY + +""" Registration info for Blender menus: <- these words are ignored +Name: 'Fix from Armature' +Blender: 232 +Group: 'Generators' +Tip: 'Fix armature deformation.' +""" + +#---------------------------------------------- +# jm soler 05/2004 : 'FixfromArmature' +#---------------------------------------------- +# Official Page : +# http://jmsoler.free.fr/util/blenderfile/py/fixfromarmature.py +# Communicate problems and errors on: +# http://www.zoo-logique.org/3D.Blender/newsportal/thread.php?group=3D.Blender +#--------------------------------------------- +# Page officielle : +# http://jmsoler.free.fr/util/blenderfile/py/fixfromarmature.py +# Communiquer les problemes et erreurs sur: +# http://www.zoo-logique.org/3D.Blender/newsportal/thread.php?group=3D.Blender +#--------------------------------------------- + +import Blender +try: + Ozero=Blender.Object.GetSelected()[0] + nomdelobjet=Ozero.getName() + Mesh=Blender.NMesh.GetRawFromObject(nomdelobjet) + Obis = Blender.Object.New ('Mesh') + Obis.link(Mesh) + Obis.setSize(Ozero.getSize()) + Obis.setEuler(Ozero.getEuler()) + Obis.setLocation(Ozero.getMatrix()[3][0:3]) + scene = Blender.Scene.getCurrent() + scene.link (Obis) +except: + print "not a mesh or no object selected" diff --git a/release/scripts/lightwave_export.py b/release/scripts/lightwave_export.py new file mode 100644 index 00000000000..6ed96300673 --- /dev/null +++ b/release/scripts/lightwave_export.py @@ -0,0 +1,528 @@ +#!BPY + +""" +Name: 'LightWave...' +Blender: 232 +Group: 'Export' +Tooltip: 'Export selected meshes to LightWave File Format (*.lwo)' +""" + +# +---------------------------------------------------------+ +# | Copyright (c) 2002 Anthony D'Agostino | +# | 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) | +# +---------------------------------------------------------+ + +import Blender, mod_meshtools +import struct, chunk, os, cStringIO, time, operator + +# ============================== +# === Write LightWave Format === +# ============================== +def write(filename): + start = time.clock() + file = open(filename, "wb") + + objects = Blender.Object.GetSelected() + objects.sort(lambda a,b: cmp(a.name, b.name)) + if not objects: + mod_meshtools.print_boxed("No mesh objects are selected.") + return + + if len(objects) > 20 and mod_meshtools.show_progress: + mod_meshtools.show_progress = 0 + + text = generate_text() + desc = generate_desc() + icon = "" #generate_icon() + + material_names = get_used_material_names(objects) + tags = generate_tags(material_names) + surfs = generate_surfs(material_names) + chunks = [text, desc, icon, tags] + + meshdata = cStringIO.StringIO() + layer_index = 0 + for object in objects: + objname = object.name + meshname = object.data.name + mesh = Blender.NMesh.GetRaw(meshname) + #mesh = Blender.NMesh.GetRawFromObject(meshname) # for SubSurf + obj = Blender.Object.Get(objname) + if not mesh: continue + + layr = generate_layr(objname, layer_index) + pnts = generate_pnts(mesh, obj.matrix) + bbox = generate_bbox(mesh) + pols = generate_pols(mesh) + ptag = generate_ptag(mesh, material_names) + + if mesh.hasFaceUV(): + vmad_uv = generate_vmad_uv(mesh) # per face + + if mod_meshtools.has_vertex_colors(mesh): + if mod_meshtools.average_vcols: + vmap_vc = generate_vmap_vc(mesh) # per vert + else: + vmad_vc = generate_vmad_vc(mesh) # per face + + write_chunk(meshdata, "LAYR", layr); chunks.append(layr) + write_chunk(meshdata, "PNTS", pnts); chunks.append(pnts) + write_chunk(meshdata, "BBOX", bbox); chunks.append(bbox) + write_chunk(meshdata, "POLS", pols); chunks.append(pols) + write_chunk(meshdata, "PTAG", ptag); chunks.append(ptag) + + if mesh.hasFaceUV(): + write_chunk(meshdata, "VMAD", vmad_uv) + chunks.append(vmad_uv) + + if mod_meshtools.has_vertex_colors(mesh): + if mod_meshtools.average_vcols: + write_chunk(meshdata, "VMAP", vmap_vc) + chunks.append(vmap_vc) + else: + write_chunk(meshdata, "VMAD", vmad_vc) + chunks.append(vmad_vc) + layer_index += 1 + + for surf in surfs: + chunks.append(surf) + + write_header(file, chunks) + write_chunk(file, "ICON", icon) + write_chunk(file, "TEXT", text) + write_chunk(file, "DESC", desc) + write_chunk(file, "TAGS", tags) + file.write(meshdata.getvalue()); meshdata.close() + for surf in surfs: + write_chunk(file, "SURF", surf) + + Blender.Window.DrawProgressBar(1.0, "") # clear progressbar + file.close() + print '\a\r', + end = time.clock() + seconds = " in %.2f %s" % (end-start, "seconds") + message = "Successfully exported " + os.path.basename(filename) + seconds + mod_meshtools.print_boxed(message) + +# ======================================= +# === Generate Null-Terminated String === +# ======================================= +def generate_nstring(string): + if len(string)%2 == 0: # even + string += "\0\0" + else: # odd + string += "\0" + return string + +# =============================== +# === Get Used Material Names === +# =============================== +def get_used_material_names(objects): + matnames = {} + for object in objects: + objname = object.name + meshname = object.data.name + mesh = Blender.NMesh.GetRaw(meshname) + if not mesh: continue + if (not mesh.materials) and (mod_meshtools.has_vertex_colors(mesh)): + # vcols only + if mod_meshtools.average_vcols: + matnames["\251 Per-Vert Vertex Colors"] = None + else: + matnames["\251 Per-Face Vertex Colors"] = None + elif (mesh.materials) and (not mod_meshtools.has_vertex_colors(mesh)): + # materials only + for material in mesh.materials: + matnames[material.name] = None + elif (not mesh.materials) and (not mod_meshtools.has_vertex_colors(mesh)): + # neither + matnames["\251 Blender Default"] = None + else: + # both + for material in mesh.materials: + matnames[material.name] = None + return matnames + +# ========================================= +# === Generate Tag Strings (TAGS Chunk) === +# ========================================= +def generate_tags(material_names): + material_names = map(generate_nstring, material_names.keys()) + tags_data = reduce(operator.add, material_names) + return tags_data + +# ======================== +# === Generate Surface === +# ======================== +def generate_surface(name, mesh): + if name.find("\251 Per-") == 0: + return generate_vcol_surf(mesh) + elif name == "\251 Blender Default": + return generate_default_surf() + else: + return generate_surf(name) + +# ====================== +# === Generate Surfs === +# ====================== +def generate_surfs(material_names): + keys = material_names.keys() + values = material_names.values() + surfaces = map(generate_surface, keys, values) + return surfaces + +# =================================== +# === Generate Layer (LAYR Chunk) === +# =================================== +def generate_layr(name, idx): + data = cStringIO.StringIO() + data.write(struct.pack(">h", idx)) # layer number + data.write(struct.pack(">h", 0)) # flags + data.write(struct.pack(">fff", 0, 0, 0)) # pivot + data.write(generate_nstring(name)) # name + return data.getvalue() + +# =================================== +# === Generate Verts (PNTS Chunk) === +# =================================== +def generate_pnts(mesh, matrix): + data = cStringIO.StringIO() + for i in range(len(mesh.verts)): + if not i%100 and mod_meshtools.show_progress: + Blender.Window.DrawProgressBar(float(i)/len(mesh.verts), "Writing Verts") + x, y, z = mod_meshtools.apply_transform(mesh.verts[i].co, matrix) + data.write(struct.pack(">fff", x, z, y)) + return data.getvalue() + +# ========================================== +# === Generate Bounding Box (BBOX Chunk) === +# ========================================== +def generate_bbox(mesh): + data = cStringIO.StringIO() + # need to transform verts here + nv = map(getattr, mesh.verts, ["co"]*len(mesh.verts)) + xx = map(operator.getitem, nv, [0]*len(nv)) + yy = map(operator.getitem, nv, [1]*len(nv)) + zz = map(operator.getitem, nv, [2]*len(nv)) + data.write(struct.pack(">6f", min(xx), min(zz), min(yy), max(xx), max(zz), max(yy))) + return data.getvalue() + +# ======================================== +# === Average All Vertex Colors (Fast) === +# ======================================== +def average_vertexcolors(mesh): + vertexcolors = {} + vcolor_add = lambda u, v: [u[0]+v[0], u[1]+v[1], u[2]+v[2], u[3]+v[3]] + vcolor_div = lambda u, s: [u[0]/s, u[1]/s, u[2]/s, u[3]/s] + for i in range(len(mesh.faces)): # get all vcolors that share this vertex + if not i%100 and mod_meshtools.show_progress: + Blender.Window.DrawProgressBar(float(i)/len(mesh.verts), "Finding Shared VColors") + for j in range(len(mesh.faces[i].v)): + index = mesh.faces[i].v[j].index + color = mesh.faces[i].col[j] + r,g,b,a = color.r, color.g, color.b, color.a + vertexcolors.setdefault(index, []).append([r,g,b,a]) + for i in range(len(vertexcolors)): # average them + if not i%100 and mod_meshtools.show_progress: + Blender.Window.DrawProgressBar(float(i)/len(mesh.verts), "Averaging Vertex Colors") + vcolor = [0,0,0,0] # rgba + for j in range(len(vertexcolors[i])): + vcolor = vcolor_add(vcolor, vertexcolors[i][j]) + shared = len(vertexcolors[i]) + vertexcolors[i] = vcolor_div(vcolor, shared) + return vertexcolors + +# ==================================================== +# === Generate Per-Vert Vertex Colors (VMAP Chunk) === +# ==================================================== +def generate_vmap_vc(mesh): + data = cStringIO.StringIO() + data.write("RGB ") # type + data.write(struct.pack(">H", 3)) # dimension + data.write(generate_nstring("Blender's Vertex Colors")) # name + vertexcolors = average_vertexcolors(mesh) + for i in range(len(vertexcolors)): + r, g, b, a = vertexcolors[i] + data.write(struct.pack(">H", i)) # vertex index + data.write(struct.pack(">fff", r/255.0, g/255.0, b/255.0)) + return data.getvalue() + +# ==================================================== +# === Generate Per-Face Vertex Colors (VMAD Chunk) === +# ==================================================== +def generate_vmad_vc(mesh): + data = cStringIO.StringIO() + data.write("RGB ") # type + data.write(struct.pack(">H", 3)) # dimension + data.write(generate_nstring("Blender's Vertex Colors")) # name + for i in range(len(mesh.faces)): + if not i%100 and mod_meshtools.show_progress: + Blender.Window.DrawProgressBar(float(i)/len(mesh.faces), "Writing Vertex Colors") + numfaceverts = len(mesh.faces[i].v) + for j in range(numfaceverts-1, -1, -1): # Reverse order + r = mesh.faces[i].col[j].r + g = mesh.faces[i].col[j].g + b = mesh.faces[i].col[j].b + v = mesh.faces[i].v[j].index + data.write(struct.pack(">H", v)) # vertex index + data.write(struct.pack(">H", i)) # face index + data.write(struct.pack(">fff", r/255.0, g/255.0, b/255.0)) + return data.getvalue() + +# ================================================ +# === Generate Per-Face UV Coords (VMAD Chunk) === +# ================================================ +def generate_vmad_uv(mesh): + data = cStringIO.StringIO() + data.write("TXUV") # type + data.write(struct.pack(">H", 2)) # dimension + data.write(generate_nstring("Blender's UV Coordinates")) # name + for i in range(len(mesh.faces)): + if not i%100 and mod_meshtools.show_progress: + Blender.Window.DrawProgressBar(float(i)/len(mesh.faces), "Writing UV Coordinates") + numfaceverts = len(mesh.faces[i].v) + for j in range(numfaceverts-1, -1, -1): # Reverse order + U,V = mesh.faces[i].uv[j] + v = mesh.faces[i].v[j].index + data.write(struct.pack(">H", v)) # vertex index + data.write(struct.pack(">H", i)) # face index + data.write(struct.pack(">ff", U, V)) + return data.getvalue() + +# ====================================== +# === Generate Variable-Length Index === +# ====================================== +def generate_vx(index): + if index < 0xFF00: + value = struct.pack(">H", index) # 2-byte index + else: + value = struct.pack(">L", index | 0xFF000000) # 4-byte index + return value + +# =================================== +# === Generate Faces (POLS Chunk) === +# =================================== +def generate_pols(mesh): + data = cStringIO.StringIO() + data.write("FACE") # polygon type + for i in range(len(mesh.faces)): + if not i%100 and mod_meshtools.show_progress: + Blender.Window.DrawProgressBar(float(i)/len(mesh.faces), "Writing Faces") + data.write(struct.pack(">H", len(mesh.faces[i].v))) # numfaceverts + numfaceverts = len(mesh.faces[i].v) + for j in range(numfaceverts-1, -1, -1): # Reverse order + index = mesh.faces[i].v[j].index + data.write(generate_vx(index)) + return data.getvalue() + +# ================================================= +# === Generate Polygon Tag Mapping (PTAG Chunk) === +# ================================================= +def generate_ptag(mesh, material_names): + data = cStringIO.StringIO() + data.write("SURF") # polygon tag type + for i in range(len(mesh.faces)): # numfaces + if not i%100 and mod_meshtools.show_progress: + Blender.Window.DrawProgressBar(float(i)/len(mesh.faces), "Writing Surface Indices") + data.write(generate_vx(i)) + if (not mesh.materials) and (mod_meshtools.has_vertex_colors(mesh)): # vcols only + if mod_meshtools.average_vcols: + name = "\251 Per-Vert Vertex Colors" + else: + name = "\251 Per-Face Vertex Colors" + elif (mesh.materials) and (not mod_meshtools.has_vertex_colors(mesh)): # materials only + idx = mesh.faces[i].mat #erialIndex + name = mesh.materials[idx].name + elif (not mesh.materials) and (not mod_meshtools.has_vertex_colors(mesh)): # neither + name = "\251 Blender Default" + else: # both + idx = mesh.faces[i].mat + name = mesh.materials[idx].name + names = material_names.keys() + surfidx = names.index(name) + data.write(struct.pack(">H", surfidx)) # surface index + return data.getvalue() + +# =================================================== +# === Generate VC Surface Definition (SURF Chunk) === +# =================================================== +def generate_vcol_surf(mesh): + data = cStringIO.StringIO() + if mod_meshtools.average_vcols and mod_meshtools.has_vertex_colors(mesh): + surface_name = generate_nstring("\251 Per-Vert Vertex Colors") + else: + surface_name = generate_nstring("\251 Per-Face Vertex Colors") + data.write(surface_name) + data.write("\0\0") + + data.write("COLR") + data.write(struct.pack(">H", 14)) + data.write(struct.pack(">fffH", 1, 1, 1, 0)) + + data.write("DIFF") + data.write(struct.pack(">H", 6)) + data.write(struct.pack(">fH", 0.0, 0)) + + data.write("LUMI") + data.write(struct.pack(">H", 6)) + data.write(struct.pack(">fH", 1.0, 0)) + + data.write("VCOL") + data.write(struct.pack(">H", 34)) + data.write(struct.pack(">fH4s", 1.0, 0, "RGB ")) # intensity, envelope, type + data.write(generate_nstring("Blender's Vertex Colors")) # name + + data.write("CMNT") # material comment + comment = "Vertex Colors: Exported from Blender\256 " + mod_meshtools.blender_version_str + comment = generate_nstring(comment) + data.write(struct.pack(">H", len(comment))) + data.write(comment) + return data.getvalue() + +# ================================================ +# === Generate Surface Definition (SURF Chunk) === +# ================================================ +def generate_surf(material_name): + data = cStringIO.StringIO() + data.write(generate_nstring(material_name)) + data.write("\0\0") + + material = Blender.Material.Get(material_name) + R,G,B = material.R, material.G, material.B + data.write("COLR") + data.write(struct.pack(">H", 14)) + data.write(struct.pack(">fffH", R, G, B, 0)) + + data.write("DIFF") + data.write(struct.pack(">H", 6)) + data.write(struct.pack(">fH", material.ref, 0)) + + data.write("LUMI") + data.write(struct.pack(">H", 6)) + data.write(struct.pack(">fH", material.emit, 0)) + + data.write("SPEC") + data.write(struct.pack(">H", 6)) + data.write(struct.pack(">fH", material.spec, 0)) + + data.write("GLOS") + data.write(struct.pack(">H", 6)) + gloss = material.hard / (255/2.0) + gloss = round(gloss, 1) + data.write(struct.pack(">fH", gloss, 0)) + + data.write("CMNT") # material comment + comment = material_name + ": Exported from Blender\256 " + mod_meshtools.blender_version_str + comment = generate_nstring(comment) + data.write(struct.pack(">H", len(comment))) + data.write(comment) + return data.getvalue() + +# ============================================= +# === Generate Default Surface (SURF Chunk) === +# ============================================= +def generate_default_surf(): + data = cStringIO.StringIO() + material_name = "\251 Blender Default" + data.write(generate_nstring(material_name)) + data.write("\0\0") + + data.write("COLR") + data.write(struct.pack(">H", 14)) + data.write(struct.pack(">fffH", 1, 1, 1, 0)) + + data.write("DIFF") + data.write(struct.pack(">H", 6)) + data.write(struct.pack(">fH", 0.8, 0)) + + data.write("LUMI") + data.write(struct.pack(">H", 6)) + data.write(struct.pack(">fH", 0, 0)) + + data.write("SPEC") + data.write(struct.pack(">H", 6)) + data.write(struct.pack(">fH", 0.5, 0)) + + data.write("GLOS") + data.write(struct.pack(">H", 6)) + gloss = 50 / (255/2.0) + gloss = round(gloss, 1) + data.write(struct.pack(">fH", gloss, 0)) + + data.write("CMNT") # material comment + comment = material_name + ": Exported from Blender\256 " + mod_meshtools.blender_version_str + + # vals = map(chr, range(164,255,1)) + # keys = range(164,255,1) + # keys = map(lambda x: `x`, keys) + # comment = map(None, keys, vals) + # comment = reduce(operator.add, comment) + # comment = reduce(operator.add, comment) + + comment = generate_nstring(comment) + data.write(struct.pack(">H", len(comment))) + data.write(comment) + return data.getvalue() + +# ============================================ +# === Generate Object Comment (TEXT Chunk) === +# ============================================ +def generate_text(): + comment = "Lightwave Export Script for Blender " + comment += mod_meshtools.blender_version_str + "\n" + comment += "by Anthony D'Agostino\n" + comment += "scorpius@netzero.com\n" + comment += "http://ourworld.compuserve.com/homepages/scorpius\n" + return generate_nstring(comment) + +# ============================================== +# === Generate Description Line (DESC Chunk) === +# ============================================== +def generate_desc(): + comment = "Copyright 2002 Scorpius Entertainment" + return generate_nstring(comment) + +# ================================================== +# === Generate Thumbnail Icon Image (ICON Chunk) === +# ================================================== +def generate_icon(): + data = cStringIO.StringIO() + file = open("f:/obj/radiosity/lwo2_icon.tga", "rb") # 60x60 uncompressed TGA + file.read(18) + icon_data = file.read(3600) # ? + file.close() + data.write(struct.pack(">HH", 0, 60)) + data.write(icon_data) + #print len(icon_data) + return data.getvalue() + +# =================== +# === Write Chunk === +# =================== +def write_chunk(file, name, data): + file.write(name) + file.write(struct.pack(">L", len(data))) + file.write(data) + +# ============================= +# === Write LWO File Header === +# ============================= +def write_header(file, chunks): + chunk_sizes = map(len, chunks) + chunk_sizes = reduce(operator.add, chunk_sizes) + form_size = chunk_sizes + len(chunks)*8 + len("FORM") + file.write("FORM") + file.write(struct.pack(">L", form_size)) + file.write("LWO2") + +def fs_callback(filename): + if filename.find('.lwo', -4) <= 0: filename += '.lwo' + write(filename) + +Blender.Window.FileSelector(fs_callback, "LWO Export") diff --git a/release/scripts/lightwave_import.py b/release/scripts/lightwave_import.py new file mode 100644 index 00000000000..5bfef5c907a --- /dev/null +++ b/release/scripts/lightwave_import.py @@ -0,0 +1,172 @@ +#!BPY + +""" +Name: 'LightWave...' +Blender: 232 +Group: 'Import' +Tooltip: 'Import LightWave Object File Format (*.lwo)' +""" + +# +---------------------------------------------------------+ +# | Copyright (c) 2002 Anthony D'Agostino | +# | 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) | +# +---------------------------------------------------------+ + +import Blender, mod_meshtools +import struct, chunk, os, cStringIO, time, operator + +# ============================= +# === Read LightWave Format === +# ============================= +def read(filename): + start = time.clock() + file = open(filename, "rb") + + # === LWO header === + form_id, form_size, form_type = struct.unpack(">4s1L4s", file.read(12)) + if (form_type != "LWOB") and (form_type != "LWO2"): + print "Can't read a file with the form_type:", form_type + return + + objname = os.path.splitext(os.path.basename(filename))[0] + + while 1: + try: + lwochunk = chunk.Chunk(file) + except EOFError: + break + if lwochunk.chunkname == "LAYR": + objname = read_layr(lwochunk) + elif lwochunk.chunkname == "PNTS": # Verts + verts = read_verts(lwochunk) + elif lwochunk.chunkname == "POLS" and form_type == "LWO2": # Faces v6.0 + faces = read_faces_6(lwochunk) + mod_meshtools.create_mesh(verts, faces, objname) + elif lwochunk.chunkname == "POLS" and form_type == "LWOB": # Faces v5.5 + faces = read_faces_5(lwochunk) + mod_meshtools.create_mesh(verts, faces, objname) + else: # Misc Chunks + lwochunk.skip() + + Blender.Window.DrawProgressBar(1.0, "") # clear progressbar + file.close() + end = time.clock() + seconds = " in %.2f %s" % (end-start, "seconds") + if form_type == "LWO2": fmt = " (v6.0 Format)" + if form_type == "LWOB": fmt = " (v5.5 Format)" + message = "Successfully imported " + os.path.basename(filename) + fmt + seconds + mod_meshtools.print_boxed(message) + +# ================== +# === Read Verts === +# ================== +def read_verts(lwochunk): + data = cStringIO.StringIO(lwochunk.read()) + numverts = lwochunk.chunksize/12 + #$verts = [] + verts = [None] * numverts + for i in range(numverts): + if not i%100 and mod_meshtools.show_progress: + Blender.Window.DrawProgressBar(float(i)/numverts, "Reading Verts") + x, y, z = struct.unpack(">fff", data.read(12)) + #$verts.append((x, z, y)) + verts[i] = (x, z, y) + return verts + +# ================= +# === Read Name === +# ================= +def read_name(file): + name = "" + while 1: + char = file.read(1) + if char == "\0": break + else: name += char + return name + +# ================== +# === Read Layer === +# ================== +def read_layr(lwochunk): + data = cStringIO.StringIO(lwochunk.read()) + idx, flags = struct.unpack(">hh", data.read(4)) + pivot = struct.unpack(">fff", data.read(12)) + layer_name = read_name(data) + if not layer_name: layer_name = "No Name" + return layer_name + +# ====================== +# === Read Faces 5.5 === +# ====================== +def read_faces_5(lwochunk): + data = cStringIO.StringIO(lwochunk.read()) + faces = [] + i = 0 + while i < lwochunk.chunksize: + if not i%100 and mod_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): + index, = struct.unpack(">H", data.read(2)) + facev.append(index) + facev.reverse() + faces.append(facev) + surfaceindex, = struct.unpack(">H", data.read(2)) + if surfaceindex < 0: + print "detail polygons follow, error." + return + i += (4+numfaceverts*2) + return faces + +# ================================== +# === Read Variable-Length Index === +# ================================== +def read_vx(data): + byte1, = struct.unpack(">B", data.read(1)) + if byte1 != 0xFF: # 2-byte index + byte2, = struct.unpack(">B", data.read(1)) + index = byte1*256 + byte2 + index_size = 2 + else: # 4-byte index + byte2, byte3, byte4 = struct.unpack(">3B", data.read(3)) + index = byte2*65536 + byte3*256 + byte4 + index_size = 4 + return index, index_size + +# ====================== +# === Read Faces 6.0 === +# ====================== +def read_faces_6(lwochunk): + data = cStringIO.StringIO(lwochunk.read()) + faces = [] + polygon_type = data.read(4) + if polygon_type != "FACE": + print "No Faces Were Found. Polygon Type:", polygon_type + return "" + i = 0 + while(i < lwochunk.chunksize-4): + if not i%100 and mod_meshtools.show_progress: + Blender.Window.DrawProgressBar(float(i)/lwochunk.chunksize, "Reading Faces") + facev = [] + numfaceverts, = struct.unpack(">H", data.read(2)) + i += 2 + + for j in range(numfaceverts): + index, index_size = read_vx(data) + i += index_size + facev.append(index) + facev.reverse() + faces.append(facev) + return faces + +def fs_callback(filename): + read(filename) + +Blender.Window.FileSelector(fs_callback, "LWO Import") diff --git a/release/scripts/mod_flags.py b/release/scripts/mod_flags.py deleted file mode 100644 index 810a510181a..00000000000 --- a/release/scripts/mod_flags.py +++ /dev/null @@ -1,19 +0,0 @@ -# +---------------------------------------------------------+ -# | Copyright (c) 2002 Anthony D'Agostino | -# | http://ourworld.compuserve.com/homepages/scorpius | -# | scorpius@compuserve.com | -# | October 25, 2002 | -# | Released under the Blender Artistic Licence (BAL) | -# | Import Export Suite v0.5 | -# +---------------------------------------------------------+ -# | Share Global Variables Across Modules | -# +---------------------------------------------------------+ - -import Blender - -blender_version = Blender.Get('version') -blender_version_str = `blender_version`[0] + '.' + `blender_version`[1:] - -show_progress = 1 # Set to 0 for faster performance -average_vcols = 1 # Off for per-face, On for per-vertex -overwrite_mesh_name = 0 # Set to 0 for safety diff --git a/release/scripts/mod_meshtools.py b/release/scripts/mod_meshtools.py index dbcdab513d5..95dae16b562 100644 --- a/release/scripts/mod_meshtools.py +++ b/release/scripts/mod_meshtools.py @@ -1,88 +1,93 @@ # +---------------------------------------------------------+ # | Copyright (c) 2001 Anthony D'Agostino | -# | http://ourworld.compuserve.com/homepages/scorpius | -# | scorpius@compuserve. | +# | 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 For All Modules | +# | Common Functions & Global Variables For All IO Modules | # +---------------------------------------------------------+ import Blender -import sys#, random, operator -import mod_flags +import sys + +show_progress = 1 # Set to 0 for faster performance +average_vcols = 1 # Off for per-face, On for per-vertex +overwrite_mesh_name = 0 # Set to 0 to increment object-name version + +blender_version = Blender.Get('version') +blender_version_str = `blender_version`[0] + '.' + `blender_version`[1:] try: - import random, operator -# =================================== -# ==== Append Faces To Face List ==== -# =================================== - def append_faces(mesh, faces, facesuv, uvcoords): - r = random.randrange(200, 255, 50) - g = random.randrange(100, 200, 50) - b = random.randrange(0, 100, 50) - for i in range(len(faces)): - if not i%100 and mod_flags.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 + import operator +except: + msg = "Error: you need a full Python install to run this script." + mod_meshtools.print_boxed(msg) + Blender.Draw.PupMenu("ERROR%t|"+msg) + +# ================================= +# === Append Faces To Face List === +# ================================= +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 + face = Blender.NMesh.Face() + for j in range(numfaceverts): + index = faces[i][j] + face.v.append(mesh.verts[index]) + if len(uvcoords) > 1: + uvidx = facesuv[i][j] + face.uv.append(uvcoords[uvidx]) + face.mode = 0 + face.col = [Blender.NMesh.Col()]*4 + mesh.faces.append(face) + else: # Triangulate n-sided convex polygon. + a, b, c = 0, 1, 2 # Indices of first triangle. + for j in range(numfaceverts-2): # Number of triangles in polygon. face = Blender.NMesh.Face() - for j in range(numfaceverts): - index = faces[i][j] - face.v.append(mesh.verts[index]) - if len(uvcoords) > 1: - uvidx = facesuv[i][j] - face.uv.append(uvcoords[uvidx]) - face.mode = 0 - #face.col = [Blender.NMesh.Col(r, g, b)]*4 # Random color - face.col = [Blender.NMesh.Col()]*4 + face.v.append(mesh.verts[faces[i][a]]) + face.v.append(mesh.verts[faces[i][b]]) + face.v.append(mesh.verts[faces[i][c]]) + b = c; c += 1 mesh.faces.append(face) - else: # Triangulate n-sided convex polygon. - a, b, c = 0, 1, 2 # Indices of first triangle. - for j in range(numfaceverts-2): # Number of triangles in polygon. - face = Blender.NMesh.Face() - face.v.append(mesh.verts[faces[i][a]]) - face.v.append(mesh.verts[faces[i][b]]) - face.v.append(mesh.verts[faces[i][c]]) - b = c; c += 1 - mesh.faces.append(face) - #face.smooth = 1 - -# ===================================== -# ==== Append Verts to Vertex List ==== -# ===================================== - def append_verts(mesh, verts, normals): - #print "Number of normals:", len(normals) - #print "Number of verts :", len(verts) - for i in range(len(verts)): - if not i%100 and mod_flags.show_progress: Blender.Window.DrawProgressBar(float(i)/len(verts), "Generating Verts") - x, y, z = verts[i] - mesh.verts.append(Blender.NMesh.Vert(x, y, z)) - if normals: - mesh.verts[i].no[0] = normals[i][0] - mesh.verts[i].no[1] = normals[i][1] - mesh.verts[i].no[2] = normals[i][2] - -# ============================= -# ==== Create Blender Mesh ==== -# ============================= - def create_mesh(verts, faces, objname, facesuv=[], uvcoords=[], normals=[]): - if normals: normal_flag = 0 - else: normal_flag = 1 - mesh = Blender.NMesh.GetRaw() - append_verts(mesh, verts, normals) - append_faces(mesh, faces, facesuv, uvcoords) - if not mod_flags.overwrite_mesh_name: - objname = versioned_name(objname) - Blender.NMesh.PutRaw(mesh, objname, normal_flag) # Name the Mesh - Blender.Object.GetSelected()[0].name=objname # Name the Object - Blender.Redraw() - -except ImportError: pass + #face.smooth = 1 -# ================================ -# ==== Increment Name Version ==== -# ================================ +# =================================== +# === Append Verts to Vertex List === +# =================================== +def append_verts(mesh, verts, normals): + #print "Number of normals:", len(normals) + #print "Number of verts :", len(verts) + for i in range(len(verts)): + if not i%100 and show_progress: Blender.Window.DrawProgressBar(float(i)/len(verts), "Generating Verts") + x, y, z = verts[i] + mesh.verts.append(Blender.NMesh.Vert(x, y, z)) + if normals: + mesh.verts[i].no[0] = normals[i][0] + mesh.verts[i].no[1] = normals[i][1] + mesh.verts[i].no[2] = normals[i][2] + +# =========================== +# === Create Blender Mesh === +# =========================== +def create_mesh(verts, faces, objname, facesuv=[], uvcoords=[], normals=[]): + if normals: normal_flag = 0 + else: normal_flag = 1 + mesh = Blender.NMesh.GetRaw() + append_verts(mesh, verts, normals) + append_faces(mesh, faces, facesuv, uvcoords) + if not overwrite_mesh_name: + objname = versioned_name(objname) + Blender.NMesh.PutRaw(mesh, objname, normal_flag) # Name the Mesh + Blender.Object.GetSelected()[0].name=objname # Name the Object + Blender.Redraw() + +# ============================== +# === Increment Name Version === +# ============================== def versioned_name(objname): existing_names = [] for object in Blender.Object.Get(): @@ -104,35 +109,40 @@ def versioned_name(objname): break return objname -# ============================= -# ==== Print Text In A Box ==== -# ============================= +# =========================== +# === Print Text In A Box === +# =========================== def print_boxed(text): lines = text.splitlines() maxlinelen = max(map(len, lines)) - print '+-' + '-'*maxlinelen + '-+' - for line in lines: print '| ' + line.ljust(maxlinelen) + ' |' - print '+-' + '-'*maxlinelen + '-+' - + if sys.platform[:3] == "win": + print chr(218)+chr(196) + chr(196)*maxlinelen + chr(196)+chr(191) + for line in lines: + print chr(179) + ' ' + line.ljust(maxlinelen) + ' ' + chr(179) + print chr(192)+chr(196) + chr(196)*maxlinelen + chr(196)+chr(217) + else: + print '+-' + '-'*maxlinelen + '-+' + for line in lines: print '| ' + line.ljust(maxlinelen) + ' |' + print '+-' + '-'*maxlinelen + '-+' print '\a\r', # beep when done -# ================================================= -# ==== Get Euler Angles From A Rotation Matrix ==== -# ================================================= -#def mat2euler(mat): -# angle_y = -math.asin(mat[0][2]) -# c = math.cos(angle_y) -# if math.fabs(c) > 0.005: -# angle_x = math.atan2(mat[1][2]/c, mat[2][2]/c) -# angle_z = math.atan2(mat[0][1]/c, mat[0][0]/c) -# else: -# angle_x = 0.0 -# angle_z = -math.atan2(mat[1][0], mat[1][1]) -# return (angle_x, angle_y, angle_z) - -# ============================ -# ==== Transpose A Matrix ==== -# ============================ +# =============================================== +# === Get euler angles from a rotation matrix === +# =============================================== +def mat2euler(mat): + angle_y = -math.asin(mat[0][2]) + c = math.cos(angle_y) + if math.fabs(c) > 0.005: + angle_x = math.atan2(mat[1][2]/c, mat[2][2]/c) + angle_z = math.atan2(mat[0][1]/c, mat[0][0]/c) + else: + angle_x = 0.0 + angle_z = -math.atan2(mat[1][0], mat[1][1]) + return (angle_x, angle_y, angle_z) + +# ========================== +# === Transpose A Matrix === +# ========================== def transpose(A): S = len(A) T = len(A[0]) @@ -142,37 +152,177 @@ def transpose(A): B[i][j] = A[j][i] return B -#def append_ntimes(Seq, N): -# Seq = reduce(operator.add, Seq) # Flatten once -# if N == 1: return Seq -# return append_ntimes(Seq, N-1) - - - -# print "mesh.has_col ", mesh.has_col -# print "mesh.hasVertexColours()", mesh.hasVertexColours() -# print "mesh.hasFaceUV() ", mesh.hasFaceUV() -# print "mesh.has_uvco ", mesh.has_uvco - -# # ============================= -# # ==== Create Blender Mesh ==== -# # ============================= -# def create_mesh_old(verts, faces, objname): -# mesh = Blender.NMesh.GetRaw() -# # === Vertex List === -# for i in range(len(verts)): -# x, y, z = verts[i] -# mesh.verts.append(Blender.NMesh.Vert(x, y ,z)) -# # === Face List === -# for i in range(len(faces)): -# face = Blender.NMesh.Face() -# for j in range(len(faces[i])): -# index = faces[i][j] -# face.v.append(mesh.verts[index]) -# mesh.faces.append(face) -# # === Name the Object === -# Blender.NMesh.PutRaw(mesh, objname) -# object = Blender.Object.GetSelected() -# object[0].name=objname -# Blender.Redraw() +# ======================= +# === Apply Transform === +# ======================= +def apply_transform(vertex, matrix): + x, y, z = vertex + xloc, yloc, zloc = matrix[3][0], matrix[3][1], matrix[3][2] + xcomponent = x*matrix[0][0] + y*matrix[1][0] + z*matrix[2][0] + xloc + ycomponent = x*matrix[0][1] + y*matrix[1][1] + z*matrix[2][1] + yloc + zcomponent = x*matrix[0][2] + y*matrix[1][2] + z*matrix[2][2] + zloc + vertex = [xcomponent, ycomponent, zcomponent] + return vertex + +# ========================= +# === Has Vertex Colors === +# ========================= +def has_vertex_colors(mesh): + # My replacement/workaround for hasVertexColours() + # The docs say: + # "Warning: If a mesh has both vertex colours and textured faces, + # this function will return False. This is due to the way Blender + # deals internally with the vertex colours array (if there are + # textured faces, it is copied to the textured face structure and + # the original array is freed/deleted)." + try: + return mesh.faces[0].col[0] + except: + return 0 + +# =========================== +# === Generate Edge Table === +# =========================== +def generate_edgetable(mesh): + edge_table = {} + numfaces = len(mesh.faces) + + for i in range(numfaces): + if not i%100 and show_progress: + Blender.Window.DrawProgressBar(float(i)/numfaces, "Generating Edge Table") + if len(mesh.faces[i].v) == 4: # Process Quadrilaterals + generate_entry_from_quad(mesh, i, edge_table) + elif len(mesh.faces[i].v) == 3: # Process Triangles + generate_entry_from_tri(mesh, i, edge_table) + else: # Skip This Face + print "Face #", i, "was skipped." + + # === Sort Edge_Table Keys & Add Edge Indices === + i = 0 + keys = edge_table.keys() + keys.sort() + for key in keys: + edge_table[key][6] = i + i += 1 + + # === Replace Tuples With Indices === + for key in keys: + for i in [2,3,4,5]: + if edge_table.has_key(edge_table[key][i]): + edge_table[key][i] = edge_table[edge_table[key][i]][6] + else: + keyrev = (edge_table[key][i][1], edge_table[key][i][0]) + edge_table[key][i] = edge_table[keyrev][6] + + return edge_table + +# ================================ +# === Generate Entry From Quad === +# ================================ +def generate_entry_from_quad(mesh, i, edge_table): + vertex4, vertex3, vertex2, vertex1 = mesh.faces[i].v + + if has_vertex_colors(mesh): + vcolor4, vcolor3, vcolor2, vcolor1 = mesh.faces[i].col + Acol = (vcolor1.r/255.0, vcolor1.g/255.0, vcolor1.b/255.0) + Bcol = (vcolor2.r/255.0, vcolor2.g/255.0, vcolor2.b/255.0) + Ccol = (vcolor3.r/255.0, vcolor3.g/255.0, vcolor3.b/255.0) + Dcol = (vcolor4.r/255.0, vcolor4.g/255.0, vcolor4.b/255.0) + + # === verts are upper case, edges are lower case === + A, B, C, D = vertex1.index, vertex2.index, vertex3.index, vertex4.index + a, b, c, d = (A, B), (B, C), (C, D), (D, A) + + if edge_table.has_key((B, A)): + edge_table[(B, A)][1] = i + edge_table[(B, A)][4] = d + edge_table[(B, A)][5] = b + if has_vertex_colors(mesh): edge_table[(B, A)][8] = Bcol + else: + if has_vertex_colors(mesh): + edge_table[(A, B)] = [i, None, d, b, None, None, None, Bcol, None] + else: + edge_table[(A, B)] = [i, None, d, b, None, None, None] + + if edge_table.has_key((C, B)): + edge_table[(C, B)][1] = i + edge_table[(C, B)][4] = a + edge_table[(C, B)][5] = c + if has_vertex_colors(mesh): edge_table[(C, B)][8] = Ccol + else: + if has_vertex_colors(mesh): + edge_table[(B, C)] = [i, None, a, c, None, None, None, Ccol, None] + else: + edge_table[(B, C)] = [i, None, a, c, None, None, None] + + if edge_table.has_key((D, C)): + edge_table[(D, C)][1] = i + edge_table[(D, C)][4] = b + edge_table[(D, C)][5] = d + if has_vertex_colors(mesh): edge_table[(D, C)][8] = Dcol + else: + if has_vertex_colors(mesh): + edge_table[(C, D)] = [i, None, b, d, None, None, None, Dcol, None] + else: + edge_table[(C, D)] = [i, None, b, d, None, None, None] + + if edge_table.has_key((A, D)): + edge_table[(A, D)][1] = i + edge_table[(A, D)][4] = c + edge_table[(A, D)][5] = a + if has_vertex_colors(mesh): edge_table[(A, D)][8] = Acol + else: + if has_vertex_colors(mesh): + edge_table[(D, A)] = [i, None, c, a, None, None, None, Acol, None] + else: + edge_table[(D, A)] = [i, None, c, a, None, None, None] + +# ==================================== +# === Generate Entry From Triangle === +# ==================================== +def generate_entry_from_tri(mesh, i, edge_table): + vertex3, vertex2, vertex1 = mesh.faces[i].v + + if has_vertex_colors(mesh): + vcolor3, vcolor2, vcolor1, _vcolor4_ = mesh.faces[i].col + Acol = (vcolor1.r/255.0, vcolor1.g/255.0, vcolor1.b/255.0) + Bcol = (vcolor2.r/255.0, vcolor2.g/255.0, vcolor2.b/255.0) + Ccol = (vcolor3.r/255.0, vcolor3.g/255.0, vcolor3.b/255.0) + + # === verts are upper case, edges are lower case === + A, B, C = vertex1.index, vertex2.index, vertex3.index + a, b, c = (A, B), (B, C), (C, A) + + if edge_table.has_key((B, A)): + edge_table[(B, A)][1] = i + edge_table[(B, A)][4] = c + edge_table[(B, A)][5] = b + if has_vertex_colors(mesh): edge_table[(B, A)][8] = Bcol + else: + if has_vertex_colors(mesh): + edge_table[(A, B)] = [i, None, c, b, None, None, None, Bcol, None] + else: + edge_table[(A, B)] = [i, None, c, b, None, None, None] + + if edge_table.has_key((C, B)): + edge_table[(C, B)][1] = i + edge_table[(C, B)][4] = a + edge_table[(C, B)][5] = c + if has_vertex_colors(mesh): edge_table[(C, B)][8] = Ccol + else: + if has_vertex_colors(mesh): + edge_table[(B, C)] = [i, None, a, c, None, None, None, Ccol, None] + else: + edge_table[(B, C)] = [i, None, a, c, None, None, None] + + if edge_table.has_key((A, C)): + edge_table[(A, C)][1] = i + edge_table[(A, C)][4] = b + edge_table[(A, C)][5] = a + if has_vertex_colors(mesh): edge_table[(A, C)][8] = Acol + else: + if has_vertex_colors(mesh): + edge_table[(C, A)] = [i, None, b, a, None, None, None, Acol, None] + else: + edge_table[(C, A)] = [i, None, b, a, None, None, None] diff --git a/release/scripts/nendo_export.py b/release/scripts/nendo_export.py new file mode 100644 index 00000000000..97796f03207 --- /dev/null +++ b/release/scripts/nendo_export.py @@ -0,0 +1,183 @@ +#!BPY + +""" +Name: 'Nendo...' +Blender: 232 +Group: 'Export' +Tooltip: 'Export selected mesh to Nendo File Format (*.ndo)' +""" + +# +---------------------------------------------------------+ +# | Copyright (c) 2001 Anthony D'Agostino | +# | http://www.redrival.com/scorpius | +# | scorpius@netzero.com | +# | September 25, 2001 | +# | Released under the Blender Artistic Licence (BAL) | +# | Import Export Suite v0.5 | +# +---------------------------------------------------------+ +# | Read and write Nendo File Format (*.nendo) | +# +---------------------------------------------------------+ + +import Blender, mod_meshtools +import struct, time, sys, os + +# ============================== +# === Write Nendo 1.1 Format === +# ============================== +def write(filename): + start = time.clock() + + objects = Blender.Object.GetSelected() + objname = objects[0].name + meshname = objects[0].data.name + mesh = Blender.NMesh.GetRaw(meshname) + obj = Blender.Object.Get(objname) + + numedges = len(mesh.verts)+len(mesh.faces)-2 + maxedges = (2**16)-1 # Blender & Wings can read more edges + #maxedges = 32767 # Nendo can't + if numedges > maxedges: + message = objname + " can't be exported to Nendo format (too many edges)." + Blender.Draw.PupMenu("Nendo Export Error%t|"+message) + return + + edge_table = mod_meshtools.generate_edgetable(mesh) + + try: + edge_table = mod_meshtools.generate_edgetable(mesh) + assert len(edge_table) <= maxedges + except: + edge_table = {} + message = "Unable to generate Edge Table for the object named " + meshname + mod_meshtools.print_boxed(message) + Blender.Draw.PupMenu("Edge Table Error%t|"+message) + Blender.Window.DrawProgressBar(1.0, "") # clear progressbar + return + + file = open(filename, "wb") + write_header(file) + write_object_flags(file, objname) + write_edge_table(file, edge_table) + write_face_table(file, edge_table) + write_vert_table(file, edge_table, mesh) + write_texture(file) + file.close() + + Blender.Window.DrawProgressBar(1.0, "") # clear progressbar + print '\a\r', + end = time.clock() + seconds = " in %.2f %s" % (end-start, "seconds") + message = "Successfully exported " + os.path.basename(filename) + seconds + mod_meshtools.print_boxed(message) + +# ==================== +# === Write Header === +# ==================== +def write_header(file): + file.write("nendo 1.1") + file.write("\0\0") + file.write("\1") # numobjects + +# ========================== +# === Write Object Flags === +# ========================== +def write_object_flags(file, objname): + file.write("\1") # good flag + file.write(struct.pack(">H", len(objname))) + file.write(objname) + file.write("\1"*4) + data = struct.pack(">18f",0,0,0,1,1,1,1,1,1,1,1,1,0.2,0.2,0.2,1,100,1) + data = "<<<< Nendo Export Script for Blender -- (c) 2004 Anthony D'Agostino >>>>" + file.write(data) + +# ======================== +# === Write Edge Table === +# ======================== +def write_edge_table(file, edge_table): + "+--------------------------------------+" + "| Wings: Sv Ev | Lf Rf | Lp Ls | Rp Rs |" + "| Nendo: Ev Sv | Lf Rf | Ls Rs | Rp Lp |" + "+--------------------------------------+" + #$print "edge_table"; pprint.pprint(edge_table) + file.write(struct.pack(">H", len(edge_table))) + keys = edge_table.keys() + keys.sort() + for key in keys: + file.write(struct.pack(">2H", key[0], key[1])) # Ev Sv + file.write(struct.pack(">2H", edge_table[key][0], edge_table[key][1])) # Lf Rf + file.write(struct.pack(">2H", edge_table[key][3], edge_table[key][5])) # Ls Rs + file.write(struct.pack(">2H", edge_table[key][4], edge_table[key][2])) # Rp Lp + file.write(struct.pack(">1B", 0)) # Hard flag + try: + r1,g1,b1 = map(lambda x:x*255, edge_table[key][8]) + r2,g2,b2 = map(lambda x:x*255, edge_table[key][7]) + except: + r1,g1,b1 = map(lambda x:x*255, [0.9,0.8,0.7]) + r2,g2,b2 = r1,g1,b1 + file.write(struct.pack(">8B", r1,g1,b1,0,r2,g2,b2,0)) + +# ======================== +# === Write Face Table === +# ======================== +def write_face_table(file, edge_table): + face_table = build_face_table(edge_table) + #$print "face_table"; pprint.pprint(face_table) + file.write(struct.pack(">H", len(face_table))) + keys = face_table.keys() + keys.sort() + for key in keys: + file.write(struct.pack(">1H", face_table[key])) + +# ======================== +# === Write Vert Table === +# ======================== +def write_vert_table(file, edge_table, mesh): + vert_table = build_vert_table(edge_table) + #$print "vert_table"; pprint.pprint(vert_table) + file.write(struct.pack(">H", len(vert_table))) + keys = vert_table.keys() + keys.sort() + for key in keys: + vertex = mesh.verts[key].co + x,y,z = map(lambda x:x*10, vertex) # scale + idx = vert_table[key] + #$print "%i % f % f % f" % (idx, x, y, z) + file.write(struct.pack(">1H3f", idx, x, z, -y)) + +# ===================== +# === Write Texture === +# ===================== +def write_texture(file): + file.write("\0"*5) + +# ======================== +# === Build Vert Table === +# ======================== +def build_vert_table(edge_table): # For Nendo + vert_table = {} + for key in edge_table.keys(): + i = edge_table[key][6] + Sv = key[0] + Ev = key[1] + vert_table[Sv] = i + vert_table[Ev] = i + return vert_table + +# ======================== +# === Build Face Table === +# ======================== +def build_face_table(edge_table): # For Nendo + face_table = {} + for key in edge_table.keys(): + i = edge_table[key][6] + Lf = edge_table[key][0] + Rf = edge_table[key][1] + face_table[Lf] = i + face_table[Rf] = i + return face_table + +def fs_callback(filename): + if filename.find('.ndo', -4) <= 0: filename += '.ndo' + write(filename) + +Blender.Window.FileSelector(fs_callback, "Nendo Export") diff --git a/release/scripts/nendo_import.py b/release/scripts/nendo_import.py new file mode 100644 index 00000000000..d14d99d87ab --- /dev/null +++ b/release/scripts/nendo_import.py @@ -0,0 +1,205 @@ +#!BPY + +""" +Name: 'Nendo...' +Blender: 232 +Group: 'Import' +Tooltip: 'Import Nendo Object File Format (*.ndo)' +""" + +# +---------------------------------------------------------+ +# | Copyright (c) 2001 Anthony D'Agostino | +# | http://www.redrival.com/scorpius | +# | scorpius@netzero.com | +# | September 25, 2001 | +# | Released under the Blender Artistic Licence (BAL) | +# | Import Export Suite v0.5 | +# +---------------------------------------------------------+ +# | Read and write Nendo File Format (*.nendo) | +# +---------------------------------------------------------+ + +import Blender, mod_meshtools +import struct, time, sys, os + +# ============================= +# === Read Nendo 1.x Format === +# ============================= +def read(filename): + start = time.clock() + file = open(filename, "rb") + version, numobjs = read_header(file) + + for object in range(numobjs): + good, = struct.unpack(">B", file.read(1)) + if not good: continue # an empty object + objname = read_object_flags(file) + edge_table = read_edge_table(file, version) + face_table = read_face_table(file) + vert_table = read_vert_table(file) + uv = read_uv(file) + verts = make_verts(vert_table) + faces = make_faces(edge_table) + mod_meshtools.create_mesh(verts, faces, objname) + + Blender.Window.DrawProgressBar(1.0, "Done") # clear progressbar + file.close() + end = time.clock() + seconds = " in %.2f %s" % (end-start, "seconds") + message = "Successfully imported " + os.path.basename(filename) + seconds + message += " (%s)" % version.title() + mod_meshtools.print_boxed(message) + +# ======================= +# === Read The Header === +# ======================= +def read_header(file): + version, = struct.unpack(">9s", file.read(9)) + misc, = struct.unpack(">H", file.read(2)) + numobjs, = struct.unpack(">B", file.read(1)) + if (version != "nendo 1.0") and (version != "nendo 1.1"): + mod_meshtools.print_boxed(file.name, "is not a Nendo file") + return + return version, numobjs + +# ========================= +# === Read Object Flags === +# ========================= +def read_object_flags(file): + namelen, = struct.unpack(">H", file.read(2)) + objname = file.read(namelen) + visible, = struct.unpack(">B", file.read(1)) + sensity, = struct.unpack(">B", file.read(1)) + other, = struct.unpack(">H", file.read(2)) # or 2 more flags? + misc = struct.unpack(">18f", file.read(72)) + return objname + +# ======================= +# === Read Edge Table === +# ======================= +def read_edge_table(file, version): + numedges, = struct.unpack(">H", file.read(2)) + edge_table = {} + for i in range(numedges): + if not i%100 and mod_meshtools.show_progress: + Blender.Window.DrawProgressBar(float(i)/numedges, "Reading Edge Table") + edge = struct.unpack(">8H", file.read(16)) + if version == "nendo 1.1": + hard, = struct.unpack(">B", file.read(1)) # edge hardness flag + color = struct.unpack(">8B", file.read(8)) + edge_table[i] = edge + return edge_table + +# ======================= +# === Read Face Table === +# ======================= +def read_face_table(file): + numfaces, = struct.unpack(">H", file.read(2)) + face_table = {} + for i in range(numfaces): + if not i%100 and mod_meshtools.show_progress: + Blender.Window.DrawProgressBar(float(i)/numfaces, "Reading Face Table") + face_table[i] = struct.unpack(">H", file.read(2))[0] + return face_table + +# ======================= +# === Read Vert Table === +# ======================= +def read_vert_table(file): + numverts, = struct.unpack(">H", file.read(2)) + vert_table = [] + for i in range(numverts): + if not i%100 and mod_meshtools.show_progress: + Blender.Window.DrawProgressBar(float(i)/numverts, "Reading Vertex Table") + w, x, y, z = struct.unpack(">H3f", file.read(14)) + vert_table.append((w,(x, y, z))) + return vert_table + +# ==================== +# === Read Texture === +# ==================== +def read_uv(file): + numuvs, = struct.unpack(">H", file.read(2)) + uvlist = struct.unpack(">"+`numuvs`+"H", file.read(numuvs*2)) + numfacesT, = struct.unpack(">H", file.read(2)) + facesT = struct.unpack(">"+`numfacesT`+"H", file.read(numfacesT*2)) + textureflag, = struct.unpack(">B", file.read(1)) + if textureflag: + xres, yres = struct.unpack(">2H", file.read(4)) + print "%ix%i" % (xres, yres) + pixel = 0 + while pixel < (xres*yres): + if not pixel%100 and mod_meshtools.show_progress: + Blender.Window.DrawProgressBar(float(pixel)/xres*yres, "Reading Texture") + count, = struct.unpack(">B", file.read(1)) + rgb = file.read(3) + pixel = pixel+count + return numuvs + +# ================== +# === Make Verts === +# ================== +def make_verts(vert_table): + matrix = [ # Rotate 90*x and Scale 0.1 + [0.1, 0.0, 0.0, 0.0], + [0.0, 0.0, 0.1, 0.0], + [0.0,-0.1, 0.0, 0.0], + [0.0, 0.0, 0.0, 1.0]] + verts = [] + for i in range(len(vert_table)): + vertex = vert_table[i][1] + vertex = mod_meshtools.apply_transform(vertex, matrix) + verts.append(vertex) + return verts + +# ======================= +# === Make Face Table === +# ======================= +def make_face_table(edge_table): # For Nendo + face_table = {} + for i in range(len(edge_table)): + Lf = edge_table[i][2] + Rf = edge_table[i][3] + face_table[Lf] = i + face_table[Rf] = i + return face_table + +# ======================= +# === Make Vert Table === +# ======================= +def make_vert_table(edge_table): # For Nendo + vert_table = {} + for i in range(len(edge_table)): + Sv = edge_table[i][1] + Ev = edge_table[i][0] + vert_table[Sv] = i + vert_table[Ev] = i + return vert_table + +# ================== +# === Make Faces === +# ================== +def make_faces(edge_table): # For Nendo + face_table = make_face_table(edge_table) + faces=[] + #for i in range(len(face_table)): + for i in face_table.keys(): # avoids a whole class of errors + face_verts = [] + current_edge = face_table[i] + while(1): + if i == edge_table[current_edge][3]: + next_edge = edge_table[current_edge][5] # Right successor edge + next_vert = edge_table[current_edge][1] + else: + next_edge = edge_table[current_edge][4] # Left successor edge + next_vert = edge_table[current_edge][0] + face_verts.append(next_vert) + current_edge = next_edge + if current_edge == face_table[i]: break + face_verts.reverse() # Flip all face normals + faces.append(face_verts) + return faces + +def fs_callback(filename): + read(filename) + +Blender.Window.FileSelector(fs_callback, "Nendo Import") diff --git a/release/scripts/obj_export.py b/release/scripts/obj_export.py new file mode 100644 index 00000000000..2fb84274c98 --- /dev/null +++ b/release/scripts/obj_export.py @@ -0,0 +1,161 @@ +#!BPY + +""" +Name: 'OBJ Wavefront' +Blender: 232 +Group: 'Export' +Tooltip: 'Save a Wavefront OBJ File' +""" + +# -------------------------------------------------------------------------- +# OBJ Export v0.9 by Campbell Barton (AKA Ideasman) +# -------------------------------------------------------------------------- +# ***** 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 ***** +# -------------------------------------------------------------------------- + +#================================================# +# Gets the world matrix of an object # +# by multiplying by parents mat's recursively # +# This only works in some simple situations, # +# needs work.... # +#================================================# +def getWorldMat(ob): + mat = ob.getMatrix() + p = ob.getParent() + if p != None: + mat = mat + getWorldMat(p) + return mat + +#==================# +# Apply Transform # +#==================# +def apply_transform(verts, matrix): + + x, y, z = verts + xloc, yloc, zloc = matrix[3][0], matrix[3][1], matrix[3][2] + xcomponent = x*matrix[0][0] + y*matrix[1][0] + z*matrix[2][0] + xloc + ycomponent = x*matrix[0][1] + y*matrix[1][1] + z*matrix[2][1] + yloc + zcomponent = x*matrix[0][2] + y*matrix[1][2] + z*matrix[2][2] + zloc + + return [xcomponent, ycomponent, zcomponent] + + +#=====================================# +# Apply Transform for vertex normals # +# ignore the translation # +#=====================================# +def apply_normal_transform(verts, matrix): + x, y, z = verts + xcomponent = x*matrix[0][0] + y*matrix[1][0] + z*matrix[2][0] + ycomponent = x*matrix[0][1] + y*matrix[1][1] + z*matrix[2][1] + zcomponent = x*matrix[0][2] + y*matrix[1][2] + z*matrix[2][2] + return Mathutils.Vector([xcomponent, ycomponent, zcomponent]) + +#====================================================# +# 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) + ' ' + + +from Blender import * + +NULL_MAT = '(null)' + +def save_obj(filename): + + file = open(filename, "w") + + # Write Header + file.write('# Blender OBJ File: ' + Get('filename') + ' \n') + file.write('# www.blender.org\n') + + # Get all meshs + for ob in Object.Get(): + if ob.getType() == 'Mesh': + m = ob.getData() + if len(m.verts) > 0: # Make sure there is somthing to write. + + # Set the default mat + currentMatName = '' + + file.write('o ' + ob.getName() + '_' + m.name + '\n') # Write Object name + + # Dosent work properly, + matrix = getWorldMat(ob) + + # Vert + for v in m.verts: + # Transform the vert + vTx = apply_transform(v.co, matrix) + + file.write('v ') + file.write(saneFloat(vTx[0])) + file.write(saneFloat(vTx[1])) + file.write(saneFloat(vTx[2]) + '\n') + + # UV + for f in m.faces: + for uvIdx in range(len(f.v)): + file.write('vt ') + if f.uv: + file.write(saneFloat(f.uv[uvIdx][0])) + file.write(saneFloat(f.uv[uvIdx][1])) + else: + file.write('0.0 ') + file.write('0.0 ') + + file.write('0.0' + '\n') + + # NORMAL + for f in m.faces: + for v in f.v: + # Transform the normal + noTx = apply_normal_transform(v.no, matrix) + noTx.normalize() + file.write('vn ') + file.write(saneFloat(noTx[0])) + file.write(saneFloat(noTx[1])) + file.write(saneFloat(noTx[2]) + '\n') + + uvIdx = 0 + for f in m.faces: + # Check material and change if needed. + if len(m.materials) > f.mat: + if currentMatName != m.materials[f.mat].getName(): + currentMatName = m.materials[f.mat].getName() + file.write('usemtl ' + currentMatName + '\n') + + elif currentMatName != NULL_MAT: + currentMatName = NULL_MAT + file.write('usemtl ' + currentMatName + '\n') + + file.write('f ') + for v in f.v: + file.write( str(m.verts.index(v) +1) + '/') # Vert IDX + file.write( str(uvIdx +1) + '/') # UV IDX + file.write( str(uvIdx +1) + ' ') # NORMAL IDX + uvIdx+=1 + file.write('\n') + + file.close() + +Window.FileSelector(save_obj, 'SELECT OBJ FILE') diff --git a/release/scripts/obj_import.py b/release/scripts/obj_import.py new file mode 100644 index 00000000000..856b156deb5 --- /dev/null +++ b/release/scripts/obj_import.py @@ -0,0 +1,245 @@ +#!BPY + +""" +Name: 'OBJ Wavefront' +Blender: 232 +Group: 'Import' +Tooltip: 'Load a Wavefront OBJ File' + """ + +# -------------------------------------------------------------------------- +# OBJ Import v0.9 by Campbell Barton (AKA Ideasman) +# -------------------------------------------------------------------------- +# ***** 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 ***** +# -------------------------------------------------------------------------- + +WHITESPACE = [' ', '\n', '\r', '\t', '\f', '\v'] # used for the split function. +NULL_MAT = '(null)' # Name for mesh's that have no mat set. + +MATLIMIT = 16 + +#==============================================# +# Strips the slashes from the back of a string # +#==============================================# +def stripPath(path): + for CH in range(len(path), 0, -1): + if path[CH-1] == "/" or path[CH-1] == "\\": + path = path[CH:] + break + return path + +#====================================================# +# Strips the prefix off the name before writing # +#====================================================# +def stripName(name): # name is a string + prefixDelimiter = '.' + return name[ : name.find(prefixDelimiter) ] + +#================================================================# +# Replace module deps 'string' for join and split # # +# - Split splits a string into a list, and join does the reverse # +#================================================================# +def split(splitString, WHITESPACE): + splitList = [] + charIndex = 0 + while charIndex < len(splitString): + # Skip white space + while charIndex < len(splitString): + if splitString[charIndex] in WHITESPACE: + charIndex += 1 + else: + break + + # Gather text that is not white space and append to splitList + startWordCharIndex = charIndex + while charIndex < len(splitString): + if splitString[charIndex] in WHITESPACE: break + charIndex += 1 + + # Now we have the first and last chars we can append the word to the list + if charIndex != startWordCharIndex: + splitList.append(splitString[startWordCharIndex:charIndex]) + + return splitList + +#===============================# +# Join list items into a string # +#===============================# +def join(joinList): + joinedString = "" + for listItem in joinList: + joinedString = joinedString + ' ' + str(listItem) + + # Remove the first space + joinedString = joinedString[1:] + return joinedString + + +from Blender import * + +def load_obj(file): + # This gets a mat or creates one of the requested name if none exist. + def getMat(matName): + # Make a new mat + try: + return Material.Get(matName) + except: + return Material.New(matName) + + def applyMat(mesh, f, mat): + # Check weather the 16 mat limit has been met. + if len( mesh.materials ) >= MATLIMIT: + print 'Warning, max material limit reached, using an existing material' + return mesh, f + + mIdx = 0 + for m in mesh.materials: + if m.getName() == mat.getName(): + break + mIdx+=1 + + if mIdx == len(mesh.materials): + mesh.addMaterial(mat) + + f.mat = mIdx + return mesh, f + + # Get the file name with no path or .obj + fileName = stripName( stripPath(file) ) + + fileLines = open(file, 'r').readlines() + + mesh = NMesh.GetRaw() # new empty mesh + + objectName = 'mesh' # If we cant get one, use this + + uvMapList = [] # store tuple uv pairs here + + nullMat = getMat(NULL_MAT) + + currentMat = nullMat # Use this mat. + + # Main loop + lIdx = 0 + while lIdx < len(fileLines): + l = split(fileLines[lIdx], WHITESPACE) + + # Detect a line that will be idnored + if len(l) == 0: + pass + elif l[0] == '#' or len(l) == 0: + pass + # VERTEX + elif l[0] == 'v': + # This is a new vert, make a new mesh + mesh.verts.append( NMesh.Vert(eval(l[1]), eval(l[2]), eval(l[3]) ) ) + + elif l[0] == 'vn': + pass + + elif l[0] == 'vt': + # This is a new vert, make a new mesh + uvMapList.append( (eval(l[1]), eval(l[2])) ) + + elif l[0] == 'f': + + # Make a face with the correct material. + f = NMesh.Face() + mesh, f = applyMat(mesh, f, currentMat) + + # Set up vIdxLs : Verts + # Set up vtIdxLs : UV + vIdxLs = [] + vtIdxLs = [] + for v in l[1:]: + objVert = split( v, ['/'] ) + + # VERT INDEX + vIdxLs.append(eval(objVert[0]) -1) + # UV + if len(objVert) == 1: + vtIdxLs.append(eval(objVert[0]) -1) # Sticky UV coords + else: + vtIdxLs.append(eval(objVert[1]) -1) # Seperate UV coords + + # Quads only, we could import quads using the method below but it polite to import a quad as a quad.f + if len(vIdxLs) == 4: + f.v.append(mesh.verts[vIdxLs[0]]) + f.v.append(mesh.verts[vIdxLs[1]]) + f.v.append(mesh.verts[vIdxLs[2]]) + f.v.append(mesh.verts[vIdxLs[3]]) + # UV MAPPING + if uvMapList: + if vtIdxLs[0] < len(uvMapList): + f.uv.append( uvMapList[ vtIdxLs[0] ] ) + if vtIdxLs[1] < len(uvMapList): + f.uv.append( uvMapList[ vtIdxLs[1] ] ) + if vtIdxLs[2] < len(uvMapList): + f.uv.append( uvMapList[ vtIdxLs[2] ] ) + if vtIdxLs[3] < len(uvMapList): + f.uv.append( uvMapList[ vtIdxLs[3] ] ) + mesh.faces.append(f) # move the face onto the mesh + + elif len(vIdxLs) >= 3: # This handles tri's and fans + for i in range(len(vIdxLs)-2): + f = NMesh.Face() + mesh, f = applyMat(mesh, f, currentMat) + f.v.append(mesh.verts[vIdxLs[0]]) + f.v.append(mesh.verts[vIdxLs[i+1]]) + f.v.append(mesh.verts[vIdxLs[i+2]]) + # UV MAPPING + if uvMapList: + if vtIdxLs[0] < len(uvMapList): + f.uv.append( uvMapList[ vtIdxLs[0] ] ) + if vtIdxLs[1] < len(uvMapList): + f.uv.append( uvMapList[ vtIdxLs[i+1] ] ) + if vtIdxLs[2] < len(uvMapList): + f.uv.append( uvMapList[ vtIdxLs[i+2] ] ) + + mesh.faces.append(f) # move the face onto the mesh + + # is o the only vert/face delimeter? + # if not we could be screwed. + elif l[0] == 'o': + # Make sure the objects is worth puttong + if len(mesh.verts) > 0: + NMesh.PutRaw(mesh, fileName + '_' + objectName) + # Make new mesh + mesh = NMesh.GetRaw() + + # New mesh name + objectName = join(l[1:]) # Use join in case of spaces + + # New texture list + uvMapList = [] + + elif l[0] == 'usemtl': + if l[1] == '(null)': + currentMat = NULL_MAT + else: + currentMat = getMat(join(l[1:])) # Use join in case of spaces + + lIdx+=1 + + # We need to do this to put the last object. + # All other objects will be put alredy + if len(mesh.verts) > 0: + NMesh.PutRaw(mesh, fileName + '_' + objectName) + +Window.FileSelector(load_obj, 'SELECT OBJ FILE') diff --git a/release/scripts/off_export.py b/release/scripts/off_export.py index 9648c1c3271..de843561e4c 100644 --- a/release/scripts/off_export.py +++ b/release/scripts/off_export.py @@ -9,8 +9,8 @@ Tooltip: 'Export selected mesh to Object File Format (*.off)' # +---------------------------------------------------------+ # | Copyright (c) 2002 Anthony D'Agostino | -# | http://ourworld.compuserve.com/homepages/scorpius | -# | scorpius@compuserve.com | +# | http://www.redrival.com/scorpius | +# | scorpius@netzero.com | # | February 3, 2001 | # | Released under the Blender Artistic Licence (BAL) | # | Import Export Suite v0.5 | @@ -18,9 +18,8 @@ Tooltip: 'Export selected mesh to Object File Format (*.off)' # | Read and write Object File Format (*.off) | # +---------------------------------------------------------+ -import Blender +import Blender, mod_meshtools #import time -import mod_flags, mod_meshtools # ============================== # ====== Write OFF Format ====== @@ -42,14 +41,14 @@ def write(filename): # === Vertex List === for i in range(len(mesh.verts)): - if not i%100 and mod_flags.show_progress: + if not i%100 and mod_meshtools.show_progress: Blender.Window.DrawProgressBar(float(i)/len(mesh.verts), "Writing Verts") x, y, z = mesh.verts[i].co file.write("%f %f %f\n" % (x, y, z)) # === Face List === for i in range(len(mesh.faces)): - if not i%100 and mod_flags.show_progress: + if not i%100 and mod_meshtools.show_progress: Blender.Window.DrawProgressBar(float(i)/len(mesh.faces), "Writing Faces") file.write(`len(mesh.faces[i].v)`+' ') mesh.faces[i].v.reverse() diff --git a/release/scripts/off_import.py b/release/scripts/off_import.py index 9f7fd5eb9f7..44c5bf6ff05 100644 --- a/release/scripts/off_import.py +++ b/release/scripts/off_import.py @@ -9,8 +9,8 @@ Tooltip: 'Import Object File Format (*.off)' # +---------------------------------------------------------+ # | Copyright (c) 2002 Anthony D'Agostino | -# | http://ourworld.compuserve.com/homepages/scorpius | -# | scorpius@compuserve.com | +# | http://www.redrival.com/scorpius | +# | scorpius@netzero.com | # | February 3, 2001 | # | Released under the Blender Artistic Licence (BAL) | # | Import Export Suite v0.5 | @@ -18,9 +18,8 @@ Tooltip: 'Import Object File Format (*.off)' # | Read and write Object File Format (*.off) | # +---------------------------------------------------------+ -import Blender +import Blender, mod_meshtools #import time -import mod_flags, mod_meshtools # ============================= # ====== Read OFF Format ====== @@ -40,7 +39,7 @@ def read(filename): # === Vertex List === for i in range(numverts): - if not i%100 and mod_flags.show_progress: + if not i%100 and mod_meshtools.show_progress: Blender.Window.DrawProgressBar(float(i)/numverts, "Reading Verts") x, y, z = file.readline().split() x, y, z = float(x), float(y), float(z) @@ -48,7 +47,7 @@ def read(filename): # === Face List === for i in range(numfaces): - if not i%100 and mod_flags.show_progress: + if not i%100 and mod_meshtools.show_progress: Blender.Window.DrawProgressBar(float(i)/numfaces, "Reading Faces") line = file.readline().split() numfaceverts = len(line)-1 diff --git a/release/scripts/radiosity_export.py b/release/scripts/radiosity_export.py index f87f8a1ef19..34c913dc1ef 100644 --- a/release/scripts/radiosity_export.py +++ b/release/scripts/radiosity_export.py @@ -9,8 +9,8 @@ Tooltip: 'Export selected mesh (with vertex colors) to Radiosity File Format (*. # +---------------------------------------------------------+ # | Copyright (c) 2002 Anthony D'Agostino | -# | http://ourworld.compuserve.com/homepages/scorpius | -# | scorpius@compuserve.com | +# | http://www.redrival.com/scorpius | +# | scorpius@netzero.com | # | April 11, 2002 | # | Released under the Blender Artistic Licence (BAL) | # | Import Export Suite v0.5 | @@ -18,14 +18,15 @@ Tooltip: 'Export selected mesh (with vertex colors) to Radiosity File Format (*. # | Read and write Radiosity File Format (*.radio) | # +---------------------------------------------------------+ -import Blender +import Blender, mod_meshtools #import time -import mod_flags, mod_meshtools + try: import struct except: msg = "Error: you need a full Python install to run this script." mod_meshtools.print_boxed(msg) + Blender.Draw.PupMenu("ERROR%t|"+msg) # ================================ # ====== Write Radio Format ====== @@ -40,10 +41,11 @@ def write(filename): mesh = Blender.NMesh.GetRaw(meshname) obj = Blender.Object.Get(objname) - if not mesh.hasVertexColours(): - message = "Please assign vertex colors before exporting.\n" + if not mod_meshtools.has_vertex_colors(mesh): + message = "Please assign vertex colors before exporting. \n" message += objname + " object was not saved." mod_meshtools.print_boxed(message) + Blender.Draw.PupMenu("ERROR%t|"+message) return # === Object Name === @@ -53,7 +55,7 @@ def write(filename): # === Vertex List === file.write(struct.pack("<l", len(mesh.verts))) for i in range(len(mesh.verts)): - if not i%100 and mod_flags.show_progress: + if not i%100 and mod_meshtools.show_progress: Blender.Window.DrawProgressBar(float(i)/len(mesh.verts), "Writing Verts") x, y, z = mesh.verts[i].co @@ -62,7 +64,7 @@ def write(filename): # === Face List === file.write(struct.pack("<l", len(mesh.faces))) for i in range(len(mesh.faces)): - if not i%100 and mod_flags.show_progress: + if not i%100 and mod_meshtools.show_progress: Blender.Window.DrawProgressBar(float(i)/len(mesh.faces), "Writing Faces") file.write(struct.pack("<b", len(mesh.faces[i].v))) diff --git a/release/scripts/radiosity_import.py b/release/scripts/radiosity_import.py index d2e784b3ed4..46705855285 100644 --- a/release/scripts/radiosity_import.py +++ b/release/scripts/radiosity_import.py @@ -9,8 +9,8 @@ Tooltip: 'Import Radiosity File Format (*.radio) with vertex colors' # +---------------------------------------------------------+ # | Copyright (c) 2002 Anthony D'Agostino | -# | http://ourworld.compuserve.com/homepages/scorpius | -# | scorpius@compuserve.com | +# | http://www.redrival.com/scorpius | +# | scorpius@netzero.com | # | April 11, 2002 | # | Released under the Blender Artistic Licence (BAL) | # | Import Export Suite v0.5 | @@ -18,14 +18,15 @@ Tooltip: 'Import Radiosity File Format (*.radio) with vertex colors' # | Read and write Radiosity File Format (*.radio) | # +---------------------------------------------------------+ -import Blender +import Blender, mod_meshtools #import time -import mod_flags, mod_meshtools + try: import struct except: msg = "Error: you need a full Python install to run this script." mod_meshtools.print_boxed(msg) + Blender.Draw.PupMenu("ERROR%t|"+msg) # =============================== # ====== Read Radio Format ====== @@ -34,7 +35,7 @@ def read(filename): #start = time.clock() file = open(filename, "rb") mesh = Blender.NMesh.GetRaw() - mesh.addMaterial(Blender.Material.New()) + #mesh.addMaterial(Blender.Material.New()) # === Object Name === namelen, = struct.unpack("<h", file.read(2)) @@ -43,7 +44,7 @@ def read(filename): # === Vertex List === numverts, = struct.unpack("<l", file.read(4)) for i in range(numverts): - if not i%100 and mod_flags.show_progress: + if not i%100 and mod_meshtools.show_progress: Blender.Window.DrawProgressBar(float(i)/numverts, "Reading Verts") x, y, z = struct.unpack("<fff", file.read(12)) mesh.verts.append(Blender.NMesh.Vert(x, y, z)) @@ -51,7 +52,7 @@ def read(filename): # === Face List === numfaces, = struct.unpack("<l", file.read(4)) for i in range(numfaces): - if not i%100 and mod_flags.show_progress: + if not i%100 and mod_meshtools.show_progress: Blender.Window.DrawProgressBar(float(i)/numfaces, "Reading Faces") face = Blender.NMesh.Face() diff --git a/release/scripts/raw_export.py b/release/scripts/raw_export.py index 809f6e2354e..9c2407c41a7 100644 --- a/release/scripts/raw_export.py +++ b/release/scripts/raw_export.py @@ -9,8 +9,8 @@ Tooltip: 'Export selected mesh to Raw Triangle Format (*.raw)' # +---------------------------------------------------------+ # | Copyright (c) 2002 Anthony D'Agostino | -# | http://ourworld.compuserve.com/homepages/scorpius | -# | scorpius@compuserve.com | +# | http://www.redrival.com/scorpius | +# | scorpius@netzero.com | # | April 28, 2002 | # | Released under the Blender Artistic Licence (BAL) | # | Import Export Suite v0.5 | @@ -18,13 +18,13 @@ Tooltip: 'Export selected mesh to Raw Triangle Format (*.raw)' # | Read and write RAW Triangle File Format (*.raw) | # +---------------------------------------------------------+ -import Blender, sys +import Blender, mod_meshtools +import sys #import time -import mod_flags, mod_meshtools -# =================================== -# ==== Write RAW Triangle Format ==== -# =================================== +# ================================= +# === Write RAW Triangle Format === +# ================================= def write(filename): #start = time.clock() file = open(filename, "wb") diff --git a/release/scripts/raw_import.py b/release/scripts/raw_import.py index c080d028e3d..f1b6cc511e4 100644 --- a/release/scripts/raw_import.py +++ b/release/scripts/raw_import.py @@ -9,8 +9,8 @@ Tooltip: 'Import Raw Triangle File Format (*.raw)' # +---------------------------------------------------------+ # | Copyright (c) 2002 Anthony D'Agostino | -# | http://ourworld.compuserve.com/homepages/scorpius | -# | scorpius@compuserve.com | +# | http://www.redrival.com/scorpius | +# | scorpius@netzero.com | # | April 28, 2002 | # | Released under the Blender Artistic Licence (BAL) | # | Import Export Suite v0.5 | @@ -18,13 +18,12 @@ Tooltip: 'Import Raw Triangle File Format (*.raw)' # | Read and write RAW Triangle File Format (*.raw) | # +---------------------------------------------------------+ -import Blender +import Blender, mod_meshtools #import time -import mod_flags, mod_meshtools -# ================================== -# ==== Read RAW Triangle Format ==== -# ================================== +# ================================ +# === Read RAW Triangle Format === +# ================================ def read(filename): #start = time.clock() file = open(filename, "rb") diff --git a/release/scripts/rvk1_torvk2.py b/release/scripts/rvk1_torvk2.py new file mode 100644 index 00000000000..efe6c9a9559 --- /dev/null +++ b/release/scripts/rvk1_torvk2.py @@ -0,0 +1,108 @@ +#!BPY + +""" Registration info for Blender menus: <- these words are ignored +Name: 'Rvk1 to Rvk2' +Blender: 232 +Group: 'Animation' +Tip: 'Copy deform data (not surf. subdiv) of active obj to rvk of the 2nd selected obj.' +""" + +#---------------------------------------------- +# jm soler (c) 05/2004 : 'Rvk1toRvk2' release under blender artistic licence +#---------------------------------------------- +# Blender Artistic License +# http://download.blender.org/documentation/html/x21254.html +#---------------------------------------------------- +# Copy the rvk (1, or armature, lattice, or +# any mesh deformation except surface +# sbdivision) of the active object to rvk (2) of +# the second selected object. Create rvk or modify +# absolute key if needed. +#---------------------------------------------- +# official Page : +# http://jmsoler.free.fr/didacticiel/blender/tutor/cpl_rvk1versrvk2.htm +# download the script : +# http://jmsoler.free.fr/util/blenderfile/py/rvk1_torvk2.py +# Communicate upon problems or errors: +# http://www.zoo-logique.org/3D.Blender/newsportal/thread.php?group=3D.Blender +#---------------------------------------------- +# Page officielle : +# http://jmsoler.free.fr/util/blenderfile/py/rvk1_torvk2.py +# Communiquer les problemes et erreurs sur: +# http://www.zoo-logique.org/3D.Blender/newsportal/thread.php?group=3D.Blender +#--------------------------------------------- +# changelog : +# - a test on mesh parity between getraw and getrawfromobject +# when there is active subsurf division. +# - can copy, or not, vertex groups from the original mesh. +#--------------------------------------------- + +import Blender +from Blender import NMesh,Draw,Object + +def rvk2rvk(): + try: + SUBMODIF=0 + RVK2=Object.GetSelected()[0] + RVK1=Object.GetSelected()[1] + + FRAME=Blender.Get('curframe') + + DATA2=RVK2.getData() + + if DATA2.getMode() & NMesh.Modes['SUBSURF'] : + SUBSURF2=DATA2.getSubDivLevels() + if SUBSURF2[0]!=0: + name = "The active object has a subsurf level different from 0 ... %t| Let script do the the modification for you ? %x1| you prefer do it yourself ? %x2 " + result = Draw.PupMenu(name) + if result==1: + DATA2.mode=DATA2.mode-NMesh.Modes['SUBSURF'] + SUBMODIF=1 + DATA2.update() + RVK2.makeDisplayList() + Blender.Redraw() + else: + return + + RVK2NAME=Object.GetSelected()[0].getName() + mesh=RVK1.getData() + meshrvk2=NMesh.GetRawFromObject(RVK2NAME) + + name = "Do you want to replace or add vertex groups ? %t| YES %x1| NO ? %x2 " + result = Draw.PupMenu(name) + + if result==1: + GROUPNAME1=mesh.getVertGroupNames() + if len(GROUPNAME1)!=0: + for GROUP1 in GROUPNAME1: + mesh.removeVertGroup(GROUP1) + + GROUPNAME2=DATA2.getVertGroupNames() + if len(GROUPNAME2)!=0: + for GROUP2 in GROUPNAME2: + mesh.addVertGroup(GROUP2) + mesh.assignVertsToGroup(GROUP2,DATA2.getVertsFromGroup(GROUP2),1.0,'replace') + + for v in meshrvk2.verts: + i= meshrvk2.verts.index(v) + v1=mesh.verts[i] + for n in range(len(v.co)): + v1.co[n]=v.co[n] + + mesh.update() + mesh.insertKey(FRAME,'relative') + mesh.update() + RVK1.makeDisplayList() + + if SUBMODIF==1: + DATA2.mode=DATA2.mode+NMesh.Modes['SUBSURF'] + SUBMODIF=0 + DATA2.update() + RVK2.makeDisplayList() + + Blender.Redraw() + except: + print 'problem : not object selected or not mesh' + + +rvk2rvk() diff --git a/release/scripts/slp_import.py b/release/scripts/slp_import.py new file mode 100644 index 00000000000..a066e333445 --- /dev/null +++ b/release/scripts/slp_import.py @@ -0,0 +1,76 @@ +#!BPY + +""" +Name: 'SLP (Pro Engineer)...' +Blender: 232 +Group: 'Import' +Tooltip: 'Import SLP (Pro Engineer) File Format (*.raw)' +""" + +# +---------------------------------------------------------+ +# | Copyright (c) 2004 Anthony D'Agostino | +# | http://www.redrival.com/scorpius | +# | scorpius@netzero.com | +# | May 3, 2004 | +# | Released under the Blender Artistic Licence (BAL) | +# | Import Export Suite v0.5 | +# +---------------------------------------------------------+ +# | Read and write SLP Triangle File Format (*.slp) | +# +---------------------------------------------------------+ + +import Blender, mod_meshtools +#import time + +# ================================ +# === Read SLP Triangle Format === +# ================================ +def read(filename): + #start = time.clock() + file = open(filename, "rb") + + raw = [] + for line in file.readlines(): + data = line.split() + if data[0] == "vertex": + vert = map(float, data[1:]) + raw.append(vert) + + tri = [] + for i in range(0, len(raw), 3): + tri.append(raw[i] + raw[i+1] + raw[i+2]) + + #$import pprint; pprint.pprint(tri) + + # Collect data from RAW format + faces = [] + for line in tri: + f1, f2, f3, f4, f5, f6, f7, f8, f9 = line + faces.append([(f1, f2, f3), (f4, f5, f6), (f7, f8, f9)]) + + # Generate verts and faces lists, without duplicates + verts = [] + coords = {} + index = 0 + for i in range(len(faces)): + for j in range(len(faces[i])): + vertex = faces[i][j] + if not coords.has_key(vertex): + coords[vertex] = index + index += 1 + verts.append(vertex) + faces[i][j] = coords[vertex] + + objname = Blender.sys.splitext(Blender.sys.basename(filename))[0] + + mod_meshtools.create_mesh(verts, faces, objname) + Blender.Window.DrawProgressBar(1.0, '') # clear progressbar + file.close() + #end = time.clock() + #seconds = " in %.2f %s" % (end-start, "seconds") + message = "Successfully imported " + Blender.sys.basename(filename)# + seconds + mod_meshtools.print_boxed(message) + +def fs_callback(filename): + read(filename) + +Blender.Window.FileSelector(fs_callback, "SLP Import") diff --git a/release/scripts/truespace_export.py b/release/scripts/truespace_export.py new file mode 100644 index 00000000000..8013278e528 --- /dev/null +++ b/release/scripts/truespace_export.py @@ -0,0 +1,265 @@ +#!BPY + +""" +Name: 'TrueSpace...' +Blender: 232 +Group: 'Export' +Tooltip: 'Export selected meshes to trueSpace File Format (*.cob)' +""" + +# +---------------------------------------------------------+ +# | Copyright (c) 2001 Anthony D'Agostino | +# | http://www.redrival.com/scorpius | +# | scorpius@netzero.com | +# | June 12, 2001 | +# | Released under the Blender Artistic Licence (BAL) | +# | Import Export Suite v0.5 | +# +---------------------------------------------------------+ +# | Read and write Caligari trueSpace File Format (*.cob) | +# +---------------------------------------------------------+ + +import Blender, mod_meshtools +import struct, os, cStringIO, time + +# ============================== +# === Write trueSpace Format === +# ============================== +def write(filename): + start = time.clock() + file = open(filename, "wb") + objects = Blender.Object.GetSelected() + + write_header(file) + + G,P,V,U,M = 1000,2000,3000,4000,5000 + for object in objects: + objname = object.name + meshname = object.data.name + mesh = Blender.NMesh.GetRaw(meshname) + obj = Blender.Object.Get(objname) + if not mesh: continue + + grou = generate_grou('Group ' + `objects.index(object)+1`) + polh = generate_polh(objname, obj, mesh) + if mod_meshtools.has_vertex_colors(mesh): vcol = generate_vcol(mesh) + unit = generate_unit() + mat1 = generate_mat1(mesh) + + if objects.index(object) == 0: X = 0 + + write_chunk(file, "Grou", 0, 1, G, X, grou) + write_chunk(file, "PolH", 0, 4, P, G, polh) + if mod_meshtools.has_vertex_colors(mesh) and vcol: + write_chunk(file, "VCol", 1, 0, V, P, vcol) + write_chunk(file, "Unit", 0, 1, U, P, unit) + write_chunk(file, "Mat1", 0, 5, M, P, mat1) + + X = G + G,P,V,U,M = map(lambda x: x+1, [G,P,V,U,M]) + + write_chunk(file, "END ", 1, 0, 0, 0, '') # End Of File Chunk + + Blender.Window.DrawProgressBar(1.0, '') # clear progressbar + file.close() + end = time.clock() + seconds = " in %.2f %s" % (end-start, "seconds") + message = "Successfully exported " + os.path.basename(filename) + seconds + mod_meshtools.print_boxed(message) + +# ============================= +# === Write COB File Header === +# ============================= +def write_header(file): + file.write("Caligari V00.01BLH"+" "*13+"\n") + +# =================== +# === Write Chunk === +# =================== +def write_chunk(file, name, major, minor, chunk_id, parent_id, data): + file.write(name) + file.write(struct.pack("<2h", major, minor)) + file.write(struct.pack("<2l", chunk_id, parent_id)) + file.write(struct.pack("<1l", len(data))) + file.write(data) + +# ============================================ +# === Generate PolH (Polygonal Data) Chunk === +# ============================================ +def generate_polh(objname, obj, mesh): + data = cStringIO.StringIO() + write_ObjectName(data, objname) + write_LocalAxes(data, obj) + write_CurrentPosition(data, obj) + write_VertexList(data, mesh) + uvcoords = write_UVCoordsList(data, mesh) + write_FaceList(data, mesh, uvcoords) + return data.getvalue() + +# === Write Object Name === +def write_ObjectName(data, objname): + data.write(struct.pack("<h", 0)) # dupecount + data.write(struct.pack("<h", len(objname))) + data.write(objname) + +# === Write Local Axes === +def write_LocalAxes(data, obj): + data.write(struct.pack("<fff", obj.mat[3][0], obj.mat[3][1], obj.mat[3][2])) + data.write(struct.pack("<fff", obj.mat[0][0]/obj.SizeX, obj.mat[1][0]/obj.SizeX, obj.mat[2][0]/obj.SizeX)) + data.write(struct.pack("<fff", obj.mat[0][1]/obj.SizeY, obj.mat[1][1]/obj.SizeY, obj.mat[2][1]/obj.SizeY)) + data.write(struct.pack("<fff", obj.mat[0][2]/obj.SizeZ, obj.mat[1][2]/obj.SizeZ, obj.mat[2][2]/obj.SizeZ)) + +# === Write Current Position === +def write_CurrentPosition(data, obj): + data.write(struct.pack("<ffff", obj.mat[0][0], obj.mat[0][1], obj.mat[0][2], obj.mat[3][0])) + data.write(struct.pack("<ffff", obj.mat[1][0], obj.mat[1][1], obj.mat[1][2], obj.mat[3][1])) + data.write(struct.pack("<ffff", obj.mat[2][0], obj.mat[2][1], obj.mat[2][2], obj.mat[3][2])) + +# === Write Vertex List === +def write_VertexList(data, mesh): + data.write(struct.pack("<l", len(mesh.verts))) + for i in range(len(mesh.verts)): + if not i%100 and mod_meshtools.show_progress: + Blender.Window.DrawProgressBar(float(i)/len(mesh.verts), "Writing Verts") + x, y, z = mesh.verts[i].co + data.write(struct.pack("<fff", -y, x, z)) + +# === Write UV Vertex List === +def write_UVCoordsList(data, mesh): + if not mesh.hasFaceUV(): + data.write(struct.pack("<l", 1)) + data.write(struct.pack("<2f", 0,0)) + return {(0,0): 0} + # === Default UV Coords (one image per face) === + # data.write(struct.pack("<l", 4)) + # data.write(struct.pack("<8f", 0,0, 0,1, 1,1, 1,0)) + # return {(0,0): 0, (0,1): 1, (1,1): 2, (1,0): 3} + # === Default UV Coords (one image per face) === + + # === collect, remove duplicates, add indices, and write the uv list === + uvdata = cStringIO.StringIO() + uvcoords = {} + uvidx = 0 + for i in range(len(mesh.faces)): + if not i%100 and mod_meshtools.show_progress: + Blender.Window.DrawProgressBar(float(i)/len(mesh.faces), "Writing UV Coords") + numfaceverts = len(mesh.faces[i].v) + for j in range(numfaceverts-1, -1, -1): # Reverse order + u,v = mesh.faces[i].uv[j] + if not uvcoords.has_key((u,v)): + uvcoords[(u,v)] = uvidx + uvidx += 1 + uvdata.write(struct.pack("<ff", u,v)) + uvdata = uvdata.getvalue() + + numuvcoords = len(uvdata)/8 + data.write(struct.pack("<l", numuvcoords)) + data.write(uvdata) + #print "Number of uvcoords:", numuvcoords, '=', len(uvcoords) + return uvcoords + +# === Write Face List === +def write_FaceList(data, mesh, uvcoords): + data.write(struct.pack("<l", len(mesh.faces))) + for i in range(len(mesh.faces)): + if not i%100 and mod_meshtools.show_progress: + Blender.Window.DrawProgressBar(float(i)/len(mesh.faces), "Writing Faces") + numfaceverts = len(mesh.faces[i].v) + data.write(struct.pack("<B", 0x10)) # Cull Back Faces Flag + data.write(struct.pack("<h", numfaceverts)) + data.write(struct.pack("<h", 0)) # Material Index + for j in range(numfaceverts-1, -1, -1): # Reverse order + index = mesh.faces[i].v[j].index + if mesh.hasFaceUV(): + uv = mesh.faces[i].uv[j] + uvidx = uvcoords[uv] + else: + uvidx = 0 + data.write(struct.pack("<ll", index, uvidx)) + +# =========================================== +# === Generate VCol (Vertex Colors) Chunk === +# =========================================== +def generate_vcol(mesh): + data = cStringIO.StringIO() + data.write(struct.pack("<l", len(mesh.faces))) + uniquecolors = {} + unique_alpha = {} + for i in range(len(mesh.faces)): + if not i%100 and mod_meshtools.show_progress: + Blender.Window.DrawProgressBar(float(i)/len(mesh.faces), "Writing Vertex Colors") + numfaceverts = len(mesh.faces[i].v) + data.write(struct.pack("<ll", i, numfaceverts)) + for j in range(numfaceverts-1, -1, -1): # Reverse order + r = mesh.faces[i].col[j].r + g = mesh.faces[i].col[j].g + b = mesh.faces[i].col[j].b + a = 100 # 100 is opaque in ts + uniquecolors[(r,g,b)] = None + unique_alpha[mesh.faces[i].col[j].a] = None + data.write(struct.pack("<BBBB", r,g,b,a)) + + #print "uniquecolors:", uniquecolors.keys() + #print "unique_alpha:", unique_alpha.keys() + if len(uniquecolors) == 1: + return None + else: + return data.getvalue() + +# ================================== +# === Generate Unit (Size) Chunk === +# ================================== +def generate_unit(): + data = cStringIO.StringIO() + data.write(struct.pack("<h", 2)) + return data.getvalue() + +# ====================================== +# === Generate Mat1 (Material) Chunk === +# ====================================== +def generate_mat1(mesh): + data = cStringIO.StringIO() + data.write(struct.pack("<h", 0)) + data.write(struct.pack("<ccB", "p", "a", 0)) + data.write(struct.pack("<fff", 1.0, 1.0, 1.0)) # rgb (0.0 - 1.0) + data.write(struct.pack("<fffff", 1, 1, 0, 0, 1)) + if mesh.hasFaceUV(): + tex_mapname = r"c:\image\maps\one-dot.tga" + data.write("t:") + data.write(struct.pack("<B", 0x00)) + data.write(struct.pack("<h", len(tex_mapname))) + data.write(tex_mapname) + data.write(struct.pack("<4f", 0,0, 1,1)) + return data.getvalue() + +# ============================ +# === Generate Group Chunk === +# ============================ +def generate_grou(name): + data = cStringIO.StringIO() + write_ObjectName(data, name) + data.write(struct.pack("<12f", 0,0,0, 1,0,0, 0,1,0, 0,0,1)) + data.write(struct.pack("<12f", 1,0,0,0, 0,1,0,0, 0,0,1,0)) + return data.getvalue() + +def fs_callback(filename): + if filename.find('.cob', -4) <= 0: filename += '.cob' + write(filename) + +Blender.Window.FileSelector(fs_callback, "COB Export") + +# === Matrix Differences between Blender & trueSpace === +# +# For the 'Local Axes' values: +# The x, y, and z-axis represent a simple rotation matrix. +# This is equivalent to Blender's object matrix before it was +# combined with the object's scaling matrix. Dividing each value +# by the appropriate scaling factor (and transposing at the same +# time) produces the original rotation matrix. +# +# For the 'Current Position' values: +# This is equivalent to Blender's object matrix except that the +# last row is omitted and the xyz location is used in the last +# column. Binary format uses a 4x3 matrix, ascii format uses a 4x4 +# matrix. +# +# For Cameras: The matrix is a little confusing. diff --git a/release/scripts/truespace_import.py b/release/scripts/truespace_import.py new file mode 100644 index 00000000000..2b4f393d81f --- /dev/null +++ b/release/scripts/truespace_import.py @@ -0,0 +1,229 @@ +#!BPY + +""" +Name: 'TrueSpace...' +Blender: 232 +Group: 'Import' +Tooltip: 'Import trueSpace Object File Format (*.cob)' +""" + +# +---------------------------------------------------------+ +# | Copyright (c) 2001 Anthony D'Agostino | +# | http://www.redrival.com/scorpius | +# | scorpius@netzero.com | +# | June 12, 2001 | +# | Released under the Blender Artistic Licence (BAL) | +# | Import Export Suite v0.5 | +# +---------------------------------------------------------+ +# | Read and write Caligari trueSpace File Format (*.cob) | +# +---------------------------------------------------------+ + +import Blender, mod_meshtools +import struct, chunk, os, cStringIO, time + +# ======================= +# === COB Chunk Class === +# ======================= +class CobChunk(chunk.Chunk): + def __init__(self, file, align = 0, bigendian = 0, inclheader = 0): #$ COB + self.closed = 0 + self.align = align # whether to align to word (2-byte) boundaries + if bigendian: + strflag = '>' + else: + strflag = '<' + self.file = file + self.chunkname = file.read(4) + if len(self.chunkname) < 4: + raise EOFError + self.major_ver, = struct.unpack(strflag+'h', file.read(2)) #$ COB + self.minor_ver, = struct.unpack(strflag+'h', file.read(2)) #$ COB + self.chunk_id, = struct.unpack(strflag+'l', file.read(4)) #$ COB + self.parent_id, = struct.unpack(strflag+'l', file.read(4)) #$ COB + try: + self.chunksize = struct.unpack(strflag+'l', file.read(4))[0] + except struct.error: + raise EOFError + if inclheader: + self.chunksize = self.chunksize - 20 #$ COB + self.size_read = 0 + try: + self.offset = self.file.tell() + except: + self.seekable = 0 + else: + self.seekable = 1 + +# ============================ +# === Read COB File Header === +# ============================ +def read_header(file): + magic, = struct.unpack("<9s", file.read(9)) + version, = struct.unpack("<6s", file.read(6)) + format, = struct.unpack("<1c", file.read(1)) + endian, = struct.unpack("<2s", file.read(2)) + misc, = struct.unpack("13s", file.read(13)) + newline, = struct.unpack("<1B", file.read(1)) + return format + +# ======================================== +# === Read PolH (Polygonal Data) Chunk === +# ======================================== +def read_polh(chunk): + data = cStringIO.StringIO(chunk.read()) + oname = read_ObjectName(data) + local = read_LocalAxes(data) + crpos = read_CurrentPosition(data) + verts = read_VertexList(data) + uvcoords = read_UVCoords(data) + faces, facesuv = read_FaceList(data, chunk) + return verts, faces, oname, facesuv, uvcoords + +# === Read Object Name === +def read_ObjectName(data): + dupecount, namelen = struct.unpack("<hh", data.read(4)) + objname = data.read(namelen) + if objname == '': objname = 'NoName' + if dupecount > 0: objname = objname + ', ' + `dupecount` + return objname + +# === Read Local Axes === +def read_LocalAxes(data): + location = struct.unpack("<fff", data.read(12)) + rotation_matrix=[] + for i in range(3): + row = struct.unpack("<fff", data.read(12)) + #print "% f % f % f" % row + rotation_matrix.append(list(row)) + #print + rotation_matrix = mod_meshtools.transpose(rotation_matrix) + +# === Read Current Position === +def read_CurrentPosition(data): + transformation_matrix=[] + for i in range(3): + row = struct.unpack("<ffff", data.read(16)) + #print "% f % f % f % f" % row + transformation_matrix.append(list(row)) + #print + +# === Read Vertex List === +def read_VertexList(data): + verts = [] + numverts, = struct.unpack("<l", data.read(4)) + for i in range(numverts): + if not i%100 and mod_meshtools.show_progress: + Blender.Window.DrawProgressBar(float(i)/numverts, "Reading Verts") + x, y, z = struct.unpack("<fff", data.read(12)) + verts.append((y, -x, z)) + return verts + +# === Read UV Vertex List === +def read_UVCoords(data): + uvcoords = [] + numuvcoords, = struct.unpack("<l", data.read(4)) + for i in range(numuvcoords): + if not i%100 and mod_meshtools.show_progress: + Blender.Window.DrawProgressBar(float(i)/numuvcoords, "Reading UV Coords") + uv = struct.unpack("<ff", data.read(8)) + uvcoords.append(uv) + + #print "num uvcoords:", len(uvcoords) + #for i in range(len(uvcoords)): print "%.4f, %.4f" % uvcoords[i] + return uvcoords + +# === Read Face List === +def read_FaceList(data, chunk): + faces = [] ; facesuv = [] + numfaces, = struct.unpack("<l", data.read(4)) + for i in range(numfaces): + if not i%100 and mod_meshtools.show_progress: + Blender.Window.DrawProgressBar(float(i)/numfaces, "Reading Faces") + + face_flags, numfaceverts = struct.unpack("<Bh", data.read(3)) + + if (face_flags & 0x08) == 0x08: + print "face #" + `i-1` + " contains a hole." + pass + else: + data.read(2) # Material Index + + facev = [] ; faceuv = [] + for j in range(numfaceverts): + index, uvidx = struct.unpack("<ll", data.read(8)) + facev.append(index); faceuv.append(uvidx) + facev.reverse() ; faceuv.reverse() + faces.append(facev) ; facesuv.append(faceuv) + + if chunk.minor_ver == 6: + DrawFlags, RadiosityQuality = struct.unpack("<lh", data.read(6)) + if chunk.minor_ver == 8: + DrawFlags, = struct.unpack("<l", data.read(4)) + + return faces , facesuv + +# ============================= +# === Read trueSpace Format === +# ============================= +def read(filename): + start = time.clock() + file = open(filename, "rb") + + # === COB header === + if read_header(file) == 'A': + print "Can't read ASCII format" + return + + while 1: + try: + cobchunk = CobChunk(file) + except EOFError: + break + if cobchunk.chunkname == "PolH": + verts, faces, objname, facesuv, uvcoords = read_polh(cobchunk) + mod_meshtools.create_mesh(verts, faces, objname, facesuv, uvcoords) + + ''' + object = Blender.Object.GetSelected() + obj = Blender.Object.Get(objname) + obj.loc = location + obj.rot = mod_meshtools.mat2euler(rotation_matrix) + obj.size = (transformation_matrix[0][0]/rotation_matrix[0][0], + transformation_matrix[1][1]/rotation_matrix[1][1], + transformation_matrix[2][2]/rotation_matrix[2][2]) + + ''' + else: + cobchunk.skip() + + Blender.Window.DrawProgressBar(1.0, '') # clear progressbar + file.close() + end = time.clock() + seconds = " in %.2f %s" % (end-start, "seconds") + message = "Successfully imported " + os.path.basename(filename) + seconds + mod_meshtools.print_boxed(message) + #print "objname :", objname + #print "numverts:", len(verts) + #print "numfaces:", len(faces) + +def fs_callback(filename): + read(filename) + +Blender.Window.FileSelector(fs_callback, "COB Import") + +# === Matrix Differences between Blender & trueSpace === +# +# For the 'Local Axes' values: +# The x, y, and z-axis represent a simple rotation matrix. +# This is equivalent to Blender's object matrix before it was +# combined with the object's scaling matrix. Dividing each value +# by the appropriate scaling factor (and transposing at the same +# time) produces the original rotation matrix. +# +# For the 'Current Position' values: +# This is equivalent to Blender's object matrix except that the +# last row is omitted and the xyz location is used in the last +# column. Binary format uses a 4x3 matrix, ascii format uses a 4x4 +# matrix. +# +# For Cameras: The matrix is a little confusing. diff --git a/release/scripts/unweld044.py b/release/scripts/unweld044.py new file mode 100644 index 00000000000..481aeab8aa2 --- /dev/null +++ b/release/scripts/unweld044.py @@ -0,0 +1,366 @@ +#!BPY +""" Registration info for Blender menus: <- these words are ignored +Name: 'UnWeld' +Blender: 232 +Group: 'Modifiers' +Tip: 'unweld all faces from one selected and commun vertex. Made vertex bevelling' +""" + +# ------------------------------------------ +# Un-Weld script 0.4.4 beta +# +# split all faces from one selected vertex +# (c) 2004 J-M Soler released under Blender Artistic License +#---------------------------------------------- +# Official Page : +# http://jmsoler.free.fr/didacticiel/blender/tutor/cpl_faces2vertex.htm#exemple +# Communicate problems and errors on: +# http://www.zoo-logique.org/3D.Blender/newsportal/thread.php?group=3D.Blender +#---------------------------------------------- +# Blender Artistic License +# http://download.blender.org/documentation/html/x21254.html +#--------------------------------------------- +# Changelog +#---------------------------------------------- +# 25/05 : +# -- separate choise, normal (same place) or spread at random, middle of the face +# -- works on several vertices too +# -- Quite vertex bevelling on <<lone>> vertex : create hole in faces around this +# vertex +# 03/06 : +# -- a sort of "bevelled vertex" extrusion controled by horizontal mouse +# displacement. just a beta test to the mouse control. +#---------------------------------------------- +# Page officielle : +# http://jmsoler.free.fr/didacticiel/blender/tutor/cpl_faces2vertex.htm#exemple +# Communiquer les problemes et erreurs sur: +# http://www.zoo-logique.org/3D.Blender/newsportal/thread.php?group=3D.Blender +# Blender Artistic License +# http://download.blender.org/documentation/html/x21254.html +#--------------------------------------------- +# Changelog +#---------------------------------------------- +# 25/05 : +# -- separation du choix, normal ou dispersion hasardeuse, milieu de face +# -- sommets multiples / +# -- Quite vertex bevelling on lone vertex : create hole in faces around the +# vertex +# 03/06 : +# -- a sort of "bevelled vertex" extrusion controled by horizontal mouse +# displacement +#---------------------------------------------- + +import Blender +from Blender import Noise +from Blender.Draw import * +from Blender.BGL import * + +Nr=Noise.random +decal=0.03 +t=[0.0,0.0,0.0] +pl=[] +orig=[] + +DEBUG = 0 +SUBSURF=0 +DIM=Create(1.0) + +def Tampon(v,t): + for n in range(len(v)): t[n]=t[n]+v[n] + return t + +def freeTampon(t): + for n in range(3): t[n]=0.0 + return t + +def TamponMoyen(t,f): + for n in range(3): t[n]/=len(f) + return t + +def appliqueMoyenne(v,t): + for n in range(len(v)): v[n]=t[n] + return v + +def docF(f0,f): + try: + f0.mat=f.mat + f0.uv=f.uv + f0.col=f.col + f0.image=f.image + return f0 + except: + pass + +def listConnecterFace(me,lebon): + listf2v={} + #tri des faces connectees aux sommets selectionnes + for f in me.faces: + for v in f.v: + if v==lebon: + if v.index not in listf2v.keys(): + listf2v[me.verts.index(v)]=[f] + elif f not in listf2v[me.verts.index(v)]: + listf2v[me.verts.index(v)].append(f) + return listf2v + +def creerFaceSupplementaire(me,lebon,listf2v): + global t + for f in listf2v[lebon.index]: + f0=Blender.NMesh.Face() + if result==3: t=freeTampon(t) + for v in f.v: + if result==3: t=Tampon(v,t) + if v!=lebon: + f0.append(v) + else: + if result==2: + nv=Blender.NMesh.Vert(lebon.co[0]+Nr()*decal,lebon.co[1]+Nr()*decal,lebon.co[2]+Nr()*decal) + else: + nv=Blender.NMesh.Vert(lebon.co[0],lebon.co[1],lebon.co[2]) + me.verts.append(nv) + f0.append(me.verts[me.verts.index(nv)]) + localise=me.verts.index(nv) + docF(f0,f) + + if result==3: + t=TamponMoyen(t,f0.v) + me.verts[localise]=appliqueMoyenne(me.verts[localise],t) + me.faces.append(f0) + del me.verts[me.verts.index(lebon)] + for f in listf2v[lebon.index]: + del me.faces[me.faces.index(f)] + return me + +def collecte_edge(listf2v,me,lebon): + back=0 + edgelist = [] + vertlist = [] + if DEBUG : print listf2v + for face in listf2v[lebon.index]: + if len(face.v) == 4: + vlist = [0,1,2,3,0] + elif len(face.v) == 3: + vlist = [0,1,2,0] + else: + vlist = [0,1] + for i in range(len(vlist)-1): + vert0 = min(face.v[vlist[i]].index,face.v[vlist[i+1]].index) + vert1 = max(face.v[vlist[i]].index,face.v[vlist[i+1]].index) + edgeinlist = 0 + if vert0==lebon.index or vert1==lebon.index: + for edge in edgelist: + if ((edge[0]==vert0) and (edge[1]==vert1)): + edgeinlist = 1 + edge[2] = edge[2]+1 + edge.append(me.faces.index(face)) + break + if edgeinlist==0: + edge = [vert0,vert1,1,me.faces.index(face)] + edgelist.append(edge) + + for edge in edgelist: + #print edge + if len(edge)==4: + del edgelist[edgelist.index(edge)] + + edges=len(edgelist) + if DEBUG : print 'number of edges : ',edges," Edge list : " ,edgelist + return edges, edgelist + +MouseClickG= Blender.Draw.LEFTMOUSE +MouseClickD= Blender.Draw.RIGHTMOUSE +MouseClickM= Blender.Draw.MIDDLEMOUSE + +mouse_x=1 +mouse_y=1 + +x=1 +y=1 + +debut=0 + +def D(): + size=Buffer(GL_FLOAT, 4) + glGetFloatv(GL_SCISSOR_BOX, size) + size= size.list + glColor3f(0.1, 0.1, 0.15) + glRasterPos2f(10, size[3]-16) + Text("Quit = Qkey") + glRasterPos2f(10, size[3]-36) + Text("Mouse to the Rigth = Increase") + glRasterPos2f(10, size[3]-56) + Text("Mouse to the Left = Decrease") + +def E(evt,val): + global mouse_x,x,pl,orig,me,debut + global mouse_y,y, MouseClickG,MouseClickD,MouseClickM + if (evt== QKEY): Exit() + + if (evt == MOUSEX): + mouse_x = val + pos=x-mouse_x + x=mouse_x + if pos==0: + pos=1 + deplace(pl,orig,abs(pos)/pos) + + if (evt == MOUSEY): mouse_y = val + +def BE(evt): + pass + + +def deplace(pl,orig,n): + global me, OBJECT + for p in pl: + #print p, orig,len(me.verts) + me.verts[p].co[0]+=n*orig[0] + me.verts[p].co[1]+=n*orig[1] + me.verts[p].co[2]+=n*orig[2] + me.update() + Blender.Redraw() + + +def VertexBevel(result): + global t,pl, orig,me, SUBSURF + unique=0 + for v in me.verts: + if v.sel==1: + lebon=v + unique+=1 + + if unique==1: + edges=0 + edgelist=[] + vertlist=[] + orig=lebon.no[:] + listf2v=listConnecterFace(me,lebon) + edges, edgelist = collecte_edge(listf2v,me,lebon) + for f in listf2v[lebon.index]: + f0=Blender.NMesh.Face() + for v in f.v: + if v!=lebon: + f0.append(v) + else: + nv=Blender.NMesh.Vert(lebon.co[0],lebon.co[1],lebon.co[2]) + nv.sel=1 + me.verts.append(nv) + f0.append(me.verts[me.verts.index(nv)]) + for e in edgelist: + if e[-1]==me.faces.index(f) or e[-2]==me.faces.index(f): + if me.verts.index(nv) not in e: + e.insert(0,me.verts.index(nv)) + docF(f0,f) + me.faces.append(f0) + vertlist.append([me.verts.index(nv),me.faces.index(f)]) + for e in edgelist : + del e[e.index(lebon.index)] + f0=Blender.NMesh.Face() + for n in range(3): + f0.v.append(me.verts[e[n]]) + me.faces.append(f0); + + for ve in vertlist: + t=freeTampon(t) + for v in me.faces[ve[1]].v: + t=Tampon(v,t) + t=TamponMoyen(t,me.faces[ve[1]].v) + ve.append(t[:]) + me.verts[ve[0]]=appliqueMoyenne(me.verts[ve[0]],t) + + def swap(x,y): + return y,x + + p=[[edgelist[0][0],edgelist[0][1]]] + while len(p)!=len(edgelist): + for n in range(1,len(edgelist)) : + if p[-1][1]== edgelist[n][0]: + p.append([edgelist[n][0],edgelist[n][1]]) + n+=1 + elif p[-1][1]== edgelist[n][1]: + edgelist[n][0],edgelist[n][1]=swap(edgelist[n][0],edgelist[n][1]) + p.append([edgelist[n][0],edgelist[n][1]]) + n+=1 + if len(p)%2==0: + P0=p[:(len(p))/2] ; P1=p[len(p)/2:]; P1.reverse() + for s in range(len(P0)-1): + f0=Blender.NMesh.Face() + table=[P0[s][0],P0[s][1],P1[s+1][0],P1[s+1][1]] + for t in table:f0.v.append(me.verts[t]) + me.faces.append(f0) + elif len(p) >3 : + P0=p[:(len(p)-1)/2];P1=p[(len(p)-1)/2:-1]; P1.reverse() + for s in range(len(P0)-1): + f0=Blender.NMesh.Face() + table=[P0[s][0],P0[s][1],P1[s+1][0],P1[s+1][1]] + for t in table:f0.v.append(me.verts[t]) + me.faces.append(f0) + f0=Blender.NMesh.Face() + table=[p[-1][0],P0[0][0],P1[-1][1]] + for t in table:f0.v.append(me.verts[t]) + me.faces.append(f0) + + elif len(p) ==3 : + if DEBUG :print P0,P1 + f0=Blender.NMesh.Face() + table=[p[0][0],p[0][1],p[1][1]] + for t in table:f0.v.append(me.verts[t]) + me.faces.append(f0) + + for f in listf2v[lebon.index]: + del me.faces[me.faces.index(f)] + del me.verts[me.verts.index(lebon)] + me.update() + + if me.mode&Blender.NMesh.Modes['SUBSURF']: + me.mode-=Blender.NMesh.Modes['SUBSURF'] + SUBSURF=1 + me.update() + OBJECT[0].makeDisplayList() + + if result==5: + pl=[] + for s in me.verts: + if s.sel==1: + pl.append(s.index) + Blender.Draw.Register(D,E,BE) + + """ + if SUBSURF==1 : + me.mode+=Blender.NMesh.Modes['SUBSURF'] + me.update() + OBJECT[0].makeDisplayList() + """ + else: + name = " It could leave only one selected vertex %t | ok %x1 ?" + result = Blender.Draw.PupMenu(name) + +OBJECT=Blender.Object.GetSelected() + +if len(OBJECT)!=0: + if OBJECT[0].getType()=='Mesh': + name = "Un-Weld, OK ? %t| unbind points %x1| with noise ? %x2| middle face ? %x3| static bevel vertex ? %x4| moving bevel vertex ? %x5|" + result = Blender.Draw.PupMenu(name) + if result: + me=OBJECT[0].getData() + unique=0 + if result<4: + #tri des sommets selectionnes + for v in me.verts: + if v.sel==1: + lebon=v + if DEBUG : print lebon + #dictionnaires des faces connectees aux sommets selectionnes + listf2v=listConnecterFace(me,lebon) + me=creerFaceSupplementaire(me,lebon,listf2v) + OBJECT[0].link(me) + OBJECT[0].makeDisplayList() + else: + VertexBevel(result) + OBJECT[0].makeDisplayList() + + else: + name = "Nothing to do! Are you sure ?" + result = Blender.Draw.PupMenu(name) + + diff --git a/release/scripts/uv_export.py b/release/scripts/uv_export.py index ef224b6eba8..5a494952487 100644 --- a/release/scripts/uv_export.py +++ b/release/scripts/uv_export.py @@ -28,7 +28,13 @@ Tooltip: 'Export the UV face layout of the selected object to a .TGA file' # # ***** END GPL LICENCE BLOCK ***** # -------------------------------------------------------------------------- -# thanks to jms for the tga functions +# thanks to jms for the tga functions: +# Writetga and buffer functions +# (c) 2002-2004 J-M Soler released under GPL licence +# Official Page : +# http://jmsoler.free.fr/didacticiel/blender/tutor/write_tga_pic.htm +# Communicate problems and errors on: +# http://www.zoo-logique.org/3D.Blender/newsportal/thread.php?group=3D.Blender # -------------------------- # Version 1.1 # Clear a bug that crashed the script when UV coords overlapped in the same faces diff --git a/release/scripts/videoscape_export.py b/release/scripts/videoscape_export.py index 6f7b0849dfd..6cfbd3e9e1e 100644 --- a/release/scripts/videoscape_export.py +++ b/release/scripts/videoscape_export.py @@ -9,8 +9,8 @@ Tooltip: 'Export selected mesh to VideoScape File Format (*.obj)' # +---------------------------------------------------------+ # | Copyright (c) 2001 Anthony D'Agostino | -# | http://ourworld.compuserve.com/homepages/scorpius | -# | scorpius@compuserve.com | +# | http://www.redrival.com/scorpius | +# | scorpius@netzero.com | # | June 5, 2001 | # | Released under the Blender Artistic Licence (BAL) | # | Import Export Suite v0.5 | @@ -22,7 +22,6 @@ Tooltip: 'Export selected mesh to VideoScape File Format (*.obj)' import Blender, mod_meshtools #import time -import mod_flags # ===================================== # ====== Write VideoScape Format ====== @@ -37,7 +36,7 @@ def write(filename): mesh = Blender.NMesh.GetRaw(meshname) obj = Blender.Object.Get(objname) - if not mesh.hasVertexColours(): + if not mod_meshtools.has_vertex_colors(mesh): message = "Please assign vertex colors before exporting.\n" message += objname + " object was not saved." mod_meshtools.print_boxed(message) @@ -51,7 +50,7 @@ def write(filename): # === Write Vertex List & Vertex Colors === for i in range(len(mesh.verts)): - if not i%100 and mod_flags.show_progress: + if not i%100 and mod_meshtools.show_progress: Blender.Window.DrawProgressBar(float(i)/len(mesh.verts), "Writing Verts") file.write("% f % f % f 0x" % tuple(mesh.verts[i].co)) for j in range(len(vcols[i])): @@ -60,7 +59,7 @@ def write(filename): # === Write Face List === for i in range(len(mesh.faces)): - if not i%100 and mod_flags.show_progress: + if not i%100 and mod_meshtools.show_progress: Blender.Window.DrawProgressBar(float(i)/len(mesh.faces), "Writing Faces") file.write("%d " % len(mesh.faces[i].v)) # numfaceverts for j in range(len(mesh.faces[i].v)): @@ -86,7 +85,7 @@ vcolor_div = lambda u, s: [u[0]/s, u[1]/s, u[2]/s, u[3]/s] def average_vertexcolors(mesh, debug=0): vertexcolors = {} for i in range(len(mesh.faces)): # get all vcolors that share this vertex - if not i%100 and mod_flags.show_progress: Blender.Window.DrawProgressBar(float(i)/len(mesh.verts), "Finding Shared VColors") + if not i%100 and mod_meshtools.show_progress: Blender.Window.DrawProgressBar(float(i)/len(mesh.verts), "Finding Shared VColors") for j in range(len(mesh.faces[i].v)): index = mesh.faces[i].v[j].index color = mesh.faces[i].col[j] @@ -95,7 +94,7 @@ def average_vertexcolors(mesh, debug=0): if debug: print 'before'; vcprint(vertexcolors) for i in range(len(vertexcolors)): # average them - if not i%100 and mod_flags.show_progress: Blender.Window.DrawProgressBar(float(i)/len(mesh.verts), "Averaging Vertex Colors") + if not i%100 and mod_meshtools.show_progress: Blender.Window.DrawProgressBar(float(i)/len(mesh.verts), "Averaging Vertex Colors") vcolor = [0,0,0,0] # rgba for j in range(len(vertexcolors[i])): vcolor = vcolor_add(vcolor, vertexcolors[i][j]) @@ -111,7 +110,7 @@ def average_vertexcolors_slow_1(mesh, debug=0): vertexcolors = [] i = 0 for vertex in mesh.verts: - if not i%100 and mod_flags.show_progress: Blender.Window.DrawProgressBar(float(i)/len(mesh.verts), "Averaging Vertex Colors") + if not i%100 and mod_meshtools.show_progress: Blender.Window.DrawProgressBar(float(i)/len(mesh.verts), "Averaging Vertex Colors") i += 1 vcolor = [0,0,0,0] # rgba shared = 0 @@ -133,7 +132,7 @@ def average_vertexcolors_slow_1(mesh, debug=0): def average_vertexcolors_slow_2(mesh, debug=0): vertexcolors = [] for i in range(len(mesh.verts)): - if not i%100 and mod_flags.show_progress: Blender.Window.DrawProgressBar(float(i)/len(mesh.verts), "Averaging Vertex Colors") + if not i%100 and mod_meshtools.show_progress: Blender.Window.DrawProgressBar(float(i)/len(mesh.verts), "Averaging Vertex Colors") vcolor = [0,0,0,0] # rgba shared = 0 for j in range(len(mesh.faces)): @@ -153,7 +152,7 @@ def average_vertexcolors_slow_2(mesh, debug=0): def average_vertexcolors_slow_3(mesh, debug=0): vertexcolors = [] for i in range(len(mesh.verts)): - if not i%100 and mod_flags.show_progress: Blender.Window.DrawProgressBar(float(i)/len(mesh.verts), "Averaging Vertex Colors") + if not i%100 and mod_meshtools.show_progress: Blender.Window.DrawProgressBar(float(i)/len(mesh.verts), "Averaging Vertex Colors") vcolor = [0,0,0,0] # rgba shared = 0 for j in range(len(mesh.faces)): diff --git a/release/scripts/wings_export.py b/release/scripts/wings_export.py new file mode 100644 index 00000000000..46112ac83fd --- /dev/null +++ b/release/scripts/wings_export.py @@ -0,0 +1,337 @@ +#!BPY + +""" +Name: 'Wings3D...' +Blender: 232 +Group: 'Export' +Tooltip: 'Export selected mesh to Wings3D File Format (*.wings)' +""" + +# +---------------------------------------------------------+ +# | Copyright (c) 2002 Anthony D'Agostino | +# | http://www.redrival.com/scorpius | +# | scorpius@netzero.com | +# | Feb 19, 2002 | +# | Released under the Blender Artistic Licence (BAL) | +# | Import Export Suite v0.5 | +# +---------------------------------------------------------+ +# | Read and write Wings3D File Format (*.wings) | +# +---------------------------------------------------------+ + +import Blender, mod_meshtools +import struct, time, sys, os, zlib, cStringIO + +# =============================================== +# === Write The 'Header' Common To All Chunks === +# =============================================== +def write_chunkheader(data, version, tag, name): + data.write(struct.pack(">BB", version, tag)) + data.write(struct.pack(">BH", 0x64, len(name))) + data.write(name) + +# =================== +# === Write Faces === +# =================== +def write_faces(data, mesh): + numfaces = len(mesh.faces) + data.write(struct.pack(">BL", 0x6C, numfaces)) + #for i in range(numfaces): + # if not i%100 and mod_meshtools.show_progress: Blender.Window.DrawProgressBar(float(i)/numfaces, "Writing Faces") + # data.write("\x6A") + data.write("\x6A" * numfaces) # same, but faster than the above loop + data.write("\x6A") + +# =================== +# === Write Verts === +# =================== +def write_verts(data, mesh): + numverts = len(mesh.verts) + data.write(struct.pack(">BL", 0x6C, numverts)) + for i in range(numverts): + if not i%100 and mod_meshtools.show_progress: Blender.Window.DrawProgressBar(float(i)/numverts, "Writing Verts") + data.write(struct.pack(">BLBL", 0x6C, 1, 0x6D, 24)) + #data.write("\x6c\x00\x00\x00\x01\x6D\x00\x00\x00\x30") + x, y, z = mesh.verts[i].co + data.write(struct.pack(">ddd", x, z, -y)) + data.write("\x6A") + data.write("\x6A") + +# =================== +# === Write Edges === +# =================== +def write_edges(data, mesh, edge_table): + numedges = len(edge_table) + data.write(struct.pack(">BL", 0x6C, numedges)) + keys = edge_table.keys() + keys.sort() + for key in keys: + i = edge_table[key][6] + if not i%100 and mod_meshtools.show_progress: Blender.Window.DrawProgressBar(float(i)/numedges, "Writing Edges") + + if mod_meshtools.has_vertex_colors(mesh): + r1, g1, b1 = edge_table[key][7] + r2, g2, b2 = edge_table[key][8] + data.write("\x6C\x00\x00\x00\x02") + data.write("\x68\x02\x64\x00\x05color") + data.write("\x6D\x00\x00\x00\x30") + data.write(struct.pack(">dddddd", r1, g1, b1, r2, g2, b2)) + #print "%f %f %f - %f %f %f" % (r1, g1, b1, r2, g2, b2) + else: + data.write("\x6C\x00\x00\x00\x01") # BL + + #$write_chunkheader(data, 0x68, 0x09, "edge") + data.write("\x68\x09\x64\x00\x04edge") # faster + + # Sv Ev (Reversed) + data.write(struct.pack(">BLBL", 0x62, key[1], 0x62, key[0])) + + # Lf Rf LP LS RP RS + for i in range(6): + if edge_table[key][i] < 256: + data.write(struct.pack(">BB", 0x61, edge_table[key][i])) + else: + data.write(struct.pack(">BL", 0x62, edge_table[key][i])) + + data.write("\x6A") + + data.write("\x6A") + +# =============================== +# === Write The Material Mode === +# =============================== +def write_mode(data, mesh): + data.write("\x6A") + data.write(struct.pack(">BL", 0x6C, 1)) + write_chunkheader(data, 0x68, 0x02, "mode") + if mod_meshtools.has_vertex_colors(mesh): + data.write(struct.pack(">BH6s", 0x64, 6, "vertex")) + else: + data.write(struct.pack(">BH8s", 0x64, 8, "material")) + data.write("\x6A") + +# ====================== +# === Write Material === +# ====================== +def write_material(data, mesh): + data.write("\x6A") + data.write(struct.pack(">BL", 0x6C, 1)) + write_chunkheader(data, 0x68, 0x02, "my default") + + data.write(struct.pack(">BL", 0x6C, 2)) + write_chunkheader(data, 0x68, 0x02, "maps") + data.write("\x6A") + write_chunkheader(data, 0x68, 0x02, "opengl") + + # === The Material Components === + data.write(struct.pack(">BL", 0x6C, 5)) + + write_chunkheader(data, 0x68, 0x02, "diffuse") + data.write("\x68\x04") + data.write("\x63"+"1.00000000000000000000"+"e+000"+"\x00"*4) + data.write("\x63"+"1.00000000000000000000"+"e+000"+"\x00"*4) + data.write("\x63"+"1.00000000000000000000"+"e+000"+"\x00"*4) + data.write("\x63"+"1.00000000000000000000"+"e+000"+"\x00"*4) + + write_chunkheader(data, 0x68, 0x02, "ambient") + data.write("\x68\x04") + data.write("\x63"+"1.00000000000000000000"+"e+000"+"\x00"*4) + data.write("\x63"+"1.00000000000000000000"+"e+000"+"\x00"*4) + data.write("\x63"+"1.00000000000000000000"+"e+000"+"\x00"*4) + data.write("\x63"+"1.00000000000000000000"+"e+000"+"\x00"*4) + + write_chunkheader(data, 0x68, 0x02, "specular") + data.write("\x68\x04") + data.write("\x63"+"1.00000000000000000000"+"e+000"+"\x00"*4) + data.write("\x63"+"1.00000000000000000000"+"e+000"+"\x00"*4) + data.write("\x63"+"1.00000000000000000000"+"e+000"+"\x00"*4) + data.write("\x63"+"1.00000000000000000000"+"e+000"+"\x00"*4) + + write_chunkheader(data, 0x68, 0x02, "emission") + data.write("\x68\x04") + data.write("\x63"+"0.00000000000000000000"+"e+000"+"\x00"*4) + data.write("\x63"+"0.00000000000000000000"+"e+000"+"\x00"*4) + data.write("\x63"+"0.00000000000000000000"+"e+000"+"\x00"*4) + data.write("\x63"+"0.00000000000000000000"+"e+000"+"\x00"*4) + + write_chunkheader(data, 0x68, 0x02, "shininess") + data.write("\x63"+"0.00000000000000000000"+"e+000"+"\x00"*4) + + #write_chunkheader(data, 0x68, 0x02, "twosided") + #data.write(struct.pack(">BH4s", 0x64, 4, "true")) + + data.write("\x6A"*3) # use *4 if no ambient light + +# ===================== +# === Generate Data === +# ===================== +def generate_data(objname, edge_table, mesh): + data = cStringIO.StringIO() + + # === wings chunk === + write_chunkheader(data, 0x68, 0x03, "wings") + + numobjs = 1 # len(Blender.Object.GetSelected()) + data.write("\x61\x02\x68\x03") # misc bytes + data.write(struct.pack(">BL", 0x6C, numobjs)) + + # === object chunk === + write_chunkheader(data, 0x68, 0x04, "object") + data.write(struct.pack(">BH", 0x6B, len(objname))) + data.write(objname) + + # === winged chunk === + write_chunkheader(data, 0x68, 0x05, "winged") + write_edges(data, mesh, edge_table) + write_faces(data, mesh) + write_verts(data, mesh) + write_mode(data, mesh) + write_material(data, mesh) + write_ambient_light(data) + return data.getvalue() + +# =========================== +# === Write Ambient Light === +# =========================== +def write_ambient_light(data): + light = [ # A quick cheat ;) + 0x6C, 0x00, 0x00, 0x00, 0x01, 0x68, 0x02, 0x64, 0x00, 0x06, 0x6C, 0x69, + 0x67, 0x68, 0x74, 0x73, 0x6C, 0x00, 0x00, 0x00, 0x01, 0x68, 0x02, 0x6B, + 0x00, 0x07, 0x41, 0x6D, 0x62, 0x69, 0x65, 0x6E, 0x74, 0x6C, 0x00, 0x00, + 0x00, 0x08, 0x68, 0x02, 0x64, 0x00, 0x07, 0x76, 0x69, 0x73, 0x69, 0x62, + 0x6C, 0x65, 0x64, 0x00, 0x04, 0x74, 0x72, 0x75, 0x65, 0x68, 0x02, 0x64, + 0x00, 0x06, 0x6C, 0x6F, 0x63, 0x6B, 0x65, 0x64, 0x64, 0x00, 0x05, 0x66, + 0x61, 0x6C, 0x73, 0x65, 0x68, 0x02, 0x64, 0x00, 0x06, 0x6F, 0x70, 0x65, + 0x6E, 0x67, 0x6C, 0x6C, 0x00, 0x00, 0x00, 0x03, 0x68, 0x02, 0x64, 0x00, + 0x04, 0x74, 0x79, 0x70, 0x65, 0x64, 0x00, 0x07, 0x61, 0x6D, 0x62, 0x69, + 0x65, 0x6E, 0x74, 0x68, 0x02, 0x64, 0x00, 0x07, 0x61, 0x6D, 0x62, 0x69, + 0x65, 0x6E, 0x74, 0x68, 0x04, 0x63, 0x31, 0x2E, 0x30, 0x30, 0x30, 0x30, + 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, + 0x30, 0x30, 0x30, 0x30, 0x65, 0x2B, 0x30, 0x30, 0x30, 0x00, 0x00, 0x00, + 0x00, 0x63, 0x31, 0x2E, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, + 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, + 0x65, 0x2B, 0x30, 0x30, 0x30, 0x00, 0x00, 0x00, 0x00, 0x63, 0x31, 0x2E, + 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, + 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x65, 0x2B, 0x30, 0x30, + 0x30, 0x00, 0x00, 0x00, 0x00, 0x63, 0x31, 0x2E, 0x30, 0x30, 0x30, 0x30, + 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, + 0x30, 0x30, 0x30, 0x30, 0x65, 0x2B, 0x30, 0x30, 0x30, 0x00, 0x00, 0x00, + 0x00, 0x68, 0x02, 0x64, 0x00, 0x08, 0x70, 0x6F, 0x73, 0x69, 0x74, 0x69, + 0x6F, 0x6E, 0x68, 0x03, 0x63, 0x30, 0x2E, 0x30, 0x30, 0x30, 0x30, 0x30, + 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, + 0x30, 0x30, 0x30, 0x65, 0x2B, 0x30, 0x30, 0x30, 0x00, 0x00, 0x00, 0x00, + 0x63, 0x33, 0x2E, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, + 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x65, + 0x2B, 0x30, 0x30, 0x30, 0x00, 0x00, 0x00, 0x00, 0x63, 0x30, 0x2E, 0x30, + 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, + 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x65, 0x2B, 0x30, 0x30, 0x30, + 0x00, 0x00, 0x00, 0x00, 0x6A, 0x68, 0x02, 0x64, 0x00, 0x07, 0x76, 0x69, + 0x73, 0x69, 0x62, 0x6C, 0x65, 0x64, 0x00, 0x04, 0x74, 0x72, 0x75, 0x65, + 0x68, 0x02, 0x64, 0x00, 0x06, 0x6C, 0x6F, 0x63, 0x6B, 0x65, 0x64, 0x64, + 0x00, 0x05, 0x66, 0x61, 0x6C, 0x73, 0x65, 0x68, 0x02, 0x64, 0x00, 0x06, + 0x79, 0x61, 0x66, 0x72, 0x61, 0x79, 0x6C, 0x00, 0x00, 0x00, 0x0B, 0x68, + 0x02, 0x64, 0x00, 0x09, 0x6D, 0x69, 0x6E, 0x69, 0x6D, 0x69, 0x7A, 0x65, + 0x64, 0x64, 0x00, 0x04, 0x74, 0x72, 0x75, 0x65, 0x68, 0x02, 0x64, 0x00, + 0x05, 0x70, 0x6F, 0x77, 0x65, 0x72, 0x63, 0x31, 0x2E, 0x30, 0x30, 0x30, + 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, + 0x30, 0x30, 0x30, 0x30, 0x30, 0x65, 0x2B, 0x30, 0x30, 0x30, 0x00, 0x00, + 0x00, 0x00, 0x68, 0x02, 0x64, 0x00, 0x04, 0x74, 0x79, 0x70, 0x65, 0x64, + 0x00, 0x09, 0x68, 0x65, 0x6D, 0x69, 0x6C, 0x69, 0x67, 0x68, 0x74, 0x68, + 0x02, 0x64, 0x00, 0x07, 0x73, 0x61, 0x6D, 0x70, 0x6C, 0x65, 0x73, 0x62, + 0x00, 0x00, 0x01, 0x00, 0x68, 0x02, 0x64, 0x00, 0x05, 0x64, 0x65, 0x70, + 0x74, 0x68, 0x61, 0x03, 0x68, 0x02, 0x64, 0x00, 0x0A, 0x62, 0x61, 0x63, + 0x6B, 0x67, 0x72, 0x6F, 0x75, 0x6E, 0x64, 0x64, 0x00, 0x09, 0x75, 0x6E, + 0x64, 0x65, 0x66, 0x69, 0x6E, 0x65, 0x64, 0x68, 0x02, 0x64, 0x00, 0x18, + 0x62, 0x61, 0x63, 0x6B, 0x67, 0x72, 0x6F, 0x75, 0x6E, 0x64, 0x5F, 0x66, + 0x69, 0x6C, 0x65, 0x6E, 0x61, 0x6D, 0x65, 0x5F, 0x48, 0x44, 0x52, 0x49, + 0x6A, 0x68, 0x02, 0x64, 0x00, 0x19, 0x62, 0x61, 0x63, 0x6B, 0x67, 0x72, + 0x6F, 0x75, 0x6E, 0x64, 0x5F, 0x66, 0x69, 0x6C, 0x65, 0x6E, 0x61, 0x6D, + 0x65, 0x5F, 0x69, 0x6D, 0x61, 0x67, 0x65, 0x6A, 0x68, 0x02, 0x64, 0x00, + 0x1A, 0x62, 0x61, 0x63, 0x6B, 0x67, 0x72, 0x6F, 0x75, 0x6E, 0x64, 0x5F, + 0x65, 0x78, 0x70, 0x6F, 0x73, 0x75, 0x72, 0x65, 0x5F, 0x61, 0x64, 0x6A, + 0x75, 0x73, 0x74, 0x61, 0x00, 0x68, 0x02, 0x64, 0x00, 0x12, 0x62, 0x61, + 0x63, 0x6B, 0x67, 0x72, 0x6F, 0x75, 0x6E, 0x64, 0x5F, 0x6D, 0x61, 0x70, + 0x70, 0x69, 0x6E, 0x67, 0x64, 0x00, 0x05, 0x70, 0x72, 0x6F, 0x62, 0x65, + 0x68, 0x02, 0x64, 0x00, 0x10, 0x62, 0x61, 0x63, 0x6B, 0x67, 0x72, 0x6F, + 0x75, 0x6E, 0x64, 0x5F, 0x70, 0x6F, 0x77, 0x65, 0x72, 0x63, 0x31, 0x2E, + 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, + 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x65, 0x2B, 0x30, 0x30, + 0x30, 0x00, 0x00, 0x00, 0x00, 0x6A, 0x68, 0x02, 0x64, 0x00, 0x07, 0x76, + 0x69, 0x73, 0x69, 0x62, 0x6C, 0x65, 0x64, 0x00, 0x04, 0x74, 0x72, 0x75, + 0x65, 0x68, 0x02, 0x64, 0x00, 0x06, 0x6C, 0x6F, 0x63, 0x6B, 0x65, 0x64, + 0x64, 0x00, 0x05, 0x66, 0x61, 0x6C, 0x73, 0x65, 0x6A, 0x6A, 0x6A] + data.write("".join(map(chr, light))) + +# ========================== +# === Write Wings Format === +# ========================== +def write(filename): + start = time.clock() + + objects = Blender.Object.GetSelected() + objname = objects[0].name + meshname = objects[0].data.name + mesh = Blender.NMesh.GetRaw(meshname) + obj = Blender.Object.Get(objname) + + try: + edge_table = mod_meshtools.generate_edgetable(mesh) + except: + edge_table = {} + message = "Unable to generate\nEdge Table for mesh.\n" + message += "Object name is: " + meshname + mod_meshtools.print_boxed(message) + #return + + if 0: + import Tkinter, tkMessageBox + sys.argv=['wings.pyo','wings.pyc'] # ? + + #Tkinter.NoDefaultRoot() + win1 = Tkinter.Tk() + ans = tkMessageBox.showerror("Error", message) + win1.pack() + print ans + if ans: + win1.quit() + win1.mainloop() + + else: + from Tkinter import Label + sys.argv = 'wings.py' + widget = Label(None, text=message) + #widget.title("Error") + widget.pack() + widget.mainloop() + + data = generate_data(objname, edge_table, mesh) + dsize = len(data) + Blender.Window.DrawProgressBar(0.98, "Compressing Data") + data = zlib.compress(data, 6) + fsize = len(data)+6 + header = "#!WINGS-1.0\r\n\032\04" + misc = 0x8350 + + file = open(filename, "wb") + file.write(header) + file.write(struct.pack(">L", fsize)) + file.write(struct.pack(">H", misc)) + file.write(struct.pack(">L", dsize)) + file.write(data) + + # Blender.Window.RedrawAll() + Blender.Window.DrawProgressBar(1.0, '') # clear progressbar + file.close() + end = time.clock() + seconds = " in %.2f %s" % (end-start, "seconds") + message = "Successfully exported " + os.path.basename(filename) + seconds + '\n\n' + message += "objname : " + objname + '\n' + message += "faces : " + `len(mesh.faces)` + '\n' + message += "edges : " + `len(edge_table)` + '\n' + message += "verts : " + `len(mesh.verts)` + '\n' + mod_meshtools.print_boxed(message) + +def fs_callback(filename): + if filename.find('.wings', -6) <= 0: filename += '.wings' + write(filename) + +Blender.Window.FileSelector(fs_callback, "Wings3D Export") diff --git a/release/scripts/wings_import.py b/release/scripts/wings_import.py new file mode 100644 index 00000000000..85d5fa377ad --- /dev/null +++ b/release/scripts/wings_import.py @@ -0,0 +1,288 @@ +#!BPY + +""" +Name: 'Wings3D...' +Blender: 232 +Group: 'Import' +Tooltip: 'Import Wings3D File Format (*.wings)' +""" + +# +---------------------------------------------------------+ +# | Copyright (c) 2002 Anthony D'Agostino | +# | http://www.redrival.com/scorpius | +# | scorpius@netzero.com | +# | Feb 19, 2002 | +# | Released under the Blender Artistic Licence (BAL) | +# | Import Export Suite v0.5 | +# +---------------------------------------------------------+ +# | Read and write Wings3D File Format (*.wings) | +# +---------------------------------------------------------+ + +import Blender, mod_meshtools +import struct, time, sys, os, zlib, cStringIO + +# ============================================== +# === Read The 'Header' Common To All Chunks === +# ============================================== +def read_chunkheader(data): + data.read(2) #version, tag = struct.unpack(">BB", data.read(2)) + misc, namelen = struct.unpack(">BH", data.read(3)) + name = data.read(namelen) + return name + +# ============================== +# === Read The Material Mode === +# ============================== +def read_mode(data): + data.read(5) # BL + read_chunkheader(data) # "mode" + misc, namelen = struct.unpack(">BH", data.read(3)) + data.read(namelen) + data.read(1) # 6A + +# ======================= +# === Read Hard Edges === +# ======================= +def read_hardedges(data): + tag = data.read(1) + if tag == '\x6A': + return # There are no hard edges + elif tag == '\x6B': + numhardedges, = struct.unpack(">H", data.read(2)) + print "numhardedges:", numhardedges + for i in range(numhardedges): + data.read(1) + elif tag == '\x6C': + numhardedges, = struct.unpack(">L", data.read(4)) + print "numhardedges:", numhardedges + for i in range(numhardedges): + misc = data.read(1) + if misc == '\x61': # next value is stored as a byte + data.read(1) + elif misc == '\x62': # next value is stored as a long + data.read(4) + data.read(1) # 6A + else: + print tag + +# ================== +# === Read Edges === +# ================== +def read_edges(data): + misc, numedges = struct.unpack(">BL", data.read(5)) + edge_table = {} # the winged-edge table + for i in range(numedges): + if not i%100 and mod_meshtools.show_progress: Blender.Window.DrawProgressBar(float(i)/numedges, "Reading Edges") + misc, etype = struct.unpack(">BL", data.read(5)) + if etype == 2: # Vertex Colors + data.read(10) # or read_chunkheader(data) # "color" + data.read(5) # BL + r1,g1,b1,r2,g2,b2 = struct.unpack(">dddddd", data.read(48)) + #print "%3d %3d %3d | %3d %3d %3d" % (r1*255,g1*255,b1*255,r2*255,g2*255,b2*255), + #print "%f %f %f | %f %f %f" % (r1, g1, b1, r2, g2, b2) + data.read(9) # or read_chunkheader(data) # "edge" + edge = [] # the eight entries for this edge + for e in range(8): # Sv Ev | Lf Rf | Lp Ls | Rp Rs + misc = data.read(1) + if misc == '\x61': # next value is stored as a byte + entry, = struct.unpack(">B", data.read(1)) + edge.append(entry) + elif misc == '\x62': # next value is stored as a long + entry, = struct.unpack(">L", data.read(4)) + edge.append(entry) + edge_table[i] = edge + data.read(1) # 6A + data.read(1) # 6A + return edge_table + +# ================== +# === Read Faces === +# ================== +def read_faces(data): + misc, numfaces = struct.unpack(">BL", data.read(5)) + for i in range(numfaces): + if not i%100 and mod_meshtools.show_progress: Blender.Window.DrawProgressBar(float(i)/numfaces, "Reading Faces") + if data.read(1) == '\x6C': # a material follows + data.read(4) + read_chunkheader(data) + misc, namelen = struct.unpack(">BH", data.read(3)) + materialname = data.read(namelen) + data.read(1) + data.read(1) # 6A + return numfaces + +# ================== +# === Read Verts === +# ================== +def read_verts(data): + misc, numverts = struct.unpack(">BL", data.read(5)) + verts = [] # a list of verts + for i in range(numverts): + if not i%100 and mod_meshtools.show_progress: Blender.Window.DrawProgressBar(float(i)/numverts, "Reading Verts") + data.read(10) + x, y, z = struct.unpack(">ddd", data.read(24)) # double precision + verts.append((x, -z, y)) + data.read(1) # 6A + data.read(1) # 6A + return verts + +# ======================= +# === Make Face Table === +# ======================= +def make_face_table(edge_table): # For Wings + face_table = {} + for i in range(len(edge_table)): + Lf = edge_table[i][2] + Rf = edge_table[i][3] + face_table[Lf] = i + face_table[Rf] = i + return face_table + +# ======================= +# === Make Vert Table === +# ======================= +def make_vert_table(edge_table): # For Wings + vert_table = {} + for i in range(len(edge_table)): + Sv = edge_table[i][0] + Ev = edge_table[i][1] + vert_table[Sv] = i + vert_table[Ev] = i + return vert_table + +# ================== +# === Make Faces === +# ================== +def make_faces(edge_table): # For Wings + face_table = make_face_table(edge_table) + faces=[] + for i in range(len(face_table)): + face_verts = [] + current_edge = face_table[i] + while(1): + if i == edge_table[current_edge][3]: + next_edge = edge_table[current_edge][7] # Right successor edge + next_vert = edge_table[current_edge][0] + else: + next_edge = edge_table[current_edge][5] # Left successor edge + next_vert = edge_table[current_edge][1] + face_verts.append(next_vert) + current_edge = next_edge + if current_edge == face_table[i]: break + face_verts.reverse() + faces.append(face_verts) + return faces + +# ======================= +# === Dump Wings File === +# ======================= +def dump_wings(filename): + import pprint + start = time.clock() + file = open(filename, "rb") + header = file.read(15) + fsize, = struct.unpack(">L", file.read(4)) # file_size - 19 + misc, = struct.unpack(">H", file.read(2)) + dsize, = struct.unpack(">L", file.read(4)) # uncompressed data size + data = file.read(fsize-6) + file.close() + data = zlib.decompress(data) + if dsize != len(data): print "ERROR: uncompressed size does not match." + data = cStringIO.StringIO(data) + print "header:", header + print read_chunkheader(data) # === wings chunk === + data.read(4) # misc bytes + misc, numobjs, = struct.unpack(">BL", data.read(5)) + print "filename:", filename + print "numobjs :", numobjs + for obj in range(numobjs): + print read_chunkheader(data) # === object chunk === + misc, namelen = struct.unpack(">BH", data.read(3)) + objname = data.read(namelen) + print read_chunkheader(data) # === winged chunk === + edge_table = read_edges(data) + numfaces = read_faces(data) + verts = read_verts(data) + read_hardedges(data) + + face_table = {} # contains an incident edge + vert_table = {} # contains an incident edge + for i in range(len(edge_table)): + face_table[edge_table[i][2]] = i # generate face_table + face_table[edge_table[i][3]] = i + vert_table[edge_table[i][0]] = i # generate vert_table + vert_table[edge_table[i][1]] = i + + print "objname :", objname + print "numedges:", len(edge_table) + print "numfaces:", numfaces + print "numverts:", len(verts) + print + print "Ä"*79 + print "edge_table:" + pprint.pprint(edge_table) + #for i in range(len(edge_table)): print "%2d" % (i), edge_table[i] + print + print "face_table:" + pprint.pprint(face_table) + #for i in range(len(face_table)): print "%2d %2d" % (i, face_table[i]) + print + print "vert_table:" + pprint.pprint(vert_table) + #for i in range(len(vert_table)): print "%2d %2d" % (i, vert_table[i]) + file.close() + end = time.clock() + print '\a\r', + sys.stderr.write("\nDone in %.2f %s" % (end-start, "seconds")) + +# ========================= +# === Read Wings Format === +# ========================= +def read(filename): + start = time.clock() + file = open(filename, "rb") + header = file.read(15) + fsize, = struct.unpack(">L", file.read(4)) # file_size - 19 + misc, = struct.unpack(">H", file.read(2)) + dsize, = struct.unpack(">L", file.read(4)) # uncompressed data size + data = file.read(fsize-6) + #print file.tell(), "bytes" + file.close() + Blender.Window.DrawProgressBar(1.0, "Decompressing Data") + data = zlib.decompress(data) + data = cStringIO.StringIO(data) + read_chunkheader(data) # wings chunk + data.read(4) # misc bytes + misc, numobjs = struct.unpack(">BL", data.read(5)) + message = "Successfully imported " + os.path.basename(filename) + '\n\n' + message += "%s %8s %8s %8s\n" % ("Object".ljust(15), "faces", "edges", "verts") + message += "%s %8s %8s %8s\n" % ("ÄÄÄÄÄÄ".ljust(15), "ÄÄÄÄÄ", "ÄÄÄÄÄ", "ÄÄÄÄÄ") + + for obj in range(numobjs): + read_chunkheader(data) # object chunk + misc, namelen = struct.unpack(">BH", data.read(3)) + objname = data.read(namelen) + read_chunkheader(data) # winged chunk + edge_table = read_edges(data) + numfaces = read_faces(data) + verts = read_verts(data) + read_hardedges(data) + read_mode(data) + faces = make_faces(edge_table) + message += "%s %8s %8s %8s\n" % (objname.ljust(15), len(faces), len(edge_table), len(verts)) + mod_meshtools.create_mesh(verts, faces, objname) + + material = data.read() + #for i in material[0:6]: print "%02X" % ord(i), + #print + Blender.Window.DrawProgressBar(1.0, "Done") # clear progressbar + data.close() + end = time.clock() + seconds = "\nDone in %.2f %s" % (end-start, "seconds") + message += seconds + mod_meshtools.print_boxed(message) + +def fs_callback(filename): + read(filename) + +Blender.Window.FileSelector(fs_callback, "Wings3D Import") diff --git a/source/blender/python/BPY_menus.c b/source/blender/python/BPY_menus.c index f2879f654c1..f43b5852a32 100644 --- a/source/blender/python/BPY_menus.c +++ b/source/blender/python/BPY_menus.c @@ -83,6 +83,8 @@ static int bpymenu_group_atoi (char *str) else if (!strcmp(str, "Animation")) return PYMENU_ANIMATION; else if (!strcmp(str, "Materials")) return PYMENU_MATERIALS; else if (!strcmp(str, "UV")) return PYMENU_UV; + else if (!strcmp(str, "Utils")) return PYMENU_UTILS; + else if (!strcmp(str, "Tools")) return PYMENU_TOOLS; /* "Misc" or an inexistent group name: use misc */ else return PYMENU_MISC; } @@ -113,6 +115,10 @@ char *BPyMenu_group_itoa (short menugroup) break; case PYMENU_UV: return "UV"; + case PYMENU_UTILS: + return "Utils"; + case PYMENU_TOOLS: + return "Tools"; case PYMENU_MISC: return "Misc"; break; diff --git a/source/blender/python/BPY_menus.h b/source/blender/python/BPY_menus.h index 5e7139f213e..20e10b06d54 100644 --- a/source/blender/python/BPY_menus.h +++ b/source/blender/python/BPY_menus.h @@ -75,19 +75,19 @@ typedef struct BPyMenu { * BPY_menus.c; * - add the necessary code to the header_***.c file in * source/blender/src/, like done in header_info.c for import/export; - * - update the bpython registering function and its documentation to include - * the new group. */ typedef enum { PYMENU_WIZARDS, /* complex 'app' scripts */ - PYMENU_MODIFIERS, /* modifies existing objs */ + PYMENU_UV, /* UV editing tools, to go in UV/Image editor space, 'UV' menu */ + PYMENU_UTILS, + PYMENU_TOOLS, + PYMENU_MODIFIERS, /* modifies existing obj *data* */ PYMENU_MISC, PYMENU_MATERIALS, PYMENU_GENERATORS, /* creates new objects */ PYMENU_IMPORT, PYMENU_EXPORT, PYMENU_ANIMATION, - PYMENU_UV, /* UV editing tools, to go in UV/Image editor space, 'UV' menu */ PYMENU_TOTAL } PYMENUHOOKS; |