Exemple #1
0
    class Vehicle:
        """A moving 'vehicle' represented by a circle and with a floating text
        label that changes over time.
        
        Each vehicle uses its own Draw object, and moves itself around by
        moving the NodePath to which the Draw object is attached. A DirectLabel
        is attached to the same NodePath for textual annotation."""
    
        def __init__(self):
            """Initialise the vehicle."""
            
            # Draw a circle to represent this vehicle.
            d = Draw()                        
            d.drawXYCircle(pos = Vec3(0,0,0))
            node = d.create()
            self.np = NodePath(node)   
            self.np.reparentTo(render)
            
            # Add a text label above and to the side of this vehicle.  
            self.label=DirectLabel( parent=self.np,
                                    text="Hello! :)", 
                                    text_wordwrap=10,
                                    relief=None,
                                    text_scale=(0.5,0.5),
                                    text_frame=(0,0,0,0),
                                    text_bg=(0,0,0,0),
                                    color=(0.88,0,0.88,1))
            self.label.setPos(2,4,2) # Offset text a little from vehicle.
            self.label.setBillboardAxis()                   
                                
            # Compute a random direction for this vehicle to move in.                    
            self.direction = Vec3(random.random()-0.5,random.random()-0.5,0)
            self.direction.normalize()

            # Add a task to move this vehicle around.
            self.prevtime = 0
            taskMgr.add(self.move,"moveTask")        
            
        def move(self,task):
            """Move the vehicle around by moving it's NodePath."""
            
            speed = 5
            elapsed = task.time - self.prevtime

            # A hard-coded ugly hack to make the vehicle bounce around inside
            # the grid.
            self.np.setPos(self.np.getPos()+((self.direction*speed)*elapsed))
            text = 'X: ' + str(self.np.getPos().getX()) + '\n'           
            text += 'Y: ' + str(self.np.getPos().getY()) + '\n'
            self.label['text'] = text
                                        
            if (self.np.getPos().getX() < -50 or
                self.np.getPos().getX() > 50 or 
                self.np.getPos().getY() < -50 or
                self.np.getPos().getY() > 50
                ):
                    self.direction = -self.direction
                        
            self.prevtime = task.time
            return Task.cont
    def activate(self):
        # create main dialog frame
        # Note: frame position references the CENTER of the frame
        self.frm = DirectFrame(
            pos = (0,0,0),
            frameSize = (self.frmLeft, self.frmRight,self.frmBottom, self.frmTop),
            relief = DGG.RIDGE,
            borderWidth = (0.01, 0.01),
            frameColor = (0.6, 0.6, 0.6, 1.0))
        
        self.frm.reparentTo(base.aspect2d)
        
        # Note: wonderfully enough, label position on the other hand
        # references the CENTER of the LEFT border of the label!
        titleLabel = DirectLabel(text = self.title,
            scale = 0.04,
            frameColor = (0.5, 0.5, 0.5, 1),
            relief = DGG.RIDGE,
            borderWidth = (0.01, 0.01),
            text_align = TextNode.ALeft)
            
        titleLabel.setPos(-self.frmWidth/2+.02, 0, self.frmHeight/2-.045)
        titleLabel.reparentTo(self.frm)
        
        sc = .04     
        self.dir_edit_field = DirectEntry(
            text = '',      # prompt text
            scale = sc,
            frameColor = (0.65, 0.65, 0.65, 1),
            command=self.setText,
            width = 32,
            numLines = 1,
            focus = 1,
            focusInCommand=self.efFocusIn,
            )

        self.dir_edit_field.setPos(-self.frmWidth/2+.02, 0, self.frmHeight/2-.13)
        self.dir_edit_field.reparentTo(self.frm)

        self.statusLabel = DirectLabel(text = self.initial_status,
            scale = 0.04,
            frameColor = (0.6, 0.6, 0.6, 1),
            # relief = DGG.RIDGE,
            # borderWidth = (0.01, 0.01),
            text_align = TextNode.ALeft)
            
        self.statusLabel.setPos(-self.frmWidth/2+.02, 0, self.frmHeight/2-.2)
        self.statusLabel.reparentTo(self.frm)
 def putBuildingMarker(self, pos, hpr = (0, 0, 0), mapIndex = None):
     marker = DirectLabel(parent=self.container, text='', text_pos=(-0.05, -0.15), text_fg=(1, 1, 1, 1), relief=None)
     gui = loader.loadModel('phase_4/models/parties/schtickerbookHostingGUI')
     icon = gui.find('**/startPartyButton_inactive')
     iconNP = aspect2d.attachNewNode('iconNP')
     icon.reparentTo(iconNP)
     icon.setX(-12.0792 / 30.48)
     icon.setZ(-9.7404 / 30.48)
     marker['text'] = '%s' % mapIndex
     marker['text_scale'] = 0.7
     marker['image'] = iconNP
     marker['image_color'] = (1, 0, 0, 1)
     marker['image_scale'] = 6
     marker.setScale(0.05)
     relX, relY = self.transformAvPos(pos)
     marker.setPos(relX, 0, relY)
     self.buildingMarkers.append(marker)
     iconNP.removeNode()
     gui.removeNode()
class MainMenu(DirectObject):
    """This class represents the main menu as seen directly after the
    application has been started"""
    def __init__(self):

        # loading music
        self.menuMusic = loader.loadMusic("music/01Menu.mp3")
        self.menuMusic.setLoop(True)

        # create a main frame as big as the window
        self.frameMain = DirectFrame(
            # set framesize the same size as the window
            frameSize = (base.a2dLeft, base.a2dRight,
                         base.a2dTop, base.a2dBottom),
            # position center
            pos = (0, 0, 0),
            # set tramsparent background color
            frameColor = (0.15, 0.15, 0.15, 1))
        #self.frameMain.reparentTo(render2d)

        self.menuBackground = OnscreenImage(
            image = 'gui/Background.png',
            scale = (1.66, 1, 1),
            pos = (0, 0, 0))
        self.menuBackground.reparentTo(self.frameMain)

        self.defaultBtnMap = base.loader.loadModel("gui/button_map")
        self.buttonGeom = (
            self.defaultBtnMap.find("**/button_ready"),
            self.defaultBtnMap.find("**/button_click"),
            self.defaultBtnMap.find("**/button_rollover"),
            self.defaultBtnMap.find("**/button_disabled"))
        self.defaultTxtMap = base.loader.loadModel("gui/textbox_map")
        self.textboxGeom = self.defaultTxtMap.find("**/textbox")

        monospace = loader.loadFont('gui/DejaVuSansMono.ttf')
        defaultFont = loader.loadFont('gui/eufm10.ttf')

        # create the title
        self.textscale = 0.25
        self.title = DirectLabel(
            # scale and position
            scale = self.textscale,
            pos = (0.0, 0.0, base.a2dTop - self.textscale),
            # frame
            frameColor = (0, 0, 0, 0),
            # Text
            text = "Dungeon Crawler",
            text_align = TextNode.ACenter,
            text_fg = (0.82,0.85,0.87,1),
            text_shadow = (0, 0, 0, 1),
            text_shadowOffset = (-0.02, -0.02),
            text_font = defaultFont)
        self.title.setTransparency(1)
        self.title.reparentTo(self.frameMain)

        # create a host button
        self.btnHostPos = Vec3(0, 0, .45)
        self.btnHostScale = 0.25
        self.btnHost = DirectButton(
            # Scale and position
            scale = self.btnHostScale,
            pos = self.btnHostPos,
            # Text
            text = "Host",
            text_scale = 0.8,
            text_pos = (0, -0.2),
            text_fg = (0.82,0.85,0.87,1),
            text_shadow = (0, 0, 0, 1),
            text_shadowOffset = (-0.02, -0.02),
            text_font = defaultFont,
            # Frame
            geom = self.buttonGeom,
            frameColor = (0, 0, 0, 0),
            relief = 0,
            pressEffect = False,
            # Functionality
            command = self.host,
            rolloverSound = None,
            clickSound = None)
        self.btnHost.setTransparency(1)
        self.btnHost.reparentTo(self.frameMain)

        # create a join button
        self.btnJoinPos = Vec3(0, 0, 0)
        self.btnJoinScale = 0.25
        self.btnJoin = DirectButton(
            scale = self.btnJoinScale,
            pos = self.btnJoinPos,
            text = "Join",
            text_scale = 0.8,
            text_pos = (0, -0.2),
            text_fg = (0.82,0.85,0.87,1),
            text_shadow = (0, 0, 0, 1),
            text_shadowOffset = (-0.02, -0.02),
            text_font = defaultFont,
            geom = self.buttonGeom,
            frameColor = (0, 0, 0, 0),
            relief = 0,
            pressEffect = False,
            command = self.join,
            rolloverSound = None,
            clickSound = None)
        self.btnJoin.setTransparency(1)
        self.btnJoin.reparentTo(self.frameMain)

        # create the IP input field
        self.txtIPPos = Vec3(0, 0, -.30)
        self.txtIPScale = 0.25
        self.txtIPWidth = 9
        self.txtIP = DirectEntry(
            # scale and position
            pos = self.txtIPPos,
            scale = self.txtIPScale,
            width = self.txtIPWidth,
            # Text
            entryFont = monospace,
            text_align = TextNode.ACenter,
            text = "",
            text_scale = 0.5,
            text_pos = (0, -0.2),
            text_fg = (0.82,0.85,0.87,1),
            text_shadow = (0, 0, 0, 1),
            text_shadowOffset = (0.04, 0.04),
            initialText = "127.0.0.1",
            numLines = 1,
            # Frame
            geom = self.textboxGeom,
            frameColor = (0, 0, 0, 0),
            relief = 0,
            # Functionality
            command = self.join,
            focusInCommand = self.clearText)
        self.txtIP.reparentTo(self.frameMain)

        # create an exit button
        self.btnExitPos = Vec3(0, 0, -.75)
        self.btnExitScale = 0.25
        self.btnExit = DirectButton(
            scale = self.btnExitScale,
            pos = self.btnExitPos,
            text = "Exit",
            text_scale = 0.8,
            text_pos = (0, -0.2),
            text_fg = (0.82,0.85,0.87,1),
            text_shadow = (0, 0, 0, 1),
            text_shadowOffset = (-0.02, -0.02),
            text_font = defaultFont,
            geom = self.buttonGeom,
            frameColor = (0, 0, 0, 0),
            relief = 0,
            pressEffect = False,
            command = lambda: base.messenger.send("escape"),
            rolloverSound = None,
            clickSound = None)
        self.btnExit.setTransparency(1)
        self.btnExit.reparentTo(self.frameMain)

        # create a mute checkbox
        self.cbVolumeMute = DirectCheckBox(
            # set size
            scale = (0.1, 0.1, 0.1),
            frameSize = (-1, 1, 1, -1),
            # functionality and visuals
            command = self.cbVolumeMute_CheckedChanged,
            isChecked = True,
            checkedImage = "gui/SoundSwitch_off.png",
            uncheckedImage = "gui/SoundSwitch_on.png",
            # mouse behaviour
            relief = 0,
            pressEffect = False,
            rolloverSound = None,
            clickSound = None
            )
        self.cbVolumeMute.setTransparency(1)
        self.cbVolumeMute.reparentTo(self.frameMain)
        self.cbVolumeMute.commandFunc(None)

        # catch window resizes and recalculate the aspectration
        self.accept("window-event", self.recalcAspectRatio)
        self.accept("showerror", self.showError)

        # show the menu right away
        self.show()

    def host(self):
        """Function which will be called by pressing the host button"""
        self.hide()
        base.messenger.send("start_server")

    def join(self, ip=None):
        """Function which will be called by pressing the join button"""
        if ip == None: ip = self.txtIP.get(True)
        if ip == "": return
        self.hide()
        base.messenger.send("start_client", [ip])

    def showError(self, msg):
        self.show()
        self.dialog = OkDialog(
            dialogName="ErrorDialog",
            text="Error: {}".format(msg),
            command=self.closeDialog)

    def closeDialog(self, args):
        self.dialog.hide()

    def show(self):
        """Show the GUI"""
        self.frameMain.show()
        self.menuMusic.play()

    def hide(self):
        """Hide the GUI"""
        self.frameMain.hide()
        self.menuMusic.stop()

    def clearText(self):
        """Function to clear the text that was previously entered in the
        IP input field"""
        self.txtIP.enterText("")

    def cbVolumeMute_CheckedChanged(self, checked):
        if bool(checked):
            base.disableAllAudio()
        else:
            base.enableAllAudio()

    def recalcAspectRatio(self, window):
        """get the new aspect ratio to resize the mainframe"""
        # set the mainframe size to the window borders again
        self.frameMain["frameSize"] = (
            base.a2dLeft, base.a2dRight,
            base.a2dTop, base.a2dBottom)

        # calculate new aspec tratio
        wp = window.getProperties()
        aspX = 1.0
        aspY = 1.0
        wpXSize = wp.getXSize()
        wpYSize = wp.getYSize()
        if wpXSize > wpYSize:
            aspX = wpXSize / float(wpYSize)
        else:
            aspY = wpYSize / float(wpXSize)
        # calculate new position/size/whatever of the gui items
        self.title.setPos(0.0, 0.0, base.a2dTop - self.textscale)
        self.menuBackground.setScale(1.0 * aspX, 1.0, 1.0 * aspY)
        self.cbVolumeMute.setPos(base.a2dRight - 0.15, 0, base.a2dBottom + 0.15)
