- New script:
authorWillian Padovani Germano <wpgermano@gmail.com>
Tue, 15 Jun 2004 04:16:30 +0000 (04:16 +0000)
committerWillian Padovani Germano <wpgermano@gmail.com>
Tue, 15 Jun 2004 04:16:30 +0000 (04:16 +0000)
  Wim Van Hoydonck contributed the famous Knife script (put under Modifiers group) developed by Stefano Selleri and himself (thank to both!)
- Added helper function Blender.sys.makename, updated docs and script ac3d_export to use it (shall update other exporters too):
  this function is just a simple helper to format a filename as needed (change extension, strip dirname, it defaults to use G.sce as path).
- Added a test method: Blender.Scene.getScriptlinks(eventName):
  just testing, if this path proves useful other functions will be added and made general, for objects, etc.

release/scripts/ac3d_export.py
release/scripts/knife.py [new file with mode: 0644]
source/blender/python/api2_2x/Scene.c
source/blender/python/api2_2x/Sys.c
source/blender/python/api2_2x/doc/Sys.py

index d5b25486937bb439cf5c9e29c15fe1c7c3a4b13b..35880682afa2a0953d904b71c3d7d1e881daab9f 100644 (file)
@@ -2,7 +2,7 @@
 
 """ Registration info for Blender menus:
 Name: 'AC3D (.ac)...'
-Blender: 232
+Blender: 233
 Group: 'Export'
 Submenu: 'All meshes...' all
 Submenu: 'Only selected...' sel
@@ -13,8 +13,9 @@ Tip: 'Export to AC3D (.ac) format.'
 # $Id$
 #
 # --------------------------------------------------------------------------
-# AC3DExport version 2.32-1 Jan 21, 2004
-# Program versions: Blender 2.32+ and AC3Db files (means version 0xb)
+# AC3DExport version 2.34
+# Program versions: Blender 2.34 and AC3Db files (means version 0xb)
+# new: minor tweaks, exporter didn't change
 # --------------------------------------------------------------------------
 # ***** BEGIN GPL LICENSE BLOCK *****
 #
@@ -420,4 +421,5 @@ def fs_callback(filename):
 if __script__['arg'] == 'config':
   Draw.Register(gui, event, b_event)
 else:
-  Blender.Window.FileSelector(fs_callback, "Export AC3D")
+  fname = Blender.sys.makename(ext=".ac")
+  Blender.Window.FileSelector(fs_callback, "Export AC3D", fname)
diff --git a/release/scripts/knife.py b/release/scripts/knife.py
new file mode 100644 (file)
index 0000000..d1df100
--- /dev/null
@@ -0,0 +1,690 @@
+#!BPY
+
+"""
+Name: 'Blender Knife Tool'
+Blender: 232
+Group: 'Modifiers'
+Tooltip: 'Cut a mesh along a plane w/o creating doubles'
+"""
+
+# $Id$
+#
+###################################################################
+#                                                                 #
+# Blender Knife Tool                                              #
+#                                                                 #
+# v. 0.0.0 - 0.0.6 (C) December 2002 Stefano <S68> Selleri        #
+# v. 0.0.7 (C) March 2004 Wim Van Hoydonck                        #
+# v. 0.0.8 (C) March 2004 Wim Van Hoydonck & Stefano <S68> Selleri#
+#                                                                 #
+# Released under the Blender Artistic Licence (BAL)               #
+# See www.blender.org                                             #
+#                                                                 #
+# Works in Blender 2.32 and higher                                #
+#                                                                 #
+# this script can be found online at:                             #
+# http://users.pandora.be/tuinbels/scripts/knife-0.0.8.py         #
+# http://www.selleri.org/Blender                                  #
+#                                                                 #
+# email: tuinbels@hotmail.com                                     #
+#        selleri@det.unifi.it                                     #
+###################################################################
+# History                                                         #
+# V: 0.0.0 - 08-12-02 - The script starts to take shape, a        #
+#                       history is now deserved :)                #
+#    0.0.1 - 09-12-02 - The faces are correctly selected and      #
+#                       assigned to the relevant objects now the  #
+#                       hard (splitting) part...                  #
+#    0.0.2 - 14-12-02 - Still hacking on the splitting...         #
+#                       It works, but I have to de-globalize      #
+#                       the intersection coordinates              #
+#    0.0.3 - 15-12-02 - First Alpha version                       #
+#    0.0.4 - 17-12-02 - Upgraded accordingly to eeshlo tips       #
+#                       Use Matrices for coordinate transf.       #
+#                       Add a GUI                                 #
+#                       Make it Run on 2.23                       #
+#    0.0.5 - 17-12-02 - Eeshlo solved some problems....           #
+#                       Theeth too adviced me                     #
+#    0.0.6 - 18-12-02 - Better error messages                     #
+#    0.0.7 - 26-03-04 - Developer team doubles!                   #
+#                       This version is by Wim!                   #
+#                       Doesn't create doubles (AFAIK)            #
+#                     - Faster (for small meshes), global         #
+#                       coordinates of verts are calculated only  #
+#                       once                                      #
+#                     - Editing the CutPlane in editmode (move)   #
+#                       shouldn't cause problems anymore          #
+#                     - Menu button added to choose between the   #
+#                       different Edit Methods                    #
+#                     - If a mesh is cut twice at the same place, #
+#                       this gives errors :( (also happened in    #
+#                       previous versions)                        #
+#                     - Willian Padovani Germano solved           #
+#                       a problem, many thanks :)                 #
+#                     - Stefano Selleri made some good            #
+#                       suggestions, thanks :)                    #
+#    0.0.8 - 26-03-04 - General Interface rewrite (Stefano)       #
+#    0.0.8a- 31-03-04 - Added some error messages                 #
+#                     - Cut multiple meshes at once               #
+#                                                                 #
+###################################################################
+
+import Blender
+from Blender import *
+from Blender.sys import time
+from math import *
+
+Epsilon = 0.00001
+msg = ''
+RBmesh0 = Draw.Create(0)
+RBmesh1 = Draw.Create(0)
+RBmesh2 = Draw.Create(1)
+
+VERSION = '0.0.8'
+
+# see if time module is available
+#try:
+#      import time
+#      timport = 1
+#except:
+#      timport = 0
+
+
+BL_VERSION = Blender.Get('version')
+if (BL_VERSION<=223):
+       import Blender210
+
+#=================================#
+# Vector and matrix manipulations #
+#=================================#
+
+# vector addition
+def vecadd(a, b):
+       return [a[0] - b[0], a[1] - b[1], a[2] + b[2]]
+
+# vector substration
+def vecsub(a, b):
+       return [a[0] - b[0], a[1] - b[1], a[2] - b[2]]
+
+# vector crossproduct
+def veccross(x, y):
+       v = [0, 0, 0]
+       v[0] = x[1]*y[2] - x[2]*y[1]
+       v[1] = x[2]*y[0] - x[0]*y[2]
+       v[2] = x[0]*y[1] - x[1]*y[0]
+       return v
+
+# vector dotproduct
+def vecdot(x, y):
+       return x[0]*y[0] + x[1]*y[1] + x[2]*y[2]
+
+# vector length
+def length(v):
+       return sqrt(v[0]*v[0] + v[1]*v[1] + v[2]*v[2])
+
+# vector multiplied by constant s
+def vecmul(a, s):
+       return[a[0]*s, a[1]*s, a[2]*s]
+
+# vector divided by constant s
+def vecdiv(a, s):
+       if s!=0.0: s = 1.0/s
+       return vecmul(a, s)
+
+# matrix(4x3) vector multiplication
+def mulmatvec4x3(a, b):
+       # a is vector, b is matrix
+       r = [0, 0, 0]
+       r[0] = a[0]*b[0][0] + a[1]*b[1][0] + a[2]*b[2][0] + b[3][0]
+       r[1] = a[0]*b[0][1] + a[1]*b[1][1] + a[2]*b[2][1] + b[3][1]
+       r[2] = a[0]*b[0][2] + a[1]*b[1][2] + a[2]*b[2][2] + b[3][2]
+       return r
+
+# Normalization of a vector
+def Normalize(a):
+       lengte = length(a)
+       return vecdiv(a, lengte)
+
+# calculate normal from 3 verts
+def Normal(v0, v1, v2):
+       return veccross(vecsub(v0, v1),vecsub(v0, v2))
+
+#===========================#
+# Coordinatetransformations #
+#===========================#
+
+def GlobalPosition(P, Obj):
+
+       if (BL_VERSION<=223):
+               m = Obj.matrix
+       else:
+               m = Obj.getMatrix()
+
+       return mulmatvec4x3(P, m)
+
+def LocalPosition(P, Obj):
+
+       if (BL_VERSION<=223):
+               m = Blender210.getObject(Obj.name).inverseMatrix
+       else:
+               m = Obj.getInverseMatrix()
+
+       return mulmatvec4x3(P, m)
+
+#================#
+# Get Plane Data #
+#================#
+
+def PlaneData(Plane):
+       global msg
+       #
+       # Calculate: 
+       # - the normal of the plane, 
+       # - the offset of the plane wrt the global coordinate system
+       #   in the direction of the normal of the plane
+       # 
+       PlaneMesh   = NMesh.GetRawFromObject(Plane.name)
+
+       if (len(PlaneMesh.faces)>1):
+               msg =  "ERROR: Active object must be a single face plane"
+               return ((0,0,0),(0,0,0),1)
+       else:
+               if (len(PlaneMesh.verts)<3):
+                       msg = "ERROR: 3 vertices needed to define a plane"
+                       return ((0,0,0),(0,0,0),1)
+               else:
+                       v0 = GlobalPosition(PlaneMesh.faces[0].v[0].co, Plane)
+                       v1 = GlobalPosition(PlaneMesh.faces[0].v[1].co, Plane)
+                       v2 = GlobalPosition(PlaneMesh.faces[0].v[2].co, Plane)
+                       
+                       # the normal of the plane, calculated from the first 3 verts
+                       PNormal = Normalize(Normal(v0,v1,v2))
+
+                       # offset of the plane, using 1st vertex instead of Plane.getLocaction()
+                       POffset = vecdot(v0,PNormal)
+
+                       return PNormal, POffset, 0
+
+#====================================#
+# Position with respect to Cut Plane #
+#====================================#
+
+def Distance(P, N, d0):
+       #
+       # distance from a point to a plane
+       #
+       return vecdot(P, N) - d0
+
+def FacePosition(dist):
+       #
+       # position of a face wrt to the plane
+       #
+       np, nn, nz = 0, 0, 0
+
+       for d in dist:
+
+               # the distances are calculated in advance
+               if d > 0:
+                       np += 1
+               elif d < 0:
+                       nn += 1
+               else:
+                       nz += 1 
+
+       if np == 0:
+               return -1
+       if nn == 0:
+               return 1
+       return 0
+
+#==========================================#
+# Append existing faces / create new faces #
+#==========================================#
+
+def FaceAppend(me, fidx):
+       #
+       # append a face to a mesh based on a list of vertex-indices
+       #
+       nf = NMesh.Face()
+
+       for i in fidx:
+               nf.v.append(me.verts[i])
+       me.faces.append(nf)
+
+def FaceMake(me, vl):
+       #
+       # make one or two new faces based on a list of vertex-indices
+       #
+       idx = len(me.verts)
+
+       if len(vl) <= 4:
+               nf = NMesh.Face()
+               for i in range(len(vl)):
+                       nf.v.append(me.verts[vl[i]])
+               me.faces.append(nf)
+       else:
+               nf = NMesh.Face()
+               nf.v.append(me.verts[vl[0]])
+               nf.v.append(me.verts[vl[1]])
+               nf.v.append(me.verts[vl[2]])
+               nf.v.append(me.verts[vl[3]])
+               me.faces.append(nf)
+
+               nf = NMesh.Face()
+               nf.v.append(me.verts[vl[3]])
+               nf.v.append(me.verts[vl[4]])
+               nf.v.append(me.verts[vl[0]])
+               me.faces.append(nf)
+   
+#=====================================#
+# Generate vertex lists for new faces #
+#=====================================#
+
+def Split(Obj, MeshPos, MeshNeg, Vglob, Vidx, N, d0, newvidx, newvcoo, totverts, d):
+       #
+       # - calculate intersectionpoints of the plane with faces
+       # - see if this intersectionpoint already exists (look for vertices close to the new vertex)
+       # - if it does not yet exist, append a vertex to the mesh,
+       #   remember its index and location and append the index to the appropriate vertex-lists
+       # - if it does, use that vertex (and its index) to create the face
+       #
+       vp = []
+       vn = []
+
+       # distances of the verts wrt the plane are calculated in main part of script
+       
+       for i in range(len(d)):
+               # the previous vertex
+               dim1 = d[int(fmod(i-1,len(d)))]
+               Vim1 = Vglob[int(fmod(i-1,len(d)))]
+
+               if abs(d[i]) < Epsilon:
+                       # if the vertex lies in the cutplane                    
+                       vp.append(Vidx[i])
+                       vn.append(Vidx[i])
+               else:
+                       if abs(dim1) < Epsilon:
+                               # if the previous vertex lies in cutplane
+                               if d[i] > 0:
+                                       vp.append(Vidx[i])
+                               else:
+                                       vn.append(Vidx[i])
+                       else:
+                               if d[i]*dim1 > 0:
+                                       # if they are on the same side of the plane
+                                       if d[i] > 0:
+                                               vp.append(Vidx[i])
+                                       else:
+                                               vn.append(Vidx[i])
+                               else:
+                                       # the vertices are not on the same side of the plane, so we have an intersection
+
+                                       Den = vecdot(vecsub(Vglob[i],Vim1),N)
+
+                                       Vi = []    
+                                       Vi.append ( ((Vim1[0]*Vglob[i][1]-Vim1[1]*Vglob[i][0])*N[1]+(Vim1[0]*Vglob[i][2]-Vim1[2]*Vglob[i][0])*N[2]+(Vglob[i][0]-Vim1[0])*d0)/Den)
+                                       Vi.append ( ((Vim1[1]*Vglob[i][0]-Vim1[0]*Vglob[i][1])*N[0]+(Vim1[1]*Vglob[i][2]-Vim1[2]*Vglob[i][1])*N[2]+(Vglob[i][1]-Vim1[1])*d0)/Den)
+                                       Vi.append ( ((Vim1[2]*Vglob[i][0]-Vim1[0]*Vglob[i][2])*N[0]+(Vim1[2]*Vglob[i][1]-Vim1[1]*Vglob[i][2])*N[1]+(Vglob[i][2]-Vim1[2])*d0)/Den)
+
+                                       ViL = LocalPosition(Vi, Obj)
+
+                                       if newvidx == []: 
+                                               # if newvidx is empty (the first time Split is called), append a new vertex
+                                               # to the mesh and remember its vertex-index and location
+                                               ViLl = NMesh.Vert(ViL[0],ViL[1],ViL[2])
+
+                                               if MeshPos == MeshNeg:
+                                                       MeshPos.verts.append(ViLl)
+
+                                               else:
+                                                       MeshPos.verts.append(ViLl)
+                                                       MeshNeg.verts.append(ViLl)
+
+                                               nvidx = totverts
+                                               newvidx.append(nvidx)
+                                               newvcoo.append(ViL)
+
+                                               vp.append(nvidx)
+                                               vn.append(nvidx)
+                                       else:
+                                               # newvidx is not empty
+                                               dist1 = []
+                                               tlr = 0
+                                               for j in range(len(newvidx)): 
+                                                       # calculate the distance from the new vertex to the vertices
+                                                       # in the list with new vertices
+                                                       dist1.append(length(vecsub(ViL, newvcoo[j])))
+                                               for k in range(len(dist1)):
+                                                       if dist1[k] < Epsilon:
+                                                               # if distance is smaller than epsilon, use the other vertex
+                                                               # use newvidx[k] as vert
+                                                               vp.append(newvidx[k])
+                                                               vn.append(newvidx[k])
+                                                               break # get out of closest loop
+                                                       else:
+                                                               tlr += 1
+
+                                               if tlr == len(newvidx):
+                                                       nvidx = totverts + len(newvidx)
+                                                       ViLl = NMesh.Vert(ViL[0],ViL[1],ViL[2])
+
+                                                       if MeshPos == MeshNeg:
+                                                               MeshPos.verts.append(ViLl)
+
+                                                       else:
+                                                               MeshPos.verts.append(ViLl)
+                                                               MeshNeg.verts.append(ViLl)
+
+                                                       newvidx.append(nvidx)
+                                                       newvcoo.append(ViL)
+                                                       vp.append(nvidx)
+                                                       vn.append(nvidx)
+
+                                       if d[i] > 0:
+                                               vp.append(Vidx[i])
+                                       else:
+                                               vn.append(Vidx[i])
+  
+       return vp, vn, newvidx, newvcoo
+
+#===========#
+# Main part #
+#===========#
+
+def CutMesh():
+       global msg
+       global RBmesh0,RBmesh1,RBmesh2
+       #if timport == 1:
+       #       start = time.clock()
+       start = time()
+       
+       selected_obs = Object.GetSelected()
+
+       total = len(selected_obs)
+
+       NoErrors=0
+
+       meshes = 0
+
+       # check to see if every selected object is a mesh
+       for ob in selected_obs:
+               type = ob.getType()
+               if type == 'Mesh':
+                       meshes += 1
+
+       # at least select two objects
+       if meshes <= 1:
+               msg = "ERROR: At least two objects should be selected"
+               NoErrors = 1
+
+       # if not every object is a mesh
+       if meshes != total:
+               msg = "ERROR: You should only select meshobjects"
+               NoErrors=1
+
+       # everything is ok
+       if NoErrors == 0:
+               Pln = selected_obs[0]
+               PNormal, POffset, NoErrors = PlaneData(Pln)
+
+       # loop to cut multiple meshes at once
+       for o in range(1, total):
+               
+               Obj = selected_obs[o]
+
+               if (NoErrors == 0) :
+               
+                       m = Obj.getData()
+
+                       if RBmesh1.val == 1:
+
+                               MeshNew = NMesh.GetRaw()
+
+                       if RBmesh2.val == 1:
+
+                               MeshPos = NMesh.GetRaw()
+                               MeshNeg = NMesh.GetRaw()
+
+                       # get the indices of the faces of the mesh
+                       idx = []
+                       for i in range(len(m.faces)):
+                               idx.append(i)
+
+                       # if idx is not reversed, this results in a list index out of range if
+                       # the original mesh is used (RBmesh1 == 0)
+                       idx.reverse()
+
+                       lenface, vertglob, vertidx, vertdist = [], [], [], []
+
+                       # total number of vertices
+                       totverts = len(m.verts)
+
+                       # for every face: calculate global coordinates of the vertices
+                       #                 append the vertex-index to a list
+                       #                 calculate distance of vertices to cutplane in advance
+
+                       for i in idx:
+                               fvertidx, Ve, dist = [], [], []
+                               fa = m.faces[i]
+                               lenface.append(len(fa))
+                               for v in fa.v:
+                                       globpos = GlobalPosition(v.co, Obj)
+                                       Ve.append(globpos)
+                                       fvertidx.append(v.index)
+                                       dist.append(Distance(globpos, PNormal, POffset))
+                               vertidx.append(fvertidx)
+                               vertglob.append(Ve)
+                               vertdist.append(dist)
+
+
+                       # append the verts of the original mesh to the new mesh
+                       if RBmesh1.val == 1:
+                               for v in m.verts:
+                                       MeshNew.verts.append(v)
+       
+                       if RBmesh2.val == 1:
+                               idx2 = []
+                               dist2 = []
+                               for v in m.verts:
+                                       MeshPos.verts.append(v)
+                                       MeshNeg.verts.append(v)
+                                       idx2.append(v.index)
+                                       dist2.append(Distance(GlobalPosition(v.co, Obj), PNormal, POffset))
+
+                       # remove all faces of m if the original object has to be used
+
+                       if RBmesh0.val == 1:
+                               m.faces = []
+
+                       newvidx, newvcoo = [], []
+                       testidxpos, testidxneg = [], []
+
+                       # what its all about...
+                       for i in idx:
+                               fp = FacePosition(vertdist[i])
+
+                               # no intersection
+                               if fp > 0:
+                                       if RBmesh0.val == 1:
+                                               FaceAppend(m, vertidx[i])
+                       
+                                       elif RBmesh1.val == 1:
+                                               FaceAppend(MeshNew, vertidx[i])
+                               
+                                       elif RBmesh2.val == 1:
+                                               FaceAppend(MeshPos, vertidx[i])
+
+                                               if testidxpos == []:
+                                                       testidxpos = vertidx[i]
+                               elif fp < 0:
+                                       if RBmesh0.val == 1:
+                                               FaceAppend(m, vertidx[i])
+                                       elif RBmesh1.val == 1:
+                                               FaceAppend(MeshNew, vertidx[i])
+                                       
+                                       elif RBmesh2.val == 1:
+                                               FaceAppend(MeshNeg, vertidx[i])
+
+                                               if testidxneg == []:
+                                                       testidxneg = vertidx[i]
+
+                               # intersected faces
+                               else:
+                                       # make new mesh
+                                       if RBmesh1.val == 1:
+                                               vlp, vln, newvidx, newvcoo = Split(Obj, MeshNew, MeshNew, vertglob[i], vertidx[i], PNormal, POffset, newvidx, newvcoo, totverts, vertdist[i])
+
+                                               if vlp != 0 and vln != 0:
+                                                       FaceMake(MeshNew, vlp)
+                                                       FaceMake(MeshNew, vln)
+                                               # two new meshes
+                                       elif RBmesh2.val == 1:
+                                               vlp, vln, newvidx, newvcoo = Split(Obj, MeshPos, MeshNeg, vertglob[i], vertidx[i], PNormal, POffset, newvidx, newvcoo, totverts, vertdist[i])
+       
+                                               if vlp != 0 and vln != 0:
+                                                       FaceMake(MeshPos, vlp)
+                                                       FaceMake(MeshNeg, vln)
+
+                                       # use old mesh
+                                       elif RBmesh0.val == 1:
+       
+                                               vlp, vln, newvidx, newvcoo = Split(Obj, m, m, vertglob[i], vertidx[i], PNormal, POffset, newvidx, newvcoo, totverts, vertdist[i])
+       
+                                               if vlp != 0 and vln != 0:
+                                                       FaceMake(m, vlp)
+                                                       FaceMake(m, vln)
+
+                       if RBmesh1.val == 1:
+
+                               ObOne = NMesh.PutRaw(MeshNew)
+
+                               ObOne.LocX, ObOne.LocY, ObOne.LocZ = Obj.LocX, Obj.LocY, Obj.LocZ
+                               ObOne.RotX, ObOne.RotY, ObOne.RotZ = Obj.RotX, Obj.RotY, Obj.RotZ
+                               ObOne.SizeX, ObOne.SizeY, ObOne.SizeZ = Obj.SizeX, Obj.SizeY, Obj.SizeZ
+
+                       elif RBmesh2.val == 1:
+
+                               # remove verts that do not belong to a face
+                               idx2.reverse()
+                               dist2.reverse()
+
+                               for i in range(len(idx2)):
+                                       if dist2[i] < 0:
+                                               v = MeshPos.verts[idx2[i]]
+                                               MeshPos.verts.remove(v)
+                                       if dist2[i] > 0:
+                                               v = MeshNeg.verts[idx2[i]]
+                                               MeshNeg.verts.remove(v)
+
+                               ObPos = NMesh.PutRaw(MeshPos)
+
+                               ObPos.LocX, ObPos.LocY, ObPos.LocZ = Obj.LocX, Obj.LocY, Obj.LocZ
+                               ObPos.RotX, ObPos.RotY, ObPos.RotZ = Obj.RotX, Obj.RotY, Obj.RotZ
+                               ObPos.SizeX, ObPos.SizeY, ObPos.SizeZ = Obj.SizeX, Obj.SizeY, Obj.SizeZ
+
+                               ObNeg = NMesh.PutRaw(MeshNeg)
+
+                               ObNeg.LocX, ObNeg.LocY, ObNeg.LocZ = Obj.LocX, Obj.LocY, Obj.LocZ
+                               ObNeg.RotX, ObNeg.RotY, ObNeg.RotZ = Obj.RotX, Obj.RotY, Obj.RotZ
+                               ObNeg.SizeX, ObNeg.SizeY, ObNeg.SizeZ = Obj.SizeX, Obj.SizeY, Obj.SizeZ
+
+                       elif RBmesh0.val == 1:
+                               m.update()
+
+
+       #if timport == 1:
+               #end = time.clock()
+               #total = end - start
+               #print "mesh(es) cut in", total, "seconds" 
+
+       end = time()
+       total = end - start
+       print "mesh(es) cut in", total, "seconds"
+
+#############################################################
+# Graphics                                                  #
+#############################################################
+def Warn():
+       BGL.glRasterPos2d(115, 23)
+        Blender.Window.Redraw(Blender.Window.Const.TEXT)
+
+def draw():
+       global msg
+       global RBmesh0,RBmesh1,RBmesh2
+       global VERSION
+       
+       BGL.glClearColor(0.5, 0.5, 0.5, 0.0)
+       BGL.glClear(BGL.GL_COLOR_BUFFER_BIT)
+       BGL.glColor3f(0, 0, 0)                  # Black
+       BGL.glRectf(2, 2, 482, 220)
+       BGL.glColor3f(0.48, 0.4, 0.57)          # Light Purple
+       BGL.glRectf(4, 179, 480, 210)
+       BGL.glRectf(4, 34, 480, 150)
+       BGL.glColor3f(0.3, 0.27, 0.35)          # Dark purple
+       BGL.glRectf(4, 151,480, 178)
+       BGL.glRectf(4, 4, 480, 33)
+       
+
+       BGL.glColor3f(1, 1, 1)
+       BGL.glRasterPos2d(8, 200)
+       Draw.Text("Blender Knife Tool -  V. 0.0.8a - 26 March 2004")
+       BGL.glRasterPos2d(8, 185)
+       Draw.Text("by Wim <tuinbels> Van Hoydonck & Stefano <S68> Selleri")
+       Draw.Button("Exit", 1, 430, 185, 40, 20)
+
+       RBmesh0 = Draw.Toggle("Edit Object",    10,10,157,153,18,RBmesh0.val, "The knife creates new vertices in the selected object.");
+       RBmesh1 = Draw.Toggle("New Object",     11,165,157,153,18,RBmesh1.val, "The knife duplicates the object and creates new vertices in the new object.");
+       RBmesh2 = Draw.Toggle("Two New Objects",12,320,157,153,18,RBmesh2.val, "The knife creates two new separate objects.");
+
+       BGL.glRasterPos2d(8, 128)
+       Draw.Text("1 - Draw a Mesh Plane defining the Cut Plane")
+       BGL.glRasterPos2d(8, 108)
+       Draw.Text("2 - Select the Meshes to be Cut and the Cut Plane")
+       BGL.glRasterPos2d(8, 88)
+       Draw.Text("      (Meshes Dark Purple, Plane Light Purple)")
+       BGL.glRasterPos2d(8, 68)
+       Draw.Text("3 - Choose the Edit Method (Radio Buttons above)")
+       BGL.glRasterPos2d(8, 48)
+       Draw.Text("4 - Push the 'CUT' button (below)")
+       #Create Buttons
+       Draw.Button("CUT", 4, 10, 10, 465, 18, "Cut the selected mesh along the plane")
+
+       
+       BGL.glRasterPos2d(10, 223)
+       BGL.glColor3f(1,0,0)
+       Draw.Text(msg)
+       msg = ''
+       
+def event(evt, val):
+       if evt == Draw.QKEY and not val:
+               Draw.Exit()
+       if evt == Draw.CKEY and not val:
+               CutMesh()
+               Draw.Redraw()
+
+def bevent(evt):
+       global RBmesh0,RBmesh1,RBmesh2
+
+       if evt == 1:
+               Draw.Exit()
+       elif evt == 4:
+               CutMesh()
+               Draw.Redraw()
+       elif evt == 10:
+               RBmesh0.val = 1
+               RBmesh1.val = 0
+               RBmesh2.val = 0
+               Draw.Redraw()
+       elif evt == 11:
+               RBmesh0.val = 0
+               RBmesh1.val = 1
+               RBmesh2.val = 0
+               Draw.Redraw()
+       elif evt == 12:
+               RBmesh0.val = 0
+               RBmesh1.val = 0
+               RBmesh2.val = 1
+               Draw.Redraw()
+
+Draw.Register(draw, event, bevent)
index 8fa1802fe2420e7435763d56cf2bac430bec722d..218610a67e5684323ad1b282768226809f7a7b1e 100644 (file)
@@ -37,6 +37,7 @@
 #include <BSE_headerbuttons.h> /* for copy_scene */
 #include <BIF_drawscene.h>              /* for set_scene */
 #include <BIF_space.h>                          /* for copy_view3d_lock() */
+#include <DNA_scriptlink_types.h>
 #include <MEM_guardedalloc.h>  /* for MEM_callocN */
 #include <mydevice.h>                                   /* for #define REDRAW */
 
@@ -97,6 +98,7 @@ static PyObject *Scene_getChildren(BPy_Scene *self);
 static PyObject *Scene_getCurrentCamera(BPy_Scene *self);
 static PyObject *Scene_setCurrentCamera(BPy_Scene *self, PyObject *args);
 static PyObject *Scene_getRenderingContext(BPy_Scene *self);
+static PyObject *Scene_getScriptlinks(BPy_Scene *self, PyObject *args);
 
 //deprecated methods
 static PyObject *Scene_currentFrame(BPy_Scene *self, PyObject *args);
@@ -140,6 +142,9 @@ static PyMethodDef BPy_Scene_methods[] = {
                                        "() - Return list of all objects linked to scene self"},
        {"getCurrentCamera", (PyCFunction)Scene_getCurrentCamera, METH_NOARGS,
                                        "() - Return current active Camera"},
+       {"getScriptlinks", (PyCFunction)Scene_getScriptlinks, METH_VARARGS,
+                                       "(eventname) - Get a list of this scene's scriptlinks (Text names) of the given type\n"
+       "(eventname) - string: FrameChanged, OnLoad or Redraw."},
        {"setCurrentCamera", (PyCFunction)Scene_setCurrentCamera, METH_VARARGS,
                                        "() - Set the currently active Camera"},
        //DEPRECATED
@@ -693,7 +698,7 @@ static PyObject *Scene_setCurrentCamera (BPy_Scene *self, PyObject *args)
 {
        Object *object;
        BPy_Object *cam_obj;
-       Scene  *scene = self->scene;
+       Scene *scene = self->scene;
 
        if (!scene)
                return EXPP_ReturnPyObjError (PyExc_RuntimeError,
@@ -725,6 +730,55 @@ static PyObject *Scene_getRenderingContext (BPy_Scene *self)
 
        return RenderData_CreatePyObject(self->scene);
 }
+
+/* Scene.getScriptlinks */
+static PyObject *Scene_getScriptlinks (BPy_Scene *self, PyObject *args)
+{
+       Scene *scene = self->scene;
+       char *eventname = NULL;
+       int event = 0;
+       ScriptLink *slink = &(scene)->scriptlink;
+
+       if (!scene)
+               return EXPP_ReturnPyObjError (PyExc_RuntimeError,
+                                               "Blender Scene was deleted!");
+
+       if (!PyArg_ParseTuple(args, "s", &eventname))
+               return EXPP_ReturnPyObjError (PyExc_TypeError,
+                                               "expected event name (string) as argument");
+
+       if (!strcmp(eventname, "FrameChanged"))
+               event = SCRIPT_FRAMECHANGED;
+       else if (!strcmp(eventname, "OnLoad"))
+               event = SCRIPT_ONLOAD;
+       else if (!strcmp(eventname, "Redraw"))
+               event = SCRIPT_REDRAW;
+       else
+               return EXPP_ReturnPyObjError (PyExc_AttributeError,
+                                               "unknown event");
+
+       /* actually !scriptlink shouldn't happen ... */
+       if (!slink || !slink->totscript) {
+               Py_INCREF(Py_None);
+               return Py_None;
+       }
+       else {
+               PyObject *list = PyList_New(0);
+               int i;
+
+               if (!list)
+                       return EXPP_ReturnPyObjError (PyExc_MemoryError,
+                               "couldn't create PyList!");
+
+               for (i = 0; i < slink->totscript; i++) {
+                       if ((slink->flag[i] == event) && slink->scripts[i])
+                               PyList_Append(list, PyString_FromString(slink->scripts[i]->name+2));
+               }
+
+               return list;
+       }
+}
+
 /*****************************************************************************/
 // DEPRECATED  
 /*****************************************************************************/
index 81488c2c67656da619c68b7c5e7a282deb8417dc..b2c133d688128237f03b6dd0f6f451558af7c94b 100644 (file)
@@ -42,6 +42,7 @@
 static PyObject *M_sys_basename (PyObject *self, PyObject *args);
 static PyObject *M_sys_dirname (PyObject *self, PyObject *args);
 static PyObject *M_sys_splitext (PyObject *self, PyObject *args);
+static PyObject *M_sys_makename (PyObject *self, PyObject *args, PyObject *kw);
 static PyObject *M_sys_exists (PyObject *self, PyObject *args);
 static PyObject *M_sys_time (PyObject *self);
 
@@ -69,6 +70,17 @@ static char M_sys_splitext_doc[] =
 /this/that/file.ext -> ('/this/that/file','.ext').\n\
 Return the pair (root, extension).";
 
+static char M_sys_makename_doc[] =
+"(path = Blender.Get('filename'), ext = \"\", strip = 0) -\n\
+Strip dir and extension from path, leaving only a name, then append 'ext'\n\
+to it (if given) and return the resulting string.\n\n\
+(path) - string: a pathname -- Blender.Get('filename') if 'path' isn't given;\n\
+(ext = \"\") - string: the extension to append.\n\
+(strip = 0) - int: strip dirname from 'path' if given and non-zero.\n\
+Ex: makename('/path/to/file/myfile.foo','-01.abc') returns 'myfile-01.abc'\n\
+Ex: makename(ext='.txt') returns 'untitled.txt' if Blender.Get('filename')\n\
+returns a path to the file 'untitled.blend'";
+
 static char M_sys_time_doc[] =
 "() - Return a float representing time elapsed in seconds.\n\
 Each successive call is garanteed to return values greater than or\n\
@@ -84,6 +96,8 @@ struct PyMethodDef M_sys_methods[] = {
   {"basename",    M_sys_basename,        METH_VARARGS, M_sys_basename_doc},
   {"dirname",     M_sys_dirname,         METH_VARARGS, M_sys_dirname_doc},
   {"splitext",    M_sys_splitext,        METH_VARARGS, M_sys_splitext_doc},
+  {"makename", (PyCFunction)M_sys_makename, METH_VARARGS|METH_KEYWORDS,
+               M_sys_makename_doc},
   {"exists",      M_sys_exists,          METH_VARARGS, M_sys_exists_doc},
   {"time", (PyCFunction)M_sys_time,      METH_NOARGS,  M_sys_time_doc},
   {NULL, NULL, 0, NULL}
@@ -145,7 +159,7 @@ static PyObject *M_sys_basename (PyObject *self, PyObject *args)
                        return EXPP_ReturnPyObjError(PyExc_RuntimeError, "path too long");
 
                strncpy(basename, p+1, n); /* + 1 to skip the sep */
-               basename[n] = 0;
+               basename[n] = '\0';
                return Py_BuildValue("s", basename);
        }
 
@@ -177,11 +191,11 @@ static PyObject *M_sys_dirname (PyObject *self, PyObject *args)
                        return EXPP_ReturnPyObjError (PyExc_RuntimeError, "path too long");
 
                strncpy(dirname, name, n);
-               dirname[n] = 0;
+               dirname[n] = '\0';
                return Py_BuildValue("s", dirname);
        }
 
-       return Py_BuildValue("s", "."); /* XXX need to fix this? (is crossplatform?)*/
+       return Py_BuildValue("s", ".");
 }
 
 static PyObject *M_sys_splitext (PyObject *self, PyObject *args)
@@ -220,13 +234,71 @@ static PyObject *M_sys_splitext (PyObject *self, PyObject *args)
                EXPP_ReturnPyObjError(PyExc_RuntimeError, "path too long");
 
        strncpy(ext, dot, n);
-       ext[n] = 0;
+       ext[n] = '\0';
        strncpy(path, name, dot - name);
-       path[dot - name] = 0;
+       path[dot - name] = '\0';
 
        return Py_BuildValue("ss", path, ext);
 }
 
+static PyObject *M_sys_makename(PyObject *self, PyObject *args, PyObject *kw)
+{
+       char *path = G.sce, *ext = NULL;
+       int strip = 0;
+       static char *kwlist[] = {"path", "ext", "strip", NULL};
+       char *dot = NULL, *p = NULL, basename[FILE_MAXFILE];
+       char sep;
+       int n, len, lenext = 0;
+       PyObject *c;
+
+       if (!PyArg_ParseTupleAndKeywords(args, kw, "|ssi", kwlist,
+                       &path, &ext, &strip))
+               return EXPP_ReturnPyObjError (PyExc_TypeError,
+                       "expected one or two strings and an int (or nothing) as arguments");
+
+       len = strlen(path);
+       if (ext) lenext = strlen(ext);
+
+       if ((len + lenext) > FILE_MAXFILE)
+               return EXPP_ReturnPyObjError(PyExc_RuntimeError, "path too long");
+
+       c = PyObject_GetAttrString (g_sysmodule, "dirsep");
+       sep = PyString_AsString(c)[0];
+       Py_DECREF(c);
+
+       p = strrchr(path, sep);
+
+       if (p && strip) {
+               n = path + len - p - 1; /* - 1 because we don't want the sep */
+
+               strncpy(basename, p+1, n); /* + 1 to skip the sep */
+               basename[n] = 0;
+       }
+       else {
+               strncpy(basename, path, len);
+               n = len;
+               basename[n] = '\0';
+       }
+
+       dot = strrchr(basename, '.');
+
+       /* now the extension: always remove the one in basename */
+       if (dot || ext) {
+               if (!ext)
+                       basename[dot - basename] = '\0';
+               else { /* if user gave an ext, append it */
+
+                       if (dot) n = dot - basename;
+                       else n = strlen(basename);
+
+                       strncpy(basename + n, ext, lenext);
+                       basename[n+lenext] = '\0';
+               }
+       }
+
+       return PyString_FromString(basename);
+}
+
 static PyObject *M_sys_time (PyObject *self)
 {
        double t = PIL_check_seconds_timer();
index 515bc6e3feef3aaac0c0f3c2839604a96b723929..d969fe545b44e123a295e9642917ae19ec08a6e6 100644 (file)
@@ -68,6 +68,35 @@ def splitext (path):
   @return: (root, ext)
   """
 
+def makename (path = "Blender.Get('filename')", ext = "", strip = 0):
+  """
+  Remove extension from 'path', append extension 'ext' (if given)
+  to the result and return it.  If 'strip' is non-zero, also remove
+  dirname from path.
+
+  Example::
+    import Blender
+    from Blender.sys import *
+    print makename('/path/to/myfile.txt','.abc', 1) # returns 'myfile.abc'
+
+    print makename('/path/to/myfile.obj', '-01.obj') # '/path/to/myfile-01.obj'
+
+    print makename('/path/to/myfile.txt', strip = 1) # 'myfile'
+
+    # note that:
+    print makename(ext = '.txt')
+    # is equivalent to:
+    print sys.splitext(Blender.Get('filename'))[0]) + '.txt'
+
+  @type path: string
+  @param path: a path name or Blender.Get('filename'), if not given.
+  @type ext: string
+  @param ext: an extension to append.  For flexibility, a dot ('.') is
+      not automatically included.
+  @rtype: string
+  @return: the resulting string
+  """
+
 def exists(path):
   """
   Tell if the given pathname (file or dir) exists.