class RepairMincroGame(DirectFrame, FSM.FSM):
    readySound = None
    goSound = None
    completeSound = None
    
    def __init__(self, repairGame, name, startText):
        DirectFrame.__init__(self, parent = repairGame.gui, relief = None)
        FSM.FSM.__init__(self, '%sFSM' % name)
        self.defaultTransitions = {
            'Idle': [
                'Intro',
                'Final'],
            'Intro': [
                'Game',
                'Idle',
                'Final'],
            'Game': [
                'Outro',
                'Idle',
                'Final'],
            'Outro': [
                'Idle',
                'Final'],
            'Final': [] }
        self.name = name
        self.repairGame = repairGame
        self.startText = startText
        self._initVars()
        self._initAudio()
        self._initVisuals()
        self._initIntervals()
        self.request('Idle')

    
    def _initVars(self):
        self.complete = False
        self.difficulty = 0

    
    def _initAudio(self):
        if not self.readySound:
            RepairMincroGame.readySound = loadSfx(SoundGlobals.SFX_MINIGAME_REPAIR_GENERAL_READY)
            RepairMincroGame.goSound = loadSfx(SoundGlobals.SFX_MINIGAME_REPAIR_GENERAL_GO)
            RepairMincroGame.completeSound = loadSfx(SoundGlobals.SFX_MINIGAME_REPAIR_GENERAL_GAMECOMPLETE)
        

    
    def _initVisuals(self):
        self.countDownLabel = DirectLabel(text = self.startText, text_fg = (1.0, 1.0, 1.0, 1.0), text_shadow = (0.0, 0.0, 0.0, 1.0), text_font = PiratesGlobals.getPirateFont(), scale = (0.16, 0.16, 0.16), pos = (0.0, 0.0, 0.14999999999999999), parent = self, relief = None, textMayChange = 1)
        self.countDownLabel.setBin('fixed', 37)
        self.winLabel = DirectLabel(text = PLocalizer.Minigame_Repair_Win, text_fg = (1.0, 1.0, 1.0, 1.0), text_font = PiratesGlobals.getPirateFont(), text_shadow = (0.0, 0.0, 0.0, 1.0), scale = (0.16, 0.16, 0.16), pos = RepairGlobals.Common.youWinPos[self.name], relief = None, parent = self)
        self.winLabel.setBin('fixed', 37)
        self.winLabel.stash()
        self.scoreLabel = DirectLabel(text = PLocalizer.Minigame_Repair_Win, text_fg = (1.0, 1.0, 1.0, 1.0), text_font = PiratesGlobals.getPirateFont(), text_shadow = (0.0, 0.0, 0.0, 1.0), scale = (0.10000000000000001, 0.10000000000000001, 0.10000000000000001), pos = RepairGlobals.Common.scorePos[self.name], relief = None, parent = self)
        self.scoreLabel.setBin('fixed', 37)
        self.scoreLabel.stash()
        self.postWinLabel = DirectLabel(text = PLocalizer.Minigame_Repair_Pick_New_Game, text_fg = (1.0, 1.0, 1.0, 1.0), text_font = PiratesGlobals.getPirateFont(), text_shadow = (0.0, 0.0, 0.0, 1.0), scale = (0.14000000000000001, 0.14000000000000001, 0.14000000000000001), pos = RepairGlobals.Common.youWinPos[self.name], relief = None, textMayChange = 1, parent = self.repairGame.gui)
        self.postWinLabel.setBin('fixed', 37)
        self.postWinLabel.stash()

    
    def _initIntervals(self):
        normalPos = Vec3(0.0, 0.0, 0.14999999999999999)
        belowScreenPos = Vec3(normalPos.getX(), normalPos.getY(), normalPos.getZ() - 0.25)
        aboveScreenPos = Vec3(normalPos.getX(), normalPos.getY(), normalPos.getZ() + 0.25)
        self.introSequence = Sequence(Func(self.setCountDown, PLocalizer.Minigame_Repair_Countdown_Ready), Parallel(LerpFunc(self.countDownLabel.setPos, fromData = belowScreenPos, toData = normalPos, duration = 0.25), LerpFunc(self.countDownLabel.setAlphaScale, fromData = 0.0, toData = 1.0, duration = 0.25)), Func(self.readySound.play), Wait(0.5), Parallel(LerpFunc(self.countDownLabel.setPos, fromData = normalPos, toData = aboveScreenPos, duration = 0.25), LerpFunc(self.countDownLabel.setAlphaScale, fromData = 1.0, toData = 0.0, duration = 0.25)), Func(self.setCountDown, self.startText), Parallel(LerpFunc(self.countDownLabel.setPos, fromData = belowScreenPos, toData = normalPos, duration = 0.25), LerpFunc(self.countDownLabel.setAlphaScale, fromData = 0.0, toData = 1.0, duration = 0.25)), Func(self.goSound.play), Wait(0.5), Parallel(LerpFunc(self.countDownLabel.setPos, fromData = normalPos, toData = aboveScreenPos, duration = 0.25), LerpFunc(self.countDownLabel.setAlphaScale, fromData = 1.0, toData = 0.0, duration = 0.25)), Func(self.request, 'Game'), name = 'RepairMincroGame.introSequence')
        normalPos = Vec3(RepairGlobals.Common.youWinPos[self.name])
        normalScorePos = Vec3(RepairGlobals.Common.scorePos[self.name])
        belowScreenPos = Vec3(normalPos.getX(), normalPos.getY(), normalPos.getZ() - 0.25)
        aboveScreenPos = Vec3(normalPos.getX(), normalPos.getY(), normalPos.getZ() + 0.25)
        belowScreenScorePos = Vec3(normalScorePos.getX(), normalScorePos.getY(), normalScorePos.getZ() - 0.25)
        aboveScreenScorePos = Vec3(normalScorePos.getX(), normalScorePos.getY(), normalScorePos.getZ() + 0.25)
        self.outroSequence = Sequence(Func(self.winLabel.setAlphaScale, 0), Func(self.scoreLabel.setAlphaScale, 0), Func(self.postWinLabel.setAlphaScale, 0), Func(self.winLabel.setPos, belowScreenPos), Func(self.scoreLabel.setPos, belowScreenScorePos), Func(self.postWinLabel.setPos, belowScreenPos), Func(self.setScoreLabelText), Func(self.winLabel.unstash), Func(self.scoreLabel.unstash), Func(self.postWinLabel.unstash), Parallel(LerpFunc(self.scoreLabel.setPos, fromData = belowScreenScorePos, toData = normalScorePos, duration = 0.25), LerpFunc(self.scoreLabel.setAlphaScale, fromData = 0.0, toData = 1.0, duration = 0.25), LerpFunc(self.winLabel.setPos, fromData = belowScreenPos, toData = normalPos, duration = 0.25), LerpFunc(self.winLabel.setAlphaScale, fromData = 0.0, toData = 1.0, duration = 0.25)), Func(self.completeSound.play), Wait(1.0), Parallel(LerpFunc(self.winLabel.setPos, fromData = normalPos, toData = aboveScreenPos, duration = 0.25), LerpFunc(self.winLabel.setAlphaScale, fromData = 1.0, toData = 0.0, duration = 0.25), LerpFunc(self.scoreLabel.setPos, fromData = normalScorePos, toData = aboveScreenScorePos, duration = 0.25), LerpFunc(self.scoreLabel.setAlphaScale, fromData = 1.0, toData = 0.0, duration = 0.25)), Func(self.winLabel.stash), Func(self.scoreLabel.stash), Func(self.stashPostWinLabelIfCycleComplete), Wait(0.25), Parallel(LerpFunc(self.postWinLabel.setPos, fromData = belowScreenPos, toData = normalPos, duration = 0.25), LerpFunc(self.postWinLabel.setAlphaScale, fromData = 0.0, toData = 1.0, duration = 0.25)), name = 'outroSequence')
        self.cleanupSequence = Sequence(Parallel(LerpFunc(self.postWinLabel.setPos, fromData = normalPos, toData = aboveScreenPos, duration = 0.5), LerpFunc(self.postWinLabel.setAlphaScale, fromData = 1.0, toData = 0.0, duration = 0.5), LerpFunc(self.scoreLabel.setAlphaScale, fromData = 1.0, toData = 0.0, duration = 0.5)), Func(self.scoreLabel.stash), Func(self.postWinLabel.stash), name = 'cleanupSequence')

    
    def updatePostWinLabel(self):
        if self.repairGame.isThereAnOpenGame():
            self.postWinLabel['text'] = PLocalizer.Minigame_Repair_Pick_New_Game
        else:
            self.postWinLabel['text'] = PLocalizer.Minigame_Repair_Waiting_For_Players
        self.postWinLabel.setText()

    
    def setScoreLabelText(self):
        labelSet = False
        for i in [
            0,
            1,
            2]:
            if not labelSet:
                percent = self.difficulty / self.repairGame.difficultyMax
                dif = RepairGlobals.Common.speedThresholds[self.name][i][1] - RepairGlobals.Common.speedThresholds[self.name][i][0]
                goalTime = RepairGlobals.Common.speedThresholds[self.name][i][0] + dif * percent
                if self.repairGame.repairClock.gameTime < goalTime:
                    labelSet = True
                    self.scoreLabel['text'] = PLocalizer.Minigame_Repair_Speed_Thresholds[i]
                
            self.repairGame.repairClock.gameTime < goalTime
        
        if not labelSet:
            self.scoreLabel['text'] = PLocalizer.Minigame_Repair_Speed_Thresholds[3]
        

    
    def stashPostWinLabelIfCycleComplete(self):
        if self.repairGame.isCycleComplete():
            self.postWinLabel.stash()
        

    
    def setDifficulty(self, difficulty):
        self.difficulty = difficulty

    
    def setCountDown(self, text):
        self.countDownLabel['text'] = text
        self.countDownLabel.setText()
        self.countDownLabel.setAlphaScale(0.0)

    
    def destroy(self):
        DirectFrame.destroy(self)
        self.countDownLabel.destroy()
        del self.countDownLabel
        self.winLabel.destroy()
        del self.winLabel
        self.introSequence.clearToInitial()
        del self.introSequence
        self.outroSequence.clearToInitial()
        del self.outroSequence
        self.cleanupSequence.clearToInitial()
        del self.cleanupSequence
        del self.repairGame
        self.cleanup()

    
    def reset(self):
        self.complete = False
        self.repairGame.repairClock.stop()

    
    def enterIdle(self):
        self.stash()

    
    def exitIdle(self):
        pass

    
    def enterIntro(self):
        self.unstash()
        self.countDownLabel.unstash()
        self.introSequence.start()
        self.reset()
        self.countDownLabel.reparentTo(self)

    
    def exitIntro(self):
        self.countDownLabel.stash()
        self.introSequence.clearToInitial()

    
    def enterGame(self):
        self.repairGame.repairClock.restart()

    
    def exitGame(self):
        self.repairGame.repairClock.pause()

    
    def enterOutro(self):
        self.outroSequence.start()
        self.complete = True

    
    def exitOutro(self):
        self.outroSequence.finish()
        self.cleanupSequence.start()
        self.reset()
        self.repairGame.gui.clearTutorial()
        self.repairGame.gui.clearTitle()

    
    def enterFinal(self):
        pass