class RepairGameButton(GuiButton):
    
    def __init__(self, parent, **kw):
        optiondefs = (('nodePath', None, None), ('image_scale', (1.0, 1.0, 1.0), None))
        self.defineoptions(kw, optiondefs)
        GuiButton.__init__(self, parent)
        self.initialiseoptions(RepairGameButton)
        self.disabledStateNode = self.stateNodePath[3].getChild(0)
        self.downStateNode = self.stateNodePath[1].getChild(0)
        self.overStateNode = self.stateNodePath[2].getChild(0)
        self.inProgress = False
        self._initGUI()

    
    def _initGUI(self):
        self.setBin('fixed', 33)
        mainGui = loader.loadModel('models/gui/gui_main')
        gui = loader.loadModel('models/gui/toplevel_gui')
        self.checkMark = gui.find('**/generic_check')
        self.checkMark.reparentTo(self)
        self.checkMark.stash()
        self.checkMark.setScale(1.0)
        self.checkMark.setColorScale(0.0, 1.0, 0.0, 1.0)
        self.checkMark.setPos(0.02, 0.0, 0.02)
        self.checkMark.setBin('fixed', 34)
        self.skillRing = DialMeter(self, wantCover = False, dangerRatio = 0.0, meterColor = Vec4(0.90000000000000002, 0.90000000000000002, 0.10000000000000001, 1.0), baseColor = Vec4(0.14999999999999999, 0.070000000000000007, 0.029999999999999999, 1.0), completeColor = Vec4(0.10000000000000001, 0.90000000000000002, 0.10000000000000001, 1.0))
        self.skillRing.reparentTo(self)
        self.skillRing.setScale(0.28499999999999998, 0.29999999999999999, 0.26500000000000001)
        self.skillRing.setBin('fixed', 32)
        self.skillGlow = OnscreenImage(parent = self, image = mainGui.find('**/icon_glow'), scale = (1.0, 1.0, 1.0), color = (1.0, 1.0, 0.59999999999999998, 1.0))
        self.glow = OnscreenImage(parent = self, image = mainGui.find('**/icon_glow'), scale = (1.0, 1.0, 1.0), color = (1.0, 1.0, 0.59999999999999998, 1.0))
        self.skillGlow.reparentTo(self)
        self.skillGlow.setBin('fixed', 31)
        self.skillGlow.stash()
        self.pirateNameBox = None
        self.pirateNameLabel = None

    
    def showGlow(self):
        self.inProgress = False
        if self.pirateNameLabel == None and self.checkMark.isStashed():
            self.skillGlow.unstash()
        

    
    def hideGlow(self):
        self.inProgress = True
        self.skillGlow.stash()

    
    def setProgress(self, percent):
        self.skillGlow.stash()
        ratio = max(0.0, percent / 100.0)
        if ratio >= 1.0:
            if self.checkMark.isStashed():
                self.checkMark.unstash()
            
        elif not self.checkMark.isStashed():
            self.checkMark.stash()
        
        if self.pirateNameLabel == None and not (self.inProgress):
            self.skillGlow.unstash()
        
        self.skillRing.update(ratio, 1.0)
        self.skillRing.wrtReparentTo(self.getParent())
        self.reparentTo(self.getParent())

    
    def updatePirateNameBox(self, pirateName):
        if self.pirateNameLabel != None and self.pirateNameLabel['text'] != pirateName:
            if self.pirateNameBox:
                self.pirateNameBox.destroy()
            
            if self.pirateNameLabel:
                self.pirateNameLabel.destroy()
            
            self.pirateNameBox = None
            self.pirateNameLabel = None
        
        if pirateName != '':
            if self.pirateNameBox:
                pass
            if not (self.pirateNameLabel['text'] == pirateName):
                self.createPirateNameBox(pirateName)
            

    
    def createPirateNameBox(self, pirateName):
        self.pirateNameLabel = DirectLabel(relief = None, state = DGG.DISABLED, text = pirateName, text_align = TextNode.ACenter, text_scale = PiratesGuiGlobals.TextScaleMed, text_fg = PiratesGuiGlobals.TextFG1, text_wordwrap = 12, textMayChange = 0, sortOrder = 91)
        self.pirateNameLabel.setBin('fixed', 33)
        height = self.pirateNameLabel.getHeight()
        width = self.pirateNameLabel.getWidth() + 0.050000000000000003
        pos = [
            0.0,
            0.0,
            height / 2 - 0.035000000000000003]
        fs = [
            -(width / 2 + 0.01),
            width / 2 + 0.01,
            -(height / 2 + 0.014999999999999999),
            height / 2 + 0.014999999999999999]
        self.pirateNameBox = BorderFrame(parent = self, state = DGG.DISABLED, frameSize = (fs[0], fs[1], fs[2], fs[3]), modelName = 'general_frame_f', pos = (0.0, 0.0, 0.0))
        self.pirateNameLabel.reparentTo(self.pirateNameBox)
        self.pirateNameLabel.setPos(pos[0], pos[1], pos[2])
        self.pirateNameBox.setClipPlaneOff()
        pos = self.pirateNameBox.getPos(aspect2d)
        x = min(pos[0], base.a2dRight - width)
        z = max(pos[2], base.a2dBottom - height)
        self.pirateNameBox.setPos(aspect2d, x, 0, z - 0.17499999999999999)
        self.pirateNameBox.flattenLight()
        self.pirateNameBox.setBin('fixed', 32)
        self.pirateNameBox.reparentTo(self)
Exemple #6
0
class QuestMap(DirectFrame):

    def __init__(self, av, **kw):
        DirectFrame.__init__(self, relief=None, sortOrder=50)
        self.initialiseoptions(QuestMap)
        self.container = DirectFrame(parent=self, relief=None)
        self.marker = DirectFrame(parent=self.container, relief=None)
        self.cogInfoFrame = DirectFrame(parent=self.container, relief=None)
        cm = CardMaker('bg')
        cm.setFrame(-0.5, 0.5, -0.5, 0.5)
        bg = self.cogInfoFrame.attachNewNode(cm.generate())
        bg.setTransparency(1)
        bg.setColor(0.5, 0.5, 0.5, 0.5)
        bg.setBin('fixed', 0)
        self.cogInfoFrame['geom'] = bg
        self.cogInfoFrame['geom_pos'] = (1.2, 0, 0)
        self.cogInfoFrame['geom_scale'] = (9, 1, 2)
        self.cogInfoFrame.setScale(0.05)
        self.cogInfoFrame.setPos(0, 0, 0.6)
        self.buildingMarkers = []
        self.suitBuildingMarkers = []
        self.questBlocks = []
        self.av = av
        self.wantToggle = False
        if base.config.GetBool('want-toggle-quest-map', True):
            self.wantToggle = True
        self.updateMarker = True
        self.cornerPosInfo = None
        self.hqPosInfo = None
        self.fishingSpotInfo = None
        self.load()
        self.setScale(1.5)
        bg.removeNode()
        self.hoodId = None
        self.zoneId = None
        self.suitPercentage = {}
        for currHoodInfo in SuitPlannerBase.SuitPlannerBase.SuitHoodInfo:
            tracks = currHoodInfo[SuitPlannerBase.SuitPlannerBase.SUIT_HOOD_INFO_TRACK]
            self.suitPercentage[currHoodInfo[SuitPlannerBase.SuitPlannerBase.SUIT_HOOD_INFO_ZONE]] = tracks

        return

    def load(self):
        gui = loader.loadModel('phase_4/models/questmap/questmap_gui')
        icon = gui.find('**/tt_t_gui_qst_arrow')
        iconNP = aspect2d.attachNewNode('iconNP')
        icon.reparentTo(iconNP)
        icon.setR(90)
        self.marker['geom'] = iconNP
        self.marker['image'] = iconNP
        self.marker.setScale(0.05)
        iconNP.removeNode()
        self.mapOpenButton = DirectButton(image=(gui.find('**/tt_t_gui_qst_mapClose'), gui.find('**/tt_t_gui_qst_mapClose'), gui.find('**/tt_t_gui_qst_mapTryToOpen')), relief=None, pos=(-0.08, 0, 0.37), parent=base.a2dBottomRight, scale=0.205, command=self.show)
        self.mapCloseButton = DirectButton(image=(gui.find('**/tt_t_gui_qst_mapOpen'), gui.find('**/tt_t_gui_qst_mapOpen'), gui.find('**/tt_t_gui_qst_mapTryToClose')), relief=None, pos=(-0.08, 0, 0.37), parent=base.a2dBottomRight, scale=0.205, command=self.hide)
        self.mapOpenButton.hide()
        self.mapCloseButton.hide()
        gui.removeNode()
        icons = loader.loadModel('phase_3/models/gui/cog_icons')
        cIcon = icons.find('**/CorpIcon')
        lIcon = icons.find('**/LegalIcon')
        mIcon = icons.find('**/MoneyIcon')
        sIcon = icons.find('**/SalesIcon')
        gIcon = icons.find('**/BoardIcon')
        cogInfoTextColor = (0.2, 0.2, 0.2, 1)
        textPos = (1.2, -0.2)
        textScale = 0.8
        self.cInfo = DirectLabel(parent=self.cogInfoFrame, text='', text_fg=cogInfoTextColor, text_pos=textPos, text_scale=textScale, geom=cIcon, geom_pos=(0, 0, 0), geom_scale=0.6, relief=None)
        self.cInfo.setPos(-2.2, 0, 0.5)
        self.lInfo = DirectLabel(parent=self.cogInfoFrame, text_fg=cogInfoTextColor, text='', text_pos=textPos, text_scale=textScale, geom=lIcon, geom_pos=(0, 0, 0), geom_scale=0.6, relief=None)
        self.lInfo.setPos(-2.2, 0, -0.5)
        self.mInfo = DirectLabel(parent=self.cogInfoFrame, text_fg=cogInfoTextColor, text='', text_pos=textPos, text_scale=textScale, geom=mIcon, geom_pos=(0, 0, 0), geom_scale=0.6, relief=None)
        self.mInfo.setPos(0.8, 0, 0.5)
        self.sInfo = DirectLabel(parent=self.cogInfoFrame, text_fg=cogInfoTextColor, text='', text_pos=textPos, text_scale=textScale, geom=sIcon, geom_pos=(0, 0, 0), geom_scale=0.6, relief=None)
        self.sInfo.setPos(0.8, 0, -0.5)
        self.gInfo = DirectLabel(parent=self.cogInfoFrame, text_fg=cogInfoTextColor, text='', text_pos=textPos, text_scale=textScale, geom=gIcon, geom_pos=(0, 0, 0), geom_scale=0.6, relief=None)
        self.gInfo.setPos(3.2, 0, 0.5)
        icons.removeNode()
        return

    def updateCogInfo(self):
        currPercentage = self.suitPercentage.get(self.zoneId)
        if currPercentage is None:
            return
        self.cInfo['text'] = '%s%%' % currPercentage[0]
        self.lInfo['text'] = '%s%%' % currPercentage[1]
        self.mInfo['text'] = '%s%%' % currPercentage[2]
        self.sInfo['text'] = '%s%%' % currPercentage[3]
        self.gInfo['text'] = '%s%%' % currPercentage[4]
        return

    def destroy(self):
        self.ignore('questPageUpdated')
        self.mapOpenButton.destroy()
        self.mapCloseButton.destroy()
        del self.mapOpenButton
        del self.mapCloseButton
        DirectFrame.destroy(self)

    def putBuildingMarker(self, pos, hpr = (0, 0, 0), mapIndex = None, isSuitBlock=False):
        marker = DirectLabel(parent = self.container, text='', text_pos = (-0.05, -0.15), text_fg = (1, 1, 1, 1), relief = None)
        gui = loader.loadModel('phase_4/models/parties/schtickerbookHostingGUI')
        icon = gui.find('**/startPartyButton_inactive')
        iconNP = aspect2d.attachNewNode('iconNP')
        icon.reparentTo(iconNP)
        icon.setX(-12.0792 / 30.48)
        icon.setZ(-9.7404 / 30.48)
        marker['text'] = '%s' % mapIndex
        marker['text_scale'] = 0.7
        marker['image'] = iconNP
        if isSuitBlock: # Make the bubble appear gray if a cog took over a task building
            marker['image_color'] = (0.5, 0.5, 0.5, 1)
        else:
            marker['image_color'] = (1, 0, 0, 1)
        marker['image_scale'] = 6
        marker.setScale(0.05)
        relX, relY = self.transformAvPos(pos)
        marker.setPos(relX, 0, relY)
        self.buildingMarkers.append(marker)
        iconNP.removeNode()
        gui.removeNode()
        return
        
    def putSuitBuildingMarker(self, pos, hpr = (0, 0, 0), blockNumber = None, track = None):
        if base.localAvatar.buildingRadar[SuitDNA.suitDepts.index(track)]:
            marker = DirectLabel(parent = self.container, text = '', text_pos = (-0.05, -0.15), text_fg = (1, 1, 1, 1),  relief = None)
            icon = self.getSuitIcon(track)
            iconNP = aspect2d.attachNewNode('suitBlock-%s' % blockNumber)
            icon.reparentTo(iconNP)
            marker['image'] = iconNP
            marker['image_scale'] = 1
            marker.setScale(0.05)
            relX, relY = self.transformAvPos(pos)
            marker.setPos(relX, 0, relY)
            self.suitBuildingMarkers.append(marker)
            iconNP.removeNode()
        else:
            pass

    def putCogdoBuildingMarker(self, pos, hpr = (0, 0, 0), blockNumber = None, track = None):
        if base.localAvatar.buildingRadar[SuitDNA.suitDepts.index(track)]:
            marker = DirectLabel(parent = self.container, text = '', relief = None)
            marker['image'] = self.getCogdoIcon(track)
            marker['image_scale'] = .5
            marker.setTransparency(1)
            marker.setScale(0.05)
            relX, relY = self.transformAvPos(pos)
            marker.setPos(relX, 0, relY)
            self.suitBuildingMarkers.append(marker)
        else:
            pass
        
    def getSuitIcon(self, dept):
        icons = loader.loadModel('phase_3/models/gui/cog_icons')
        if dept == 'c':
            corpIcon = icons.find('**/CorpIcon')
        elif dept == 's':
            corpIcon = icons.find('**/SalesIcon')
        elif dept == 'l':
            corpIcon = icons.find('**/LegalIcon')
        elif dept == 'm':
            corpIcon = icons.find('**/MoneyIcon')
        elif dept == 'g':
            corpIcon = icons.find('**/BoardIcon')
        else:
            corpIcon = None
        icons.removeNode()
        return corpIcon
        
    def getCogdoIcon(self, dept):
        if dept == 's':
            image = 'phase_3.5/maps/sbfo.png'
        if dept == 'l':
            image = 'phase_3.5/maps/lbfo.png'
        else:
            image = None
        return image
        
    def updateQuestInfo(self):
        for marker in self.buildingMarkers:
            marker.destroy()

        self.buildingMarkers = []
        self.questBlocks = []
        
        for (i, questDesc) in enumerate(self.av.quests):
            mapIndex = i + 1
            quest = Quests.getQuest(questDesc[0])
            toNpcId = questDesc[2]
            if quest is None:
                return

            completed = quest.getCompletionStatus(self.av, questDesc) == Quests.COMPLETE
            if not completed:
                if quest.getType() == Quests.RecoverItemQuest:
                    if quest.getHolder() == Quests.AnyFish:
                        self.putBuildingMarker(self.fishingSpotInfo, mapIndex=mapIndex)
                    continue
                elif quest.getType() not in (
                    Quests.DeliverGagQuest, Quests.DeliverItemQuest,
                    Quests.VisitQuest, Quests.TrackChoiceQuest):
                    continue

            if toNpcId == Quests.ToonHQ:
                self.putBuildingMarker(self.hqPosInfo, mapIndex=mapIndex)
                continue

            npcZoneId = NPCToons.getNPCZone(toNpcId)
            hoodId = ZoneUtil.getCanonicalHoodId(npcZoneId)
            branchId = ZoneUtil.getCanonicalBranchZone(npcZoneId)

            if (self.hoodId != hoodId) or (self.zoneId != branchId):
                continue

            for blockIndex in xrange(base.cr.playGame.dnaStore.getNumBlockNumbers()):
                blockNumber = base.cr.playGame.dnaStore.getBlockNumberAt(blockIndex)
                zoneId = base.cr.playGame.dnaStore.getZoneFromBlockNumber(blockNumber)
                interiorZoneId = (zoneId - (zoneId%100)) + 500 + blockNumber
                if npcZoneId == interiorZoneId:
                    self.questBlocks.append(blockNumber)
                    self.putBuildingMarker(
                        base.cr.playGame.dnaStore.getDoorPosHprFromBlockNumber(blockNumber).getPos(render),
                        base.cr.playGame.dnaStore.getDoorPosHprFromBlockNumber(blockNumber).getHpr(render),
                        mapIndex=mapIndex,
                        isSuitBlock=base.cr.playGame.dnaStore.isSuitBlock(blockNumber))
                    continue
                    
        for blockIndex in xrange(base.cr.playGame.dnaStore.getNumBlockNumbers()):
            blockNumber = base.cr.playGame.dnaStore.getBlockNumberAt(blockIndex)
            if base.cr.playGame.dnaStore.isSuitBlock(blockNumber) and blockNumber not in self.questBlocks:
                self.putSuitBuildingMarker(
                    base.cr.playGame.dnaStore.getDoorPosHprFromBlockNumber(blockNumber).getPos(render),
                    base.cr.playGame.dnaStore.getDoorPosHprFromBlockNumber(blockNumber).getHpr(render),
                    blockNumber,
                    base.cr.playGame.dnaStore.getSuitBlockTrack(blockNumber))
                    
            if base.cr.playGame.dnaStore.isCogdoBlock(blockNumber) and blockNumber not in self.questBlocks:
                self.putCogdoBuildingMarker(
                    base.cr.playGame.dnaStore.getDoorPosHprFromBlockNumber(blockNumber).getPos(render),
                    base.cr.playGame.dnaStore.getDoorPosHprFromBlockNumber(blockNumber).getHpr(render),
                    blockNumber,
                    base.cr.playGame.dnaStore.getCogdoBlockTrack(blockNumber))
                continue
                
    def transformAvPos(self, pos):
        if self.cornerPosInfo is None:
            return (0, 0)
        topRight = self.cornerPosInfo[0]
        bottomLeft = self.cornerPosInfo[1]
        relativeX = (pos.getX() - bottomLeft.getX()) / (topRight.getX() - bottomLeft.getX()) - 0.5
        relativeY = (pos.getY() - bottomLeft.getY()) / (topRight.getY() - bottomLeft.getY()) - 0.5
        return (relativeX, relativeY)

    def update(self, task):
        if self.av:
            if self.updateMarker:
                relX, relY = self.transformAvPos(self.av.getPos())
                self.marker.setPos(relX, 0, relY)
                self.marker.setHpr(0, 0, -180 - self.av.getH())
        i = 0
        for buildingMarker in self.buildingMarkers:
            if not buildingMarker.isEmpty():
                buildingMarker.setScale((math.sin(task.time * 16.0 + i * math.pi / 3.0) + 1) * 0.005 + 0.04)
                i = i + 1
        for buildingMarker in self.suitBuildingMarkers:
            if not buildingMarker.isEmpty():
                buildingMarker.setScale((math.sin(task.time * 16.0 + i * math.pi / 3.0) + 1) * 0.005 + 0.04)
                i = i + 1
                
        return Task.cont

    def updateMap(self):
        if self.av:
            hoodId = ZoneUtil.getCanonicalHoodId(self.av.getLocation()[1])
            zoneId = ZoneUtil.getCanonicalBranchZone(self.av.getLocation()[1])
            try:
                mapsGeom = loader.loadModel('phase_4/models/questmap/%s_maps' % ToontownGlobals.dnaMap[hoodId])
            except:
                self.stop()
                return
            mapImage = mapsGeom.find('**/%s_%s_english' % (ToontownGlobals.dnaMap[hoodId], zoneId))
            if not mapImage.isEmpty():
                self.container['image'] = mapImage
                self.resetFrameSize()
                self.cornerPosInfo = QuestMapGlobals.CornerPosTable.get('%s_%s_english' % (ToontownGlobals.dnaMap[hoodId], zoneId))
                self.hqPosInfo = QuestMapGlobals.HQPosTable.get('%s_%s_english' % (ToontownGlobals.dnaMap[hoodId], zoneId))
                self.fishingSpotInfo = QuestMapGlobals.FishingSpotPosTable.get('%s_%s_english' % (ToontownGlobals.dnaMap[hoodId], zoneId))
                self.cogInfoPos = QuestMapGlobals.CogInfoPosTable.get('%s_%s_english' % (ToontownGlobals.dnaMap[hoodId], zoneId))
                self.cogInfoFrame.setPos(self.cogInfoPos)
                self.hide()
                self.hoodId = hoodId
                self.zoneId = zoneId
                self.updateQuestInfo()
                self.updateCogInfo()
                taskMgr.add(self.update, 'questMapUpdate')
            else:
                self.stop()
                mapsGeom.removeNode()

    def start(self):
        self.container.show()
        self.accept('questPageUpdated', self.updateMap)
        self.handleMarker()
        self.updateMap()

    def initMarker(self, task):
        if self.av:
            if not hasattr(base.cr.playGame.getPlace(), 'isInterior') or not base.cr.playGame.getPlace().isInterior:
                relX, relY = self.transformAvPos(self.av.getPos())
                self.marker.setPos(relX, 0, relY)
                self.marker.setHpr(0, 0, -180 - self.av.getH())
            self.marker['geom_scale'] = 1.4 * task.time % 0.5 * 10 + 1
            self.marker['geom_color'] = (1,
             1,
             1,
             0.8 - 1.4 * task.time % 0.5 * 2 / 0.8 + 0.2)
        if task.time < 1:
            return Task.cont
        else:
            self.marker['geom_color'] = (1, 1, 1, 0)
            return Task.done

    def show(self):
        taskMgr.add(self.initMarker, 'questMapInit')
        DirectFrame.show(self)
        self.mapOpenButton.hide()
        if self.container['image']:
            self.mapCloseButton.show()

    def hide(self):
        taskMgr.remove('questMapInit')
        DirectFrame.hide(self)
        if self.container['image']:
            self.mapOpenButton.show()
        self.mapCloseButton.hide()

    def toggle(self):
        if self.isHidden():
            self.show()
        else:
            self.hide()

    def obscureButton(self):
        self.mapOpenButton.hide()
        self.mapCloseButton.hide()

    def stop(self):
        self.container['image'] = None
        for marker in self.buildingMarkers:
            marker.destroy()
        for marker in self.suitBuildingMarkers:
            marker.destroy()
            
        self.buildingMarkers = []
        self.suitBuildingMarkers = []
        self.questBlocks = []
        self.container.hide()
        self.hide()
        self.obscureButton()
        self.ignore('questPageUpdated')
        taskMgr.remove('questMapUpdate')
        return

    def handleMarker(self):
        if hasattr(base.cr.playGame.getPlace(), 'isInterior') and base.cr.playGame.getPlace().isInterior:
            self.updateMarker = False
        else:
            self.updateMarker = True

    def acceptOnscreenHooks(self):
        if self.wantToggle:
            self.accept(ToontownGlobals.MapHotkey, self.toggle)
        else:
            self.accept(ToontownGlobals.MapHotkeyOn, self.show)
            self.accept(ToontownGlobals.MapHotkeyOff, self.hide)
        self.updateMap()

    def ignoreOnscreenHooks(self):
        self.ignore(ToontownGlobals.MapHotkey)
        self.ignore(ToontownGlobals.MapHotkeyOn)
        self.ignore(ToontownGlobals.MapHotkeyOff)
        self.obscureButton()
