def __init__(self, *args, **kwargs): p3d.SingleTask.__init__(self, *args, **kwargs) self.fromCollideMask = kwargs.pop('fromCollideMask', None) self.node = None self.collEntry = None # Create collision nodes self.collTrav = CollisionTraverser() #self.collTrav.showCollisions( render ) self.collHandler = CollisionHandlerQueue() self.pickerRay = CollisionRay() # Create collision ray pickerNode = CollisionNode(self.name) pickerNode.addSolid(self.pickerRay) pickerNode.setIntoCollideMask(BitMask32.allOff()) pickerNp = self.camera.attachNewNode(pickerNode) self.collTrav.addCollider(pickerNp, self.collHandler) # Create collision mask for the ray if one is specified if self.fromCollideMask is not None: pickerNode.setFromCollideMask(self.fromCollideMask) # Bind mouse button events eventNames = ['mouse1', 'control-mouse1', 'mouse1-up'] for eventName in eventNames: self.accept(eventName, self.FireEvent, [eventName])
def leftClick(self): self.mouse1Down = True #Collision traversal pickerNode = CollisionNode('mouseRay') pickerNP = base.camera.attachNewNode(pickerNode) pickerNode.setFromCollideMask(GeomNode.getDefaultCollideMask()) pickerRay = CollisionRay() pickerNode.addSolid(pickerRay) myTraverser = CollisionTraverser() myHandler = CollisionHandlerQueue() myTraverser.addCollider(pickerNP, myHandler) if base.mouseWatcherNode.hasMouse(): mpos = base.mouseWatcherNode.getMouse() pickerRay.setFromLens(base.camNode, mpos.getX(), mpos.getY()) myTraverser.traverse(render) # Assume for simplicity's sake that myHandler is a CollisionHandlerQueue. if myHandler.getNumEntries() > 0: # This is so we get the closest object myHandler.sortEntries() pickedObj = myHandler.getEntry(0).getIntoNodePath() objTag = pickedObj.findNetTag('mouseCollisionTag').getTag('mouseCollisionTag') if objTag and len(objTag)>0: messenger.send('object_click',[objTag]) pickerNP.remove()
def __init__(self, mainClass): base.cTrav = CollisionTraverser('world') # collisionHandler = CollisionHandlerEvent() self.collisionHandler2 = CollisionHandlerQueue() pickerNode = CollisionNode('mouse ray CollisionNode') pickerNP = base.camera.attachNewNode(pickerNode) self.pickerRay = CollisionRay() pickerNode.addSolid(self.pickerRay) # base.cTrav.showCollisions(render) # The ray tag pickerNode.setTag('rays', 'ray1') base.cTrav.addCollider(pickerNP, self.collisionHandler2) self.tileSelected = (0, 0) self.unitSelected = None self.buildingSelected = None self.tempJob = None self.accept("mouse1", self.mouseClick1, [mainClass]) self.accept("mouse3", self.mouseClick3, [mainClass]) taskMgr.add(self.rayUpdate, "Mouse checking")
def setupCollisions(self): self.collTrav = CollisionTraverser() # rapid collisions detected using below plus FLUID pos self.collTrav.setRespectPrevTransform(True) self.playerGroundSphere = CollisionSphere(0, 1.5, -1.5, 1.5) self.playerGroundCol = CollisionNode('playerSphere') self.playerGroundCol.addSolid(self.playerGroundSphere) # bitmasks self.playerGroundCol.setFromCollideMask(BitMask32.bit(0)) self.playerGroundCol.setIntoCollideMask(BitMask32.allOff()) self.world.setGroundMask(BitMask32.bit(0)) self.world.setWaterMask(BitMask32.bit(0)) # and done self.playerGroundColNp = self.player.attach(self.playerGroundCol) self.playerGroundHandler = CollisionHandlerQueue() self.collTrav.addCollider(self.playerGroundColNp, self.playerGroundHandler) # DEBUG as per video: if (self.debug == True): self.playerGroundColNp.show() self.collTrav.showCollisions(self.render)
def makeNodeLocator(self, environment): meshNode = CollisionNode("NavMeshNodeLocator") meshNode.setFromCollideMask(BitMask32.allOff()) meshNode.setIntoCollideMask(OTPGlobals.PathFindingBitmask) self.polyHashToPID = {} for pId in self.polyToAngles: vertCount = 0 corners = [] for angle in self.polyToAngles[pId]: if angle != 180: # It's a corner corners.append(vertCount) vertCount += 1 # XXX this code only works for square nodes at present # Unfortunately we can only make triangle or square CollisionPolygons on the fly assert len(corners) == 4 #import pdb #pdb.set_trace() verts = [] for vert in corners: verts.append( (self.vertexCoords[self.polyToVerts[pId][vert]][0], self.vertexCoords[self.polyToVerts[pId][vert]][1], 0)) #import pdb #pdb.set_trace() poly = CollisionPolygon(verts[0], verts[1], verts[2], verts[3]) assert poly not in self.polyHashToPID self.polyHashToPID[poly] = pId meshNode.addSolid(poly) ray = CollisionRay() ray.setDirection(0, 0, -1) ray.setOrigin(0, 0, 0) rayNode = CollisionNode("NavMeshRay") rayNode.setFromCollideMask(OTPGlobals.PathFindingBitmask) rayNode.setIntoCollideMask(BitMask32.allOff()) rayNode.addSolid(ray) self.meshNodePath = environment.attachNewNode(meshNode) self.rayNodePath = environment.attachNewNode(rayNode) self.meshNodePath.setTwoSided(True) self.chq = CollisionHandlerQueue() self.traverser = CollisionTraverser() self.traverser.addCollider(self.rayNodePath, self.chq)
class RepairMousePicker: def __init__(self): self.pickerNode = CollisionNode('RepairMousePicker.pickerNode') self.pickerNP = base.cam2d.attachNewNode(self.pickerNode) self.pickerRay = CollisionRay() self.pickerNode.addSolid(self.pickerRay) self.collisionTraverser = CollisionTraverser() self.collisionHandler = CollisionHandlerQueue() self.collisionTraverser.addCollider(self.pickerNP, self.collisionHandler) self.clearCollisionMask() self.orthographic = True def destroy(self): del self.pickerNode self.pickerNP.removeNode() del self.pickerNP del self.pickerRay del self.collisionTraverser del self.collisionHandler def setOrthographic(self, ortho): self.orthographic = ortho def setCollisionMask(self, mask): self.pickerNode.setFromCollideMask(mask) def clearCollisionMask(self): self.pickerNode.setFromCollideMask(BitMask32.allOff()) def getCollisions(self, traverseRoot, useIntoNodePaths = False): if not base.mouseWatcherNode.hasMouse(): return [] mpos = base.mouseWatcherNode.getMouse() if self.orthographic: self.pickerRay.setFromLens(base.cam2d.node(), 0, 0) self.pickerNP.setPos(mpos.getX(), 0.0, mpos.getY()) else: self.pickerRay.setFromLens(base.cam2d.node(), mpos.getX(), mpos.getY()) self.pickerNP.setPos(0.0, 0.0, 0.0) self.collisionTraverser.traverse(traverseRoot) pickedObjects = [] if useIntoNodePaths: for i in range(self.collisionHandler.getNumEntries()): pickedObjects.append(self.collisionHandler.getEntry(i).getIntoNodePath()) else: for i in range(self.collisionHandler.getNumEntries()): pickedObjects.append(self.collisionHandler.getEntry(i)) return pickedObjects
def setMousePicker(self): self.picker = CollisionTraverser() self.pq = CollisionHandlerQueue() self.pickerNode = CollisionNode('mouseRay') self.pickerNP = camera.attachNewNode(self.pickerNode) self.pickerNode.setFromCollideMask(BitMask32.bit(1)) self.pickerRay = CollisionRay() self.pickerNode.addSolid(self.pickerRay) self.picker.addCollider(self.pickerNP, self.pq) self.selectable = render.attachNewNode("selectable")
def __init__(self, model, run, walk, startPos, scale): """Initialise the character. Arguments: model -- The path to the character's model file (string) run : The path to the model's run animation (string) walk : The path to the model's walk animation (string) startPos : Where in the world the character will begin (pos) scale : The amount by which the size of the model will be scaled (float) """ self.controlMap = {"left":0, "right":0, "up":0, "down":0} self.actor = Actor(Config.MYDIR+model, {"run":Config.MYDIR+run, "walk":Config.MYDIR+walk}) self.actor.reparentTo(render) self.actor.setScale(scale) self.actor.setPos(startPos) self.controller = Controller.LocalController(self) taskMgr.add(self.move,"moveTask") # Note: deriving classes DO NOT need # to add their own move tasks to the # task manager. If they override # self.move, then their own self.move # function will get called by the # task manager (they must then # explicitly call Character.move in # that function if they want it). self.prevtime = 0 self.isMoving = False # We will detect the height of the terrain by creating a collision # ray and casting it downward toward the terrain. One ray will # start above ralph's head, and the other will start above the camera. # A ray may hit the terrain, or it may hit a rock or a tree. If it # hits the terrain, we can detect the height. If it hits anything # else, we rule that the move is illegal. self.cTrav = CollisionTraverser() self.groundRay = CollisionRay() self.groundRay.setOrigin(0,0,1000) self.groundRay.setDirection(0,0,-1) self.groundCol = CollisionNode('ralphRay') self.groundCol.addSolid(self.groundRay) self.groundCol.setFromCollideMask(BitMask32.bit(1)) self.groundCol.setIntoCollideMask(BitMask32.allOff()) self.groundColNp = self.actor.attachNewNode(self.groundCol) self.groundHandler = CollisionHandlerQueue() self.cTrav.addCollider(self.groundColNp, self.groundHandler)
class RepairMousePicker: def __init__(self): self.pickerNode = CollisionNode('RepairMousePicker.pickerNode') self.pickerNP = base.cam2d.attachNewNode(self.pickerNode) self.pickerRay = CollisionRay() self.pickerNode.addSolid(self.pickerRay) self.collisionTraverser = CollisionTraverser() self.collisionHandler = CollisionHandlerQueue() self.collisionTraverser.addCollider(self.pickerNP, self.collisionHandler) self.clearCollisionMask() self.orthographic = True def destroy(self): del self.pickerNode self.pickerNP.removeNode() del self.pickerNP del self.pickerRay del self.collisionTraverser del self.collisionHandler def setOrthographic(self, ortho): self.orthographic = ortho def setCollisionMask(self, mask): self.pickerNode.setFromCollideMask(mask) def clearCollisionMask(self): self.pickerNode.setFromCollideMask(BitMask32.allOff()) def getCollisions(self, traverseRoot, useIntoNodePaths=False): if not base.mouseWatcherNode.hasMouse(): return [] mpos = base.mouseWatcherNode.getMouse() if self.orthographic: self.pickerRay.setFromLens(base.cam2d.node(), 0, 0) self.pickerNP.setPos(mpos.getX(), 0.0, mpos.getY()) else: self.pickerRay.setFromLens(base.cam2d.node(), mpos.getX(), mpos.getY()) self.pickerNP.setPos(0.0, 0.0, 0.0) self.collisionTraverser.traverse(traverseRoot) pickedObjects = [] if useIntoNodePaths: for i in range(self.collisionHandler.getNumEntries()): pickedObjects.append( self.collisionHandler.getEntry(i).getIntoNodePath()) else: for i in range(self.collisionHandler.getNumEntries()): pickedObjects.append(self.collisionHandler.getEntry(i)) return pickedObjects
def __init__(self): self.pickerNode = CollisionNode('RepairMousePicker.pickerNode') self.pickerNP = base.cam2d.attachNewNode(self.pickerNode) self.pickerRay = CollisionRay() self.pickerNode.addSolid(self.pickerRay) self.collisionTraverser = CollisionTraverser() self.collisionHandler = CollisionHandlerQueue() self.collisionTraverser.addCollider(self.pickerNP, self.collisionHandler) self.clearCollisionMask() self.orthographic = True
class Selector(object): '''A Selector listens for mouse clicks and then runs select. Select then broadcasts the selected tag (if there is one)''' def __init__(self): ''' Should the traverser be shared? ''' LOG.debug("[Selector] Initializing") # The collision traverser does the checking of solids for collisions self.cTrav = CollisionTraverser() # The collision handler queue is a simple handler that records all # detected collisions during traversal self.cHandler = CollisionHandlerQueue() self.pickerNode = CollisionNode('mouseRay') self.pickerNP = camera.attachNewNode(self.pickerNode) self.pickerNode.setFromCollideMask(GeomNode.getDefaultCollideMask()) self.pickerRay = CollisionRay() self.pickerNode.addSolid(self.pickerRay) self.cTrav.addCollider(self.pickerNP, self.cHandler) # Start listening to clicks self.resume() def select(self, event): LOG.debug("[Selector] Selecting ") if base.mouseWatcherNode.hasMouse(): mpos = base.mouseWatcherNode.getMouse() self.pickerRay.setFromLens(base.camNode, mpos.getX(), mpos.getY()) self.cTrav.traverse(render) # TODO - change this to a lower node if self.cHandler.getNumEntries() > 0: #LOG.debug("[Selector] Entries=%d"%self.cHandler.getNumEntries()) self.cHandler.sortEntries() selectionNP = self.cHandler.getEntry(0).getIntoNodePath() selection = selectionNP.findNetTag('SelectorTag').getTag( 'SelectorTag') if selection is not '': LOG.debug("[Selector] Collision with %s" % selection) Event.Dispatcher().broadcast( Event.Event('E_EntitySelect', src=self, data=selection)) else: LOG.debug("[Selector] No collision") #Event.Dispatcher().broadcast(Event.Event('E_EntityUnSelect', src=self, data=selection)) def pause(self): Event.Dispatcher().unregister(self, 'E_Mouse_1') def resume(self): print("unpausing selector") Event.Dispatcher().register(self, 'E_Mouse_1', self.select)
def init_collide(self): # why the heck he import within method from pandac.PandaModules import CollisionTraverser, CollisionNode from pandac.PandaModules import CollisionHandlerQueue, CollisionRay # init and import collision for object self.cTrav = CollisionTraverser('MousePointer') self.cQueue = CollisionHandlerQueue() self.cNode = CollisionNode('MousePointer') self.cNodePath = base.camera.attachNewNode(self.cNode) self.cNode.setFromCollideMask(GeomNode.getDefaultCollideMask()) self.cRay = CollisionRay() self.cNode.addSolid(self.cRay) self.cTrav.addCollider(self.cNodePath, self.cQueue)
def __init__(self, actor): """Initialise the camera, setting it to follow 'actor'. Arguments: actor -- The Actor that the camera will initially follow. """ self.actor = actor self.prevtime = 0 # The camera's controls: # "left" = move the camera left, 0 = off, 1 = on # "right" = move the camera right, 0 = off, 1 = on self.controlMap = {"left": 0, "right": 0} taskMgr.add(self.move, "cameraMoveTask") # Create a "floater" object. It is used to orient the camera above the # target actor's head. self.floater = NodePath(PandaNode("floater")) self.floater.reparentTo(render) # Set up the camera. base.disableMouse() base.camera.setPos(self.actor.getX(), self.actor.getY() + 2, 2) # uncomment for topdown #base.camera.setPos(self.actor.getX(),self.actor.getY()+10,2) #base.camera.setHpr(180, -50, 0) # A CollisionRay beginning above the camera and going down toward the # ground is used to detect camera collisions and the height of the # camera above the ground. A ray may hit the terrain, or it may hit a # rock or a tree. If it hits the terrain, we detect the camera's # height. If it hits anything else, the camera is in an illegal # position. self.cTrav = CollisionTraverser() self.groundRay = CollisionRay() self.groundRay.setOrigin(0, 0, 1000) self.groundRay.setDirection(0, 0, -1) self.groundCol = CollisionNode('camRay') self.groundCol.addSolid(self.groundRay) self.groundCol.setFromCollideMask(BitMask32.bit(1)) self.groundCol.setIntoCollideMask(BitMask32.allOff()) self.groundColNp = base.camera.attachNewNode(self.groundCol) self.groundHandler = CollisionHandlerQueue() self.cTrav.addCollider(self.groundColNp, self.groundHandler)
class Selector(object): '''A Selector listens for mouse clicks and then runs select. Select then broadcasts the selected tag (if there is one)''' def __init__(self): ''' Should the traverser be shared? ''' LOG.debug("[Selector] Initializing") # The collision traverser does the checking of solids for collisions self.cTrav = CollisionTraverser() # The collision handler queue is a simple handler that records all # detected collisions during traversal self.cHandler = CollisionHandlerQueue() self.pickerNode = CollisionNode('mouseRay') self.pickerNP = camera.attachNewNode(self.pickerNode) self.pickerNode.setFromCollideMask(GeomNode.getDefaultCollideMask()) self.pickerRay = CollisionRay() self.pickerNode.addSolid(self.pickerRay) self.cTrav.addCollider(self.pickerNP, self.cHandler) # Start listening to clicks self.resume() def select(self, event): LOG.debug("[Selector] Selecting ") if base.mouseWatcherNode.hasMouse(): mpos = base.mouseWatcherNode.getMouse() self.pickerRay.setFromLens(base.camNode, mpos.getX(), mpos.getY()) self.cTrav.traverse(render) # TODO - change this to a lower node if self.cHandler.getNumEntries() > 0: #LOG.debug("[Selector] Entries=%d"%self.cHandler.getNumEntries()) self.cHandler.sortEntries() selectionNP = self.cHandler.getEntry(0).getIntoNodePath() selection = selectionNP.findNetTag('SelectorTag').getTag('SelectorTag') if selection is not '': LOG.debug("[Selector] Collision with %s" % selection) Event.Dispatcher().broadcast(Event.Event('E_EntitySelect', src=self, data=selection)) else: LOG.debug("[Selector] No collision") #Event.Dispatcher().broadcast(Event.Event('E_EntityUnSelect', src=self, data=selection)) def pause(self): Event.Dispatcher().unregister(self, 'E_Mouse_1') def resume(self): print("unpausing selector") Event.Dispatcher().register(self, 'E_Mouse_1', self.select)
def __init__(self): self.keys = {} for char in string.ascii_lowercase: self.keys[char] = BUTTON_UP def makeKeyPair(ch): def keyUp(): self.keys[ch] = BUTTON_DOWN #print "%s UP" % (ch) def keyDown(): self.keys[ch] = BUTTON_UP #print "%s DOWN" % (ch) return [keyUp, keyDown] keyPair = makeKeyPair(char) self.accept(char, keyPair[0]) self.accept(char + '-up', keyPair[1]) self.accept('mouse1', self.leftClick) self.accept('mouse1-up', self.leftClickUp) self.accept('mouse2', self.mClick) self.accept('mouse2-up', self.mClickUp) self.accept('mouse3', self.rightClick) self.accept('mouse3-up', self.rightClickUp) self.mouse1Down = False self.mouse2Down = False self.mouse3Down = False self.trackMouseTimeOld = 0 self.trackMouseX = 0 self.trackMouseY = 0 self.trackMouse_Mouse1DownOld = False self.trackMouse_Mouse2DownOld = False self.trackMouse_Mouse3DownOld = False taskMgr.add(self.trackMouseTask, 'trackMouseTask') # base.cTrav = CollisionTraverser() self.pickerQ = CollisionHandlerQueue() self.pickerCollN = CollisionNode('mouseRay') self.pickerCamN = base.camera.attachNewNode(self.pickerCollN) self.pickerCollN.setFromCollideMask(BitMask32.bit(1)) self.pickerRay = CollisionRay() self.pickerCollN.addSolid(self.pickerRay) base.cTrav.addCollider(self.pickerCamN, self.pickerQ) self.objectUnderCursor = None
def createBallColliderModel(self): #creates the collider sphere around the ball cSphereRad = 9.9 self.cTrav = CollisionTraverser() #moves over all possible collisions self.ballModelSphere = CollisionSphere(0, 0, 0, cSphereRad) #collision mesh around ball is a simple sphere self.ballModelCol = CollisionNode('ballModelSphere') self.ballModelCol.addSolid(self.ballModelSphere) self.ballModelCol.setFromCollideMask(BitMask32.bit(0)) self.ballModelCol.setIntoCollideMask(BitMask32.allOff()) self.ballModelColNp = self.ballModel.attachNewNode(self.ballModelCol) self.ballModelGroundHandler = CollisionHandlerQueue() #collision handler queue stores all collision points self.cTrav.addCollider(self.ballModelColNp, self.ballModelGroundHandler)
def __init__( self, *args, **kwargs ): p3d.SingleTask.__init__( self, *args, **kwargs ) self.fromCollideMask = kwargs.pop( 'fromCollideMask', None ) self.node = None self.collEntry = None # Create collision nodes self.collTrav = CollisionTraverser() #self.collTrav.showCollisions( render ) self.collHandler = CollisionHandlerQueue() self.pickerRay = CollisionRay() # Create collision ray pickerNode = CollisionNode( self.name ) pickerNode.addSolid( self.pickerRay ) pickerNode.setIntoCollideMask( BitMask32.allOff() ) pickerNp = self.camera.attachNewNode( pickerNode ) self.collTrav.addCollider( pickerNp, self.collHandler ) # Create collision mask for the ray if one is specified if self.fromCollideMask is not None: pickerNode.setFromCollideMask( self.fromCollideMask ) # Bind mouse button events eventNames = ['mouse1', 'control-mouse1', 'mouse1-up'] for eventName in eventNames: self.accept( eventName, self.FireEvent, [eventName] )
def __init__(self,actor): self.actor = actor self.prevtime = 0 self.controlMap = {"left":0, "right":0} taskMgr.add(self.move,"cameraMoveTask") self.floater = NodePath(PandaNode("floater")) self.floater.reparentTo(render) base.disableMouse() #base.camera.setPos(self.actor.getX(),self.actor.getY()+10,2) base.camera.setPos(self.actor.getX()-30,self.actor.getY()-10,self.actor.getZ()+7) camera.setHpr(-60,0,0) self.cTrav = CollisionTraverser() self.groundRay = CollisionRay() self.groundRay.setOrigin(0,0,1000) self.groundRay.setDirection(0,0,-1) self.groundCol = CollisionNode('camRay') self.groundCol.addSolid(self.groundRay) self.groundCol.setFromCollideMask(BitMask32.bit(1)) self.groundCol.setIntoCollideMask(BitMask32.allOff()) self.groundColNp = base.camera.attachNewNode(self.groundCol) self.groundHandler = CollisionHandlerQueue() self.cTrav.addCollider(self.groundColNp, self.groundHandler) self.groundColNp.show()
def placeItem(self, item): # Add ground collision detector to the health item self.cTrav1 = CollisionTraverser() self.collectGroundRay = CollisionRay() self.collectGroundRay.setOrigin(0,0,300) self.collectGroundRay.setDirection(0,0,-1) self.collectGroundCol = CollisionNode('colRay') self.collectGroundCol.addSolid(self.collectGroundRay) self.collectGroundCol.setFromCollideMask(BitMask32.bit(1)) self.collectGroundCol.setIntoCollideMask(BitMask32.allOff()) self.collectGroundColNp = item.attachNewNode(self.collectGroundCol) self.collectGroundHandler = CollisionHandlerQueue() base.cTrav1.addCollider(self.collectGroundColNp, self.collectGroundHandler) placed = False; while placed == False: # re-randomize position item.setPos(-random.randint(-350,300),-random.randint(-100,150),0) base.cTrav1.traverse(render) # Get Z position from terrain collision entries = [] for j in range(self.collectGroundHandler.getNumEntries()): entry = self.collectGroundHandler.getEntry(j) entries.append(entry) entries.sort(lambda x,y: cmp(y.getSurfacePoint(render).getZ(), x.getSurfacePoint(render).getZ())) if (len(entries)>0) and (entries[0].getIntoNode().getName() == "terrain"): item.setZ(entries[0].getSurfacePoint(render).getZ()+4) placed = True
def __init__(self, mainClass): base.cTrav = CollisionTraverser('world') # collisionHandler = CollisionHandlerEvent() self.collisionHandler2 = CollisionHandlerQueue() pickerNode=CollisionNode('mouse ray CollisionNode') pickerNP = base.camera.attachNewNode(pickerNode) self.pickerRay=CollisionRay() pickerNode.addSolid(self.pickerRay) # base.cTrav.showCollisions(render) # The ray tag pickerNode.setTag('rays','ray1') base.cTrav.addCollider(pickerNP, self.collisionHandler2) self.tileSelected = (0,0) self.unitSelected = None self.buildingSelected = None self.tempJob = None self.accept("mouse1", self.mouseClick1, [mainClass]) self.accept("mouse3", self.mouseClick3, [mainClass]) taskMgr.add(self.rayUpdate, "Mouse checking")
def __init__(self, parserClass, mainClass, mapLoaderClass, modelLoaderClass): self.switchState = False # self.t = Timer() self.keyMap = {"left": 0, "right": 0, "forward": 0, "backward": 0} self.ralph = Actor( "data/models/units/ralph/ralph", {"run": "data/models/units/ralph/ralph-run", "walk": "data/models/units/ralph/ralph-walk"}, ) self.ralph.reparentTo(render) # self.ralph.setPos(42, 30, 0) self.ralph.setPos(6, 10, 0) self.ralph.setScale(0.1) self.accept("escape", sys.exit) self.accept("arrow_left", self.setKey, ["left", 1]) self.accept("arrow_left-up", self.setKey, ["left", 0]) self.accept("arrow_right", self.setKey, ["right", 1]) self.accept("arrow_right-up", self.setKey, ["right", 0]) self.accept("arrow_up", self.setKey, ["forward", 1]) self.accept("arrow_up-up", self.setKey, ["forward", 0]) self.accept("arrow_down", self.setKey, ["backward", 1]) self.accept("arrow_down-up", self.setKey, ["backward", 0]) self.isMoving = False self.cTrav = CollisionTraverser() self.ralphGroundRay = CollisionRay() self.ralphGroundRay.setOrigin(0, 0, 1000) self.ralphGroundRay.setDirection(0, 0, -1) self.ralphGroundCol = CollisionNode("ralphRay") self.ralphGroundCol.addSolid(self.ralphGroundRay) self.ralphGroundCol.setFromCollideMask(BitMask32.bit(0)) self.ralphGroundCol.setIntoCollideMask(BitMask32.allOff()) self.ralphGroundColNp = self.ralph.attachNewNode(self.ralphGroundCol) self.ralphGroundHandler = CollisionHandlerQueue() self.cTrav.addCollider(self.ralphGroundColNp, self.ralphGroundHandler) # self.ralphGroundCol.show() base.cam.reparentTo(self.ralph) base.cam.setPos(0, 9, 7) self.floater2 = NodePath(PandaNode("floater2")) self.floater2.reparentTo(self.ralph) self.floater2.setZ(self.floater2.getZ() + 6) base.cam.lookAt(self.floater2) # Uncomment this line to see the collision rays # self.ralphGroundColNp.show() # self.camGroundColNp.show() # Uncomment this line to show a visual representation of the # collisions occuring # self.cTrav.showCollisions(render) self.floater = NodePath(PandaNode("floater")) self.floater.reparentTo(render) taskMgr.add(self.move, "movingTask", extraArgs=[mainClass, parserClass, mapLoaderClass, modelLoaderClass])
def __init__( self, name, camera=None, rootNp=None, fromCollideMask=None, pickTag=None, gizmos=None ): p3d.Object.__init__( self, name, camera, rootNp ) self.fromCollideMask = fromCollideMask self.pickTag = pickTag self.selection = set([]) self.node = None self.np = None self.collEntry = None self.gizmos = gizmos assert self.gizmos is not None # Create a marquee self.marquee = marquee.Marquee( '%sMarquee' % self.name ) # Create collision ray self.pickerRay = CollisionRay() # Create collision node pickerNode = CollisionNode( self.name ) pickerNode.addSolid( self.pickerRay ) pickerNode.setFromCollideMask( self.fromCollideMask ) self.pickerNp = camera.attachNewNode( pickerNode ) #pickerNp.setCollideMask(AXIS_COLLISION_MASK) self.collHandler = CollisionHandlerQueue() self.collTrav = CollisionTraverser() self.collTrav.showCollisions( render ) self.collTrav.addCollider( self.pickerNp, self.collHandler ) # Bind mouse button events eventNames = ['mouse1', 'control-mouse1', 'mouse1-up'] for eventName in eventNames: self.accept( eventName, self.FireEvent, [eventName] ) #== self.selectionCol = None
def __init__( self, name, camera=None, rootNp=None, fromCollideMask=None, pickTag=None ): gizmo_core.Object.__init__( self, name, camera, rootNp ) self.fromCollideMask = fromCollideMask self.pickTag = pickTag self.selection = [] self.node = None self.collEntry = None # Create a marquee self.marquee = gizmo_core.Marquee( '%sMarquee' % self.name ) # Create collision nodes self.collTrav = CollisionTraverser() #self.collTrav.showCollisions( render ) self.collHandler = CollisionHandlerQueue() self.pickerRay = CollisionRay() # Create collision ray pickerNode = CollisionNode( self.name ) pickerNode.addSolid( self.pickerRay ) pickerNode.setIntoCollideMask( BitMask32.allOff() ) pickerNp = camera.attachNewNode( pickerNode ) self.collTrav.addCollider( pickerNp, self.collHandler ) # Create collision mask for the ray if one is specified if self.fromCollideMask is not None: pickerNode.setFromCollideMask( self.fromCollideMask ) # Bind mouse button events eventNames = ['mouse1', 'control-mouse1', 'mouse1-up'] for eventName in eventNames: self.accept( eventName, self.FireEvent, [eventName] )
class Picker(object): ''' classdocs ''' def __init__(self, camera, mouseWatcherNode, camNode, things): ''' Constructor ''' self.mouseWatcherNode = mouseWatcherNode self.camNode = camNode self.things = things self.pickerRay = CollisionRay() self.pickerNode = CollisionNode('mouseRay') self.pickerNode.setFromCollideMask(BitMask32.bit(1)) self.pickerNode.addSolid(self.pickerRay) self.pickerNP = camera.attachNewNode(self.pickerNode) self.pq = CollisionHandlerQueue() self.picker = CollisionTraverser() self.picker.addCollider(self.pickerNP, self.pq) def getMouseOn(self, mouse_x, mouse_y): #Set the position of the ray based on the mouse position self.pickerRay.setFromLens(self.camNode, mouse_x, mouse_y) self.picker.traverse(self.things.node) if self.pq.getNumEntries() > 0: #if we have hit something, sort the hits so that the closest #is first, and highlight that node self.pq.sortEntries() selectedNode = self.pq.getEntry(0).getIntoNode() selectedNodeId = selectedNode.getTag('nodeId') thingId = selectedNode.getTag('ID') mouseOnInfo = MouseOnInfo(self.things.getById(thingId), thingId, selectedNode, selectedNodeId, mouse_x, mouse_y) return mouseOnInfo
def _DistributedBanquetTable__endFireWater(self): if self.aimStart == None: return None if not self.state == "Controlled": return None if not self.avId == localAvatar.doId: return None taskMgr.remove(self.waterPowerTaskName) messenger.send("wakeup") self.aimStart = None origin = self.nozzle.getPos(render) target = self.boss.getPos(render) angle = deg2Rad(self.waterPitcherNode.getH() + 90) x = math.cos(angle) y = math.sin(angle) fireVector = Point3(x, y, 0) if self.power < 0.001: self.power = 0.001 self.lastPowerFired = self.power fireVector *= self.fireLength * self.power target = origin + fireVector segment = CollisionSegment(origin[0], origin[1], origin[2], target[0], target[1], target[2]) fromObject = render.attachNewNode(CollisionNode("pitcherColNode")) fromObject.node().addSolid(segment) fromObject.node().setFromCollideMask( ToontownGlobals.PieBitmask | ToontownGlobals.CameraBitmask | ToontownGlobals.FloorBitmask ) fromObject.node().setIntoCollideMask(BitMask32.allOff()) queue = CollisionHandlerQueue() base.cTrav.addCollider(fromObject, queue) base.cTrav.traverse(render) queue.sortEntries() self.hitObject = None if queue.getNumEntries(): entry = queue.getEntry(0) target = entry.getSurfacePoint(render) self.hitObject = entry.getIntoNodePath() base.cTrav.removeCollider(fromObject) fromObject.removeNode() self.d_firingWater(origin, target) self.fireWater(origin, target) self.resetPowerBar()
def _initCollisions(self): self._camCollRay = CollisionRay() camCollNode = CollisionNode('CameraToonRay') camCollNode.addSolid(self._camCollRay) camCollNode.setFromCollideMask(OTPGlobals.WallBitmask | OTPGlobals.CameraBitmask | ToontownGlobals.FloorEventBitmask | ToontownGlobals.CeilingBitmask) camCollNode.setIntoCollideMask(0) self._camCollNP = self._camera.attachNewNode(camCollNode) self._camCollNP.show() self._collOffset = Vec3(0, 0, 0.5) self._collHandler = CollisionHandlerQueue() self._collTrav = CollisionTraverser() self._collTrav.addCollider(self._camCollNP, self._collHandler) self._betweenCamAndToon = {} self._transNP = NodePath('trans') self._transNP.reparentTo(render) self._transNP.setTransparency(True) self._transNP.setAlphaScale(Globals.Camera.AlphaBetweenToon) self._transNP.setBin('fixed', 10000)
def Coll(self): base.cTrav = CollisionTraverser() self.collHandler = CollisionHandlerQueue() self.pickerNode = CollisionNode('mouseRay') self.pickerNP = camera.attachNewNode(self.pickerNode) self.pickerNode.setFromCollideMask(GeomNode.getDefaultCollideMask()) self.pickerRay = CollisionRay() self.pickerNode.addSolid(self.pickerRay) base.cTrav.addCollider(self.pickerNP, self.collHandler)
def __init__(self): self.picker = CollisionTraverser() self.pickerQ = CollisionHandlerQueue() pickerCollN = CollisionNode('heightChecker') self.pickerNode = render.attachNewNode(pickerCollN) pickerCollN.setFromCollideMask(BitMask32.bit(1)) pickerCollN.setIntoCollideMask(BitMask32.allOff()) self.pickerRay = CollisionRay(0,0,300,0,0,-1) pickerCollN.addSolid(self.pickerRay) self.picker.addCollider(self.pickerNode, self.pickerQ)
class heightChecker(): def __init__(self): self.picker = CollisionTraverser() self.pickerQ = CollisionHandlerQueue() pickerCollN = CollisionNode('heightChecker') self.pickerNode = render.attachNewNode(pickerCollN) pickerCollN.setFromCollideMask(BitMask32.bit(1)) pickerCollN.setIntoCollideMask(BitMask32.allOff()) self.pickerRay = CollisionRay(0,0,300,0,0,-1) pickerCollN.addSolid(self.pickerRay) self.picker.addCollider(self.pickerNode, self.pickerQ) def getHeight(self,obj,pos): res=0 self.pickerNode.setPos(pos) self.picker.traverse(obj) if self.pickerQ.getNumEntries() > 0: self.pickerQ.sortEntries() res=self.pickerQ.getEntry(0).getSurfacePoint(render).getZ() return res
def setupCollision(self): # create collision traverser self.picker = CollisionTraverser() # create collision handler self.pq = CollisionHandlerQueue() # create collision node self.pickerNode = CollisionNode('mouseRay') # create collision node # attach new collision node to camera node self.pickerNP = camera.attachNewNode( self.pickerNode) # attach collision node to camera # set bit mask to one self.pickerNode.setFromCollideMask(BitMask32.bit(1)) # set bit mask # create a collision ray self.pickerRay = CollisionRay() # create collision ray # add picker ray to the picker node self.pickerNode.addSolid( self.pickerRay) # add the collision ray to the collision node # make the traverser know about the picker node and its even handler queue self.picker.addCollider( self.pickerNP, self.pq) # add the colision node path and collision handler queue #self.picker.showCollisions( render ) # render or draw the collisions #self.pickerNP.show( ) # render picker ray # create col node self.colPlane = CollisionNode('colPlane') # add solid to col node plane self.colPlane.addSolid( CollisionPlane(Plane(Vec3(0, 0, 1), Point3(0, 0, 0)))) # attach new node to the render self.colPlanePath = render.attachNewNode(self.colPlane) #self.colPlanePath.show( ) # render node # make the col plane look at the camera # this makes it alway look at the camera no matter the orientation # we need this because the ray nees to intersect a plane parallel # to the camera self.colPlanePath.lookAt(camera) # prop up the col plane self.colPlanePath.setP(-45) # set bit mask to one # as I understand it, this makes all col nodes with bit mask one # create collisions while ignoring others of other masks self.colPlanePath.node().setIntoCollideMask(BitMask32.bit(1))
def Collision(self): self.mpos3d=0 self.plane = Plane(Vec3(0, 0, 1), Point3(0, 0, 0)) base.cTrav = CollisionTraverser() self.collHandler = CollisionHandlerQueue() self.pickerNode = CollisionNode('mouseRay') self.pickerNP = camera.attachNewNode(self.pickerNode) self.pickerNode.setFromCollideMask(GeomNode.getDefaultCollideMask()) self.pickerRay = CollisionRay() self.pickerNode.addSolid(self.pickerRay) base.cTrav.addCollider(self.pickerNP, self.collHandler)
def initialize(self): """ To setup collision detection we need: a. A CollisionNode having a ray as its solid and placed at the position of the camera while also having the same orientation as the camera. b. A new nodepath placed in the scenegraph as an immediate child of the camera. It will be used to insert the collision node in the scenegraph. c. A CollisionRay for firing rays based on mouse clicks. d. A collisions traverser. e. A collisions queue where all found collisions will be stored for later processing. """ self.traverser = CollisionTraverser('Hotspots collision traverser') self.collisionsQueue = CollisionHandlerQueue() self.pickerNode = CollisionNode('mouseRay') self.pickerRay = CollisionRay() self.pickerNode.addSolid(self.pickerRay) self.pickerNP = self.renderer.getCamera().attachNewNode( self.pickerNode) self.traverser.addCollider(self.pickerNP, self.collisionsQueue)
def __init__(self): self.picker = CollisionTraverser() self.pickerQ = CollisionHandlerQueue() pickerCollN = CollisionNode('mouseRay') pickerCamN = base.camera.attachNewNode(pickerCollN) pickerCollN.setFromCollideMask(BitMask32.bit(1)) pickerCollN.setIntoCollideMask(BitMask32.allOff()) self.pickerRay = CollisionRay() pickerCollN.addSolid(self.pickerRay) self.picker.addCollider(pickerCamN, self.pickerQ) self.accept('mouse1',self.pick)
def init_collide(self): from pandac.PandaModules import CollisionTraverser, CollisionNode from pandac.PandaModules import CollisionHandlerQueue, CollisionRay self.cTrav = CollisionTraverser('MousePointer') self.cQueue = CollisionHandlerQueue() self.cNode = CollisionNode('MousePointer') self.cNodePath = base.camera.attachNewNode(self.cNode) self.cNode.setFromCollideMask(GeomNode.getDefaultCollideMask()) self.cRay = CollisionRay() self.cNode.addSolid(self.cRay) self.cTrav.addCollider(self.cNodePath, self.cQueue)
def __init__(self): ''' Should the traverser be shared? ''' LOG.debug("[Selector] Initializing") # The collision traverser does the checking of solids for collisions self.cTrav = CollisionTraverser() # The collision handler queue is a simple handler that records all # detected collisions during traversal self.cHandler = CollisionHandlerQueue() self.pickerNode = CollisionNode('mouseRay') self.pickerNP = camera.attachNewNode(self.pickerNode) self.pickerNode.setFromCollideMask(GeomNode.getDefaultCollideMask()) self.pickerRay = CollisionRay() self.pickerNode.addSolid(self.pickerRay) self.cTrav.addCollider(self.pickerNP, self.cHandler) # Start listening to clicks self.resume()
class mouseControl(DirectObject): def __init__(self): self.picker = CollisionTraverser() self.pickerQ = CollisionHandlerQueue() pickerCollN = CollisionNode('mouseRay') pickerCamN = base.camera.attachNewNode(pickerCollN) pickerCollN.setFromCollideMask(BitMask32.bit(1)) pickerCollN.setIntoCollideMask(BitMask32.allOff()) self.pickerRay = CollisionRay() pickerCollN.addSolid(self.pickerRay) self.picker.addCollider(pickerCamN, self.pickerQ) self.accept('mouse1',self.pick) def pick(self): if base.mouseWatcherNode.hasMouse(): mpos = base.mouseWatcherNode.getMouse() self.pickerRay.setFromLens(base.camNode, mpos.getX(), mpos.getY()) self.picker.traverse(render) for i in xrange(self.pickerQ.getNumEntries()): entry=self.pickerQ.getEntry(i) player.control('replace_wp', ('goto', Vec3(entry.getSurfacePoint(render))))
def leftClick(self): self.mouse1Down = True #Collision traversal pickerNode = CollisionNode('mouseRay') pickerNP = base.camera.attachNewNode(pickerNode) pickerNode.setFromCollideMask(GeomNode.getDefaultCollideMask()) pickerRay = CollisionRay() pickerNode.addSolid(pickerRay) myTraverser = CollisionTraverser() myHandler = CollisionHandlerQueue() myTraverser.addCollider(pickerNP, myHandler) if base.mouseWatcherNode.hasMouse(): mpos = base.mouseWatcherNode.getMouse() pickerRay.setFromLens(base.camNode, mpos.getX(), mpos.getY()) myTraverser.traverse(render) # Assume for simplicity's sake that myHandler is a CollisionHandlerQueue. if myHandler.getNumEntries() > 0: # This is so we get the closest object myHandler.sortEntries() pickedObj = myHandler.getEntry(0).getIntoNodePath() objTag = pickedObj.findNetTag('mouseCollisionTag').getTag( 'mouseCollisionTag') if objTag and len(objTag) > 0: messenger.send('object_click', [objTag]) pickerNP.remove()
def __init__(self, game_data, gfx_manager): self.game_data = game_data self.gui_traverser = CollisionTraverser() self.handler = CollisionHandlerQueue() self.selectable_objects = {} for cid, model in gfx_manager.character_models.items(): new_collision_node = CollisionNode('person_' + str(cid)) new_collision_node.addSolid( CollisionTube(0, 0, 0.5, 0, 0, 1.5, 0.5)) new_collision_nodepath = model.attachNewNode(new_collision_node) new_collision_nodepath.setTag("type", "character") new_collision_nodepath.setTag("id", str(cid)) picker_node = CollisionNode('mouseRay') picker_np = camera.attachNewNode(picker_node) self.picker_ray = CollisionRay() picker_node.addSolid(self.picker_ray) self.gui_traverser.addCollider(picker_np, self.handler) self.floor = CollisionPlane(Plane(Vec3(0, 0, 1), Point3(0, 0, 0))) self.floor_np = render.attachNewNode(CollisionNode('floor')) self.floor_np.setTag("type", "ground") self.floor_np.node().addSolid(self.floor)
class Gui3D: def __init__(self, game_data, gfx_manager): self.game_data = game_data self.gui_traverser = CollisionTraverser() self.handler = CollisionHandlerQueue() self.selectable_objects = {} for cid, model in gfx_manager.character_models.items(): new_collision_node = CollisionNode('person_' + str(cid)) new_collision_node.addSolid( CollisionTube(0, 0, 0.5, 0, 0, 1.5, 0.5)) new_collision_nodepath = model.attachNewNode(new_collision_node) new_collision_nodepath.setTag("type", "character") new_collision_nodepath.setTag("id", str(cid)) picker_node = CollisionNode('mouseRay') picker_np = camera.attachNewNode(picker_node) self.picker_ray = CollisionRay() picker_node.addSolid(self.picker_ray) self.gui_traverser.addCollider(picker_np, self.handler) self.floor = CollisionPlane(Plane(Vec3(0, 0, 1), Point3(0, 0, 0))) self.floor_np = render.attachNewNode(CollisionNode('floor')) self.floor_np.setTag("type", "ground") self.floor_np.node().addSolid(self.floor) def mouse_click(self): if base.mouseWatcherNode.hasMouse(): mpos = base.mouseWatcherNode.getMouse() self.picker_ray.setFromLens(base.camNode, mpos.getX(), mpos.getY()) self.gui_traverser.traverse(render) num_entries = self.handler.getNumEntries() if num_entries > 0: self.handler.sortEntries() entry = self.handler.getEntry(0) selected = entry.getIntoNodePath() selected_type = selected.getTag("type") if selected_type == "character": self.game_data.select_character(int(selected.getTag("id"))) elif selected_type == "ground": self.game_data.click_point(entry.getSurfacePoint(render))
def __init__(self,model): # We will detect the height of the terrain by creating a collision # ray and casting it downward toward the terrain. One ray will # start above ralph's head, and the other will start above the camera. # A ray may hit the terrain, or it may hit a rock or a tree. If it # hits the terrain, we can detect the height. If it hits anything # else, we rule that the move is illegal. self.cTrav = CollisionTraverser() self.ralphGroundRay = CollisionRay() self.ralphGroundRay.setOrigin(0,0,1000) self.ralphGroundRay.setDirection(0,0,-1) self.ralphGroundCol = CollisionNode('ralphRay') self.ralphGroundCol.addSolid(self.ralphGroundRay) self.ralphGroundCol.setFromCollideMask(BitMask32.bit(0)) self.ralphGroundCol.setIntoCollideMask(BitMask32.allOff()) self.ralphGroundColNp = self.ralph.attachNewNode(self.ralphGroundCol) self.ralphGroundHandler = CollisionHandlerQueue() self.cTrav.addCollider(self.ralphGroundColNp, self.ralphGroundHandler) self.camGroundRay = CollisionRay() self.camGroundRay.setOrigin(0,0,1000) self.camGroundRay.setDirection(0,0,-1) self.camGroundCol = CollisionNode('camRay') self.camGroundCol.addSolid(self.camGroundRay) self.camGroundCol.setFromCollideMask(BitMask32.bit(0)) self.camGroundCol.setIntoCollideMask(BitMask32.allOff()) self.camGroundColNp = base.camera.attachNewNode(self.camGroundCol) self.camGroundHandler = CollisionHandlerQueue() self.cTrav.addCollider(self.camGroundColNp, self.camGroundHandler) # Uncomment this line to see the collision rays self.ralphGroundColNp.show() self.camGroundColNp.show() #Uncomment this line to show a visual representation of the #collisions occuring self.cTrav.showCollisions(render)
class Gui3D: def __init__(self, game_data, gfx_manager): self.game_data = game_data self.gui_traverser = CollisionTraverser() self.handler = CollisionHandlerQueue() self.selectable_objects = {} for cid, model in gfx_manager.character_models.items(): new_collision_node = CollisionNode('person_' + str(cid)) new_collision_node.addSolid(CollisionTube(0, 0, 0.5, 0, 0, 1.5, 0.5)) new_collision_nodepath = model.attachNewNode(new_collision_node) new_collision_nodepath.setTag("type","character") new_collision_nodepath.setTag("id",str(cid)) picker_node = CollisionNode('mouseRay') picker_np = camera.attachNewNode(picker_node) self.picker_ray = CollisionRay() picker_node.addSolid(self.picker_ray) self.gui_traverser.addCollider(picker_np, self.handler) self.floor = CollisionPlane(Plane(Vec3(0, 0, 1), Point3(0, 0, 0))) self.floor_np = render.attachNewNode(CollisionNode('floor')) self.floor_np.setTag("type", "ground") self.floor_np.node().addSolid(self.floor) def mouse_click(self): if base.mouseWatcherNode.hasMouse(): mpos = base.mouseWatcherNode.getMouse() self.picker_ray.setFromLens(base.camNode, mpos.getX(), mpos.getY()) self.gui_traverser.traverse(render) num_entries = self.handler.getNumEntries() if num_entries > 0: self.handler.sortEntries() entry = self.handler.getEntry(0) selected = entry.getIntoNodePath() selected_type = selected.getTag("type") if selected_type == "character": self.game_data.select_character(int(selected.getTag("id"))) elif selected_type == "ground": self.game_data.click_point(entry.getSurfacePoint(render))
def __init__(self,actor): """Initialise the camera, setting it to follow 'actor'. Arguments: actor -- The Actor that the camera will initially follow. """ self.actor = actor self.prevtime = 0 # The camera's controls: # "left" = move the camera left, 0 = off, 1 = on # "right" = move the camera right, 0 = off, 1 = on self.controlMap = {"left":0, "right":0} taskMgr.add(self.move,"cameraMoveTask") # Create a "floater" object. It is used to orient the camera above the # target actor's head. self.floater = NodePath(PandaNode("floater")) self.floater.reparentTo(render) # Set up the camera. base.disableMouse() base.camera.setPos(self.actor.getX(),self.actor.getY()+2, 2) # uncomment for topdown #base.camera.setPos(self.actor.getX(),self.actor.getY()+10,2) #base.camera.setHpr(180, -50, 0) # A CollisionRay beginning above the camera and going down toward the # ground is used to detect camera collisions and the height of the # camera above the ground. A ray may hit the terrain, or it may hit a # rock or a tree. If it hits the terrain, we detect the camera's # height. If it hits anything else, the camera is in an illegal # position. self.cTrav = CollisionTraverser() self.groundRay = CollisionRay() self.groundRay.setOrigin(0,0,1000) self.groundRay.setDirection(0,0,-1) self.groundCol = CollisionNode('camRay') self.groundCol.addSolid(self.groundRay) self.groundCol.setFromCollideMask(BitMask32.bit(1)) self.groundCol.setIntoCollideMask(BitMask32.allOff()) self.groundColNp = base.camera.attachNewNode(self.groundCol) self.groundHandler = CollisionHandlerQueue() self.cTrav.addCollider(self.groundColNp, self.groundHandler)
def initialize_collision_handling(self): self.collision_handling_mutex = Lock() self.cTrav = CollisionTraverser() self.groundRay = CollisionRay() self.groundRay.setOrigin(0,0,1000) self.groundRay.setDirection(0,0,-1) self.groundCol = CollisionNode(self.attach_object.name + "_collision_node") self.groundCol.setIntoCollideMask(BitMask32.bit(0)) self.groundCol.setFromCollideMask(BitMask32.bit(0)) self.groundCol.addSolid(self.groundRay) self.groundColNp = self.attach_object.render_model.attachNewNode(self.groundCol) self.groundHandler = CollisionHandlerQueue() self.cTrav.addCollider(self.groundColNp, self.groundHandler)
def __init__(self, model, run, walk, startPos, scale,select,saysome): self.playerGUI = saysome print(self.playerGUI.getpausevalue()) self.controlMap = {"left":0, "right":0, "forward":0} self.select = select self.actor = Actor(model, {"run":run, "walk":walk}) self.actor.reparentTo(render) self.actor.setScale(scale) self.actor.setPos(startPos) self.actor.setHpr(90,0,0) taskMgr.add(self.move,"moveTask") self.prevtime = 0 self.isMoving = False self.cTrav = CollisionTraverser() self.groundRay = CollisionRay(0,0,1000,0,0,-1) self.groundCol = CollisionNode('ralphRay') self.groundCol.addSolid(self.groundRay) self.groundCol.setFromCollideMask(BitMask32.bit(1)) self.groundCol.setIntoCollideMask(BitMask32.allOff()) self.groundColNp = self.actor.attachNewNode(self.groundCol) self.groundHandler = CollisionHandlerQueue() self.cTrav.addCollider(self.groundColNp, self.groundHandler) self.sphere = CollisionSphere(0,0,0,3) self.spherecol = CollisionNode('ralphSphere') self.spherecol.addSolid(self.sphere) self.spherecol.setFromCollideMask(BitMask32.bit(1)) self.spherecol.setIntoCollideMask(BitMask32.allOff()) self.ralphcolhs = self.actor.attachNewNode(self.spherecol) self.ralphcolhandler = CollisionHandlerQueue() self.cTrav.addCollider(self.ralphcolhs , self.ralphcolhandler)
def __init__(self): self.keys = {} for char in string.ascii_lowercase: self.keys[char] = BUTTON_UP def makeKeyPair(ch): def keyUp(): self.keys[ch] = BUTTON_DOWN #print "%s UP" % (ch) def keyDown(): self.keys[ch] = BUTTON_UP #print "%s DOWN" % (ch) return [keyUp, keyDown] keyPair = makeKeyPair(char) self.accept(char,keyPair[0]) self.accept(char+'-up',keyPair[1]) self.accept('mouse1',self.leftClick) self.accept('mouse1-up',self.leftClickUp) self.accept('mouse2',self.mClick) self.accept('mouse2-up',self.mClickUp) self.accept('mouse3',self.rightClick) self.accept('mouse3-up',self.rightClickUp) self.mouse1Down = False self.mouse2Down = False self.mouse3Down = False self.trackMouseTimeOld = 0 self.trackMouseX = 0 self.trackMouseY = 0 self.trackMouse_Mouse1DownOld = False self.trackMouse_Mouse2DownOld = False self.trackMouse_Mouse3DownOld = False taskMgr.add(self.trackMouseTask, 'trackMouseTask') # base.cTrav = CollisionTraverser() self.pickerQ = CollisionHandlerQueue() self.pickerCollN = CollisionNode('mouseRay') self.pickerCamN = base.camera.attachNewNode(self.pickerCollN) self.pickerCollN.setFromCollideMask(BitMask32.bit(1)) self.pickerRay = CollisionRay() self.pickerCollN.addSolid(self.pickerRay) base.cTrav.addCollider(self.pickerCamN, self.pickerQ) self.objectUnderCursor = None
def __init__( self, bit=[PICKABLE] ): global OBJECTIDMAPPING #Since we are using collision detection to do picking, we set it up like #any other collision detection system with a traverser and a handler self.picker = CollisionTraverser() #Make a traverser self.pq = CollisionHandlerQueue() #Make a handler #Make a collision node for our picker ray self.pickerNode = CollisionNode('mouseRay') #Attach that node to the camera since the ray will need to be positioned #relative to it self.pickerNP = base.camera.attachNewNode(self.pickerNode) #Everything to be picked will use bit 1. This way if we were doing other #collision we could seperate it self.pickerNode.setFromCollideMask(bitMaskOr(bit)) self.pickerRay = CollisionRay() #Make our ray self.pickerNode.addSolid(self.pickerRay) #Add it to the collision node #Register the ray as something that can cause collisions self.picker.addCollider(self.pickerNP, self.pq)
def createCollisionHandlers(self): # Create a new collision traverser instance. We will use this to determine # if any collisions occurred after performing movement. self.cTrav = CollisionTraverser() camGroundRay = CollisionRay() camGroundRay.setOrigin(0, 0, 1000) camGroundRay.setDirection(0, 0, -1) camGroundCol = CollisionNode('camRay') camGroundCol.addSolid(camGroundRay) camGroundCol.setFromCollideMask(BitMask32.bit(0)) camGroundCol.setIntoCollideMask(BitMask32.allOff()) camGroundColNp = base.camera.attachNewNode(camGroundCol) self.camGroundHandler = CollisionHandlerQueue() self.cTrav.addCollider(camGroundColNp, self.camGroundHandler) # register the collision pusher self.pusher = CollisionHandlerPusher() # register collision event pattern names self.pusher.addInPattern('col-%fn-into')
def createRay(self, obj, ent, name, show=False, x=0, y=0, z=0, dx=0, dy=0, dz=-1): #create queue obj.queue = CollisionHandlerQueue() #create ray obj.rayNP = ent.attachNewNode(CollisionNode(name)) obj.ray = CollisionRay(x, y, z, dx, dy, dz) obj.rayNP.node().addSolid(obj.ray) obj.rayNP.node().setFromCollideMask(GeomNode.getDefaultCollideMask()) sandbox.pickTrav.addCollider(obj.rayNP, obj.queue) if show: obj.rayNP.show()
def setupCollisions(self): self.coll_trav = CollisionTraverser() self.player_ground_sphere = CollisionSphere(0, 1.5, -1.5, 1.5) self.player_ground_col = CollisionNode('playerSphere') self.player_ground_col.addSolid(self.player_ground_sphere) # bitmasks self.player_ground_col.setFromCollideMask(BitMask32.bit(0)) self.player_ground_col.setIntoCollideMask(BitMask32.allOff()) self.world.setCollideMask(BitMask32.bit(0)) self.water.setCollideMask(BitMask32.bit(0)) # and done self.player_ground_col_np = self.player.attachNewNode(self.player_ground_col) self.player_ground_handler = CollisionHandlerQueue() self.coll_trav.addCollider(self.player_ground_col_np, self.player_ground_handler) # DEBUG if self.debug: self.player_ground_col_np.show() self.coll_trav.showCollisions(self.render)
def __endFireWater(self): if self.aimStart == None: return if not self.state == 'Controlled': return if not self.avId == localAvatar.doId: return taskMgr.remove(self.waterPowerTaskName) messenger.send('wakeup') self.aimStart = None origin = self.nozzle.getPos(render) target = self.boss.getPos(render) angle = deg2Rad(self.waterPitcherNode.getH() + 90) x = math.cos(angle) y = math.sin(angle) fireVector = Point3(x, y, 0) if self.power < 0.001: self.power = 0.001 self.lastPowerFired = self.power fireVector *= self.fireLength * self.power target = origin + fireVector segment = CollisionSegment(origin[0], origin[1], origin[2], target[0], target[1], target[2]) fromObject = render.attachNewNode(CollisionNode('pitcherColNode')) fromObject.node().addSolid(segment) fromObject.node().setFromCollideMask(ToontownGlobals.PieBitmask | ToontownGlobals.CameraBitmask | ToontownGlobals.FloorBitmask) fromObject.node().setIntoCollideMask(BitMask32.allOff()) queue = CollisionHandlerQueue() base.cTrav.addCollider(fromObject, queue) base.cTrav.traverse(render) queue.sortEntries() self.hitObject = None if queue.getNumEntries(): entry = queue.getEntry(0) target = entry.getSurfacePoint(render) self.hitObject = entry.getIntoNodePath() base.cTrav.removeCollider(fromObject) fromObject.removeNode() self.d_firingWater(origin, target) self.fireWater(origin, target) self.resetPowerBar() return
def __init__(self, name, world, pos): ActorNode.__init__(self, name) self.nodePath = NodePath(self) self.world = world # init the model or the Actor self.model = self.getModel() self.model.reparentTo(self.nodePath) self.nodePath.setPos(*pos) self.prevPos = self.nodePath.getPos() # collision detection fromObject = self.nodePath.attachNewNode(CollisionNode(name)) self.addSolids(fromObject) fromObject.show() # setup the ground ray, needed for detecting the ground groundRay = CollisionRay() groundRay.setOrigin(0, 0, 1000) groundRay.setDirection(0, 0, -1) groundCol = CollisionNode('groundRay') groundCol.addSolid(groundRay) groundCol.setFromCollideMask(BitMask32.bit(0)) groundCol.setIntoCollideMask(BitMask32.allOff()) groundColNp = base.camera.attachNewNode(groundCol) self.groundHandler = CollisionHandlerQueue() self.world.cTrav.addCollider(groundColNp, self.groundHandler) # self.world.cTrav.addCollider(fromObject, self.world.pusher) # self.world.pusher.addCollider(fromObject, self.nodePath) self.postInit()
class NavMesh(object): notify = directNotify.newCategory("NavMesh") def __init__(self, filepath=None, filename=None): if filename is not None: self._initFromFilename(filepath, filename) def initFromPolyData(self, polyToVerts, vertToPolys, polyToAngles, vertexCoords, environmentHash): ''' Initialize the mesh from a set of polygons. polyToVerts: Dictionary mapping a polygon ID to a set of N vertex IDs vertToPolys: Dictionary mapping a vertex ID to a set of poly IDs (of every poly that includes it) polyToAngles: Dictionary mapping a polygon ID to a set of N angles (in vertex order) vertexCoords: Dictionary mapping a vertex ID to the coordinates of the vertex in worldspace environmentHash: Hash value derived from the same collision geometry as the other arguments. See AreaMapper.getEnvironmentHash(). ''' self.polyToVerts = polyToVerts self.vertToPolys = vertToPolys self.polyToAngles = polyToAngles self.vertexCoords = vertexCoords self.environmentHash = environmentHash self.connectionLookup = {} self.connections = [] self._discoverInitialConnectivity() self.optimizeMesh() def visualize(self, parentNodePath, highlightVerts=[], pathVerts=[], visitedVerts=[]): ''' XXX Should move this into a product-specific class. ''' gFormat = GeomVertexFormat.getV3cp() self.visVertexData = GeomVertexData("OMGVERTEXDATA2", gFormat, Geom.UHDynamic) self.visVertexWriter = GeomVertexWriter(self.visVertexData, "vertex") self.visVertexColorWriter = GeomVertexWriter(self.visVertexData, "color") vertToWriterIndex = {} currIndex = 0 for v in self.vertexCoords.keys(): vertToWriterIndex[v] = currIndex x = self.vertexCoords[v][0] y = self.vertexCoords[v][1] z = self.vertexCoords[v][2] self.visVertexWriter.addData3f(x, y, z + 0.5) if v in highlightVerts: self.visVertexColorWriter.addData4f(1.0, 0.0, 0.0, 1.0) elif v in visitedVerts: self.visVertexColorWriter.addData4f(0.0, 0.0, 1.0, 1.0) else: self.visVertexColorWriter.addData4f(1.0, 1.0, 0.0, 1.0) currIndex += 1 pathOffsetIntoIndex = currIndex for v in pathVerts: self.visVertexWriter.addData3f(v[0], v[1], v[2] + 0.5) self.visVertexColorWriter.addData4f(0.0, 1.0, 0.0, 1.0) currIndex += 1 lines = GeomLinestrips(Geom.UHStatic) for p in self.polyToVerts.keys(): for v in self.polyToVerts[p]: lines.addVertex(vertToWriterIndex[v]) lines.addVertex(vertToWriterIndex[self.polyToVerts[p][0]]) lines.closePrimitive() if len(pathVerts) > 0: for i in xrange(len(pathVerts)): lines.addVertex(pathOffsetIntoIndex + i) lines.closePrimitive() self.visGeom = Geom(self.visVertexData) self.visGeom.addPrimitive(lines) self.visGN = GeomNode("NavMeshVis") self.visGN.addGeom(self.visGeom) self.visNodePath = parentNodePath.attachNewNode(self.visGN) self.visNodePath.setTwoSided(True) def _discoverInitialConnectivity(self): print "Building initial connectivity graph..." for pId in self.polyToVerts.keys(): verts = self.polyToVerts[pId] numVerts = len(verts) candidates = [] neighborPolys = [] for v in verts: candidates += [ p for p in self.vertToPolys[v] if (p not in candidates) and (p != pId) ] for vNum in xrange(numVerts): neighbor = [p for p in candidates if ((verts[vNum] in self.polyToVerts[p]) and \ (verts[(vNum+1)%numVerts] in self.polyToVerts[p]))] if len(neighbor) == 0: neighborPolys.append(None) elif len(neighbor) == 1: neighborPolys.append(neighbor[0]) else: raise "Two neighbors found for the same edge?!?!" self.connectionLookup[pId] = neighborPolys # --------- Begin stitching code --------- def _attemptToMergePolys(self, polyA, polyB): newVerts = [] newAngles = [] newConnections = [] vertsA = self.polyToVerts[polyA] vertsB = self.polyToVerts[polyB] lenA = len(vertsA) lenB = len(vertsB) anglesA = self.polyToAngles[polyA] anglesB = self.polyToAngles[polyB] sharedVerts = [v for v in vertsA if (v in vertsB)] locA = 0 while vertsA[locA] not in sharedVerts: locA += 1 while vertsA[locA] in sharedVerts: locA = (locA - 1) % lenA locA = (locA + 1) % lenA CCWmost = vertsA[locA] CCWmostLocA = locA while vertsA[locA] in sharedVerts: locA = (locA + 1) % lenA locA = (locA - 1) % lenA CWmost = vertsA[locA] CWmostLocA = locA # Convexity Check. # Verify that removing the edge preserves convexity and bail out if not. locA = 0 locB = 0 while vertsA[locA] != CCWmost: locA += 1 while vertsB[locB] != CCWmost: locB += 1 CCWmostAngleSum = anglesA[locA] + anglesB[locB] CCWmostLocB = locB if CCWmostAngleSum > 180: return False locA = 0 locB = 0 while vertsA[locA] != CWmost: locA += 1 while vertsB[locB] != CWmost: locB += 1 CWmostAngleSum = anglesA[locA] + anglesB[locB] if CWmostAngleSum > 180: return False # We've found the CW-most vert of the shared edge. # Now walk A clockwise until we hit the CCW-most vert of the shared edge. newVerts.append(CWmost) newAngles.append(CWmostAngleSum) newConnections.append(self.connectionLookup[polyA][locA]) locA = (locA + 1) % lenA while vertsA[locA] != CCWmost: newVerts.append(vertsA[locA]) newAngles.append(anglesA[locA]) newConnections.append(self.connectionLookup[polyA][locA]) locA = (locA + 1) % lenA # Now we've hit the CCW-most vert of the shared edge. # Walk B clockwise until we get back to the CW-most vert of the shared edge. locB = CCWmostLocB newVerts.append(CCWmost) newAngles.append(CCWmostAngleSum) neighbor = self.connectionLookup[polyB][locB] newConnections.append(neighbor) if neighbor is not None: for i in xrange(len(self.connectionLookup[neighbor])): if self.connectionLookup[neighbor][i] == polyB: self.connectionLookup[neighbor][i] = polyA locB = (locB + 1) % lenB while vertsB[locB] != CWmost: newVerts.append(vertsB[locB]) newAngles.append(anglesB[locB]) neighbor = self.connectionLookup[polyB][locB] newConnections.append(neighbor) if neighbor is not None: for i in xrange(len(self.connectionLookup[neighbor])): if self.connectionLookup[neighbor][i] == polyB: self.connectionLookup[neighbor][i] = polyA locB = (locB + 1) % lenB # We've added every vertex, its proper angle, and connectivity info # to the new polygon. Now replace A with the new guy and remove B. self.polyToVerts[polyA] = newVerts self.polyToAngles[polyA] = newAngles self.connectionLookup[polyA] = newConnections # Make sure we have vertex->poly pointers for all the new verts we added to A. for v in newVerts: if polyA not in self.vertToPolys[v]: self.vertToPolys[v].append(polyA) # Clean up all of B's old vertices. for v in vertsB: self.vertToPolys[v].remove(polyB) if len(self.vertToPolys[v]) == 0: # No one's using this vertex anymore, remove it del self.vertToPolys[v] del self.vertexCoords[v] del self.polyToVerts[polyB] del self.polyToAngles[polyB] del self.connectionLookup[polyB] return True def _attemptToGrowPoly(self, pId): for neighbor in self.connectionLookup.get(pId, []): if (neighbor is not None) and self._attemptToMergePolys( pId, neighbor): return True return False def _growEachPolyOnce(self): grewAtLeastOne = False for pId in self.connectionLookup.keys(): if self._attemptToGrowPoly(pId): grewAtLeastOne = True return grewAtLeastOne def optimizeMesh(self): ''' Takes a mesh that is already functionally complete and optimizes it for better performance. Reduces poly count and cuts out redundant vertices. Also compacts the polygon IDs into a contiguous range from 0 to N. No need to do the same for vertex IDs yet. ''' '''print "Stitching polygons: %s -> " % (len(self.polyToVerts)), orig = len(self.polyToVerts) numPasses = 1 while self._growEachPolyOnce(): print "%s -> " % (len(self.polyToVerts)), numPasses += 1 print "Done!\nPoly count reduced to %0.1f%% of original." % (len(self.polyToVerts)/float(orig)*100.0)''' self._pruneExtraVerts() self._compactPolyIds() self.numNodes = len(self.connections) biggest = 0 biggestPoly = -1 for p in self.polyToVerts: if len(self.polyToVerts[p]) > biggest: biggest = len(self.polyToVerts[p]) biggestPoly = p print "Most verts in a single poly: ", biggest assert biggest < 256 def _cleanPoly(self, polyId): verts = self.polyToVerts[polyId] angles = self.polyToAngles[polyId] neighbors = self.connectionLookup[polyId] numVerts = len(verts) newVerts = [] newAngles = [] newNeighbors = [] for i in xrange(numVerts): if (angles[i] != 180) or \ (len(self.vertToPolys.get(verts[i],[])) > 2) or \ (neighbors[i] != neighbors[(i-1)%numVerts]): # Keep vertex newVerts.append(verts[i]) newAngles.append(angles[i]) newNeighbors.append(neighbors[i]) else: # Remove vertex, this will happen twice so pop it self.vertToPolys.pop(verts[i], None) self.vertexCoords.pop(verts[i], None) if len(verts) != len(newVerts): self.polyToVerts[polyId] = newVerts self.polyToAngles[polyId] = newAngles self.connectionLookup[polyId] = newNeighbors assert len(newVerts) < 256 def _pruneExtraVerts(self): print "Pruning extra vertices..." print "Starting verts: %s" % len(self.vertToPolys) for polyId in self.connectionLookup.keys(): self._cleanPoly(polyId) print "Ending verts: %s" % len(self.vertToPolys) def _compactPolyIds(self): polyList = self.polyToVerts.keys() polyList.sort() oldToNewId = {None: None} newPolyToVerts = {} newPolyToAngles = {} self.connections = [] currId = 0 for oldId in polyList: oldToNewId[oldId] = currId self.connections.append([]) currId += 1 for oldId in polyList: newPolyToVerts[oldToNewId[oldId]] = self.polyToVerts[oldId] newPolyToAngles[oldToNewId[oldId]] = self.polyToAngles[oldId] #self.connections[oldToNewId[oldId]] = [] for edgeNum in xrange(len(self.connectionLookup[oldId])): self.connections[oldToNewId[oldId]].append( oldToNewId[self.connectionLookup[oldId][edgeNum]]) self.polyToVerts = newPolyToVerts self.polyToAngles = newPolyToAngles del self.connectionLookup # --------- Begin pathfinding code --------- def _findCentroid(self, polyId): verts = self.polyToVerts[polyId] numVerts = len(verts) x = 0 y = 0 z = 0 for v in verts: x += self.vertexCoords[v][0] y += self.vertexCoords[v][1] z += self.vertexCoords[v][2] x /= numVerts y /= numVerts z /= numVerts return (x, y, z) ## def _estimateDistanceBetweenPolys(self, polyA, polyB): ## centroidA = self._findCentroid(polyA) ## centroidB = self._findCentroid(polyB) ## dx = centroidA[0] - centroidB[0] ## dy = centroidA[1] - centroidB[1] ## dz = centroidA[2] - centroidB[2] ## return math.sqrt(dx*dx + dy*dy + dz*dz) def _walkToNeighbor(self, currPoly, neighborPoly): currVerts = self.polyToVerts[currPoly] neighborVerts = self.polyToVerts[neighborPoly] lenCurr = len(currVerts) sharedVerts = [v for v in currVerts if (v in neighborVerts)] loc = 0 while currVerts[loc] not in sharedVerts: loc += 1 while currVerts[loc] in sharedVerts: loc = (loc - 1) % lenCurr loc = (loc + 1) % lenCurr CCWmost = currVerts[loc] CCWmostLoc = loc while currVerts[loc] in sharedVerts: loc = (loc + 1) % lenCurr loc = (loc - 1) % lenCurr CWmost = currVerts[loc] CCWmostCoords = self.vertexCoords[CCWmost] CWmostCoords = self.vertexCoords[CWmost] # For now, walk to the midpoint of the connecting edge departingEdge = CCWmostLoc # Don't need this with goal->start search neighborsEdge = 0 while self.connections[neighborPoly][neighborsEdge] != currPoly: neighborsEdge += 1 return (neighborsEdge, ((CWmostCoords[0] + CCWmostCoords[0]) / 2.0, (CWmostCoords[1] + CCWmostCoords[1]) / 2.0, (CWmostCoords[2] + CCWmostCoords[2]) / 2.0)) ## def _remakePath(self,walkBack,currNode): ## if currNode in walkBack: ## p = self._remakePath(walkBack,walkBack[currNode]) ## return p + [currNode,] ## return [currNode,] ## def findRoute(self, startNode, goalNode): ## ''' ## So much love for A*. ## ''' ## nodeToF = {} ## nodeToG = {} ## nodeToH = {} ## walkBack = {} ## #nodeToEntryPoint = {} ## self.nodeToEntryPoint[startNode] = self._findCentroid(startNode) ## nodeToG[startNode] = 0 ## nodeToH[startNode] = self._estimateDistanceBetweenPolys(startNode,goalNode) ## nodeToF[startNode] = nodeToG[startNode] + nodeToH[startNode] ## closedSet = {} ## openSet = {} ## openQueue = PriQueue() # Priority = F score ## openSet[startNode] = 1 ## openQueue.push((nodeToF[startNode],startNode)) ## goalPoint = self._findCentroid(goalNode) ## while len(openSet) > 0: ## f,currNode = openQueue.pop(0) ## del openSet[currNode] ## self.aStarWasHere[currNode] = 1 ## if currNode == goalNode: ## return self._remakePath(walkBack,currNode) ## closedSet[currNode] = 1 ## currPoint = self.nodeToEntryPoint[currNode] ## for neighbor in self.connections[currNode]: ## if (neighbor is not None) and (neighbor not in closedSet): ## departingEdge,newEntryPoint = self._walkToNeighbor(currNode,currPoint,neighbor) ## newG = nodeToG[currNode] + math.sqrt((newEntryPoint[0] - currPoint[0])**2 + \ ## (newEntryPoint[1] - currPoint[1])**2 + \ ## (newEntryPoint[2] - currPoint[2])**2) ## gotHereFasterThanBefore = False ## if neighbor not in openSet: ## openSet[neighbor] = 1 ## gotHereFasterThanBefore = True ## elif newG < nodeToG[neighbor]: ## openQueue.remove((nodeToF[neighbor],neighbor)) ## gotHereFasterThanBefore = True ## if gotHereFasterThanBefore: ## walkBack[neighbor] = currNode ## self.nodeToEntryPoint[neighbor] = newEntryPoint ## nodeToH[neighbor] = math.sqrt((goalPoint[0] - newEntryPoint[0])**2 + \ ## (goalPoint[1] - newEntryPoint[1])**2 + \ ## (goalPoint[2] - newEntryPoint[2])**2) ## nodeToG[neighbor] = newG ## nodeToF[neighbor] = nodeToG[neighbor] + nodeToH[neighbor] ## openQueue.push((nodeToF[neighbor],neighbor)) ## raise "No path found! D:" def _findAllRoutesToGoal(self, goalNode): ''' Find the shortest path from ALL start nodes to the given goal node. (Djikstra) After running, self.pathData[startNode][goalNode] == outgoing edge from startNode to the next node for the given value of goalNode and ALL values of startNode. ''' nodeToG = {} walkBack = {} nodeDeparturePoint = {} nodeDeparturePoint[goalNode] = self._findCentroid(goalNode) nodeToG[goalNode] = 0 closedSet = {} openSet = {} openQueue = PriQueue() openSet[goalNode] = 1 openQueue.push((nodeToG[goalNode], goalNode)) walkBack[goalNode] = (0, goalNode) while len(openSet) > 0: f, currNode = openQueue.pop(0) del openSet[currNode] closedSet[currNode] = 1 currPoint = nodeDeparturePoint[currNode] for neighbor in self.connections[currNode]: if (neighbor is not None) and (neighbor not in closedSet): neighborsEdge, newPoint = self._walkToNeighbor( currNode, neighbor) newG = nodeToG[currNode] + math.sqrt((newPoint[0] - currPoint[0])**2 + \ (newPoint[1] - currPoint[1])**2 + \ (newPoint[2] - currPoint[2])**2) gotHereFasterThanBefore = False if neighbor not in openSet: openSet[neighbor] = 1 gotHereFasterThanBefore = True elif newG < nodeToG[neighbor]: openQueue.remove((nodeToG[neighbor], neighbor)) gotHereFasterThanBefore = True if gotHereFasterThanBefore: walkBack[neighbor] = (neighborsEdge, currNode) nodeDeparturePoint[neighbor] = newPoint nodeToG[neighbor] = newG openQueue.push((nodeToG[neighbor], neighbor)) for startNode in xrange(len(self.connections)): departingEdge = walkBack[startNode][0] assert self.pathData[startNode][goalNode] is None self.pathData[startNode][goalNode] = departingEdge def generatePathData(self, rowRange=None): ''' Entry point for path preprocessing. Solves all pairs shortest path for this mesh. Stores the result in self.pathData. SLOW. Expect 8-10 minutes on Port Royal alone. Currently runs Djikstra on every possible start node. There are faster approaches for APSP, but... ''' if rowRange is None: rowRange = (0, self.numNodes) self.initPathData() for goalNode in xrange(rowRange[0], rowRange[1]): self._findAllRoutesToGoal(goalNode) def createPathTable(self): ''' Takes a 2D array self.pathData and changes it in place. Each row is changed into a run-length encoded string. Then, feeds the data into a new PathTable instance. ''' for row in self.pathData: for val in row: if val == None: raise "Incomplete path data!" shortestPathLookup = self.pathData self.pathData = [] # Run-Length Encode the whole thing! for start in xrange(self.numNodes): row = [] lastVal = None nodesInRow = 0 for goal in xrange(self.numNodes): val = shortestPathLookup[start][goal] if val != lastVal: row.append([goal, val]) lastVal = val nodesInRow += 1 else: nodesInRow += 1 assert nodesInRow == self.numNodes stringsRow = [] # Convert row to a bytestring to save space for item in row: assert item[0] < 65536 assert item[1] < 256 stringsRow.append( chr(item[0] / 256) + chr(item[0] % 256) + chr(item[1])) assert len(stringsRow[-1]) == 3 rowString = string.join(stringsRow, "") self.pathData.append(rowString) self.pathTable = PathTable(self.pathData, self.connections) def printPathData(self): ''' Outputs the pickled path table to stdout. ''' import sys sys.stdout.write(pickle.dumps(self.pathData, protocol=0)) def initPathData(self): self.pathData = [] for i in xrange(self.numNodes): self.pathData.append([ None, ] * self.numNodes) def addPaths(self, partialData): for i in xrange(len(partialData)): for j in xrange(len(partialData[i])): if partialData[i][j] is not None: assert self.pathData[i][j] is None self.pathData[i][j] = partialData[i][j] ## def pathTableLookup(self, startNode, goalNode): ## ''' ## Look up the equivalent of pathData[goalNode][startNode] in our run-length encoded data. ## ''' ## if startNode >= self.numNodes or goalNode >= self.numNodes: ## raise "Invalid node ID. Must be less than self.numNodes (%s)." % self.numNodes ## str = self.pathData[startNode] ## pos = 0 ## while (pos < len(str)) and (256*ord(str[pos]) + ord(str[pos+1]) <= goalNode): ## #print pos, ": ",256*ord(str[pos]) + ord(str[pos+1]) ## pos += 3 ## pos -= 3 ## return ord(str[pos+2]) def findRoute(self, startNode, goalNode): ''' Returns the node-by-node route from startNode to goalNode. ''' return self.pathTable.findRoute(startNode, goalNode) def makeNodeLocator(self, environment): meshNode = CollisionNode("NavMeshNodeLocator") meshNode.setFromCollideMask(BitMask32.allOff()) meshNode.setIntoCollideMask(OTPGlobals.PathFindingBitmask) self.polyHashToPID = {} for pId in self.polyToAngles: vertCount = 0 corners = [] for angle in self.polyToAngles[pId]: if angle != 180: # It's a corner corners.append(vertCount) vertCount += 1 # XXX this code only works for square nodes at present # Unfortunately we can only make triangle or square CollisionPolygons on the fly assert len(corners) == 4 #import pdb #pdb.set_trace() verts = [] for vert in corners: verts.append( (self.vertexCoords[self.polyToVerts[pId][vert]][0], self.vertexCoords[self.polyToVerts[pId][vert]][1], 0)) #import pdb #pdb.set_trace() poly = CollisionPolygon(verts[0], verts[1], verts[2], verts[3]) assert poly not in self.polyHashToPID self.polyHashToPID[poly] = pId meshNode.addSolid(poly) ray = CollisionRay() ray.setDirection(0, 0, -1) ray.setOrigin(0, 0, 0) rayNode = CollisionNode("NavMeshRay") rayNode.setFromCollideMask(OTPGlobals.PathFindingBitmask) rayNode.setIntoCollideMask(BitMask32.allOff()) rayNode.addSolid(ray) self.meshNodePath = environment.attachNewNode(meshNode) self.rayNodePath = environment.attachNewNode(rayNode) self.meshNodePath.setTwoSided(True) self.chq = CollisionHandlerQueue() self.traverser = CollisionTraverser() self.traverser.addCollider(self.rayNodePath, self.chq) def findNodeFromPos(self, environment, x, y): self.rayNodePath.setPos(environment, x, y, 50000) self.chq.clearEntries() self.traverser.traverse(self.meshNodePath) if self.chq.getNumEntries() != 1: self.notify.warning("No node found at position: %s, %s in %s" % (x, y, environment)) return 0 e = self.chq.getEntry(0) assert e.hasInto() if not e.hasInto(): self.notify.warning("No into found for collision %s" % (e)) pId = self.polyHashToPID[e.getInto()] return pId # --------- Begin long-term storage code --------- def writeToFile(self, filename, storePathTable=True): ''' Output the contents of this mesh to the file specified. Saving to a file lets us avoid doing expensive precomputation every time a mesh instance is required. ''' if self.environmentHash is None: raise "Attempted write to file without valid environment hash!" if storePathTable and not self.pathData: raise "Attempted to write empty pathData. Call NavMesh.generatePathTable() first!" f = open(filename, 'wb') if storePathTable: pickle.dump([ self.environmentHash, self.polyToVerts, self.polyToAngles, self.vertexCoords, self.connections, self.pathData ], f, protocol=2) f.close() self.pathData = None else: pickle.dump([ self.environmentHash, self.polyToVerts, self.polyToAngles, self.vertexCoords, self.connections, None ], f, protocol=2) f.close() print "Successfully wrote to file %s." % filename def _initFromString(self, str): contents = pickle.loads(str) self.environmentHash = contents[0] self.polyToVerts = contents[1] self.polyToAngles = contents[2] self.vertexCoords = contents[3] self.connections = contents[4] self.pathData = contents[5] if self.pathData is not None: self.pathTable = PathTable(self.pathData, self.connections) self.pathData = None self.numNodes = len(self.connections) def _initFromFilename(self, filepath, filename): vfs = VirtualFileSystem.getGlobalPtr() filename = Filename(filename) searchPath = DSearchPath() #searchPath.appendDirectory(Filename('.')) #searchPath.appendDirectory(Filename('etc')) #searchPath.appendDirectory(Filename.fromOsSpecific(os.path.expandvars('~'))) #searchPath.appendDirectory(Filename.fromOsSpecific(os.path.expandvars('$HOME'))) searchPath.appendDirectory( Filename.fromOsSpecific(os.path.expandvars(filepath))) found = vfs.resolveFilename(filename, searchPath) if not found: raise IOError, "File not found!" str = vfs.readFile(filename, 1) self._initFromString(str) def checkHash(self, envHash): ''' "Does this mesh represent the environment I think it does?" If this check fails, the mesh is out of date (or being used with the wrong environment). In either case, whoever generated this instance should discard it and create a new mesh from scratch. ''' return envHash == self.environmentHash
class MousePicker(p3d.SingleTask): """ Class to represent a ray fired from the input camera lens using the mouse. """ def __init__(self, *args, **kwargs): p3d.SingleTask.__init__(self, *args, **kwargs) self.fromCollideMask = kwargs.pop('fromCollideMask', None) self.node = None self.collEntry = None # Create collision nodes self.collTrav = CollisionTraverser() #self.collTrav.showCollisions( render ) self.collHandler = CollisionHandlerQueue() self.pickerRay = CollisionRay() # Create collision ray pickerNode = CollisionNode(self.name) pickerNode.addSolid(self.pickerRay) pickerNode.setIntoCollideMask(BitMask32.allOff()) pickerNp = self.camera.attachNewNode(pickerNode) self.collTrav.addCollider(pickerNp, self.collHandler) # Create collision mask for the ray if one is specified if self.fromCollideMask is not None: pickerNode.setFromCollideMask(self.fromCollideMask) # Bind mouse button events eventNames = ['mouse1', 'control-mouse1', 'mouse1-up'] for eventName in eventNames: self.accept(eventName, self.FireEvent, [eventName]) def OnUpdate(self, task, x=None, y=None): # Update the ray's position if self.mouseWatcherNode.hasMouse(): mp = self.mouseWatcherNode.getMouse() x, y = mp.getX(), mp.getY() if x is None or y is None: return self.pickerRay.setFromLens(self.camera.node(), x, y) # Traverse the hierarchy and find collisions self.collTrav.traverse(self.rootNp) if self.collHandler.getNumEntries(): # If we have hit something, sort the hits so that the closest is first self.collHandler.sortEntries() collEntry = self.collHandler.getEntry(0) node = collEntry.getIntoNode() # If this node is different to the last node, send a mouse leave # event to the last node, and a mouse enter to the new node if node != self.node: if self.node is not None: messenger.send('%s-mouse-leave' % self.node.getName(), [self.collEntry]) messenger.send('%s-mouse-enter' % node.getName(), [collEntry]) # Send a message containing the node name and the event over name, # including the collision entry as arguments messenger.send('%s-mouse-over' % node.getName(), [collEntry]) # Keep these values self.collEntry = collEntry self.node = node elif self.node is not None: # No collisions, clear the node and send a mouse leave to the last # node that stored messenger.send('%s-mouse-leave' % self.node.getName(), [self.collEntry]) self.node = None def FireEvent(self, event): """ Send a message containing the node name and the event name, including the collision entry as arguments. """ if self.node is not None: messenger.send('%s-%s' % (self.node.getName(), event), [self.collEntry]) def GetFirstNodePath(self): """ Return the first node in the collision queue if there is one, None otherwise. """ if self.collHandler.getNumEntries(): collEntry = self.collHandler.getEntry(0) return collEntry.getIntoNodePath() return None
class CogdoFlyingCameraManager: def __init__(self, cam, parent, player, level): self._toon = player.toon self._camera = cam self._parent = parent self._player = player self._level = level self._enabled = False def enable(self): if self._enabled: return self._toon.detachCamera() self._prevToonY = 0.0 levelBounds = self._level.getBounds() l = Globals.Camera.LevelBoundsFactor self._bounds = ((levelBounds[0][0] * l[0], levelBounds[0][1] * l[0]), (levelBounds[1][0] * l[1], levelBounds[1][1] * l[1]), (levelBounds[2][0] * l[2], levelBounds[2][1] * l[2])) self._lookAtZ = self._toon.getHeight( ) + Globals.Camera.LookAtToonHeightOffset self._camParent = NodePath('CamParent') self._camParent.reparentTo(self._parent) self._camParent.setPos(self._toon, 0, 0, 0) self._camParent.setHpr(180, Globals.Camera.Angle, 0) self._camera.reparentTo(self._camParent) self._camera.setPos(0, Globals.Camera.Distance, 0) self._camera.lookAt(self._toon, 0, 0, self._lookAtZ) self._cameraLookAtNP = NodePath('CameraLookAt') self._cameraLookAtNP.reparentTo(self._camera.getParent()) self._cameraLookAtNP.setPosHpr(self._camera.getPos(), self._camera.getHpr()) self._levelBounds = self._level.getBounds() self._enabled = True self._frozen = False self._initCollisions() def _initCollisions(self): self._camCollRay = CollisionRay() camCollNode = CollisionNode('CameraToonRay') camCollNode.addSolid(self._camCollRay) camCollNode.setFromCollideMask(OTPGlobals.WallBitmask | OTPGlobals.CameraBitmask | ToontownGlobals.FloorEventBitmask | ToontownGlobals.CeilingBitmask) camCollNode.setIntoCollideMask(0) self._camCollNP = self._camera.attachNewNode(camCollNode) self._camCollNP.show() self._collOffset = Vec3(0, 0, 0.5) self._collHandler = CollisionHandlerQueue() self._collTrav = CollisionTraverser() self._collTrav.addCollider(self._camCollNP, self._collHandler) self._betweenCamAndToon = {} self._transNP = NodePath('trans') self._transNP.reparentTo(render) self._transNP.setTransparency(True) self._transNP.setAlphaScale(Globals.Camera.AlphaBetweenToon) self._transNP.setBin('fixed', 10000) def _destroyCollisions(self): self._collTrav.removeCollider(self._camCollNP) self._camCollNP.removeNode() del self._camCollNP del self._camCollRay del self._collHandler del self._collOffset del self._betweenCamAndToon self._transNP.removeNode() del self._transNP def freeze(self): self._frozen = True def unfreeze(self): self._frozen = False def disable(self): if not self._enabled: return self._destroyCollisions() self._camera.wrtReparentTo(render) self._cameraLookAtNP.removeNode() del self._cameraLookAtNP self._camParent.removeNode() del self._camParent del self._prevToonY del self._lookAtZ del self._bounds del self._frozen self._enabled = False def update(self, dt=0.0): self._updateCam(dt) self._updateCollisions() def _updateCam(self, dt): toonPos = self._toon.getPos() camPos = self._camParent.getPos() x = camPos[0] z = camPos[2] toonWorldX = self._toon.getX(render) maxX = Globals.Camera.MaxSpinX toonWorldX = clamp(toonWorldX, -1.0 * maxX, maxX) spinAngle = Globals.Camera.MaxSpinAngle * toonWorldX * toonWorldX / ( maxX * maxX) newH = 180.0 + spinAngle self._camParent.setH(newH) spinAngle = spinAngle * (pi / 180.0) distBehindToon = Globals.Camera.SpinRadius * cos(spinAngle) distToRightOfToon = Globals.Camera.SpinRadius * sin(spinAngle) d = self._camParent.getX() - clamp(toonPos[0], *self._bounds[0]) if abs(d) > Globals.Camera.LeewayX: if d > Globals.Camera.LeewayX: x = toonPos[0] + Globals.Camera.LeewayX else: x = toonPos[0] - Globals.Camera.LeewayX x = self._toon.getX(render) + distToRightOfToon boundToonZ = min(toonPos[2], self._bounds[2][1]) d = z - boundToonZ if d > Globals.Camera.MinLeewayZ: if self._player.velocity[2] >= 0 and toonPos[ 1] != self._prevToonY or self._player.velocity[2] > 0: z = boundToonZ + d * INVERSE_E**(dt * Globals.Camera.CatchUpRateZ) elif d > Globals.Camera.MaxLeewayZ: z = boundToonZ + Globals.Camera.MaxLeewayZ elif d < -Globals.Camera.MinLeewayZ: z = boundToonZ - Globals.Camera.MinLeewayZ if self._frozen: y = camPos[1] else: y = self._toon.getY(render) - distBehindToon self._camParent.setPos(x, smooth(camPos[1], y), smooth(camPos[2], z)) if toonPos[2] < self._bounds[2][1]: h = self._cameraLookAtNP.getH() if d >= Globals.Camera.MinLeewayZ: self._cameraLookAtNP.lookAt(self._toon, 0, 0, self._lookAtZ) elif d <= -Globals.Camera.MinLeewayZ: self._cameraLookAtNP.lookAt(self._camParent, 0, 0, self._lookAtZ) self._cameraLookAtNP.setHpr(h, self._cameraLookAtNP.getP(), 0) self._camera.setHpr( smooth(self._camera.getHpr(), self._cameraLookAtNP.getHpr())) self._prevToonY = toonPos[1] def _updateCollisions(self): pos = self._toon.getPos(self._camera) + self._collOffset self._camCollRay.setOrigin(pos) direction = -Vec3(pos) direction.normalize() self._camCollRay.setDirection(direction) self._collTrav.traverse(render) nodesInBetween = {} if self._collHandler.getNumEntries() > 0: self._collHandler.sortEntries() for entry in self._collHandler.getEntries(): name = entry.getIntoNode().getName() if name.find('col_') >= 0: np = entry.getIntoNodePath().getParent() if not np in nodesInBetween: nodesInBetween[np] = np.getParent() for np in nodesInBetween.keys(): if np in self._betweenCamAndToon: del self._betweenCamAndToon[np] else: np.setTransparency(True) np.wrtReparentTo(self._transNP) if np.getName().find('lightFixture') >= 0: if not np.find('**/*floor_mesh').isEmpty(): np.find('**/*floor_mesh').hide() elif np.getName().find('platform') >= 0: if not np.find('**/*Floor').isEmpty(): np.find('**/*Floor').hide() for np, parent in self._betweenCamAndToon.items(): np.wrtReparentTo(parent) np.setTransparency(False) if np.getName().find('lightFixture') >= 0: if not np.find('**/*floor_mesh').isEmpty(): np.find('**/*floor_mesh').show() elif np.getName().find('platform') >= 0: if not np.find('**/*Floor').isEmpty(): np.find('**/*Floor').show() self._betweenCamAndToon = nodesInBetween
class MouseControls(DirectObject.DirectObject): def __init__(self): self.keys = {} for char in string.ascii_lowercase: self.keys[char] = BUTTON_UP def makeKeyPair(ch): def keyUp(): self.keys[ch] = BUTTON_DOWN #print "%s UP" % (ch) def keyDown(): self.keys[ch] = BUTTON_UP #print "%s DOWN" % (ch) return [keyUp, keyDown] keyPair = makeKeyPair(char) self.accept(char, keyPair[0]) self.accept(char + '-up', keyPair[1]) self.accept('mouse1', self.leftClick) self.accept('mouse1-up', self.leftClickUp) self.accept('mouse2', self.mClick) self.accept('mouse2-up', self.mClickUp) self.accept('mouse3', self.rightClick) self.accept('mouse3-up', self.rightClickUp) self.mouse1Down = False self.mouse2Down = False self.mouse3Down = False self.trackMouseTimeOld = 0 self.trackMouseX = 0 self.trackMouseY = 0 self.trackMouse_Mouse1DownOld = False self.trackMouse_Mouse2DownOld = False self.trackMouse_Mouse3DownOld = False taskMgr.add(self.trackMouseTask, 'trackMouseTask') # base.cTrav = CollisionTraverser() self.pickerQ = CollisionHandlerQueue() self.pickerCollN = CollisionNode('mouseRay') self.pickerCamN = base.camera.attachNewNode(self.pickerCollN) self.pickerCollN.setFromCollideMask(BitMask32.bit(1)) self.pickerRay = CollisionRay() self.pickerCollN.addSolid(self.pickerRay) base.cTrav.addCollider(self.pickerCamN, self.pickerQ) self.objectUnderCursor = None #taskMgr.add(self.mousePickerTask, 'Mouse picker process') def leftClick(self): self.mouse1Down = True #Collision traversal pickerNode = CollisionNode('mouseRay') pickerNP = base.camera.attachNewNode(pickerNode) pickerNode.setFromCollideMask(GeomNode.getDefaultCollideMask()) pickerRay = CollisionRay() pickerNode.addSolid(pickerRay) myTraverser = CollisionTraverser() myHandler = CollisionHandlerQueue() myTraverser.addCollider(pickerNP, myHandler) if base.mouseWatcherNode.hasMouse(): mpos = base.mouseWatcherNode.getMouse() pickerRay.setFromLens(base.camNode, mpos.getX(), mpos.getY()) myTraverser.traverse(render) # Assume for simplicity's sake that myHandler is a CollisionHandlerQueue. if myHandler.getNumEntries() > 0: # This is so we get the closest object myHandler.sortEntries() pickedObj = myHandler.getEntry(0).getIntoNodePath() objTag = pickedObj.findNetTag('mouseCollisionTag').getTag( 'mouseCollisionTag') if objTag and len(objTag) > 0: messenger.send('object_click', [objTag]) pickerNP.remove() def leftClickUp(self): self.mouse1Down = False def mClick(self): self.mouse2Down = True def mClickUp(self): self.mouse2Down = False def rightClick(self): self.mouse3Down = True def rightClickUp(self): self.mouse3Down = False def trackMouseTask(self, task): timeElapsed = task.time - self.trackMouseTimeOld if timeElapsed < 0.05: return Task.cont self.trackMouseTimeOld = task.time if base.mouseWatcherNode.hasMouse(): mX = base.mouseWatcherNode.getMouseX() mY = base.mouseWatcherNode.getMouseY() diffX = mX - self.trackMouseX diffY = mY - self.trackMouseY if (abs(diffX) > DRAG_THRESH) or (abs(diffY) > DRAG_THRESH): messenger.send('mouseDelta', [diffX, diffY]) self.trackMouseX = mX self.trackMouseY = mY if self.trackMouse_Mouse1DownOld and self.mouse1Down: messenger.send('mouse1Delta', [diffX, diffY]) if self.trackMouse_Mouse2DownOld and self.mouse2Down: messenger.send('mouse2Delta', [diffX, diffY]) if self.trackMouse_Mouse3DownOld and self.mouse3Down: messenger.send('mouse3Delta', [diffX, diffY]) self.trackMouse_Mouse1DownOld = self.mouse1Down self.trackMouse_Mouse2DownOld = self.mouse2Down self.trackMouse_Mouse3DownOld = self.mouse3Down return Task.cont def mousePickerTask(self, task): print 'lalala: ', self.objectUnderCursor if base.mouseWatcherNode.hasMouse(): mpos = base.mouseWatcherNode.getMouse() self.pickerRay.setFromLens(base.camNode, mpos.getX(), mpos.getY()) #self.picker.traverse(base.render) if self.pickerQ.getNumEntries() > 0: self.pickerQ.sortEntries() firstNode = self.pickerQ.getEntry(0).getIntoNode() if firstNode != self.objectUnderCursor: if self.objectUnderCursor: messenger.send( 'interactive-scene-event', [self.objectUnderCursor.getName(), 'rollout']) print 'Rollout', self.objectUnderCursor.getName() self.objectUnderCursor = firstNode messenger.send( 'interactive-scene-event', [self.objectUnderCursor.getName(), 'rollin']) print 'Rollin', self.objectUnderCursor.getName() else: if self.objectUnderCursor: messenger.send( 'interactive-scene-event', [self.objectUnderCursor.getName(), 'rollout']) print 'Rollout', self.objectUnderCursor.getName() self.objectUnderCursor = None return task.cont
class NodeRaycaster: def __init__(self, renderer): self.log = logging.getLogger('pano.raycaster') self.renderer = renderer #Stores the collisions of the camera ray with the cubemap self.collisionsQueue = None #Variables for setting up collision detection in Panda self.pickerNP = None self.pickerNode = None self.pickerRay = None self.traverser = None def initialize(self): """ To setup collision detection we need: a. A CollisionNode having a ray as its solid and placed at the position of the camera while also having the same orientation as the camera. b. A new nodepath placed in the scenegraph as an immediate child of the camera. It will be used to insert the collision node in the scenegraph. c. A CollisionRay for firing rays based on mouse clicks. d. A collisions traverser. e. A collisions queue where all found collisions will be stored for later processing. """ self.traverser = CollisionTraverser('Hotspots collision traverser') self.collisionsQueue = CollisionHandlerQueue() self.pickerNode = CollisionNode('mouseRay') self.pickerRay = CollisionRay() self.pickerNode.addSolid(self.pickerRay) self.pickerNP = self.renderer.getCamera().attachNewNode( self.pickerNode) self.traverser.addCollider(self.pickerNP, self.collisionsQueue) def dispose(self): if self.pickerNP is not None: self.traverser.removeCollider(self.pickerNP) self.pickerNode.clearSolids() self.pickerNP.removeNode() def raycastWindow(self, x, y, returnAll=False): ''' Casts a camera ray, whose origin is implicitly defined by the given window coordinates, against the rendered scene returns information regarding the hit point, if any. @param x: The x window coordinate of the ray's origin in render2d space. @param y: The y window coordinate of the ray's origin in render2d space @param returnAll: If set to False then only the closest collided geometry is returned, otherwise all nodepaths whose collision nodes were intersected by the camera ray will be returned. @return: If returnAll was False, then a list containing a tuple of the form (topmost intersected NodePath, contact point Point3f). if returnAll was set to True, a list of tuples in the same form as above, one tuple for each intersection. None if no collision occurred. ''' #This makes the ray's origin the camera and makes the ray point #to the screen coordinates of the mouse self.pickerRay.setFromLens(self.renderer.getCamera().node(), x, y) #Check for collision only with the node self.traverser.traverse(self.renderer.getSceneRoot()) if self.collisionsQueue.getNumEntries() > 0: if not returnAll: self.collisionsQueue.sortEntries() cEntry = self.collisionsQueue.getEntry(0) if cEntry.hasInto(): return [(cEntry.getIntoNodePath(), cEntry.getSurfacePoint())] else: return None else: nodepaths = [] for i in xrange(self.collisionsQueue.getNumEntries()): cEntry = self.collisionsQueue.getEntry(i) if cEntry.hasInto(): # self.log.debug('adding collision into-nodepath: %s' % str(cEntry.getIntoNodePath())) intoNP = cEntry.getIntoNodePath() nodepaths.append( (intoNP, cEntry.getSurfacePoint(intoNP))) return nodepaths