示例#2
0
class ZCanvas(object):
    """The singleton zcanvas represents the infinite and infinitely scalable
    zoomplane and manages the viewport through which the user sees the zoomplane
    (including zooming and panning the viewport). If you want to place an object 
    on the zoom plane, you must attach it to the viewport node held by zcanvas.
    
    Messages sent by zcanvas (see messager.py to subscribe to these):
    
    'new focus'     --  viewport's focused znode has changed.
                  
                        arg: the newly focused znode.
    
    'message started'   --  a new text message is being displayed on the
                            overlay.
                  
                            arg: a MessageStarted event object.
                            
    'message ended' --  a text message has finished being displayed on the
                        overlay.
                        
                        arg: None.
                            
    'zooming to znode'  --  the viewport has begun zooming to a znode.
                            
                            arg: the znode being zoomed to.
                            
    'zooming to zparent'    -- the viewport has begun zooming back to a
                               parent node of the previously focused node.
                               
                               arg: the znode being zoomed to, or None if the
                                    viewport is zooming back to its home
                                    position.
                                        
    'zoom done' --  the viewport has finished zooming to a znode.

                    arg: None.
    
    'do drag'   --  a drag signal has been received (zcanvas.drag was called).
                    
                    arg: the znode to be dragged.
                               
    'do drop'   --  a drop signal has been received (zcanvas.drop was called).
                    
                    arg: the znode currently being dragged.
    
    """

    def __init__(self):
        """Initialise the singleton zcanvas instance: setup the viewport node,
        the collision rays for mouse picking, and start the task method used
        for mouse picking, and other initialisation details.

        """
        # This is the node that is transformed to implement viewport panning and
        # zooming.
        self.viewport = aspect2d.attachNewNode('zcanvas')

        # This is the node that user classes attach nodepaths to if they want
        # them to be on the zoom plane.
        self.home = self.viewport.attachNewNode('home')
        #self.home.showTightBounds()
                
        # This interval is used when the viewport is automatically transformed
        # to focus on a given nodepath, and also when the viewport is zoomed in
        # or out manually.
        self._zoomInterval = None

        # The time (in seconds) that it takes to move the viewport from the 
        # minimum to the maximum position on the Y axis when manually zooming.
        # (Controls the speed when manually zooming the viewport.)
        self.zoom_time = 2
        
        # Minimum and maximum positions for the viewport when manually moving on
        # the Y axis. FIXME: remove these arbitrary limits?
        self.max_zoom = 4.0
        self.min_zoom = .1
        
        # Interval used to manually pan the viewport left and right, and its
        # speed and minimum and maximum positions.
        self.pan_x_interval = None
        self.pan_x_time = 2
        self.max_pan_x = 1.33
        self.min_pan_x = -1.33

        # Interval used to manually pan the viewport up and down, and its
        # speed and minimum and maximum positions.
        self.pan_z_interval = None
        self.pan_z_time = 2
        self.max_pan_z = 1.0
        self.min_pan_z = -1.0 

        # The zcanvas' collision ray, collision mask, etc. used for mouse
        # picking.
        cn = CollisionNode('zoom collision ray')
        cn.addSolid(CollisionRay(0,-100,0, 0,1,0))
        from pandac.PandaModules import BitMask32
        self.mask = BitMask32.bit(0)
        cn.setFromCollideMask(self.mask)
        cn.setIntoCollideMask(BitMask32.allOff())
        self._cnp = aspect2d.attachNewNode(cn)
        self._ctrav=CollisionTraverser()
        self._queue = CollisionHandlerQueue()
        self._ctrav.addCollider(self._cnp, self._queue)
        # For debugging only.
        # self._ctrav.showCollisions(self.viewport)

        # Attributes that record which zoomable, draggable and highlightable
        # (if any) the mouse pointer is currently over.
        self._zoomMouseOver = None
        self._dragMouseOver = None
        self._highlightMouseOver = None

        # The draggable (if any) that is currently being dragged.
        self._draggee = None

        # Task method that does the mouse picking.
        taskMgr.add(self._mouseOverTask,'_mouseOverTask')

        # The currently focused node. A managed property.
        self.__focus = None

        # Catch the 'zoom done' message from panda's messenger system and echo
        # it to my custom messager system. (Because we use
        # interval.setDoneEvent to send the 'zoom done' message it must
        # initially be sent through panda's messenger).
        base.accept('zoom done',messager.send,['zoom done'])
                
    def getfocus(self): return self.__focus

    def setfocus(self,obj):
        self.__focus = obj
        messager.send('new focus',self.focus)

    # focus is a property whose set method ensures that observer's are notified 
    # whenever it changes.
    focus = property(fget=getfocus, fset=setfocus,
                      doc ="The viewport's currently focused object.")
                    
    def message(self,text,duration=5):
        """Display a text message to the user for a given duration in seconds.
        
        """
        # If we're already displaying a message, finish it early.
        if hasattr(self,'help'):
            self.help.detachNode()
            self.sequence.finish()

        # The new message.        
        self.help = DirectLabel(text = text, text_scale=.1,
                                text_fg=(.8,.8,.8,1), frameColor=(.2,.2,.2,0), 
                                frameVisibleScale=(1.2,1.2))
        self.help.setPos(0,0,-.7)
        self.help.setAlphaScale(0) # At first the message is fully transparent.

        # This function is used to fade the message in and out.
        def fade(t):
            """Set the alpha of the message to t (multiplied by a constant 
            factor)."""
            self.help.setAlphaScale(t*.9)
            self.help.setColor(.2,.2,.2,t*.7)
            
        # Create a sequence of intervals to fade in the message, wait for
        # `duration`, then fade it out.
        fade_in = LerpFunc(fade, fromData = 0, toData = 1, duration = .5,
                           blendType = 'noBlend', extraArgs = [], name = None)
        fade_out = LerpFunc(fade, fromData = 1, toData = 0, duration = .5,
                            blendType = 'noBlend', extraArgs = [], name = None)
        self.sequence = Sequence(fade_in,Wait(duration),fade_out)
        self.sequence.setDoneEvent('message ended')
        self.sequence.start()
        messager.send('message started',MessageStarted(text,duration))

    def _mouseOverTask(self,t):
        """Move the CollisionRay to the position of the mouse pointer, check
        for collisions, and update various attributes related to what nodes the
        mouse is over.

        """
        if not base.mouseWatcherNode.hasMouse():
            # The mouse is outside of the window, do nothing.
            return Task.cont

        # Do the collision test.
        np = self._findCollision()

        # The zoomable, draggable, droppable and highlightable classes set
        # `self` as a python tag on the nodepaths that they wrap. We use these 
        # tags to find out if np is below the nodepath of a zoomable, draggable,
        # droppable or highlightable in the scene graph.

        prevHighlightMouseOver = self._highlightMouseOver

        if self._draggee is not None:
            # Something is being dragged, so search for a droppable.
            if np is not None:
                # Find the nearest droppable that is an ancestor to np, if any.
                self._highlightMouseOver = np.getNetPythonTag('droppable')
            else:
                self._highlightMouseOver = None
        else:
            # Nothing is being dragged, so search for a zoomable, a draggable
            # and a highlightable.
            # FIXME: zoomable and draggable only really need to be searched for
            # when the zoom and drag buttons are clicked.
            if np is not None:
                   
                # Find the nearest zoomable that is an ancestor of np, if any.
                self._zoomMouseOver = np.getNetPythonTag('zoomable')

                # Find the nearest draggable that is an ancestor to np, if any.
                self._dragMouseOver = np.getNetPythonTag('draggable')
            
                # Find the nearest highlightable that is an ancestor to np, if any.
                self._highlightMouseOver = np.getNetPythonTag('highlightable')
            else:
                self._zoomMouseOver = None
                self._dragMouseOver = None
                self._highlightMouseOver = None

        # Highlight and unhighlight nodes as necessary.
        if prevHighlightMouseOver != self._highlightMouseOver:
            if prevHighlightMouseOver is not None:
                prevHighlightMouseOver.unhighlight()
            if self._highlightMouseOver is not None:
                self._highlightMouseOver.highlight()

        return Task.cont

    def _findCollision(self):        
        """Helper method for _mouseOverTask. Move the CollisionRay ray to be
        over the mouse pointer, run a collision test, and return the first
        nodepath that the ray collides with, or None if nothing is hit. Also
        return None if the mouse is over a DirectGUI object.

        returns -- NodePath or None.
        """
        # If the mouse is over a DirectGUI object then zcanvas doesn't test
        # for collisions. (Leave it to DirectGUI to handle mouse-overs of 
        # DirectGUI objects.)
        if base.mouseWatcherNode.isOverRegion():
            return None

        # Move the CollisionRay's NodePath to where the mouse pointer is.
        mpos = base.mouseWatcherNode.getMouse()
        self._cnp.setPos(render2d,mpos[0],0,mpos[1])

        # Run the collision  test.
        self._ctrav.traverse(aspect2d)
        
        if self._queue.getNumEntries() == 0:
            # The ray didn't collide with anything.
            return None

        # FIXME: what we need to return here is the nodepath, of those in the
        # queue, that would be rendered last and appear on top of the others,
        # i.e. the one that is rightmost and lowest in the scene graph. If the
        # collision system walks the scene graph top-to-bottom and left-to-right
        # then that should be the last nodepath in the queue. For now, we guess
        # that that is correct.
        #
        # If this breaks down, we can try setting non-zero Y-values on the 
        # nodepaths corresponding to their conceptual Y-order, and see if that
        # allows us to use queue.sort(), or if that doesn't work, introduce my
        # own Y-order attribute to my classes.
        np = self._queue.getEntry(self._queue.getNumEntries()-1).getIntoNodePath()
        return np

    def zoomTo(self):
        """
        If the mouse pointer is over a zoomable and we are not already zooming,
        focus the viewport on the zoomable that the mouse pointer is over.

        """
        if self.isZooming():
            # If we are already in the process of zooming we don't want to
            # initiate another zoom.
            return
        elif self._zoomMouseOver is None:
            # The mouse pointer is not over any zoomable.
            return
        else:
            self._zoomToNodePath(self._zoomMouseOver.np)
            self.focus = self._zoomMouseOver
            messager.send('zooming to znode',self._zoomMouseOver)

    # Rename this to auto_zoom_out?
    def zoomToParent(self):
        """
        If self.focus is not None and we are not already zooming, focus the
        viewport on the next zoomable above self.focus in the scene graph, or
        if there is no such zoomable, move the viewport to it's home position.

        """
        if self.focus is not None and not self.isZooming():
            p = self.focus.getParent().getNetPythonTag('zoomable')
            if p is None:
                self._zoomToNodePath(self.home)
                self.focus = None
            else:
                self._zoomToNodePath(p.np)
                self.focus = p
            messager.send('zooming to zparent',self.focus)

    def drag(self):
        """Begin dragging the draggable that is currently under the mouse 
        pointer, if any."""

        if self._dragMouseOver is not None:
            self._draggee = self._dragMouseOver
            self._dragMouseOver = None
            self._zoomMouseOver = None
            messager.send('do drag',self._draggee)
            self._draggee.drag()

    def drop(self):
        """Drop the node currently being dragged, if any."""

        if self._draggee is not None:
            messager.send('do drop',self._draggee)
            self._draggee.drop()
            self._draggee = None

    # FIXME: this should be a module-level utility function somewhere, not an
    # instance method.
    def find_center(self,bottom_left,top_right):
        """Given two points bottom_left and top_right representing opposite
        corners of a rectangular region (e.g. a bounding box returned by
        NodePath.getTightBounds()), return a point representing the center of
        the rectangular region.
        
        returns : Point3
        
        """
        l = bottom_left.getX()
        b = bottom_left.getZ()
        r = top_right.getX()
        t = top_right.getZ()
        center_x = l + ((r-l)/2.0)
        center_z = b + ((t-b)/2.0)
        center = Point3(center_x,0,center_z)
        return center

    def _zoomToNodePath(self,np):
        """Create and start an interval that will move the viewport to
        focus on the nodepath np.

        """
        # ynjh_jo's zoom code.
        posZoom=self.viewport.getRelativePoint(np.getParent(),self.find_center(*np.getTightBounds()))
        bounds3 = np.getTightBounds()
        oldScale = self.viewport.getScale()
        self.viewport.setScale(1,1,1)
        bounds = render2d.getRelativeVector(np.getParent(),bounds3[1]-bounds3[0])
        self.viewport.setScale(oldScale)
        selfRatio = base.getAspectRatio()*bounds[0]/bounds[2]
        maxScale = 2./bounds[2*( selfRatio<base.getAspectRatio() )]
        zoomable = np.getPythonTag('zoomable')
        if zoomable is not None:        
            maxScale *= zoomable.magnification
        else:
            maxScale *= 0.8 # Hard-coded magnification factor for home node.
        self.zoomInterval = self.viewport.posHprScaleInterval(.5,
            -posZoom*maxScale,
            self.viewport.getHpr(),
            Vec3(maxScale,1,maxScale)
            )
        self.zoomInterval.setDoneEvent('zoom done')            
        self.zoomInterval.start()

    def _zoomToHome(self):
        """Create and start an interval that will move the viewport back
        to its home position.

        """
        # ynjh_jo's code again.
        self._zoomInterval = self.viewport.posHprScaleInterval(
            duration = .5,
            pos = Point3(0,0,0),
            hpr = self.viewport.getHpr(),
            scale = Vec3(1,1,1)
            )
        self.zoomInterval.setDoneEvent('zoom done')    
        self._zoomInterval.start()

    def isZooming(self):
        """Return True if the viewport is currently zooming in or out, False if
        it is not.
        
        """
        if self._zoomInterval is None:
            return False
        elif self._zoomInterval.isPlaying():
            return True
        else:
            return False

    # Methods for manual panning and zooming.
    # FIXME. This don't interact nicely with the automatic zooming above, and
    # they don't generate any events. 
    def zoom_in(self):

        if self._zoomInterval is not None:
            if self._zoomInterval.isPlaying():
                self._zoomInterval.pause()

        current_zoom = self.viewport.getScale().getY()
        duration = ((self.max_zoom-current_zoom)/self.max_zoom)*self.zoom_time

        self._zoomInterval = self.viewport.scaleInterval(
            duration=duration,
            scale=4,
            name = "zoom_in")
        self._zoomInterval.start()

    def zoom_out(self):

        if self._zoomInterval is not None:
            if self._zoomInterval.isPlaying():
                self._zoomInterval.pause()
   
        current_zoom = self.viewport.getScale().getY()
        duration = ((current_zoom-self.min_zoom)/self.max_zoom)*self.zoom_time
       
        self._zoomInterval = self.viewport.scaleInterval(
            duration=.5,
            scale=.1,
            name = "zoom_out")
        self._zoomInterval.start()

    def stop_zoom_in(self):
   
        if self._zoomInterval is not None:
            if self._zoomInterval.isPlaying() and self._zoomInterval.getName() == "zoom_in":
                self._zoomInterval.pause()

    def stop_zoom_out(self):
   
        if self._zoomInterval is not None:
            if self._zoomInterval.isPlaying() and self._zoomInterval.getName() == "zoom_out":
                self._zoomInterval.pause()

    def pan_left(self):

        if self.pan_x_interval is not None:
            if self.pan_x_interval.isPlaying():
                self.pan_x_interval.pause()

        current_pan = self.viewport.getPos().getX()
        duration = ((self.max_pan_x-current_pan)/self.max_pan_x)*self.pan_x_time

        self.pan_x_interval = self.viewport.posInterval(
            duration=duration,
            pos = Vec3(self.max_pan_x,self.viewport.getPos().getY(),self.viewport.getPos().getZ()),
            name = "pan_left")
        self.pan_x_interval.start()

    def pan_right(self):

        if self.pan_x_interval is not None:
            if self.pan_x_interval.isPlaying():
                self.pan_x_interval.pause()

        current_pan = self.viewport.getPos().getX()
        duration = ((current_pan-self.min_pan_x)/self.max_pan_x)*self.pan_x_time

        self.pan_x_interval = self.viewport.posInterval(
            duration=duration,
            pos = Vec3(self.min_pan_x,self.viewport.getPos().getY(),self.viewport.getPos().getZ()),
            name = "pan_right")
        self.pan_x_interval.start()

    def stop_pan_left(self):
   
        if self.pan_x_interval is not None:
            if self.pan_x_interval.isPlaying() and self.pan_x_interval.getName() == "pan_left":
                self.pan_x_interval.pause()

    def stop_pan_right(self):
   
        if self.pan_x_interval is not None:
            if self.pan_x_interval.isPlaying() and self.pan_x_interval.getName() == "pan_right":
                self.pan_x_interval.pause()

    def pan_down(self):

        if self.pan_z_interval is not None:
            if self.pan_z_interval.isPlaying():
                self.pan_z_interval.pause()

        current_pan = self.viewport.getPos().getZ()
        duration = ((self.max_pan_z-current_pan)/self.max_pan_z)*self.pan_z_time

        self.pan_z_interval = self.viewport.posInterval(
            duration=duration,
            pos = Vec3(self.viewport.getPos().getX(),self.viewport.getPos().getY(),self.max_pan_z),
            name = "pan_down")
        self.pan_z_interval.start()

    def pan_up(self):

        if self.pan_z_interval is not None:
            if self.pan_z_interval.isPlaying():
                self.pan_z_interval.pause()

        current_pan = self.viewport.getPos().getZ()
        duration = ((current_pan-self.min_pan_z)/self.max_pan_z)*self.pan_z_time

        self.pan_z_interval = self.viewport.posInterval(
            duration=duration,
            pos = Vec3(self.viewport.getPos().getX(),self.viewport.getPos().getY(),self.min_pan_z),
            name = "pan_up")
        self.pan_z_interval.start()

    def stop_pan_up(self):
   
        if self.pan_z_interval is not None:
            if self.pan_z_interval.isPlaying() and self.pan_z_interval.getName() == "pan_up":
                self.pan_z_interval.pause()

    def stop_pan_down(self):
   
        if self.pan_z_interval is not None:
            if self.pan_z_interval.isPlaying() and self.pan_z_interval.getName() == "pan_down":
                self.pan_z_interval.pause() 