Exemple #7
0
    def createGui(self):
        base.cr.renderFrame()

        self.m = loader.loadFont("phase_3/models/fonts/MickeyFont.bam")
        self.bg = loader.loadModel(
            "phase_3/models/gui/tt_m_gui_pat_mainGui.bam")
        self.qtbtn = loader.loadModel("phase_3/models/gui/quit_button.bam")

        self.trash_gui = loader.loadModel(
            "phase_3/models/gui/trashcan_gui.bam")

        self.bg_img = OnscreenImage(
            image=self.bg.find('**/tt_t_gui_pat_background'))

        self.setTitle("Pick  A  Toon  To  Play")

        base.setBackgroundColor(self.BgColor)

        self.btn1 = DirectButton(
            geom=self.bg.find('**/tt_t_gui_pat_squareGreen'),
            relief=None,
            pos=(0.012, 0, 0.306),
            text_wordwrap=6,
            text_fg=(1, 1, 1, 1))
        self.btn2 = DirectButton(
            geom=self.bg.find('**/tt_t_gui_pat_squarePink'),
            relief=None,
            pos=(0.01, 0, -0.515),
            text_wordwrap=6,
            text_fg=(1, 1, 1, 1))
        self.btn3 = DirectButton(
            geom=self.bg.find('**/tt_t_gui_pat_squareRed'),
            relief=None,
            pos=(-0.84, 0, 0.36),
            text_wordwrap=6,
            text_fg=(1, 1, 1, 1))
        self.btn4 = DirectButton(
            geom=self.bg.find('**/tt_t_gui_pat_squareYellow'),
            relief=None,
            pos=(0.865, 0, -0.45),
            text_wordwrap=6,
            text_fg=(1, 1, 1, 1))
        self.btn5 = DirectButton(
            geom=self.bg.find('**/tt_t_gui_pat_squareBlue'),
            relief=None,
            pos=(-0.87, 0, -0.44),
            text_wordwrap=6,
            text_fg=(1, 1, 1, 1))
        self.btn6 = DirectButton(
            geom=self.bg.find('**/tt_t_gui_pat_squarePurple'),
            relief=None,
            pos=(0.873, 0, 0.335),
            text_wordwrap=6,
            text_fg=(1, 1, 1, 1))

        self.quit_btn = DirectButton(geom=(self.qtbtn.find('**/QuitBtn_RLVR'),
                                           self.qtbtn.find('**/QuitBtn_RLVR'),
                                           self.qtbtn.find('**/QuitBtn_RLVR')),
                                     relief=None,
                                     text="Quit",
                                     text_font=self.m,
                                     text_scale=0.105,
                                     text_pos=(0, -0.035),
                                     pos=(1.05, 0, -0.9),
                                     text_fg=(1, 0.9, 0.1, 1),
                                     geom1_scale=(1.02, 1, 1),
                                     geom2_scale=(1.02, 1, 1),
                                     command=self.quitGame)

        self.btnList = []
        self.btnList.append(self.btn1)
        self.btnList.append(self.btn2)
        self.btnList.append(self.btn3)
        self.btnList.append(self.btn4)
        self.btnList.append(self.btn5)
        self.btnList.append(self.btn6)

        self.headList = []

        #datafiler = open("toons/data.txt", "r")
        #if datafiler.read() == "-":
        #	for btn in self.btnList:
        #		btn['state'] = DGG.DISABLED
        #	self.quit_btn['state'] = DGG.DISABLED
        #	self.tutorial.askTutorial()
        #	datafilew = open("toons/data.txt", "w")
        #	datafilew.write("+")
        #	datafilew.flush()
        #	datafilew.close()
        #datafiler.close()

        for slot in range(6):
            if self.avChooser.hasToonInSlot(slot):
                notify.info("found existing Toon in slot %s" % (str(slot)))
                frame = DirectFrame(relief=None,
                                    parent=self.btnList[slot],
                                    pos=(0, 0, -0.1))
                headframe = hidden.attachNewNode('head')
                headframe.setPosHprScale(0, 5, -0.1, 180, 0, 0, 0.24, 0.24,
                                         0.24)
                headframe.reparentTo(self.btnList[slot].stateNodePath[0], 20)
                headframe.instanceTo(self.btnList[slot].stateNodePath[1], 20)
                headframe.instanceTo(self.btnList[slot].stateNodePath[2], 20)
                toon = ToonHead(base.cr)
                self.headList.append(toon)
                gender, animal, head, headcolor = self.avChooser.getHeadInfo(
                    slot)
                toon.generateHead(gender, animal, head, 1)
                toon.getGeomNode().setDepthWrite(1)
                toon.getGeomNode().setDepthTest(1)
                toon.startBlink()
                toon.startLookAround()
                toon.reparentTo(headframe)
                toon.setHeadColor(headcolor)
                toon.flattenLight()
                name_lbl = DirectLabel(text=self.avChooser.getNameInSlot(slot),
                                       text_scale=0.08,
                                       text_fg=(1, 1, 1, 1),
                                       text_wordwrap=7,
                                       relief=None,
                                       text_shadow=(0, 0, 0, 1))
                name_lbl.reparentTo(self.btnList[slot].stateNodePath[0], 20)
                name_lbl.instanceTo(self.btnList[slot].stateNodePath[1], 20)
                name_lbl.instanceTo(self.btnList[slot].stateNodePath[2], 20)
                name_lbl.setPos(self.name_pos[slot])
                name_lbl.setHpr(self.name_hpr[slot])
                self.btnList[slot]['text'] = ("", "Play This Toon",
                                              "Play This Toon", "")
                self.btnList[slot]['text_scale'] = 0.1
                self.btnList[slot]['text_pos'] = (0, 0)
                self.btnList[slot]['text_fg'] = (1, 0.9, 0, 1)
                self.btnList[slot]['text_wordwrap'] = 6
                self.btnList[slot]['text_font'] = self.m
                self.btnList[slot]['command'] = self.fadeMenu
                self.btnList[slot]['extraArgs'] = ["playGame", slot]
                delBtn = DirectButton(
                    text=("", "Delete", "Delete", ""),
                    text_scale=0.15,
                    scale=0.5,
                    text_pos=(0, -0.1),
                    text_fg=(1, 1, 1, 1),
                    relief=None,
                    geom=(self.trash_gui.find('**/TrashCan_CLSD'),
                          self.trash_gui.find('**/TrashCan_OPEN'),
                          self.trash_gui.find('**/TrashCan_RLVR')),
                    pos=self.trash_pos[slot],
                    command=self.deleteToon,
                    extraArgs=[
                        self.avChooser.getAvChoiceBySlot(slot).getAvId()
                    ],
                    text_shadow=(0, 0, 0, 1))
                delBtn.reparentTo(self.btnList[slot].stateNodePath[0], 20)
                delBtn.instanceTo(self.btnList[slot].stateNodePath[1], 20)
                delBtn.instanceTo(self.btnList[slot].stateNodePath[2], 20)
            else:
                self.btnList[slot]['text'] = "Make A Toon"
                self.btnList[slot]['text_font'] = self.m
                self.btnList[slot]['text0_scale'] = 0.1
                self.btnList[slot]['text1_scale'] = 0.12
                self.btnList[slot]['text2_scale'] = 0.12
                self.btnList[slot]['text3_scale'] = 0.1
                self.btnList[slot]['text0_fg'] = (0, 1, 0.8, 0.5)
                self.btnList[slot]['text1_fg'] = (0, 1, 0.8, 1)
                self.btnList[slot]['text2_fg'] = (0.3, 1, 0.9, 1)
                self.btnList[slot]['text3_fg'] = (0, 1, 0.8, 0.5)
                self.btnList[slot]['text_font'] = self.m
                self.btnList[slot]['command'] = self.fadeMenu
                self.btnList[slot]['extraArgs'] = ["mat", slot]
                self.btnList[slot]['text_wordwrap'] = 6
