Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'release')
-rw-r--r--release/scripts/Axiscopy.py78
-rw-r--r--release/scripts/clean_mesh.py188
-rw-r--r--release/scripts/knife.py2
-rw-r--r--release/scripts/mod_ai2obj.py383
-rw-r--r--release/scripts/mod_eps2obj.py390
-rw-r--r--release/scripts/mod_gimp2obj.py320
-rw-r--r--release/scripts/mod_svg2obj.py647
-rw-r--r--release/scripts/obj_export.py232
-rw-r--r--release/scripts/obj_import.py570
-rw-r--r--release/scripts/paths_import.py35
-rw-r--r--release/scripts/skin.py558
-rw-r--r--release/scripts/tex2uvbaker.py254
-rw-r--r--release/windows/installer/00.blender.nsi8
13 files changed, 3270 insertions, 395 deletions
diff --git a/release/scripts/Axiscopy.py b/release/scripts/Axiscopy.py
new file mode 100644
index 00000000000..bfdb89806cd
--- /dev/null
+++ b/release/scripts/Axiscopy.py
@@ -0,0 +1,78 @@
+#!BPY
+
+""" Registration info for Blender menus: <- these words are ignored
+Name: 'Axis Orientation Copy'
+Blender: 233
+Group: 'Object'
+Tip: 'Copy the axis orientation of the active object to all selected mesh object'
+"""
+
+# $Id$
+#
+#----------------------------------------------
+# A Vanpoucke (xand)
+#from the previous script realignaxis
+#----------------------------------------------
+# Communiquer les problemes et erreurs sur:
+# http://www.zoo-logique.org/3D.Blender/newsportal/thread.php?group=3D.Blender
+# --------------------------------------------------------------------------
+# ***** BEGIN GPL LICENSE BLOCK *****
+#
+# Copyright (C) 2003, 2004: A Vanpoucke
+#
+# 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 *****
+# --------------------------------------------------------------------------
+
+from Blender import *
+from Blender import Mathutils
+from Blender.Mathutils import *
+
+
+def applyTransform(mesh,mat):
+ for v in mesh.verts:
+ vec = VecMultMat(v.co,mat)
+ v.co[0], v.co[1], v.co[2] = vec[0], vec[1], vec[2]
+
+
+
+
+oblist =Object.GetSelected()
+lenob=len(oblist)
+
+if lenob<2:
+ Draw.PupMenu("Select at least 2 objects")
+else :
+ source=oblist[0]
+ nsource=source.name
+ texte="Copy axis orientation from : " + nsource + " ?%t|OK"
+ result=Draw.PupMenu(texte)
+
+
+ for cible in oblist[1:]:
+ if cible.getType()=='Mesh':
+ if source.rot!=cible.rot:
+ rotcible=cible.mat.toEuler().toMatrix()
+ rotsource=source.mat.toEuler().toMatrix()
+ rotsourcet = CopyMat(rotsource)
+ rotsourcet.invert()
+ mat=rotcible*rotsourcet
+ ncible=cible.name
+ me=NMesh.GetRaw(ncible)
+ applyTransform(me,mat)
+ NMesh.PutRaw(me,ncible)
+ cible.makeDisplayList()
+ cible.rot=source.rot
diff --git a/release/scripts/clean_mesh.py b/release/scripts/clean_mesh.py
new file mode 100644
index 00000000000..7fa3a496b34
--- /dev/null
+++ b/release/scripts/clean_mesh.py
@@ -0,0 +1,188 @@
+#!BPY
+
+"""
+Name: 'Cleanup Meshes'
+Blender: 234
+Group: 'Mesh'
+Tooltip: 'Clean unused data from all selected meshes'
+"""
+
+# $Id$
+#
+# --------------------------------------------------------------------------
+# Mesh Cleaner 1.0 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 *****
+# --------------------------------------------------------------------------
+
+
+# Made by Ideasman/Campbell 2004/04/25 - ideasman@linuxmail.org
+
+import Blender
+from Blender import *
+from math import sqrt
+
+VRemNum = ERemNum = FRemNum = 0 # Remember for statistics
+
+
+#================#
+# Math functions #
+#================#
+def compare(f1, f2, limit):
+ if f1 + limit > f2 and f1 - limit < f2:
+ return 1
+ return 0
+
+def measure(v1, v2):
+ return Mathutils.Vector([v1[0]-v2[0], v1[1] - v2[1], v1[2] - v2[2]]).length
+
+def triArea2D(v1, v2, v3):
+ e1 = measure(v1, v2)
+ e2 = measure(v2, v3)
+ e3 = measure(v3, v1)
+ p = e1+e2+e3
+ return 0.25 * sqrt(p*(p-2*e1)*(p-2*e2)*(p-2*e3))
+
+
+#=============================#
+# Blender functions/shortcuts #
+#=============================#
+def error(str):
+ Draw.PupMenu('ERROR%t|'+str)
+
+def getLimit(text):
+ return Draw.PupFloatInput(text, 0.001, 0.0, 1.0, 0.1, 3)
+
+def faceArea(f):
+ if len(f.v) == 4:
+ return triArea2D(f.v[0].co, f.v[1].co, f.v[2].co) + triArea2D(f.v[0].co, f.v[2].co, f.v[3].co)
+ elif len(f.v) == 3:
+ return triArea2D(f.v[0].co, f.v[1].co, f.v[2].co)
+
+
+
+#================#
+# Mesh functions #
+#================#
+def delFreeVert(mesh):
+ global VRemNum
+ usedList = eval('[' + ('False,' * len(mesh.verts) )+ ']')
+ # Now tag verts that areused
+ for f in mesh.faces:
+ for v in f.v:
+ usedList[mesh.verts.index(v)] = True
+ vIdx = 0
+ for bool in usedList:
+ if bool == False:
+ mesh.verts.remove(mesh.verts[vIdx])
+ vIdx -= 1
+ VRemNum += 1
+ vIdx += 1
+ mesh.update()
+
+
+def delEdge(mesh):
+ global ERemNum
+ fIdx = 0
+ while fIdx < len(mesh.faces):
+ if len(mesh.faces[fIdx].v) == 2:
+ mesh.faces.remove(mesh.faces[fIdx])
+ ERemNum += 1
+ fIdx -= 1
+ fIdx +=1
+ mesh.update()
+
+def delEdgeLen(mesh, limit):
+ global ERemNum
+ fIdx = 0
+ while fIdx < len(mesh.faces):
+ if len(mesh.faces[fIdx].v) == 2:
+ if measure(mesh.faces[fIdx].v[0].co, mesh.faces[fIdx].v[1].co) <= limit:
+ mesh.faces.remove(mesh.faces[fIdx])
+ ERemNum += 1
+ fIdx -= 1
+ fIdx +=1
+ mesh.update()
+
+def delFaceArea(mesh, limit):
+ global FRemNum
+ fIdx = 0
+ while fIdx < len(mesh.faces):
+ if len(mesh.faces[fIdx].v) > 2:
+ if faceArea(mesh.faces[fIdx]) <= limit:
+ mesh.faces.remove(mesh.faces[fIdx])
+ FRemNum += 1
+ fIdx -= 1
+ fIdx +=1
+ mesh.update()
+
+
+#====================#
+# Make a mesh list #
+#====================#
+
+is_editmode = Window.EditMode()
+if is_editmode: Window.EditMode(0)
+
+meshList = []
+if len(Object.GetSelected()) > 0:
+ for ob in Object.GetSelected():
+ if ob.getType() == 'Mesh':
+ meshList.append(ob.getData())
+
+
+#====================================#
+# Popup menu to select the functions #
+#====================================#
+if len(meshList) == 0:
+ error('no meshes in selection')
+else:
+ method = Draw.PupMenu(\
+ 'Clean Mesh, Remove...%t|\
+ Verts: free standing|\
+ Edges: not in a face|\
+ Edges: below a length|\
+ Faces: below an area|%l|\
+ All of the above|')
+
+ if method >= 3:
+ limit = getLimit('threshold: ')
+
+ if method != -1:
+ for mesh in meshList:
+ if method == 1:
+ delFreeVert(mesh)
+ elif method == 2:
+ delEdge(mesh)
+ elif method == 3:
+ delEdgeLen(mesh, limit)
+ elif method == 4:
+ delFaceArea(mesh, limit)
+ elif method == 6: # All of them
+ delFaceArea(mesh, limit)
+ delEdge(mesh)
+ delFreeVert(mesh)
+
+ mesh.update(0)
+ Redraw()
+
+if is_editmode: Window.EditMode(1)
+
+if method != -1:
+ Draw.PupMenu('Removed from ' + str(len(meshList)) +' Mesh(es)%t|' + 'Verts:' + str(VRemNum) + ' Edges:' + str(ERemNum) + ' Faces:' + str(FRemNum))
diff --git a/release/scripts/knife.py b/release/scripts/knife.py
index 4a7943d8902..f9f8aedf72b 100644
--- a/release/scripts/knife.py
+++ b/release/scripts/knife.py
@@ -4,7 +4,7 @@
Name: 'Blender Knife Tool'
Blender: 232
Group: 'Mesh'
-Tooltip: 'Cut a mesh along a plane w/o creating doubles'
+Tooltip: 'Cut selected mesh(es) along an active plane w/o creating doubles'
"""
# $Id$
diff --git a/release/scripts/mod_ai2obj.py b/release/scripts/mod_ai2obj.py
new file mode 100644
index 00000000000..07342737aad
--- /dev/null
+++ b/release/scripts/mod_ai2obj.py
@@ -0,0 +1,383 @@
+"""
+#----------------------------------------------
+# (c) jm soler juillet 2004, released under Blender Artistic Licence
+# for the Blender 2.34 Python Scripts Bundle.
+#----------------------------------------------
+# Page officielle :
+# http://jmsoler.free.fr/didacticiel/blender/tutor/cpl_import_ai.htm
+# Communiquer les problemes et erreurs sur:
+# http://www.zoo-logique.org/3D.Blender/newsportal/thread.php?group=3D.Blender
+#
+# 0.1.1 : 2004/08/03, bug in boudingbox reading when Value are negative
+#
+"""
+SHARP_IMPORT=0
+SCALE=1
+DEVELOPPEMENT=0
+
+import sys
+#oldpath=sys.path
+import Blender
+BLversion=Blender.Get('version')
+
+try:
+ import nt
+ os=nt
+ os.sep='\\'
+
+except:
+ import posix
+ os=posix
+ os.sep='/'
+
+def isdir(path):
+ try:
+ st = os.stat(path)
+ return 1
+ except:
+ return 0
+
+def split(pathname):
+ if pathname.find(os.sep)!=-1:
+ k0=pathname.split(os.sep)
+ else:
+ if os.sep=='/':
+ k0=pathname.split('\\')
+ else:
+ k0=pathname.split('/')
+
+ directory=pathname.replace(k0[len(k0)-1],'')
+ Name=k0[len(k0)-1]
+ return directory, Name
+
+def join(l0,l1):
+ return l0+os.sep+l1
+
+os.isdir=isdir
+os.split=split
+os.join=join
+
+def filtreFICHIER(nom):
+ f=open(nom,'r')
+ t=f.readlines()
+ f.close()
+
+ if len(t)==1 and t[0].find('\r'):
+ t=t[0].split('\r')
+
+ if len(t)>1:
+ return t
+ else:
+ name = "OK?%t| Not a valid file or an empty file ... " # if no %xN int is set, indices start from 1
+ result = Draw.PupMenu(name)
+
+ return 'false'
+
+#===============================
+# Data
+#===============================
+#===============================
+# Blender Curve Data
+#===============================
+objBEZIER=0
+objSURFACE=5
+typBEZIER3D=1 #3D
+typBEZIER2D=9 #2D
+
+class Bez:
+ def __init__(self):
+ self.co=[]
+ self.ha=[0,0]
+
+class ITEM:
+ def __init__(self):
+ self.type = typBEZIER3D,
+ self.pntsUV = [0,0]
+ self.resolUV = [32,0]
+ self.orderUV = [0,0]
+ self.flagUV = [0,0]
+ self.Origine = [0.0,0.0]
+ self.beziers_knot = []
+
+class COURBE:
+ def __init__(self):
+ self.magic_number='3DG3'
+ self.type = objBEZIER
+ self.number_of_items = 0
+ self.ext1_ext2 = [0,0]
+ self.matrix = """0.0 0.0 1.0 0.0
+0.0 1.0 0.0 0.0
+0.0 0.0 1.0 0.0
+0.0 0.0 0.0 1.0 """
+ self.ITEM = {}
+
+courbes=COURBE()
+
+PATTERN={}
+
+BOUNDINGBOX={'rec':[],'coef':1.0}
+npat=0
+#=====================================================================
+#======== name of the curve in teh courbes dictionnary ===============
+#=====================================================================
+n0=0
+
+#=====================================================================
+#====================== current Point ================================
+#=====================================================================
+CP=[0.0,0.0] #currentPoint
+
+#=====================================================================
+#===== to compare last position to the original move to displacement =
+#===== needed for cyclic efinition =================================
+#=====================================================================
+def test_egalitedespositions(f1,f2):
+ if f1[0]==f2[0] and f1[1]==f2[1]:
+ return Blender.TRUE
+ else:
+ return Blender.FALSE
+
+
+def Open_GEOfile(dir,nom):
+ if BLversion>=233:
+ Blender.Load(dir+nom+'OOO.obj', 1)
+ BO=Blender.Object.Get()
+ BO[-1].RotY=0.0
+ BO[-1].makeDisplayList()
+ Blender.Window.RedrawAll()
+ else:
+ print "Not yet implemented"
+
+def create_GEOtext(courbes):
+ global SCALE, B, BOUNDINGBOX
+ r=BOUNDINGBOX['rec']
+
+ if SCALE==1:
+ SCALE=1.0
+ elif SCALE==2:
+ SCALE=r[2]-r[0]
+ elif SCALE==3:
+ SCALE=r[3]-r[1]
+
+ t=[]
+ t.append(courbes.magic_number+'\n')
+ t.append(str(courbes.type)+'\n')
+ t.append(str(courbes.number_of_items)+'\n')
+ t.append(str(courbes.ext1_ext2[0])+' '+str(courbes.ext1_ext2[1])+'\n')
+ t.append(courbes.matrix+'\n')
+
+ for k in courbes.ITEM.keys():
+ t.append("%s\n"%courbes.ITEM[k].type)
+ t.append("%s %s \n"%(courbes.ITEM[k].pntsUV[0],courbes.ITEM[k].pntsUV[1]))
+ t.append("%s %s \n"%(courbes.ITEM[k].resolUV[0],courbes.ITEM[k].resolUV[1]))
+ t.append("%s %s \n"%(courbes.ITEM[k].orderUV[0],courbes.ITEM[k].orderUV[1]))
+ t.append("%s %s \n"%(courbes.ITEM[k].flagUV[0],courbes.ITEM[k].flagUV[1]))
+
+ flag =courbes.ITEM[k].flagUV[0]
+
+ for k2 in range(flag,len(courbes.ITEM[k].beziers_knot)):
+ k1 =courbes.ITEM[k].beziers_knot[k2]
+ t.append("%4f 0.0 %4f \n"%(float(k1.co[0])/SCALE,float(k1.co[1])/SCALE))
+ t.append("%4f 0.0 %4f \n"%(float(k1.co[2])/SCALE,float(k1.co[3])/SCALE))
+ t.append("%4f 0.0 %4f \n"%(float(k1.co[4])/SCALE,float(k1.co[5])/SCALE))
+ t.append(str(k1.ha[0])+' '+str(k1.ha[1])+'\n')
+ return t
+
+def save_GEOfile(dir,nom,t):
+ f=open(dir+nom+'OOO.obj','w')
+ f.writelines(t)
+ f.close()
+ #warning = "REMINDER : %t | Do not forget to rename your blender file NOW ! %x1"
+ #result = Blender.Draw.PupMenu(warning)
+
+
+#=====================================================================
+#===== AI format : DEBUT =========================
+#=====================================================================
+def mouvement_vers(l,n0,CP):
+ if n0 in courbes.ITEM.keys():
+ #if test_egalitedespositions(courbes.ITEM[n0].Origine,CP):
+ # courbes.ITEM[n0].flagUV[0]=1
+ n0+=1
+ else:
+ CP=[l[-3].replace('d',''),l[-2]]
+ #i=
+ courbes.ITEM[n0]=ITEM()
+ courbes.ITEM[n0].Origine=[l[-3].replace('d',''),l[-2]]
+
+ B=Bez()
+ B.co=[CP[0],CP[1],CP[0],CP[1],CP[0],CP[1]]
+ B.ha=[0,0]
+ courbes.ITEM[n0].beziers_knot.append(B)
+
+ return courbes,n0,CP
+
+def courbe_vers_c(l,l2, n0,CP): #c,C
+
+ B=Bez()
+ B.co=[l[2],l[3],l[4],l[5],l[0],l[1]]
+
+ if len(courbes.ITEM[n0].beziers_knot)==1:
+ CP=[l[0],l[1]]
+ courbes.ITEM[n0].Origine=[l[0],l[1]]
+
+ if l[-1]=='C':
+ B.ha=[2,2]
+ else:
+ B.ha=[0,0]
+
+ courbes.ITEM[n0].beziers_knot.append(B)
+ if len(l2)>1 and l2[-1] in Actions.keys():
+ B.co[-2]=l2[0]
+ B.co[-1]=l2[1]
+ else:
+ #B.co[-2]=courbes.ITEM[n0].beziers_knot[-1].co[0]
+ #B.co[-1]=courbes.ITEM[n0].beziers_knot[-].co[1]
+
+ B.co[-2]=CP[0]
+ B.co[-1]=CP[1]
+ return courbes,n0,CP
+
+
+def courbe_vers_v(l,n0,CP): #v-V
+ B=Bez()
+ B.co=[l[2],l[3],l[0],l[1],l[2],l[3]]
+ if l[-1]=='V':
+ B.ha=[2,2]
+ else:
+ B.ha=[0,0]
+ courbes.ITEM[n0].beziers_knot.append(B)
+ CP=[l[0],l[1]]
+ return courbes,n0,CP
+
+def courbe_vers_y(l,n0,CP): #y
+ B=Bez()
+ B.co=[l[2],l[3],l[0],l[1],l[2],l[3]]
+ if l[-1]=='Y':
+ B.ha=[2,2]
+ else:
+ B.ha=[0,0]
+ courbes.ITEM[n0].beziers_knot.append(B)
+ CP=[l[2],l[3]]
+ return courbes,n0,CP
+
+
+def ligne_tracee_l(l,n0,CP):
+ B=Bez()
+ B.co=[l[0],l[1],l[0],l[1],l[0],l[1]]
+ if l[-1]=='L':
+ B.ha=[2,2]
+ else:
+ B.ha=[0,0]
+ courbes.ITEM[n0].beziers_knot.append(B)
+ CP=[l[0],l[1]]
+ return courbes,n0,CP
+
+Actions= { "C" : courbe_vers_c,
+ "c" : courbe_vers_c,
+ "V" : courbe_vers_v,
+ "v" : courbe_vers_v,
+ "Y" : courbe_vers_y,
+ "y" : courbe_vers_y,
+ "m" : mouvement_vers,
+ "l" : ligne_tracee_l,
+ "L" : ligne_tracee_l}
+
+TAGcourbe=Actions.keys()
+
+def pik_pattern(t,l):
+ global npat, PATTERN, BOUNDINGBOX
+ while t[l].find('%%EndSetup')!=0:
+ if t[l].find('%%BoundingBox:')!=-1:
+ t[l]=t[l][t[l].find(':')+1:]
+ l0=t[l].split()
+ BOUNDINGBOX['rec']=[float(l0[-4]),float(l0[-3]),float(l0[-2]),float(l0[-1])]
+ r=BOUNDINGBOX['rec']
+ BOUNDINGBOX['coef']=(r[3]-r[1])/(r[2]-r[0])
+ #print l,
+ if t[l].find('BeginPattern')!=-1:
+ nomPattern=t[l][t[l].find('(')+1:t[l].find(')')]
+ PATTERN[nomPattern]={}
+
+ if t[l].find('BeginPatternLayer')!=-1:
+ npat+=1
+ PATTERN[nomPattern][npat]=[]
+ while t[l].find('EndPatternLayer')==-1:
+ #print t[l]
+ PATTERN[nomPattern][npat].append(l)
+ l+=1
+ if l+1<len(t):
+ l=l+1
+ else:
+ return 1,l
+ return 1,l
+
+def scan_FILE(nom):
+ global CP, courbes, SCALE
+ dir,name=split(nom)
+ name=name.split('.')
+ n0=0
+ result=0
+ t=filtreFICHIER(nom)
+
+ if nom.upper().find('.AI')!=-1 and t!='false':
+ if not SHARP_IMPORT:
+ warning = "Select Size : %t| As is %x1 | Scale on Height %x2| Scale on Width %x3"
+ SCALE = Blender.Draw.PupMenu(warning)
+
+ npat=0
+ l=0
+ do=0
+ while l <len(t)-1 :
+ if not do:
+ do,l=pik_pattern(t,l)
+ #print 'len(t)',len(t)
+ t[l].replace('\n','')
+ if t[l][0]!='%':
+ l0=t[l].split()
+ if l0[-1] in TAGcourbe:
+ if l0[-1] in ['C','c']:
+ l2=t[l+1].split()
+ courbes,n0,CP=Actions[l0[-1]](l0,l2,n0,CP)
+ else:
+ courbes,n0,CP=Actions[l0[-1]](l0,n0,CP)
+ l=l+1; #print l
+ t=[]
+ courbes.number_of_items=len(courbes.ITEM.keys())
+ for k in courbes.ITEM.keys():
+ courbes.ITEM[k].pntsUV[0] =len(courbes.ITEM[k].beziers_knot)
+
+ if test_egalitedespositions(courbes.ITEM[k].Origine,
+ [courbes.ITEM[k].beziers_knot[-1].co[-2],
+ courbes.ITEM[k].beziers_knot[-1].co[-1]]):
+ courbes.ITEM[k].flagUV[0]=1
+ courbes.ITEM[k].pntsUV[0] -=1
+
+ if courbes.number_of_items>0:
+ if len(PATTERN.keys() )>0:
+ #print len(PATTERN.keys() )
+ warning = "Pattern list (for info not used): %t| "
+ p0=1
+ for P in PATTERN.keys():
+ warning+="%s %%x%s|"%(P,p0)
+ p0+=1
+ Padd = Blender.Draw.PupMenu(warning)
+
+ t=create_GEOtext(courbes)
+ save_GEOfile(dir,name[0],t)
+ Open_GEOfile(dir,name[0])
+ else:
+ pass
+#=====================================================================
+#====================== AI format mouvements =========================
+#=====================================================================
+#=========================================================
+# une sorte de contournement qui permet d'utiliser la fonction
+# et de documenter les variables Window.FileSelector
+#=========================================================
+def fonctionSELECT(nom):
+ scan_FILE(nom)
+
+if DEVELOPPEMENT==1:
+ Blender.Window.FileSelector (fonctionSELECT, 'SELECT AI FILE')
+#sys.path=oldpath
diff --git a/release/scripts/mod_eps2obj.py b/release/scripts/mod_eps2obj.py
new file mode 100644
index 00000000000..8db89892fc6
--- /dev/null
+++ b/release/scripts/mod_eps2obj.py
@@ -0,0 +1,390 @@
+#----------------------------------------------
+# (c) jm soler juillet 2004, released under Blender Artistic Licence
+# for the Blender 2.34 Python Scripts Bundle.
+#----------------------------------------------
+# Page officielle :
+# http://jmsoler.free.fr/didacticiel/blender/tutor/cpl_import_eps.htm
+# Communiquer les problemes et erreurs sur:
+# http://www.zoo-logique.org/3D.Blender/newsportal/thread.php?group=3D.Blender
+#----------------------------------------------
+
+SHARP_IMPORT=0
+SCALE=1
+scale=1
+
+import sys
+#oldpath=sys.path
+import Blender
+BLversion=Blender.Get('version')
+
+try:
+ import nt
+ os=nt
+ os.sep='\\'
+
+except:
+ import posix
+ os=posix
+ os.sep='/'
+
+def isdir(path):
+ try:
+ st = os.stat(path)
+ return 1
+ except:
+ return 0
+
+def split(pathname):
+ if pathname.find(os.sep)!=-1:
+ k0=pathname.split(os.sep)
+ else:
+ if os.sep=='/':
+ k0=pathname.split('\\')
+ else:
+ k0=pathname.split('/')
+
+ directory=pathname.replace(k0[len(k0)-1],'')
+ Name=k0[len(k0)-1]
+ return directory, Name
+
+def join(l0,l1):
+ return l0+os.sep+l1
+
+os.isdir=isdir
+os.split=split
+os.join=join
+
+def filtreFICHIER(nom):
+ f=open(nom,'r')
+ t=f.readlines()
+ f.close()
+ if len(t)==1 and t[0].find('\r'):
+ t=t[0].split('\r')
+ if len(t)>1:
+ return t
+ else:
+ name = "OK?%t| Not a valid file or an empty file ... " # if no %xN int is set, indices start from 1
+ result = Draw.PupMenu(name)
+ return 'false'
+
+#===============================
+# Data
+#===============================
+#===============================
+# Blender Curve Data
+#===============================
+objBEZIER=0
+objSURFACE=5
+typBEZIER3D=1 #3D
+typBEZIER2D=9 #2D
+
+class Bez:
+ def __init__(self):
+ self.co=[]
+ self.ha=[0,0]
+
+class ITEM:
+ def __init__(self):
+ self.type = typBEZIER3D,
+ self.pntsUV = [0,0]
+ self.resolUV = [32,0]
+ self.orderUV = [0,0]
+ self.flagUV = [0,0]
+ self.Origine = [0.0,0.0]
+ self.beziers_knot = []
+
+class COURBE:
+ def __init__(self):
+ self.magic_number='3DG3'
+ self.type = objBEZIER
+ self.number_of_items = 0
+ self.ext1_ext2 = [0,0]
+ self.matrix = """0.0 0.0 1.0 0.0
+0.0 1.0 0.0 0.0
+0.0 0.0 1.0 0.0
+0.0 0.0 0.0 1.0 """ #- right-handed object matrix. Used to determine position, rotation and size
+ self.ITEM = {}
+
+courbes=COURBE()
+PATTERN={}
+BOUNDINGBOX={'rec':[],'coef':1.0}
+npat=0
+#=====================================================================
+#======== name of the curve in teh courbes dictionnary ===============
+#=====================================================================
+n0=0
+
+#=====================================================================
+#====================== current Point ================================
+#=====================================================================
+CP=[0.0,0.0] #currentPoint
+
+#=====================================================================
+#===== to compare last position to the original move to displacement =
+#===== needed for cyclic efinition =================================
+#=====================================================================
+def test_egalitedespositions(f1,f2):
+ if f1[0]==f2[0] and f1[1]==f2[1]:
+ return Blender.TRUE
+ else:
+ return Blender.FALSE
+
+
+def Open_GEOfile(dir,nom):
+ global SCALE,BOUNDINGBOX, scale
+ if BLversion>=233:
+ Blender.Load(dir+nom+'OOO.obj', 1)
+ BO=Blender.Object.Get()
+
+ BO[-1].RotY=3.1416
+ BO[-1].RotZ=3.1416
+ BO[-1].RotX=3.1416/2.0
+ if scale==1:
+ BO[-1].LocY+=BOUNDINGBOX['rec'][3]
+ else:
+ BO[-1].LocY+=BOUNDINGBOX['rec'][3]/SCALE
+
+ BO[-1].makeDisplayList()
+ Blender.Window.RedrawAll()
+ else:
+ print "Not yet implemented"
+
+def create_GEOtext(courbes):
+ global SCALE, B, BOUNDINGBOX,scale
+ r=BOUNDINGBOX['rec']
+
+ if scale==1:
+ SCALE=1.0
+ elif scale==2:
+ SCALE=r[2]-r[0]
+ elif scale==3:
+ SCALE=r[3]-r[1]
+
+ t=[]
+ t.append(courbes.magic_number+'\n')
+ t.append(str(courbes.type)+'\n')
+ t.append(str(courbes.number_of_items)+'\n')
+ t.append(str(courbes.ext1_ext2[0])+' '+str(courbes.ext1_ext2[1])+'\n')
+ t.append(courbes.matrix+'\n')
+
+ for k in courbes.ITEM.keys():
+ t.append("%s\n"%courbes.ITEM[k].type)
+ t.append("%s %s \n"%(courbes.ITEM[k].pntsUV[0],courbes.ITEM[k].pntsUV[1]))
+ t.append("%s %s \n"%(courbes.ITEM[k].resolUV[0],courbes.ITEM[k].resolUV[1]))
+ t.append("%s %s \n"%(courbes.ITEM[k].orderUV[0],courbes.ITEM[k].orderUV[1]))
+ t.append("%s %s \n"%(courbes.ITEM[k].flagUV[0],courbes.ITEM[k].flagUV[1]))
+
+ flag =courbes.ITEM[k].flagUV[0]
+
+ for k2 in range(flag,len(courbes.ITEM[k].beziers_knot)):
+ k1 =courbes.ITEM[k].beziers_knot[k2]
+ t.append("%4f 0.0 %4f \n"%(float(k1.co[0])/SCALE,float(k1.co[1])/SCALE))
+ t.append("%4f 0.0 %4f \n"%(float(k1.co[2])/SCALE,float(k1.co[3])/SCALE))
+ t.append("%4f 0.0 %4f \n"%(float(k1.co[4])/SCALE,float(k1.co[5])/SCALE))
+ t.append(str(k1.ha[0])+' '+str(k1.ha[1])+'\n')
+ return t
+
+def save_GEOfile(dir,nom,t):
+ f=open(dir+nom+'OOO.obj','w')
+ f.writelines(t)
+ f.close()
+
+ #name = "REMINDER : %t | Do not forget to rename your blender file NOW ! %x1"
+ #result = Blender.Draw.PupMenu(name)
+
+
+#=====================================================================
+#===== EPS format : DEBUT =========================
+#=====================================================================
+def mouvement_vers(l,n0,CP):
+ if n0 in courbes.ITEM.keys():
+ #if test_egalitedespositions(courbes.ITEM[n0].Origine,CP):
+ # courbes.ITEM[n0].flagUV[0]=1
+ n0+=1
+ CP=[l[-3].replace('d',''),l[-2]]
+ else:
+ CP=[l[-3].replace('d',''),l[-2]]
+ #i=
+ courbes.ITEM[n0]=ITEM()
+ courbes.ITEM[n0].Origine=[l[-3].replace('d',''),l[-2]]
+
+ B=Bez()
+ B.co=[CP[0],CP[1],CP[0],CP[1],CP[0],CP[1]]
+ B.ha=[0,0]
+ courbes.ITEM[n0].beziers_knot.append(B)
+
+ return courbes,n0,CP
+
+def rmouvement_vers(l,n0,CP):
+ if n0 in courbes.ITEM.keys():
+ #if test_egalitedespositions(courbes.ITEM[n0].Origine,CP):
+ # courbes.ITEM[n0].flagUV[0]=1
+ n0+=1
+ CP=["%4f"%(float(l[-3])+float(CP[0])),"%4f"%(float(l[-2])+float(CP[1]))]
+ else:
+ CP=["%4f"%(float(l[-3])+float(CP[0])),"%4f"%(float(l[-2])+float(CP[1]))]
+ #i=
+ courbes.ITEM[n0]=ITEM()
+ courbes.ITEM[n0].Origine=[l[-3].replace('d',''),l[-2]]
+
+ B=Bez()
+ B.co=[CP[0],CP[1],CP[0],CP[1],CP[0],CP[1]]
+ B.ha=[0,0]
+ courbes.ITEM[n0].beziers_knot.append(B)
+ return courbes,n0,CP
+
+def courbe_vers_c(l, l2, n0,CP): #c,C
+ """
+ B=Bez()
+ B.co=[l[0],l[1],l[2],l[3],l[4],l[5]]
+ B.ha=[0,0]
+
+ courbes.ITEM[n0].beziers_knot.append(B)
+ """
+ B=Bez()
+ B.co=[l[2],l[3],l[4],l[5],l[0],l[1]]
+ if len(courbes.ITEM[n0].beziers_knot)==1:
+ CP=[l[0],l[1]]
+ courbes.ITEM[n0].Origine=[l[0],l[1]]
+ if l[-1]=='C':
+ B.ha=[2,2]
+ else:
+ B.ha=[0,0]
+ courbes.ITEM[n0].beziers_knot.append(B)
+ if len(l2)>1 and l2[-1] in Actions.keys():
+ B.co[-2]=l2[0]
+ B.co[-1]=l2[1]
+ else:
+ B.co[-2]=CP[0]
+ B.co[-1]=CP[1]
+ return courbes,n0,CP
+
+def ligne_tracee_l(l,n0,CP):
+ B=Bez()
+ B.co=[l[0],l[1],l[0],l[1],l[0],l[1]]
+ B.ha=[0,0]
+ courbes.ITEM[n0].beziers_knot.append(B)
+ CP=[l[0],l[1]]
+ return courbes,n0,CP
+
+def rligne_tracee_l(l,n0,CP):
+ B=Bez()
+ B.co=["%4f"%(float(l[0])+float(CP[0])),
+ "%4f"%(float(l[1])+float(CP[1])),
+ "%4f"%(float(l[0])+float(CP[0])),
+ "%4f"%(float(l[1])+float(CP[1])),
+ "%4f"%(float(l[0])+float(CP[0])),
+ "%4f"%(float(l[1])+float(CP[1]))]
+ B.ha=[0,0]
+ courbes.ITEM[n0].beziers_knot.append(B)
+ CP=[l[0],l[1]]
+ return courbes,n0,CP
+
+Actions= { "curveto" : courbe_vers_c,
+ "curveto" : courbe_vers_c,
+ "moveto" : mouvement_vers,
+ "rmoveto" : mouvement_vers,
+ "lineto" : ligne_tracee_l,
+ "rlineto" : rligne_tracee_l
+}
+
+TAGcourbe=Actions.keys()
+
+"""
+def pik_pattern(t,l):
+ global npat, PATTERN, BOUNDINGBOX
+ while t[l].find('%%EndSetup')!=0:
+ if t[l].find('%%BoundingBox:')!=-1:
+ l0=t[l].split()
+ BOUNDINGBOX['rec']=[float(l0[-4]),float(l0[-3]),float(l0[-2]),float(l0[-1])]
+ r=BOUNDINGBOX['rec']
+ BOUNDINGBOX['coef']=(r[3]-r[1])/(r[2]-r[0])
+ print l,
+ if t[l].find('BeginPatternLayer')!=-1:
+ npat+=1
+ PATTERN[npat]=[]
+ while t[l].find('EndPatternLayer')==-1:
+ print t[l]
+ PATTERN[npat].append(l)
+ l+=1
+ if l+1<len(t):
+ l=l+1
+ else:
+ return 1,l
+ return 1,l
+"""
+
+def scan_FILE(nom):
+ global CP, courbes, SCALE, scale
+ dir,name=split(nom)
+ name=name.split('.')
+ n0=0
+ result=0
+ t=filtreFICHIER(nom)
+
+ if nom.upper().find('.EPS')!=-1 or nom.upper().find('.PS')!=-1 and t!='false':
+ if not SHARP_IMPORT:
+ warning = "Select Size : %t| As is %x1 | Scale on Height %x2| Scale on Width %x3"
+ scale = Blender.Draw.PupMenu(warning)
+ npat=0
+ l=0
+ do=0
+ while l <len(t)-1 :
+ if t[l].find('%%BoundingBox:')!=-1:
+ l0=t[l].split()
+ BOUNDINGBOX['rec']=[float(l0[-4]),float(l0[-3]),float(l0[-2]),float(l0[-1])]
+ r=BOUNDINGBOX['rec']
+ BOUNDINGBOX['coef']=(r[3]-r[1])/(r[2]-r[0])
+ """
+ if not do:
+ do,l=pik_pattern(t,l)
+ """
+ #print 'len(t)',len(t)
+ t[l].replace('\n','')
+ if t[l][0]!='%':
+ l0=t[l].split()
+ if l0!=[] and l0[-1] in TAGcourbe:
+ if l0[-1] in ['curveto']:
+ l2=t[l+1].split()
+ courbes,n0,CP=Actions[l0[-1]](l0,l2,n0,CP)
+ else:
+ courbes,n0,CP=Actions[l0[-1]](l0,n0,CP)
+
+ l=l+1#; print l
+ t=[]
+
+ if t!='false':
+ courbes.number_of_items=len(courbes.ITEM.keys())
+
+ for k in courbes.ITEM.keys():
+ courbes.ITEM[k].pntsUV[0] =len(courbes.ITEM[k].beziers_knot)
+
+ if test_egalitedespositions(courbes.ITEM[k].Origine,
+ [courbes.ITEM[k].beziers_knot[-1].co[-2],
+ courbes.ITEM[k].beziers_knot[-1].co[-1]]):
+ courbes.ITEM[k].flagUV[0]=1
+ courbes.ITEM[k].pntsUV[0] -=1
+
+ if courbes.number_of_items>0:
+ if len(PATTERN.keys() )>0:
+ #print len(PATTERN.keys() )
+ pass
+ t=create_GEOtext(courbes)
+ save_GEOfile(dir,name[0],t)
+ Open_GEOfile(dir,name[0])
+ else:
+ pass
+
+
+#=====================================================================
+#====================== EPS format mouvements =========================
+#=====================================================================
+#=========================================================
+# une sorte de contournement qui permet d'utiliser la fonction
+# et de documenter les variables Window.FileSelector
+#=========================================================
+def fonctionSELECT(nom):
+ scan_FILE(nom)
+
+#Blender.Window.FileSelector (fonctionSELECT, 'SELECT .EPS/.PS FILE')
+#sys.path=oldpath
diff --git a/release/scripts/mod_gimp2obj.py b/release/scripts/mod_gimp2obj.py
new file mode 100644
index 00000000000..7128107cfcd
--- /dev/null
+++ b/release/scripts/mod_gimp2obj.py
@@ -0,0 +1,320 @@
+"""
+#----------------------------------------------
+# (c) jm soler juillet 2004, released under Blender Artistic Licence
+# for the Blender 2.34 Python Scripts Bundle.
+#----------------------------------------------
+# Page officielle :
+# http://jmsoler.free.fr/didacticiel/blender/tutor/cpl_import_gimp.htm
+# Communiquer les problemes et erreurs sur:
+# http://www.zoo-logique.org/3D.Blender/newsportal/thread.php?group=3D.Blender
+#---------------------------------------------
+"""
+SHARP_IMPORT=0
+SCALE=1
+
+import sys
+#oldpath=sys.path
+
+import Blender
+BLversion=Blender.Get('version')
+
+try:
+ import nt
+ os=nt
+ os.sep='\\'
+
+except:
+ import posix
+ os=posix
+ os.sep='/'
+
+def isdir(path):
+ try:
+ st = os.stat(path)
+ return 1
+ except:
+ return 0
+
+def split(pathname):
+ if pathname.find(os.sep)!=-1:
+ k0=pathname.split(os.sep)
+ else:
+ if os.sep=='/':
+ k0=pathname.split('\\')
+ else:
+ k0=pathname.split('/')
+
+ directory=pathname.replace(k0[len(k0)-1],'')
+ Name=k0[len(k0)-1]
+ return directory, Name
+
+def join(l0,l1):
+ return l0+os.sep+l1
+
+os.isdir=isdir
+os.split=split
+os.join=join
+
+def filtreFICHIER(nom):
+ f=open(nom,'r')
+ t=f.readlines()
+ f.close()
+ if len(t)==1 and t[0].find('\r'):
+ t=t[0].split('\r')
+ if len(t)>1 and t[1].find('#POINTS:')==0:
+ return t
+ else:
+ warning = "OK?%t| Not a valid file or an empty file ... " # if no %xN int is set, indices start from 1
+ result = Blender.Draw.PupMenu(warning)
+ return "false"
+
+#===============================
+# Data
+#===============================
+#===============================
+# Blender Curve Data
+#===============================
+objBEZIER=0
+objSURFACE=5
+typBEZIER3D=1 #3D
+typBEZIER2D=9 #2D
+
+class Bez:
+ def __init__(self):
+ self.co=[]
+ self.ha=[0,0]
+
+ def echo(self):
+ #print 'co = ', self.co
+ #print 'ha = ', self.ha
+ pass
+
+class ITEM:
+ def __init__(self):
+ self.type = typBEZIER3D,
+ self.pntsUV = [0,0]
+ self.resolUV = [32,0]
+ self.orderUV = [0,0]
+ self.flagUV = [0,0]
+ self.Origine = [0.0,0.0]
+ self.beziers_knot = []
+
+class COURBE:
+ def __init__(self):
+ self.magic_number='3DG3'
+ self.type = objBEZIER
+ self.number_of_items = 0
+ self.ext1_ext2 = [0,0]
+ self.matrix = """0.0 0.0 1.0 0.0
+0.0 1.0 0.0 0.0
+0.0 0.0 1.0 0.0
+0.0 0.0 0.0 1.0 """ #- right-handed object matrix. Used to determine position, rotation and size
+ self.ITEM = {}
+
+courbes=COURBE()
+PATTERN={}
+BOUNDINGBOX={'rec':[],'coef':1.0}
+npat=0
+#=====================================================================
+#======== name of the curve in the courbes dictionnary ===============
+#=====================================================================
+n0=0
+
+#=====================================================================
+#====================== current Point ================================
+#=====================================================================
+CP=[0.0,0.0] #currentPoint
+
+def MINMAX(b):
+ global BOUNDINGBOX
+ r=BOUNDINGBOX['rec']
+ for m in range(0,len(b)-2,2):
+ #print m, m+1 , len(b)-1
+ #print b[m], r, r[0]
+ if float(b[m])<r[0]:
+ r[0]=float(b[m])
+
+ if float(b[m])>r[2]: r[2]=float(b[m])
+
+ if float(b[m+1])<r[1]: r[1]=float(b[m+1])
+ if float(b[m+1])>r[3]: r[3]=float(b[m+1])
+
+#=====================================================================
+#===== to compare last position to the original move to displacement =
+#===== needed for cyclic efinition =================================
+#=====================================================================
+def test_egalitedespositions(f1,f2):
+ if f1[0]==f2[0] and f1[1]==f2[1]:
+ return Blender.TRUE
+ else:
+ return Blender.FALSE
+
+
+def Open_GEOfile(dir,nom):
+ if BLversion>=233:
+ Blender.Load(dir+nom+'OOO.obj', 1)
+ BO=Blender.Object.Get()
+
+ BO[-1].LocZ=1.0
+
+ BO[-1].makeDisplayList()
+ Blender.Window.RedrawAll()
+ else:
+ print "Not yet implemented"
+
+def create_GEOtext(courbes):
+ global SCALE, B, BOUNDINGBOX
+ r=BOUNDINGBOX['rec']
+ if SCALE==1:
+ SCALE=1.0
+ elif SCALE==2:
+ SCALE=r[2]-r[0]
+ elif SCALE==3:
+ SCALE=r[3]-r[1]
+
+ t=[]
+ t.append(courbes.magic_number+'\n')
+ t.append(str(courbes.type)+'\n')
+ t.append(str(courbes.number_of_items)+'\n')
+ t.append(str(courbes.ext1_ext2[0])+' '+str(courbes.ext1_ext2[1])+'\n')
+ t.append(courbes.matrix+'\n')
+
+ for k in courbes.ITEM.keys():
+
+ t.append("%s\n"%courbes.ITEM[k].type)
+
+ t.append("%s %s \n"%(courbes.ITEM[k].pntsUV[0],courbes.ITEM[k].pntsUV[1]))
+ t.append("%s %s \n"%(courbes.ITEM[k].resolUV[0],courbes.ITEM[k].resolUV[1]))
+ t.append("%s %s \n"%(courbes.ITEM[k].orderUV[0],courbes.ITEM[k].orderUV[1]))
+ t.append("%s %s \n"%(courbes.ITEM[k].flagUV[0],courbes.ITEM[k].flagUV[1]))
+
+ flag =0#courbes.ITEM[k].flagUV[0]
+
+ for k2 in range(flag,len(courbes.ITEM[k].beziers_knot)):
+ k1 =courbes.ITEM[k].beziers_knot[k2]
+ t.append("%4f 0.0 %4f \n"%(float(k1.co[0])/SCALE,float(k1.co[1])/SCALE))
+ t.append("%4f 0.0 %4f \n"%(float(k1.co[4])/SCALE,float(k1.co[5])/SCALE))
+ t.append("%4f 0.0 %4f \n"%(float(k1.co[2])/SCALE,float(k1.co[3])/SCALE))
+ t.append(str(k1.ha[0])+' '+str(k1.ha[1])+'\n')
+ return t
+
+def save_GEOfile(dir,nom,t):
+ f=open(dir+nom+'OOO.obj','w')
+ f.writelines(t)
+ f.close()
+ #warning = "REMINDER : %t | Do not forget to rename your blender file NOW ! %x1"
+ #result = Blender.Draw.PupMenu(warning)
+
+
+#=====================================================================
+#===== GIMP format : DEBUT =========================
+#=====================================================================
+CLOSED=0
+
+def mouvement_vers(l,l1,l2,n0):
+ global BOUNDINGBOX, CP
+ if l[1] == '3' :
+ n0+=1
+ courbes.ITEM[n0]=ITEM()
+ courbes.ITEM[n0].Origine=[l[-3],l[-1],]
+ courbes.ITEM[n0-1].beziers_knot[0].co[0]=CP[0]
+ courbes.ITEM[n0-1].beziers_knot[0].co[1]=CP[1]
+ CP=[l2[-3], l2[-1]]
+
+ elif l[1]=='1' and (n0 not in courbes.ITEM.keys()):
+ courbes.ITEM[n0]=ITEM()
+ courbes.ITEM[n0].Origine=[l[-3],l[-1],]
+ CP=[l2[-3], l2[-1]]
+
+ B=Bez()
+ B.co=[ CP[0],CP[1],
+ l1[-3], l1[-1],
+ l[-3], l[-1]]
+
+ CP=[l2[-3], l2[-1]]
+
+ if BOUNDINGBOX['rec']==[]:
+ BOUNDINGBOX['rec']=[float(l2[-3]), float(l2[-1]), float(l[-3]), float(l[-1])]
+ B.ha=[0,0]
+
+ """
+ if len( courbes.ITEM[n0].beziers_knot)>=1:
+ courbes.ITEM[n0].beziers_knot[-1].co[2]=l1[-3]
+ courbes.ITEM[n0].beziers_knot[-1].co[3]=l1[-1]
+ """
+
+ MINMAX(B.co)
+ courbes.ITEM[n0].beziers_knot.append(B)
+ return courbes,n0
+
+Actions= { "1" : mouvement_vers,
+ "3" : mouvement_vers }
+
+TAGcourbe=Actions.keys()
+
+def scan_FILE(nom):
+ global CP, courbes, SCALE, MAX, MIN, CLOSED
+ dir,name=split(nom)
+ name=name.split('.')
+ #print name
+ n0=0
+ result=0
+ t=filtreFICHIER(nom)
+ if t!="false":
+ if not SHARP_IMPORT:
+ warning = "Select Size : %t| As is %x1 | Scale on Height %x2| Scale on Width %x3"
+ SCALE = Blender.Draw.PupMenu(warning)
+ npat=0
+ l=0
+ while l <len(t)-1 :
+ #print 'len(t)',len(t)
+ t[l].replace('\n','')
+ if t[l][0]!='%':
+ l0=t[l].split()
+ #print l0[0], l0[1]
+ if l0[0]=='TYPE:' and l0[1] in TAGcourbe:
+ #print l0[0], l0[1],
+ l1=t[l+1].split()
+ l2=t[l+2].split()
+ courbes,n0=Actions[l0[1]](l0,l1,l2,n0)
+ elif l0[0]=='#Point':
+ POINTS= int(l0[0])
+ elif l0[0]=='CLOSED:' and l0[1]=='1':
+ CLOSED=1
+ l=l+1;
+
+ courbes.number_of_items=len(courbes.ITEM.keys())
+
+ courbes.ITEM[n0].beziers_knot[0].co[0]=CP[0]
+ courbes.ITEM[n0].beziers_knot[0].co[1]=CP[1]
+
+ for k in courbes.ITEM.keys():
+ #print k
+ if CLOSED == 1:
+ B=Bez()
+ B.co=courbes.ITEM[k].beziers_knot[0].co[:]
+ B.ha=courbes.ITEM[k].beziers_knot[0].ha[:]
+ B.echo()
+ courbes.ITEM[k].beziers_knot.append(B)
+ courbes.ITEM[k].flagUV[0]=1
+ courbes.ITEM[k].pntsUV[0] =len(courbes.ITEM[k].beziers_knot)
+
+ if courbes.number_of_items>0:
+ t=create_GEOtext(courbes)
+ save_GEOfile(dir,name[0],t)
+ Open_GEOfile(dir,name[0])
+ else:
+ pass
+
+#=====================================================================
+#====================== GIMP Path format mouvements =========================
+#=====================================================================
+#=========================================================
+# une sorte de contournement qui permet d'utiliser la fonction
+# et de documenter les variables Window.FileSelector
+#=========================================================
+def fonctionSELECT(nom):
+ scan_FILE(nom)
+
+#Blender.Window.FileSelector (fonctionSELECT, 'SELECT a GIMP Path FILE')
+#sys.path=oldpath
diff --git a/release/scripts/mod_svg2obj.py b/release/scripts/mod_svg2obj.py
new file mode 100644
index 00000000000..d180b0d26c5
--- /dev/null
+++ b/release/scripts/mod_svg2obj.py
@@ -0,0 +1,647 @@
+"""
+(c) jm soler juillet 2004, released under Blender Artistic Licence
+ for the Blender 2.34 Python Scripts Bundle.
+#---------------------------------------------------------------------------
+# Page officielle :
+# http://jmsoler.free.fr/didacticiel/blender/tutor/cpl_import_svg.htm
+# Communiquer les problemes et erreurs sur:
+# http://www.zoo-logique.org/3D.Blender/newsportal/thread.php?group=3D.Blender
+#---------------------------------------------------------------------------
+
+-- Concept : translate SVG file in GEO .obj file and try to load it.
+-- Real problem : the name of the blender file is changed ...
+-- Curiousity : the original matrix must be :
+
+ 0.0 0.0 1.0 0.0
+ 0.0 1.0 0.0 0.0
+ 0.0 0.0 1.0 0.0
+ 0.0 0.0 0.0 1.0
+
+ and not:
+ 1.0 0.0 0.0 0.0
+ 0.0 1.0 0.0 0.0
+ 0.0 0.0 1.0 0.0
+ 0.0 0.0 0.0 1.0
+
+-- Options :
+ SHARP_IMPORT = 0
+ choise between "As is", "Devide by height" and "Devide by width"
+ SHARP_IMPORT = 1
+ no choise
+
+-- Possible bug : sometime, the new curves object's RotY value
+ jumps to -90.0 degrees without any reason.
+
+Yet done:
+ M : absolute move to
+ Z : close path
+ L : absolute line to
+ C : absolute curve to
+ S : absolute curve to with only one handle
+ l : relative line to 2004/08/03
+ c : relative curve to 2004/08/03
+ s : relative curve to with only one handle
+
+To do: A,S,V,H,Q,T,
+ a,s, m, v, h, q,t
+
+Changelog:
+ 0.1.1 : - control file without extension
+ 0.2.0 : - improved reading of several data of the same type
+ following the same command (for gimp import)
+ 0.2.1 : - better choice for viewboxing ( takes the viewbox if found,
+ instead of x,y,width and height
+ 0.2.2 : - read compact path data from Illustrator 10
+ 0.2.3 : - read a few new relative displacements
+ 0.2.4 : - better hash for command with followed by a lone data
+ (h,v) or uncommun number (a)
+==================================================================================
+=================================================================================="""
+
+SHARP_IMPORT=0
+SCALE=1
+scale=1
+DEBUG =0
+DEVELOPPEMENT=1
+
+import sys
+#oldpath=sys.path
+import Blender
+BLversion=Blender.Get('version')
+
+try:
+ import nt
+ os=nt
+ os.sep='\\'
+
+except:
+ import posix
+ os=posix
+ os.sep='/'
+
+def isdir(path):
+ try:
+ st = os.stat(path)
+ return 1
+ except:
+ return 0
+
+def split(pathname):
+ if pathname.find(os.sep)!=-1:
+ k0=pathname.split(os.sep)
+ else:
+ if os.sep=='/':
+ k0=pathname.split('\\')
+ else:
+ k0=pathname.split('/')
+
+ directory=pathname.replace(k0[len(k0)-1],'')
+ Name=k0[len(k0)-1]
+ return directory, Name
+
+def join(l0,l1):
+ return l0+os.sep+l1
+
+os.isdir=isdir
+os.split=split
+os.join=join
+
+def filtreFICHIER(nom):
+ f=open(nom,'r')
+ t=f.read()
+ f.close()
+ t=t.replace('\r','')
+ t=t.replace('\n','')
+
+ if t.upper().find('<SVG')==-1:
+ name = "OK?%t| Not a valid file or an empty file ... " # if no %xN int is set, indices start from 1
+ result = Blender.Draw.PupMenu(name)
+ return "false"
+ else:
+ return t
+
+#===============================
+# Data
+#===============================
+#===============================
+# Blender Curve Data
+#===============================
+objBEZIER=0
+objSURFACE=5
+typBEZIER3D=1 #3D
+typBEZIER2D=9 #2D
+
+class Bez:
+ def __init__(self):
+ self.co=[]
+ self.ha=[0,0]
+
+class ITEM:
+ def __init__(self):
+ self.type = typBEZIER3D,
+ self.pntsUV = [0,0]
+ self.resolUV = [32,0]
+ self.orderUV = [0,0]
+ self.flagUV = [0,0]
+ self.Origine = [0.0,0.0]
+ self.beziers_knot = []
+
+class COURBE:
+ def __init__(self):
+ self.magic_number='3DG3'
+ self.type = objBEZIER
+ self.number_of_items = 0
+ self.ext1_ext2 = [0,0]
+ self.matrix = """0.0 0.0 1.0 0.0
+0.0 1.0 0.0 0.0
+0.0 0.0 1.0 0.0
+0.0 0.0 0.0 1.0 """
+ self.ITEM = {}
+
+
+courbes=COURBE()
+PATTERN={}
+BOUNDINGBOX={'rec':[],'coef':1.0}
+npat=0
+#=====================================================================
+#======== name of the curve in the curves dictionnary ===============
+#=====================================================================
+n0=0
+
+#=====================================================================
+#====================== current Point ================================
+#=====================================================================
+CP=[0.0,0.0] #currentPoint
+
+#=====================================================================
+#===== to compare last position to the original move to displacement =
+#===== needed for cyclic definition inAI, EPS forma ================
+#=====================================================================
+def test_egalitedespositions(f1,f2):
+ if f1[0]==f2[0] and f1[1]==f2[1]:
+ return Blender.TRUE
+ else:
+ return Blender.FALSE
+
+
+def Open_GEOfile(dir,nom):
+ global SCALE,BOUNDINGBOX, scale
+ if BLversion>=233:
+ Blender.Load(dir+nom+'OOO.obj', 1)
+ BO=Blender.Object.Get()
+
+ BO[-1].RotY=3.1416
+ BO[-1].RotZ=3.1416
+ BO[-1].RotX=3.1416/2.0
+
+ if scale==1:
+ BO[-1].LocY+=BOUNDINGBOX['rec'][3]
+ else:
+ BO[-1].LocY+=BOUNDINGBOX['rec'][3]/SCALE
+
+ BO[-1].makeDisplayList()
+ Blender.Window.RedrawAll()
+ else:
+ print "Not yet implemented"
+
+def create_GEOtext(courbes):
+ global SCALE, B, BOUNDINGBOX,scale
+ r=BOUNDINGBOX['rec']
+
+ if scale==1:
+ SCALE=1.0
+ elif scale==2:
+ SCALE=r[2]-r[0]
+ elif scale==3:
+ SCALE=r[3]-r[1]
+
+ t=[]
+ t.append(courbes.magic_number+'\n')
+ t.append(str(courbes.type)+'\n')
+ t.append(str(courbes.number_of_items)+'\n')
+ t.append(str(courbes.ext1_ext2[0])+' '+str(courbes.ext1_ext2[1])+'\n')
+ t.append(courbes.matrix+'\n')
+
+ for k in courbes.ITEM.keys():
+ t.append("%s\n"%courbes.ITEM[k].type)
+ t.append("%s %s \n"%(courbes.ITEM[k].pntsUV[0],courbes.ITEM[k].pntsUV[1]))
+ t.append("%s %s \n"%(courbes.ITEM[k].resolUV[0],courbes.ITEM[k].resolUV[1]))
+ t.append("%s %s \n"%(courbes.ITEM[k].orderUV[0],courbes.ITEM[k].orderUV[1]))
+ t.append("%s %s \n"%(courbes.ITEM[k].flagUV[0],courbes.ITEM[k].flagUV[1]))
+
+ flag =0#courbes.ITEM[k].flagUV[0]
+
+ for k2 in range(flag,len(courbes.ITEM[k].beziers_knot)):
+ #k1 =courbes.ITEM[k].beziers_knot[k2]
+ k1=ajustement(courbes.ITEM[k].beziers_knot[k2], SCALE)
+
+ t.append("%4f 0.0 %4f \n"%(k1[4],k1[5]))
+ t.append("%4f 0.0 %4f \n"%(k1[0],k1[1]))
+ t.append("%4f 0.0 %4f \n"%(k1[2],k1[3]))
+ t.append(str(courbes.ITEM[k].beziers_knot[k2].ha[0])+' '+str(courbes.ITEM[k].beziers_knot[k2].ha[1])+'\n')
+
+ return t
+
+def save_GEOfile(dir,nom,t):
+ f=open(dir+nom+'OOO.obj','w')
+ f.writelines(t)
+ f.close()
+ #warning = "REMINDER : %t | Do not forget to rename your blender file NOW ! %x1"
+ #result = Blender.Draw.PupMenu(warning)
+
+
+def filtre_DATA(c,D,n):
+ global DEBUG,TAGcourbe
+ l=[]
+
+ if len(c[0])==1 and D[c[1]+1].find(',')!=-1:
+ for n2 in range(1,n+1):
+ ld=D[c[1]+n2].split(',')
+ for l_ in ld:
+ l.append(l_)
+
+ elif len(c[0])==1 and D[c[1]+2][0] not in TAGcourbe:
+ for n2 in range(1,n*2+1):
+ l.append(D[c[1]+n2])
+ if DEBUG==1 : print l
+
+ return l
+
+#=====================================================================
+#===== SVG format : DEBUT =========================
+#=====================================================================
+
+def contruit_SYMETRIC(l):
+ L=[float(l[0]), float(l[1]),
+ float(l[2]),float(l[3])]
+ X=L[0]-(L[2]-L[0])
+ Y=L[1]-(L[3]-L[1])
+ l =[l[0],l[1],"%4s"%X,"%4s"%Y,l[2],l[3]]
+ return l
+
+def mouvement_vers(c, D, n0,CP):
+ global DEBUG,TAGcourbe
+ #print c,D[c[1]+1]
+
+ l=filtre_DATA(c,D,1)
+ #print l
+ if n0 in courbes.ITEM.keys():
+ n0+=1
+ CP=[l[0],l[1]]
+ else:
+ CP=[l[0],l[1]]
+
+ courbes.ITEM[n0]=ITEM()
+ courbes.ITEM[n0].Origine=[l[0],l[1]]
+
+ B=Bez()
+ B.co=[CP[0],CP[1],CP[0],CP[1],CP[0],CP[1]]
+ B.ha=[0,0]
+
+ courbes.ITEM[n0].beziers_knot.append(B)
+ if DEBUG==1: print courbes.ITEM[n0], CP
+
+
+ return courbes,n0,CP
+
+def boucle_z(c,D,n0,CP): #Z,z
+ #print c, 'close'
+ courbes.ITEM[n0].flagUV[0]=1
+ return courbes,n0,CP
+
+def courbe_vers_s(c,D,n0,CP): #S,s
+ l=filtre_DATA(c,D,2)
+ if c[0]=='s':
+ l=["%4s"%(float(l[0])+float(CP[0])),
+ "%4s"%(float(l[1])+float(CP[1])),
+ "%4s"%(float(l[2])+float(CP[0])),
+ "%4s"%(float(l[3])+float(CP[1]))]
+ l=contruit_SYMETRIC(l)
+ B=Bez()
+ B.co=[l[4],l[5],l[2],l[3],l[0],l[1]] #plus toucher au 2-3
+ B.ha=[0,0]
+
+ BP=courbes.ITEM[n0].beziers_knot[-1]
+ BP.co[2]=l[2] #4-5 point prec
+ BP.co[3]=l[3]
+
+ courbes.ITEM[n0].beziers_knot.append(B)
+ if DEBUG==1: print B.co,BP.co
+ CP=[l[4],l[5]]
+
+ if D[c[1]+3] not in TAGcourbe :
+ c[1]+=2
+ courbe_vers_c(c, D, n0,CP)
+ return courbes,n0,CP
+
+def courbe_vers_a(c,D,n0,CP): #A
+ #print c
+ return courbes,n0,CP
+
+def courbe_vers_q(c,D,n0,CP): #Q
+ #print c
+ return courbes,n0,CP
+
+def courbe_vers_t(c,D,n0,CP): #T
+ return courbes,n0,CP
+
+def courbe_vers_c(c, D, n0,CP): #c,C
+
+ l=filtre_DATA(c,D,3)
+ #print l, c, CP
+
+ if c[0]=='c':
+ l=["%4s"%(float(l[0])+float(CP[0])),
+ "%4s"%(float(l[1])+float(CP[1])),
+ "%4s"%(float(l[2])+float(CP[0])),
+ "%4s"%(float(l[3])+float(CP[1])),
+ "%4s"%(float(l[4])+float(CP[0])),
+ "%4s"%(float(l[5])+float(CP[1]))]
+
+ #print l
+
+ B=Bez()
+ B.co=[l[4],
+ l[5],
+ l[0],
+ l[1],
+ l[2],
+ l[3]] #plus toucher au 2-3
+
+ B.ha=[0,0]
+
+ BP=courbes.ITEM[n0].beziers_knot[-1]
+
+ BP.co[2]=l[0]
+ BP.co[3]=l[1]
+
+ courbes.ITEM[n0].beziers_knot.append(B)
+ if DEBUG==1: print B.co,BP.co
+
+ CP=[l[4],l[5]]
+
+ if D[c[1]+4] not in TAGcourbe :
+ c[1]+=3
+ courbe_vers_c(c, D, n0,CP)
+
+ return courbes,n0,CP
+
+
+def ligne_tracee_l(c, D, n0,CP): #L,l
+ #print c
+
+ l=filtre_DATA(c,D,1)
+ if c[0]=='l':
+ l=["%4s"%(float(l[0])+float(CP[0])),
+ "%4s"%(float(l[1])+float(CP[1]))]
+
+ B=Bez()
+ B.co=[l[0],l[1],l[0],l[1],l[0],l[1]]
+ B.ha=[0,0]
+ courbes.ITEM[n0].beziers_knot.append(B)
+
+ CP=[l[0],l[1]]
+
+ if D[c[1]+2] not in TAGcourbe :
+ c[1]+=1
+ ligne_tracee_l(c, D, n0,CP) #L
+
+ return courbes,n0,CP
+
+
+def ligne_tracee_h(c,D,n0,CP): #H,h
+
+ return courbes,n0,CP
+
+def ligne_tracee_v(c,D,n0,CP): #V
+ #print c
+ #CP=[]
+ return courbes,n0,CP
+
+def boucle_tracee_z(c,D,n0,CP): #Z
+ #print c
+ #CP=[]
+ return courbes,n0,CP
+
+Actions= { "C" : courbe_vers_c,
+ "A" : courbe_vers_a,
+ "S" : courbe_vers_s,
+ "M" : mouvement_vers,
+ "V" : ligne_tracee_v,
+ "L" : ligne_tracee_l,
+ "H" : ligne_tracee_h,
+ "Z" : boucle_z,
+ "Q" : courbe_vers_q,
+ "T" : courbe_vers_t,
+
+ "c" : courbe_vers_c,
+ "a" : courbe_vers_a,
+ "s" : courbe_vers_s,
+ "m" : mouvement_vers,
+ "v" : ligne_tracee_v,
+ "l" : ligne_tracee_l,
+ "h" : ligne_tracee_h,
+ "z" : boucle_z,
+ "q" : courbe_vers_q,
+ "T" : courbe_vers_t
+}
+
+TAGcourbe=Actions.keys()
+
+def get_content(val,t0):
+ t=t0[:]
+ if t.find(' '+val+'="')!=-1:
+ t=t[t.find(' '+val+'="')+len(' '+val+'="'):]
+ val=t[:t.find('"')]
+ t=t[t.find('"'):]
+ #----------------------------------------------------------------
+ #print t[:10], val
+ #wait=raw_input('wait:' )
+
+ return t0,val
+ else:
+ return t0,0
+
+def get_tag(val,t):
+
+ t=t[t.find('<'+val):]
+ val=t[:t.find('>')+1]
+ t=t[t.find('>')+1:]
+
+ if DEBUG==3 : print t[:10], val
+
+ return t,val
+
+def get_val(val,t):
+ d=""
+ for l in t:
+ if l.find(val+'="')!=-1:
+ d=l[l[:-1].rfind('"')+1:-1]
+ for nn in d :
+ if '012345670.'.find(nn)==-1:
+ d=d.replace(nn,"")
+ d=float(d)
+ break
+ d=0.0
+ return d
+
+def get_BOUNDBOX(BOUNDINGBOX,SVG,viewbox):
+ if viewbox==0:
+ h=get_val('height',SVG)
+ w=get_val('width',SVG)
+ BOUNDINGBOX['rec']=[0.0,0.0,w,h]
+ r=BOUNDINGBOX['rec']
+ BOUNDINGBOX['coef']=w/h
+ else:
+ viewbox=viewbox.split()
+ BOUNDINGBOX['rec']=[float(viewbox[0]),float(viewbox[1]),float(viewbox[2]),float(viewbox[3])]
+ r=BOUNDINGBOX['rec']
+ BOUNDINGBOX['coef']=(r[2]-r[0])/(r[3]-r[1])
+
+ return BOUNDINGBOX
+
+def unpack_DATA(DATA):
+ DATA[0]=DATA[0].replace('-',',-')
+ for d in Actions.keys():
+ DATA[0]=DATA[0].replace(d,','+d+',')
+ DATA[0]=DATA[0].replace(',,',',')
+ if DATA[0][0]==',':DATA[0]=DATA[0][1:]
+ if DATA[0][-1]==',':DATA[0]=DATA[0][:-1]
+ DATA[0]=DATA[0].replace('\n','')
+ DATA[0]=DATA[0].replace('\t','')
+ DATA[0]=DATA[0].split(',')
+ D2=[]
+ D1=DATA[0]
+
+ for cell in range(len(D1)):
+ if D1[cell] in Actions.keys():
+ D2.append(D1[cell])
+ n=1
+ if D1[cell] not in ['h','v','H','V','a','A']:
+ while cell+n+1<len(D1) and (D1[cell+n] not in Actions.keys()):
+ D2.append(D1[cell+n]+','+D1[cell+n+1])
+ n+=2
+ elif D1[cell] in ['h','v','H','V']:
+ while cell+n+1<len(D1) and (D1[cell+n] not in Actions.keys()):
+ D2.append(D1[cell+n])
+ n+=1
+ elif D1[cell] in ['a','A']:
+ #(rx ry rotation-axe-x drapeau-arc-large drapeau-balayage x y)
+ #150,150 0 1,0 150,-150
+ D2.append(D1[cell+n]+','+D1[cell+n+1])
+ D2.append(D1[cell+n+2])
+ D2.append(D1[cell+n+3]+','+D1[cell+n+4])
+ D2.append(D1[cell+n+5]+','+D1[cell+n+6])
+ n+=7
+ return D2
+
+def format_PATH(t):
+
+ t,PATH=get_tag('path',t)
+
+ if PATH.find(' id="')!=-1:
+ PATH,ID=get_content('id',PATH)
+ #print 'ident = ', ID
+
+ if PATH.find(' STROKE="')!=-1:
+ PATH,ID=get_content('stroke',PATH)
+ #print 'path stroke = ', ID
+
+ if PATH.find(' stroke-width="')!=-1:
+ PATH,ID=get_content('stroke-width',PATH)
+ #print 'path stroke-width = ', ID
+
+ if PATH.find(' d="')!=-1:
+ PATH,D=get_content('d',PATH)
+
+ #print "D0= :",D
+
+ D=D.split(' ')
+ #print len(D)
+ #for D0 in D:
+ #print " ----> D = :", D0
+
+ if len(D)==1 or len(D[0])>1:
+ D1=[]
+ for D0 in D:
+ D1+=unpack_DATA([D0])[:]
+ D=D1
+
+ #print "D2= :",D
+ return t,D
+
+
+def scan_FILE(nom):
+ global CP, courbes, SCALE, DEBUG, BOUNDINGBOX, scale
+ dir,name=split(nom)
+ name=name.split('.')
+ n0=0
+ result=0
+
+ t=filtreFICHIER(nom)
+
+ if t!='false':
+ if not SHARP_IMPORT:
+ warning = "Select Size : %t| As is %x1 | Scale on Height %x2| Scale on Width %x3"
+ scale = Blender.Draw.PupMenu(warning)
+ npat=0
+ l=0
+ do=0
+ t,SVG=get_tag('svg',t)
+
+ SVG,viewbox=get_content('viewBox',SVG)
+
+ SVG=SVG.split(' ')
+ if viewbox==0:
+ BOUNDINGBOX = get_BOUNDBOX(BOUNDINGBOX,SVG,0)
+ else:
+ BOUNDINGBOX = get_BOUNDBOX(BOUNDINGBOX,SVG,viewbox)
+
+ #print t
+
+ while t.find('path')!=-1:
+
+ t,D=format_PATH(t)
+
+ cursor=0
+ for cell in D:
+ if DEBUG==2 : print 'cell : ',cell ,' --'
+ #print 'cell',cell
+ if len(cell)>=1 and cell[0] in TAGcourbe:
+ courbes,n0,CP=Actions[cell]([cell,cursor], D, n0,CP)
+
+ cursor+=1
+
+ courbes.number_of_items=len(courbes.ITEM.keys())
+
+ for k in courbes.ITEM.keys():
+ courbes.ITEM[k].pntsUV[0] =len(courbes.ITEM[k].beziers_knot)
+
+ if courbes.number_of_items>0:
+ if len(PATTERN.keys() )>0:
+ if DEBUG == 3 : print len(PATTERN.keys() )
+ t=create_GEOtext(courbes)
+ save_GEOfile(dir,name[0],t)
+ Open_GEOfile(dir,name[0])
+ else:
+ pass
+
+def ajustement(v,s):
+
+ a,b,c,d,e,f=float(v.co[0]),float(v.co[1]),float(v.co[2]),float(v.co[3]),float(v.co[4]),float(v.co[5])
+ return [a/s,-b/s,c/s,-d/s,e/s,-f/s]
+
+#=====================================================================
+#====================== SVG format mouvements ========================
+#=====================================================================
+
+#=====================================================================
+# une sorte de contournement qui permet d'utiliser la fonction
+# et de documenter les variables Window.FileSelector
+#=====================================================================
+def fonctionSELECT(nom):
+ scan_FILE(nom)
+
+if DEVELOPPEMENT==0:
+ Blender.Window.FileSelector (fonctionSELECT, 'SELECT a .SVG FILE')
+ #sys.path=oldpath
diff --git a/release/scripts/obj_export.py b/release/scripts/obj_export.py
index 814f9b481a2..12e09828169 100644
--- a/release/scripts/obj_export.py
+++ b/release/scripts/obj_export.py
@@ -7,8 +7,6 @@ Group: 'Export'
Tooltip: 'Save a Wavefront OBJ File'
"""
-# $Id$
-#
# --------------------------------------------------------------------------
# OBJ Export v0.9 by Campbell Barton (AKA Ideasman)
# --------------------------------------------------------------------------
@@ -49,19 +47,6 @@ def stripPath(path):
return path
-#================================================#
-# 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 #
#==================#
@@ -118,119 +103,110 @@ def save_mtl(filename):
def save_obj(filename):
-
- # First output all material
- mtlfilename = filename[:-4] + '.mtl'
- save_mtl(mtlfilename)
-
-
-
- file = open(filename, "w")
-
-
- # Write Header
- file.write('# Blender OBJ File: ' + Get('filename') + ' \n')
- file.write('# www.blender.org\n')
-
- # Tell the obj file what file to use.
- file.write('mtllib ' + stripPath(mtlfilename) + ' \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 = NULL_MAT
- currentImgName = NULL_IMG
-
- file.write('o ' + ob.getName() + '_' + m.name + '\n') # Write Object name
-
- # Dosent work properly,
- matrix = getWorldMat(ob)
-
- smooth = 0
-
- # 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:
- if len(f.v) > 2:
- 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 f1 in m.faces:
- if len(f1.v) > 2:
- for v in f1.v:
- # Transform the normal
- noTx = apply_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')
+
+ # First output all material
+ mtlfilename = filename[:-4] + '.mtl'
+ save_mtl(mtlfilename)
+
+ file = open(filename, "w")
+
+ # Write Header
+ file.write('# Blender OBJ File: ' + Get('filename') + ' \n')
+ file.write('# www.blender.org\n')
+
+ # Tell the obj file what file to use.
+ file.write('mtllib ' + stripPath(mtlfilename) + ' \n')
+
+ # Initialize totals, these are updated each object
+ totverts = totuvco = 0
+
+
+ # 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 = NULL_MAT
+ currentImgName = NULL_IMG
+
+ file.write('o ' + ob.getName() + '_' + m.name + '\n') # Write Object name
+
+ # Works 100% Yay
+ matrix = ob.getMatrix('worldspace')
+
+ # Vert
+ for v in m.verts:
+ # Transform the vert
+ vTx = apply_transform(v.co, matrix)
- uvIdx = 0
- for f in m.faces:
- if len(f.v) > 2:
- # 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('v ')
+ file.write(saneFloat(vTx[0]))
+ file.write(saneFloat(vTx[1]))
+ file.write(saneFloat(vTx[2]) + '\n')
+
+ # UV
+ for f in m.faces:
+ if len(f.v) > 2:
+ 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 f1 in m.faces:
+ if len(f1.v) > 2:
+ for v in f1.v:
+ # Transform the normal
+ noTx = apply_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:
+ if len(f.v) > 2:
+ # 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')
- # UV IMAGE
- # If the face uses a different image from the one last set then add a usemap line.
- if f.image:
- if f.image.filename != currentImgName:
- currentImgName = f.image.filename
- file.write( 'usemat ' + stripPath(currentImgName) +'\n') # Set a new image for all following faces
-
- elif currentImgName != NULL_IMG: # Not using an image so set to NULL_IMG
- currentImgName = NULL_IMG
+ elif currentMatName != NULL_MAT:
+ currentMatName = NULL_MAT
+ file.write('usemtl ' + currentMatName + '\n')
+
+ # UV IMAGE
+ # If the face uses a different image from the one last set then add a usemap line.
+ if f.image:
+ if f.image.filename != currentImgName:
+ currentImgName = f.image.filename
file.write( 'usemat ' + stripPath(currentImgName) +'\n') # Set a new image for all following faces
-
- if f.smooth == 1:
- if smooth == 0:
- smooth = 1
- file.write('s 1\n')
-
- if f.smooth == 0:
- if smooth == 1:
- smooth = 0
- file.write('s off\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, 'Export OBJ', newFName('obj'))
+
+ elif currentImgName != NULL_IMG: # Not using an image so set to NULL_IMG
+ currentImgName = NULL_IMG
+ file.write( 'usemat ' + stripPath(currentImgName) +'\n') # Set a new image for all following faces
+
+ file.write('f ')
+ for v in f.v:
+ file.write( str(m.verts.index(v) + totverts +1) + '/') # Vert IDX
+ file.write( str(uvIdx + totuvco +1) + '/') # UV IDX
+ file.write( str(uvIdx + totuvco +1) + ' ') # NORMAL IDX
+ uvIdx+=1
+ file.write('\n')
+
+ # Make the indicies global rather then per mesh
+ totverts += len(m.verts)
+ totuvco += uvIdx
+ file.close()
+
+Window.FileSelector(save_obj, 'Export Wavefront OBJ', newFName('obj'))
diff --git a/release/scripts/obj_import.py b/release/scripts/obj_import.py
index e19c52b7be1..236b9705d33 100644
--- a/release/scripts/obj_import.py
+++ b/release/scripts/obj_import.py
@@ -53,19 +53,18 @@ def pathName(path,name):
# 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
+ 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) ]
+ prefixDelimiter = '.'
+ return name[ : name.find(prefixDelimiter) ]
from Blender import *
@@ -74,27 +73,27 @@ from Blender import *
# 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)
+ # Make a new mat
+ try:
+ return Material.Get(matName)
+ except:
+ return Material.New(matName)
#==================================================================================#
# This function sets textures defined in .mtl file #
#==================================================================================#
def getImg(img_fileName):
- for i in Image.Get():
- if i.filename == img_fileName:
- return i
+ for i in Image.Get():
+ if i.filename == img_fileName:
+ return i
- # if we are this far it means the image hasnt been loaded.
- try:
- return Image.Load(img_fileName)
- except:
- print "unable to open", img_fileName
- return
+ # if we are this far it means the image hasnt been loaded.
+ try:
+ return Image.Load(img_fileName)
+ except:
+ print "unable to open", img_fileName
+ return
@@ -102,270 +101,309 @@ def getImg(img_fileName):
# This function sets textures defined in .mtl file #
#==================================================================================#
def load_mat_image(mat, img_fileName, type, mesh):
- try:
- image = Image.Load(img_fileName)
- except:
- print "unable to open", img_fileName
- return
+ try:
+ image = Image.Load(img_fileName)
+ except:
+ print "unable to open", img_fileName
+ return
- texture = Texture.New(type)
- texture.setType('Image')
- texture.image = image
+ texture = Texture.New(type)
+ texture.setType('Image')
+ texture.image = image
- # adds textures to faces (Textured/Alt-Z mode)
- # Only apply the diffuse texture to the face if the image has not been set with the inline usemat func.
- if type == 'Kd':
- for f in mesh.faces:
- if mesh.materials[f.mat].name == mat.name:
-
- # the inline usemat command overides the material Image
- if not f.image:
- f.image = image
+ # adds textures to faces (Textured/Alt-Z mode)
+ # Only apply the diffuse texture to the face if the image has not been set with the inline usemat func.
+ if type == 'Kd':
+ for f in mesh.faces:
+ if mesh.materials[f.mat].name == mat.name:
+
+ # the inline usemat command overides the material Image
+ if not f.image:
+ f.image = image
- # adds textures for materials (rendering)
- if type == 'Ka':
- mat.setTexture(0, texture, Texture.TexCo.UV, Texture.MapTo.CMIR)
- if type == 'Kd':
- mat.setTexture(1, texture, Texture.TexCo.UV, Texture.MapTo.COL)
- if type == 'Ks':
- mat.setTexture(2, texture, Texture.TexCo.UV, Texture.MapTo.SPEC)
+ # adds textures for materials (rendering)
+ if type == 'Ka':
+ mat.setTexture(0, texture, Texture.TexCo.UV, Texture.MapTo.CMIR)
+ if type == 'Kd':
+ mat.setTexture(1, texture, Texture.TexCo.UV, Texture.MapTo.COL)
+ if type == 'Ks':
+ mat.setTexture(2, texture, Texture.TexCo.UV, Texture.MapTo.SPEC)
#==================================================================================#
# This function loads materials from .mtl file (have to be defined in obj file) #
#==================================================================================#
def load_mtl(dir, mtl_file, mesh):
- mtl_fileName = dir + mtl_file
- try:
- fileLines= open(mtl_fileName, 'r').readlines()
- except:
- print "unable to open", mtl_fileName
- return
+ # Remove ./
+ if mtl_file[:2] == './':
+ mtl_file= mtl_file[2:]
+
+ mtl_fileName = dir + mtl_file
+ try:
+ fileLines= open(mtl_fileName, 'r').readlines()
+ except:
+ print "unable to open", mtl_fileName
+ return
- lIdx=0
- while lIdx < len(fileLines):
- l = fileLines[lIdx].split()
+ lIdx=0
+ while lIdx < len(fileLines):
+ l = fileLines[lIdx].split()
- # Detect a line that will be ignored
- if len(l) == 0:
- pass
- elif l[0] == '#' or len(l) == 0:
- pass
- elif l[0] == 'newmtl':
- currentMat = getMat(' '.join(l[1:]))
- elif l[0] == 'Ka':
- currentMat.setMirCol(eval(l[1]), eval(l[2]), eval(l[3]))
- elif l[0] == 'Kd':
- currentMat.setRGBCol(eval(l[1]), eval(l[2]), eval(l[3]))
- elif l[0] == 'Ks':
- currentMat.setSpecCol(eval(l[1]), eval(l[2]), eval(l[3]))
- elif l[0] == 'Ns':
- currentMat.setHardness( int((eval(l[1])*0.51)) )
- elif l[0] == 'd':
- currentMat.setAlpha(eval(l[1]))
- elif l[0] == 'Tr':
- currentMat.setAlpha(eval(l[1]))
- elif l[0] == 'map_Ka':
- img_fileName = dir + l[1]
- load_mat_image(currentMat, img_fileName, 'Ka', mesh)
- elif l[0] == 'map_Ks':
- img_fileName = dir + l[1]
- load_mat_image(currentMat, img_fileName, 'Ks', mesh)
- elif l[0] == 'map_Kd':
- img_fileName = dir + l[1]
- load_mat_image(currentMat, img_fileName, 'Kd', mesh)
- lIdx+=1
+ # Detect a line that will be ignored
+ if len(l) == 0:
+ pass
+ elif l[0] == '#' or len(l) == 0:
+ pass
+ elif l[0] == 'newmtl':
+ currentMat = getMat(' '.join(l[1:]))
+ elif l[0] == 'Ka':
+ currentMat.setMirCol(eval(l[1]), eval(l[2]), eval(l[3]))
+ elif l[0] == 'Kd':
+ currentMat.setRGBCol(eval(l[1]), eval(l[2]), eval(l[3]))
+ elif l[0] == 'Ks':
+ currentMat.setSpecCol(eval(l[1]), eval(l[2]), eval(l[3]))
+ elif l[0] == 'Ns':
+ currentMat.setHardness( int((eval(l[1])*0.51)) )
+ elif l[0] == 'd':
+ currentMat.setAlpha(eval(l[1]))
+ elif l[0] == 'Tr':
+ currentMat.setAlpha(eval(l[1]))
+ elif l[0] == 'map_Ka':
+ img_fileName = dir + l[1]
+ load_mat_image(currentMat, img_fileName, 'Ka', mesh)
+ elif l[0] == 'map_Ks':
+ img_fileName = dir + l[1]
+ load_mat_image(currentMat, img_fileName, 'Ks', mesh)
+ elif l[0] == 'map_Kd':
+ img_fileName = dir + l[1]
+ load_mat_image(currentMat, img_fileName, 'Kd', mesh)
+ lIdx+=1
#==================================================================================#
# This loads data from .obj file #
#==================================================================================#
def load_obj(file):
- 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
+ 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
-
- # Get the file name with no path or .obj
- fileName = stripName( stripPath(file) )
-
- mtl_fileName = ''
-
- DIR = pathName(file, 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.
- currentImg = NULL_IMG # Null image is a string, otherwise this should be set to an image object.
+
+ 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) )
+
+ mtl_fileName = ''
+
+ DIR = pathName(file, stripPath(file))
- smooth = 0
+ fileLines = open(file, 'r').readlines()
+
+ mesh = NMesh.GetRaw() # new empty mesh
+
+ objectName = 'mesh' # If we cant get one, use this
+
+ uvMapList = [(0,0)] # store tuple uv pairs here
+
+ # This dummy vert makes life a whole lot easier-
+ # pythons index system then aligns with objs, remove later
+ vertList = [NMesh.Vert(0, 0, 0)] # store tuple uv pairs here
+
+ # Here we store a boolean list of which verts are used or not
+ # no we know weather to add them to the current mesh
+ # This is an issue with global vertex indicies being translated to per mesh indicies
+ # like blenders, we start with a dummy just like the vert.
+ # -1 means unused, any other value refers to the local mesh index of the vert.
+ usedList = [-1]
+
+ nullMat = getMat(NULL_MAT)
+
+ currentMat = nullMat # Use this mat.
+ currentImg = NULL_IMG # Null image is a string, otherwise this should be set to an image object.
- # Main loop
- lIdx = 0
- while lIdx < len(fileLines):
- l = fileLines[lIdx].split()
-
- # 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:]:
- # OBJ files can have // or / to seperate vert/texVert/normal
- # this is a bit of a pain but we must deal with it.
- # Well try // first and if that has a len of 1 then we'll try /
- objVert = v.split('//', -1)
- if len(objVert) == 1:
- objVert = objVert[0].split('/', -1)
-
- # 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]])
- # SMOTH FACE
- f.smooth = smooth
- # 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
- # Apply the current image to the face
- if currentImg != NULL_IMG:
- mesh.faces[-1].image = currentImg
+ # Main loop
+ lIdx = 0
+ while lIdx < len(fileLines):
+ l = fileLines[lIdx].split()
+
+ # 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
+ vertList.append( NMesh.Vert(eval(l[1]), eval(l[2]), eval(l[3]) ) )
+ usedList.append(-1) # Ad the moment this vert is not used by any mesh.
+
+ 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 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]])
- # SMOTH FACE
- f.smooth = smooth
- # 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
- # Apply the current image to the face
- if currentImg != NULL_IMG:
- mesh.faces[-1].image = currentImg
-
-
- # is o the only vert/face delimeter?
- # if not we could be screwed.
- elif l[0] == 'o':
- # Some material stuff
- if mtl_fileName != '':
- load_mtl(DIR, mtl_fileName, mesh)
+ 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
+ # Start with a dummy objects so python accepts OBJs 1 is the first index.
+ vIdxLs = []
+ vtIdxLs = []
+ fHasUV = len(uvMapList)-1 # Assume the face has a UV until it sho it dosent, if there are no UV coords then this will start as 0.
+ for v in l[1:]:
+ # OBJ files can have // or / to seperate vert/texVert/normal
+ # this is a bit of a pain but we must deal with it.
+ objVert = v.split('/', -1)
- # 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 = []
-
- # setting smooth surface on or off
- elif l[0] == 's':
- if l[1] == 'off':
- smooth = 0
- else:
- smooth = 1
-
- elif l[0] == 'usemtl':
- if l[1] == '(null)':
- currentMat = getMat(NULL_MAT)
- else:
- currentMat = getMat(' '.join(l[1:])) # Use join in case of spaces
+ # Vert Index - OBJ supports negative index assignment (like python)
+
+ vIdxLs.append(eval(objVert[0]))
+ if fHasUV:
+ # UV
+ if len(objVert) == 1:
+ vtIdxLs.append(eval(objVert[0])) # Sticky UV coords
+ elif objVert[1] != '': # Its possible that theres no texture vert just he vert and normal eg 1//2
+ vtIdxLs.append(eval(objVert[1])) # Seperate UV coords
+ else:
+ fHasUV = 0
+
+ # Dont add a UV to the face if its larger then the UV coord list
+ # The OBJ file would have to be corrupt or badly written for thi to happen
+ # but account for it anyway.
+ if vtIdxLs[-1] > len(uvMapList):
+ fHasUV = 0
+ print 'badly written OBJ file, invalid references to UV Texture coordinates.'
+
+ # Quads only, we could import quads using the method below but it polite to import a quad as a quad.
+ if len(vIdxLs) == 4:
+ for i in [0,1,2,3]:
+ if usedList[vIdxLs[i]] == -1:
+ mesh.verts.append(vertList[vIdxLs[i]])
+ f.v.append(mesh.verts[-1])
+ usedList[vIdxLs[i]] = len(mesh.verts)-1
+ else:
+ f.v.append(mesh.verts[usedList[vIdxLs[i]]])
+
+ # UV MAPPING
+ if fHasUV:
+ for i in [0,1,2,3]:
+ f.uv.append( uvMapList[ vtIdxLs[i] ] )
+ mesh.faces.append(f) # move the face onto the mesh
+ # Apply the current image to the face
+ if currentImg != NULL_IMG:
+ mesh.faces[-1].image = currentImg
+
+ 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)
+
+ if usedList[vIdxLs[0]] == -1:
+ mesh.verts.append(vertList[vIdxLs[0]])
+ f.v.append(mesh.verts[-1])
+ usedList[vIdxLs[0]] = len(mesh.verts)-1
+ else:
+ f.v.append(mesh.verts[usedList[vIdxLs[0]]])
+
+ if usedList[vIdxLs[i+1]] == -1:
+ mesh.verts.append(vertList[vIdxLs[i+1]])
+ f.v.append(mesh.verts[-1])
+ usedList[vIdxLs[i+1]] = len(mesh.verts)-1
+ else:
+ f.v.append(mesh.verts[usedList[vIdxLs[i+1]]])
+
+ if usedList[vIdxLs[i+2]] == -1:
+ mesh.verts.append(vertList[vIdxLs[i+2]])
+ f.v.append(mesh.verts[-1])
+ usedList[vIdxLs[i+2]] = len(mesh.verts)-1
+ else:
+ f.v.append(mesh.verts[usedList[vIdxLs[i+2]]])
+
+ # UV MAPPING
+ if fHasUV:
+ f.uv.append( uvMapList[ vtIdxLs[0] ] )
+ f.uv.append( uvMapList[ vtIdxLs[i+1] ] )
+ f.uv.append( uvMapList[ vtIdxLs[i+2] ] )
+ mesh.faces.append(f) # move the face onto the mesh
+
+ # Apply the current image to the face
+ if currentImg != NULL_IMG:
+ mesh.faces[-1].image = currentImg
+
+ # Object / Group
+ elif l[0] == 'o' or l[0] == 'g':
+
+ # Reset the used list
+ ulIdx = 0
+ while ulIdx < len(usedList):
+ usedList[ulIdx] = -1
+ ulIdx +=1
+
+ # Some material stuff
+ if mtl_fileName != '':
+ load_mtl(DIR, mtl_fileName, mesh)
+
+ # Make sure the objects is worth putting
+ if len(mesh.verts) > 1:
+ mesh.verts.remove(mesh.verts[0])
+ ob = NMesh.PutRaw(mesh, fileName + '_' + objectName)
+ if ob != None: # Name the object too.
+ ob.name = fileName + '_' + objectName
- elif l[0] == 'usemat':
- if l[1] == '(null)':
- currentImg = NULL_IMG
- else:
- currentImg = getImg(DIR + ' '.join(l[1:])) # Use join in case of spaces
-
-
- elif l[0] == 'mtllib':
- mtl_fileName = l[1]
-
- lIdx+=1
+ # Make new mesh
+ mesh = NMesh.GetRaw()
+ # This dummy vert makes life a whole lot easier-
+ # pythons index system then aligns with objs, remove later
+ mesh.verts.append( NMesh.Vert(0, 0, 0) )
+
+ # New mesh name
+ objectName = '_'.join(l[1:]) # Use join in case of spaces
+
+
+ elif l[0] == 'usemtl':
+ if l[1] == '(null)':
+ currentMat = getMat(NULL_MAT)
+ else:
+ currentMat = getMat(' '.join(l[1:])) # Use join in case of spaces
+
+ elif l[0] == 'usemat':
+ if l[1] == '(null)':
+ currentImg = NULL_IMG
+ else:
+ currentImg = getImg(DIR + ' '.join(l[1:])) # Use join in case of spaces
+
+
+ elif l[0] == 'mtllib':
+ mtl_fileName = l[1]
+
+ lIdx+=1
- # Some material stuff
- if mtl_fileName != '':
- load_mtl(DIR, mtl_fileName, mesh)
-
- # 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)
+ # Some material stuff
+ if mtl_fileName != '':
+ load_mtl(DIR, mtl_fileName, mesh)
+
+ # We need to do this to put the last object.
+ # All other objects will be put alredy
+ if len(mesh.verts) > 1:
+ mesh.verts.remove(mesh.verts[0])
+ ob = NMesh.PutRaw(mesh, fileName + '_' + objectName)
+ if ob != None: # Name the object too.
+ ob.name = fileName + '_' + objectName
-Window.FileSelector(load_obj, 'Import OBJ')
+Window.FileSelector(load_obj, 'Import Wavefront OBJ')
diff --git a/release/scripts/paths_import.py b/release/scripts/paths_import.py
new file mode 100644
index 00000000000..89535e2b872
--- /dev/null
+++ b/release/scripts/paths_import.py
@@ -0,0 +1,35 @@
+#!BPY
+
+"""
+Name: 'Paths (.svg, .ps, .eps, .ai, Gimp)'
+Blender: 233
+Group: 'Import'
+Submenu: 'Gimp 1.0 - 1.2.5' Gimp_1_0
+Submenu: 'Gimp 2.0' Gimp_2_0
+Submenu: 'Illustrator (.ai) PS-Adobe-2.0' AI
+Submenu: 'InkScape (.svg)' SVG
+Submenu: 'Postscript (.eps/.ps) PS-Adobe-2.0' EPS
+Tip: 'Import a path from any of a set of formats (still experimental)'
+"""
+
+import Blender
+
+argv=__script__['arg']
+
+if argv=='SVG':
+ from mod_svg2obj import *
+
+elif argv=='AI':
+ from mod_ai2obj import *
+
+elif argv=='EPS':
+ from mod_eps2obj import *
+
+elif argv=='Gimp_1_0':
+ from mod_gimp2obj import *
+
+elif argv=='Gimp_2_0':
+ from mod_svg2obj import *
+
+text = 'Import %s' % argv
+Blender.Window.FileSelector (fonctionSELECT, text)
diff --git a/release/scripts/skin.py b/release/scripts/skin.py
new file mode 100644
index 00000000000..77792c1326b
--- /dev/null
+++ b/release/scripts/skin.py
@@ -0,0 +1,558 @@
+#!BPY
+
+"""
+Name: 'Skin Two Vert-loops / Loft Multiple'
+Blender: 234
+Group: 'Mesh'
+Submenu: 'Loft-loop - shortest edge method' A1
+Submenu: 'Loft-loop - even method' A2
+Submenu: 'Loft-segment - shortest edge' B1
+Submenu: 'Loft-segment - even method' B2
+Tooltip: 'Select 2 or more vert loops, then run this script'
+"""
+
+# $Id$
+#
+# --------------------------------------------------------------------------
+# Skin Selected edges 1.0 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 *****
+# --------------------------------------------------------------------------
+
+
+
+# Made by Ideasman/Campbell 2004/04/25 - ideasman@linuxmail.org
+
+import Blender
+from Blender import *
+import math
+from math import *
+arg = __script__['arg']
+
+
+#================#
+# Math functions #
+#================#
+
+# Measure 2 points
+def measure(v1, v2):
+ return Mathutils.Vector([v1[0]-v2[0], v1[1] - v2[1], v1[2] - v2[2]]).length
+
+# Clamp
+def clamp(max, number):
+ while number >= max:
+ number = number - max
+ return number
+
+#=============================================================#
+# List func that takes the last item and adds it to the front #
+#=============================================================#
+def listRotate(ls):
+ return [ls[-1]] + ls[:-1]
+
+#=================================================================#
+# Recieve a list of locs: [x,y,z] and return the average location #
+#=================================================================#
+def averageLocation(locList):
+ avLoc = [0,0,0]
+
+ # Loop through x/y/z
+ for coordIdx in [0,1,2]:
+
+ # Add all the values from 1 of the 3 coords at the avLoc.
+ for loc in locList:
+ avLoc[coordIdx] += loc[coordIdx]
+
+ avLoc[coordIdx] = avLoc[coordIdx] / len(locList)
+ return avLoc
+
+
+
+#=============================#
+# Blender functions/shortcuts #
+#=============================#
+def error(str):
+ Draw.PupMenu('ERROR%t|'+str)
+
+# Returns a new face that has the same properties as the origional face
+# With no verts though
+def copyFace(face):
+ newFace = NMesh.Face()
+ # Copy some generic properties
+ newFace.mode = face.mode
+ if face.image != None:
+ newFace.image = face.image
+ newFace.flag = face.flag
+ newFace.mat = face.mat
+ newFace.smooth = face.smooth
+ return newFace
+
+#=============================================#
+# Find a selected vert that 2 faces share. #
+#=============================================#
+def selVertBetween2Faces(face1, face2):
+ for v1 in face1.v:
+ if v1.sel:
+ for v2 in face2.v:
+ if v1 == v2:
+ return v1
+
+
+#=======================================================#
+# Measure the total distance between all the edges in #
+# 2 vertex loops #
+#=======================================================#
+def measureVloop(mesh, v1loop, v2loop, surplusFaces):
+ totalDist = 0
+
+ # Rotate the vertloops to cycle through each pair.
+ # of faces to compate the distance between the 2 poins
+ for ii in range(len(v1loop)):
+ if ii not in surplusFaces:
+ V1 = selVertBetween2Faces(mesh.faces[v1loop[0]], mesh.faces[v1loop[1]])
+ V2 = selVertBetween2Faces(mesh.faces[v2loop[0]], mesh.faces[v2loop[1]])
+
+ P1 = (V1[0],V1[1],V1[2])
+ P2 = (V2[0],V2[1],V2[2])
+
+ totalDist += measure(P1,P2)
+ v1loop = listRotate(v1loop)
+ v2loop = listRotate(v2loop)
+
+ #selVertBetween2Faces(mesh.faces[v2loop[0]], mesh.faces[v2loop[1]])
+ return totalDist
+
+# Remove the shortest edge from a vert loop
+def removeSmallestFace(mesh, vloop):
+ bestDistSoFar = None
+ bestFIdxSoFar = None
+ for fIdx in vloop:
+ vSelLs = []
+ for v in mesh.faces[fIdx].v:
+ if v.sel:
+ vSelLs.append(v)
+
+ dist = measure(vSelLs[0].co, vSelLs[1].co)
+
+ if bestDistSoFar == None:
+ bestDistSoFar = dist
+ bestFIdxSoFar = fIdx
+ elif dist < bestDistSoFar:
+ bestDistSoFar = dist
+ bestFIdxSoFar = fIdx
+
+ # Return the smallest face index of the vloop that was sent
+ return bestFIdxSoFar
+
+
+#=============================================#
+# Take 2 vert loops and skin them #
+#=============================================#
+def skinVertLoops(mesh, v1loop, v2loop):
+
+
+ #=============================================#
+ # Handle uneven vert loops, this is tricky #
+ #=============================================#
+ # Reorder so v1loop is always the biggest
+ if len(v1loop) < len(v2loop):
+ v1loop, v2loop = v2loop, v1loop
+
+ # Work out if the vert loops are equel or not, if not remove the extra faces from the larger
+ surplusFaces = []
+ tempv1loop = eval(str(v1loop)) # strip faces off this one, use it to keep track of which we have taken faces from.
+ if len(v1loop) > len(v2loop):
+
+ # Even face method.
+ if arg[1] == '2':
+ remIdx = 0
+ faceStepping = len( v1loop) / len(v2loop)
+ while len(v1loop) - len(surplusFaces) > len(v2loop):
+ remIdx += faceStepping
+ surplusFaces.append(tempv1loop[ clamp(len(tempv1loop),remIdx) ])
+ tempv1loop.remove(surplusFaces[-1])
+
+ # Shortest face
+ elif arg[1] == '1':
+ while len(v1loop) - len(surplusFaces) > len(v2loop):
+ surplusFaces.append(removeSmallestFace(mesh, tempv1loop))
+ tempv1loop.remove(surplusFaces[-1])
+
+
+ tempv1loop = None
+
+ v2loop = optimizeLoopOrdedShortEdge(mesh, v1loop, v2loop, surplusFaces)
+
+ # make Faces from
+ lenVloop = len(v1loop)
+ lenSupFaces = len(surplusFaces)
+ fIdx = 0
+ offset = 0
+ while fIdx < lenVloop:
+
+ face = copyFace( mesh.faces[v1loop[clamp(lenVloop, fIdx+1)]] )
+
+ if v1loop[fIdx] in surplusFaces:
+ # Draw a try, this face does not catch with an edge.
+ # So we must draw a tri and wedge it in.
+
+ # Copy old faces properties
+
+ face.v.append( selVertBetween2Faces(\
+ mesh.faces[v1loop[clamp(lenVloop, fIdx)]],\
+ mesh.faces[v1loop[clamp(lenVloop, fIdx+1)]]) )
+
+ face.v.append( selVertBetween2Faces(\
+ mesh.faces[v1loop[clamp(lenVloop, fIdx+1)]],\
+ mesh.faces[v1loop[clamp(lenVloop, fIdx+2)]]) )
+
+ #face.v.append( selVertBetween2Faces(\
+ #mesh.faces[v2loop[clamp(lenVloop - lenSupFaces, (fIdx - offset +1 ))]],\
+ #mesh.faces[v2loop[clamp(lenVloop - lenSupFaces, (fIdx - offset + 2))]]) )
+
+ face.v.append( selVertBetween2Faces(\
+ mesh.faces[v2loop[clamp(lenVloop - lenSupFaces, (fIdx - offset))]],\
+ mesh.faces[v2loop[clamp(lenVloop - lenSupFaces, fIdx - offset + 1)]]) )
+
+ mesh.faces.append(face)
+
+ # We need offset to work out how much smaller v2loop is at this current index.
+ offset+=1
+
+
+ else:
+ # Draw a normal quad between the 2 edges/faces
+
+ face.v.append( selVertBetween2Faces(\
+ mesh.faces[v1loop[clamp(lenVloop, fIdx)]],\
+ mesh.faces[v1loop[clamp(lenVloop, fIdx+1)]]) )
+
+ face.v.append( selVertBetween2Faces(\
+ mesh.faces[v1loop[clamp(lenVloop, fIdx+1)]],\
+ mesh.faces[v1loop[clamp(lenVloop, fIdx+2)]]) )
+
+ face.v.append( selVertBetween2Faces(\
+ mesh.faces[v2loop[clamp(lenVloop - lenSupFaces, (fIdx - offset +1 ))]],\
+ mesh.faces[v2loop[clamp(lenVloop - lenSupFaces, (fIdx - offset + 2))]]) )
+
+ face.v.append( selVertBetween2Faces(\
+ mesh.faces[v2loop[clamp(lenVloop - lenSupFaces, (fIdx - offset))]],\
+ mesh.faces[v2loop[clamp(lenVloop - lenSupFaces, fIdx - offset + 1)]]) )
+
+ mesh.faces.append(face)
+
+ fIdx +=1
+
+ return mesh
+
+
+
+#=======================================================#
+# Takes a face and returns the number of selected verts #
+#=======================================================#
+def faceVSel(face):
+ vSel = 0
+ for v in face.v:
+ if v.sel:
+ vSel +=1
+ return vSel
+
+
+
+
+#================================================================#
+# This function takes a face and returns its selected vert loop #
+# it returns a list of face indicies
+#================================================================#
+def vertLoop(mesh, startFaceIdx, fIgLs): # fIgLs is a list of faces to ignore.
+ # Here we store the faces indicies that
+ # are a part of the first vertex loop
+ vertLoopLs = [startFaceIdx]
+
+ restart = 0
+ while restart == 0:
+ # this keeps the face loop going until its told to stop,
+ # If the face loop does not find an adjacent face then the vert loop has been compleated
+ restart = 1
+
+ # Get my selected verts for the active face/edge.
+ selVerts = []
+ for v in mesh.faces[vertLoopLs[-1]].v:
+ selVerts.append(v)
+
+ fIdx = 0
+ while fIdx < len(mesh.faces) and restart:
+ # Not already added to the vert list
+ if fIdx not in fIgLs + vertLoopLs:
+ # Has 2 verts selected
+ if faceVSel(mesh.faces[fIdx]) > 1:
+ # Now we need to find if any of the selected verts
+ # are shared with our active face. (are we next to ActiveFace)
+ for v in mesh.faces[fIdx].v:
+ if v in selVerts:
+ vertLoopLs.append(fIdx)
+ restart = 0 # restart the face loop.
+ break
+
+ fIdx +=1
+
+ return vertLoopLs
+
+
+
+
+#================================================================#
+# Now we work out the optimum order to 'skin' the 2 vert loops #
+# by measuring the total distance of all edges created, #
+# test this for every possible series of joins #
+# and find the shortest, Once this is done the #
+# shortest dist can be skinned. #
+# returns only the 2nd-reordered vert loop #
+#================================================================#
+def optimizeLoopOrded(mesh, v1loop, v2loop):
+ bestSoFar = None
+
+ # Measure the dist, ii is just a counter
+ for ii in range(len(v1loop)):
+
+ # Loop twice , Once for the forward test, and another for the revearsed
+ for iii in [0, 0]:
+ dist = measureVloop(mesh, v1loop, v2loop)
+ # Initialize the Best distance recorded
+ if bestSoFar == None:
+ bestSoFar = dist
+ bestv2Loop = eval(str(v2loop))
+
+ elif dist < bestSoFar: # Update the info if a better vloop rotation is found.
+ bestSoFar = dist
+ bestv2Loop = eval(str(v2loop))
+
+ # We might have got the vert loop backwards, try the other way
+ v2loop.reverse()
+ v2loop = listRotate(v2loop)
+ return bestv2Loop
+
+
+
+#================================================================#
+# Now we work out the optimum order to 'skin' the 2 vert loops #
+# by measuring the total distance of all edges created, #
+# test this for every possible series of joins #
+# and find the shortest, Once this is done the #
+# shortest dist can be skinned. #
+# returns only the 2nd-reordered vert loop #
+#================================================================#
+def optimizeLoopOrdedShortEdge(mesh, v1loop, v2loop, surplusFaces):
+ bestSoFar = None
+
+ # Measure the dist, ii is just a counter
+ for ii in range(len(v2loop)):
+
+ # Loop twice , Once for the forward test, and another for the revearsed
+ for iii in [0, 0]:
+ dist = measureVloop(mesh, v1loop, v2loop, surplusFaces)
+ print 'dist', dist
+ # Initialize the Best distance recorded
+ if bestSoFar == None:
+ bestSoFar = dist
+ bestv2Loop = eval(str(v2loop))
+
+ elif dist < bestSoFar: # Update the info if a better vloop rotation is found.
+ bestSoFar = dist
+ bestv2Loop = eval(str(v2loop))
+
+ # We might have got the vert loop backwards, try the other way
+ v2loop.reverse()
+ v2loop = listRotate(v2loop)
+ print 'best so far ', bestSoFar
+ return bestv2Loop
+
+
+
+
+
+
+#==============================#
+# Find our vert loop list #
+#==============================#
+# Find a face with 2 verts selected,
+#this will be the first face in out vert loop
+def findVertLoop(mesh, fIgLs): # fIgLs is a list of faces to ignore.
+
+ startFaceIdx = None
+
+ fIdx = 0
+ while fIdx < len(mesh.faces):
+ if fIdx not in fIgLs:
+ # Do we have an edge?
+ if faceVSel(mesh.faces[fIdx]) > 1:
+ # THIS IS THE STARTING FACE.
+ startFaceIdx = fIdx
+ break
+ fIdx+=1
+
+ # Here we access the function that generates the real vert loop
+ if startFaceIdx != None:
+ return vertLoop(mesh, startFaceIdx, fIgLs)
+ else:
+ # We are out'a vert loops, return a None,
+ return None
+
+#===================================#
+# Get the average loc of a vertloop #
+# This is used when working out the #
+# order to loft an object #
+#===================================#
+def vLoopAverageLoc(mesh, vertLoop):
+ locList = [] # List of vert locations
+
+ fIdx = 0
+ while fIdx < len(mesh.faces):
+ if fIdx in vertLoop:
+ for v in mesh.faces[fIdx].v:
+ if v.sel:
+ locList.append(v.co)
+ fIdx+=1
+
+ return averageLocation(locList)
+
+
+
+#=================================================#
+# Vert loop group functions
+
+def getAllVertLoops(mesh):
+ # Make a chain of vert loops.
+ fIgLs = [] # List of faces to ignore
+ allVLoops = [findVertLoop(mesh, fIgLs)]
+ while allVLoops[-1] != None:
+
+ # In future ignore all faces in this vert loop
+ fIgLs += allVLoops[-1]
+
+ # Add the new vert loop to the list
+ allVLoops.append( findVertLoop(mesh, fIgLs) )
+
+ return allVLoops[:-1] # Remove the last Value- None.
+
+
+def reorderCircularVLoops(mesh, allVLoops):
+ # Now get a location for each vert loop.
+ allVertLoopLocs = []
+ for vLoop in allVLoops:
+ allVertLoopLocs.append( vLoopAverageLoc(mesh, vLoop) )
+
+ # We need to find the longest distance between 2 vert loops so we can
+ reorderedVLoopLocs = []
+
+ # Start with this one, then find the next closest.
+ # in doing this make a new list called reorderedVloop
+ currentVLoop = 0
+ reorderedVloopIdx = [currentVLoop]
+ newOrderVLoops = [allVLoops[0]] # This is a re-ordered allVLoops
+ while len(reorderedVloopIdx) != len(allVLoops):
+ bestSoFar = None
+ bestVIdxSoFar = None
+ for vLoopIdx in range(len(allVLoops)):
+ if vLoopIdx not in reorderedVloopIdx + [currentVLoop]:
+ if bestSoFar == None:
+ bestSoFar = measure( allVertLoopLocs[vLoopIdx], allVertLoopLocs[currentVLoop] )
+ bestVIdxSoFar = vLoopIdx
+ else:
+ newDist = measure( allVertLoopLocs[vLoopIdx], allVertLoopLocs[currentVLoop] )
+ if newDist < bestSoFar:
+ bestSoFar = newDist
+ bestVIdxSoFar = vLoopIdx
+
+ reorderedVloopIdx.append(bestVIdxSoFar)
+ reorderedVLoopLocs.append(allVertLoopLocs[bestVIdxSoFar])
+ newOrderVLoops.append( allVLoops[bestVIdxSoFar] )
+
+ # Start looking for the next best fit
+ currentVLoop = bestVIdxSoFar
+
+ # This is not the locicle place to put this but its convieneint.
+ # Here we find the 2 vert loops that are most far apart
+ # We use this to work out which 2 vert loops not to skin when making an open loft.
+ vLoopIdx = 0
+ # Longest measured so far - 0 dummy.
+ bestSoFar = 0
+ while vLoopIdx < len(reorderedVLoopLocs):
+
+
+ # Skin back to the start if needs be, becuase this is a crcular loft
+ toSkin2 = vLoopIdx + 1
+ if toSkin2 == len(reorderedVLoopLocs):
+ toSkin2 = 0
+
+
+ newDist = measure( reorderedVLoopLocs[vLoopIdx], reorderedVLoopLocs[toSkin2] )
+
+ if newDist >= bestSoFar:
+ bestSoFar = newDist
+ vLoopIdxNotToSkin = vLoopIdx + 1
+
+ vLoopIdx +=1
+
+ return newOrderVLoops, vLoopIdxNotToSkin
+
+
+is_editmode = Window.EditMode()
+if is_editmode: Window.EditMode(0)
+
+# Get a mesh and raise errors if we cant
+mesh = None
+if len(Object.GetSelected()) > 0:
+ if Object.GetSelected()[0].getType() == 'Mesh':
+ mesh = Object.GetSelected()[0].getData()
+ else:
+ error('please select a mesh')
+else:
+ error('no mesh object selected')
+
+
+if mesh != None:
+ allVLoops = getAllVertLoops(mesh)
+
+ # Re order the vert loops
+ allVLoops, vLoopIdxNotToSkin = reorderCircularVLoops(mesh, allVLoops)
+
+ vloopIdx = 0
+ while vloopIdx < len(allVLoops):
+ #print range(len(allVLoops) )
+ #print vloopIdx
+ #print allVLoops[vloopIdx]
+
+ # Skin back to the start if needs be, becuase this is a crcular loft
+ toSkin2 = vloopIdx + 1
+ if toSkin2 == len(allVLoops):
+ toSkin2 = 0
+
+ # Circular loft or not?
+ if arg[0] == 'B': # B for open
+ if vloopIdx != vLoopIdxNotToSkin:
+ mesh = skinVertLoops(mesh, allVLoops[vloopIdx], allVLoops[toSkin2])
+ elif arg[0] == 'A': # A for closed
+ mesh = skinVertLoops(mesh, allVLoops[vloopIdx], allVLoops[toSkin2])
+
+ vloopIdx +=1
+
+ mesh.update()
+
+if is_editmode: Window.EditMode(1)
diff --git a/release/scripts/tex2uvbaker.py b/release/scripts/tex2uvbaker.py
new file mode 100644
index 00000000000..45dbb2e5b11
--- /dev/null
+++ b/release/scripts/tex2uvbaker.py
@@ -0,0 +1,254 @@
+#!BPY
+
+""" Registration info for Blender menus:
+Name: 'Texture Baker'
+Blender: 233
+Group: 'UV'
+Tooltip: 'Procedural to uvmapped texture baker'
+"""
+
+#---------------------------------------------
+# Last release : 0.2.2 , 2004/08/01 , 22h13
+#---------------------------------------------
+#---------------------------------------------
+# (c) jm soler 07/2004 : 'Procedural Texture Baker'
+# Based on a Martin Theeth' Poirier's really
+# good idea :
+# it makes a rvk mesh with uv coords of the
+# original mesh.
+# released under Blender Artistic Licence
+#
+# 0.2.2 : if the uv mesh objet exists it used,
+# no creation of a new one. As the lamp and
+# the camera
+# 0.2.1 : This script automaticaly frame and shoot the
+# new uv mesh . The image file is saved ine the
+# /render folder.
+#
+#---------------------------------------------
+# On user-friendly side :
+#---------------------------------------------
+#- Tadje Vobovnik adds the Select Image Size Menu
+#
+#---------------------------------------------
+# Official Page :
+# http://jmsoler.free.fr/util/blenderfile/py/text2uvbaker.py
+# For problems and errors:
+# http://www.zoo-logique.org/3D.Blender/newsportal/thread.php?group=3D.Blender
+#---------------------------------------------
+
+import Blender
+from Blender import NMesh, Draw, Object, Scene, Camera
+
+FRAME = 100
+XYLIMIT = [0.0, 0.]
+OBJPOS = 100.0
+
+helpmsg = """
+Texture Baker:
+
+This script saves an uv texture layout of the chosen mesh, that can be used as
+an uv map for it. It is a way to export procedural textures from Blender as
+normal image textures that can be edited with a 2d image manipulation program
+or used with the mesh in games and other 3d applications.
+
+Basic instructions:
+- Enter face mode and define uv coordinates for your mesh;
+- Define its materials and textures and set "Map Input" coordinates to UV;
+- Run this script and check the console.
+"""
+
+def GET_newobject (TYPE):
+ SCENE = Blender.Scene.getCurrent()
+ OBJECT = Blender.Object.New(TYPE)
+ SCENE.link(OBJECT)
+ return OBJECT, SCENE
+
+def SAVE_image (rc, name, FRAME):
+ MYDIR = ''
+ RENDERDIR = rc.getRenderPath()
+ rc.setRenderPath(RENDERDIR + MYDIR)
+ print "Render folder:", RENDERDIR + MYDIR
+ IMAGETYPE = Blender.Scene.Render.PNG
+ rc.setImageType(IMAGETYPE)
+ NEWFRAME = FRAME
+ OLDEFRAME = rc.endFrame()
+ OLDSFRAME = rc.startFrame()
+ rc.startFrame(NEWFRAME)
+ rc.endFrame(NEWFRAME)
+ rc.renderAnim()
+
+ try:
+ import nt
+ os = nt
+
+ except:
+ import posix
+ os = posix
+
+ FILENAME = "%04d" % NEWFRAME
+ FILENAME = FILENAME.replace (' ', '0')
+ FILENAME = RENDERDIR + MYDIR + FILENAME + '.png'
+
+ try:
+ TRUE = os.stat(FILENAME)
+ newfname = RENDERDIR + MYDIR + name
+ if newfname.find('.png', -4) < 0: newfname += '.png'
+ os.rename(FILENAME, newfname)
+ print "Renamed to:", newfname
+
+ except:
+ pass
+
+ rc.endFrame(OLDEFRAME)
+ rc.startFrame(OLDSFRAME)
+ rc.setRenderPath(RENDERDIR)
+
+def SHOOT (XYlimit, frame, obj, name, FRAME):
+ try:
+ CAM = Blender.Object.Get('UVCAMERA')
+ Cam = CAM.getData()
+ SC = Blender.Scene.getCurrent()
+
+ except:
+ Cam = Blender.Camera.New()
+ Cam.name = 'UVCamera'
+ CAM, SC = GET_newobject('Camera')
+ CAM.link(Cam)
+ CAM.setName('UVCAMERA')
+ Cam.lens = 30
+ Cam.name = 'UVCamera'
+
+ CAM.setLocation(obj.getLocation())
+ CAM.LocX += XYlimit[0] / 2.0
+ CAM.LocY += XYlimit[1] / 2.0
+ CAM.LocZ += max (XYlimit[0], XYlimit[1])
+ CAM.setEuler (0.0, 0.0, 0.0)
+
+ try:
+ LAMP = Blender.Object.Get('Eclairage')
+ lampe = LAMP.getData()
+ SC = Blender.Scene.getCurrent()
+
+ except:
+ lampe = Blender.Lamp.New()
+ lampe.name = 'lumin'
+ LAMP, SC = GET_newobject('Lamp')
+ LAMP.link(lampe)
+ LAMP.setName('Eclairage')
+
+ LAMP.setLocation(obj.getLocation())
+ LAMP.LocX += XYlimit[0] / 2.0
+ LAMP.LocY += XYlimit[1] / 2.0
+ LAMP.LocZ += max (XYlimit[0], XYlimit[1])
+ LAMP.setEuler (0.0, 0.0, 0.0)
+ context = SC.getRenderingContext()
+ Camold = SC.getCurrentCamera()
+ SC.setCurrentCamera(CAM)
+ OLDy = context.imageSizeY()
+ OLDx = context.imageSizeX()
+ tres = Draw.PupMenu('TEXTURE OUT RESOLUTION : %t | 256 %x1 | 512 %x2 | 768 %x3 | 1024 %x4')
+
+ if (tres) == 1: res = 256
+
+ elif (tres) == 2: res = 512
+
+ elif (tres) == 3: res = 768
+
+ elif (tres) == 4: res = 1024
+
+ else: res = 512
+
+ context.imageSizeY(res)
+ context.imageSizeX(res)
+ SAVE_image (context, name, FRAME)
+ context.imageSizeY(OLDy)
+ context.imageSizeX(OLDx)
+ SC.setCurrentCamera(Camold)
+ Blender.Set ('curframe', frame)
+
+def Mesh2UVCoord ():
+ try:
+ MESH3D = Object.GetSelected()[0]
+
+ if MESH3D.getType() == 'Mesh':
+ MESH = MESH3D.getData()
+ MESH2 = Blender.NMesh.GetRaw()
+
+ for f in MESH.faces:
+ f1 = Blender.NMesh.Face()
+
+ for v in f.v:
+ v1 = Blender.NMesh.Vert (v.co[0], v.co[1], v.co[2])
+ MESH2.verts.append(v1)
+ f1.v.append(MESH2.verts[len(MESH2.verts) - 1])
+
+ MESH2.faces.append(f1)
+ f1.uv = f.uv[:]
+ f1.col = f.col[:]
+ f1.smooth = f.smooth
+ f1.mode = f.mode
+ f1.flag = f.flag
+ f1.mat = f.mat
+
+ MESH2.materials = MESH.materials[:]
+
+ try:
+ NewOBJECT=Blender.Object.Get('UVOBJECT')
+ CurSCENE=Blender.Scene.getCurrent()
+ except:
+ NewOBJECT, CurSCENE = GET_newobject('Mesh')
+
+ NewOBJECT.link(MESH2)
+
+ #NewOBJECT, CurSCENE = GET_newobject('Mesh')
+ #NewOBJECT.link(MESH2)
+
+ NewOBJECT.setLocation (OBJPOS, OBJPOS, 0.0)
+ NewOBJECT.setEuler (0.0, 0.0, 0.0)
+
+ MESH2.removeAllKeys()
+
+ MESH2.update()
+ MESH2.insertKey (1, 'absolute')
+ MESH2.update()
+
+ for f in MESH2.faces:
+ for v in f.v:
+ for n in [0, 1]:
+ v.co[n] = f.uv[f.v.index(v)][n]
+ exec "if v.co[%s] > XYLIMIT[%s]: XYLIMIT[%s] = v.co[%s]" % (n, n, n, n)
+
+ v.co[2] = 0.0
+
+ print XYLIMIT
+
+ MESH2.update()
+ MESH2.insertKey (FRAME, 'absolute')
+ MESH2.update()
+ imagename = 'uvtext'
+
+ name = "CHANGE IMAGE NAME ? %t | Replace it | No replace | Script help"
+ result = Draw.PupMenu(name)
+
+ if result == 1:
+ imagename = Draw.PupStrInput ('Image Name:', imagename, 32)
+
+ if result != 3:
+ SHOOT (XYLIMIT, FRAME, NewOBJECT, imagename, FRAME)
+ Blender.Redraw()
+ else:
+ Draw.PupMenu("Ready%t|Please check console for instructions")
+ print helpmsg
+
+ else:
+ name = "Error%t|Active object is not a mesh or has no UV coordinates"
+ result = Draw.PupMenu(name)
+ print 'problem : no object selected or not mesh'
+
+ except:
+ name = "Error%t|Active object is not a mesh or has no UV coordinates"
+ result = Draw.PupMenu(name)
+ print 'problem : no object selected or not mesh'
+
+Mesh2UVCoord()
diff --git a/release/windows/installer/00.blender.nsi b/release/windows/installer/00.blender.nsi
index 2ee972b97b9..86c3c1f8bc6 100644
--- a/release/windows/installer/00.blender.nsi
+++ b/release/windows/installer/00.blender.nsi
@@ -258,11 +258,13 @@ Section "Blender-VERSION (required)" SecCopyUI
File DISTDIR\.blender\scripts\ac3d_export.py
File DISTDIR\.blender\scripts\ac3d_import.py
File DISTDIR\.blender\scripts\Apply_def.py
+ File DISTDIR\.blender\scripts\Axiscopy.py
File DISTDIR\.blender\scripts\batch_name_edit.py
File DISTDIR\.blender\scripts\bevel_center.py
File DISTDIR\.blender\scripts\blender2cal3d.py
File DISTDIR\.blender\scripts\bvh_export.py
File DISTDIR\.blender\scripts\bvh_import.py
+ File DISTDIR\.blender\scripts\clean_mesh.py
File DISTDIR\.blender\scripts\DirectX8Exporter.py
File DISTDIR\.blender\scripts\DirectXExporter.py
File DISTDIR\.blender\scripts\disp_paint.py
@@ -282,8 +284,12 @@ Section "Blender-VERSION (required)" SecCopyUI
File DISTDIR\.blender\scripts\knife.py
File DISTDIR\.blender\scripts\lightwave_export.py
File DISTDIR\.blender\scripts\lightwave_import.py
+ File DISTDIR\.blender\scripts\mod_ai2obj.py
File DISTDIR\.blender\scripts\mod_blender.py
+ File DISTDIR\.blender\scripts\mod_eps2obj.py
+ File DISTDIR\.blender\scripts\mod_gimp2obj.py
File DISTDIR\.blender\scripts\mod_meshtools.py
+ File DISTDIR\.blender\scripts\mod_svg2obj.py
File DISTDIR\.blender\scripts\nendo_export.py
File DISTDIR\.blender\scripts\nendo_import.py
File DISTDIR\.blender\scripts\obdatacopier.py
@@ -291,6 +297,7 @@ Section "Blender-VERSION (required)" SecCopyUI
File DISTDIR\.blender\scripts\obj_import.py
File DISTDIR\.blender\scripts\off_export.py
File DISTDIR\.blender\scripts\off_import.py
+ File DISTDIR\.blender\scripts\paths_import.py
File DISTDIR\.blender\scripts\radiosity_export.py
File DISTDIR\.blender\scripts\radiosity_import.py
File DISTDIR\.blender\scripts\raw_export.py
@@ -298,6 +305,7 @@ Section "Blender-VERSION (required)" SecCopyUI
File DISTDIR\.blender\scripts\renameobjectbyblock.py
File DISTDIR\.blender\scripts\rvk1_torvk2.py
File DISTDIR\.blender\scripts\sel_same.py
+ File DISTDIR\.blender\scripts\skin.py
File DISTDIR\.blender\scripts\slp_import.py
File DISTDIR\.blender\scripts\sysinfo.py
File DISTDIR\.blender\scripts\truespace_export.py