class World(DirectObject): instance = None def __init__(self): render.setAntialias(AntialiasAttrib.MAuto) # Enable physics - perhaps this should go someplace else, but it must # be done before the Vehicle is initialized. base.enableParticles() aei = AngularEulerIntegrator() base.physicsMgr.attachAngularIntegrator(aei) SelectionEngine.getDefault().enable() SelectionManager.getDefault().enable() # Make the environment and the vehicle model. makeEnvironment() self.vehicle = Vehicle(render) MissionElement.loadElementConfig('mission_elements.plist') #layoutName = AppPreferences.get('last_layout', 'defaultLayout.plist') if len(sys.argv) == 2: layoutName = sys.argv[1] print "Using command line argument %s for layout" % layoutName else: print "Using default layout file" print "Use ./sim2.py [layout file] to use a different layout" print "Or press Ctrl+O to open a new layout in the simulator" layoutName = 'defaultLayout.plist' self.layout = MissionLayout.loadLayout(layoutName) render.attachNewNode(self.layout) self.vehicle.setLayout(self.layout) #Link the layout # Set up render buffer viewer, to aide debugging. self.accept("v", base.bufferViewer.toggleEnable) self.accept("V", base.bufferViewer.toggleEnable) base.bufferViewer.setPosition("llcorner") # Set up file saver self.accept('s', self._saveLayout) self.accept('o', self._openLayout) self.accept('f', self._setFreq) root = Tk() root.withdraw() self.modButtons = ModifierButtons() self.modButtons.addButton(KeyboardButton.control()) self.accept('control', self.modButtons.buttonDown, [KeyboardButton.control()]) self.accept('control-up', self.modButtons.buttonUp, [KeyboardButton.control()]) # Add GUI Controls ''' buttonReady = makeGeom('button_ready.png') b = DirectButton(geom = (buttonReady, makeGeom('button_click.png'), makeGeom('button_rollover.png'), buttonReady), relief = None) b.reparentTo(pixel2d) b.hide() b.setPos(base.win.getXSize()/2, 0, -base.win.getYSize()/2) b.setScale(1, 1, 1) b.bind(DirectGuiGlobals.ACCEPT, eventHandler, ['accept']) b.bind(DirectGuiGlobals.ACCEPTFAILED, eventHandler, ['accept failed']) b.bind(DirectGuiGlobals.ADJUST, eventHandler, ['adjust']) b.bind(DirectGuiGlobals.B1CLICK, eventHandler, ['b1click']) b.bind(DirectGuiGlobals.B1PRESS, eventHandler, ['b1press']) b.bind(DirectGuiGlobals.B1RELEASE, eventHandler, ['b1release']) b.bind(DirectGuiGlobals.B2CLICK, eventHandler, ['b2click']) b.bind(DirectGuiGlobals.B2PRESS, eventHandler, ['b2press']) b.bind(DirectGuiGlobals.B2RELEASE, eventHandler, ['b2release']) b.bind(DirectGuiGlobals.B3CLICK, eventHandler, ['b3click']) b.bind(DirectGuiGlobals.B3PRESS, eventHandler, ['b3press']) b.bind(DirectGuiGlobals.B3RELEASE, eventHandler, ['b3release']) b.bind(DirectGuiGlobals.ENTER, eventHandler, ['enter']) b.bind(DirectGuiGlobals.EXIT, eventHandler, ['exit']) b.bind(DirectGuiGlobals.WITHIN, eventHandler, ['within']) b.bind(DirectGuiGlobals.WITHOUT, eventHandler, ['without']) b.bind(DirectGuiGlobals.CURSORMOVE, eventHandler, ['cursormove']) # b['frameSize'] = (3, 3, 3, 3) ''' @classmethod def getInstance(cls): if cls.instance == None: cls.instance = World() return cls.instance def _saveLayout(self): if self.modButtons.isDown(KeyboardButton.control()): self.modButtons.buttonUp(KeyboardButton.control()) self.modButtons.buttonUp(KeyboardButton.asciiKey('s')) filename = asksaveasfilename(filetypes=[('plist files', '*.plist')]) if filename: self.layout.save(filename) AppPreferences.set('last_layout', filename) def _setFreq(self): #TODO: Check pinger selected pinger = None for element in self.layout.elements: if element.getTypeName() == "Pinger" and element.isSelected(): pinger = element break if pinger is None: return newfreq = askinteger("Set Pinger Frequency", "Set this pinger to which frequency? (in Hz)", initialvalue=pinger.pinger_frequency, minvalue=10000, maxvalue=50000) if newfreq is None: print "No frequency specified, aborting" return pinger.pinger_frequency = newfreq print "Frequency of pinger set to %d Hz" % newfreq def _openLayout(self): if self.modButtons.isDown(KeyboardButton.control()): self.modButtons.buttonUp(KeyboardButton.control()) self.modButtons.buttonUp(KeyboardButton.asciiKey('o')) filename = askopenfilename(filetypes=[('plist files', '*.plist')]) if filename: if self.layout: NodePath(self.layout).detachNode() self.layout = MissionLayout.loadLayout(filename) render.attachNewNode(self.layout) AppPreferences.set('last_layout', filename)
class CameraController(DirectObject): instance = None def __init__(self): self.instructionText = addInstructions(0.95, '[ESC]: Leave Mouselook mode.') self.eventDispatcher = EventDispatcher() self.cameraMode = None self.clickPos = Vec2() self.lastMousePos = Vec2() self.focus = Vec3() self.mouseDown = False self.initialPos = Vec3() self.initialHpr = Vec3() self.initialMat = None # Disable the built-in mouse camera control (it sucks). base.disableMouse() self.setCameraMode(TRACKBALL) # Set the camera's initial position. base.camera.setPosHpr(0, 12, 30, 180, -70, 0) # Turn off events generated with modifier buttons, e.g. 'shift-a' # This is to keep keyboard control working after you alt-tab out # of the app. base.mouseWatcherNode.setModifierButtons(ModifierButtons()) base.buttonThrowers[0].node().setModifierButtons(ModifierButtons()) # This is a diagonal matrix that keeps track of movement key # state. The first three diagonal entries can be 1, 0, or -1. self.mouseLookTransMat = Mat4.scaleMat(Vec3(0.0, 0.0, 0.0)) # Keep track of how many movement keys are currently pressed. This # lets us short-circuit past a lot of math when no keys are held. self.keysHeld = 0 # Handle events for the movement keys. for key, value in key2MatArgs.items(): self.accept(key, self._moveKeyHandler, value) self.accept('escape', self._escKeyHandler) self.accept('m', self._mKeyHandler) self.accept('mouse1', self._mouseDownHandler, [1]) self.accept('mouse1-up', self._mouseUpHandler, [1]) self.accept('mouse2', self._mouseDownHandler, [2]) self.accept('mouse2-up', self._mouseUpHandler, [2]) self.accept('wheel_up', self._mouseWheelHandler, [1]) self.accept('wheel_down', self._mouseWheelHandler, [-1]) self.modButtons = ModifierButtons() self.modButtons.addButton(KeyboardButton.control()) self.accept('control', self.modButtons.buttonDown, [KeyboardButton.control()]) self.accept('control-up', self.modButtons.buttonUp, [KeyboardButton.control()]) self.accept(base.win.getWindowEvent(), self._windowHandler) @classmethod def getInstance(cls): if cls.instance == None: cls.instance = cls() return cls.instance def setFocus(self, position): self.focus = position base.camera.lookAt(render, position) def addEventHandler(self, evtType, handler): self.eventDispatcher.addHandler(evtType, handler) def getCameraMode(self): return self.cameraMode def setCameraMode(self, mode): if mode == self.cameraMode: return winProps = WindowProperties() # Tear-down code for the current mode. if self.cameraMode == MOUSELOOK: winProps.setCursorHidden(False) self.removeTask(self.viewTask) elif self.cameraMode == TRACKBALL: self.removeTask(self.viewTask) # Set-up code for the new mode. if mode == MOUSELOOK: winProps.setCursorHidden(True) # Mouse accumulator. Whenever the mouse moves, it is reset to the # center of the window. The accumulator keeps track of the total # movement self.mouseAccX = 0 self.mouseAccY = 0 self.recenterMouse = True # Add a task that moves the camera based on mouse position. self.viewTask = taskMgr.add(self._mlViewTask, 'MLViewTask') self.lastFrameTime = 0 # Used to calculate dt in mlViewTask. self.instructionText.setText('[ESC]: Leave Mouselook Mode') elif mode == TRACKBALL: self.instructionText.setText('[m]: Enter Mouselook Mode') self.viewTask = taskMgr.add(self._trackballTask, 'TrackballTask') self.cameraMode = mode self.eventDispatcher.dispatchEvent(EVT_CAMERA_MODE, self) base.win.requestProperties(winProps) def _windowHandler(self, window): pos = aspect2d.find('a2dTopLeft').getPos() self.instructionText.setPos(pos.getX() + 0.05, pos.getZ() - 0.05) hasFocus = window.getProperties().getForeground() if not hasFocus: self.setCameraMode(TRACKBALL) def _escKeyHandler(self): self.setCameraMode(TRACKBALL) def _mKeyHandler(self): if self.cameraMode == MOUSELOOK: self.setCameraMode(TRACKBALL) else: self.setCameraMode(MOUSELOOK) def _mouseWheelHandler(self, arg): deltY = base.camera.getPos().length() * arg * 0.15 transl = Mat4.translateMat(0, deltY, 0) base.camera.setMat(transl * base.camera.getMat()) self.eventDispatcher.dispatchEvent(EVT_CAMERA_MOVE, base.camera) def _mouseDownHandler(self, button): if base.mouseWatcherNode.hasMouse(): if button == 2 or self.modButtons.isDown(KeyboardButton.control()): self.clickPos = Vec2(base.mouseWatcherNode.getMouse()) self.mouseDown = True offset = self.focus - base.camera.getPos() self.initialTranslation = offset.length() self.initialHpr = base.camera.getHpr() def _mouseUpHandler(self, button): self.mouseDown = False def _moveKeyHandler(self, *matArgs): self.mouseLookTransMat.setCell(*matArgs) # matArgs[2] is 0 for key release events. if (matArgs[2]): self.keysHeld += 1 else: self.keysHeld -= 1 def _trackballTask(self, task): if not self.mouseDown: return Task.cont if (base.mouseWatcherNode.hasMouse()): mpos = base.mouseWatcherNode.getMouse() if mpos == self.lastMousePos: return Task.cont mDelta = mpos - self.clickPos heading = -mDelta.x * 100 + self.initialHpr.x pitch = mDelta.y * 100 + self.initialHpr.y if pitch > 90: pitch = 90 elif pitch < -90: pitch = -90 trans1 = Mat4.translateMat(self.focus) rotx = Mat4.rotateMat(heading, Vec3(0, 0, 1)) roty = Mat4.rotateMat(pitch, Vec3(1, 0, 0)) trans2 = Mat4.translateMat(0, -self.initialTranslation, 0) rotation = trans2 * roty * rotx * trans1 base.camera.setMat(rotation) self.eventDispatcher.dispatchEvent(EVT_CAMERA_MOVE, base.camera) self.lastMousePos = Vec2(mpos) return Task.cont def _mlViewTask(self, task): t = globalClock.getFrameTime() dt = t - self.lastFrameTime self.lastFrameTime = t if (self.keysHeld): # Update camera position based on keyboard controls. T = Mat4() T.invertAffineFrom(base.camera.getMat()) cameraMoveMat = T*self.mouseLookTransMat xDir = cameraMoveMat.getCol3(0) yDir = cameraMoveMat.getCol3(1) zDir = cameraMoveMat.getCol3(2) currentPos = base.camera.getPos() nextPos = currentPos + (xDir + yDir + zDir)*(dt*8) base.camera.setPos(nextPos) self.eventDispatcher.dispatchEvent(EVT_CAMERA_MOVE, base.camera) if (base.mouseWatcherNode.hasMouse()): halfWidth = base.win.getProperties().getXSize()/2 halfHeight = base.win.getProperties().getYSize()/2 if self.recenterMouse: # Don't move the camera, but center the pointer. This is # useful when entering mouselook mode, to prevent the camera # from jumping to the pointer. heading, pitch = base.camera.getH(), base.camera.getP() self.mouseAccX = int(heading / ML_MULT) self.mouseAccY = int(pitch / ML_MULT) self.recenterMouse = False # Only do this once. else: mpos = base.mouseWatcherNode.getMouse() x, y = mpos.getX(), mpos.getY() # short-circuit if mouse hasn't moved or is outside the window. if x == 0 and y == 0 or x > 1.0 or y > 1.0: return Task.cont # Convert x and y to pixels. self.mouseAccX -= int(round(x*halfWidth)) self.mouseAccY += int(round(y*halfHeight)) base.camera.setHpr(self.mouseAccX*ML_MULT, self.mouseAccY*ML_MULT, 0.0) base.win.movePointer(0, halfWidth, halfHeight) return Task.cont
class World(DirectObject): instance = None def __init__(self): render.setAntialias(AntialiasAttrib.MAuto) # Enable physics - perhaps this should go someplace else, but it must # be done before the Vehicle is initialized. base.enableParticles() aei = AngularEulerIntegrator() base.physicsMgr.attachAngularIntegrator(aei) SelectionEngine.getDefault().enable() SelectionManager.getDefault().enable() # Make the environment and the vehicle model. makeEnvironment() self.vehicle = Vehicle(render) MissionElement.loadElementConfig('mission_elements.plist') #layoutName = AppPreferences.get('last_layout', 'defaultLayout.plist') if len(sys.argv) == 2: layoutName = sys.argv[1] print "Using command line argument %s for layout" %layoutName else: print "Using default layout file" print "Use ./sim2.py [layout file] to use a different layout" print "Or press Ctrl+O to open a new layout in the simulator" layoutName = 'defaultLayout.plist' self.layout = MissionLayout.loadLayout(layoutName) render.attachNewNode(self.layout) self.vehicle.setLayout(self.layout) #Link the layout # Set up render buffer viewer, to aide debugging. self.accept("v", base.bufferViewer.toggleEnable) self.accept("V", base.bufferViewer.toggleEnable) base.bufferViewer.setPosition("llcorner") # Set up file saver self.accept('s', self._saveLayout) self.accept('o', self._openLayout) self.accept('f', self._setFreq) root = Tk() root.withdraw() self.modButtons = ModifierButtons() self.modButtons.addButton(KeyboardButton.control()) self.accept('control', self.modButtons.buttonDown, [KeyboardButton.control()]) self.accept('control-up', self.modButtons.buttonUp, [KeyboardButton.control()]) # Add GUI Controls ''' buttonReady = makeGeom('button_ready.png') b = DirectButton(geom = (buttonReady, makeGeom('button_click.png'), makeGeom('button_rollover.png'), buttonReady), relief = None) b.reparentTo(pixel2d) b.hide() b.setPos(base.win.getXSize()/2, 0, -base.win.getYSize()/2) b.setScale(1, 1, 1) b.bind(DirectGuiGlobals.ACCEPT, eventHandler, ['accept']) b.bind(DirectGuiGlobals.ACCEPTFAILED, eventHandler, ['accept failed']) b.bind(DirectGuiGlobals.ADJUST, eventHandler, ['adjust']) b.bind(DirectGuiGlobals.B1CLICK, eventHandler, ['b1click']) b.bind(DirectGuiGlobals.B1PRESS, eventHandler, ['b1press']) b.bind(DirectGuiGlobals.B1RELEASE, eventHandler, ['b1release']) b.bind(DirectGuiGlobals.B2CLICK, eventHandler, ['b2click']) b.bind(DirectGuiGlobals.B2PRESS, eventHandler, ['b2press']) b.bind(DirectGuiGlobals.B2RELEASE, eventHandler, ['b2release']) b.bind(DirectGuiGlobals.B3CLICK, eventHandler, ['b3click']) b.bind(DirectGuiGlobals.B3PRESS, eventHandler, ['b3press']) b.bind(DirectGuiGlobals.B3RELEASE, eventHandler, ['b3release']) b.bind(DirectGuiGlobals.ENTER, eventHandler, ['enter']) b.bind(DirectGuiGlobals.EXIT, eventHandler, ['exit']) b.bind(DirectGuiGlobals.WITHIN, eventHandler, ['within']) b.bind(DirectGuiGlobals.WITHOUT, eventHandler, ['without']) b.bind(DirectGuiGlobals.CURSORMOVE, eventHandler, ['cursormove']) # b['frameSize'] = (3, 3, 3, 3) ''' @classmethod def getInstance(cls): if cls.instance == None: cls.instance = World() return cls.instance def _saveLayout(self): if self.modButtons.isDown(KeyboardButton.control()): self.modButtons.buttonUp(KeyboardButton.control()) self.modButtons.buttonUp(KeyboardButton.asciiKey('s')) filename = asksaveasfilename(filetypes=[('plist files', '*.plist')]) if filename: self.layout.save(filename) AppPreferences.set('last_layout', filename) def _setFreq(self): #TODO: Check pinger selected pinger = None for element in self.layout.elements: if element.getTypeName() == "Pinger" and element.isSelected(): pinger = element break if pinger is None: return newfreq = askinteger("Set Pinger Frequency", "Set this pinger to which frequency? (in Hz)", initialvalue=pinger.pinger_frequency, minvalue=10000, maxvalue=50000) if newfreq is None: print "No frequency specified, aborting" return pinger.pinger_frequency = newfreq print "Frequency of pinger set to %d Hz" % newfreq def _openLayout(self): if self.modButtons.isDown(KeyboardButton.control()): self.modButtons.buttonUp(KeyboardButton.control()) self.modButtons.buttonUp(KeyboardButton.asciiKey('o')) filename = askopenfilename(filetypes=[('plist files', '*.plist')]) if filename: if self.layout: NodePath(self.layout).detachNode() self.layout = MissionLayout.loadLayout(filename) render.attachNewNode(self.layout) AppPreferences.set('last_layout', filename)
class CameraController(DirectObject): instance = None def __init__(self): self.instructionText = addInstructions(0.95, '[ESC]: Leave Mouselook mode.') self.eventDispatcher = EventDispatcher() self.cameraMode = None self.clickPos = Vec2() self.lastMousePos = Vec2() self.focus = Vec3() self.mouseDown = False self.initialPos = Vec3() self.initialHpr = Vec3() self.initialMat = None # Disable the built-in mouse camera control (it sucks). base.disableMouse() self.setCameraMode(TRACKBALL) # Set the camera's initial position. base.camera.setPosHpr(0, 12, 30, 180, -70, 0) # Turn off events generated with modifier buttons, e.g. 'shift-a' # This is to keep keyboard control working after you alt-tab out # of the app. base.mouseWatcherNode.setModifierButtons(ModifierButtons()) base.buttonThrowers[0].node().setModifierButtons(ModifierButtons()) # This is a diagonal matrix that keeps track of movement key # state. The first three diagonal entries can be 1, 0, or -1. self.mouseLookTransMat = Mat4.scaleMat(Vec3(0.0, 0.0, 0.0)) # Keep track of how many movement keys are currently pressed. This # lets us short-circuit past a lot of math when no keys are held. self.keysHeld = 0 # Handle events for the movement keys. for key, value in key2MatArgs.items(): self.accept(key, self._moveKeyHandler, value) self.accept('escape', self._escKeyHandler) self.accept('m', self._mKeyHandler) self.accept('mouse1', self._mouseDownHandler, [1]) self.accept('mouse1-up', self._mouseUpHandler, [1]) self.accept('mouse2', self._mouseDownHandler, [2]) self.accept('mouse2-up', self._mouseUpHandler, [2]) self.accept('wheel_up', self._mouseWheelHandler, [1]) self.accept('wheel_down', self._mouseWheelHandler, [-1]) self.modButtons = ModifierButtons() self.modButtons.addButton(KeyboardButton.control()) self.accept('control', self.modButtons.buttonDown, [KeyboardButton.control()]) self.accept('control-up', self.modButtons.buttonUp, [KeyboardButton.control()]) self.accept(base.win.getWindowEvent(), self._windowHandler) @classmethod def getInstance(cls): if cls.instance == None: cls.instance = cls() return cls.instance def setFocus(self, position): self.focus = position base.camera.lookAt(render, position) def addEventHandler(self, evtType, handler): self.eventDispatcher.addHandler(evtType, handler) def getCameraMode(self): return self.cameraMode def setCameraMode(self, mode): if mode == self.cameraMode: return winProps = WindowProperties() # Tear-down code for the current mode. if self.cameraMode == MOUSELOOK: winProps.setCursorHidden(False) self.removeTask(self.viewTask) elif self.cameraMode == TRACKBALL: self.removeTask(self.viewTask) # Set-up code for the new mode. if mode == MOUSELOOK: winProps.setCursorHidden(True) # Mouse accumulator. Whenever the mouse moves, it is reset to the # center of the window. The accumulator keeps track of the total # movement self.mouseAccX = 0 self.mouseAccY = 0 self.recenterMouse = True # Add a task that moves the camera based on mouse position. self.viewTask = taskMgr.add(self._mlViewTask, 'MLViewTask') self.lastFrameTime = 0 # Used to calculate dt in mlViewTask. self.instructionText.setText('[ESC]: Leave Mouselook Mode') elif mode == TRACKBALL: self.instructionText.setText('[m]: Enter Mouselook Mode') self.viewTask = taskMgr.add(self._trackballTask, 'TrackballTask') self.cameraMode = mode self.eventDispatcher.dispatchEvent(EVT_CAMERA_MODE, self) base.win.requestProperties(winProps) def _windowHandler(self, window): pos = aspect2d.find('a2dTopLeft').getPos() self.instructionText.setPos(pos.getX() + 0.05, pos.getZ() - 0.05) hasFocus = window.getProperties().getForeground() if not hasFocus: self.setCameraMode(TRACKBALL) def _escKeyHandler(self): self.setCameraMode(TRACKBALL) def _mKeyHandler(self): if self.cameraMode == MOUSELOOK: self.setCameraMode(TRACKBALL) else: self.setCameraMode(MOUSELOOK) def _mouseWheelHandler(self, arg): deltY = base.camera.getPos().length() * arg * 0.15 transl = Mat4.translateMat(0, deltY, 0) base.camera.setMat(transl * base.camera.getMat()) self.eventDispatcher.dispatchEvent(EVT_CAMERA_MOVE, base.camera) def _mouseDownHandler(self, button): if base.mouseWatcherNode.hasMouse(): if button == 2 or self.modButtons.isDown(KeyboardButton.control()): self.clickPos = Vec2(base.mouseWatcherNode.getMouse()) self.mouseDown = True offset = self.focus - base.camera.getPos() self.initialTranslation = offset.length() self.initialHpr = base.camera.getHpr() def _mouseUpHandler(self, button): self.mouseDown = False def _moveKeyHandler(self, *matArgs): self.mouseLookTransMat.setCell(*matArgs) # matArgs[2] is 0 for key release events. if (matArgs[2]): self.keysHeld += 1 else: self.keysHeld -= 1 def _trackballTask(self, task): if not self.mouseDown: return Task.cont if (base.mouseWatcherNode.hasMouse()): mpos = base.mouseWatcherNode.getMouse() if mpos == self.lastMousePos: return Task.cont mDelta = mpos - self.clickPos heading = -mDelta.x * 100 + self.initialHpr.x pitch = mDelta.y * 100 + self.initialHpr.y if pitch > 90: pitch = 90 elif pitch < -90: pitch = -90 trans1 = Mat4.translateMat(self.focus) rotx = Mat4.rotateMat(heading, Vec3(0, 0, 1)) roty = Mat4.rotateMat(pitch, Vec3(1, 0, 0)) trans2 = Mat4.translateMat(0, -self.initialTranslation, 0) rotation = trans2 * roty * rotx * trans1 base.camera.setMat(rotation) self.eventDispatcher.dispatchEvent(EVT_CAMERA_MOVE, base.camera) self.lastMousePos = Vec2(mpos) return Task.cont def _mlViewTask(self, task): t = globalClock.getFrameTime() dt = t - self.lastFrameTime self.lastFrameTime = t if (self.keysHeld): # Update camera position based on keyboard controls. T = Mat4() T.invertAffineFrom(base.camera.getMat()) cameraMoveMat = T * self.mouseLookTransMat xDir = cameraMoveMat.getCol3(0) yDir = cameraMoveMat.getCol3(1) zDir = cameraMoveMat.getCol3(2) currentPos = base.camera.getPos() nextPos = currentPos + (xDir + yDir + zDir) * (dt * 8) base.camera.setPos(nextPos) self.eventDispatcher.dispatchEvent(EVT_CAMERA_MOVE, base.camera) if (base.mouseWatcherNode.hasMouse()): halfWidth = base.win.getProperties().getXSize() / 2 halfHeight = base.win.getProperties().getYSize() / 2 if self.recenterMouse: # Don't move the camera, but center the pointer. This is # useful when entering mouselook mode, to prevent the camera # from jumping to the pointer. heading, pitch = base.camera.getH(), base.camera.getP() self.mouseAccX = int(heading / ML_MULT) self.mouseAccY = int(pitch / ML_MULT) self.recenterMouse = False # Only do this once. else: mpos = base.mouseWatcherNode.getMouse() x, y = mpos.getX(), mpos.getY() # short-circuit if mouse hasn't moved or is outside the window. if x == 0 and y == 0 or x > 1.0 or y > 1.0: return Task.cont # Convert x and y to pixels. self.mouseAccX -= int(round(x * halfWidth)) self.mouseAccY += int(round(y * halfHeight)) base.camera.setHpr(self.mouseAccX * ML_MULT, self.mouseAccY * ML_MULT, 0.0) base.win.movePointer(0, halfWidth, halfHeight) return Task.cont