Exemple #8
0
class FileDialog(DirectObject):

    def __init__(self, title, initial_status, callback):
        self.frmLeft = -.7
        self.frmBottom = -.12
        self.frmRight = .7
        self.frmTop = .12
        
        self.frmWidth = self.frmRight - self.frmLeft
        self.frmHeight = self.frmTop - self.frmBottom
        
        self.title = title
        self.initial_status = initial_status
        self.callback = callback
        
        self.result = None
        self.done = 0
            
            
    def activate(self):
        # create main dialog frame
        # Note: frame position references the CENTER of the frame
        self.frm = DirectFrame(
            pos = (0,0,0),
            frameSize = (self.frmLeft, self.frmRight,self.frmBottom, self.frmTop),
            relief = DGG.RIDGE,
            borderWidth = (0.01, 0.01),
            frameColor = (0.6, 0.6, 0.6, 1.0))
        
        self.frm.reparentTo(base.aspect2d)
        
        # Note: wonderfully enough, label position on the other hand
        # references the CENTER of the LEFT border of the label!
        titleLabel = DirectLabel(text = self.title,
            scale = 0.04,
            frameColor = (0.5, 0.5, 0.5, 1),
            relief = DGG.RIDGE,
            borderWidth = (0.01, 0.01),
            text_align = TextNode.ALeft)
            
        titleLabel.setPos(-self.frmWidth/2+.02, 0, self.frmHeight/2-.045)
        titleLabel.reparentTo(self.frm)
        
        sc = .04     
        self.dir_edit_field = DirectEntry(
            text = '',      # prompt text
            scale = sc,
            frameColor = (0.65, 0.65, 0.65, 1),
            command=self.setText,
            width = 32,
            numLines = 1,
            focus = 1,
            focusInCommand=self.efFocusIn,
            )

        self.dir_edit_field.setPos(-self.frmWidth/2+.02, 0, self.frmHeight/2-.13)
        self.dir_edit_field.reparentTo(self.frm)

        self.statusLabel = DirectLabel(text = self.initial_status,
            scale = 0.04,
            frameColor = (0.6, 0.6, 0.6, 1),
            # relief = DGG.RIDGE,
            # borderWidth = (0.01, 0.01),
            text_align = TextNode.ALeft)
            
        self.statusLabel.setPos(-self.frmWidth/2+.02, 0, self.frmHeight/2-.2)
        self.statusLabel.reparentTo(self.frm)

    # call this if you need to run a form before your mainloop starts steppping the taskMgr
    def run(self):
        while self.done != 1:
            taskMgr.step()

        taskMgr.step()          # once more to make the last output from the dialog visible
                                # while we load a zone
        self.frm.removeNode()

    def end(self):
        self.frm.removeNode()
        

    # callback function to set  text: called by the Panda3d taskMgr when the user
    # has entered something into the DirectEntry widget
    def setText(self, textEntered):
        print 'dir_edit_field::setText:', textEntered
        self.done = self.callback(textEntered)
        if self.done != 1:
            self.dir_edit_field['focus'] = 1

                
    #clear the text
    def efFocusIn(self):
        print 'focus in'
        self.dir_edit_field.enterText('')
        
    def setStatus(self, status):
        self.statusLabel['text'] = status
Exemple #9
0
class RepairGameButton(GuiButton):
    def __init__(self, parent, **kw):
        optiondefs = (('nodePath', None, None), ('image_scale', (1.0, 1.0,
                                                                 1.0), None))
        self.defineoptions(kw, optiondefs)
        GuiButton.__init__(self, parent)
        self.initialiseoptions(RepairGameButton)
        self.disabledStateNode = self.stateNodePath[3].getChild(0)
        self.downStateNode = self.stateNodePath[1].getChild(0)
        self.overStateNode = self.stateNodePath[2].getChild(0)
        self.inProgress = False
        self._initGUI()
        return

    def _initGUI(self):
        self.setBin('fixed', 33)
        mainGui = loader.loadModel('models/gui/gui_main')
        gui = loader.loadModel('models/gui/toplevel_gui')
        self.checkMark = gui.find('**/generic_check')
        self.checkMark.reparentTo(self)
        self.checkMark.stash()
        self.checkMark.setScale(1.0)
        self.checkMark.setColorScale(0.0, 1.0, 0.0, 1.0)
        self.checkMark.setPos(0.02, 0.0, 0.02)
        self.checkMark.setBin('fixed', 34)
        self.skillRing = DialMeter(self,
                                   wantCover=False,
                                   dangerRatio=0.0,
                                   meterColor=Vec4(0.9, 0.9, 0.1, 1.0),
                                   baseColor=Vec4(0.15, 0.07, 0.03, 1.0),
                                   completeColor=Vec4(0.1, 0.9, 0.1, 1.0))
        self.skillRing.reparentTo(self)
        self.skillRing.setScale(0.285, 0.3, 0.265)
        self.skillRing.setBin('fixed', 32)
        self.skillGlow = self.glow = OnscreenImage(
            parent=self,
            image=mainGui.find('**/icon_glow'),
            scale=(1.0, 1.0, 1.0),
            color=(1.0, 1.0, 0.6, 1.0))
        self.skillGlow.reparentTo(self)
        self.skillGlow.setBin('fixed', 31)
        self.skillGlow.stash()
        self.pirateNameBox = None
        self.pirateNameLabel = None
        return

    def showGlow(self):
        self.inProgress = False
        if self.pirateNameLabel == None and self.checkMark.isStashed():
            self.skillGlow.unstash()
        return

    def hideGlow(self):
        self.inProgress = True
        self.skillGlow.stash()

    def setProgress(self, percent):
        self.skillGlow.stash()
        ratio = max(0.0, percent / 100.0)
        if ratio >= 1.0:
            if self.checkMark.isStashed():
                self.checkMark.unstash()
        else:
            if not self.checkMark.isStashed():
                self.checkMark.stash()

        if self.pirateNameLabel == None and not self.inProgress:
            self.skillGlow.unstash()

        self.skillRing.update(ratio, 1.0)
        self.skillRing.wrtReparentTo(self.getParent())
        self.reparentTo(self.getParent())

    def updatePirateNameBox(self, pirateName):
        if self.pirateNameLabel != None and self.pirateNameLabel[
                'text'] != pirateName:
            if self.pirateNameBox:
                self.pirateNameBox.destroy()
            if self.pirateNameLabel:
                self.pirateNameLabel.destroy()
            self.pirateNameBox = None
            self.pirateNameLabel = None
        if pirateName != '' and not (self.pirateNameBox
                                     and self.pirateNameLabel['text']
                                     == pirateName):
            self.createPirateNameBox(pirateName)
        return

    def createPirateNameBox(self, pirateName):
        self.pirateNameLabel = DirectLabel(
            relief=None,
            state=DGG.DISABLED,
            text=pirateName,
            text_align=TextNode.ACenter,
            text_scale=PiratesGuiGlobals.TextScaleMed,
            text_fg=PiratesGuiGlobals.TextFG1,
            text_wordwrap=12,
            textMayChange=0,
            sortOrder=91)
        self.pirateNameLabel.setBin('fixed', 33)
        height = self.pirateNameLabel.getHeight()
        width = self.pirateNameLabel.getWidth() + 0.05
        pos = [0.0, 0.0, height / 2 - 0.035]
        fs = [
            -(width / 2 + 0.01), width / 2 + 0.01, -(height / 2 + 0.015),
            height / 2 + 0.015
        ]
        self.pirateNameBox = BorderFrame(parent=self,
                                         state=DGG.DISABLED,
                                         frameSize=(fs[0], fs[1], fs[2],
                                                    fs[3]),
                                         modelName='general_frame_f',
                                         pos=(0.0, 0.0, 0.0))
        self.pirateNameLabel.reparentTo(self.pirateNameBox)
        self.pirateNameLabel.setPos(pos[0], pos[1], pos[2])
        self.pirateNameBox.setClipPlaneOff()
        pos = self.pirateNameBox.getPos(aspect2d)
        x = min(pos[0], base.a2dRight - width)
        z = max(pos[2], base.a2dBottom - height)
        self.pirateNameBox.setPos(aspect2d, x, 0, z - 0.175)
        self.pirateNameBox.flattenLight()
        self.pirateNameBox.setBin('fixed', 32)
        self.pirateNameBox.reparentTo(self)
        return