class SimpleInteractive(DirectObject):
    def __init__(self, object, name, proximityText):
        DirectObject.__init__(self)
        self.object = object
        self.proximityText = proximityText
        self.proximityEvent = name
        self.enterProximityEvent = 'enter' + name
        self.exitProximityEvent = 'exit' + name
        self.useLabel = None
        self.fader = None
        self.size = 6
        self.disk = None
        proximitySphere = CollisionSphere(0, 0, 0, self.size)
        proximitySphere.setTangible(0)
        proximityNode = CollisionNode(self.proximityEvent)
        proximityNode.setIntoCollideMask(PiratesGlobals.WallBitmask)
        proximityNode.addSolid(proximitySphere)
        self.proximityNodePath = self.object.attachNewNode(proximityNode)
        self.accept(self.enterProximityEvent, self.approach)
        self.accept(self.exitProximityEvent, self.leave)

    def createInteractionDisk(self):
        self.disk = loader.loadModel('models/effects/selectionCursor')
        self.disk.setScale(self.size)
        self.disk.setColorScale(0, 1, 0, 1)
        self.disk.setP(-90)
        self.disk.setZ(0.025000000000000001)
        self.disk.setBillboardAxis(6)
        self.disk.reparentTo(self.object)
        self.disk.setBin('shadow', 0)
        self.disk.setTransparency(TransparencyAttrib.MAlpha)
        self.disk.setDepthWrite(0)
        self.disk.setDepthTest(0)

    def loadUseLabel(self, text):
        self.useLabel = DirectLabel(
            parent=aspect2d,
            frameColor=(0.10000000000000001, 0.10000000000000001, 0.25,
                        0.20000000000000001),
            text=text,
            text_align=TextNode.ACenter,
            text_scale=0.059999999999999998,
            text_pos=(0.02, 0.02),
            text_fg=(1, 1, 1, 1),
            text_shadow=(0, 0, 0, 1),
            textMayChange=1,
            text_font=PiratesGlobals.getPirateOutlineFont())
        self.useLabel.setPos(0, 0, -0.69999999999999996)
        self.useLabel.setAlphaScale(0)
        self.useLabel.hide()

    def fadeInText(self):
        if self.fader:
            self.fader.pause()

    def interactionAllowed(self, avId):
        return True

    def approach(self, collEntry):
        if not self.interactionAllowed(localAvatar.doId):
            return None

        if not self.disk:
            self.createInteractionDisk()

        if self.proximityText:
            if not self.useLabel:
                self.loadUseLabel(self.proximityText)

            if self.fader:
                self.fader.pause()

            fadeIn = LerpFunctionInterval(self.useLabel.setAlphaScale,
                                          fromData=0,
                                          toData=1,
                                          duration=0.5)
            self.fader = Sequence(Func(self.useLabel.show), fadeIn)
            self.fader.start()

        self.disk.show()
        self.accept(USE_KEY_EVENT, self.handleUseKey)

    def requestInteraction(self, avId):
        pass

    def handleUseKey(self):
        self.requestInteraction(localAvatar.doId)

    def leave(self, collEntry):
        if self.disk:
            self.disk.hide()

        if self.proximityText:
            if self.fader:
                self.fader.pause()
                self.fader = None

            if self.useLabel:
                self.useLabel.hide()

        self.ignore(USE_KEY_EVENT)
