use f.area where possible over python function and use len(mface) over len(mface.v)
[blender.git] / release / scripts / knife.py
1 #!BPY
2
3 """
4 Name: 'Knife Tool'
5 Blender: 232
6 Group: 'Object'
7 Tooltip: 'Cut selected mesh(es) along an active plane w/o creating doubles'
8 """
9
10 __author__ = ["Stefano <S68> Selleri", "Wim Van Hoydonck"]
11 __url__ = ("blender", "elysiun")
12 __version__ = "0.0.8a 03/31/04"
13
14 __bpydoc__ = """\
15 "Blender Knife Tool" uses the active mesh plane to cut all selected meshes.
16
17 Usage:
18
19 Create, resize and position a "cutting plane", which will be used to cut
20 the mesh(es), then:
21
22 - select mesh(es) to be cut;<br>
23 - select cutting plane (it will be the active object);<br>
24 - run this script from 3d View's "Object->Scripts" menu.
25
26 Options:
27
28 - edit object: knife creates new vertices in the selected mesh(es);<br>
29 - create new object: knife duplicates objects and creates new vertices in the
30 new objects;<br>
31 - create two new objects: knife creates two new separate objects.
32 """
33
34 # $Id$
35 #
36 ###################################################################
37 #                                                                 #
38 # Blender Knife Tool                                              #
39 #                                                                 #
40 # v. 0.0.0 - 0.0.6 (C) December 2002 Stefano <S68> Selleri        #
41 # v. 0.0.7 (C) March 2004 Wim Van Hoydonck                        #
42 # v. 0.0.8 (C) March 2004 Wim Van Hoydonck & Stefano <S68> Selleri#
43 #                                                                 #
44 # Released under the Blender Artistic Licence (BAL)               #
45 # See www.blender.org                                             #
46 #                                                                 #
47 # Works in Blender 2.32 and higher                                #
48 #                                                                 #
49 # this script can be found online at:                             #
50 # http://users.pandora.be/tuinbels/scripts/knife-0.0.8.py         #
51 # http://www.selleri.org/Blender                                  #
52 #                                                                 #
53 # email: tuinbels@hotmail.com                                     #
54 #        selleri@det.unifi.it                                     #
55 ###################################################################
56 # History                                                         #
57 # V: 0.0.0 - 08-12-02 - The script starts to take shape, a        #
58 #                       history is now deserved :)                #
59 #    0.0.1 - 09-12-02 - The faces are correctly selected and      #
60 #                       assigned to the relevant objects now the  #
61 #                       hard (splitting) part...                  #
62 #    0.0.2 - 14-12-02 - Still hacking on the splitting...         #
63 #                       It works, but I have to de-globalize      #
64 #                       the intersection coordinates              #
65 #    0.0.3 - 15-12-02 - First Alpha version                       #
66 #    0.0.4 - 17-12-02 - Upgraded accordingly to eeshlo tips       #
67 #                       Use Matrices for coordinate transf.       #
68 #                       Add a GUI                                 #
69 #                       Make it Run on 2.23                       #
70 #    0.0.5 - 17-12-02 - Eeshlo solved some problems....           #
71 #                       Theeth too adviced me                     #
72 #    0.0.6 - 18-12-02 - Better error messages                     #
73 #    0.0.7 - 26-03-04 - Developer team doubles!                   #
74 #                       This version is by Wim!                   #
75 #                       Doesn't create doubles (AFAIK)            #
76 #                     - Faster (for small meshes), global         #
77 #                       coordinates of verts are calculated only  #
78 #                       once                                      #
79 #                     - Editing the CutPlane in editmode (move)   #
80 #                       shouldn't cause problems anymore          #
81 #                     - Menu button added to choose between the   #
82 #                       different Edit Methods                    #
83 #                     - If a mesh is cut twice at the same place, #
84 #                       this gives errors :( (also happened in    #
85 #                       previous versions)                        #
86 #                     - Willian Padovani Germano solved           #
87 #                       a problem, many thanks :)                 #
88 #                     - Stefano Selleri made some good            #
89 #                       suggestions, thanks :)                    #
90 #    0.0.8 - 26-03-04 - General Interface rewrite (Stefano)       #
91 #    0.0.8a- 31-03-04 - Added some error messages                 #
92 #                     - Cut multiple meshes at once               #
93 #                                                                 #
94 ###################################################################
95
96 import Blender
97 from Blender import *
98 from Blender.sys import time
99 from math import *
100
101 Epsilon = 0.00001
102 msg = ''
103 RBmesh0 = Draw.Create(0)
104 RBmesh1 = Draw.Create(0)
105 RBmesh2 = Draw.Create(1)
106
107 VERSION = '0.0.8'
108
109 # see if time module is available
110 #try:
111 #       import time
112 #       timport = 1
113 #except:
114 #       timport = 0
115
116
117 BL_VERSION = Blender.Get('version')
118 if (BL_VERSION<=223):
119         import Blender210
120
121 #=================================#
122 # Vector and matrix manipulations #
123 #=================================#
124
125 # vector addition
126 def vecadd(a, b):
127         return [a[0] - b[0], a[1] - b[1], a[2] + b[2]]
128
129 # vector substration
130 def vecsub(a, b):
131         return [a[0] - b[0], a[1] - b[1], a[2] - b[2]]
132
133 # vector crossproduct
134 def veccross(x, y):
135         v = [0, 0, 0]
136         v[0] = x[1]*y[2] - x[2]*y[1]
137         v[1] = x[2]*y[0] - x[0]*y[2]
138         v[2] = x[0]*y[1] - x[1]*y[0]
139         return v
140
141 # vector dotproduct
142 def vecdot(x, y):
143         return x[0]*y[0] + x[1]*y[1] + x[2]*y[2]
144
145 # vector length
146 def length(v):
147         return sqrt(v[0]*v[0] + v[1]*v[1] + v[2]*v[2])
148
149 # vector multiplied by constant s
150 def vecmul(a, s):
151         return[a[0]*s, a[1]*s, a[2]*s]
152
153 # vector divided by constant s
154 def vecdiv(a, s):
155         if s!=0.0: s = 1.0/s
156         return vecmul(a, s)
157
158 # matrix(4x3) vector multiplication
159 def mulmatvec4x3(a, b):
160         # a is vector, b is matrix
161         r = [0, 0, 0]
162         r[0] = a[0]*b[0][0] + a[1]*b[1][0] + a[2]*b[2][0] + b[3][0]
163         r[1] = a[0]*b[0][1] + a[1]*b[1][1] + a[2]*b[2][1] + b[3][1]
164         r[2] = a[0]*b[0][2] + a[1]*b[1][2] + a[2]*b[2][2] + b[3][2]
165         return r
166
167 # Normalization of a vector
168 def Normalize(a):
169         lengte = length(a)
170         return vecdiv(a, lengte)
171
172 # calculate normal from 3 verts
173 def Normal(v0, v1, v2):
174         return veccross(vecsub(v0, v1),vecsub(v0, v2))
175
176 #===========================#
177 # Coordinatetransformations #
178 #===========================#
179
180 def GlobalPosition(P, Obj):
181
182         if (BL_VERSION<=223):
183                 m = Obj.matrix
184         else:
185                 m = Obj.getMatrix()
186
187         return mulmatvec4x3(P, m)
188
189 def LocalPosition(P, Obj):
190
191         if (BL_VERSION<=223):
192                 m = Blender210.getObject(Obj.name).inverseMatrix
193         else:
194                 m = Obj.getInverseMatrix()
195
196         return mulmatvec4x3(P, m)
197
198 #================#
199 # Get Plane Data #
200 #================#
201
202 def PlaneData(Plane):
203         global msg
204         #
205         # Calculate: 
206         # - the normal of the plane, 
207         # - the offset of the plane wrt the global coordinate system
208         #   in the direction of the normal of the plane
209         # 
210         PlaneMesh   = NMesh.GetRawFromObject(Plane.name)
211
212         if (len(PlaneMesh.faces)>1):
213                 msg =  "ERROR: Active object must be a single face plane"
214                 return ((0,0,0),(0,0,0),1)
215         else:
216                 if (len(PlaneMesh.verts)<3):
217                         msg = "ERROR: 3 vertices needed to define a plane"
218                         return ((0,0,0),(0,0,0),1)
219                 else:
220                         v0 = GlobalPosition(PlaneMesh.faces[0].v[0].co, Plane)
221                         v1 = GlobalPosition(PlaneMesh.faces[0].v[1].co, Plane)
222                         v2 = GlobalPosition(PlaneMesh.faces[0].v[2].co, Plane)
223                         
224                         # the normal of the plane, calculated from the first 3 verts
225                         PNormal = Normalize(Normal(v0,v1,v2))
226
227                         # offset of the plane, using 1st vertex instead of Plane.getLocaction()
228                         POffset = vecdot(v0,PNormal)
229
230                         return PNormal, POffset, 0
231
232 #====================================#
233 # Position with respect to Cut Plane #
234 #====================================#
235
236 def Distance(P, N, d0):
237         #
238         # distance from a point to a plane
239         #
240         return vecdot(P, N) - d0
241
242 def FacePosition(dist):
243         #
244         # position of a face wrt to the plane
245         #
246         np, nn, nz = 0, 0, 0
247
248         for d in dist:
249
250                 # the distances are calculated in advance
251                 if d > 0:
252                         np += 1
253                 elif d < 0:
254                         nn += 1
255                 else:
256                         nz += 1 
257
258         if np == 0:
259                 return -1
260         if nn == 0:
261                 return 1
262         return 0
263
264 #==========================================#
265 # Append existing faces / create new faces #
266 #==========================================#
267
268 def FaceAppend(me, fidx):
269         #
270         # append a face to a mesh based on a list of vertex-indices
271         #
272         nf = NMesh.Face()
273
274         for i in fidx:
275                 nf.v.append(me.verts[i])
276         me.faces.append(nf)
277
278 def FaceMake(me, vl):
279         #
280         # make one or two new faces based on a list of vertex-indices
281         #
282         idx = len(me.verts)
283
284         if len(vl) <= 4:
285                 nf = NMesh.Face()
286                 for i in range(len(vl)):
287                         nf.v.append(me.verts[vl[i]])
288                 me.faces.append(nf)
289         else:
290                 nf = NMesh.Face()
291                 nf.v.append(me.verts[vl[0]])
292                 nf.v.append(me.verts[vl[1]])
293                 nf.v.append(me.verts[vl[2]])
294                 nf.v.append(me.verts[vl[3]])
295                 me.faces.append(nf)
296
297                 nf = NMesh.Face()
298                 nf.v.append(me.verts[vl[3]])
299                 nf.v.append(me.verts[vl[4]])
300                 nf.v.append(me.verts[vl[0]])
301                 me.faces.append(nf)
302    
303 #=====================================#
304 # Generate vertex lists for new faces #
305 #=====================================#
306
307 def Split(Obj, MeshPos, MeshNeg, Vglob, Vidx, N, d0, newvidx, newvcoo, totverts, d):
308         #
309         # - calculate intersectionpoints of the plane with faces
310         # - see if this intersectionpoint already exists (look for vertices close to the new vertex)
311         # - if it does not yet exist, append a vertex to the mesh,
312         #   remember its index and location and append the index to the appropriate vertex-lists
313         # - if it does, use that vertex (and its index) to create the face
314         #
315  
316         vp = []
317         vn = []
318
319         # distances of the verts wrt the plane are calculated in main part of script
320         
321         for i in range(len(d)):
322                 # the previous vertex
323                 dim1 = d[int(fmod(i-1,len(d)))]
324                 Vim1 = Vglob[int(fmod(i-1,len(d)))]
325
326                 if abs(d[i]) < Epsilon:
327                         # if the vertex lies in the cutplane                    
328                         vp.append(Vidx[i])
329                         vn.append(Vidx[i])
330                 else:
331                         if abs(dim1) < Epsilon:
332                                 # if the previous vertex lies in cutplane
333                                 if d[i] > 0:
334                                         vp.append(Vidx[i])
335                                 else:
336                                         vn.append(Vidx[i])
337                         else:
338                                 if d[i]*dim1 > 0:
339                                         # if they are on the same side of the plane
340                                         if d[i] > 0:
341                                                 vp.append(Vidx[i])
342                                         else:
343                                                 vn.append(Vidx[i])
344                                 else:
345                                         # the vertices are not on the same side of the plane, so we have an intersection
346
347                                         Den = vecdot(vecsub(Vglob[i],Vim1),N)
348
349                                         Vi = []    
350                                         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)
351                                         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)
352                                         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)
353
354                                         ViL = LocalPosition(Vi, Obj)
355
356                                         if newvidx == []: 
357                                                 # if newvidx is empty (the first time Split is called), append a new vertex
358                                                 # to the mesh and remember its vertex-index and location
359                                                 ViLl = NMesh.Vert(ViL[0],ViL[1],ViL[2])
360
361                                                 if MeshPos == MeshNeg:
362                                                         MeshPos.verts.append(ViLl)
363
364                                                 else:
365                                                         MeshPos.verts.append(ViLl)
366                                                         MeshNeg.verts.append(ViLl)
367
368                                                 nvidx = totverts
369                                                 newvidx.append(nvidx)
370                                                 newvcoo.append(ViL)
371
372                                                 vp.append(nvidx)
373                                                 vn.append(nvidx)
374                                         else:
375                                                 # newvidx is not empty
376                                                 dist1 = []
377                                                 tlr = 0
378                                                 for j in range(len(newvidx)): 
379                                                         # calculate the distance from the new vertex to the vertices
380                                                         # in the list with new vertices
381                                                         dist1.append(length(vecsub(ViL, newvcoo[j])))
382                                                 for k in range(len(dist1)):
383                                                         if dist1[k] < Epsilon:
384                                                                 # if distance is smaller than epsilon, use the other vertex
385                                                                 # use newvidx[k] as vert
386                                                                 vp.append(newvidx[k])
387                                                                 vn.append(newvidx[k])
388                                                                 break # get out of closest loop
389                                                         else:
390                                                                 tlr += 1
391
392                                                 if tlr == len(newvidx):
393                                                         nvidx = totverts + len(newvidx)
394                                                         ViLl = NMesh.Vert(ViL[0],ViL[1],ViL[2])
395
396                                                         if MeshPos == MeshNeg:
397                                                                 MeshPos.verts.append(ViLl)
398
399                                                         else:
400                                                                 MeshPos.verts.append(ViLl)
401                                                                 MeshNeg.verts.append(ViLl)
402
403                                                         newvidx.append(nvidx)
404                                                         newvcoo.append(ViL)
405                                                         vp.append(nvidx)
406                                                         vn.append(nvidx)
407
408                                         if d[i] > 0:
409                                                 vp.append(Vidx[i])
410                                         else:
411                                                 vn.append(Vidx[i])
412   
413         return vp, vn, newvidx, newvcoo
414
415 #===========#
416 # Main part #
417 #===========#
418
419 def CutMesh():
420         global msg
421         global RBmesh0,RBmesh1,RBmesh2
422         #if timport == 1:
423         #       start = time.clock()
424         start = time()
425         
426         selected_obs = Object.GetSelected()
427
428         total = len(selected_obs)
429
430         NoErrors=0
431
432         meshes = 0
433
434         # check to see if every selected object is a mesh
435         for ob in selected_obs:
436                 type = ob.getType()
437                 if type == 'Mesh':
438                         meshes += 1
439
440         # at least select two objects
441         if meshes <= 1:
442                 msg = "ERROR: At least two objects should be selected"
443                 NoErrors = 1
444
445         # if not every object is a mesh
446         if meshes != total:
447                 msg = "ERROR: You should only select meshobjects"
448                 NoErrors=1
449
450         # everything is ok
451         if NoErrors == 0:
452                 Pln = selected_obs[0]
453                 PNormal, POffset, NoErrors = PlaneData(Pln)
454
455         # loop to cut multiple meshes at once
456         for o in range(1, total):
457                 
458                 Obj = selected_obs[o]
459
460                 if (NoErrors == 0) :
461                 
462                         m = Obj.getData()
463
464                         if RBmesh1.val == 1:
465
466                                 MeshNew = NMesh.GetRaw()
467
468                         if RBmesh2.val == 1:
469
470                                 MeshPos = NMesh.GetRaw()
471                                 MeshNeg = NMesh.GetRaw()
472
473                         # get the indices of the faces of the mesh
474                         idx = []
475                         for i in range(len(m.faces)):
476                                 idx.append(i)
477
478                         # if idx is not reversed, this results in a list index out of range if
479                         # the original mesh is used (RBmesh1 == 0)
480                         idx.reverse()
481
482                         lenface, vertglob, vertidx, vertdist = [], [], [], []
483
484                         # total number of vertices
485                         totverts = len(m.verts)
486
487                         # for every face: calculate global coordinates of the vertices
488                         #                 append the vertex-index to a list
489                         #                 calculate distance of vertices to cutplane in advance
490
491                         for i in idx:
492                                 fvertidx, Ve, dist = [], [], []
493                                 fa = m.faces[i]
494                                 lenface.append(len(fa))
495                                 for v in fa.v:
496                                         globpos = GlobalPosition(v.co, Obj)
497                                         Ve.append(globpos)
498                                         fvertidx.append(v.index)
499                                         dist.append(Distance(globpos, PNormal, POffset))
500                                 vertidx.append(fvertidx)
501                                 vertglob.append(Ve)
502                                 vertdist.append(dist)
503
504
505                         # append the verts of the original mesh to the new mesh
506                         if RBmesh1.val == 1:
507                                 for v in m.verts:
508                                         MeshNew.verts.append(v)
509         
510                         if RBmesh2.val == 1:
511                                 idx2 = []
512                                 dist2 = []
513                                 for v in m.verts:
514                                         MeshPos.verts.append(v)
515                                         MeshNeg.verts.append(v)
516                                         idx2.append(v.index)
517                                         dist2.append(Distance(GlobalPosition(v.co, Obj), PNormal, POffset))
518
519                         # remove all faces of m if the original object has to be used
520
521                         if RBmesh0.val == 1:
522                                 m.faces = []
523
524                         newvidx, newvcoo = [], []
525                         testidxpos, testidxneg = [], []
526
527                         # what its all about...
528                         for i in idx:
529                                 fp = FacePosition(vertdist[i])
530
531                                 # no intersection
532                                 if fp > 0:
533                                         if RBmesh0.val == 1:
534                                                 FaceAppend(m, vertidx[i])
535                         
536                                         elif RBmesh1.val == 1:
537                                                 FaceAppend(MeshNew, vertidx[i])
538                                 
539                                         elif RBmesh2.val == 1:
540                                                 FaceAppend(MeshPos, vertidx[i])
541
542                                                 if testidxpos == []:
543                                                         testidxpos = vertidx[i]
544                                 elif fp < 0:
545                                         if RBmesh0.val == 1:
546                                                 FaceAppend(m, vertidx[i])
547                                         elif RBmesh1.val == 1:
548                                                 FaceAppend(MeshNew, vertidx[i])
549                                         
550                                         elif RBmesh2.val == 1:
551                                                 FaceAppend(MeshNeg, vertidx[i])
552
553                                                 if testidxneg == []:
554                                                         testidxneg = vertidx[i]
555
556                                 # intersected faces
557                                 else:
558                                         # make new mesh
559                                         if RBmesh1.val == 1:
560                                                 vlp, vln, newvidx, newvcoo = Split(Obj, MeshNew, MeshNew, vertglob[i], vertidx[i], PNormal, POffset, newvidx, newvcoo, totverts, vertdist[i])
561
562                                                 if vlp != 0 and vln != 0:
563                                                         FaceMake(MeshNew, vlp)
564                                                         FaceMake(MeshNew, vln)
565                                                 # two new meshes
566                                         elif RBmesh2.val == 1:
567                                                 vlp, vln, newvidx, newvcoo = Split(Obj, MeshPos, MeshNeg, vertglob[i], vertidx[i], PNormal, POffset, newvidx, newvcoo, totverts, vertdist[i])
568         
569                                                 if vlp != 0 and vln != 0:
570                                                         FaceMake(MeshPos, vlp)
571                                                         FaceMake(MeshNeg, vln)
572
573                                         # use old mesh
574                                         elif RBmesh0.val == 1:
575         
576                                                 vlp, vln, newvidx, newvcoo = Split(Obj, m, m, vertglob[i], vertidx[i], PNormal, POffset, newvidx, newvcoo, totverts, vertdist[i])
577         
578                                                 if vlp != 0 and vln != 0:
579                                                         FaceMake(m, vlp)
580                                                         FaceMake(m, vln)
581
582                         if RBmesh1.val == 1:
583
584                                 ObOne = NMesh.PutRaw(MeshNew)
585
586                                 ObOne.LocX, ObOne.LocY, ObOne.LocZ = Obj.LocX, Obj.LocY, Obj.LocZ
587                                 ObOne.RotX, ObOne.RotY, ObOne.RotZ = Obj.RotX, Obj.RotY, Obj.RotZ
588                                 ObOne.SizeX, ObOne.SizeY, ObOne.SizeZ = Obj.SizeX, Obj.SizeY, Obj.SizeZ
589
590                         elif RBmesh2.val == 1:
591
592                                 # remove verts that do not belong to a face
593                                 idx2.reverse()
594                                 dist2.reverse()
595
596                                 for i in range(len(idx2)):
597                                         if dist2[i] < 0:
598                                                 v = MeshPos.verts[idx2[i]]
599                                                 MeshPos.verts.remove(v)
600                                         if dist2[i] > 0:
601                                                 v = MeshNeg.verts[idx2[i]]
602                                                 MeshNeg.verts.remove(v)
603
604                                 ObPos = NMesh.PutRaw(MeshPos)
605
606                                 ObPos.LocX, ObPos.LocY, ObPos.LocZ = Obj.LocX, Obj.LocY, Obj.LocZ
607                                 ObPos.RotX, ObPos.RotY, ObPos.RotZ = Obj.RotX, Obj.RotY, Obj.RotZ
608                                 ObPos.SizeX, ObPos.SizeY, ObPos.SizeZ = Obj.SizeX, Obj.SizeY, Obj.SizeZ
609
610                                 ObNeg = NMesh.PutRaw(MeshNeg)
611
612                                 ObNeg.LocX, ObNeg.LocY, ObNeg.LocZ = Obj.LocX, Obj.LocY, Obj.LocZ
613                                 ObNeg.RotX, ObNeg.RotY, ObNeg.RotZ = Obj.RotX, Obj.RotY, Obj.RotZ
614                                 ObNeg.SizeX, ObNeg.SizeY, ObNeg.SizeZ = Obj.SizeX, Obj.SizeY, Obj.SizeZ
615
616                         elif RBmesh0.val == 1:
617                                 m.update()
618
619
620         #if timport == 1:
621                 #end = time.clock()
622                 #total = end - start
623                 #print "mesh(es) cut in", total, "seconds" 
624
625         end = time()
626         total = end - start
627         print "mesh(es) cut in", total, "seconds"
628
629 #############################################################
630 # Graphics                                                  #
631 #############################################################
632 def Warn():
633         BGL.glRasterPos2d(115, 23)
634         Blender.Window.Redraw(Blender.Window.Const.TEXT)
635
636 def draw():
637         global msg
638         global RBmesh0,RBmesh1,RBmesh2
639         global VERSION
640         
641         BGL.glClearColor(0.5, 0.5, 0.5, 0.0)
642         BGL.glClear(BGL.GL_COLOR_BUFFER_BIT)
643         BGL.glColor3f(0, 0, 0)                  # Black
644         BGL.glRectf(2, 2, 482, 220)
645         BGL.glColor3f(0.48, 0.4, 0.57)          # Light Purple
646         BGL.glRectf(4, 179, 480, 210)
647         BGL.glRectf(4, 34, 480, 150)
648         BGL.glColor3f(0.3, 0.27, 0.35)          # Dark purple
649         BGL.glRectf(4, 151,480, 178)
650         BGL.glRectf(4, 4, 480, 33)
651         
652
653         BGL.glColor3f(1, 1, 1)
654         BGL.glRasterPos2d(8, 200)
655         Draw.Text("Blender Knife Tool -  V. 0.0.8a - 26 March 2004")
656         BGL.glRasterPos2d(8, 185)
657         Draw.Text("by Wim <tuinbels> Van Hoydonck & Stefano <S68> Selleri")
658         Draw.Button("Exit", 1, 430, 185, 40, 20)
659
660         RBmesh0 = Draw.Toggle("Edit Object",    10,10,157,153,18,RBmesh0.val, "The knife creates new vertices in the selected object.");
661         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.");
662         RBmesh2 = Draw.Toggle("Two New Objects",12,320,157,153,18,RBmesh2.val, "The knife creates two new separate objects.");
663
664         BGL.glRasterPos2d(8, 128)
665         Draw.Text("1 - Draw a Mesh Plane defining the Cut Plane")
666         BGL.glRasterPos2d(8, 108)
667         Draw.Text("2 - Select the Meshes to be Cut and the Cut Plane")
668         BGL.glRasterPos2d(8, 88)
669         Draw.Text("      (Meshes Dark Purple, Plane Light Purple)")
670         BGL.glRasterPos2d(8, 68)
671         Draw.Text("3 - Choose the Edit Method (Radio Buttons above)")
672         BGL.glRasterPos2d(8, 48)
673         Draw.Text("4 - Push the 'CUT' button (below)")
674         #Create Buttons
675         Draw.Button("CUT", 4, 10, 10, 465, 18, "Cut the selected mesh along the plane")
676
677         
678         BGL.glRasterPos2d(10, 223)
679         BGL.glColor3f(1,0,0)
680         Draw.Text(msg)
681         msg = ''
682         
683 def event(evt, val):
684         if (evt == Draw.QKEY or evt == Draw.ESCKEY) and not val:
685                 Draw.Exit()
686         if evt == Draw.CKEY and not val:
687                 CutMesh()
688                 Draw.Redraw()
689
690 def bevent(evt):
691         global RBmesh0,RBmesh1,RBmesh2
692
693         if evt == 1:
694                 Draw.Exit()
695         elif evt == 4:
696                 CutMesh()
697                 Draw.Redraw()
698         elif evt == 10:
699                 RBmesh0.val = 1
700                 RBmesh1.val = 0
701                 RBmesh2.val = 0
702                 Draw.Redraw()
703         elif evt == 11:
704                 RBmesh0.val = 0
705                 RBmesh1.val = 1
706                 RBmesh2.val = 0
707                 Draw.Redraw()
708         elif evt == 12:
709                 RBmesh0.val = 0
710                 RBmesh1.val = 0
711                 RBmesh2.val = 1
712                 Draw.Redraw()
713
714 Draw.Register(draw, event, bevent)