Exemple #10
0
class QuestPoster(DirectFrame):
    notify = directNotify.newCategory('QuestPoster')

    # We need to declare and initialize these variables here
    # because some methods use them as default arguments.
    auxIcon = None

    # Requires one parameter, quest, this must be a Quest instance.
    # The next argument, parent, is where to reparent the DirectFrame to.
    # The next arguments are simply additional options when setting up the DirectFrame.
    def __init__(self, quest, parent=aspect2d, **kw):
        # The quest this poster is representing.
        self.quest = quest

        # Let's define our options for the DirectFrame.
        bookModel = loader.loadModel(
            'phase_3.5/models/gui/stickerbook_gui.bam')
        optiondefs = (('relief', None,
                       None), ('image', bookModel.find('**/questCard'),
                               None), ('image_scale', (0.8, 1.0, 0.58), None),
                      ('state', DGG.NORMAL, None))
        self.defineoptions(kw, optiondefs)

        # Finally, initialize the DirectFrame.
        DirectFrame.__init__(self, relief=None)
        self.initialiseoptions(QuestPoster)

        # Let's declare and initialize our barebone GUI element variables.
        self.titleLabel = DirectLabel(parent=self,
                                      relief=None,
                                      text=self.quest.getName(),
                                      text_font=CIGlobals.getMinnieFont(),
                                      text_fg=QuestGlobals.TEXT_COLOR,
                                      text_scale=0.05,
                                      text_align=TextNode.ACenter,
                                      text_wordwrap=25.0,
                                      textMayChange=1,
                                      pos=(0, 0, 0.23))

        ##########################################################################
        #           THE FOLLOWING ELEMENTS BELOW ARE GROUPED TOGETHER            #
        ##########################################################################

        # The background frame where the objective image is displayed.
        # This is the colored background frame.
        self.auxFrame = DirectFrame(
            parent=self,
            relief=None,
            image=bookModel.find('**/questPictureFrame'),
            image_scale=QuestGlobals.IMAGE_SCALE_SMALL,
            text='',
            text_pos=(0, -0.11),
            text_fg=QuestGlobals.TEXT_COLOR,
            text_scale=QuestGlobals.QPtextScale,
            text_align=TextNode.ACenter,
            text_wordwrap=11.0,
            pos=QuestGlobals.DEFAULT_LEFT_PICTURE_POS)

        # The icon that goes on top of the aux frame.
        self.auxIcon = DirectFrame(parent=self.auxFrame,
                                   relief=None,
                                   text=' ',
                                   text_font=CIGlobals.getSuitFont(),
                                   text_pos=(0, -0.03),
                                   text_fg=QuestGlobals.TEXT_COLOR,
                                   text_scale=0.13,
                                   text_align=TextNode.ACenter,
                                   text_wordwrap=13.0,
                                   textMayChange=1)
        self.auxIcon.setColorOff(-1)

        # The aux text saying: DEFEAT, RECOVER, etc.
        self.auxText = DirectLabel(parent=self,
                                   relief=None,
                                   text=QuestGlobals.RECOVER,
                                   text_font=CIGlobals.getToonFont(),
                                   text_scale=QuestGlobals.QPauxText,
                                   text_fg=QuestGlobals.TEXT_COLOR,
                                   text_align=TextNode.ACenter,
                                   textMayChange=1,
                                   pos=QuestGlobals.DEFAULT_AUX_POS)
        self.auxText.hide()

        ##########################################################################

        # Information displayed about the objective.
        self.objectiveInfo = DirectLabel(
            parent=self,
            relief=None,
            text='',
            text_font=CIGlobals.getToonFont(),
            text_fg=QuestGlobals.TEXT_COLOR,
            text_scale=0.04,
            text_align=TextNode.ACenter,
            text_wordwrap=QuestGlobals.QPtextWordwrap,
            textMayChange=1,
            pos=(QuestGlobals.DEFAULT_INFO_POS))
        self.objectiveInfo.hide()

        # Information displayed showing the location.
        self.locationInfo = DirectLabel(
            parent=self,
            relief=None,
            text='N/A',
            text_font=CIGlobals.getToonFont(),
            text_fg=QuestGlobals.TEXT_COLOR,
            text_scale=QuestGlobals.QPtextScale,
            text_align=TextNode.ACenter,
            text_wordwrap=QuestGlobals.QPtextWordwrap,
            textMayChange=1,
            pos=(0, 0, -0.115))
        self.locationInfo.hide()

        # The progress bar showing the objective's progress
        self.progressBar = DirectWaitBar(parent=self,
                                         relief=DGG.SUNKEN,
                                         frameSize=(-0.95, 0.95, -0.1, 0.12),
                                         borderWidth=(0.025, 0.025),
                                         scale=0.2,
                                         frameColor=(0.945, 0.875, 0.706, 1.0),
                                         barColor=(0.5, 0.7, 0.5, 1),
                                         text='0/0',
                                         text_font=CIGlobals.getToonFont(),
                                         text_scale=0.19,
                                         text_fg=(0.05, 0.14, 0.4, 1),
                                         text_align=TextNode.ACenter,
                                         text_pos=(0, -0.05),
                                         pos=(0, 0, -0.2425))
        self.progressBar.hide()

        # The wood panel at the bottom where rewards are displayed.
        rewardFrameGeom = loader.loadModel(
            'phase_4/models/gui/gag_shop_purchase_gui.bam')
        self.rewardFrame = DirectFrame(
            parent=self,
            relief=None,
            geom=rewardFrameGeom.find('**/Goofys_Sign'),
            geom_scale=(0.615, 0, 0.4),
            pos=(-0.01, 0, -0.25))

        # The text displayed on the right side of the frame with additional information, if necessary.
        self.sideInfo = DirectLabel(parent=self,
                                    relief=None,
                                    text=QuestGlobals.JUST_FOR_FUN,
                                    text_fg=(0.0, 0.439, 1.0, 1.0),
                                    text_shadow=(0, 0, 0, 1),
                                    pos=(-0.2825, 0, 0.2),
                                    scale=0.03)
        self.sideInfo.setR(-30)

        # This side information is usually not needed, let's hide it.
        self.sideInfo.hide()

        # Remove the nodes of the loaded models we no longer need.
        bookModel.removeNode()
        rewardFrameGeom.removeNode()

        # Let's hide this until it is needed.
        self.hide()
        return

    def setup(self):
        objective = self.quest.currentObjective
        objective.updateInfo()

        self.objectiveInfo.show()
        self.auxFrame.show()

        self.locationInfo['text'] = QuestGlobals.getLocationText(
            objective.location)
        self.locationInfo['text_pos'] = (0,
                                         0 if not QuestGlobals.isShopLocation(
                                             objective.location) else 0.025)
        self.locationInfo.show()

        # Let's setup the quest progress bar
        progress = objective.amount if hasattr(objective, 'amount') else None

        if progress and objective.neededAmount > 0:
            self.progressBar['range'] = objective.getNeededAmount()
            self.progressBar['value'] = progress & pow(2, 16) - 1

        if objective.__class__ in [
                DeliverItemObjective, CogObjective, RecoverItemObjective
        ]:
            self.progressBar.show()

        self.auxText.show()

        # Let's handle the objectives.
        if objective.__class__ == CogObjective:
            self.handleCogObjective()
        elif objective.__class__ == VisitNPCObjective:
            self.handleNPCObjective()

        self.titleLabel.initialiseoptions(DirectLabel)
        self.auxIcon.initialiseoptions(DirectFrame)
        self.auxText.initialiseoptions(DirectLabel)
        self.objectiveInfo.initialiseoptions(DirectLabel)
        self.locationInfo.initialiseoptions(DirectLabel)
        self.rewardFrame.initialiseoptions(DirectFrame)
        self.sideInfo.initialiseoptions(DirectLabel)

    # Changes geometry and scale of an icon.
    def handleSimpleIcon(self, geom, scale, icon):
        icon['geom'] = geom
        icon['geom_scale'] = scale

    def handleComplexIcon(self,
                          geom,
                          icon,
                          scale=QuestGlobals.IMAGE_SCALE_SMALL):
        isHead = True if type(geom) == ToonHead else geom.getName() == (
            '%sHead' % CIGlobals.Suit)

        if isHead:
            geom.setDepthWrite(1)
            geom.setDepthTest(1)
            self.fitGeometry(geom, fFlip=1)
            self.handleSimpleIcon(geom, scale, icon)

            # We have to rotate the head and set the scale of the icon.
            if CIGlobals.Suit in geom.getName():
                cogName = geom.getPythonTag('Settings')
                data = QuestGlobals.Suit2PosterZNDScale.get(cogName)
                zOffset = data[0]
                headScale = data[1]
                icon.setScale(headScale)
                icon.setZ(icon.getZ() + zOffset)
                geom.setH(180)
        else:
            raise ValueError(
                'Tried to use #handleComplexIcon() on a non-complex icon. Use this method for 3D geometry.'
            )

    def handleCogObjective(self,
                           iconElement=auxIcon,
                           auxText=QuestGlobals.DEFEAT,
                           frameColor=QuestGlobals.BLUE):
        objective = self.quest.currentObjective
        infoText = objective.getTaskInfo(speech=False)

        if objective.__class__ == RecoverItemObjective:
            infoText = QuestGlobals.makePlural(objective.name)
            print 'Yep'

        if not iconElement:
            iconElement = self.auxIcon

        # Let's make sure we have a current objective that is
        # an instance of the CogObjective class and this poster isn't destroyed.
        if not objective or not hasattr(self, 'titleLabel') or not isinstance(
                objective, CogObjective):
            return

        if objective.dept:
            icons = loader.loadModel('phase_3/models/gui/cog_icons.bam')
            deptIcon = None

            if objective.dept == Dept.BOSS:
                deptIcon = icons.find('**/CorpIcon')
            else:
                deptIcon = icons.find('**/%sIcon' %
                                      objective.dept.getTie().title())

            # Correct the medallion color.
            deptIcon.setColor(SuitGlobals.medallionColors[objective.dept])

            # Setup the icon and remove the icons node.
            self.handleSimpleIcon(deptIcon, 0.13, iconElement)
            icons.removeNode()
        elif not objective.name:
            # We aren't fighting a Cog in particular.
            cogIcon = QuestGlobals.getCogIcon()
            self.handleSimpleIcon(cogIcon, cogIcon.getScale(), iconElement)

        # We're fighting a Cog in particular.
        if objective.name:
            cogHeadInstance = SuitBank.getSuitByName(objective.name).getHead()
            cogHead = cogHeadInstance.generate()
            cogHead.setName('%sHead' % CIGlobals.Suit)
            cogHead.setPythonTag('Settings', cogHeadInstance.head)
            cogHeadInstance.setScale(2)
            self.handleComplexIcon(cogHead, iconElement)

        if not iconElement is self.auxIcon:
            if hasattr(self, 'goalInfo'):
                # We're working with the second frame, on the right.
                # Let's update the information pertaining to this side.
                self.goalInfo['text'] = infoText
                self.goalInfo.setPos(QuestGlobals.RECOVER_INFO2_POS)
                self.auxText.setPos(QuestGlobals.RECOVER_AUX_POS)
            else:
                raise AttributeError(
                    'Attempted to setup DoubleFrame information for poster using default style.'
                )
        else:
            self.objectiveInfo['text'] = infoText
            self.auxText['text'] = auxText

        # Let's set the progress bar text
        pgBarText = '%d of %d %s' % (objective.amount, objective.neededAmount,
                                     QuestGlobals.makePastTense(auxText))
        self.progressBar['text'] = pgBarText

        # Let's set the color of the poster.
        frame = self.auxFrame if iconElement is self.auxIcon else self.goalFrame
        frame['image_color'] = Vec4(*frameColor)

    def handleNPCObjective(self,
                           iconElement=auxIcon,
                           auxText=QuestGlobals.VISIT,
                           frameColor=QuestGlobals.BROWN):
        objective = self.quest.currentObjective
        infoText = CIGlobals.NPCToonNames[objective.npcId]

        if not iconElement:
            iconElement = self.auxIcon

        # Let's make sure we have a current objective that is
        # an instance of the CogObjective class and this poster isn't destroyed.
        if not objective or not hasattr(self, 'titleLabel') or not isinstance(
                objective, VisitNPCObjective):
            return

        # Let's generate the head.
        dna = ToonDNA()
        dna.setDNAStrand(CIGlobals.NPCToonDict.get(objective.npcId)[2])
        head = ToonHead(base.cr)
        head.generateHead(dna.getGender(),
                          dna.getAnimal(),
                          dna.getHead(),
                          forGui=1)
        head.setHeadColor(dna.getHeadColor())
        self.handleComplexIcon(head, iconElement)

        self.auxText['text'] = auxText

        if not iconElement is self.auxIcon:
            if hasattr(self, 'goalInfo'):
                # We're working with the second frame, on the right.
                # Let's update the information pertaining to this side.
                self.goalInfo['text'] = infoText
                self.goalInfo.setPos(QuestGlobals.RECOVER_INFO2_POS)
                self.auxText.setPos(QuestGlobals.RECOVER_AUX_POS)
                self.goalFrame['image_color'] = frameColor
            else:
                raise AttributeError(
                    'Attempted to setup DoubleFrame information for poster using default style.'
                )
        else:
            self.objectiveInfo['text'] = infoText
            self.auxFrame['image_color'] = frameColor

    def fitGeometry(self, geom, fFlip=0, dimension=0.8):
        p1 = Point3()
        p2 = Point3()
        geom.calcTightBounds(p1, p2)
        if fFlip:
            t = p1[0]
            p1.setX(-p2[0])
            p2.setX(-t)
        d = p2 - p1
        biggest = max(d[0], d[2])
        s = dimension / biggest
        mid = (p1 + d / 2.0) * s
        geomXform = hidden.attachNewNode('geomXform')
        for child in geom.getChildren():
            child.reparentTo(geomXform)

        geomXform.setPosHprScale(-mid[0], -mid[1] + 1, -mid[2], 180, 0, 0, s,
                                 s, s)
        geomXform.reparentTo(geom)

    def destroy(self):
        if hasattr(self, 'titleLabel'):
            self.titleLabel.destroy()
            self.auxFrame.destroy()
            self.auxIcon.destroy()
            self.auxText.destroy()
            self.objectiveInfo.destroy()
            self.locationInfo.destroy()
            self.progressBar.destroy()
            self.rewardFrame.destroy()
            self.sideInfo.destroy()
            del self.titleLabel
            del self.auxFrame
            del self.auxIcon
            del self.auxText
            del self.objectiveInfo
            del self.locationInfo
            del self.progressBar
            del self.rewardFrame
            del self.sideInfo
            DirectFrame.destroy(self)
            self.notify.debug('Destroyed all elements.')
