def drawEdgeSelection(self, edge, alpha=0.4): """Draw a hilight around the edge.""" if isinstance(edge, SuperEdge): for subedge in edge.edgeOrder(): self.drawEdgeSelection(subedge) for vx in edge.bends: self.drawVertexSelection(vx) return ctx = self.graph.parent # Multiply points if snapping to grid # for Netcli (has no parent) showG = False if not ctx == None: if ctx.showGrid: showG = True if showG: srcpos = utilities.mult3D(edge.source.pos, ctx.spacing) tgtpos = utilities.mult3D(edge.target.pos, ctx.spacing) else: srcpos = edge.source.pos tgtpos = edge.target.pos diff = utilities.diff3D(srcpos, tgtpos) dist = utilities.dist3D(c=diff) # Avoid dividing by zero - # don't draw anything for zero-length edges if dist <= 0: return glEnable(GL_BLEND) glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA) glPushMatrix() pigment = edge.color + (alpha,) glColor4f(*pigment) # Figure out radius boost factor x = max(log(40 * edge.radius, 10), 0) phi = acos(diff[Z_AXIS] / dist) * 180 / pi theta = atan2(diff[Y_AXIS], diff[X_AXIS]) * 180 / pi glTranslatef(*srcpos) glRotatef(theta, 0.0, 0.0, 1.0) glRotatef(phi, 0.0, 1.0, 0.0) gluQuadricOrientation(self.quad, GLU_OUTSIDE) gluQuadricTexture(self.quad, GL_TRUE) gluQuadricDrawStyle(self.quad, GLU_FILL) gluQuadricNormals(self.quad, GLU_SMOOTH) # glRotated(90, 1, 0, 0) gluCylinder(self.quad, edge.radius + x, edge.radius + x, dist, config.current['global:draw-edge-sides'], config.current['global:draw-edge-sides']) glPopMatrix() glDisable(GL_BLEND)
def realPosition(self, camera): """ Figure out the world-space coordinates of this cursor relative to the camera given. """ from utilities import mult3D, add3D from camera import X_AXIS, Y_AXIS, Z_AXIS x = mult3D(camera.yz, self.pos[X_AXIS]) y = mult3D(camera.up, self.pos[Y_AXIS]) z = mult3D(camera.vpn, self.pos[Z_AXIS]) offset = add3D(x, y) offset = add3D(offset, z) return add3D(offset, camera.pos)
def InputPos(self, pos): """ Translate an input device position for the cursor. """ from utilities import add3D, diff3D, mult3D self.move = False #Initialize jitter last position if self.first: self.lastPos = self.posMap(*pos) self.first = False if self.calibrate: mapped = self.posMap(*pos) offset = mult3D(mapped, self.posScale) self.posOrigin = offset self.calibrate = False if not self.manager.contexts.active: return # Translate the cursor position for use mapped = self.posMap(*pos) #Check for jitter for i in range(0, 3): dif = abs(mapped[i] - self.lastPos[i]) if dif < float(self.jitter): self.move = False or self.move else: self.move = True #Real Movement - not jitter! if self.move: offset = mult3D(mapped, self.posScale) offset = diff3D(self.posOrigin, offset) self.manager.contexts.active.cursor.inputPos(offset) self.manager.contexts.active.showCursor = True self.lastPos = mapped # Determine if cursor is below ground plane oldStatus = self.manager.contexts.active.HUDstatus if self.manager.contexts.active.graph.findGroundPlane() > \ self.manager.contexts.active.cursor.realPosition( \ self.manager.contexts.active.camera)[1]: self.manager.contexts.active.HUDstatus = "Cursor below groundplane" else: if oldStatus == "Cursor below groundplane": oldStatus = "" self.manager.contexts.active.HUDstatus = oldStatus
def useTracker(self): """ camera.useTracker() -> void Offsets the camera (should be called after use()) based on the current position of the tracker. """ if self.trackPosOffset: # Calculate the offset relative to the camera - rather than relative to the world. x = mult3D(self.yz, self.trackPosOffset[X_AXIS]) y = mult3D(self.up, self.trackPosOffset[Y_AXIS]) z = mult3D(self.vpn, self.trackPosOffset[Z_AXIS]) offset = add3D(x, y) offset = add3D(offset, z) GL.glTranslatef(*offset) if self.trackRotMatrix: GL.glMultMatrix(*self.trackRotMatrix)
def vertexWarp(self, vertex, refresh=None): """ Warp to vertex, using the Animator. """ from utilities import add3D, diff3D, mult3D offset = add3D(mult3D(self.camera.vpn, -10.0), (0.0, vertex.radius * 3.0, 0.0)) if self.showGrid: npos = utilities.mult3D(vertex.pos, self.spacing) else: npos = vertex.pos targetpos = add3D(npos, offset) self.parent.animator.perspCameraMove(self.camera, newPos=targetpos, newLook=npos, duration=1.0)
def arrangeStepwise(self, graph, vertices, newPos, duration, wait=0.0, tween=True): """ Arrange the vertices of the graph into a new layout specified by an indexed list of new positions newPos. The vertices will be positioned one at a time. """ assert (len(newPos) == len(vertices)) delay = float(duration) / len(vertices) from math import floor if tween: if delay > (1.0 / self.parent.fps): # No sense tweening faster than the frame rate can keep up stepsPerVert = int(floor(delay / (1.0 / self.parent.fps))) totalMove = [diff3D(a, b) for a, b in zip([x.pos for x in vertices], newPos)] partialMove = [div3D(x, stepsPerVert) for x in totalMove] else: tween = False accum = wait for i in range(len(vertices)): if tween: accum += delay / stepsPerVert for step in range(stepsPerVert - 1): self.post(accum, objects=( vertices[i], ), props=( ( 'pos', add3D(vertices[i].pos, mult3D(partialMove[i], (step + 1))), ), ), changeGraph=graph, ) accum += delay / stepsPerVert else: accum += delay self.post(accum, objects=( vertices[i], ), props=( ('pos', newPos[i]), ), changeGraph=graph, ) self.signal()
def lookAt(self, target, refresh=None): """ Re-point the current camera to look at some object in the graph. Target can be: - a position in 3-space expressed as a 3-tuple of floats - a Vertex object - an Edge object (will look at the midpoint) """ if isinstance(target, Vertex): if self.showGrid: tgt = target tgt.pos = utilities.mult3D(target.pos, self.spacing) else: tgt = target elif isinstance(target, Edge): if self.showGrid: tgt = target tgt.source.pos = utilities.mult3D(target.source.pos, self.spacing) tgt.target.pos = utilities.mult3D(target.target.pos, self.spacing) else: tgt = target elif self.showGrid: tgt = utilities.mult3D(target, self.spacing) else: tgt = target if self.orthoMode: # XXX# Do something pass else: self.parent.animator.perspCameraMove( camera=self.camera, newLook=tgt, duration=1.2, )
def InputPos(self, pos): """ Translate an input device position for the cursor. """ from utilities import add3D, diff3D, mult3D #Camera jitter: no move to start self.move = False #Initiate jitter last position if self.first: self.lastPos = self.posMap(*pos) self.first = False print "jitter:", self.jitter if self.calibrate: mapped = self.posMap(*pos) offset = mult3D(mapped, self.posScale) self.posOrigin = offset self.calibrate = False if not self.manager.contexts.active: return # Translate the cursor position for use mapped = self.posMap(*pos) #Check for jitter for i in range(0, 3): dif = abs(mapped[i] - self.lastPos[i]) if dif < float(self.jitter): self.move = False or self.move else: self.move = True #Real Movement - not jitter! if self.move: offset = mult3D(mapped, self.posScale) offset = diff3D(self.posOrigin, offset) self.manager.contexts.active.camera.inputTrackPos(offset) self.lastPos = mapped
def perspCameraLookatMove(self, camera, newPos, fixLook, duration, wait=0.0): """ Moves the camera smoothly to a new position and orientation. If newLook is None, does not change the orientation of the camera. If newPos is None, does not change the position of the camera. """ from camera import Camera, OrthoCamera, X_AXIS, Y_AXIS, Z_AXIS assert (not isinstance(camera, OrthoCamera)) fixLook = self.normalizePos(fixLook) steps = int(duration * self.parent.fps) deltaPos = diff3D(camera.pos, newPos) stepPos = div3D(deltaPos, steps) accum = wait delay = 1.0 / self.parent.fps # Set up the animation for i in range(steps - 1): accum += delay self.post(accum, objects=(camera,), props=( ( 'pos', add3D(camera.pos, mult3D(stepPos, i + 1)) ), ( 'lookAt', fixLook), ), call=( ('absrotate', (Y_AXIS, stepYaw), {}), ('rotate', (X_AXIS, stepPitch), {}), ), ) # Finish up in the correct place accum += delay self.post(accum, objects=(camera,), props=( ('pos', newPos), ('lookAt', fixLook), ), ) self.signal()
def arrangeMorph(self, graph, vertices, newPos, duration, wait=0.0): """ Arrange the vertices of the graph into a new layout specified by an indexed list of new positions newPos. The vertices will be positioned simultaneously (smooth morph) """ assert (len(newPos) == len(vertices)) accum = wait steps = int(duration * self.parent.fps) delay = 1.0 / self.parent.fps d = [div3D(diff3D(a.pos, b), steps) for a, b in zip(vertices, newPos)] for i in range(steps - 1): accum += delay self.post(accum, objects=vertices, multiprops=( ( 'pos', [add3D(a.pos, mult3D(b, i + 1)) for a, b in zip(vertices, d)] ), ), changeGraph=graph, ) accum += delay self.post(accum, objects=vertices, multiprops=( ('pos', newPos), ), changeGraph=graph, ) self.signal()
def drawVertex(self, vertex, alpha=1.0): """ draw a vertex in 3D """ glPushMatrix() if config.current['global:enable-anaglyph']: pigment = (1.0, 1.0, 1.0, 1.0) else: pigment = vertex.color + (alpha,) glColor4f(*pigment) # For Netcli (has no parent) showG = False ctx = self.graph.parent if not ctx == None: if ctx.showGrid: showG = True if showG: vrtpos = utilities.mult3D(vertex.pos, ctx.spacing) else: vrtpos = vertex.pos glTranslatef(vrtpos[0], vrtpos[1], vrtpos[2]) # glutSolidSphere(vertex.radius, config.current['global:draw-sphere-slices'], config.current['global:draw-sphere-stacks']) gluQuadricOrientation(self.quad, GLU_OUTSIDE) gluQuadricTexture(self.quad, GL_TRUE) gluQuadricDrawStyle(self.quad, GLU_FILL) gluQuadricNormals(self.quad, GLU_SMOOTH) glRotated(90, 1, 0, 0) gluSphere(self.quad, vertex.radius, config.current['global:draw-sphere-slices'], config.current['global:draw-sphere-stacks']) glPopMatrix()
def drawVertexSelection(self, vertex, alpha=0.6): glEnable(GL_BLEND) glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA) glPushMatrix() pigment = vertex.color + (alpha,) glColor4f(*pigment) ctx = self.graph.parent # For Netcli (has no parent) showG = False if not ctx == None: if ctx.showGrid: showG = True if showG: vrtpos = utilities.mult3D(vertex.pos, ctx.spacing) else: vrtpos = vertex.pos glTranslatef(vrtpos[0], vrtpos[1], vrtpos[2]) if vertex.radius > 0: x = max(log(40 * vertex.radius, 10), 0) else: x = 1 # glutSolidSphere(vertex.radius + x, config.current['global:draw-sphere-slices'], config.current['global:draw-sphere-stacks']) gluQuadricOrientation(self.quad, GLU_OUTSIDE) gluQuadricTexture(self.quad, GL_TRUE) gluQuadricDrawStyle(self.quad, GLU_FILL) gluQuadricNormals(self.quad, GLU_SMOOTH) glRotated(90, 1, 0, 0) gluSphere(self.quad, vertex.radius + x, config.current['global:draw-sphere-slices'], config.current['global:draw-sphere-stacks']) glPopMatrix() glDisable(GL_BLEND)
def drawEdge(self, edge, alpha=1.0): """ draw an edge in 3D. """ # Superedge drawing is a no-op - all the parts will already have been # drawn. if isinstance(edge, SuperEdge): return if config.current['global:enable-anaglyph']: pigment = (1.0, 1.0, 1.0, alpha) else: pigment = edge.color + (alpha,) glColor4f(*pigment) # For Netcli (has no parent) ctx = self.graph.parent showG = False if not ctx == None: if ctx.showGrid: showG = True if showG: srcpos = utilities.mult3D(edge.source.pos, ctx.spacing) tgtpos = utilities.mult3D(edge.target.pos, ctx.spacing) else: srcpos = edge.source.pos tgtpos = edge.target.pos if config.current['global:draw-edge-cylinders']: diff = utilities.diff3D(srcpos, tgtpos) dist = utilities.dist3D(c=diff) # Avoid dividing by zero - # don't draw anything for zero-length edges if dist <= 0: return glPushMatrix() phi = acos(diff[Z_AXIS] / dist) * 180 / pi theta = atan2(diff[Y_AXIS], diff[X_AXIS]) * 180 / pi glTranslatef(*srcpos) glRotatef(theta, 0.0, 0.0, 1.0) glRotatef(phi, 0.0, 1.0, 0.0) gluQuadricOrientation(self.quad, GLU_OUTSIDE) gluQuadricTexture(self.quad, GL_TRUE) gluQuadricDrawStyle(self.quad, GLU_FILL) gluQuadricNormals(self.quad, GLU_SMOOTH) #glRotated(90, 1, 0, 0) gluCylinder(self.quad, edge.radius, edge.radius, dist, config.current['global:draw-edge-sides'], config.current['global:draw-edge-sides']) glPopMatrix() else: # not drawing edges as cylinders glDisable(GL_LIGHTING) glEnable(GL_LINE_SMOOTH) glLineWidth(config.current['global:draw-edge-linewidth']) glBegin(GL_LINES) glVertex3f(srcpos[0], srcpos[1], srcpos[2]) glVertex3f(tgtpos[0], tgtpos[1], tgtpos[2]) glEnd() glEnable(GL_LIGHTING)
def draw(self, edgeNameBase=None, vertNameBase=None): """Draw the elements of this context on the current GL canvas.""" if not self.ready: self.init() # Set up the camera if self.orthoMode: activecam = self.orthocamera else: activecam = self.camera activecam.use() # Apply the tracker offsets. activecam.useTracker() if self.graph.vertices_selected: orbitCentre = self.graph.vertices_selected[0] else: orbitCentre = self.graph.centerOfMass() # Multiply points if snapping to grid if self.showGrid: ocp = utilities.mult3D(orbitCentre.pos, self.spacing) else: ocp = orbitCentre.pos if config.current['global:camera-orbit'] == "cw": self.camera.absorbit(ocp, Y_AXIS, -1) elif config.current['global:camera-orbit'] == "ccw": self.camera.absorbit(ocp, Y_AXIS, 1) # Only draw decorations if we're in render mode - not in # selection mode. if glGetInteger(GL_RENDER_MODE) == GL_RENDER: # Draw the ground plane if it's enabled, but not when we're # using ortho mode glEnable(GL_CULL_FACE) if self.showPlane and not self.orthoMode: self.decor.drawGroundPlane(height=self.graph.findGroundPlane(), color=self.planeColor, reference=self.camera.pos) # # Draw the graph # glEnable(GL_TEXTURE_2D) self.graphgl.draw(edgeNameBase=edgeNameBase, vertNameBase=vertNameBase) # # Draw A grid if the user wants one # if self.showGridLines: self.decor.drawGrid(parent=self, pos=self.pos, sizeX=self.sizeX, sizeY=self.sizeY, sizeZ=self.sizeZ, spacing=self.spacing) # Only draw decorations if we're in render mode - not in # selection mode. if glGetInteger(GL_RENDER_MODE) == GL_RENDER: glEnable(GL_CULL_FACE) # Draw the coordinate axes if they're enabled if self.showAxes: self.decor.drawAxes() # Draw local axes if required # print "window:",wx.Window.FindFocus(), "\n canvas:", self.parent.canvas showA = False if not self.parent == None: if wx.Window.FindFocus() == self.parent.canvas: showA = True if self.showLocalAxes and showA: localAxes = (X_AXIS, Y_AXIS, Z_AXIS) labels = ('Q', 'A', 'W', 'S', 'E', 'D') if self.orthoMode: if self.orthoMode[0] == X_AXIS: localAxes = (Y_AXIS, Z_AXIS) if self.orthoMode[1] > 0: labels = (None, None, 'W', 'S', 'D', 'A') else: labels = (None, None, 'W', 'S', 'A', 'D') elif self.orthoMode[0] == Y_AXIS: localAxes = (X_AXIS, Z_AXIS) if self.orthoMode[1] > 0: labels = ('A', 'D', None, None, 'S', 'W') else: labels = ('D', 'A', None, None, 'S', 'W') elif self.orthoMode[0] == Z_AXIS: localAxes = (X_AXIS, Y_AXIS) if self.orthoMode[1] > 0: labels = ('A', 'D', 'W', 'S', None, None) else: labels = ('D', 'A', 'W', 'S', None, None) for v in self.graph.vertices_selected: if v.hidden: continue self.decor.draw_localaxes(self, v, axes=localAxes, labels=labels) # Draw vertex labels if selected. if self.showVertexLabels: if self.showDummyLabels: vxlist = self.graph.vertices else: vxlist = [x for x in self.graph.vertices if not isinstance(x, DummyVertex)] if len(vxlist) > 0: if self.vertexLabelName: labelFunc = lambda v: str(v.name) else: labelFunc = lambda v: str(v.id) self.decor.drawVertexLabels(parent=self, vxlist=vxlist, labelFunc=labelFunc, labelStrokeWidth=self.vertexLabelStroke, labelColor=self.vertexLabelColor, shadowColor=self.vertexShadowColor) if self.showHUD: if self.showCursor: self.decor.drawHUD(activecam, self.graph.vertices_selected, pos=self.cursor.realPosition(activecam), status=self.HUDstatus) else: self.decor.drawHUD(activecam, self.graph.vertices_selected, status=self.HUDstatus) if self.showCursor: # First, draw the local grid around the cursor position. # self.decor.drawLocalGrid(pos = self.cursor.realPosition(activecam), size=1, spacing=5.0, snap=5.0) glEnable(GL_CULL_FACE) glDisable(GL_TEXTURE_2D) glDisable(GL_POLYGON_SMOOTH) self.decor.drawCursor(camera=activecam, cursor=self.cursor) for d in self.drawList.values(): d.draw()
def perspCameraMove(self, camera, newPos=None, newLook=None, duration=1.0, wait=0.0): """ Moves the camera smoothly to a new position and orientation. If newLook is None, does not change the orientation of the camera. If newPos is None, does not change the position of the camera. """ from camera import Camera, OrthoCamera, X_AXIS, Y_AXIS, Z_AXIS assert (not isinstance(camera, OrthoCamera)) newCam = Camera() if newPos != None: newCam.pos = self.normalizePos(newPos) else: newCam.pos = camera.pos if newLook != None: newCam.lookAt = self.normalizePos(newLook) else: newCam.lookAt = camera.lookAt steps = int(duration * self.parent.fps) (oldTheta, oldPhi) = camera.polar() (newTheta, newPhi) = newCam.polar() deltaYaw = newTheta - oldTheta deltaPitch = newPhi - oldPhi deltaPos = diff3D(camera.pos, newCam.pos) # Check to make sure we're coming around the short side if deltaYaw > 180.0: deltaYaw = deltaYaw - 360.0 elif deltaYaw < -180.0: deltaYaw = deltaYaw + 360.0 print "DeltaYaw", deltaYaw stepYaw = deltaYaw / steps stepPitch = deltaPitch / steps stepPos = div3D(deltaPos, steps) accum = wait delay = 1.0 / self.parent.fps # Set up the animation for i in range(steps - 1): accum += delay self.post(accum, objects=( camera, ), props=( ( 'pos', add3D(camera.pos, mult3D(stepPos, i + 1)), ), ), call=( ('absrotate', (Y_AXIS, stepYaw), {}), ('rotate', (X_AXIS, stepPitch), {}), ), ) # Finish up in the correct place accum += delay self.post(accum, objects=(camera,), props=( ('pos', newCam.pos), ('lookAt', newCam.lookAt), ), ) self.signal()
def drawVertexLabels(self, parent, vxlist, labelFunc, labelStrokeWidth, labelColor, shadowColor): """ drawVertexLabels(vxlist, labelFunc, labelStrokeWidth, labelColor, shadowColor) -> void Draws labels for vertices in vxlist on an ortho projection layer. labelStrokeWidth: A float controlling the strokewidth for the label text. labelColor: A 3-tuple float color: the label text shadowColor: A 3-tuple float color: the label shadow labelFunc: A function that takes a vertex object and returns some value to use as the label for the vertex. """ # model = glGetFloat(GL_MODELVIEW_MATRIX) model = glGetDouble(GL_MODELVIEW_MATRIX) proj = glGetDouble(GL_PROJECTION_MATRIX) view = glGetInteger(GL_VIEWPORT) coords = range(len(vxlist)) ctx = parent for vnum in range(len(vxlist)): v = vxlist[vnum] # Multiply points if snapping to grid if ctx.showGrid: vpos = utilities.mult3D(v.pos, ctx.spacing) else: vpos = v.pos #print "not projected:", vpos coords[vnum] = gluProject(vpos[0], vpos[1], vpos[2], model, proj, view) # Switch to an orthogonal projection for drawing the labels glDisable(GL_LIGHTING) glMatrixMode(GL_PROJECTION) glPushMatrix() glLoadIdentity() glOrtho(view[0], view[2], view[1], view[3], 0.0, 1.0) glMatrixMode(GL_MODELVIEW) glPushMatrix() glLoadIdentity() glLineWidth(labelStrokeWidth) glDisable(GL_LINE_SMOOTH) gluLookAt(0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0) # Unproject the screen coordinates into the new ortho projection model = glGetDouble(GL_MODELVIEW_MATRIX) proj = glGetDouble(GL_PROJECTION_MATRIX) view = glGetInteger(GL_VIEWPORT) for vnum in range(len(vxlist)): v = vxlist[vnum] label = str(labelFunc(v)) if len(label) < 1 or v.hidden: continue x, y, z = coords[vnum] #print "BEFORE:", label, "at:", x, y, z trX, trY, trZ = gluUnProject(x, y, z, model, proj, view) #print "After:", label, "at:", trX, trY, trZ # Because we flatten the Z coordinate in the ortho project, # we have to manually discard Things Behind Us if trZ < 0.0: continue glPushMatrix() glTranslatef(trX, trY, 0.5) x = min(12.0 * trZ, 0.20) glScalef(x, x, x) offset = len(label) % 2 * -50.0 + -50.0 * (len(label) - 1) glTranslatef(offset, 0.0, 0.0) glTranslatef(0.0, 0.0, 0.0) # Draw the shadow glColor4f(shadowColor[0], shadowColor[1], shadowColor[2], 1.0) glPushMatrix() glTranslatef(7.5, -7.5, -0.5) for c in label: glutStrokeCharacter(GLUT_STROKE_ROMAN, ord(c)) glPopMatrix() # Draw the label glColor4f(labelColor[0], labelColor[1], labelColor[2], 1.0) glPushMatrix() for c in label: glutStrokeCharacter(GLUT_STROKE_ROMAN, ord(c)) glPopMatrix() glPopMatrix() glPopMatrix() glMatrixMode(GL_PROJECTION) glPopMatrix() glMatrixMode(GL_MODELVIEW) glEnable(GL_LIGHTING)
def onKey(self, evt): # Check to see if we have a valid context from utilities import mult3D ctx = self.parent.contexts.active if not ctx: evt.Skip() return # Mac compatibility: keycode is int. try: key = evt.KeyCode() except: key = evt.KeyCode print 'keycode:', key # Regular camera movement controls if not ctx.orthoMode: if ctx.graph.vertices_selected: orbitCentre = ctx.graph.vertices_selected[0] else: orbitCentre = ctx.graph.centerOfMass() # Multiply points if snapping to grid if ctx.showGrid: ocp = mult3D(orbitCentre.pos, ctx.spacing) else: ocp = orbitCentre.pos # Directional keys # if key == wx.WXK_LEFT: if evt.ShiftDown(): ctx.camera.absorbit(ocp, camera.Y_AXIS, -1) else: if config.current['global:fly-mode']: ctx.camera.rotate(camera.Y_AXIS, 1) else: ctx.camera.move(camera.X_AXIS, -1) elif key == wx.WXK_RIGHT: if evt.ShiftDown(): ctx.camera.absorbit(ocp, camera.Y_AXIS, 1) else: if config.current['global:fly-mode']: ctx.camera.rotate(camera.Y_AXIS, -1) else: ctx.camera.move(camera.X_AXIS, 1) elif key == wx.WXK_UP: if evt.ShiftDown(): ctx.camera.absmove(camera.Y_AXIS, 1) else: ctx.camera.move(camera.Z_AXIS, 1) elif key == wx.WXK_DOWN: if evt.ShiftDown(): ctx.camera.absmove(camera.Y_AXIS, -1) else: ctx.camera.move(camera.Z_AXIS, -1) # # Roll keys # elif key == ord(','): ctx.camera.rotate(camera.Z_AXIS, -1) elif key == ord('.'): ctx.camera.rotate(camera.Z_AXIS, 1) # # Normalize # elif key == ord('n') or key == ord('N'): ctx.camera.up = (0.0, 1.0, 0.0) # # Delete # elif key == wx.WXK_DELETE: if len(ctx.graph.vertices_selected) > 0: self.parent.sidebar.OnVertexDelete(evt) if len(ctx.graph.edges_selected) > 0: edge = ctx.graph.edges_selected[0] if isinstance(edge.source, graph.DummyVertex) or isinstance(edge.target, graph.DummyVertex): self.parent.sound.Error() else: self.parent.sidebar.OnEdgeDelete(evt) # # Vertex movement keys # elif key == ord('q') or key == ord('Q'): for v in ctx.graph.vertices_selected: ctx.graph.modVertex(v, 'shift').shift(graph.X_AXIS, 1) self.parent.sidebar.UpdateVertexPanel() elif key == ord('a') or key == ord('A'): for v in ctx.graph.vertices_selected: ctx.graph.modVertex(v, 'shift').shift(graph.X_AXIS, -1) self.parent.sidebar.UpdateVertexPanel() elif key == ord('w') or key == ord('W'): for v in ctx.graph.vertices_selected: ctx.graph.modVertex(v, 'shift').shift(graph.Y_AXIS, 1) self.parent.sidebar.UpdateVertexPanel() elif key == ord('s') or key == ord('S'): for v in ctx.graph.vertices_selected: ctx.graph.modVertex(v, 'shift').shift(graph.Y_AXIS, -1) self.parent.sidebar.UpdateVertexPanel() elif key == ord('e') or key == ord('E'): for v in ctx.graph.vertices_selected: ctx.graph.modVertex(v, 'shift').shift(graph.Z_AXIS, 1) self.parent.sidebar.UpdateVertexPanel() elif key == ord('d') or key == ord('D'): for v in ctx.graph.vertices_selected: ctx.graph.modVertex(v, 'shift').shift(graph.Z_AXIS, -1) self.parent.sidebar.UpdateVertexPanel() # Undo / Redo Keys elif key == 26: print "shift down:", evt.ShiftDown() print "Stack size:", len(ctx.UndoStack.stack) if not evt.ShiftDown(): if ctx.UndoStack.stack: print "Undo\n" ctx.UndoStack.pop(ctx.RedoStack) else: self.parent.sound.Error() else: if ctx.RedoStack.stack: print "Redo\n" ctx.RedoStack.pop(ctx.UndoStack) else: self.parent.sound.Error() # # Debugging keys # elif key == ord('z'): if ctx.graph.consistencyCheck(): print >> stderr, "Consistency check passed." elif key == ord('Z'): if evt.m_controlDown and evt.ShiftDown(): ctx.RedoStack.pop() return ctx.graph.dump() print "Theta, Phi:", ctx.camera.polar() elif key == ord('x'): def ref_func(): # Yield to let the graph canvas refresh itself. wx.Yield() if ctx.graph.vertices_selected: ctx.vertexWarp(ctx.graph.vertices_selected[0], refresh=ref_func) else: print >> stderr, "Nothing selected, not warping." elif key == ord('c'): self.vergence = self.vergence - 0.10 glMatrixMode(GL_PROJECTION) glLoadIdentity() self.resizeProjection() elif key == ord('v'): self.vergence = self.vergence + 0.10 glMatrixMode(GL_PROJECTION) glLoadIdentity() self.resizeProjection() elif key == ord('p'): self.parent.inputmgr.calibrateAll() print "calibrating!" elif key == ord('y'): self.parent.inputmgr.wandaInput2D(0, 20) elif key == ord('h'): self.parent.inputmgr.wandaInput2D(0, -20) elif key == ord('j'): from flock import BUT_UP, BUT_DOWN self.parent.inputmgr.wandaButtonLeft(BUT_DOWN) elif key == ord('J'): from flock import BUT_UP, BUT_DOWN self.parent.inputmgr.wandaButtonLeft(BUT_UP) elif key == ord('k'): from flock import BUT_UP, BUT_DOWN self.parent.inputmgr.wandaButtonMid(BUT_DOWN) elif key == ord('K'): from flock import BUT_UP, BUT_DOWN self.parent.inputmgr.wandaButtonMid(BUT_UP) elif key == ord('l'): from flock import BUT_UP, BUT_DOWN self.parent.inputmgr.wandaButtonRight(BUT_DOWN) elif key == ord('L'): from flock import BUT_UP, BUT_DOWN self.parent.inputmgr.wandaButtonRight(BUT_UP) # Rotate around center of mass elif key == ord('O'): if config.current['global:camera-orbit'] == "cw": config.current['global:camera-orbit'] = "ccw" elif config.current['global:camera-orbit'] == "ccw": config.current['global:camera-orbit'] = None else: config.current['global:camera-orbit'] = "cw" else: evt.Skip() return # Ortho camera movement controls. else: flipLR = 1 flipUD = 1 if ctx.orthoMode[0] == camera.X_AXIS: axisLR = camera.Z_AXIS axisUD = camera.Y_AXIS if ctx.orthoMode[1] < 0: flipLR = -1 elif ctx.orthoMode[0] == camera.Y_AXIS: axisLR = camera.X_AXIS axisUD = camera.Z_AXIS flipUD = -1 elif ctx.orthoMode[0] == camera.Z_AXIS: axisLR = camera.X_AXIS axisUD = camera.Y_AXIS if ctx.orthoMode[1] > 0: flipLR = -1 if key == wx.WXK_LEFT: ctx.orthocamera.move(camera.X_AXIS, -1) elif key == wx.WXK_RIGHT: ctx.orthocamera.move(camera.X_AXIS, 1) elif key == wx.WXK_UP: if evt.ShiftDown(): ctx.orthocamera.move(camera.Z_AXIS, 1) else: ctx.orthocamera.move(camera.Y_AXIS, 1) elif key == wx.WXK_DOWN: if evt.ShiftDown(): ctx.orthocamera.move(camera.Z_AXIS, -1) else: ctx.orthocamera.move(camera.Y_AXIS, -1) elif key == ord('w') or key == ord('W'): for v in ctx.graph.vertices_selected: ctx.graph.modVertex(v).shift(axisUD, 1 * flipUD) self.parent.sidebar.UpdateVertexPanel() elif key == ord('s') or key == ord('S'): for v in ctx.graph.vertices_selected: ctx.graph.modVertex(v).shift(axisUD, -1 * flipUD) self.parent.sidebar.UpdateVertexPanel() elif key == ord('a') or key == ord('A'): for v in ctx.graph.vertices_selected: ctx.graph.modVertex(v).shift(axisLR, -1 * flipLR) self.parent.sidebar.UpdateVertexPanel() elif key == ord('d') or key == ord('D'): for v in ctx.graph.vertices_selected: ctx.graph.modVertex(v).shift(axisLR, 1 * flipLR) self.parent.sidebar.UpdateVertexPanel() elif key == ord('x'): def ref_func(): # Yield to let the graph canvas refresh itself. wx.Yield() if ctx.graph.vertices_selected: ctx.vertexWarp(ctx.graph.vertices_selected[0], refresh=ref_func) else: print >> stderr, "Nothing selected, not warping." else: evt.Skip() return