示例#1
0
 def setScale(self, *args, **kwargs):
     DirectFrame.setScale(self, *args, **args)
     self.resetArcBall()
示例#2
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.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()
        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 = []
        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 xrange(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)

        return

    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/%s_maps' %
                                            ToontownGlobals.dnaMap[hoodId])
                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()
            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')
        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 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
        self.accessibleObjectives = quest.accessibleObjectives if quest else []
        self.viewObjective = quest.accessibleObjectives.seek(
        ) if quest else None

        isObjComplete = False if not quest else (
            self.accessibleObjectives.isComplete() or quest.isComplete())

        # 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),
                      ('image_color', (1.0, 1.0, 1.0,
                                       1.0) if not isObjComplete else Vec4(
                                           *QuestGlobals.LIGHT_GREEN),
                       None), ('state', DGG.NORMAL, None))
        self.defineoptions(kw, optiondefs)

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

        # Let's declare and initialize our barebone GUI element variables.
        questTitle = '' if not self.quest else self.quest.name
        self.titleLabel = DirectLabel(parent=self,
                                      relief=None,
                                      text=questTitle,
                                      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.

        circleGui = loader.loadModel(
            'phase_4/models/gui/CircleIconBackgroundGui.bam')
        self.auxFrame = DirectFrame(
            parent=self,
            relief=None,
            image=circleGui.find('**/circle_display_interior'),
            image_scale=0.18,
            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)

        if self.quest and len(
                self.quest.accessibleObjectives) > 1 and not isObjComplete:
            # We can only use arrows when we have more than one objective available.
            arrowGui = loader.loadModel('phase_4/models/gui/QuestArrowGui.bam')
            self.prevObjArrow = DirectButton(
                parent=self.auxFrame,
                relief=None,
                geom=((arrowGui.find('**/quest_arrow_enabled'),
                       arrowGui.find('**/quest_arrow_click'),
                       arrowGui.find('**/quest_arrow_mouseover'),
                       arrowGui.find('**/quest_arrow_disabled'))),
                scale=0.08,
                command=self.switchObjective,
                extraArgs=[0],
                hpr=(180, 0, 0),
                pos=QuestGlobals.DEFAULT_LEFT_ARROW_POS)

            self.nextObjArrow = DirectButton(
                parent=self.auxFrame,
                relief=None,
                geom=((arrowGui.find('**/quest_arrow_enabled'),
                       arrowGui.find('**/quest_arrow_click'),
                       arrowGui.find('**/quest_arrow_mouseover'),
                       arrowGui.find('**/quest_arrow_disabled'))),
                scale=0.08,
                command=self.switchObjective,
                pos=QuestGlobals.DEFAULT_RIGHT_ARROW_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)

        self.auxOutline = DirectLabel(
            parent=self.auxFrame,
            relief=None,
            image=circleGui.find('**/circle_display_outline'),
            image_scale=0.18)

        # 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.62, 0, 0.4),
            pos=(-0.015, 0, -0.25))

        # Let's setup our reward frames.
        reward = None

        if self.quest and len(self.quest.rewards) > 0:
            reward = self.quest.rewards[0]
        self.lReward = QuestRewardFrame(self, reward)

        # 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.
        circleGui.removeNode()
        bookModel.removeNode()
        rewardFrameGeom.removeNode()

        # We are only removing this node if we generated arrows.
        if hasattr(self, 'arrowGui'):
            arrowGui.removeNode()

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

    def switchObjective(self, forward=1):
        if forward:
            self.accessibleObjectives.nextObjective()
        else:
            self.accessibleObjectives.lastObjective()
        self.viewObjective = self.accessibleObjectives.seek()
        self.setup()

    def setup(self):
        if self.quest:
            objective = self.viewObjective
            complete = self.accessibleObjectives.isComplete()

            # Let's reset our positioning of elements.
            self.auxFrame.setPos(QuestGlobals.DEFAULT_LEFT_PICTURE_POS)
            self.auxText.setPos(QuestGlobals.DEFAULT_AUX_POS)
            self.objectiveInfo.setPos(QuestGlobals.DEFAULT_INFO_POS)

            # Let's reset our icon.
            self.auxIcon.setScale(1, 1, 1)
            self.auxIcon.setPos(0, 0, 0)
            self.auxIcon.setHpr(0, 0, 0)

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

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

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

            if objective.HasProgress and objective.goal > 1 and not complete:
                self.progressBar.show()

            self.auxText.show()

            # Let's handle the objectives.
            if not complete:
                if objective.__class__ == CogObjective:
                    self.handleCogObjective()
                elif objective.__class__ == CogBuildingObjective:
                    self.handleCogBuildingObjective()
                elif objective.__class__ == MinigameObjective:
                    self.handleMinigameObjective()
                elif objective.__class__ == VisitNPCObjective:
                    self.handleNPCObjective()
            else:
                bgColor = QuestGlobals.RED

                if objective.type in DefeatObjectives:
                    bgColor = QuestGlobals.BLUE

                self.handleNPCObjective(auxText=QuestGlobals.RETURN + ' to',
                                        frameColor=bgColor)

            self.lReward.setup()

            newLineInObjInfo = '\n' in self.objectiveInfo['text']
            isShopLoc = QuestGlobals.isShopLocation(
                objective.area) if not complete else True

            if complete:
                locationText = QuestGlobals.getLocationText(None, objective)
            else:
                locationText = QuestGlobals.getLocationText(objective.area)

            self.locationInfo['text'] = locationText
            self.locationInfo['text_pos'] = (0.0, (0.025 if isShopLoc else (
                -0.025 if newLineInObjInfo else 0.0)))
            self.locationInfo.show()
        else:
            # We want to be able to show empty quest posters.
            self.titleLabel.hide()
            self.auxFrame.hide()
            self.auxIcon.hide()

        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)
        self.lReward.initialiseoptions(DirectFrame)

        # Handle arrow stuff if necessary.
        if hasattr(self, 'prevObjArrow'):
            index = self.accessibleObjectives.seeker
            self.prevObjArrow['state'] = DGG.NORMAL
            self.nextObjArrow['state'] = DGG.NORMAL
            self.prevObjArrow.setPos(QuestGlobals.DEFAULT_LEFT_ARROW_POS)
            self.nextObjArrow.setPos(QuestGlobals.DEFAULT_RIGHT_ARROW_POS)

            if index == 0:
                self.prevObjArrow['state'] = DGG.DISABLED
            elif index == len(self.accessibleObjectives) - 1:
                self.nextObjArrow['state'] = DGG.DISABLED

            self.prevObjArrow.initialiseoptions(DirectButton)
            self.nextObjArrow.initialiseoptions(DirectButton)

    # 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):
        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)
            icon.setH(180)
        else:
            icon.setZ(icon.getZ() - 0.01)

    def handleCogObjective(self,
                           iconElement=auxIcon,
                           auxText=QuestGlobals.DEFEAT,
                           frameColor=QuestGlobals.BLUE):
        objective = self.viewObjective
        infoText = objective.getTaskInfo()

        if objective.__class__ == RecoverItemObjective:
            infoText = CIGlobals.makePlural(objective.cog)

        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 objective.cog == QuestGlobals.Any:
            # We aren't fighting a Cog in particular.
            cogIcon = QuestGlobals.getCogIcon()
            self.handleSimpleIcon(cogIcon, 0.13, iconElement)

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

            # HACK FIX: Corrects the buggy Flunky glasses.
            glasses = cogHead.find('**/glasses')
            if glasses and not glasses.isEmpty():
                glasses.setScale(1)
                glasses.reparentTo(cogHead)

        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

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

        self.auxText['text'] = auxText

        # 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 handleCogBuildingObjective(self,
                                   iconElement=auxIcon,
                                   auxText=QuestGlobals.DEFEAT,
                                   frameColor=QuestGlobals.BLUE):
        objective = self.viewObjective
        infoText = objective.getTaskInfo()

        if not iconElement:
            iconElement = self.auxIcon

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

        # If we aren't looking for any specific department of building.
        if objective.dept == QuestGlobals.Any:
            # Let's just use the good ol' generic building icon.
            self.handleSimpleIcon(QuestGlobals.getCogBuildingIcon(),
                                  QuestGlobals.SIMPLE_IMAGE_SCALE, iconElement)
        else:
            # Ah geez, we're looking for a specific department.
            # Bossbot tie names are messed up, so we need this if statement.
            dept = objective.dept.getTie(
            ) if not objective.dept == Dept.BOSS else 'corp'
            bldgMdl = loader.loadModel(
                'phase_4/models/modules/suit_landmark_%s.bam' % dept)

            # Next, we need to load the building elevator.
            elevator = loader.loadModel('phase_4/models/modules/elevator.bam')
            elevator.reparentTo(bldgMdl.find('**/*_door_origin'))

            self.handleComplexIcon(bldgMdl, iconElement)

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

        self.objectiveInfo['text'] = infoText
        self.auxText['text'] = auxText
        self.auxFrame['image_color'] = Vec4(*frameColor)

    def handleMinigameObjective(self,
                                iconElement=auxIcon,
                                auxText=QuestGlobals.PLAY,
                                frameColor=QuestGlobals.RED):
        objective = self.viewObjective
        infoText = objective.getTaskInfo()

        if not iconElement:
            iconElement = self.auxIcon

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

        # Let's set the icon to the minigame icon.
        self.handleSimpleIcon(QuestGlobals.getTrolleyIcon(),
                              QuestGlobals.SIMPLE_IMAGE_SCALE, iconElement)

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

        self.objectiveInfo['text'] = infoText
        self.auxText['text'] = auxText
        self.auxFrame['image_color'] = Vec4(*frameColor)

    def handleNPCObjective(self,
                           iconElement=auxIcon,
                           auxText=QuestGlobals.VISIT,
                           frameColor=QuestGlobals.BROWN):
        objective = self.viewObjective
        npcId = 0

        if self.accessibleObjectives.isComplete() and not hasattr(
                objective, 'npcId'):
            npcId = objective.assigner
        elif hasattr(objective, 'npcId'):
            npcId = objective.npcId

        if npcId == 0:
            infoText = 'A %s' % NPCGlobals.lHQOfficerF
        else:
            infoText = NPCGlobals.NPCToonNames[npcId]

        if not iconElement:
            iconElement = self.auxIcon

        # Let's generate the head.
        if not npcId == 0:
            dna = ToonDNA()
            dna.setDNAStrand(NPCGlobals.NPCToonDict.get(npcId)[2])
            head = ToonGlobals.generateGuiHead(dna)
            self.handleComplexIcon(head,
                                   iconElement,
                                   scale=QuestGlobals.IMAGE_SCALE_SMALL - 0.01)
        else:
            self.handleSimpleIcon(QuestGlobals.getHQIcon(),
                                  QuestGlobals.SIMPLE_IMAGE_SCALE, 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.auxOutline.destroy()
            self.auxText.destroy()
            self.objectiveInfo.destroy()
            self.locationInfo.destroy()
            self.progressBar.destroy()
            self.rewardFrame.destroy()
            self.sideInfo.destroy()
            self.lReward.destroy()

            # We need to cleanup our arrows if they were created.
            if hasattr(self, 'prevObjArrow'):
                self.prevObjArrow.destroy()
                self.nextObjArrow.destroy()
                del self.prevObjArrow
                del self.nextObjArrow

            del self.titleLabel
            del self.auxFrame
            del self.auxIcon
            del self.auxOutline
            del self.auxText
            del self.objectiveInfo
            del self.locationInfo
            del self.progressBar
            del self.rewardFrame
            del self.sideInfo
            del self.lReward
            del self.accessibleObjectives
            del self.viewObjective
            DirectFrame.destroy(self)
            self.notify.debug('Destroyed all elements.')
示例#4
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 Transitions:

    # These may be reassigned before the fade or iris transitions are
    # actually invoked to change the models that will be used.
    IrisModelName = "models/misc/iris"
    FadeModelName = "models/misc/fade"

    def __init__(self, loader,
                 model=None,
                 scale=3.0,
                 pos=Vec3(0, 0, 0)):
        self.transitionIval = None
        self.__transitionFuture = None
        self.letterboxIval = None
        self.__letterboxFuture = None
        self.iris = None
        self.fade = None
        self.letterbox = None
        self.fadeModel = model
        self.imagePos = pos
        if model:
            self.alphaOff = Vec4(1, 1, 1, 0)
            self.alphaOn = Vec4(1, 1, 1, 1)
            model.setTransparency(1)
            self.lerpFunc = LerpColorScaleInterval
        else:
            self.alphaOff = Vec4(0, 0, 0, 0)
            self.alphaOn = Vec4(0, 0, 0, 1)
            self.lerpFunc = LerpColorInterval

        self.irisTaskName = "irisTask"
        self.fadeTaskName = "fadeTask"
        self.letterboxTaskName = "letterboxTask"

    def __del__(self):
        if self.fadeModel:
            self.fadeModel.removeNode()
            self.fadeModel = None

    ##################################################
    # Fade
    ##################################################

    # We can set a custom model for the fade before using it for the first time
    def setFadeModel(self, model, scale=1.0):
        self.fadeModel = model
        # We have to change some default parameters for a custom fadeModel
        self.alphaOn = Vec4(1, 1, 1, 1)

        # Reload fade if its already been created
        if self.fade:
            self.fade.destroy()
            self.fade = None
            self.loadFade()

    def loadFade(self):
        if self.fade is None:
            # We create a DirectFrame for the fade polygon, instead of
            # simply loading the polygon model and using it directly,
            # so that it will also obscure mouse events for objects
            # positioned behind it.
            self.fade = DirectFrame(
                parent = ShowBaseGlobal.hidden,
                guiId = 'fade',
                relief = None,
                image = self.fadeModel,
                image_scale = (4, 2, 2),
                state = DGG.NORMAL,
                )
            if not self.fadeModel:
                # No fade model was given, so we make this the fade model.
                self.fade["relief"] = DGG.FLAT
                self.fade["frameSize"] = (-2, 2, -1, 1)
                self.fade["frameColor"] = (0, 0, 0, 1)
                self.fade.setTransparency(TransparencyAttrib.MAlpha)
            self.fade.setBin('unsorted', 0)
            self.fade.setColor(0,0,0,0)

        self.fade.setScale(max(base.a2dRight, base.a2dTop))

    def getFadeInIval(self, t=0.5, finishIval=None, blendType='noBlend'):
        """
        Returns an interval without starting it.  This is particularly useful in
        cutscenes, so when the cutsceneIval is escaped out of we can finish the fade immediately
        """
        #self.noTransitions() masad: this creates a one frame pop, is it necessary?
        self.loadFade()

        transitionIval = Sequence(Func(self.fade.reparentTo, aspect2d, DGG.FADE_SORT_INDEX),
                                  Func(self.fade.showThrough),  # in case aspect2d is hidden for some reason
                                  self.lerpFunc(self.fade, t,
                                                self.alphaOff,
                                                # self.alphaOn,
                                                blendType=blendType
                                                ),
                                  Func(self.fade.detachNode),
                                  name = self.fadeTaskName,
                                  )
        if finishIval:
            transitionIval.append(finishIval)
        return transitionIval

    def getFadeOutIval(self, t=0.5, finishIval=None, blendType='noBlend'):
        """
        Create a sequence that lerps the color out, then
        parents the fade to hidden
        """
        self.noTransitions()
        self.loadFade()

        transitionIval = Sequence(Func(self.fade.reparentTo, aspect2d, DGG.FADE_SORT_INDEX),
                                  Func(self.fade.showThrough),  # in case aspect2d is hidden for some reason
                                  self.lerpFunc(self.fade, t,
                                                self.alphaOn,
                                                # self.alphaOff,
                                                blendType=blendType
                                                ),
                                  name = self.fadeTaskName,
                                  )
        if finishIval:
            transitionIval.append(finishIval)
        return transitionIval

    def fadeIn(self, t=0.5, finishIval=None, blendType='noBlend'):
        """
        Play a fade in transition over t seconds.
        Places a polygon on the aspect2d plane then lerps the color
        from black to transparent. When the color lerp is finished, it
        parents the fade polygon to hidden.
        """
        gsg = base.win.getGsg()
        if gsg:
            # If we're about to fade in from black, go ahead and
            # preload all the textures etc.
            base.graphicsEngine.renderFrame()
            render.prepareScene(gsg)
            render2d.prepareScene(gsg)

        if (t == 0):
            # Fade in immediately with no lerp
            #print "transitiosn: fadeIn 0.0"
            self.noTransitions()
            self.loadFade()
            self.fade.detachNode()
            fut = AsyncFuture()
            fut.setResult(None)
            return fut
        else:
            # Create a sequence that lerps the color out, then
            # parents the fade to hidden
            self.transitionIval = self.getFadeInIval(t, finishIval, blendType)
            self.transitionIval.append(Func(self.__finishTransition))
            self.__transitionFuture = AsyncFuture()
            self.transitionIval.start()
            return self.__transitionFuture

    def fadeOut(self, t=0.5, finishIval=None, blendType='noBlend'):
        """
        Play a fade out transition over t seconds.
        Places a polygon on the aspect2d plane then lerps the color
        from transparent to full black. When the color lerp is finished,
        it leaves the fade polygon covering the aspect2d plane until you
        fadeIn or call noFade.
        lerp
        """
        if (t == 0):
            # Fade out immediately with no lerp
            self.noTransitions()
            self.loadFade()

            self.fade.reparentTo(aspect2d, DGG.FADE_SORT_INDEX)
            self.fade.setColor(self.alphaOn)
        elif ConfigVariableBool('no-loading-screen', False):
            if finishIval:
                self.transitionIval = finishIval
                self.transitionIval.start()
        else:
            # Create a sequence that lerps the color out, then
            # parents the fade to hidden
            self.transitionIval = self.getFadeOutIval(t, finishIval, blendType)
            self.transitionIval.append(Func(self.__finishTransition))
            self.__transitionFuture = AsyncFuture()
            self.transitionIval.start()
            return self.__transitionFuture

        # Immediately done, so return a dummy future.
        fut = AsyncFuture()
        fut.setResult(None)
        return fut

    def fadeOutActive(self):
        return self.fade and self.fade.getColor()[3] > 0

    def fadeScreen(self, alpha=0.5):
        """
        Put a semitransparent screen over the camera plane
        to darken out the world. Useful for drawing attention to
        a dialog box for instance
        """
        #print "transitiosn: fadeScreen"
        self.noTransitions()
        self.loadFade()

        self.fade.reparentTo(aspect2d, DGG.FADE_SORT_INDEX)
        self.fade.setColor(self.alphaOn[0],
                           self.alphaOn[1],
                           self.alphaOn[2],
                           alpha)

    def fadeScreenColor(self, color):
        """
        Put a semitransparent screen over the camera plane
        to darken out the world. Useful for drawing attention to
        a dialog box for instance
        """
        #print "transitiosn: fadeScreenColor"
        self.noTransitions()
        self.loadFade()

        self.fade.reparentTo(aspect2d, DGG.FADE_SORT_INDEX)
        self.fade.setColor(color)

    def noFade(self):
        """
        Removes any current fade tasks and parents the fade polygon away
        """
        #print "transitiosn: noFade"
        if self.transitionIval:
            self.transitionIval.pause()
            self.transitionIval = None
        if self.__transitionFuture:
            self.__transitionFuture.cancel()
            self.__transitionFuture = None
        if self.fade:
            # Make sure to reset the color, since fadeOutActive() is looking at it
            self.fade.setColor(self.alphaOff)
            self.fade.detachNode()

    def setFadeColor(self, r, g, b):
        self.alphaOn.set(r, g, b, 1)
        self.alphaOff.set(r, g, b, 0)


    ##################################################
    # Iris
    ##################################################

    def loadIris(self):
        if self.iris == None:
            self.iris = loader.loadModel(self.IrisModelName)
            self.iris.setPos(0, 0, 0)

    def irisIn(self, t=0.5, finishIval=None, blendType = 'noBlend'):
        """
        Play an iris in transition over t seconds.
        Places a polygon on the aspect2d plane then lerps the scale
        of the iris polygon up so it looks like we iris in. When the
        scale lerp is finished, it parents the iris polygon to hidden.
        """
        self.noTransitions()
        self.loadIris()
        if (t == 0):
            self.iris.detachNode()
            fut = AsyncFuture()
            fut.setResult(None)
            return fut
        else:
            self.iris.reparentTo(aspect2d, DGG.FADE_SORT_INDEX)

            scale = 0.18 * max(base.a2dRight, base.a2dTop)
            self.transitionIval = Sequence(LerpScaleInterval(self.iris, t,
                                                   scale = scale,
                                                   startScale = 0.01,
                                                   blendType=blendType),
                                 Func(self.iris.detachNode),
                                 Func(self.__finishTransition),
                                 name = self.irisTaskName,
                                 )
            self.__transitionFuture = AsyncFuture()
            if finishIval:
                self.transitionIval.append(finishIval)
            self.transitionIval.start()
            return self.__transitionFuture

    def irisOut(self, t=0.5, finishIval=None, blendType='noBlend'):
        """
        Play an iris out transition over t seconds.
        Places a polygon on the aspect2d plane then lerps the scale
        of the iris down so it looks like we iris out. When the scale
        lerp is finished, it leaves the iris polygon covering the
        aspect2d plane until you irisIn or call noIris.
        """
        self.noTransitions()
        self.loadIris()
        self.loadFade()  # we need this to cover up the hole.
        if (t == 0):
            self.iris.detachNode()
            self.fadeOut(0)
            fut = AsyncFuture()
            fut.setResult(None)
            return fut
        else:
            self.iris.reparentTo(aspect2d, DGG.FADE_SORT_INDEX)

            scale = 0.18 * max(base.a2dRight, base.a2dTop)
            self.transitionIval = Sequence(LerpScaleInterval(self.iris, t,
                                                   scale = 0.01,
                                                   startScale = scale,
                                                   blendType=blendType),
                                 Func(self.iris.detachNode),
                                 # Use the fade to cover up the hole that the iris would leave
                                 Func(self.fadeOut, 0),
                                 Func(self.__finishTransition),
                                 name = self.irisTaskName,
                                 )
            self.__transitionFuture = AsyncFuture()
            if finishIval:
                self.transitionIval.append(finishIval)
            self.transitionIval.start()
            return self.__transitionFuture

    def noIris(self):
        """
        Removes any current iris tasks and parents the iris polygon away
        """
        if self.transitionIval:
            self.transitionIval.pause()
            self.transitionIval = None
        if self.iris != None:
            self.iris.detachNode()
        # Actually we need to remove the fade too,
        # because the iris effect uses it.
        self.noFade()

    def noTransitions(self):
        """
        This call should immediately remove any and all transitions running
        """
        self.noFade()
        self.noIris()
        # Letterbox is not really a transition, it is a screen overlay
        # self.noLetterbox()

    def __finishTransition(self):
        if self.__transitionFuture:
            self.__transitionFuture.setResult(None)
            self.__transitionFuture = None

    ##################################################
    # Letterbox
    ##################################################

    def loadLetterbox(self):
        if not self.letterbox:
            # We create a DirectFrame for the fade polygon, instead of
            # simply loading the polygon model and using it directly,
            # so that it will also obscure mouse events for objects
            # positioned behind it.
            self.letterbox = NodePath("letterbox")
            # Allow fade in and out of the bars
            self.letterbox.setTransparency(1)

            # Allow DirectLabels to be parented to the letterbox sensibly
            self.letterbox.setBin('unsorted', 0)

            # Allow a custom look to the letterbox graphic.

            # TODO: This model isn't available everywhere.  We should
            # pass it in as a parameter.
            button = loader.loadModel('models/gui/toplevel_gui',
                                      okMissing = True)

            barImage = None
            if button:
                barImage = button.find('**/generic_button')

            self.letterboxTop = DirectFrame(
                parent = self.letterbox,
                guiId = 'letterboxTop',
                relief = DGG.FLAT,
                state = DGG.NORMAL,
                frameColor = (0, 0, 0, 1),
                borderWidth = (0, 0),
                frameSize = (-1, 1, 0, 0.2),
                pos = (0, 0, 1.0),
                image = barImage,
                image_scale = (2.25,1,.5),
                image_pos = (0,0,.1),
                image_color = (0.3,0.3,0.3,1),
                sortOrder = 0,
                )
            self.letterboxBottom = DirectFrame(
                parent = self.letterbox,
                guiId = 'letterboxBottom',
                relief = DGG.FLAT,
                state = DGG.NORMAL,
                frameColor = (0, 0, 0, 1),
                borderWidth = (0, 0),
                frameSize = (-1, 1, 0, 0.2),
                pos = (0, 0, -1.2),
                image = barImage,
                image_scale = (2.25,1,.5),
                image_pos = (0,0,.1),
                image_color = (0.3,0.3,0.3,1),
                sortOrder = 0,
                )

            # masad: always place these at the bottom of render
            self.letterboxTop.setBin('sorted',0)
            self.letterboxBottom.setBin('sorted',0)
            self.letterbox.reparentTo(render2d, -1)
            self.letterboxOff(0)

    def noLetterbox(self):
        """
        Removes any current letterbox tasks and parents the letterbox polygon away
        """
        if self.letterboxIval:
            self.letterboxIval.pause()
            self.letterboxIval = None
        if self.__letterboxFuture:
            self.__letterboxFuture.cancel()
            self.__letterboxFuture = None
        if self.letterbox:
            self.letterbox.stash()

    def __finishLetterbox(self):
        if self.__letterboxFuture:
            self.__letterboxFuture.setResult(None)
            self.__letterboxFuture = None

    def letterboxOn(self, t=0.25, finishIval=None, blendType='noBlend'):
        """
        Move black bars in over t seconds.
        """
        self.noLetterbox()
        self.loadLetterbox()
        self.letterbox.unstash()
        if (t == 0):
            self.letterboxBottom.setPos(0, 0, -1)
            self.letterboxTop.setPos(0, 0, 0.8)
            fut = AsyncFuture()
            fut.setResult(None)
            return fut
        else:
            self.__letterboxFuture = AsyncFuture()
            self.letterboxIval = Sequence(Parallel(
                LerpPosInterval(self.letterboxBottom,
                                t,
                                pos = Vec3(0, 0, -1),
                                #startPos = Vec3(0, 0, -1.2),
                                blendType=blendType
                                ),
                LerpPosInterval(self.letterboxTop,
                                t,
                                pos = Vec3(0, 0, 0.8),
                                # startPos = Vec3(0, 0, 1),
                                blendType=blendType
                                ),
                ),
                                          Func(self.__finishLetterbox),
                                          name = self.letterboxTaskName,
                                          )
            if finishIval:
                self.letterboxIval.append(finishIval)
            self.letterboxIval.start()
            return self.__letterboxFuture

    def letterboxOff(self, t=0.25, finishIval=None, blendType='noBlend'):
        """
        Move black bars away over t seconds.
        """
        self.noLetterbox()
        self.loadLetterbox()
        self.letterbox.unstash()
        if (t == 0):
            self.letterbox.stash()
            fut = AsyncFuture()
            fut.setResult(None)
            return fut
        else:
            self.__letterboxFuture = AsyncFuture()
            self.letterboxIval = Sequence(Parallel(
                LerpPosInterval(self.letterboxBottom,
                                t,
                                pos = Vec3(0, 0, -1.2),
                                # startPos = Vec3(0, 0, -1),
                                blendType=blendType
                                ),
                LerpPosInterval(self.letterboxTop,
                                t,
                                pos = Vec3(0, 0, 1),
                                # startPos = Vec3(0, 0, 0.8),
                                blendType=blendType
                                ),
                ),
                                          Func(self.letterbox.stash),
                                          Func(self.__finishLetterbox),
                                          Func(messenger.send,'letterboxOff'),
                                          name = self.letterboxTaskName,
                                          )
            if finishIval:
                self.letterboxIval.append(finishIval)
            self.letterboxIval.start()
            return self.__letterboxFuture
class OptionsPage(BookPage):
    notify = directNotify.newCategory("OptionsPage")

    # Keys are categories and values are x-positions for the text.
    Categories = OrderedDict()
    Categories[AboutCategory] = 0.09
    Categories[GeneralCategory] = 0.07
    Categories[ControlsCategory] = 0.05
    Categories[SoundCategory] = 0.0825
    Categories[DisplayCategory] = 0.07
    Categories[AdvancedDisplayCategory] = 0.05

    def __init__(self, book):
        BookPage.__init__(self, book, "Options")
        self.currentCategory = None
        self.tabs = []

    def load(self):
        BookPage.load(self)
        icons = loader.loadModel('phase_3.5/models/gui/sos_textures.bam')
        self.icon = icons.find('**/switch')
        icons.detachNode()

    def enter(self):
        BookPage.enter(self)
        self.tabScaleFrame = DirectFrame(parent=self.book)
        self.tabScaleFrame.setZ(0.7683)
        self.tabsFrame = DirectFrame(parent=self.tabScaleFrame)

        tabWidth = 0.379136800766
        spacing = 0.075

        totalWidth = 0.0
        bookWidth = 2.0

        for i in xrange(len(self.Categories.keys())):
            if i > 0:
                totalWidth += spacing
            totalWidth += tabWidth
            cl = self.Categories.keys()[i]
            tab = CategoryTab(self, cl.Name, [cl],
                              ((tabWidth + spacing) * i, 0, 0),
                              self.Categories.values()[i])
            self.tabs.append(tab)

        self.tabsFrame.setX(totalWidth / -2.0)
        self.tabScaleFrame.setScale(min(1.0, 1.0 / (totalWidth / bookWidth)))

        self.pickCategory(AboutCategory)

    def closeWindow(self):
        if self.currentCategory:
            self.currentCategory.cleanup()
            self.currentCategory = None

    def pickCategory(self, cat):
        if self.currentCategory:
            self.currentCategory.cleanup()
            self.currentCategory = None
        self.currentCategory = cat(self)
        for tab in self.tabs:
            if tab['extraArgs'][0] is cat:
                tab['state'] = DGG.DISABLED
            else:
                tab['state'] = DGG.NORMAL
        #self.currentCategory.show()

    def exit(self):
        if self.currentCategory:
            self.currentCategory.cleanup()
            self.currentCategory = None
        for tab in self.tabs:
            tab.destroy()
        self.tabsFrame.destroy()
        del self.tabsFrame
        self.tabScaleFrame.destroy()
        del self.tabScaleFrame
        self.tabs = []
        BookPage.exit(self)
示例#7
0
class Transitions:

    # These may be reassigned before the fade or iris transitions are
    # actually invoked to change the models that will be used.
    IrisModelName = "models/misc/iris"
    FadeModelName = "models/misc/fade"

    def __init__(self, loader,
                 model=None,
                 scale=3.0,
                 pos=Vec3(0, 0, 0)):
        self.transitionIval = None
        self.__transitionFuture = None
        self.letterboxIval = None
        self.__letterboxFuture = None
        self.iris = None
        self.fade = None
        self.letterbox = None
        self.fadeModel = model
        self.imagePos = pos
        if model:
            self.alphaOff = Vec4(1, 1, 1, 0)
            self.alphaOn = Vec4(1, 1, 1, 1)
            model.setTransparency(1)
            self.lerpFunc = LerpColorScaleInterval
        else:
            self.alphaOff = Vec4(0, 0, 0, 0)
            self.alphaOn = Vec4(0, 0, 0, 1)
            self.lerpFunc = LerpColorInterval

        self.irisTaskName = "irisTask"
        self.fadeTaskName = "fadeTask"
        self.letterboxTaskName = "letterboxTask"

    def __del__(self):
        if self.fadeModel:
            self.fadeModel.removeNode()
            self.fadeModel = None

    ##################################################
    # Fade
    ##################################################

    # We can set a custom model for the fade before using it for the first time
    def setFadeModel(self, model, scale=1.0):
        self.fadeModel = model
        # We have to change some default parameters for a custom fadeModel
        self.alphaOn = Vec4(1, 1, 1, 1)

        # Reload fade if its already been created
        if self.fade:
            self.fade.destroy()
            self.fade = None
            self.loadFade()

    def loadFade(self):
        if self.fade is None:
            # We create a DirectFrame for the fade polygon, instead of
            # simply loading the polygon model and using it directly,
            # so that it will also obscure mouse events for objects
            # positioned behind it.
            self.fade = DirectFrame(
                parent = hidden,
                guiId = 'fade',
                relief = None,
                image = self.fadeModel,
                image_scale = (4, 2, 2),
                state = DGG.NORMAL,
                )
            if not self.fadeModel:
                # No fade model was given, so we make this the fade model.
                self.fade["relief"] = DGG.FLAT
                self.fade["frameSize"] = (-2, 2, -1, 1)
                self.fade["frameColor"] = (0, 0, 0, 1)
                self.fade.setTransparency(TransparencyAttrib.MAlpha)
            self.fade.setBin('unsorted', 0)
            self.fade.setColor(0,0,0,0)

        self.fade.setScale(max(base.a2dRight, base.a2dTop))

    def getFadeInIval(self, t=0.5, finishIval=None, blendType='noBlend'):
        """
        Returns an interval without starting it.  This is particularly useful in
        cutscenes, so when the cutsceneIval is escaped out of we can finish the fade immediately
        """
        #self.noTransitions() masad: this creates a one frame pop, is it necessary?
        self.loadFade()

        transitionIval = Sequence(Func(self.fade.reparentTo, aspect2d, DGG.FADE_SORT_INDEX),
                                  Func(self.fade.showThrough),  # in case aspect2d is hidden for some reason
                                  self.lerpFunc(self.fade, t,
                                                self.alphaOff,
                                                # self.alphaOn,
                                                blendType=blendType
                                                ),
                                  Func(self.fade.detachNode),
                                  name = self.fadeTaskName,
                                  )
        if finishIval:
            transitionIval.append(finishIval)
        return transitionIval

    def getFadeOutIval(self, t=0.5, finishIval=None, blendType='noBlend'):
        """
        Create a sequence that lerps the color out, then
        parents the fade to hidden
        """
        self.noTransitions()
        self.loadFade()

        transitionIval = Sequence(Func(self.fade.reparentTo, aspect2d, DGG.FADE_SORT_INDEX),
                                  Func(self.fade.showThrough),  # in case aspect2d is hidden for some reason
                                  self.lerpFunc(self.fade, t,
                                                self.alphaOn,
                                                # self.alphaOff,
                                                blendType=blendType
                                                ),
                                  name = self.fadeTaskName,
                                  )
        if finishIval:
            transitionIval.append(finishIval)
        return transitionIval

    def fadeIn(self, t=0.5, finishIval=None, blendType='noBlend'):
        """
        Play a fade in transition over t seconds.
        Places a polygon on the aspect2d plane then lerps the color
        from black to transparent. When the color lerp is finished, it
        parents the fade polygon to hidden.
        """
        gsg = base.win.getGsg()
        if gsg:
            # If we're about to fade in from black, go ahead and
            # preload all the textures etc.
            base.graphicsEngine.renderFrame()
            render.prepareScene(gsg)
            render2d.prepareScene(gsg)

        if (t == 0):
            # Fade in immediately with no lerp
            #print "transitiosn: fadeIn 0.0"
            self.noTransitions()
            self.loadFade()
            self.fade.detachNode()
            fut = AsyncFuture()
            fut.setResult(None)
            return fut
        else:
            # Create a sequence that lerps the color out, then
            # parents the fade to hidden
            self.transitionIval = self.getFadeInIval(t, finishIval, blendType)
            self.transitionIval.append(Func(self.__finishTransition))
            self.__transitionFuture = AsyncFuture()
            self.transitionIval.start()
            return self.__transitionFuture

    def fadeOut(self, t=0.5, finishIval=None, blendType='noBlend'):
        """
        Play a fade out transition over t seconds.
        Places a polygon on the aspect2d plane then lerps the color
        from transparent to full black. When the color lerp is finished,
        it leaves the fade polygon covering the aspect2d plane until you
        fadeIn or call noFade.
        lerp
        """
        if (t == 0):
            # Fade out immediately with no lerp
            self.noTransitions()
            self.loadFade()

            self.fade.reparentTo(aspect2d, DGG.FADE_SORT_INDEX)
            self.fade.setColor(self.alphaOn)
        elif ConfigVariableBool('no-loading-screen', False):
            if finishIval:
                self.transitionIval = finishIval
                self.transitionIval.start()
        else:
            # Create a sequence that lerps the color out, then
            # parents the fade to hidden
            self.transitionIval = self.getFadeOutIval(t, finishIval, blendType)
            self.transitionIval.append(Func(self.__finishTransition))
            self.__transitionFuture = AsyncFuture()
            self.transitionIval.start()
            return self.__transitionFuture

        # Immediately done, so return a dummy future.
        fut = AsyncFuture()
        fut.setResult(None)
        return fut

    def fadeOutActive(self):
        return self.fade and self.fade.getColor()[3] > 0

    def fadeScreen(self, alpha=0.5):
        """
        Put a semitransparent screen over the camera plane
        to darken out the world. Useful for drawing attention to
        a dialog box for instance
        """
        #print "transitiosn: fadeScreen"
        self.noTransitions()
        self.loadFade()

        self.fade.reparentTo(aspect2d, DGG.FADE_SORT_INDEX)
        self.fade.setColor(self.alphaOn[0],
                           self.alphaOn[1],
                           self.alphaOn[2],
                           alpha)

    def fadeScreenColor(self, color):
        """
        Put a semitransparent screen over the camera plane
        to darken out the world. Useful for drawing attention to
        a dialog box for instance
        """
        #print "transitiosn: fadeScreenColor"
        self.noTransitions()
        self.loadFade()

        self.fade.reparentTo(aspect2d, DGG.FADE_SORT_INDEX)
        self.fade.setColor(color)

    def noFade(self):
        """
        Removes any current fade tasks and parents the fade polygon away
        """
        #print "transitiosn: noFade"
        if self.transitionIval:
            self.transitionIval.pause()
            self.transitionIval = None
        if self.__transitionFuture:
            self.__transitionFuture.cancel()
            self.__transitionFuture = None
        if self.fade:
            # Make sure to reset the color, since fadeOutActive() is looking at it
            self.fade.setColor(self.alphaOff)
            self.fade.detachNode()

    def setFadeColor(self, r, g, b):
        self.alphaOn.set(r, g, b, 1)
        self.alphaOff.set(r, g, b, 0)


    ##################################################
    # Iris
    ##################################################

    def loadIris(self):
        if self.iris == None:
            self.iris = loader.loadModel(self.IrisModelName)
            self.iris.setPos(0, 0, 0)

    def irisIn(self, t=0.5, finishIval=None, blendType = 'noBlend'):
        """
        Play an iris in transition over t seconds.
        Places a polygon on the aspect2d plane then lerps the scale
        of the iris polygon up so it looks like we iris in. When the
        scale lerp is finished, it parents the iris polygon to hidden.
        """
        self.noTransitions()
        self.loadIris()
        if (t == 0):
            self.iris.detachNode()
            fut = AsyncFuture()
            fut.setResult(None)
            return fut
        else:
            self.iris.reparentTo(aspect2d, DGG.FADE_SORT_INDEX)

            scale = 0.18 * max(base.a2dRight, base.a2dTop)
            self.transitionIval = Sequence(LerpScaleInterval(self.iris, t,
                                                   scale = scale,
                                                   startScale = 0.01,
                                                   blendType=blendType),
                                 Func(self.iris.detachNode),
                                 Func(self.__finishTransition),
                                 name = self.irisTaskName,
                                 )
            self.__transitionFuture = AsyncFuture()
            if finishIval:
                self.transitionIval.append(finishIval)
            self.transitionIval.start()
            return self.__transitionFuture

    def irisOut(self, t=0.5, finishIval=None, blendType='noBlend'):
        """
        Play an iris out transition over t seconds.
        Places a polygon on the aspect2d plane then lerps the scale
        of the iris down so it looks like we iris out. When the scale
        lerp is finished, it leaves the iris polygon covering the
        aspect2d plane until you irisIn or call noIris.
        """
        self.noTransitions()
        self.loadIris()
        self.loadFade()  # we need this to cover up the hole.
        if (t == 0):
            self.iris.detachNode()
            self.fadeOut(0)
            fut = AsyncFuture()
            fut.setResult(None)
            return fut
        else:
            self.iris.reparentTo(aspect2d, DGG.FADE_SORT_INDEX)

            scale = 0.18 * max(base.a2dRight, base.a2dTop)
            self.transitionIval = Sequence(LerpScaleInterval(self.iris, t,
                                                   scale = 0.01,
                                                   startScale = scale,
                                                   blendType=blendType),
                                 Func(self.iris.detachNode),
                                 # Use the fade to cover up the hole that the iris would leave
                                 Func(self.fadeOut, 0),
                                 Func(self.__finishTransition),
                                 name = self.irisTaskName,
                                 )
            self.__transitionFuture = AsyncFuture()
            if finishIval:
                self.transitionIval.append(finishIval)
            self.transitionIval.start()
            return self.__transitionFuture

    def noIris(self):
        """
        Removes any current iris tasks and parents the iris polygon away
        """
        if self.transitionIval:
            self.transitionIval.pause()
            self.transitionIval = None
        if self.iris != None:
            self.iris.detachNode()
        # Actually we need to remove the fade too,
        # because the iris effect uses it.
        self.noFade()

    def noTransitions(self):
        """
        This call should immediately remove any and all transitions running
        """
        self.noFade()
        self.noIris()
        # Letterbox is not really a transition, it is a screen overlay
        # self.noLetterbox()

    def __finishTransition(self):
        if self.__transitionFuture:
            self.__transitionFuture.setResult(None)
            self.__transitionFuture = None

    ##################################################
    # Letterbox
    ##################################################

    def loadLetterbox(self):
        if not self.letterbox:
            # We create a DirectFrame for the fade polygon, instead of
            # simply loading the polygon model and using it directly,
            # so that it will also obscure mouse events for objects
            # positioned behind it.
            self.letterbox = NodePath("letterbox")
            # Allow fade in and out of the bars
            self.letterbox.setTransparency(1)

            # Allow DirectLabels to be parented to the letterbox sensibly
            self.letterbox.setBin('unsorted', 0)

            # Allow a custom look to the letterbox graphic.

            # TODO: This model isn't available everywhere.  We should
            # pass it in as a parameter.
            button = loader.loadModel('models/gui/toplevel_gui',
                                      okMissing = True)

            barImage = None
            if button:
                barImage = button.find('**/generic_button')

            self.letterboxTop = DirectFrame(
                parent = self.letterbox,
                guiId = 'letterboxTop',
                relief = DGG.FLAT,
                state = DGG.NORMAL,
                frameColor = (0, 0, 0, 1),
                borderWidth = (0, 0),
                frameSize = (-1, 1, 0, 0.2),
                pos = (0, 0, 1.0),
                image = barImage,
                image_scale = (2.25,1,.5),
                image_pos = (0,0,.1),
                image_color = (0.3,0.3,0.3,1),
                sortOrder = 0,
                )
            self.letterboxBottom = DirectFrame(
                parent = self.letterbox,
                guiId = 'letterboxBottom',
                relief = DGG.FLAT,
                state = DGG.NORMAL,
                frameColor = (0, 0, 0, 1),
                borderWidth = (0, 0),
                frameSize = (-1, 1, 0, 0.2),
                pos = (0, 0, -1.2),
                image = barImage,
                image_scale = (2.25,1,.5),
                image_pos = (0,0,.1),
                image_color = (0.3,0.3,0.3,1),
                sortOrder = 0,
                )

            # masad: always place these at the bottom of render
            self.letterboxTop.setBin('sorted',0)
            self.letterboxBottom.setBin('sorted',0)
            self.letterbox.reparentTo(render2d, -1)
            self.letterboxOff(0)

    def noLetterbox(self):
        """
        Removes any current letterbox tasks and parents the letterbox polygon away
        """
        if self.letterboxIval:
            self.letterboxIval.pause()
            self.letterboxIval = None
        if self.__letterboxFuture:
            self.__letterboxFuture.cancel()
            self.__letterboxFuture = None
        if self.letterbox:
            self.letterbox.stash()

    def __finishLetterbox(self):
        if self.__letterboxFuture:
            self.__letterboxFuture.setResult(None)
            self.__letterboxFuture = None

    def letterboxOn(self, t=0.25, finishIval=None, blendType='noBlend'):
        """
        Move black bars in over t seconds.
        """
        self.noLetterbox()
        self.loadLetterbox()
        self.letterbox.unstash()
        if (t == 0):
            self.letterboxBottom.setPos(0, 0, -1)
            self.letterboxTop.setPos(0, 0, 0.8)
            fut = AsyncFuture()
            fut.setResult(None)
            return fut
        else:
            self.__letterboxFuture = AsyncFuture()
            self.letterboxIval = Sequence(Parallel(
                LerpPosInterval(self.letterboxBottom,
                                t,
                                pos = Vec3(0, 0, -1),
                                #startPos = Vec3(0, 0, -1.2),
                                blendType=blendType
                                ),
                LerpPosInterval(self.letterboxTop,
                                t,
                                pos = Vec3(0, 0, 0.8),
                                # startPos = Vec3(0, 0, 1),
                                blendType=blendType
                                ),
                ),
                                          Func(self.__finishLetterbox),
                                          name = self.letterboxTaskName,
                                          )
            if finishIval:
                self.letterboxIval.append(finishIval)
            self.letterboxIval.start()
            return self.__letterboxFuture

    def letterboxOff(self, t=0.25, finishIval=None, blendType='noBlend'):
        """
        Move black bars away over t seconds.
        """
        self.noLetterbox()
        self.loadLetterbox()
        self.letterbox.unstash()
        if (t == 0):
            self.letterbox.stash()
            fut = AsyncFuture()
            fut.setResult(None)
            return fut
        else:
            self.__letterboxFuture = AsyncFuture()
            self.letterboxIval = Sequence(Parallel(
                LerpPosInterval(self.letterboxBottom,
                                t,
                                pos = Vec3(0, 0, -1.2),
                                # startPos = Vec3(0, 0, -1),
                                blendType=blendType
                                ),
                LerpPosInterval(self.letterboxTop,
                                t,
                                pos = Vec3(0, 0, 1),
                                # startPos = Vec3(0, 0, 0.8),
                                blendType=blendType
                                ),
                ),
                                          Func(self.letterbox.stash),
                                          Func(self.__finishLetterbox),
                                          Func(messenger.send,'letterboxOff'),
                                          name = self.letterboxTaskName,
                                          )
            if finishIval:
                self.letterboxIval.append(finishIval)
            self.letterboxIval.start()
            return self.__letterboxFuture
示例#8
0
class GuiButton2:
    def __init__(self, hugpos, offset, aspect, plane, name):
        self.enabled = True
        self.name = name
        
        self.frame = DirectFrame(   relief = DGG.FLAT
                                  , frameColor = (0, 0, 0, 0)
                                  , scale = 1
                                  , frameSize = (-0.3, 0.3, -0.3, 0.3) ) #32/600=0.05333
        self.frame.setScale(0.0533)
        
        self.imageObject = OnscreenImage(image = name+".png", pos = (0, 0, 0))
        self.imageObject.setTransparency(TransparencyAttrib.MAlpha)
        self.imageObject.setAlphaScale(1) 
        self.imageObject.reparentTo(self.frame)
        
        self.hugpos = hugpos
        self.offset = offset
        self.redraw(aspect)

    def redraw(self, aspect, flag="wide"):
        if self.hugpos == "top":
            p = base.a2dTopLeft.getPos()#@UndefinedVariable
            p.setX(p.getX() + self.offset.getX() + 0.05)
            p.setZ(p.getZ() + self.offset.getZ() - GUI_TOP_OFFSET - 0.05)
        elif self.hugpos == "bottom":
            p = base.a2dBottomLeft.getPos()#@UndefinedVariable
            p.setX(p.getX() + self.offset.getX() + 0.05)
            p.setZ(p.getZ() + self.offset.getZ() + GUI_BOTTOM_OFFSET - 0.05)
        elif self.hugpos == "right":
            p = base.a2dBottomRight.getPos()#@UndefinedVariable
            p.setX(p.getX() + self.offset.getX() + 0.05)
            p.setZ(p.getZ() + self.offset.getZ() + GUI_BOTTOM_OFFSET - 0.05)
        self.frame.setPos(p)
        if flag == "wide":
            posx, posy = self.frame.getTightBounds()
            self.pos_min_x = posx.getX() / aspect
            self.pos_min_y = posx.getZ()
            self.pos_max_x = posy.getX() / aspect
            self.pos_max_y = posy.getZ()
        elif flag == "tall":
            posx, posy = self.frame.getTightBounds()
            self.pos_min_x = posx.getX()
            self.pos_min_y = posx.getZ() / aspect
            self.pos_max_x = posy.getX()
            self.pos_max_y = posy.getZ() / aspect
            
    def turnOn(self):
        self.imageObject.setImage(self.name+"_on.png")#@UndefinedVariable
        self.imageObject.setTransparency(TransparencyAttrib.MAlpha)
        
    def turnOff(self):
        self.imageObject.setImage(self.name+".png")#@UndefinedVariable
        self.imageObject.setTransparency(TransparencyAttrib.MAlpha)    
            
    def enable(self):
        self.imageObject.setImage(self.name+".png")#@UndefinedVariable
        self.imageObject.setTransparency(TransparencyAttrib.MAlpha)
        self.enabled = True
        
    def disable(self):
        self.imageObject.setImage("empty.png")#@UndefinedVariable
        self.imageObject.setTransparency(TransparencyAttrib.MAlpha)
        self.enabled = False
            
    def removeNode(self):
        self.frame.removeNode()   
        
    def setAbility(self, ability):
        self.name = ability
        self.imageObject.setImage(self.name+".png")
        self.imageObject.setTransparency(TransparencyAttrib.MAlpha)
        self.imageObject.setAlphaScale(1) 
示例#9
0
class RewardPanel(DirectFrame):
    notify = directNotify.newCategory('RewardPanel')

    def __init__(self, panelData):
        dialogBox = loader.loadModel('phase_3/models/gui/dialog_box_gui.bam')
        DirectFrame.__init__(self,
                             relief=None,
                             geom=dialogBox,
                             geom_color=CIGlobals.DialogColor,
                             geom_scale=(1.75, 1, 0.75 * 1.1),
                             geom_pos=Point3(0, 0, -0.05),
                             pos=(0, 0, 0.661))
        self.initialiseoptions(RewardPanel)
        self.setScale(0.8)

        # The data for the reward panel inside of a RPToonData object.
        self.panelData = panelData

        # Top wood panel saying Reward Panel
        gagShopNodes = loader.loadModel(
            'phase_4/models/gui/gag_shop_purchase_gui.bam')
        # Original pos: (-0.02, 0, 0.3) scale = (1.55, 1, 1)
        self.titlePanel = OnscreenImage(
            parent=self,
            image=gagShopNodes.find('**/Goofys_Sign'),
            pos=(0, 0, 0.3),
            hpr=(1, 0, 0),
            scale=(1.3, 1, 0.9))

        self.avatarNamePanel = DirectFrame(parent=self.titlePanel,
                                           pos=(0, 0.005, 0))
        self.avatarText = OnscreenText(parent=self.avatarNamePanel,
                                       text='',
                                       font=CIGlobals.getMickeyFont(),
                                       fg=(0.698, 0.13, 0.13, 1),
                                       mayChange=1,
                                       scale=(0.1, 0.13, 0.1))

        self.panelContentsTitle = OnscreenText(parent=self,
                                               text=GagPanelName,
                                               font=CIGlobals.getMickeyFont(),
                                               pos=(0, 0.24, 0),
                                               fg=(0.3725, 0.619, 0.627, 1),
                                               mayChange=1)

        self.playerInfo = DirectFrame(parent=self,
                                      relief=None,
                                      pos=(-0.5, 0, 0))
        self.playerInfo.setBin('gui-popup', 0)

        self.bonusText = OnscreenText(parent=self.playerInfo,
                                      text='2X Cog Office Bonus!',
                                      font=CIGlobals.getToonFont(),
                                      pos=(0, 0.15, 0),
                                      scale=(0.055, 0.055, 0.055),
                                      align=TextNode.ACenter)
        self.bonusText.hide()

        ##################################################################################
        # GUI Elements relating to the Favorite Gag/Gag Popup Used for showing Gag Unlock#
        ##################################################################################
        self.favoriteGagText = OnscreenText(parent=self.playerInfo,
                                            text=FavoriteGag,
                                            font=CIGlobals.getMickeyFont(),
                                            pos=FavoriteGagTitlePos,
                                            fg=(1, 0.2, 0.2, 1),
                                            sort=0)

        glow = loader.loadModel('phase_4/models/minigames/particleGlow.bam')
        self.favoriteGagGlow = OnscreenImage(parent=self.playerInfo,
                                             image=glow,
                                             pos=FavoriteGagPos,
                                             color=GagGlowColor,
                                             scale=(0.8, 0.8, 0.8))
        self.favoriteGagGlow.setBin('gui-popup', 10)
        # particleGlow.bam uses a material since it's normally part of render, not render2d.
        # Since render2d is still fixed-function, we have to explicitly enable shader generation
        # to correctly display the glow in render2d.
        self.favoriteGagGlow.setShaderAuto()

        invIcons = loader.loadModel('phase_3.5/models/gui/inventory_icons.bam')
        gag = invIcons.find(
            GagGlobals.InventoryIconByName.get(GagGlobals.Foghorn))
        self.favoriteGag = OnscreenImage(parent=self.playerInfo,
                                         image=gag,
                                         pos=FavoriteGagPos,
                                         scale=(1.65, 1.65, 1.65))
        self.favoriteGag.setBin('gui-popup', 20)

        self.favoriteGagName = OnscreenText(parent=self.playerInfo,
                                            text=GagGlobals.Foghorn,
                                            font=CIGlobals.getToonFont(),
                                            pos=FavoriteGagNamePos,
                                            mayChange=1)

        ################################################################################
        # GUI elements showing gag experience on the right-side of the gag exp panel   #
        ################################################################################

        self.gagExpFrame = DirectFrame(parent=self,
                                       relief=None,
                                       pos=(0.085, 0, 0.15))
        self.trackLabels = []
        self.trackIncLabels = []
        self.trackBars = []
        self.trackBarsOffset = 0

        for i in range(len(GagGlobals.TrackNameById.values())):
            track = GagGlobals.TrackNameById.values()[i]
            color = GagGlobals.TrackColorByName.get(track)
            label = DirectLabel(parent=self.gagExpFrame,
                                relief=None,
                                text=track.upper(),
                                text_scale=0.05,
                                text_align=TextNode.ARight,
                                pos=(0.13, 0, -0.09 * i),
                                text_pos=(0, -0.02))
            incrementLabel = DirectLabel(parent=self.gagExpFrame,
                                         relief=None,
                                         text='',
                                         text_scale=0.05,
                                         text_align=TextNode.ALeft,
                                         pos=(0.65, 0, -0.09 * i),
                                         text_pos=(0, -0.02))
            progressBar = DirectWaitBar(
                parent=self.gagExpFrame,
                relief=DGG.SUNKEN,
                frameSize=(-1, 1, -0.15, 0.15),
                borderWidth=(0.02, 0.02),
                scale=0.25,
                frameColor=(color[0] * 0.7, color[1] * 0.7, color[2] * 0.7, 1),
                barColor=(color[0], color[1], color[2], 1),
                text='0/0',
                text_scale=0.18,
                text_fg=(0, 0, 0, 1),
                text_align=TextNode.ACenter,
                text_pos=(0, -0.05),
                pos=(0.4, 0, -0.09 * i))
            self.trackLabels.append(label)
            self.trackIncLabels.append(incrementLabel)
            self.trackBars.append(progressBar)

        ################################################################################
        # GUI elements showing progress updates on quests                              #
        ################################################################################

        self.questFrame = DirectFrame(parent=self, relief=None)
        self.questPosters = []

        self.congratsLeft = OnscreenText(parent=self.playerInfo,
                                         pos=(-0.1, 0.125, -0.1),
                                         text='',
                                         scale=0.06,
                                         align=TextNode.ARight)
        self.congratsLeft.setR(-30)
        self.congratsRight = OnscreenText(parent=self.playerInfo,
                                          pos=(0.1, 0.125, 0.1),
                                          text='',
                                          scale=0.06,
                                          align=TextNode.ALeft)
        self.congratsRight.setR(30)

        glow.removeNode()
        invIcons.removeNode()
        gagShopNodes.removeNode()
        dialogBox.removeNode()

    def __getAvatarTextScale(self):
        totalWidth = self.avatarText.node().getWidth()
        panelWidth = 9.2
        defaultTextScale = 1.0

        scale = min(defaultTextScale,
                    defaultTextScale / (totalWidth / panelWidth))
        return (scale, scale, scale)

    def enterOff(self):
        pass

    def exitOff(self):
        pass

    def setPanelData(self, panelData):
        self.panelData = panelData
        self.avatarText['text'] = self.panelData.avatarName
        self.avatarNamePanel.setScale(self.__getAvatarTextScale())

        # Let's set the data for our gag experience here.
        for i in range(len(self.trackLabels)):
            track = self.panelData.getTrackByName(
                GagGlobals.TrackNameById.values()[i])
            bar = self.trackBars[i]
            bar['text'] = '%d/%d' % (track.exp, track.maxExp)

            # When the maximum experience of a track isn't 0, we know it isn't unlocked.
            if track.maxExp == -1:
                bar.hide()

            self.trackIncLabels[i]['text'] = ''
            self.trackIncLabels[i].show()

    def __chooseRewardShot(self, av):
        shotChoices = [(0, 8, av.getHeight() * 0.66, 179, 15, 0),
                       (5.2, 5.45, av.getHeight() * 0.66, 131.5, 3.6, 0)]
        shot = random.choice(shotChoices)
        return shot

    def getQuestsProgressInterval(self):
        avatar = self.panelData.avatar
        intervals = []

        def toggleFavoriteGagItems(visible):
            for item in [
                    self.favoriteGag, self.favoriteGagGlow,
                    self.favoriteGagText, self.favoriteGagName
            ]:
                if not visible:
                    item.hide()
                else:
                    item.show()

        def setupQuestPosters():
            questManager = avatar.questManager
            numQuests = len(questManager.quests.values())

            yPos = 0.47

            displayData = {
                1: [[Point3(0.0, 0.0, yPos)], 0.88],
                2: [[Point3(-0.42, 0.0, yPos),
                     Point3(0.45, 0.0, yPos)], 0.88],
                3: [[
                    Point3(-0.57, 0.0, yPos),
                    Point3(0.0, 0.0, yPos),
                    Point3(0.57, 0.0, yPos)
                ], 0.70],
                4: [[
                    Point3(-0.32, 0.0, 0.62),
                    Point3(-0.32, 0.0, 0.30),
                    Point3(0.32, 0.0, 0.62),
                    Point3(0.32, 0.0, 0.30)
                ], 0.52]
            }

            # A full frame is a frame showing two quests at once.
            howManyFullFrames = math.ceil(numQuests / 2.0)
            howManyRemainderFrames = (numQuests - howManyFullFrames)

            for i, quest in enumerate(questManager.quests.values()):
                poster = QuestGlobals.generatePoster(quest,
                                                     parent=self.questFrame)
                poster.setScale(displayData.get(numQuests)[1])
                poster.setPos(displayData.get(numQuests)[0][i])
                poster.show()
                self.questPosters.append(poster)

        intervals.append(Func(self.gagExpFrame.hide))
        intervals.append(Func(self.playerInfo.show))
        intervals.append(Func(self.panelContentsTitle.setText,
                              QuestsPanelName))
        intervals.append(Func(toggleFavoriteGagItems, False))
        intervals.append(Func(setupQuestPosters))
        #intervals.append(Func(self.playerInfo.initialiseoptions, DirectFrame))

        return intervals

    def getGagExperienceInterval(self):
        avatar = self.panelData.avatar
        intervals = []

        shot = self.__chooseRewardShot(avatar)

        intervals.append(Func(base.camera.reparentTo, avatar))
        intervals.append(Func(base.camera.setPosHpr, *shot))
        intervals.append(Func(self.congratsLeft.hide))
        intervals.append(Func(self.congratsRight.hide))
        intervals.append(Func(self.panelContentsTitle.setText, GagPanelName))
        intervals.append(Func(self.setFavoriteGag, self.panelData.favoriteGag))
        intervals.append(Func(self.gagExpFrame.show))
        intervals.append(Func(self.playerInfo.show))
        intervals.append(Wait(1.0))

        for i in range(len(self.trackLabels)):
            track = self.panelData.getTrackByName(
                GagGlobals.TrackNameById.values()[i])
            intervals.extend(self.getTrackIntervalList(track, i))

        return intervals

    def getNextExpValue(self, newValue, track):
        if newValue < track.maxExp or track.maxExp == 0:
            return track.maxExp
        else:
            levels = GagGlobals.TrackExperienceAmounts[track.name]
            index = levels.index(track.maxExp)

            if index + 1 < len(levels):
                return levels[index + 1]
            return -1

    def incrementExp(self, trackIndex, track, newValue):
        bar = self.trackBars[trackIndex]
        nextExp = GagGlobals.getMaxExperienceValue(newValue, track.name)
        oldValue = bar['value']
        color = GagGlobals.TrackColorByName.get(track.name)

        bar['text'] = '%d/%d' % (newValue, nextExp)
        bar['range'] = nextExp if not nextExp == -1 else newValue
        bar['value'] = newValue
        bar['barColor'] = (color[0], color[1], color[2], 1)

    def resetBarColor(self, trackIndex):
        color = GagGlobals.TrackColorByName.get(
            GagGlobals.TrackNameById.values()[trackIndex])
        self.trackBars[trackIndex]['barColor'] = (color[0] * 0.8,
                                                  color[1] * 0.8,
                                                  color[2] * 0.8, 1)

    def showTrackIncLabel(self, trackIndex, track, increment):
        label = self.trackIncLabels[trackIndex]

        # Only show increments when that track is unlocked.
        if track.exp != -1:
            label['text'] = '+%d' % increment
        label.show()

    def getTrackIntervalList(self, track, trackIndex):
        tickDelay = 1.0 / 60
        intervalList = []

        intervalList.append(
            Func(self.showTrackIncLabel, trackIndex, track, track.increment))

        barTime = 2.0 if track.exp > 0 else 0.25
        numTicks = int(math.ceil(barTime / tickDelay))
        for i in range(numTicks):
            t = (i + 1) / float(numTicks)
            newValue = int(track.exp + t * track.increment + 0.5)
            intervalList.append(
                Func(self.incrementExp, trackIndex, track, newValue))
            intervalList.append(Wait(tickDelay))

        intervalList.append(Func(self.resetBarColor, trackIndex))
        intervalList.append(Wait(0.2))

        if track.maxExp > 0 and (track.maxExp != GagGlobals.MaxedTrackExperiences.get(track.name) \
                    and (track.exp + track.increment) >= track.maxExp):
            gagIndex = GagGlobals.TrackExperienceAmounts.get(track.name).index(
                track.maxExp) + 1
            newGag = GagGlobals.TrackGagNamesByTrackName.get(
                track.name)[gagIndex]
            intervalList.append(
                self.getShowGagUnlockedInterval(track.name, newGag))

        return intervalList

    def getShowGagUnlockedInterval(self, track, gagName):
        seq = Sequence(
            Func(self.gagExpFrame.hide),
            Func(self.panelContentsTitle.setText, 'Gag Unlocked!'),
            Func(self.playerInfo.show), Func(self.setFavoriteGag, gagName),
            Func(self.favoriteGagName.setY, -0.35),
            Func(self.favoriteGagText.setY, 0.105),
            Func(self.favoriteGagText.setText, 'New %s Gag' % track),
            Func(self.bonusText.hide), Func(self.playerInfo.setPos, 0, 0, 0),
            Func(self.playerInfo.initialiseoptions, DirectFrame))
        seq.append(self.getCongratsInterval())
        seq.append(Wait(1.0))
        seq.append(self.getHideGagUnlockedInterval())
        seq.append(Func(self.gagExpFrame.show))
        seq.append(Wait(0.5))
        return seq

    def getHideGagUnlockedInterval(self):
        def correctPositioning(guiElement, pos):
            guiElement['pos'] = pos

        seq = Sequence(
            Func(self.panelContentsTitle.setText, GagPanelName),
            Func(self.setFavoriteGag, self.panelData.favoriteGag),
            Func(self.playerInfo.setX, -0.5),
            Func(correctPositioning, self.favoriteGagName, FavoriteGagNamePos),
            Func(self.favoriteGagText.setText, FavoriteGag),
            Func(correctPositioning, self.favoriteGagText,
                 FavoriteGagTitlePos), Func(self.congratsLeft.hide),
            Func(self.congratsRight.hide))

        return seq

    def __getRandomCongratsPair(self):
        msgs = list(NewGagCongratsMessages)

        msg = msgs[random.randint(0, len(msgs) - 1)]
        msgs.remove(msg)

        return (msg, msgs[random.randint(0, len(msgs) - 1)])

    def getCongratsInterval(self):
        msgs = self.__getRandomCongratsPair()
        self.congratsLeft['text'] = msgs[0]
        self.congratsRight['text'] = msgs[1]

        sfx = loader.loadSfx('phase_3/audio/sfx/GUI_balloon_popup.ogg')
        sfx.setLoop(False)
        sfx.setVolume(1.0)

        def makeSequence(text):
            seq = Sequence(Wait(1.0), Func(text.show))
            seq.append(Func(sfx.play))
            seq.append(
                CIGlobals.makePulseEffectInterval(text, 1.0, 0.01, 1.05, 0.5,
                                                  0.25))
            seq.append(Func(sfx.stop))
            return seq

        return Sequence(makeSequence(self.congratsLeft),
                        makeSequence(self.congratsRight))

    def setFavoriteGag(self, gagName):
        invIcons = loader.loadModel('phase_3.5/models/gui/inventory_icons.bam')
        gag = invIcons.find(GagGlobals.InventoryIconByName.get(gagName))
        self.favoriteGagName.setText(gagName)
        self.favoriteGag['image'] = gag
        invIcons.removeNode()

    def destroy(self):
        if self.titlePanel:
            self.titlePanel.destroy()
        if self.avatarText:
            self.avatarText.destroy()
        if self.avatarNamePanel:
            self.avatarNamePanel.destroy()
        if self.panelContentsTitle:
            self.panelContentsTitle.destroy()
        if self.favoriteGag:
            self.favoriteGag.destroy()
        if self.favoriteGagGlow:
            self.favoriteGagGlow.destroy()
        if self.favoriteGagName:
            self.favoriteGagName.destroy()
        if self.playerInfo:
            self.playerInfo.destroy()
        if self.trackLabels:
            for label in self.trackLabels:
                label.destroy()
        if self.trackIncLabels:
            for label in self.trackIncLabels:
                label.destroy()
        if self.trackBars:
            for bar in self.trackBars:
                bar.destroy()
        if self.congratsLeft:
            self.congratsLeft.destroy()
        if self.congratsRight:
            self.congratsRight.destroy()
        if self.gagExpFrame:
            self.gagExpFrame.destroy()
        if self.panelData:
            self.panelData = None
        del self.titlePanel
        del self.avatarText
        del self.avatarNamePanel
        del self.panelContentsTitle
        del self.favoriteGag
        del self.favoriteGagGlow
        del self.favoriteGagName
        del self.playerInfo
        del self.trackLabels
        del self.trackIncLabels
        del self.trackBars
        del self.gagExpFrame
        del self.congratsLeft
        del self.congratsRight
        del self.panelData
        DirectFrame.destroy(self)
 def setScale(self, *args, **kwargs):
     DirectFrame.setScale(self, *args, **kwargs)
     self.resetArcBall()
示例#11
0
class DoubleFrameQuestPoster(QuestPoster):
    notify = directNotify.newCategory('DoubleFrameQuestPoster')

    def __init__(self, quest, parent=aspect2d, **kw):
        QuestPoster.__init__(self, quest, parent, **kw)

        # This text is in between the two frames and it usually says
        # either "from:" or "to:"
        self.fromToMiddleText = DirectLabel(
            parent=self,
            relief=None,
            text=QuestGlobals.FROM,
            text_font=CIGlobals.getToonFont(),
            text_scale=QuestGlobals.QPauxText,
            text_fg=QuestGlobals.TEXT_COLOR,
            text_align=TextNode.ACenter,
            textMayChange=1,
            pos=QuestGlobals.DEFAULT_MIDDLE_POS)
        self.fromToMiddleText.hide()

        ##########################################################################
        #           THE FOLLOWING ELEMENTS BELOW ARE GROUPED TOGETHER            #
        ##########################################################################
        # We need this again for certain geometry.
        circleGui = loader.loadModel(
            'phase_4/models/gui/CircleIconBackgroundGui.bam')

        # The background frame where the objective image is displayed.
        # This is the colored background frame.
        self.goalFrame = DirectFrame(
            parent=self,
            relief=None,
            image=circleGui.find('**/circle_display_interior'),
            image_scale=0.18,
            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_RIGHT_PICTURE_POS)
        self.goalFrame.hide()

        # The icon that goes on top of the goal frame.
        self.goalIcon = DirectFrame(parent=self.goalFrame,
                                    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.goalIcon.setColorOff(-1)
        self.goalIcon.hide()

        self.goalOutline = DirectLabel(
            parent=self.goalFrame,
            relief=None,
            image=circleGui.find('**/circle_display_outline'),
            image_scale=0.18)
        self.goalOutline.hide()

        # Information displayed about the additional goal.
        self.goalInfo = 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_INFO2_POS))
        self.goalInfo.hide()

        circleGui.removeNode()
        return

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

    def setup(self):
        QuestPoster.setup(self)
        objective = self.viewObjective

        # Let's reset our icon.
        self.goalIcon.setScale(1, 1, 1)
        self.goalIcon.setPos(0, 0, 0)
        self.goalIcon.setHpr(0, 0, 0)

        if objective.__class__ in DoubleFrameObjectives:
            if objective.__class__ == DeliverItemObjective:
                # It's kind of hard to return delivered stuff to somebody.
                # We're not handling complete objectives from here.
                self.handleDeliverItemObjective()
            elif objective.__class__ == RecoverItemObjective:
                self.handleRecoverItemObjective()

            if len(self.quest.accessibleObjectives) > 1:
                self.prevObjArrow.setPos(QuestGlobals.SECONDARY_LEFT_ARROW_POS)
                self.nextObjArrow.setPos(
                    QuestGlobals.SECONDARY_RIGHT_ARROW_POS)

            self.goalFrame.show()
            self.goalIcon.show()
            self.goalOutline.show()
            self.goalInfo.show()
            self.fromToMiddleText.show()
        else:
            self.goalFrame.hide()
            self.goalIcon.hide()
            self.goalOutline.hide()
            self.goalInfo.hide()
            self.fromToMiddleText.hide()
        self.goalIcon.initialiseoptions(DirectFrame)
        self.initialiseoptions(DoubleFrameQuestPoster)

    def handleRecoverItemObjective(self):
        objective = self.viewObjective

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

        # Let's make the left icon use the item icon we chose.
        self.handleSimpleIcon(objective.itemIcon, 0.12, self.auxIcon)

        # Handle the objective information.
        infoText = '%d %s' % (objective.goal,
                              CIGlobals.makePlural(objective.itemName))
        if objective.goal == 1:
            infoText = objective.itemName

        # Update the positions and information regarding the left side.
        self.auxFrame.setPos(QuestGlobals.RECOVER_LEFT_PICTURE_POS)
        self.auxFrame['image_color'] = QuestGlobals.GREEN
        self.objectiveInfo.setPos(QuestGlobals.RECOVER_INFO_POS)
        self.objectiveInfo['text'] = infoText
        self.fromToMiddleText[
            'text'] = QuestGlobals.FROM if not objective.isComplete(
            ) else QuestGlobals.TO

        if not objective.isComplete():
            self.handleCogObjective(self.goalIcon,
                                    auxText=QuestGlobals.RECOVER,
                                    frameColor=QuestGlobals.GREEN)

            # Let's set the progress bar text
            pgBarText = '%d of %d %s' % (objective.progress, objective.goal,
                                         CIGlobals.makePastTense(
                                             QuestGlobals.RECOVER))
            self.progressBar['text'] = pgBarText
            self.progressBar['value'] = objective.progress & pow(2, 16) - 1
        else:
            self.handleNPCObjective(self.goalIcon,
                                    auxText=QuestGlobals.RETURN,
                                    frameColor=QuestGlobals.BLUE)

    def handleDeliverItemObjective(self):
        objective = self.viewObjective

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

        # Correct the scaling if we need to and set the icon.
        scale = 0.12 if objective.itemIcon.getName() == 'package' else 0.85
        self.handleSimpleIcon(objective.itemIcon, scale, self.auxIcon)
        self.auxFrame.setPos(QuestGlobals.RECOVER_LEFT_PICTURE_POS)
        self.auxFrame['image_color'] = QuestGlobals.RED

        infoText = '%d %s' % (objective.goal,
                              CIGlobals.makePlural(objective.itemName))
        if objective.goal == 1:
            infoText = objective.itemName
        self.objectiveInfo.setPos(QuestGlobals.RECOVER_INFO_POS)
        self.objectiveInfo['text'] = infoText
        self.fromToMiddleText['text'] = QuestGlobals.TO

        # Let's set the progress bar text
        pgBarText = '%d of %d %s' % (objective.progress, objective.goal,
                                     CIGlobals.makePastTense(
                                         QuestGlobals.DELIVER))
        self.progressBar['text'] = pgBarText
        self.progressBar['value'] = objective.progress & pow(2, 16) - 1

        self.handleNPCObjective(self.goalIcon,
                                auxText=QuestGlobals.DELIVER,
                                frameColor=QuestGlobals.RED)

    def destroy(self):
        self.fromToMiddleText.destroy()
        self.goalFrame.destroy()
        self.goalIcon.destroy()
        self.goalOutline.destroy()
        self.goalInfo.destroy()
        del self.fromToMiddleText
        del self.goalFrame
        del self.goalIcon
        del self.goalOutline
        del self.goalInfo
        QuestPoster.destroy(self)