class DirectSidebar(DirectFrame):
  def __init__(
        self,
        parent=None,
        frameSize=(1, 1),
        dragbarSize=0.05,
        align=ALIGN_LEFT|ALIGN_TOP,
        orientation=HORIZONTAL,
        opendir=RIGHT_OR_DOWN,
        pos=Vec3(0,0,0),
        text='',
        toggleFunc=None,
        frameColor=(1,1,1,1),
      ):
    if parent is None:
      parent=aspect2d
    self.dragbarSize=dragbarSize
    self.align=align
    self.orientation=orientation
    self.opendir=opendir
    self.pos=pos
    self.frameSize=frameSize
    self.toggleFunc=toggleFunc
    
    self.collapsed=False
    
    DirectFrame.__init__(
        self, parent=parent,
        frameSize=(0,frameSize[0],0,frameSize[1]),
        frameColor=frameColor,
        suppressMouse=1,
      )
    self.initialiseoptions(DirectSidebar)
    self.resetFrameSize()
    
    self.collapseButton = DirectButton(
        parent=parent, 
        borderWidth=(0, 0),
        relief=DGG.FLAT,
        command=self.toggleCollapsed,
      )
    self.label = DirectLabel(
        parent=self.collapseButton,
        scale=0.04,
        text=text,
        text_align=TextNode.ACenter,
        frameColor=(0,0,0,0)
      )
    if self.orientation == HORIZONTAL:
      self.label.setPos(Vec3(frameSize[0]/2.,0,0.015))
    if self.orientation == VERTICAL:
      self.label.setPos(Vec3(0.035,0,frameSize[1]/2.))
      self.label.setR(-90)
    
    self.accept('window-event', self.update)
    self.update()
  
  def destroy(self):
    self.label.detachNode()
    self.collapseButton.detachNode()
    self.detachNode()
    self.ignoreAll()#'window-event', self.update)
  
  def __del__(self):
    self.destroy()
  
  def update(self, args=None):
    aspectRatio=base.getAspectRatio()
    framePos=Vec3(self.pos[0],0,self.pos[2])
    
    if self.align & ALIGN_LEFT:
      framePos+=Vec3(-aspectRatio,0,0)
    if self.align & ALIGN_RIGHT:
      framePos+=Vec3(aspectRatio,0,0)
    if self.align & ALIGN_TOP:
      framePos+=Vec3(0,0,1-self.frameSize[1])
    if self.align & ALIGN_BOTTOM:
      framePos+=Vec3(0,0,-1)
    
    if self.orientation == HORIZONTAL:
      if self.align & ALIGN_RIGHT: # a small help for the user
        framePos-=Vec3(self.frameSize[0],0,0)
      buttonSize=(0,self.frameSize[0],0,self.dragbarSize)
      if self.opendir == RIGHT_OR_DOWN: # correct
        if self.collapsed:
          buttonPos=framePos+Vec3(0,0,self.frameSize[1]-self.dragbarSize)
        else:
          buttonPos=framePos+Vec3(0,0,-self.dragbarSize)
      elif self.opendir == LEFT_OR_UP:
        if self.collapsed:
          buttonPos=framePos
        else:
          buttonPos=framePos+Vec3(0,0,self.frameSize[1])
    
    elif self.orientation == VERTICAL:
      buttonSize=(0,self.dragbarSize,0,self.frameSize[1])
      if self.opendir == RIGHT_OR_DOWN:
        if self.collapsed:
          buttonPos=framePos
        else:
          buttonPos=framePos+Vec3(self.frameSize[0],0,0)
      elif self.opendir == LEFT_OR_UP:
        framePos-=Vec3(self.frameSize[0],0,0) # a small help for the user
        if self.collapsed:
          buttonPos=framePos+Vec3(self.frameSize[0]-self.dragbarSize,0,0)
        else:
          buttonPos=framePos
    
    if self.collapsed:
      self.hide()
    else:
      self.show()
    
    self.setPos(framePos)
    self.collapseButton.setPos(buttonPos)
    self.collapseButton['frameSize']=buttonSize
  
  def toggleCollapsed(self,state=None):
    if state is None:
      state=not self.collapsed
    self.collapsed=state
    if self.toggleFunc:
      try:
        self.toggleFunc(state)
      except:
        traceback.print_exc()
    self.update()
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)
Exemple #13
0
class ItemButton(DirectButton):
    def __init__(self, page, pos):
        DirectButton.__init__(self,
                              parent=page,
                              relief=None,
                              command=self.handleClick,
                              pos=pos)
        self.window = page
        self.item = None
        self.values = None
        self.label = DirectLabel(text='',
                                 relief=None,
                                 parent=self,
                                 text_scale=0.05)
        self.label.initialiseoptions(DirectLabel)
        self.label.hide()
        self.hide()

    def setItem(self, item, values):
        if values:
            image = values.get('image')
            price = values.get('price')
            text = ''

            self.item = item
            self.values = values
            self['geom'] = image

            if values.get('type') == ItemType.GAG:
                gagId = base.cr.attackMgr.getAttackIDByName(item)
                supply = base.localAvatar.getBackpack().getSupply(gagId)
                maxSupply = base.localAvatar.getBackpack().getMaxSupply(gagId)
                self.setScale(1.3)
                self.label['text_scale'] = 0.05
                self.label.setPos(0, 0, -0.11)
                self.setTransparency(TransparencyAttrib.MNone)
            elif values.get('type') == ItemType.UPGRADE:
                upgradeID = values.get('upgradeID')
                avID = base.localAvatar.getPUInventory()[1]
                supply = 0
                maxSupply = values.get('maxUpgrades')

                battle = base.localAvatar.getBattleZone()
                if battle and battle.getTurretManager():
                    turret = battle.getTurretManager().getTurret()
                    if turret and turret.getGagID() == upgradeID:
                        supply = 1

                if avID == upgradeID:
                    dataSupply = base.localAvatar.getPUInventory()[0]
                    if dataSupply > 0:
                        supply = dataSupply

                self.setScale(0.15)
                self.label['text_scale'] = 0.3
                self.label.setPos(0, 0, -1.2)
                self.setTransparency(TransparencyAttrib.MNone)
            elif values.get('type') == ItemType.HEAL:
                text = '%s\n%s JBS' % (
                    item, price) if 'showTitle' in values else item
                self.setTransparency(TransparencyAttrib.MAlpha)
                self.setScale(0.105)
                self.label['text_scale'] = 0.55
                self.label.setPos(0, 0, -1.6)
            text = text if text else '%s/%s\n%s JBS' % (
                str(supply), str(maxSupply), str(price))
            self.label['text'] = text

            self.label.initialiseoptions(DirectLabel)
            self.initialiseoptions(ItemButton)

            self.label.show()
            self.show()

    def update(self):
        money = base.localAvatar.getMoney()
        if self.values:
            itemType = self.values.get('type')
            price = self.values.get('price')
            self.setColorScale(NORMAL_COLOR)
            if price > money:
                self.setColorScale(GRAYED_OUT_COLOR)
            if itemType == ItemType.GAG:
                backpack = base.localAvatar.getBackpack()
                gagId = base.cr.attackMgr.getAttackIDByName(self.item)
                supply = backpack.getSupply(gagId)
                maxSupply = backpack.getMaxSupply(gagId)
                inBackpack = backpack.hasGag(gagId)
                if not inBackpack or inBackpack and supply >= maxSupply:
                    self.setColorScale(GRAYED_OUT_COLOR)
                self.label['text'] = '%s/%s\n%s JBS' % (
                    str(supply), str(maxSupply), str(price))
            elif itemType == ItemType.UPGRADE:
                maxSupply = self.values.get('maxUpgrades')
                upgradeID = self.values.get('upgradeID')
                avID = base.localAvatar.getPUInventory()[1]
                supply = 0
                turretCount = 0
                hasTurret = False

                battle = base.localAvatar.getBattleZone()
                if battle and battle.getTurretManager():
                    turretCount = battle.getTurretCount()
                    turret = battle.getTurretManager().getTurret()
                    if turret:
                        hasTurret = True
                        if turret.getGagID() == upgradeID:
                            supply = 1

                if avID == upgradeID:
                    dataSupply = base.localAvatar.getPUInventory()[0]
                    if dataSupply > 0:
                        supply = dataSupply

                if supply > 0 or base.localAvatar.getPUInventory(
                )[0] > 0 or hasTurret or turretCount == CogBattleGlobals.MAX_TURRETS:
                    self.setColorScale(GRAYED_OUT_COLOR)

                self.label['text'] = '%s\n%s/%s\n%s JBS' % (
                    self.item, str(supply), str(maxSupply), str(price))
            elif itemType == ItemType.HEAL:
                if base.localAvatar.getHealth(
                ) == base.localAvatar.getMaxHealth() or self.shop.hasCooldown(
                        self.item):
                    self.setColorScale(GRAYED_OUT_COLOR)

    def handleClick(self):
        if self.item:
            self.window.shop.purchaseItem(self.item)

    def destroy(self):
        DirectFrame.destroy(self)
Exemple #14
0
def _parseText(nodePath, parent):
    notify.debug('creating %s' % nodePath.getName()[len(TEXT_PREFIX) + 1:])
    label = DirectLabel(parent = parent, relief = None, text = nodePath.getName()[len(TEXT_PREFIX) + 1:], text_align = TextNode.ACenter, text_scale = 0.10000000000000001, sortOrder = 50)
    label.setPos(nodePath.getPos() * SCALE_MULTIPLIER)
    return (nodePath.getName()[len(TEXT_PREFIX) + 1:], label)
Exemple #15
0
class QuestMap(DirectFrame):
    def __init__(self, av, **kw):
        DirectFrame.__init__(self, relief=None, sortOrder=50)
        self.initialiseoptions(QuestMap)
        self.container = DirectFrame(parent=self, relief=None)
        self.marker = DirectFrame(parent=self.container, relief=None)
        self.cogInfoFrame = DirectFrame(parent=self.container, relief=None)
        cm = CardMaker('bg')
        cm.setFrame(-0.5, 0.5, -0.5, 0.5)
        bg = self.cogInfoFrame.attachNewNode(cm.generate())
        bg.setTransparency(1)
        bg.setColor(0.5, 0.5, 0.5, 0.5)
        bg.setBin('fixed', 0)
        self.cogInfoFrame['geom'] = bg
        self.cogInfoFrame['geom_pos'] = (0, 0, 0)
        self.cogInfoFrame['geom_scale'] = (6, 1, 2)
        self.cogInfoFrame.setScale(0.05)
        self.cogInfoFrame.setPos(0, 0, 0.6)
        self.buildingMarkers = []
        self.av = av
        self.wantToggle = False
        if ConfigVariableBool('want-toggle-quest-map', True).getValue():
            self.wantToggle = True
        self.updateMarker = True
        self.cornerPosInfo = None
        self.hqPosInfo = None
        self.fishingSpotInfo = None
        self.load()
        self.setScale(1.5)
        bg.removeNode()
        self.hoodId = None
        self.zoneId = None
        self.suitPercentage = {}
        for currHoodInfo in SuitPlannerBase.SuitPlannerBase.SuitHoodInfo:
            tracks = currHoodInfo[
                SuitPlannerBase.SuitPlannerBase.SUIT_HOOD_INFO_TRACK]
            self.suitPercentage[currHoodInfo[
                SuitPlannerBase.SuitPlannerBase.SUIT_HOOD_INFO_ZONE]] = tracks

    def load(self):
        gui = loader.loadModel(
            'phase_4/models/questmap/tt_m_gui_qst_questmap_gui')
        icon = gui.find('**/tt_t_gui_qst_arrow')
        iconNP = aspect2d.attachNewNode('iconNP')
        icon.reparentTo(iconNP)
        icon.setR(90)
        self.marker['geom'] = iconNP
        self.marker['image'] = iconNP
        self.marker.setScale(0.05)
        iconNP.removeNode()
        self.mapOpenButton = DirectButton(
            image=(gui.find('**/tt_t_gui_qst_mapClose'),
                   gui.find('**/tt_t_gui_qst_mapClose'),
                   gui.find('**/tt_t_gui_qst_mapTryToOpen')),
            relief=None,
            pos=(-0.084, 0, 0.37),
            parent=base.a2dBottomRight,
            scale=0.205,
            command=self.show,
        )
        self.mapCloseButton = DirectButton(
            image=(gui.find('**/tt_t_gui_qst_mapOpen'),
                   gui.find('**/tt_t_gui_qst_mapOpen'),
                   gui.find('**/tt_t_gui_qst_mapTryToClose')),
            relief=None,
            pos=(-0.084, 0, 0.37),
            parent=base.a2dBottomRight,
            scale=0.205,
            command=self.hide,
        )
        self.mapOpenButton.hide()
        self.mapCloseButton.hide()
        gui.removeNode()
        icons = loader.loadModel('phase_3/models/gui/cog_icons')
        cIcon = icons.find('**/CorpIcon')
        lIcon = icons.find('**/LegalIcon')
        mIcon = icons.find('**/MoneyIcon')
        sIcon = icons.find('**/SalesIcon')
        cogInfoTextColor = (0.2, 0.2, 0.2, 1)
        textPos = (1.2, -0.2)
        textScale = 0.8

        self.cInfo = DirectLabel(
            parent=self.cogInfoFrame,
            text="",
            text_fg=cogInfoTextColor,
            text_pos=textPos,
            text_scale=textScale,
            geom=cIcon,
            geom_pos=(-0.2, 0, 0),
            geom_scale=0.8,
            relief=None,
        )
        self.cInfo.setPos(-2.2, 0, 0.5)

        self.lInfo = DirectLabel(
            parent=self.cogInfoFrame,
            text_fg=cogInfoTextColor,
            text="",
            text_pos=textPos,
            text_scale=textScale,
            geom=lIcon,
            geom_pos=(-0.2, 0, 0),
            geom_scale=0.8,
            relief=None,
        )
        self.lInfo.setPos(-2.2, 0, -0.5)

        self.mInfo = DirectLabel(
            parent=self.cogInfoFrame,
            text_fg=cogInfoTextColor,
            text="",
            text_pos=textPos,
            text_scale=textScale,
            geom=mIcon,
            geom_pos=(-0.2, 0, 0),
            geom_scale=0.8,
            relief=None,
        )
        self.mInfo.setPos(0.8, 0, 0.5)

        self.sInfo = DirectLabel(
            parent=self.cogInfoFrame,
            text_fg=cogInfoTextColor,
            text="",
            text_pos=textPos,
            text_scale=textScale,
            geom=sIcon,
            geom_pos=(-0.2, 0, 0),
            geom_scale=0.8,
            relief=None,
        )
        self.sInfo.setPos(0.8, 0, -0.5)

        icons.removeNode()

    def updateCogInfo(self):
        currPercentage = self.suitPercentage.get(self.zoneId)
        if currPercentage is None:
            return
        self.cInfo['text'] = '%s%%' % currPercentage[0]
        self.lInfo['text'] = '%s%%' % currPercentage[1]
        self.mInfo['text'] = '%s%%' % currPercentage[2]
        self.sInfo['text'] = '%s%%' % currPercentage[3]

    def destroy(self):
        self.ignore('questPageUpdated')
        self.mapOpenButton.destroy()
        self.mapCloseButton.destroy()
        del self.mapOpenButton
        del self.mapCloseButton
        DirectFrame.destroy(self)

    def putBuildingMarker(self, pos, hpr=(0, 0, 0), mapIndex=None):
        marker = DirectLabel(parent=self.container,
                             text='',
                             text_pos=(-0.05, -0.15),
                             text_fg=(1, 1, 1, 1),
                             relief=None)
        gui = loader.loadModel(
            'phase_4/models/parties/schtickerbookHostingGUI')
        icon = gui.find('**/startPartyButton_inactive')
        iconNP = aspect2d.attachNewNode('iconNP')
        icon.reparentTo(iconNP)
        icon.setX(-12.0792 / 30.48)
        icon.setZ(-9.7404 / 30.48)
        marker['text'] = '%s' % mapIndex
        marker['text_scale'] = 0.7
        marker['image'] = iconNP
        marker['image_color'] = (1, 0, 0, 1)
        marker['image_scale'] = 6
        marker.setScale(0.05)
        relX, relY = self.transformAvPos(pos)
        marker.setPos(relX, 0, relY)
        self.buildingMarkers.append(marker)
        iconNP.removeNode()
        gui.removeNode()

    def updateQuestInfo(self):
        for marker in self.buildingMarkers:
            marker.destroy()

        self.buildingMarkers = []
        dnaStore = base.cr.playGame.dnaStore
        for questIndex in self.av.questPage.quests.keys():
            questDesc = self.av.questPage.quests.get(questIndex)
            if questDesc is None:
                continue
            mapIndex = questIndex + 1
            questId, fromNpcId, toNpcId, rewardId, toonProgress = questDesc
            quest = Quests.getQuest(questId)
            fComplete = quest.getCompletionStatus(self.av,
                                                  questDesc) == Quests.COMPLETE
            if not fComplete:
                if quest.getType() == Quests.RecoverItemQuest:
                    if quest.getHolder() == Quests.AnyFish:
                        self.putBuildingMarker(self.fishingSpotInfo,
                                               mapIndex=mapIndex)
                    continue
                elif quest.getType(
                ) != Quests.DeliverGagQuest and quest.getType(
                ) != Quests.DeliverItemQuest and quest.getType(
                ) != Quests.VisitQuest and quest.getType(
                ) != Quests.TrackChoiceQuest:
                    continue
            if toNpcId == Quests.ToonHQ:
                self.putBuildingMarker(self.hqPosInfo, mapIndex=mapIndex)
            else:
                npcZone = NPCToons.getNPCZone(toNpcId)
                hoodId = ZoneUtil.getCanonicalHoodId(npcZone)
                branchId = ZoneUtil.getCanonicalBranchZone(npcZone)
                if self.hoodId == hoodId and self.zoneId == branchId:
                    for blockIndex in range(dnaStore.getNumBlockTitles()):
                        blockNumber = dnaStore.getTitleBlockAt(blockIndex)
                        zone = dnaStore.getZoneFromBlockNumber(blockNumber)
                        branchZone = zone - zone % 100
                        finalZone = branchZone + 500 + blockNumber
                        buildingType = dnaStore.getBlockBuildingType(
                            blockNumber)
                        if npcZone == finalZone:
                            self.putBuildingMarker(
                                dnaStore.getDoorPosHprFromBlockNumber(
                                    blockNumber).getPos(),
                                dnaStore.getDoorPosHprFromBlockNumber(
                                    blockNumber).getHpr(),
                                mapIndex=mapIndex)

    def transformAvPos(self, pos):
        if self.cornerPosInfo is None:
            return (0, 0)
        topRight = self.cornerPosInfo[0]
        bottomLeft = self.cornerPosInfo[1]
        relativeX = (pos.getX() - bottomLeft.getX()) / (
            topRight.getX() - bottomLeft.getX()) - 0.5
        relativeY = (pos.getY() - bottomLeft.getY()) / (
            topRight.getY() - bottomLeft.getY()) - 0.5
        return (relativeX, relativeY)

    def update(self, task):
        if self.av:
            if self.updateMarker:
                relX, relY = self.transformAvPos(self.av.getPos())
                self.marker.setPos(relX, 0, relY)
                self.marker.setHpr(0, 0, -180 - self.av.getH())
        i = 0
        for buildingMarker in self.buildingMarkers:
            buildingMarker.setScale(
                (math.sin(task.time * 16.0 + i * math.pi / 3.0) + 1) * 0.005 +
                0.04)
            i = i + 1

        return Task.cont

    def updateMap(self):
        if self.av:
            try:
                hoodId = ZoneUtil.getCanonicalHoodId(self.av.getLocation()[1])
                zoneId = ZoneUtil.getCanonicalBranchZone(
                    self.av.getLocation()[1])
                mapsGeom = loader.loadModel(
                    'phase_4/models/questmap/tt_m_gui_qst_%s_maps' %
                    ToontownGlobals.dnaMap[hoodId])
                mapImage = mapsGeom.find(
                    '**/tt_t_gui_qst_%s_%s' %
                    (ToontownGlobals.dnaMap[hoodId], zoneId))
                if not mapImage.isEmpty():
                    self.container['image'] = mapImage
                    self.resetFrameSize()
                    self.cornerPosInfo = QuestMapGlobals.CornerPosTable.get(
                        'tt_t_gui_qst_%s_%s' %
                        (ToontownGlobals.dnaMap[hoodId], zoneId))
                    self.hqPosInfo = QuestMapGlobals.HQPosTable.get(
                        'tt_t_gui_qst_%s_%s' %
                        (ToontownGlobals.dnaMap[hoodId], zoneId))
                    self.fishingSpotInfo = QuestMapGlobals.FishingSpotPosTable.get(
                        'tt_t_gui_qst_%s_%s' %
                        (ToontownGlobals.dnaMap[hoodId], zoneId))
                    self.cogInfoPos = QuestMapGlobals.CogInfoPosTable.get(
                        'tt_t_gui_qst_%s_%s' %
                        (ToontownGlobals.dnaMap[hoodId], zoneId))
                    self.cogInfoFrame.setPos(self.cogInfoPos)
                    self.hide()
                    self.hoodId = hoodId
                    self.zoneId = zoneId
                    self.updateQuestInfo()
                    self.updateCogInfo()
                    taskMgr.add(self.update, 'questMapUpdate')
                else:
                    self.stop()
                mapsGeom.removeNode()
            except:
                self.stop()

    def start(self):
        self.container.show()
        self.accept('questPageUpdated', self.updateMap)
        self.handleMarker()
        self.updateMap()

    def initMarker(self, task):
        if self.av:
            if not hasattr(base.cr.playGame.getPlace(), 'isInterior'
                           ) or not base.cr.playGame.getPlace().isInterior:
                relX, relY = self.transformAvPos(self.av.getPos())
                self.marker.setPos(relX, 0, relY)
                self.marker.setHpr(0, 0, -180 - self.av.getH())
            self.marker['geom_scale'] = 1.4 * task.time % 0.5 * 10 + 1
            self.marker['geom_color'] = (1, 1, 1, 0.8 -
                                         1.4 * task.time % 0.5 * 2 / 0.8 + 0.2)
        if task.time < 1:
            return Task.cont
        else:
            self.marker['geom_color'] = (1, 1, 1, 0)
            return Task.done

    def show(self):
        taskMgr.add(self.initMarker, 'questMapInit')
        DirectFrame.show(self)
        self.mapOpenButton.hide()
        if self.container['image']:
            self.mapCloseButton.show()

    def hide(self):
        taskMgr.remove('questMapInit')
        DirectFrame.hide(self)
        if self.container['image']:
            self.mapOpenButton.show()
        self.mapCloseButton.hide()

    def toggle(self):
        if self.isHidden():
            self.show()
        else:
            self.hide()

    def obscureButton(self):
        self.mapOpenButton.hide()
        self.mapCloseButton.hide()

    def stop(self):
        self.container['image'] = None
        for marker in self.buildingMarkers:
            marker.destroy()

        self.buildingMarkers = []
        self.container.hide()
        self.hide()
        self.obscureButton()
        self.ignore('questPageUpdated')
        taskMgr.remove('questMapUpdate')

    def handleMarker(self):
        if hasattr(base.cr.playGame.getPlace(),
                   'isInterior') and base.cr.playGame.getPlace().isInterior:
            self.updateMarker = False
        else:
            self.updateMarker = True

    def acceptOnscreenHooks(self):
        if self.wantToggle:
            self.accept(ToontownGlobals.MapHotkey, self.toggle)
        else:
            self.accept(ToontownGlobals.MapHotkeyOn, self.show)
            self.accept(ToontownGlobals.MapHotkeyOff, self.hide)
        self.updateMap()

    def ignoreOnscreenHooks(self):
        self.ignore(ToontownGlobals.MapHotkey)
        self.ignore(ToontownGlobals.MapHotkeyOn)
        self.ignore(ToontownGlobals.MapHotkeyOff)
        self.obscureButton()