示例#4
0
class SimpleInteractive(DirectObject):
    
    def __init__(self, object, name, proximityText):
        DirectObject.__init__(self)
        self.object = object
        self.proximityText = proximityText
        self.proximityEvent = name
        self.enterProximityEvent = 'enter' + name
        self.exitProximityEvent = 'exit' + name
        self.useLabel = None
        self.fader = None
        self.size = 6
        self.disk = None
        proximitySphere = CollisionSphere(0, 0, 0, self.size)
        proximitySphere.setTangible(0)
        proximityNode = CollisionNode(self.proximityEvent)
        proximityNode.setIntoCollideMask(PiratesGlobals.WallBitmask)
        proximityNode.addSolid(proximitySphere)
        self.proximityNodePath = self.object.attachNewNode(proximityNode)
        self.accept(self.enterProximityEvent, self.approach)
        self.accept(self.exitProximityEvent, self.leave)

    
    def createInteractionDisk(self):
        self.disk = loader.loadModel('models/effects/selectionCursor')
        self.disk.setScale(self.size)
        self.disk.setColorScale(0, 1, 0, 1)
        self.disk.setP(-90)
        self.disk.setZ(0.025000000000000001)
        self.disk.setBillboardAxis(6)
        self.disk.reparentTo(self.object)
        self.disk.setBin('shadow', 0)
        self.disk.setTransparency(TransparencyAttrib.MAlpha)
        self.disk.setDepthWrite(0)
        self.disk.setDepthTest(0)

    
    def loadUseLabel(self, text):
        self.useLabel = DirectLabel(parent = aspect2d, frameColor = (0.10000000000000001, 0.10000000000000001, 0.25, 0.20000000000000001), text = text, text_align = TextNode.ACenter, text_scale = 0.059999999999999998, text_pos = (0.02, 0.02), text_fg = (1, 1, 1, 1), text_shadow = (0, 0, 0, 1), textMayChange = 1, text_font = PiratesGlobals.getPirateOutlineFont())
        self.useLabel.setPos(0, 0, -0.69999999999999996)
        self.useLabel.setAlphaScale(0)
        self.useLabel.hide()

    
    def fadeInText(self):
        if self.fader:
            self.fader.pause()
        

    
    def interactionAllowed(self, avId):
        return True

    
    def approach(self, collEntry):
        if not self.interactionAllowed(localAvatar.doId):
            return None
        
        if not self.disk:
            self.createInteractionDisk()
        
        if self.proximityText:
            if not self.useLabel:
                self.loadUseLabel(self.proximityText)
            
            if self.fader:
                self.fader.pause()
            
            fadeIn = LerpFunctionInterval(self.useLabel.setAlphaScale, fromData = 0, toData = 1, duration = 0.5)
            self.fader = Sequence(Func(self.useLabel.show), fadeIn)
            self.fader.start()
        
        self.disk.show()
        self.accept(USE_KEY_EVENT, self.handleUseKey)

    
    def requestInteraction(self, avId):
        pass

    
    def handleUseKey(self):
        self.requestInteraction(localAvatar.doId)

    
    def leave(self, collEntry):
        if self.disk:
            self.disk.hide()
        
        if self.proximityText:
            if self.fader:
                self.fader.pause()
                self.fader = None
            
            if self.useLabel:
                self.useLabel.hide()
            
        
        self.ignore(USE_KEY_EVENT)