#!BPY """ Name: 'insect_walk' Blender: 228 Group: 'Animation' Tooltip: 'Procedural Insect Walk' """ # --------------------------------------------------------------------------------------- # # Procedural Insect Walk # # By Laurent Wibaux , parts by # Released under the Blender Artistic Licence (BAL) # See www.blender.org # --------------------------------------------------------------------------------------- # # ---- Special thanks to for the following procedures ---------------------------# # From vecf.py: # vecDot, vecNorm, vecSub, vecCross, vecProj # matrixToEulerRot # From Track_Axis.py: # getTrackingRotationMatrix # --------------------------------------------------------------------------------------- # # ---- History -------------------------------------------------------------------------- # # 0.4 2003-09-01 First public release # --------------------------------------------------------------------------------------- # # ---- Constants ------------------------------------------------------------------------ # VERSION = 0.4 # Naming of the objects to create LENP = LEG_END_NAME_PREFIX = 'L' # Construction is Proxy_Name.[LENP]LegNum[LENS].Side LENS = LEG_END_NAME_SUFFIX = 'E' # i.e.: Proxy_Name.L1E.R, Proxy_Name.L3E.L CENTER = 'C' # the center object: Proxy_Name.C # End of user defined variables # Constants RP = RIGHT_PAIR = 0 LP = LEFT_PAIR = 1 # General settings FF = FIRST_FRAME = 1 # begin evaluating at this frame LF = LAST_FRAME = 100 # stop evaluating after this frame # Dynamics of the movement MT = MOVE_TIME = 6 # number of frames/cycle a leg is moving # an even number greater than 0 # Description of the body of the insect LAX = LEG_ATTACHMENT_X = [0.3, 0.45, 0.4, 0.35] # position of each leg of a pair from the proxy center LAY = LEG_ATTACHMENT_Y = [0.6, 0.0, -0.6, -1.2] # position of each pair of leg from the proxy center LAZ = LEG_ATTACHMENT_Z = [1.5, 1.5, 1.5, 1.5] # height of the leg attachment from the proxy LSL = LEG_SHADOW_LENGTHS = [[3.0, 3.5, 3.0, 3.0], # total length of the cord of the right legs [3.0, 3.5, 3.0, 3.0]] # total length of the cord of the left legs LSE = LEG_STEP_ELEVATION = [0.5, 0.5, 0.5, 0.5] # elevation of the legs during a step LRR = LEG_REST_ROTATIONS = [[30.0, 0.0, -30.0, -50.0], # max rotation of the right legs (in degrees) [150.0, 180.0, -150.0, -130.0]] # max rotation of the left legs (in degrees) SIZING_RATIO = 1.0 # ratio to apply to the NPL = NUMBER_OF_PAIR_OF_LEGS = 4 # number of pair of legs # --------------------------------------------------------------------------------------- # # Data initialization # --------------------------------------------------------------------------------------- # from Blender import Object, Scene, Window, Ipo, NMesh, Draw, BGL import math proxy = Object.GetSelected() scene = Scene.getCurrent() lastLegP = [list(), list()] legRestRP = [list(), list()] lastLegRot = [list(), list()] legAtt = list() legElev = list() legShadows = [list(), list()] legRestRot = [list(), list()] for legNum in range(NPL): legAtt.append([Draw.Create(LAX[legNum]), Draw.Create(LAY[legNum]), Draw.Create(LAZ[legNum])]) legElev.append(Draw.Create(LSE[legNum])) for side in range(2): lastLegP[side].append([0.0, 0.0, 0.0]) legRestRP[side].append([0.0, 0.0, 0.0]) lastLegRot[side].append([0.0, 0.0, 0.0]) legShadows[side].append(Draw.Create(LSL[side][legNum])) legRestRot[side].append(Draw.Create(LRR[side][legNum])) startFrame = Draw.Create(FF) endFrame = Draw.Create(LF) stepLength = Draw.Create(MT) sizingRatio = Draw.Create(SIZING_RATIO) NPL = 3 nbLegs = Draw.Create(NPL) msgString = "Ready" if proxy != []: proxyName = Draw.Create(proxy[0].name) else: proxyName = Draw.Create("") # --------------------------------------------------------------------------------------- # # Vector utils # --------------------------------------------------------------------------------------- # def vecDot(v1, v2): return v1[0]*v2[0] + v1[1]*v2[1] + v1[2]*v2[2] def vecNorm(v): det = vecDot(v, v) if det>0.0: det = 1.0/math.sqrt(det) v[0] *= det v[1] *= det v[2] *= det return v def vecSub(a, b): return [a[0]-b[0], a[1]-b[1], a[2]-b[2]] def vecCross(v1, v2): r = [0.0, 0.0, 0.0] r[0] = v1[1]*v2[2] - v1[2]*v2[1] r[1] = v1[2]*v2[0] - v1[0]*v2[2] r[2] = v1[0]*v2[1] - v1[1]*v2[0] return r def vecProj(v2, v1): factor = vecDot(v1, v2)/vecDot(v1, v1) return [factor*v1[0], factor*v1[1], factor*v1[2]] # --------------------------------------------------------------------------------------- # # Matrix utils # --------------------------------------------------------------------------------------- # def relToAbs3(referenceO, relativeP): # params: referenceO: the object to relate to # relativeP: the position relative to the reference object # returns: the absolute position of relativeP absP = [0, 0, 0] oMat = referenceO.getMatrix() absP[0] = oMat[0][0]*relativeP[0] + oMat[1][0]*relativeP[1] + oMat[2][0]*relativeP[2] + oMat[3][0] absP[1] = oMat[0][1]*relativeP[0] + oMat[1][1]*relativeP[1] + oMat[2][1]*relativeP[2] + oMat[3][1] absP[2] = oMat[0][2]*relativeP[0] + oMat[1][2]*relativeP[1] + oMat[2][2]*relativeP[2] + oMat[3][2] return absP def rotateMatrix90Degree(mat): # params: mat: the 3x3 matrix to rotate # returns: a rotated matrix by 90° around Z return [[-mat[1][0], -mat[1][1], -mat[1][2]], [mat[0][0], mat[0][1], mat[0][2]], [mat[2][0], mat[2][1], mat[2][2]]] def matrixToEulerRot(mat): # params: mat: the 3x3 from which to exctract the Euler angles # returns: the Euler rotation angles mtx = [list(mat[0][:3]), list(mat[1][:3]), list(mat[2][:3])] angle_y = -math.asin(max(min(mtx[0][2], 1.0), -1.0)) C = math.cos(angle_y) if C != 0.0: C = 1.0/C angle_x = math.atan2(mtx[1][2] * C, mtx[2][2] * C) angle_z = math.atan2(mtx[0][1] * C, mtx[0][0] * C) return [angle_x, angle_y, angle_z] def getTrackingRotationMatrix(targetP, trackingP, rotationPlanNormalV): # params: targetP: the point to look at # trackingP: the point to look from # rotationPlanNormalV: the normal of the plan on which the tracking rotation occurs # returns: the rotation matrix to apply so that the object at trackingP point to targetP AB = vecSub(targetP, trackingP) T1 = vecNorm(vecSub(AB, vecProj(AB, rotationPlanNormalV))) T2 = vecNorm(vecCross(T1, rotationPlanNormalV)) return [T2, T1, rotationPlanNormalV] # --------------------------------------------------------------------------------------- # # IPO utils # --------------------------------------------------------------------------------------- # def writeLocIPOCurvePoint(ipo, frame, point): # inputs: ipo: the IPOblock to use # frame: at what frame # point: the 3D coordinate to write idx = 0 for c in [ipo[1], ipo[2], ipo[3]]: c.addBezier((frame, point[idx])) c.update() idx += 1 def writeRotIPOCurvePoint(ipo, frame, point): # inputs: ipo: the IPOblock to use # frame: at what frame # point: the 3D coordinate to write idx = 0 for c in [ipo[4], ipo[5], ipo[6]]: c.addBezier((frame, point[idx])) c.update() idx += 1 def makeRotLocIPO(name, ipol, expol): # inputs: name: desired name for this IPOblock # ipol: type of interpolation # expol: type of extrapolation # outputs: list of [ipo, newcurves] ipo = Ipo.New('Object', name) lxc = ipo.addCurve('LocX') lyc = ipo.addCurve('LocY') lzc = ipo.addCurve('LocZ') rxc = ipo.addCurve('RotX') ryc = ipo.addCurve('RotY') rzc = ipo.addCurve('RotZ') for curve in [lxc, lyc, lzc, rxc, ryc, rzc]: curve.setInterpolation(ipol) curve.setExtrapolation(expol) return [ipo, lxc, lyc, lzc, rxc, ryc, rzc] # --------------------------------------------------------------------------------------- # # Main functions # --------------------------------------------------------------------------------------- # def getLegName(legNum, side): return proxy.name + "." + LENP + str(legNum) + LENS + "." + side def createLegEnd(legName): legEnd = Object.Get(legName) if legEnd == None: legEnd = Object.New('Empty') legEnd.name = legName scene.link(legEnd) def calculateLegUpP(side, legNum): global lastLegP legEndP = [legRestRP[side][legNum][0], legRestRP[side][legNum][1], 0.0] legEndAbsP = relToAbs3(proxy, legEndP) hasMoved = 0 for i in range(3): if abs(legEndAbsP[i]-lastLegP[side][legNum][i]) > 0.02: hasMoved = 1 if hasMoved == 1: pMat = proxy.getMatrix() legEndP[i] = legEndP[i] + pMat[2][i]*LSE[legNum] return relToAbs3(proxy, legEndP) else: return lastLegP[side][legNum] def calculateLegDownP(side, legNum): global lastLegP legEndP = [legRestRP[side][legNum][0], legRestRP[side][legNum][1], 0.0] legEndAbsP = relToAbs3(proxy, legEndP) hasMoved = 0 for i in range(3): if abs(legEndAbsP[i]-lastLegP[side][legNum][i]) > 0.02: hasMoved = 1 if hasMoved == 1: for i in range(3): lastLegP[side][legNum][i] = legEndAbsP[i] return lastLegP[side][legNum] def calculateLegRot(side, legNum, proxyNormV, checkOverflow): global lastLegRot, lastLegP, LAX, LAY legA = [LAX[legNum], LAY[legNum], 0.0] if side == LP: legA[0] = -LAX[legNum] rotMat = getTrackingRotationMatrix(relToAbs3(proxy, legA), lastLegP[side][legNum], proxyNormV) eulerRot = matrixToEulerRot(rotateMatrix90Degree(rotMat)) # check that we don't overflow the angles if checkOverflow != 0: for i in range(3): if abs(eulerRot[i] - lastLegRot[side][legNum][i]) > math.pi: if lastLegRot[side][legNum][i] < 0: eulerRot[i] = -2*math.pi + eulerRot[i] if lastLegRot[side][legNum][i] > 0: eulerRot[i] = 2*math.pi + eulerRot[i] for i in range(3): lastLegRot[side][legNum][i] = eulerRot[i] return eulerRot def writeLegIpos(frame, legIpos, isL1RMoving, isLegUp): global lastLegP if isL1RMoving == 1: # move L1R, L2L, L3R, L4L for legNum in range(NPL): if legNum == 0 or legNum == 2: if isLegUp == 0: writeLocIPOCurvePoint(legIpos[RP][legNum], frame, lastLegP[RP][legNum]) writeLocIPOCurvePoint(legIpos[LP][legNum], frame, calculateLegDownP(LP, legNum)) else: writeLocIPOCurvePoint(legIpos[RP][legNum], frame, calculateLegUpP(RP, legNum)) if legNum == 1 or legNum == 3: if isLegUp ==0: writeLocIPOCurvePoint(legIpos[LP][legNum], frame, lastLegP[LP][legNum]) writeLocIPOCurvePoint(legIpos[RP][legNum], frame, calculateLegDownP(RP, legNum)) else: writeLocIPOCurvePoint(legIpos[LP][legNum], frame, calculateLegUpP(LP, legNum)) else: # move L1L, L2R, L3L, L4R for legNum in range(NPL): if legNum == 0 or legNum == 2: if isLegUp == 0: writeLocIPOCurvePoint(legIpos[RP][legNum], frame, calculateLegDownP(RP, legNum)) writeLocIPOCurvePoint(legIpos[LP][legNum], frame, lastLegP[LP][legNum]) else: writeLocIPOCurvePoint(legIpos[LP][legNum], frame, calculateLegUpP(LP, legNum)) if legNum == 1 or legNum == 3: if isLegUp ==0: writeLocIPOCurvePoint(legIpos[LP][legNum], frame, calculateLegDownP(LP, legNum)) writeLocIPOCurvePoint(legIpos[RP][legNum], frame, lastLegP[RP][legNum]) else: writeLocIPOCurvePoint(legIpos[RP][legNum], frame, calculateLegUpP(RP, legNum)) if isLegUp == 0: proxyNormV = vecNorm(proxy.getMatrix()[2]) for legNum in range(NPL): writeRotIPOCurvePoint(legIpos[RP][legNum], frame, calculateLegRot(RP, legNum, proxyNormV, 1)) writeRotIPOCurvePoint(legIpos[LP][legNum], frame, calculateLegRot(LP, legNum, proxyNormV, 1)) def walkInsect(): global LRR, LAX, LAY, LSL, LSE, NPL global legRestRP, lastLegP global scene, proxy, proxyName, msgString proxy = None layer = 0 status = 'UNDEFINED ERROR' lastBodyRot = [0.0, 0.0, 0.0] NPL = nbLegs.val for legNum in range(NPL): LAX[legNum] = sizingRatio.val*legAtt[legNum][0].val LAY[legNum] = sizingRatio.val*legAtt[legNum][1].val LAZ[legNum] = sizingRatio.val*legAtt[legNum][2].val LSE[legNum] = sizingRatio.val*legElev[legNum].val for side in range(2): LRR[side][legNum] = legRestRot[side][legNum].val*math.pi/180 LSL[side][legNum] = sizingRatio.val*legShadows[side][legNum].val legRestRP[side][legNum][0] = math.cos(LRR[side][legNum])*LSL[side][legNum] + LAX[legNum] if side == LP: legRestRP[side][legNum][0] -= 2*LAX[legNum] legRestRP[side][legNum][1] = math.sin(LRR[side][legNum])*LSL[side][legNum] + LAY[legNum] # make sure that there's an actual walker proxy to use: if len(proxyName.val) >= 1: proxy = Object.Get(proxyName.val) if proxy == None: status = 'Proxy object does not exist' else: layer = proxy.layer status = 'OK' scene = Scene.getCurrent() if scene == []: status = 'No scene selected' if status=='OK': currentUserFrame = scene.currentFrame() if scene.currentFrame() != startFrame.val: scene.currentFrame(startFrame.val) Window.Redraw('View') # initialize the positions of the empties lastBodyRot = matrixToEulerRot(proxy.getMatrix()) proxyNormV = vecNorm(proxy.getMatrix()[2]) for n in range(NPL): calculateLegDownP(RP, n) calculateLegDownP(LP, n) calculateLegRot(RP, legNum, proxyNormV, 0) calculateLegRot(RP, legNum, proxyNormV, 0) voidIpo = makeRotLocIPO('void', 'Linear', 'Constant') # clear any ipo left iCenter = Object.Get(proxy.name + "." + CENTER) if iCenter != None: iCenter.link(voidIpo[0]) for legNum in range(NPL): legEnd = Object.Get(getLegName(legNum+1, "R")) if legEnd != None: legEnd.link(voidIpo) legEnd = Object.Get(getLegName(legNum+1, "L")) if legEnd != None: legEnd.link(voidIpo) # define the body centre if iCenter == None: iCenter = Object.New('Empty') iCenter.name = proxy.name + "." + CENTER scene.link(iCenter) # define the leg end for legNum in range(NPL): legEnd = Object.Get(getLegName(legNum+1, "R")) if legEnd == None: createLegEnd(getLegName(legNum+1, "R")) legEnd = Object.Get(getLegName(legNum+1, "L")) if legEnd == None: createLegEnd(getLegName(legNum+1, "L")) # define the ipos iCenterIpo = makeRotLocIPO("ipo." + proxy.name + "." + CENTER, 'Linear', 'Constant') legIpos = [list(), list()] for legNum in range(NPL): legIpos[RP].append(makeRotLocIPO("ipo." + getLegName(legNum+1, "R"), 'Linear', 'Constant')) legIpos[LP].append(makeRotLocIPO("ipo." + getLegName(legNum+1, "L"), 'Linear', 'Constant')) isL1RMoving = 0 cpf = startFrame.val while cpf <= endFrame.val: if scene.currentFrame() != cpf: scene.currentFrame(cpf) Window.Redraw('View') msgString = "Processing frame " + str(cpf) + "/" + str(endFrame.val); Draw.Draw() # Move the center writeLocIPOCurvePoint(iCenterIpo, cpf, relToAbs3(proxy, [0, 0, LAZ[1]])) eulerRot = matrixToEulerRot(proxy.getMatrix()) for i in range(3): if abs(eulerRot[i] - lastBodyRot[i]) > math.pi: if lastBodyRot[i] < 0: eulerRot[i] = -2*math.pi + eulerRot[i] if lastBodyRot[i] > 0: eulerRot[i] = 2*math.pi + eulerRot[i] for i in range(3): lastBodyRot[i] = eulerRot[i] writeRotIPOCurvePoint(iCenterIpo, cpf, eulerRot) # Move legs, alternate left and right pair isL1RMoving += 1 if isL1RMoving == 2: isL1RMoving = 0 writeLegIpos(cpf, legIpos, isL1RMoving, 0) cpf = cpf + stepLength.val/2 # move the leg up, making sure we don't end up with a leg up if cpf + stepLength.val/2 < endFrame.val: writeLegIpos(cpf, legIpos, isL1RMoving, 1) cpf = cpf + stepLength.val/2 # link the ipos iCenter.link(iCenterIpo[0]) iCenter.layer = layer for legNum in range(NPL): legEnd = Object.Get(getLegName(legNum+1, "R")) legEnd.link(legIpos[0][legNum][0]) legEnd.layer = layer legEnd = Object.Get(getLegName(legNum+1, "L")) legEnd.link(legIpos[1][legNum][0]) legEnd.layer = layer # At last, as a friendly gesture, restore the frame to whatever the user # was looking at before running the script, and refresh the screens: scene.currentFrame(currentUserFrame) Window.RedrawAll() msgString = "Ready"; Draw.Draw() else: msgString = status; Draw.Draw() # --------------------------------------------------------------------------------------- # # GUI definition # --------------------------------------------------------------------------------------- # def makeInsectSymetrical(): global legShadows, legRestRot for n in range(3): if legRestRot[RP][n].val >= 0: legRestRot[LP][n].val = 180-legRestRot[RP][n].val else: legRestRot[LP][n].val = -180-legRestRot[RP][n].val legShadows[LP][n].val = legShadows[RP][n].val Draw.Redraw() def paintSectionTitle(text, x, y, w): BGL.glColor3f(0.8, 0.8, 0.8) BGL.glRectf(x-5, y-7, x+w+4, y+14) BGL.glColor3f(0.65, 0.65, 0.65) BGL.glRectf(x-3, y-5, x+w+2, y+12) BGL.glColor3f(0.0, 0.0, 0.0) BGL.glRasterPos2i(x+2, y) Draw.Text(text) def draw(): X, Y, W = 16, 116, 316 global proxyName, startFrame, endFrame, stepLength, msgString global legAtt, legShadows, legElev, legRestRot, sizingRatio, nbLegs BGL.glClearColor(0.55, 0.55, 0.55, 0.0) BGL.glClear(BGL.GL_COLOR_BUFFER_BIT) paintSectionTitle("Insect procedural walk - wibauxl - " + str(VERSION), X+1, Y + nbLegs.val*2*21 + 130, W-4) # insect body definition paintSectionTitle("Insect body definition", X+1, Y + nbLegs.val*2*21 + 103, 125) BGL.glColor3f(0.8,0.8,0.8) BGL.glRectf(X-4, Y, X+W, Y + nbLegs.val*2*21 + 98) BGL.glColor3f(0.0,0.0,0.0) curY = Y + 5 sizingRatio = Draw.Slider("Sizing ratio: ", 220, X+40, curY, 270, 19, sizingRatio.val, 0.1, 10.0, 0, "Overall sizing factor to apply to the above dimensions"); curY += 10 curY += 20 + nbLegs.val*21 BGL.glRasterPos2i(X+60, curY); Draw.Text("Rot.R") BGL.glRasterPos2i(X+120, curY); Draw.Text("Rot.L") BGL.glRasterPos2i(X+189, curY); Draw.Text("Shadow.R") BGL.glRasterPos2i(X+252, curY); Draw.Text("Shadow.L") for n in range(nbLegs.val): BGL.glRasterPos2i(X, curY-(n+1)*20) Draw.Text("Leg " + str(n+1) + ":") legRestRot[RP][n] = Draw.Number("", 100+n, X+40, curY-3-(n+1)*21, 60, 18, legRestRot[RP][n].val, -180.0, 180.0, "Rest rotation for right leg") legRestRot[LP][n] = Draw.Number("", 110+n, X+102, curY-3-(n+1)*21, 60, 18, legRestRot[LP][n].val, -180.0, 180.0, "Rest rotation for left leg") legShadows[RP][n] = Draw.Number("", 120+n, X+188, curY-3-(n+1)*21, 60, 18, legShadows[RP][n].val, 0.0, 100.0, "Shadow length for right leg") legShadows[LP][n] = Draw.Number("", 130+n, X+250, curY-3-(n+1)*21, 60, 18, legShadows[LP][n].val, 0.0, 100.0, "Shadow length for left leg") curY += 20 + nbLegs.val*21 BGL.glRasterPos2i(X+50, curY); Draw.Text("Start X") BGL.glRasterPos2i(X+111, curY); Draw.Text("Start Y") BGL.glRasterPos2i(X+173, curY); Draw.Text("Start Z") BGL.glRasterPos2i(X+246, curY); Draw.Text("Step height") for n in range(nbLegs.val): BGL.glRasterPos2i(X, curY-(n+1)*20) Draw.Text("Leg " + str(n+1) + ":") for i in range(3): legAtt[n][i] = Draw.Number("", 140+3*n+i, X+40+i*62, curY-3-(n+1)*21, 60, 18, legAtt[n][i].val, -100.0, 100.0, "Leg attachment position") legElev[n] = Draw.Number("", 150+n, X+250, curY-3-(n+1)*21, 60, 18, legElev[n].val, -100.0, 100.0, "Leg tip max height to the ground during step") curY += 23 BGL.glRasterPos2i(X, curY); Draw.Text("Number of legs:") nbLegs = Draw.Menu("6 %x3|8 %x4", 3, X+102, curY-3, 60, 18, nbLegs.val) Draw.Button("Make symetrical", 10, X+190, curY-4, 120, 20, "Make left and right legs rest rotation and shadow length the same"); # animation definition curY = Y-20 paintSectionTitle("Animation", X+1, curY, 70) BGL.glColor3f(0.8,0.8,0.8) BGL.glRectf(X-4, curY-5, X+W, curY-60) BGL.glColor3f(0.0,0.0,0.0) curY -= 26 BGL.glRasterPos2i(X, curY+2); Draw.Text("Proxy:") proxyName = Draw.String("", 80, X+40, curY-4, 176, 19, proxyName.val, 64, "Name of the proxy") Draw.Button("Get selected", 11, X+220, curY-4, 90, 19, "Get the proxy name from the object currently selected") curY -= 24 BGL.glRasterPos2i(X, curY+2); Draw.Text("Start:") startFrame = Draw.Number("", 3, X+40, curY-3, 50, 18, startFrame.val, 1, 10000, "Frame at which the walk starts") BGL.glRasterPos2i(X+115, curY+2); Draw.Text("End:") endFrame = Draw.Number("", 170, X+145, curY-3, 50, 18, endFrame.val, startFrame.val+1, 10000, "Frame at which the walk ends") BGL.glRasterPos2i(X+220, curY+2); Draw.Text("Step:") stepLength = Draw.Number("", 180, X+260, curY-3, 50, 18, stepLength.val, 2, 10000, "Number of frames required to perform a step") # Status and buttons curY = Y-88 BGL.glColor3f(0.85,0.85,0.85) BGL.glRectf(X-4, curY, X+180, curY-20) BGL.glColor3f(0.0,0.0,0.9) BGL.glRasterPos2i(X+1, curY-14); Draw.Text(msgString) Draw.Button("Run", 12, X+185, curY-19, 63, 19) Draw.Button("Exit", 1, X+252, curY-19, 63, 19) def event(evt, val): if (evt== Draw.ESCKEY and not val): Draw.Exit() def bevent(evt): global msgString if (evt== 1): Draw.Exit() elif (evt== 2): Draw.Redraw() elif (evt== 3): Draw.Redraw() elif (evt== 10): makeInsectSymetrical() elif (evt== 11): obj = Object.GetSelected() if obj != []: proxyName.val = obj[0].name else: proxyName.val = "" msgString = "Got nothing" Draw.Redraw() elif (evt== 12): walkInsect() Draw.Register(draw, event, bevent)