Exemple #16
0
class FileDialog(DirectObject):

    def __init__(self, title, initial_status, callback):
        self.frmLeft = -.7
        self.frmBottom = -.12
        self.frmRight = .7
        self.frmTop = .12
        
        self.frmWidth = self.frmRight - self.frmLeft
        self.frmHeight = self.frmTop - self.frmBottom
        
        self.title = title
        self.initial_status = initial_status
        self.callback = callback
        
        self.result = None
        self.done = 0
            
            
    def activate(self):
        # create main dialog frame
        # Note: frame position references the CENTER of the frame
        self.frm = DirectFrame(
            pos = (0,0,0),
            frameSize = (self.frmLeft, self.frmRight,self.frmBottom, self.frmTop),
            relief = DGG.RIDGE,
            borderWidth = (0.01, 0.01),
            frameColor = (0.6, 0.6, 0.6, 1.0))
        
        self.frm.reparentTo(base.aspect2d)
        
        # Note: wonderfully enough, label position on the other hand
        # references the CENTER of the LEFT border of the label!
        titleLabel = DirectLabel(text = self.title,
            scale = 0.04,
            frameColor = (0.5, 0.5, 0.5, 1),
            relief = DGG.RIDGE,
            borderWidth = (0.01, 0.01),
            text_align = TextNode.ALeft)
            
        titleLabel.setPos(-self.frmWidth/2+.02, 0, self.frmHeight/2-.045)
        titleLabel.reparentTo(self.frm)
        
        sc = .04     
        self.dir_edit_field = DirectEntry(
            text = '',      # prompt text
            scale = sc,
            frameColor = (0.65, 0.65, 0.65, 1),
            command=self.setText,
            width = 32,
            numLines = 1,
            focus = 1,
            focusInCommand=self.efFocusIn,
            )

        self.dir_edit_field.setPos(-self.frmWidth/2+.02, 0, self.frmHeight/2-.13)
        self.dir_edit_field.reparentTo(self.frm)

        self.statusLabel = DirectLabel(text = self.initial_status,
            scale = 0.04,
            frameColor = (0.6, 0.6, 0.6, 1),
            # relief = DGG.RIDGE,
            # borderWidth = (0.01, 0.01),
            text_align = TextNode.ALeft)
            
        self.statusLabel.setPos(-self.frmWidth/2+.02, 0, self.frmHeight/2-.2)
        self.statusLabel.reparentTo(self.frm)

    # call this if you need to run a form before your mainloop starts steppping the taskMgr
    def run(self):
        while self.done != 1:
            taskMgr.step()

        taskMgr.step()          # once more to make the last output from the dialog visible
                                # while we load a zone
        self.frm.removeNode()

    def end(self):
        self.frm.removeNode()
        

    # callback function to set  text: called by the Panda3d taskMgr when the user
    # has entered something into the DirectEntry widget
    def setText(self, textEntered):
        print 'dir_edit_field::setText:', textEntered
        self.done = self.callback(textEntered)
        if self.done != 1:
            self.dir_edit_field['focus'] = 1

                
    #clear the text
    def efFocusIn(self):
        print 'focus in'
        self.dir_edit_field.enterText('')
        
    def setStatus(self, status):
        self.statusLabel['text'] = status
Exemple #17
0
def _parseText(nodePath, parent):
    notify.debug('creating %s' % nodePath.getName()[len(TEXT_PREFIX) + 1:])
    label = DirectLabel(parent=parent, relief=None, text=nodePath.getName()[len(TEXT_PREFIX) + 1:], text_align=TextNode.ACenter, text_scale=0.1, sortOrder=50)
    label.setPos(nodePath.getPos() * SCALE_MULTIPLIER)
    return (
     nodePath.getName()[len(TEXT_PREFIX) + 1:], label)
Exemple #18
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() 
Exemple #19
0
class SimpleInteractive(DirectObject):
    __module__ = __name__

    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)
        return

    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.025)
        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.1, 0.1, 0.25, 0.2),
            text=text,
            text_align=TextNode.ACenter,
            text_scale=0.06,
            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.7)
        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
        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)
        return
