class YourClass(ShowBase): def __init__(self): ShowBase.__init__(self) self.disableMouse() self.camera.setPos(campos[0], campos[1], campos[2]) self.camera.lookAt(bcenter[0], bcenter[1], bcenter[2]) self.plane = Plane(Vec3(pvector[0], pvector[1], pvector[2]), Point3(bcenter[0], bcenter[1], bcenter[2])) taskMgr.add(self.__getMousePos, "_YourClass__getMousePos") def __getMousePos(self, task): poslst = [] for mpos in (LPoint2f(-1, -1), LPoint2f(1, -1), LPoint2f(1, 1), LPoint2f(-1, 1)): pos3d = Point3() nearPoint = Point3() farPoint = Point3() base.camLens.extrude(mpos, nearPoint, farPoint) if self.plane.intersectsLine( pos3d, render.getRelativePoint(camera, nearPoint), render.getRelativePoint(camera, farPoint)): pass poslst.append(pos3d) global count count = count + 1 if count > 9: print_message(poslst) exit() else: return task.again
def getMousePlaneIntersect(self, mPos3Dref, normVec): mPos = base.mouseWatcherNode.getMouse() plane = Plane(normVec, self.grabModelNP.getPos()) nearPoint = Point3() farPoint = Point3() base.camLens.extrude(mPos, nearPoint, farPoint) if plane.intersectsLine(mPos3Dref, render.getRelativePoint(camera, nearPoint), render.getRelativePoint(camera, farPoint)): return True return False
class YourClass(ShowBase): def __init__(self): ShowBase.__init__(self) self.disableMouse() self.camera.setPos(campos[0], campos[1], campos[2]) self.camera.lookAt(bcenter[0], bcenter[1], bcenter[2]) self.plane = Plane(Vec3(pvector[0], pvector[1], pvector[2]), Point3(bcenter[0], bcenter[1], bcenter[2])) taskMgr.add(self.__getMousePos, "_YourClass__getMousePos") def __getMousePos(self, task): coords = [] for pixel in pixels: mpos = LPoint2f((pixel[0]-250)/250, (250-pixel[1])/250) pos3d = Point3() nearPoint = Point3() farPoint = Point3() base.camLens.extrude(mpos, nearPoint, farPoint) if self.plane.intersectsLine(pos3d, render.getRelativePoint(camera, nearPoint), render.getRelativePoint(camera, farPoint)): pass coords.append([pos3d[0], pos3d[1], pos3d[2]]) coordls['coord'] = coords with open(filename, "w") as lujs: json.dump(coordls, lujs) exit()
class Scene(): def __init__(self, root, loader, show_base): ''' Main scene class @param root: root node for the scene @param loader: models loader @param show_base: link to the ShowBase exemplar, i.e. base or app, which inherited from ShowBase @param path_dict: dictionary with pathes to search resources (sounds, meshes, images, shaders) type:path ''' self.root = root self.loader = loader self.show_base = show_base self.path_dict = { 'sounds': 'res', 'meshes': 'res', 'images': 'res', 'materials': 'res' } # Raw data, which should loaded from JSON file self.data_dict = { 'objects': {}, 'assets': {}, 'scene': {}, 'materials': {} } # Data after passing through import extension strored in # variables below this comment self.objects = {} self.lights = {} self.sounds = {} self.cameras = {} self.textures = {} self.meshes = {} # Container for different options which can be used by extensions self.flags = {} # Builtin variables self._current_cam_number = 0 self._level_plane = Plane(Vec3(0, 0, 1), Point3(0, 0, 0)) def get_mouse_level_pos(self, task=None): if base.mouseWatcherNode.hasMouse(): mpos = base.mouseWatcherNode.getMouse() pos3d = Point3() nearPoint = Point3() farPoint = Point3() self.show_base.camLens.extrude(mpos, nearPoint, farPoint) #if self.plane.intersectsLine(pos3d, # render.getRelativePoint(camera, nearPoint), # render.getRelativePoint(camera, farPoint)): # print "Mouse ray intersects ground plane at ", pos3d self._level_plane.intersectsLine( pos3d, render.getRelativePoint(self.show_base.camera, nearPoint), render.getRelativePoint(self.show_base.camera, farPoint)) if task: self._mouse_hit = pos3d return task.again else: return pos3d def pass_through_ext(self, action): for ext in extensions: if ext.target == 'prepare': ext.invoke(self, action) for ext in extensions: if ext.target == 'scene': ext.invoke(self, self.data_dict['scene'], action) elif ext.target == 'asset': for asset in self.data_dict['assets'].values(): ex.invoke(self, asset, action) elif ext.target == 'object': for obj in self.data_dict['objects'].values(): ext.invoke(self, obj, action) elif ext.target == 'material': for material in self.data_dict['materials'].values(): ext.invoke(self, material, action) elif ext.target not in ('prepare', 'finishing'): print 'ERROR:EXTENSION: unknown target "%s"' % ext.target for ext in extensions: if ext.target == 'finishing': ext.invoke(self, action) def load(self, fname): self.jsd_file = fname f = open(fname, 'r') data_dict = json.loads(f.read()) f.close() self.data_dict = data_dict self.pass_through_ext('LOAD') def unload(self): self.pass_through_ext('UNLOAD') def switch_camera(self, camera=None): if self.cameras: if camera: if type(camera) == int: t_cam = self.cameras.values()[camera] else: t_cam = self.cameras[camera] else: self._current_cam_number += 1 if self._current_cam_number >= len(self.cameras): self._current_cam_number = 0 t_cam = self.cameras.values()[self._current_cam_number] self.show_base.disableMouse() #self.show_base.camera.setMat(t_cam.getMat()) self.show_base.camera.reparentTo(t_cam) self.show_base.cam.node().setLens(t_cam.node().getLens()) def debug(self, frustum=True, light_pos=True, buffers=False): z = loader.loadModel('zup-axis') z.flattenStrong() if frustum: for cam in self.cameras.values(): z.copyTo(cam) cam.node().showFrustum() for light in self.lights.values(): if light_pos: z.copyTo(light['NP']) if 'shadow_cam' in light and frustum: light['shadow_cam'].node().showFrustum() if buffers: self.show_base.bufferViewer.toggleEnable() self.show_base.oobe()
class Player(GameObject): def __init__(self): GameObject.__init__(self, Vec3(0, 0, 0), "Models/PandaChan/act_p3d_chan", { "stand" : "Models/PandaChan/a_p3d_chan_idle", "walk" : "Models/PandaChan/a_p3d_chan_run" }, 5, 10, "player") self.actor.getChild(0).setH(180) mask = BitMask32() mask.setBit(1) self.collider.node().setIntoCollideMask(mask) mask = BitMask32() mask.setBit(1) self.collider.node().setFromCollideMask(mask) base.pusher.addCollider(self.collider, self.actor) base.cTrav.addCollider(self.collider, base.pusher) self.lastMousePos = Vec2(0, 0) self.groundPlane = Plane(Vec3(0, 0, 1), Vec3(0, 0, 0)) self.ray = CollisionRay(0, 0, 0, 0, 1, 0) rayNode = CollisionNode("playerRay") rayNode.addSolid(self.ray) mask = BitMask32() mask.setBit(2) rayNode.setFromCollideMask(mask) mask = BitMask32() rayNode.setIntoCollideMask(mask) self.rayNodePath = render.attachNewNode(rayNode) self.rayQueue = CollisionHandlerQueue() base.cTrav.addCollider(self.rayNodePath, self.rayQueue) self.beamModel = loader.loadModel("Models/Misc/bambooLaser") self.beamModel.reparentTo(self.actor) self.beamModel.setZ(1.5) self.beamModel.setLightOff() self.beamModel.hide() self.damagePerSecond = -5.0 self.yVector = Vec2(0, 1) self.actor.loop("stand") def update(self, keys, dt): GameObject.update(self, dt) self.walking = False if keys["up"]: self.walking = True self.velocity.addY(self.acceleration*dt) if keys["down"]: self.walking = True self.velocity.addY(-self.acceleration*dt) if keys["left"]: self.walking = True self.velocity.addX(-self.acceleration*dt) if keys["right"]: self.walking = True self.velocity.addX(self.acceleration*dt) if self.walking: standControl = self.actor.getAnimControl("stand") if standControl.isPlaying(): standControl.stop() walkControl = self.actor.getAnimControl("walk") if not walkControl.isPlaying(): self.actor.loop("walk") else: standControl = self.actor.getAnimControl("stand") if not standControl.isPlaying(): self.actor.stop("walk") self.actor.loop("stand") mouseWatcher = base.mouseWatcherNode if mouseWatcher.hasMouse(): mousePos = mouseWatcher.getMouse() else: mousePos = self.lastMousePos mousePos3D = Point3() nearPoint = Point3() farPoint = Point3() base.camLens.extrude(mousePos, nearPoint, farPoint) self.groundPlane.intersectsLine(mousePos3D, render.getRelativePoint(base.camera, nearPoint), render.getRelativePoint(base.camera, farPoint)) firingVector = Vec3(mousePos3D - self.actor.getPos()) firingVector2D = firingVector.getXy() firingVector2D.normalize() firingVector.normalize() heading = self.yVector.signedAngleDeg(firingVector2D) self.actor.setH(heading) if keys["shoot"]: if self.rayQueue.getNumEntries() > 0: self.rayQueue.sortEntries() rayHit = self.rayQueue.getEntry(0) hitPos = rayHit.getSurfacePoint(render) hitNodePath = rayHit.getIntoNodePath() if hitNodePath.hasPythonTag("owner"): hitObject = hitNodePath.getPythonTag("owner") if not isinstance(hitObject, TrapEnemy): hitObject.alterHealth(self.damagePerSecond*dt) beamLength = (hitPos - self.actor.getPos()).length() self.beamModel.setSy(beamLength) self.beamModel.show() else: self.beamModel.hide() if firingVector.length() > 0.001: self.ray.setOrigin(self.actor.getPos()) self.ray.setDirection(firingVector) self.lastMousePos = mousePos def cleanup(self): base.cTrav.removeCollider(self.rayNodePath) GameObject.cleanup(self)
class Player(GameObject): def __init__(self): GameObject.__init__( self, Vec3(0, 0, 0), "Models/PandaChan/act_p3d_chan", { "stand": "Models/PandaChan/a_p3d_chan_idle", "walk": "Models/PandaChan/a_p3d_chan_run" }, 5, 10, "player") self.actor.getChild(0).setH(180) mask = BitMask32() mask.setBit(1) self.collider.node().setIntoCollideMask(mask) mask = BitMask32() mask.setBit(1) self.collider.node().setFromCollideMask(mask) base.pusher.addCollider(self.collider, self.actor) base.cTrav.addCollider(self.collider, base.pusher) self.lastMousePos = Vec2(0, 0) self.groundPlane = Plane(Vec3(0, 0, 1), Vec3(0, 0, 0)) self.ray = CollisionRay(0, 0, 0, 0, 1, 0) rayNode = CollisionNode("playerRay") rayNode.addSolid(self.ray) mask = BitMask32() mask.setBit(2) rayNode.setFromCollideMask(mask) mask = BitMask32() rayNode.setIntoCollideMask(mask) self.rayNodePath = render.attachNewNode(rayNode) self.rayQueue = CollisionHandlerQueue() base.cTrav.addCollider(self.rayNodePath, self.rayQueue) self.beamModel = loader.loadModel("Models/Misc/bambooLaser") self.beamModel.reparentTo(self.actor) self.beamModel.setZ(1.5) self.beamModel.setLightOff() self.beamModel.hide() self.beamHitModel = loader.loadModel("Models/Misc/bambooLaserHit") self.beamHitModel.reparentTo(render) self.beamHitModel.setZ(1.5) self.beamHitModel.setLightOff() self.beamHitModel.hide() self.beamHitPulseRate = 0.15 self.beamHitTimer = 0 self.damagePerSecond = -5.0 self.score = 0 self.scoreUI = OnscreenText(text="0", pos=(-1.3, 0.825), mayChange=True, align=TextNode.ALeft) self.healthIcons = [] for i in range(self.maxHealth): icon = OnscreenImage(image="UI/health.png", pos=(-1.275 + i * 0.075, 0, 0.95), scale=0.04) icon.setTransparency(True) self.healthIcons.append(icon) self.damageTakenModel = loader.loadModel("Models/Misc/playerHit") self.damageTakenModel.setLightOff() self.damageTakenModel.setZ(1.0) self.damageTakenModel.reparentTo(self.actor) self.damageTakenModel.hide() self.damageTakenModelTimer = 0 self.damageTakenModelDuration = 0.15 self.laserSoundNoHit = loader.loadSfx("Sounds/laserNoHit.ogg") self.laserSoundNoHit.setLoop(True) self.laserSoundHit = loader.loadSfx("Sounds/laserHit.ogg") self.laserSoundHit.setLoop(True) self.beamHitLight = PointLight("beamHitLight") self.beamHitLight.setColor(Vec4(0.1, 1.0, 0.2, 1)) self.beamHitLight.setAttenuation((1.0, 0.1, 0.5)) self.beamHitLightNodePath = render.attachNewNode(self.beamHitLight) self.hurtSound = loader.loadSfx("Sounds/FemaleDmgNoise.ogg") self.yVector = Vec2(0, 1) self.actor.loop("stand") def update(self, keys, dt): GameObject.update(self, dt) self.walking = False if keys["up"]: self.walking = True self.velocity.addY(self.acceleration * dt) if keys["down"]: self.walking = True self.velocity.addY(-self.acceleration * dt) if keys["left"]: self.walking = True self.velocity.addX(-self.acceleration * dt) if keys["right"]: self.walking = True self.velocity.addX(self.acceleration * dt) if self.walking: standControl = self.actor.getAnimControl("stand") if standControl.isPlaying(): standControl.stop() walkControl = self.actor.getAnimControl("walk") if not walkControl.isPlaying(): self.actor.loop("walk") else: standControl = self.actor.getAnimControl("stand") if not standControl.isPlaying(): self.actor.stop("walk") self.actor.loop("stand") mouseWatcher = base.mouseWatcherNode if mouseWatcher.hasMouse(): mousePos = mouseWatcher.getMouse() else: mousePos = self.lastMousePos mousePos3D = Point3() nearPoint = Point3() farPoint = Point3() base.camLens.extrude(mousePos, nearPoint, farPoint) self.groundPlane.intersectsLine( mousePos3D, render.getRelativePoint(base.camera, nearPoint), render.getRelativePoint(base.camera, farPoint)) firingVector = Vec3(mousePos3D - self.actor.getPos()) firingVector2D = firingVector.getXy() firingVector2D.normalize() firingVector.normalize() heading = self.yVector.signedAngleDeg(firingVector2D) self.actor.setH(heading) self.beamHitTimer -= dt if self.beamHitTimer <= 0: self.beamHitTimer = self.beamHitPulseRate self.beamHitModel.setH(random.uniform(0.0, 360.0)) self.beamHitModel.setScale( math.sin(self.beamHitTimer * 3.142 / self.beamHitPulseRate) * 0.4 + 0.9) if keys["shoot"]: if self.rayQueue.getNumEntries() > 0: scoredHit = False self.rayQueue.sortEntries() rayHit = self.rayQueue.getEntry(0) hitPos = rayHit.getSurfacePoint(render) hitNodePath = rayHit.getIntoNodePath() if hitNodePath.hasPythonTag("owner"): hitObject = hitNodePath.getPythonTag("owner") if not isinstance(hitObject, TrapEnemy): hitObject.alterHealth(self.damagePerSecond * dt) scoredHit = True beamLength = (hitPos - self.actor.getPos()).length() self.beamModel.setSy(beamLength) self.beamModel.show() if scoredHit: if self.laserSoundNoHit.status() == AudioSound.PLAYING: self.laserSoundNoHit.stop() if self.laserSoundHit.status() != AudioSound.PLAYING: self.laserSoundHit.play() self.beamHitModel.show() self.beamHitModel.setPos(hitPos) self.beamHitLightNodePath.setPos(hitPos + Vec3(0, 0, 0.5)) if not render.hasLight(self.beamHitLightNodePath): render.setLight(self.beamHitLightNodePath) else: if self.laserSoundHit.status() == AudioSound.PLAYING: self.laserSoundHit.stop() if self.laserSoundNoHit.status() != AudioSound.PLAYING: self.laserSoundNoHit.play() if render.hasLight(self.beamHitLightNodePath): render.clearLight(self.beamHitLightNodePath) self.beamHitModel.hide() else: if render.hasLight(self.beamHitLightNodePath): render.clearLight(self.beamHitLightNodePath) self.beamModel.hide() self.beamHitModel.hide() if self.laserSoundNoHit.status() == AudioSound.PLAYING: self.laserSoundNoHit.stop() if self.laserSoundHit.status() == AudioSound.PLAYING: self.laserSoundHit.stop() if firingVector.length() > 0.001: self.ray.setOrigin(self.actor.getPos()) self.ray.setDirection(firingVector) self.lastMousePos = mousePos if self.damageTakenModelTimer > 0: self.damageTakenModelTimer -= dt self.damageTakenModel.setScale(2.0 - self.damageTakenModelTimer / self.damageTakenModelDuration) if self.damageTakenModelTimer <= 0: self.damageTakenModel.hide() def updateScore(self): self.scoreUI.setText(str(self.score)) def alterHealth(self, dHealth): GameObject.alterHealth(self, dHealth) self.updateHealthUI() self.damageTakenModel.show() self.damageTakenModel.setH(random.uniform(0.0, 360.0)) self.damageTakenModelTimer = self.damageTakenModelDuration self.hurtSound.play() def updateHealthUI(self): for index, icon in enumerate(self.healthIcons): if index < self.health: icon.show() else: icon.hide() def cleanup(self): self.scoreUI.removeNode() for icon in self.healthIcons: icon.removeNode() self.beamHitModel.removeNode() base.cTrav.removeCollider(self.rayNodePath) self.laserSoundHit.stop() self.laserSoundNoHit.stop() render.clearLight(self.beamHitLightNodePath) self.beamHitLightNodePath.removeNode() GameObject.cleanup(self)
class CameraHandler(DirectObject): def __init__(self, showbase): DirectObject.__init__(self) self.showbase = showbase self.showbase.disableMouse() # This disables the default mouse based camera control used by panda. This default control is awkward, and won't be used. self.showbase.camera.setPos(0, -150, 200) self.showbase.camera.lookAt(0, 0, 0) # Gives the camera an initial position and rotation. self.mx, self.my = 0, 0 # Sets up variables for storing the mouse coordinates self.orbiting = False # A boolean variable for specifying whether the camera is in orbiting mode. Orbiting mode refers to when the camera is being moved # because the user is holding down the right mouse button. self.target = Vec3() # sets up a vector variable for the camera's target. The target will be the coordinates that the camera is currently focusing on. self.camDist = 150 # A variable that will determine how far the camera is from it's target focus self.panRateDivisor = 10 # This variable is used as a divisor when calculating how far to move the camera when panning. Higher numbers will yield slower panning # and lower numbers will yield faster panning. This must not be set to 0. self.panZoneSize = .1 # This variable controls how close the mouse cursor needs to be to the edge of the screen to start panning the camera. It must be less than 1, # and I recommend keeping it less than .2 self.panLimitsX = Vec2(-1000, 1000) self.panLimitsY = Vec2(-1000, 1000) # These two vairables will serve as limits for how far the camera can pan, so you don't scroll away from the map. self.maxZoomOut = 500 self.maxZoomIn = 25 # These two variables set the max distance a person can zoom in or out self.orbitRate = 75 # This is the rate of speed that the camera will rotate when middle mouse is pressed and mouse moved # recommended rate 50-100 self.setTarget(0, 0, 0) # calls the setTarget function to set the current target position to the origin. self.turnCameraAroundPoint(0, 0) # calls the turnCameraAroundPoint function with a turn amount of 0 to set the camera position based on the target and camera distance self.accept("mouse2", self.startOrbit) # sets up the camrea handler to accept a right mouse click and start the "drag" mode. self.accept("mouse2-up", self.stopOrbit) # sets up the camrea handler to understand when the right mouse button has been released, and ends the "drag" mode when # the release is detected. self.storeX = 0 self.storeY = 0 # for storing of the x and y for the orbit # The next pair of lines use lambda, which creates an on-the-spot one-shot function. self.accept("wheel_up", self.zoomIn) # sets up the camera handler to detet when the mouse wheel is rolled upwards and uses a lambda function to call the # adjustCamDist function with the argument 0.9 self.accept("wheel_down", self.zoomOut) # sets up the camera handler to detet when the mouse wheel is rolled upwards and uses a lambda function to call the # adjustCamDist function with the argument 1.1 # Keys array (down if 1, up if 0) self.keys = {"cam-left": 0, "cam-right": 0, "cam-up": 0, "cam-down": 0} # Using Arrow Keys self.accept("arrow_left", self.setValue, [self.keys, "cam-left", 1]) self.accept("arrow_right", self.setValue, [self.keys, "cam-right", 1]) self.accept("arrow_up", self.setValue, [self.keys, "cam-up", 1]) self.accept("arrow_down", self.setValue, [self.keys, "cam-down", 1]) self.accept("arrow_left-up", self.setValue, [self.keys, "cam-left", 0]) self.accept("arrow_right-up", self.setValue, [self.keys, "cam-right", 0]) self.accept("arrow_up-up", self.setValue, [self.keys, "cam-up", 0]) self.accept("arrow_down-up", self.setValue, [self.keys, "cam-down", 0]) self.keyPanRate = 1.5 # pan rate for when user presses the arrow keys # set up plane for checking collision with for mouse-3d world self.plane = Plane(Vec3(0, 0, 1), Point3(0, 0, 0)) def destroy(self): self.ignoreAll() def setValue(self, array, key, value): array[key] = value def clamp(self, val, minVal, maxVal): val = min(max(val, minVal), maxVal) return val def zoomOut(self): if self.camDist <= self.maxZoomOut: self.adjustCamDist(1.1) return True def zoomIn(self): if self.camDist >= self.maxZoomIn: self.adjustCamDist(0.9) return True def turnCameraAroundPoint(self, deltaX, deltaY): # This function performs two important tasks. First, it is used for the camera orbital movement that occurs when the # right mouse button is held down. It is also called with 0s for the rotation inputs to reposition the camera during the # panning and zooming movements. # The delta inputs represent the change in rotation of the camera, which is also used to determine how far the camera # actually moves along the orbit. newCamHpr = Vec3() newCamPos = Vec3() # Creates temporary containers for the new rotation and position values of the camera. camHpr = self.showbase.camera.getHpr() # Creates a container for the current HPR of the camera and stores those values. newCamHpr.setX(camHpr.getX() + deltaX) newCamHpr.setY(self.clamp(camHpr.getY() - deltaY, -85, -10)) newCamHpr.setZ(camHpr.getZ()) # Adjusts the newCamHpr values according to the inputs given to the function. The Y value is clamped to prevent # the camera from orbiting beneath the ground plane and to prevent it from reaching the apex of the orbit, which # can cause a disturbing fast-rotation glitch. self.showbase.camera.setHpr(newCamHpr) # Sets the camera's rotation to the new values. angleradiansX = newCamHpr.getX() * (math.pi / 180.0) angleradiansY = newCamHpr.getY() * (math.pi / 180.0) # Generates values to be used in the math that will calculate the new position of the camera. newCamPos.setX(self.camDist * math.sin(angleradiansX) * math.cos(angleradiansY) + self.target.getX()) newCamPos.setY(-self.camDist * math.cos(angleradiansX) * math.cos(angleradiansY) + self.target.getY()) newCamPos.setZ(-self.camDist * math.sin(angleradiansY) + self.target.getZ()) self.showbase.camera.setPos(newCamPos.getX(), newCamPos.getY(), newCamPos.getZ()) # Performs the actual math to calculate the camera's new position and sets the camera to that position. # Unfortunately, this math is over my head, so I can't fully explain it. self.showbase.camera.lookAt(self.target.getX(), self.target.getY(), self.target.getZ()) # Points the camera at the target location. def getTarget(self): return self.target # returns the cur def setTarget(self, x, y, z): # This function is used to give the camera a new target position. x = self.clamp(x, self.panLimitsX.getX(), self.panLimitsX.getY()) self.target.setX(x) y = self.clamp(y, self.panLimitsY.getX(), self.panLimitsY.getY()) self.target.setY(y) self.target.setZ(z) # Stores the new target position values in the target variable. The x and y values are clamped to the pan limits. def setPanLimits(self, xMin, xMax, yMin, yMax): # This function is used to set the limitations of the panning movement. self.panLimitsX = (xMin, xMax) self.panLimitsY = (yMin, yMax) # Sets the inputs into the limit variables. def startOrbit(self): # This function puts the camera into orbiting mode. # Get windows properties props = WindowProperties() # Set Hide Cursor Property # props.setCursorHidden(True) # Set properties self.showbase.win.requestProperties(props) # hide cursor if self.showbase.mouseWatcherNode.hasMouse(): # We're going to use the mouse, so we have to make sure it's in the game window. If it's not and we try to use it, we'll get # a crash error. mpos = self.showbase.mouseWatcherNode.getMouse() self.storeX = mpos.getX() self.storeY = mpos.getY() # take current cursor values self.showbase.win.movePointer(0, self.showbase.win.getXSize() / 2, self.showbase.win.getYSize() / 2) # set to center self.mx = 0 self.my = 0 self.orbiting = True # Sets the orbiting variable to true to designate orbiting mode as on. def stopOrbit(self): # This function takes the camera out of orbiting mode. self.orbiting = False # Sets the orbiting variable to false to designate orbiting mode as off. self.showbase.win.movePointer( 0, int((self.storeX + 1.0) / 2 * self.showbase.win.getXSize()), int(self.showbase.win.getYSize() - ((self.storeY + 1.0) / 2 * self.showbase.win.getYSize()))) # set to taken cursor values from startOrbit if self.showbase.mouseWatcherNode.hasMouse(): # We're going to use the mouse, so we have to make sure it's in the game window. If it's not and we try to use it, we'll get # a crash error. mpos = self.showbase.mouseWatcherNode.getMouse() self.mx = mpos.getX() self.my = mpos.getY() # Get windows properties props = WindowProperties() # Set Hide Cursor Property props.setCursorHidden(False) # Set properties self.showbase.win.requestProperties(props) # reshow cursor def adjustCamDist(self, distFactor): # This function increases or decreases the distance between the camera and the target position to simulate zooming in and out. # The distFactor input controls the amount of camera movement. # For example, inputing 0.9 will set the camera to 90% of it's previous distance. self.camDist = self.camDist * distFactor # Sets the new distance into self.camDist. self.turnCameraAroundPoint(0, 0) # Calls turnCameraAroundPoint with 0s for the rotation to reset the camera to the new position. def camMoveTask(self, dt): # This task is the camera handler's work house. It's set to be called every frame and will control both orbiting and panning the camera. if self.showbase.mouseWatcherNode.hasMouse(): # We're going to use the mouse, so we have to make sure it's in the game window. If it's not and we try to use it, we'll get # a crash error. mpos = self.showbase.mouseWatcherNode.getMouse() # Gets the mouse position if self.orbiting: # Checks to see if the camera is in orbiting mode. Orbiting mode overrides panning, because it would be problematic if, while # orbiting the camera the mouse came close to the screen edge and started panning the camera at the same time. self.turnCameraAroundPoint( (self.mx - mpos.getX()) * self.orbitRate * dt, (self.my - mpos.getY()) * self.orbitRate * dt) else: # If the camera isn't in orbiting mode, we check to see if the mouse is close enough to the edge of the screen to start panning moveY = False moveX = False # these two booleans are used to denote if the camera needs to pan. X and Y refer to the mouse position that causes the # panning. X is the left or right edge of the screen, Y is the top or bottom. if self.my > (1 - self.panZoneSize): angleradiansX1 = self.showbase.camera.getH() * (math.pi / 180.0) panRate1 = (1 - self.my - self.panZoneSize) * ( self.camDist / self.panRateDivisor) moveY = True if self.my < (-1 + self.panZoneSize): angleradiansX1 = self.showbase.camera.getH() * ( math.pi / 180.0) + math.pi panRate1 = (1 + self.my - self.panZoneSize) * ( self.camDist / self.panRateDivisor) moveY = True if self.mx > (1 - self.panZoneSize): angleradiansX2 = self.showbase.camera.getH() * ( math.pi / 180.0) + math.pi * 0.5 panRate2 = (1 - self.mx - self.panZoneSize) * ( self.camDist / self.panRateDivisor) moveX = True if self.mx < (-1 + self.panZoneSize): angleradiansX2 = self.showbase.camera.getH() * ( math.pi / 180.0) - math.pi * 0.5 panRate2 = (1 + self.mx - self.panZoneSize) * ( self.camDist / self.panRateDivisor) moveX = True # These four blocks check to see if the mouse cursor is close enough to the edge of the screen to start panning and then # perform part of the math necessary to find the new camera position. Once again, the math is a bit above my head, so # I can't properly explain it. These blocks also set the move booleans to true so that the next lines will move the camera. # If up or down keys are pressed if self.keys["cam-up"] ^ self.keys["cam-down"]: moveY = True panRate1 = self.keyPanRate # Update warlock position on z plane if self.keys["cam-up"]: angleradiansX1 = self.showbase.camera.getH() * ( math.pi / 180.0) + math.pi if self.keys["cam-down"]: angleradiansX1 = self.showbase.camera.getH() * ( math.pi / 180.0) # If left or right keys are pressed if self.keys["cam-left"] ^ self.keys["cam-right"]: moveX = True panRate2 = self.keyPanRate # Update warlock position on x plane if self.keys["cam-left"]: angleradiansX2 = self.showbase.camera.getH() * ( math.pi / 180.0) + math.pi * 0.5 if self.keys["cam-right"]: angleradiansX2 = self.showbase.camera.getH() * ( math.pi / 180.0) - math.pi * 0.5 if moveY: tempX = self.target.getX( ) + math.sin(angleradiansX1) * panRate1 * dt * 50 tempX = self.clamp(tempX, self.panLimitsX.getX(), self.panLimitsX.getY()) self.target.setX(tempX) tempY = self.target.getY( ) - math.cos(angleradiansX1) * panRate1 * dt * 50 tempY = self.clamp(tempY, self.panLimitsY.getX(), self.panLimitsY.getY()) self.target.setY(tempY) self.turnCameraAroundPoint(0, 0) if moveX: tempX = self.target.getX( ) - math.sin(angleradiansX2) * panRate2 * dt * 50 tempX = self.clamp(tempX, self.panLimitsX.getX(), self.panLimitsX.getY()) self.target.setX(tempX) tempY = self.target.getY( ) + math.cos(angleradiansX2) * panRate2 * dt * 50 tempY = self.clamp(tempY, self.panLimitsY.getX(), self.panLimitsY.getY()) self.target.setY(tempY) self.turnCameraAroundPoint(0, 0) # These two blocks finalize the math necessary to find the new camera position and apply the transformation to the # camera's TARGET. Then turnCameraAroundPoint is called with 0s for rotation, and it resets the camera position based # on the position of the target. The x and y values are clamped to the pan limits before they are applied. # print self.target) self.mx = mpos.getX() self.my = mpos.getY() # The old mouse positions are updated to the current mouse position as the final step. # Finds 3d world point on the z = 0 plane for destination/target def getMouse3D(self): # make sure process has the mouse to not cause error if self.showbase.mouseWatcherNode.hasMouse(): # get screen coordinates of mouse mpos = self.showbase.mouseWatcherNode.getMouse() pos3d = Point3() nearPoint = Point3() farPoint = Point3() # find vector of cameras facing from mouse screen coordinates and get near and far points on frustrum self.showbase.camLens.extrude(mpos, nearPoint, farPoint) # check for intersection with z = 0 plane if self.plane.intersectsLine( pos3d, self.showbase.render.getRelativePoint( self.showbase.camera, nearPoint), self.showbase.render.getRelativePoint( self.showbase.camera, farPoint)): # return this position if exists return pos3d # or return (-1, -1, -1) return Vec3(-1, -1, -1)