Ejemplo n.º 1
0
    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])
Ejemplo n.º 2
0
    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()
Ejemplo n.º 3
0
    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")
Ejemplo n.º 4
0
    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)
Ejemplo n.º 5
0
    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
Ejemplo n.º 7
0
 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")
Ejemplo n.º 8
0
    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) 
Ejemplo n.º 9
0
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
Ejemplo n.º 10
0
 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
Ejemplo n.º 11
0
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)
Ejemplo n.º 12
0
 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)
Ejemplo n.º 13
0
    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)
Ejemplo n.º 14
0
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)
Ejemplo n.º 15
0
    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
Ejemplo n.º 16
0
    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)
Ejemplo n.º 17
0
 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] )
Ejemplo n.º 18
0
    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()
Ejemplo n.º 19
0
    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
Ejemplo n.º 20
0
	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")
Ejemplo n.º 21
0
Archivo: fpsTest.py Proyecto: croza/RR2
    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])
Ejemplo n.º 22
0
 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
Ejemplo n.º 23
0
 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] )
Ejemplo n.º 24
0
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()
Ejemplo n.º 26
0
 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)
Ejemplo n.º 27
0
 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.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
Ejemplo n.º 29
0
 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)
Ejemplo n.º 30
0
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
Ejemplo n.º 31
0
 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))
Ejemplo n.º 32
0
 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)
Ejemplo n.º 33
0
 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)
Ejemplo n.º 34
0
 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)                
Ejemplo n.º 35
0
 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)
Ejemplo n.º 36
0
    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()
Ejemplo n.º 37
0
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))))
Ejemplo n.º 38
0
    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()
Ejemplo n.º 39
0
    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)
Ejemplo n.º 40
0
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))
Ejemplo n.º 41
0
    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)
Ejemplo n.º 42
0
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))
Ejemplo n.º 43
0
    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) 
Ejemplo n.º 44
0
	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)
Ejemplo n.º 45
0
    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)
Ejemplo n.º 46
0
    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
Ejemplo n.º 47
0
 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)
Ejemplo n.º 48
0
 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)
Ejemplo n.º 49
0
    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')
Ejemplo n.º 50
0
 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()
Ejemplo n.º 51
0
    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)
Ejemplo n.º 52
0
 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
Ejemplo n.º 53
0
    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()
Ejemplo n.º 54
0
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
Ejemplo n.º 55
0
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
Ejemplo n.º 56
0
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
Ejemplo n.º 57
0
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
Ejemplo n.º 58
0
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