Exemple #20
0
class QuestMap(DirectFrame):

    def __init__(self, av, **kw):
        DirectFrame.__init__(self, relief=None, sortOrder=50)
        self.initialiseoptions(QuestMap)
        self.container = DirectFrame(parent=self, relief=None)
        self.marker = DirectFrame(parent=self.container, relief=None)
        self.cogInfoFrame = DirectFrame(parent=self.container, relief=None)
        cm = CardMaker('bg')
        cm.setFrame(-0.5, 0.5, -0.5, 0.5)
        bg = self.cogInfoFrame.attachNewNode(cm.generate())
        bg.setTransparency(1)
        bg.setColor(0.5, 0.5, 0.5, 0.5)
        bg.setBin('fixed', 0)
        self.cogInfoFrame['geom'] = bg
        self.cogInfoFrame['geom_pos'] = (0, 0, 0)
        self.cogInfoFrame['geom_scale'] = (6, 1, 2)
        self.cogInfoFrame.setScale(0.05)
        self.cogInfoFrame.setPos(0, 0, 0.6)
        self.buildingMarkers = []
        self.av = av
        self.wantToggle = False
        if base.config.GetBool('want-toggle-quest-map', True):
            self.wantToggle = True
        self.updateMarker = True
        self.cornerPosInfo = None
        self.hqPosInfo = None
        self.fishingSpotInfo = None
        self.load()
        self.setScale(1.5)
        bg.removeNode()
        self.hoodId = None
        self.zoneId = None
        self.suitPercentage = {}
        for currHoodInfo in SuitPlannerBase.SuitPlannerBase.SuitHoodInfo:
            tracks = currHoodInfo[SuitPlannerBase.SuitPlannerBase.SUIT_HOOD_INFO_TRACK]
            self.suitPercentage[currHoodInfo[SuitPlannerBase.SuitPlannerBase.SUIT_HOOD_INFO_ZONE]] = tracks

        return

    def load(self):
        gui = loader.loadModel('phase_4/models/questmap/questmap_gui')
        icon = gui.find('**/tt_t_gui_qst_arrow')
        iconNP = aspect2d.attachNewNode('iconNP')
        icon.reparentTo(iconNP)
        icon.setR(90)
        self.marker['geom'] = iconNP
        self.marker['image'] = iconNP
        self.marker.setScale(0.05)
        iconNP.removeNode()
        self.mapOpenButton = DirectButton(image=(gui.find('**/tt_t_gui_qst_mapClose'), gui.find('**/tt_t_gui_qst_mapClose'), gui.find('**/tt_t_gui_qst_mapTryToOpen')), relief=None, pos=(-0.08, 0, 0.37), parent=base.a2dBottomRight, scale=0.205, command=self.show)
        self.mapCloseButton = DirectButton(image=(gui.find('**/tt_t_gui_qst_mapOpen'), gui.find('**/tt_t_gui_qst_mapOpen'), gui.find('**/tt_t_gui_qst_mapTryToClose')), relief=None, pos=(-0.08, 0, 0.37), parent=base.a2dBottomRight, scale=0.205, command=self.hide)
        self.mapOpenButton.hide()
        self.mapCloseButton.hide()
        gui.removeNode()
        icons = loader.loadModel('phase_3/models/gui/cog_icons')
        cIcon = icons.find('**/CorpIcon')
        lIcon = icons.find('**/LegalIcon')
        mIcon = icons.find('**/MoneyIcon')
        sIcon = icons.find('**/SalesIcon')
        cogInfoTextColor = (0.2, 0.2, 0.2, 1)
        textPos = (1.2, -0.2)
        textScale = 0.8
        self.cInfo = DirectLabel(parent=self.cogInfoFrame, text='', text_fg=cogInfoTextColor, text_pos=textPos, text_scale=textScale, geom=cIcon, geom_pos=(-0.2, 0, 0), geom_scale=0.8, relief=None)
        self.cInfo.setPos(-2.2, 0, 0.5)
        self.lInfo = DirectLabel(parent=self.cogInfoFrame, text_fg=cogInfoTextColor, text='', text_pos=textPos, text_scale=textScale, geom=lIcon, geom_pos=(-0.2, 0, 0), geom_scale=0.8, relief=None)
        self.lInfo.setPos(-2.2, 0, -0.5)
        self.mInfo = DirectLabel(parent=self.cogInfoFrame, text_fg=cogInfoTextColor, text='', text_pos=textPos, text_scale=textScale, geom=mIcon, geom_pos=(-0.2, 0, 0), geom_scale=0.8, relief=None)
        self.mInfo.setPos(0.8, 0, 0.5)
        self.sInfo = DirectLabel(parent=self.cogInfoFrame, text_fg=cogInfoTextColor, text='', text_pos=textPos, text_scale=textScale, geom=sIcon, geom_pos=(-0.2, 0, 0), geom_scale=0.8, relief=None)
        self.sInfo.setPos(0.8, 0, -0.5)
        icons.removeNode()
        return

    def updateCogInfo(self):
        currPercentage = self.suitPercentage.get(self.zoneId)
        if currPercentage is None:
            return
        self.cInfo['text'] = '%s%%' % currPercentage[0]
        self.lInfo['text'] = '%s%%' % currPercentage[1]
        self.mInfo['text'] = '%s%%' % currPercentage[2]
        self.sInfo['text'] = '%s%%' % currPercentage[3]
        return

    def destroy(self):
        self.ignore('questPageUpdated')
        self.mapOpenButton.destroy()
        self.mapCloseButton.destroy()
        del self.mapOpenButton
        del self.mapCloseButton
        DirectFrame.destroy(self)

    def putBuildingMarker(self, pos, hpr = (0, 0, 0), mapIndex = None):
        marker = DirectLabel(parent=self.container, text='', text_pos=(-0.05, -0.15), text_fg=(1, 1, 1, 1), relief=None)
        gui = loader.loadModel('phase_4/models/parties/schtickerbookHostingGUI')
        icon = gui.find('**/startPartyButton_inactive')
        iconNP = aspect2d.attachNewNode('iconNP')
        icon.reparentTo(iconNP)
        icon.setX(-12.0792 / 30.48)
        icon.setZ(-9.7404 / 30.48)
        marker['text'] = '%s' % mapIndex
        marker['text_scale'] = 0.7
        marker['image'] = iconNP
        marker['image_color'] = (1, 0, 0, 1)
        marker['image_scale'] = 6
        marker.setScale(0.05)
        relX, relY = self.transformAvPos(pos)
        marker.setPos(relX, 0, relY)
        self.buildingMarkers.append(marker)
        iconNP.removeNode()
        gui.removeNode()
        return

    def updateQuestInfo(self):
        for marker in self.buildingMarkers:
            marker.destroy()

        self.buildingMarkers = []

        for (i, questDesc) in enumerate(self.av.quests):
            mapIndex = i + 1
            quest = Quests.getQuest(questDesc[0])
            toNpcId = questDesc[2]

            completed = quest.getCompletionStatus(self.av, questDesc) == Quests.COMPLETE
            if not completed:
                if quest.getType() == Quests.RecoverItemQuest:
                    if quest.getHolder() == Quests.AnyFish:
                        self.putBuildingMarker(self.fishingSpotInfo, mapIndex=mapIndex)
                    continue
                elif quest.getType() not in (
                    Quests.DeliverGagQuest, Quests.DeliverItemQuest,
                    Quests.VisitQuest, Quests.TrackChoiceQuest):
                    continue

            if toNpcId == Quests.ToonHQ:
                self.putBuildingMarker(self.hqPosInfo, mapIndex=mapIndex)
                continue

            npcZoneId = NPCToons.getNPCZone(toNpcId)
            hoodId = ZoneUtil.getCanonicalHoodId(npcZoneId)
            branchId = ZoneUtil.getCanonicalBranchZone(npcZoneId)

            if (self.hoodId != hoodId) or (self.zoneId != branchId):
                continue

            for blockIndex in xrange(base.cr.playGame.dnaStore.getNumBlockNumbers()):
                blockNumber = base.cr.playGame.dnaStore.getBlockNumberAt(blockIndex)
                zoneId = base.cr.playGame.dnaStore.getZoneFromBlockNumber(blockNumber)
                interiorZoneId = (zoneId - (zoneId%100)) + 500 + blockNumber
                if npcZoneId == interiorZoneId:
                    self.putBuildingMarker(
                        base.cr.playGame.dnaStore.getDoorPosHprFromBlockNumber(blockNumber).getPos(render),
                        base.cr.playGame.dnaStore.getDoorPosHprFromBlockNumber(blockNumber).getHpr(render),
                        mapIndex=mapIndex)

    def transformAvPos(self, pos):
        if self.cornerPosInfo is None:
            return (0, 0)
        topRight = self.cornerPosInfo[0]
        bottomLeft = self.cornerPosInfo[1]
        relativeX = (pos.getX() - bottomLeft.getX()) / (topRight.getX() - bottomLeft.getX()) - 0.5
        relativeY = (pos.getY() - bottomLeft.getY()) / (topRight.getY() - bottomLeft.getY()) - 0.5
        return (relativeX, relativeY)

    def update(self, task):
        if self.av:
            if self.updateMarker:
                relX, relY = self.transformAvPos(self.av.getPos())
                self.marker.setPos(relX, 0, relY)
                self.marker.setHpr(0, 0, -180 - self.av.getH())
        i = 0
        for buildingMarker in self.buildingMarkers:
            buildingMarker.setScale((math.sin(task.time * 16.0 + i * math.pi / 3.0) + 1) * 0.005 + 0.04)
            i = i + 1

        return Task.cont

    def updateMap(self):
        if self.av:
            hoodId = ZoneUtil.getCanonicalHoodId(self.av.getLocation()[1])
            zoneId = ZoneUtil.getCanonicalBranchZone(self.av.getLocation()[1])
            try:
                mapsGeom = loader.loadModel('phase_4/models/questmap/%s_maps' % ToontownGlobals.dnaMap[hoodId])
            except:
                self.stop()
                return
            mapImage = mapsGeom.find('**/%s_%s_english' % (ToontownGlobals.dnaMap[hoodId], zoneId))
            if not mapImage.isEmpty():
                self.container['image'] = mapImage
                self.resetFrameSize()
                self.cornerPosInfo = QuestMapGlobals.CornerPosTable.get('%s_%s_english' % (ToontownGlobals.dnaMap[hoodId], zoneId))
                self.hqPosInfo = QuestMapGlobals.HQPosTable.get('%s_%s_english' % (ToontownGlobals.dnaMap[hoodId], zoneId))
                self.fishingSpotInfo = QuestMapGlobals.FishingSpotPosTable.get('%s_%s_english' % (ToontownGlobals.dnaMap[hoodId], zoneId))
                self.cogInfoPos = QuestMapGlobals.CogInfoPosTable.get('%s_%s_english' % (ToontownGlobals.dnaMap[hoodId], zoneId))
                self.cogInfoFrame.setPos(self.cogInfoPos)
                self.hide()
                self.hoodId = hoodId
                self.zoneId = zoneId
                self.updateQuestInfo()
                self.updateCogInfo()
                taskMgr.add(self.update, 'questMapUpdate')
            else:
                self.stop()
                mapsGeom.removeNode()

    def start(self):
        self.container.show()
        self.accept('questPageUpdated', self.updateMap)
        self.handleMarker()
        self.updateMap()

    def initMarker(self, task):
        if self.av:
            if not hasattr(base.cr.playGame.getPlace(), 'isInterior') or not base.cr.playGame.getPlace().isInterior:
                relX, relY = self.transformAvPos(self.av.getPos())
                self.marker.setPos(relX, 0, relY)
                self.marker.setHpr(0, 0, -180 - self.av.getH())
            self.marker['geom_scale'] = 1.4 * task.time % 0.5 * 10 + 1
            self.marker['geom_color'] = (1,
             1,
             1,
             0.8 - 1.4 * task.time % 0.5 * 2 / 0.8 + 0.2)
        if task.time < 1:
            return Task.cont
        else:
            self.marker['geom_color'] = (1, 1, 1, 0)
            return Task.done

    def show(self):
        taskMgr.add(self.initMarker, 'questMapInit')
        DirectFrame.show(self)
        self.mapOpenButton.hide()
        if self.container['image']:
            self.mapCloseButton.show()

    def hide(self):
        taskMgr.remove('questMapInit')
        DirectFrame.hide(self)
        if self.container['image']:
            self.mapOpenButton.show()
        self.mapCloseButton.hide()

    def toggle(self):
        if self.isHidden():
            self.show()
        else:
            self.hide()

    def obscureButton(self):
        self.mapOpenButton.hide()
        self.mapCloseButton.hide()

    def stop(self):
        self.container['image'] = None
        for marker in self.buildingMarkers:
            marker.destroy()

        self.buildingMarkers = []
        self.container.hide()
        self.hide()
        self.obscureButton()
        self.ignore('questPageUpdated')
        taskMgr.remove('questMapUpdate')
        return

    def handleMarker(self):
        if hasattr(base.cr.playGame.getPlace(), 'isInterior') and base.cr.playGame.getPlace().isInterior:
            self.updateMarker = False
        else:
            self.updateMarker = True

    def acceptOnscreenHooks(self):
        if self.wantToggle:
            self.accept(ToontownGlobals.MapHotkey, self.toggle)
        else:
            self.accept(ToontownGlobals.MapHotkeyOn, self.show)
            self.accept(ToontownGlobals.MapHotkeyOff, self.hide)
        self.updateMap()

    def ignoreOnscreenHooks(self):
        self.ignore(ToontownGlobals.MapHotkey)
        self.ignore(ToontownGlobals.MapHotkeyOn)
        self.ignore(ToontownGlobals.MapHotkeyOff)
        self.obscureButton()
class CharityScreen(DistributedObject):
    notify = directNotify.newCategory('CharityScreen')

    def __init__(self, cr):
        DistributedObject.__init__(self, cr)
        self.zone2pos = {
            ToontownGlobals.ToontownCentral: (40, 0, 25),
            ToontownGlobals.DonaldsDock: (-25, 17, 25),
            ToontownGlobals.DaisyGardens: (5, 137, 25),
            ToontownGlobals.MinniesMelodyland: (0, 0, 8),
            ToontownGlobals.TheBrrrgh: (-111, -44, 25),
            ToontownGlobals.DonaldsDreamland: (0, 0, 6)
        }
        self.bob = None
        self.screenObject = None
        self.counter = None

    def announceGenerate(self):
        self.cr.chairityEvent = self

    def start(self, zoneId):
        threading.Thread(target=taskMgr.add,
                         args=(self.setCount, 'countTask')).start()

        def startScreen(*args):
            self.screenObject = args[0]
            if not self.screenObject:
                return
            self.screenObject.reparentTo(render)
            text = ''  # "Welcome to PRE-BETA!\nPlease note that there are bugs.\nReport them to the devs!"
            if ZoneUtil.getHoodId(zoneId) == ToontownGlobals.MinniesMelodyland:
                self.screenObject.reparentTo(
                    self.cr.playGame.getPlace().loader.geom.find(
                        '**/center_icon'))
            self.screenObject.setPos(
                self.zone2pos.get(ZoneUtil.getHoodId(zoneId), (0, 0, 6)))
            self.screenObject.setHpr(-90, 0, 0)
            self.counter = DirectLabel(
                parent=render,
                pos=(0, 0, 0),
                relief=None,
                text=text,
                text_scale=1,
                text_fg=(1, 1, 1, 1),
                text_align=TextNode.ACenter,
                text_font=ToontownGlobals.getMinnieFont())
            self.counter.reparentTo(self.screenObject)
            self.counter.setPos(
                self.screenObject.find("**/front_screen").getPos() +
                Point3(0.0, -1.5, 0.3))

            self.counterback = DirectLabel(
                parent=render,
                pos=(0, 0, 0),
                relief=None,
                text=text,
                text_scale=1,
                text_fg=(1, 1, 1, 1),
                text_align=TextNode.ACenter,
                text_font=ToontownGlobals.getMinnieFont())
            self.counterback.reparentTo(self.screenObject)
            self.counterback.setPos(
                self.screenObject.find("**/back_screen").getPos() +
                Point3(0.0, 1.5, 0.3))
            self.counterback.setHpr(180, 0, 0)

            self.bob = Sequence(
                LerpPosInterval(nodePath=self.screenObject,
                                duration=3.2,
                                pos=(self.screenObject.getX(),
                                     self.screenObject.getY(),
                                     self.screenObject.getZ() + 1.65),
                                blendType='easeInOut'),
                Sequence(
                    Wait(0.050),
                    LerpPosInterval(nodePath=self.screenObject,
                                    duration=3.0,
                                    pos=(self.screenObject.getX(),
                                         self.screenObject.getY(),
                                         self.screenObject.getZ()),
                                    blendType='easeInOut'),
                    Sequence(Wait(0.050))))
            self.bob.loop()

        asyncloader.loadModel(
            "phase_3.5/models/events/charity/flying_screen.bam",
            callback=startScreen)

    def setCount(self, task):
        self.count = base.localAvatar.getStat(ToontownGlobals.STATS_COGS)
        cash = self.count / 1000.0
        cash = '{:,.2f}'.format(cash)
        if self.counter and self.counterback:
            self.counter['text'] = (
                str(self.count) +
                "\nCogs Destroyed\nYou've earned %s USD\nfor the Extra Life Charity!"
            ) % cash
            self.counterback['text'] = (
                str(self.count) +
                "\nCogs Destroyed\nYou've earned %s USD\nfor the Extra Life Charity!"
            ) % cash
        taskMgr.doMethodLater(10, self.setCount, 'countTask')

    def unload(self):
        self.notify.debug("Unloading Charity Screen!")
        self.ignoreAll()
        if self.bob:
            self.bob.finish()
            self.bob = None
        if self.screenObject:
            self.screenObject.removeNode()
            self.screenObject = None

    def delete(self):
        self.cr.chairityEvent = None
        self.notify.debug("Deleting Charity Screen!")
        taskMgr.remove('countTask')
        if self.bob:
            self.bob.finish()
            self.bob = None
        if self.screenObject:
            self.screenObject.removeNode()
            self.screenObject = None