Esempio n. 1
0
    def addWinIndicator(self, avId, card):
        if not avId or card is None:
            return

        trackId, cardTier = card

        index = len(self.roundResults[avId][trackId])
        if avId != base.localAvatar.doId:
            index += 5

        image = self.trackIcons[trackId].copyTo(NodePath())
        np = CARD_MODELS[cardTier].copyTo(NodePath())
        image.reparentTo(np)
        image.setScale(ICON_SCALE[trackId])
        image.setR(-90)
        card = DirectButton(parent=aspect2d,
                            relief=None,
                            geom=np,
                            geom_hpr=UNREVEALED_HPR,
                            geom_scale=0.3,
                            state=DGG.DISABLED,
                            command=self.doNothing,
                            scale=(0.2, 1, 0.2))

        pos = WON_CARD_POSITIONS[trackId][index]
        card.setPos(pos)
        self.winIndicators.append(card)
Esempio n. 2
0
def load(args):
    """Sets up the GUI for the main menu.
    Arguments:
        This takes no arguments.
    """

    global backFrame
    global menuFrame
    global pauseText
    global backButton

    font_digital = loader.loadFont('digital.egg')

    backFrame = DirectFrame()
    backFrame['frameColor'] = (0, 0, 0, .5)
    backFrame['frameSize'] = (2, -2, 2, -2)
    backFrame.setPos(0, 0, 0)

    menuFrame = DirectFrame()
    menuFrame.reparentTo(backFrame)
    menuFrame['frameColor'] = (1, 1, 1, .5)
    menuFrame['frameSize'] = (.5, -.5, .5, -.5)
    menuFrame.setPos(0, 0, 0)

    pauseText = OnscreenText()
    pauseText['text'] = ('PAUSED')
    pauseText['scale'] = (.1)
    pauseText['font'] = (font_digital)
    pauseText['fg'] = (1, 1, 1, 1)
    pauseText.setPos(0, .9)

    backButton = DirectButton()
    backButton.reparentTo(menuFrame)
    backButton['text'] = ('Back')
    backButton['text_scale'] = (.1)
    backButton['text_pos'] = (0, -0.03)
    backButton['frameVisibleScale'] = (2, 0.5, 0)
    backButton['frameColor'] = (1, 1, 1, 0)
    backButton['command'] = (messenger.send)
    backButton['extraArgs'] = ("switch_gui", [gui.menu.pause_options, gui.menu.pause])
    backButton.setPos(0, 0, 0)
Esempio n. 3
0
    def startGame(self, avIds):
        for avId in avIds:
            self.roundResults[avId] = {}

        # create the dummy cards
        for i in range(0, NUM_CARDS):
            np = CARD_MODELS[0].copyTo(NodePath())
            card = DirectButton(parent=aspect2d,
                                relief=None,
                                geom=np,
                                geom_hpr=UNREVEALED_HPR,
                                geom_scale=0.6,
                                state=DGG.DISABLED,
                                text_pos=(-.6, 0.62),
                                text_scale=0.6,
                                command=self.doNothing,
                                scale=0.15)
            card.setPos(CARD_POSITIONS[NUM_CARDS + i])
            self.dummyDeck[i] = card

        self.fsm.request('Playing')
Esempio n. 4
0
    def receiveCards(self, cards):
        # only new cards should be passed through this function
        emptySlotIndexes = [
            i for i, x in enumerate(self.localDeck) if x is None
        ]

        for i, info in enumerate(cards):
            trackId, cardTier = info

            np = CARD_MODELS[cardTier].copyTo(NodePath())
            image = self.trackIcons[trackId].copyTo(np)
            image.setScale(ICON_SCALE[trackId])
            image.setR(-90)
            if trackId == TRACK_ICE:
                image.setPos(0.7, 0, 0.2)

            card = DirectButton(parent=aspect2d,
                                relief=None,
                                geom=np,
                                geom_hpr=UNREVEALED_HPR,
                                geom_scale=0.6,
                                command=self.selectedCard,
                                extraArgs=[info],
                                text=str(cardTier),
                                text_pos=(-.59, 0.62),
                                text_font=FONT,
                                text_scale=0.6,
                                scale=0.15)
            slotIndex = emptySlotIndexes[i]
            card.setPos(CARD_POSITIONS[slotIndex])
            self.localDeck[slotIndex] = info

            self.cardButtons[info] = card

        if self.otherCard:
            self.otherCard.show()
class ScreenshotViewer:
    notify = DirectNotifyGlobal.directNotify.newCategory('ScreenshotViewer')

    def __init__(self):
        self.resetImages()
        imageFrame = PDialog(parent = aspect2dp, pos = (0, 0, 0.10000000000000001), image_scale = (1.3 * 4 / 3.0, 1, 1.3), fadeScreen = 0.84999999999999998, scale = 1.1000000000000001)
        imageFrame.hide()
        imX = 0.84999999999999998
        imY = imX * 3 / 4.0
        self.imageObj = OnscreenImage(parent = imageFrame, image = self.screens[0], scale = (imX, 1, imY), pos = (0, 0, -0.025000000000000001))
        self.imageLabel = DirectLabel(parent = imageFrame, relief = None, state = DGG.DISABLED, pos = (0, 0, -0.75), textMayChange = 1, text_fg = (0.59999999999999998, 0.59999999999999998, 0.59999999999999998, 1), text_scale = 0.040000000000000001)
        self.imageLabel.hide()
        topGui = loader.loadModel('models/gui/toplevel_gui')
        arrow = topGui.find('**/generic_arrow')
        buttons = loader.loadModel('models/gui/lookout_gui')
        closeButton = (buttons.find('**/lookout_close_window'), buttons.find('**/lookout_close_window_down'), buttons.find('**/lookout_close_window_over'))
        xs = 1.2
        self.nextButton = DirectButton(parent = imageFrame, relief = None, command = self.next, pos = (0.69999999999999996, 0, 0), image = arrow, image_scale = (-xs, xs, xs), sortOrder = -5)
        self.prevButton = DirectButton(parent = imageFrame, relief = None, command = self.prev, pos = (-0.69999999999999996, 0, 0), image = arrow, image_scale = xs, sortOrder = -5)
        self.closeButton = DirectButton(parent = imageFrame, relief = None, command = self.close, pos = (0.78000000000000003, 0, -0.5), image = closeButton, image_scale = 0.29999999999999999, text = PLocalizer.lClose, text_fg = PiratesGuiGlobals.TextFG1, text_scale = 0.050000000000000003, text_pos = (0, -0.10000000000000001), sortOrder = -5)
        self.showIval = Sequence(Func(imageFrame.show), Wait(1), Parallel(LerpPosInterval(self.closeButton, 0.20000000000000001, Vec3(0.78000000000000003, 0, -0.80000000000000004), Vec3(0.78000000000000003, 0, -0.5)), LerpPosInterval(self.nextButton, 0.20000000000000001, Vec3(1, 0, 0), Vec3(0.69999999999999996, 0, 0)), LerpPosInterval(self.prevButton, 0.20000000000000001, Vec3(-1, 0, 0), Vec3(-0.69999999999999996, 0, 0))), Func(self.imageLabel.show))
        self.imageFrame = imageFrame
        base.transitions.fadeScreen(0.84999999999999998)


    def destroy(self):
        self.imageFrame.destroy()


    def resetImages(self):
        filenames = os.listdir(os.curdir + '/' + PLocalizer.ScreenshotDir)
        self.screens = _[1]
        self.currentIndex = 0


    def resetButtons(self):
        self.closeButton.setPos(Vec3(0.78000000000000003, 0, -0.5))
        self.nextButton.setPos(Vec3(0.69999999999999996, 0, 0))
        self.prevButton.setPos(Vec3(-0.69999999999999996, 0, 0))


    def showImage(self, index):
        if index >= 0 and index < len(self.screens):
            self.imageFrame.show()
            self.imageObj.setImage(self.screens[index])
            pandafile = Filename(str(ExecutionEnvironment.getCwd()))
            winfile = pandafile.toOsSpecific()
            self.imageLabel['text'] = '%s:\n%s\n%s\n[%s/%s]' % (PLocalizer.ScreenshotLocation, winfile, self.screens[index], index + 1, len(self.screens))
            self.imageLabel['text_fg'] = (0.59999999999999998, 0.59999999999999998, 0.59999999999999998, 1)
            self.imageLabel['text_scale'] = 0.040000000000000001

        if len(self.screens) == 1:
            self.prevButton['state'] = DGG.DISABLED
            self.nextButton['state'] = DGG.DISABLED
        else:
            self.prevButton['state'] = DGG.NORMAL
            self.nextButton['state'] = DGG.NORMAL


    def next(self):
        self.currentIndex = (self.currentIndex + 1) % len(self.screens)

        try:
            self.showImage(self.currentIndex)
        except:
            self.notify.error('Bad image')



    def prev(self):
        self.currentIndex = (self.currentIndex - 1) % len(self.screens)

        try:
            self.showImage(self.currentIndex)
        except:
            self.notify.error('Bad Image')



    def close(self):
        self.imageFrame.hide()


    def show(self):
        self.resetImages()
        self.resetButtons()
        self.showImage(0)
        self.showIval.start()


    def toggleShow(self):
        if self.imageFrame.isHidden():
            self.show()
        else:
            self.close()
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.')
Esempio n. 7
0
class ScreenshotViewer:
    notify = DirectNotifyGlobal.directNotify.newCategory('ScreenshotViewer')

    def __init__(self):
        self.resetImages()
        imageFrame = PDialog(parent=aspect2dp,
                             pos=(0, 0, 0.10000000000000001),
                             image_scale=(1.3 * 4 / 3.0, 1, 1.3),
                             fadeScreen=0.84999999999999998,
                             scale=1.1000000000000001)
        imageFrame.hide()
        imX = 0.84999999999999998
        imY = imX * 3 / 4.0
        self.imageObj = OnscreenImage(parent=imageFrame,
                                      image=self.screens[0],
                                      scale=(imX, 1, imY),
                                      pos=(0, 0, -0.025000000000000001))
        self.imageLabel = DirectLabel(parent=imageFrame,
                                      relief=None,
                                      state=DGG.DISABLED,
                                      pos=(0, 0, -0.75),
                                      textMayChange=1,
                                      text_fg=(0.59999999999999998,
                                               0.59999999999999998,
                                               0.59999999999999998, 1),
                                      text_scale=0.040000000000000001)
        self.imageLabel.hide()
        topGui = loader.loadModel('models/gui/toplevel_gui')
        arrow = topGui.find('**/generic_arrow')
        buttons = loader.loadModel('models/gui/lookout_gui')
        closeButton = (buttons.find('**/lookout_close_window'),
                       buttons.find('**/lookout_close_window_down'),
                       buttons.find('**/lookout_close_window_over'))
        xs = 1.2
        self.nextButton = DirectButton(parent=imageFrame,
                                       relief=None,
                                       command=self.next,
                                       pos=(0.69999999999999996, 0, 0),
                                       image=arrow,
                                       image_scale=(-xs, xs, xs),
                                       sortOrder=-5)
        self.prevButton = DirectButton(parent=imageFrame,
                                       relief=None,
                                       command=self.prev,
                                       pos=(-0.69999999999999996, 0, 0),
                                       image=arrow,
                                       image_scale=xs,
                                       sortOrder=-5)
        self.closeButton = DirectButton(parent=imageFrame,
                                        relief=None,
                                        command=self.close,
                                        pos=(0.78000000000000003, 0, -0.5),
                                        image=closeButton,
                                        image_scale=0.29999999999999999,
                                        text=PLocalizer.lClose,
                                        text_fg=PiratesGuiGlobals.TextFG1,
                                        text_scale=0.050000000000000003,
                                        text_pos=(0, -0.10000000000000001),
                                        sortOrder=-5)
        self.showIval = Sequence(
            Func(imageFrame.show), Wait(1),
            Parallel(
                LerpPosInterval(
                    self.closeButton, 0.20000000000000001,
                    Vec3(0.78000000000000003, 0, -0.80000000000000004),
                    Vec3(0.78000000000000003, 0, -0.5)),
                LerpPosInterval(self.nextButton, 0.20000000000000001,
                                Vec3(1, 0, 0), Vec3(0.69999999999999996, 0,
                                                    0)),
                LerpPosInterval(self.prevButton, 0.20000000000000001,
                                Vec3(-1, 0, 0), Vec3(-0.69999999999999996, 0,
                                                     0))),
            Func(self.imageLabel.show))
        self.imageFrame = imageFrame
        base.transitions.fadeScreen(0.84999999999999998)

    def destroy(self):
        self.imageFrame.destroy()

    def resetImages(self):
        filenames = os.listdir(os.curdir + '/' + PLocalizer.ScreenshotDir)
        continue
        self.screens = _[1]
        self.currentIndex = 0

    def resetButtons(self):
        self.closeButton.setPos(Vec3(0.78000000000000003, 0, -0.5))
        self.nextButton.setPos(Vec3(0.69999999999999996, 0, 0))
        self.prevButton.setPos(Vec3(-0.69999999999999996, 0, 0))

    def showImage(self, index):
        if index >= 0 and index < len(self.screens):
            self.imageFrame.show()
            self.imageObj.setImage(self.screens[index])
            pandafile = Filename(str(ExecutionEnvironment.getCwd()))
            winfile = pandafile.toOsSpecific()
            self.imageLabel['text'] = '%s:\n%s\n%s\n[%s/%s]' % (
                PLocalizer.ScreenshotLocation, winfile, self.screens[index],
                index + 1, len(self.screens))
            self.imageLabel['text_fg'] = (0.59999999999999998,
                                          0.59999999999999998,
                                          0.59999999999999998, 1)
            self.imageLabel['text_scale'] = 0.040000000000000001

        if len(self.screens) == 1:
            self.prevButton['state'] = DGG.DISABLED
            self.nextButton['state'] = DGG.DISABLED
        else:
            self.prevButton['state'] = DGG.NORMAL
            self.nextButton['state'] = DGG.NORMAL

    def next(self):
        self.currentIndex = (self.currentIndex + 1) % len(self.screens)

        try:
            self.showImage(self.currentIndex)
        except:
            self.notify.error('Bad image')

    def prev(self):
        self.currentIndex = (self.currentIndex - 1) % len(self.screens)

        try:
            self.showImage(self.currentIndex)
        except:
            self.notify.error('Bad Image')

    def close(self):
        self.imageFrame.hide()

    def show(self):
        self.resetImages()
        self.resetButtons()
        self.showImage(0)
        self.showIval.start()

    def toggleShow(self):
        if self.imageFrame.isHidden():
            self.show()
        else:
            self.close()
class DirectFolderBrowser(DirectObject):
    def __init__(self, command, fileBrowser=False, defaultPath="~", defaultFilename="unnamed.txt", fileExtensions=[], tooltip=None):
        """
        A simple file and folder browser

        command: The command that will be called on closing the browser
        fileBrowser: If set to True the browser will show files, otherwise it will only show folders
        defaultPath: The initial path the browser will be set to show
        defaultFilename: The filename that will be set by default, only usefull if fileBrowser is True
        fileExtensions: A list of extensions. Only files with those extensions will be shown. Only usefull if fileBrowser is True
        tooltip: An instance of the Tooltip class to display tooltips for certain parts of the editor
        """
        self.tt = tooltip
        self.command = command
        self.showFiles = fileBrowser
        self.fileExtensions = fileExtensions
        self.showHidden = False

        self.currentPath = os.path.expanduser(defaultPath)
        if not os.path.exists(self.currentPath):
            self.currentPath = os.path.expanduser("~")
        self.previousPath = self.currentPath

        self.screenWidthPx = base.getSize()[0]
        self.screenWidthPxHalf = self.screenWidthPx * 0.5
        self.screenHeightPx = base.getSize()[1]
        self.screenHeightPxHalf = self.screenHeightPx * 0.5

        self.mainFrame = DirectFrame(
            relief=1,
            frameSize=(-self.screenWidthPxHalf,self.screenWidthPxHalf,-self.screenHeightPxHalf,self.screenHeightPxHalf),
            frameColor=(1, 1, 1, 1),
            pos=LPoint3f(base.getSize()[0]/2, 0, -base.getSize()[1]/2),
            parent=base.pixel2d,
            state=DGG.NORMAL,
        )

        self.pathRightMargin = 153
        self.pathEntryWidth = self.screenWidthPx - self.pathRightMargin

        self.pathEntry = DirectEntry(
            parent=self.mainFrame,
            relief=DGG.SUNKEN,
            frameColor=(1, 1, 1, 1),
            pad=(0.2, 0.2),
            pos=LPoint3f(-self.screenWidthPxHalf + 15, 0, self.screenHeightPxHalf - 25),
            scale=12,
            width=self.pathEntryWidth/12,
            overflow=True,
            command=self.entryAccept,
            initialText=self.currentPath,
            focusInCommand=base.messenger.send,
            focusInExtraArgs=["unregisterKeyboardEvents"],
            focusOutCommand=base.messenger.send,
            focusOutExtraArgs=["reregisterKeyboardEvents"],
        )
        x = self.pathEntryWidth/2-28
        self.btnReload = DirectButton(
            parent=self.mainFrame,
            relief=1,
            frameColor = (
                (0.8, 0.8, 0.8, 1), # Normal
                (0.9, 0.9, 1, 1), # Click
                (0.8, 0.8, 1, 1), # Hover
                (0.5, 0.5, 0.5, 1)), # Disabled
            frameSize=(-14, 14, -10, 18),
            pos=LPoint3f(x, 0, self.screenHeightPxHalf - 25),
            command=self.folderReload,
            image="icons/Reload.png",
            image_scale=14,
            image_pos=(0,0,4),
        )
        self.btnReload.setTransparency(TransparencyAttrib.M_multisample)
        if self.tt is not None:
            self.btnReload.bind(DGG.ENTER, self.tt.show, ["Reload Folder"])
            self.btnReload.bind(DGG.EXIT, self.tt.hide)
        x += 28
        self.btnFolderUp = DirectButton(
            parent=self.mainFrame,
            relief=1,
            frameColor = (
                (0.8, 0.8, 0.8, 1), # Normal
                (0.9, 0.9, 1, 1), # Click
                (0.8, 0.8, 1, 1), # Hover
                (0.5, 0.5, 0.5, 1)), # Disabled
            frameSize=(-14, 14, -10, 18),
            pos=LPoint3f(x, 0, self.screenHeightPxHalf - 25),
            command=self.folderUp,
            image="icons/FolderUp.png",
            image_scale=14,
            image_pos=(0,0,4),
        )
        self.btnFolderUp.setTransparency(TransparencyAttrib.M_multisample)
        if self.tt is not None:
            self.btnFolderUp.bind(DGG.ENTER, self.tt.show, ["Move up one level"])
            self.btnFolderUp.bind(DGG.EXIT, self.tt.hide)
        x += 28
        self.btnFolderNew = DirectButton(
            parent=self.mainFrame,
            relief=1,
            frameColor = (
                (0.8, 0.8, 0.8, 1), # Normal
                (0.9, 0.9, 1, 1), # Click
                (0.8, 0.8, 1, 1), # Hover
                (0.5, 0.5, 0.5, 1)), # Disabled
            frameSize=(-14, 14, -10, 18),
            pos=LPoint3f(x, 0, self.screenHeightPxHalf - 25),
            command=self.folderNew,
            image="icons/FolderNew.png",
            image_scale=14,
            image_pos=(0,0,4),
        )
        self.btnFolderNew.setTransparency(TransparencyAttrib.M_multisample)
        if self.tt is not None:
            self.btnFolderNew.bind(DGG.ENTER, self.tt.show, ["Create new folder"])
            self.btnFolderNew.bind(DGG.EXIT, self.tt.hide)
        x += 28
        self.btnFolderShowHidden = DirectButton(
            parent=self.mainFrame,
            relief=1,
            frameColor = (
                (0.8, 0.8, 0.8, 1), # Normal
                (0.9, 0.9, 1, 1), # Click
                (0.8, 0.8, 1, 1), # Hover
                (0.5, 0.5, 0.5, 1)), # Disabled
            frameSize=(-14, 14, -10, 18),
            pos=LPoint3f(x, 0, self.screenHeightPxHalf - 25),
            command=self.folderShowHidden,
            image="icons/FolderShowHidden.png",
            image_scale=14,
            image_pos=(0,0,4),
        )
        self.btnFolderShowHidden.setTransparency(TransparencyAttrib.M_multisample)
        if self.tt is not None:
            self.btnFolderShowHidden.bind(DGG.ENTER, self.tt.show, ["Show/Hide hidden files and folders"])
            self.btnFolderShowHidden.bind(DGG.EXIT, self.tt.hide)

        color = (
            (0.8, 0.8, 0.8, 1), # Normal
            (0.9, 0.9, 1, 1), # Click
            (0.8, 0.8, 1, 1), # Hover
            (0.5, 0.5, 0.5, 1)) # Disabled
        self.container = DirectScrolledFrame(
            relief=DGG.RIDGE,
            borderWidth=(2, 2),
            frameColor=(1, 1, 1, 1),
            frameSize=(-self.screenWidthPxHalf+10, self.screenWidthPxHalf-10, -self.screenHeightPxHalf+50, self.screenHeightPxHalf-50),
            canvasSize=(-self.screenWidthPxHalf+31, self.screenWidthPxHalf-10, -self.screenHeightPxHalf+50, self.screenHeightPxHalf-50),
            pos=LPoint3f(0, 0, 0),
            parent=self.mainFrame,
            scrollBarWidth=20,
            verticalScroll_scrollSize=20,
            verticalScroll_thumb_relief=DGG.FLAT,
            verticalScroll_incButton_relief=DGG.FLAT,
            verticalScroll_decButton_relief=DGG.FLAT,
            verticalScroll_thumb_frameColor=color,
            verticalScroll_incButton_frameColor=color,
            verticalScroll_decButton_frameColor=color,
            horizontalScroll_thumb_relief=DGG.FLAT,
            horizontalScroll_incButton_relief=DGG.FLAT,
            horizontalScroll_decButton_relief=DGG.FLAT,
            horizontalScroll_thumb_frameColor=color,
            horizontalScroll_incButton_frameColor=color,
            horizontalScroll_decButton_frameColor=color,
            state=DGG.NORMAL,
        )
        self.container.bind(DGG.MWDOWN, self.scroll, [0.01])
        self.container.bind(DGG.MWUP, self.scroll, [-0.01])

        self.btnOk = DirectButton(
            parent=self.mainFrame,
            relief=1,
            frameColor = (
                (0.8, 0.8, 0.8, 1), # Normal
                (0.9, 0.9, 1, 1), # Click
                (0.8, 0.8, 1, 1), # Hover
                (0.5, 0.5, 0.5, 1)), # Disabled
            frameSize=(-45, 45, -6, 14),
            pos=LPoint3f(self.screenWidthPxHalf-160, 0, -self.screenHeightPxHalf+25),
            text = "ok",
            text_scale=12,
            command=command,
            extraArgs=[1],
        )
        self.btnCancel = DirectButton(
            parent=self.mainFrame,
            relief=1,
            frameColor = (
                (0.8, 0.8, 0.8, 1), # Normal
                (0.9, 0.9, 1, 1), # Click
                (0.8, 0.8, 1, 1), # Hover
                (0.5, 0.5, 0.5, 1)), # Disabled
            frameSize=(-45, 45, -6, 14),
            pos=LPoint3f(self.screenWidthPxHalf-55, 0, -self.screenHeightPxHalf+25),
            text = "Cancel",
            text_scale=12,
            command=command,
            extraArgs=[0]
        )

        if self.showFiles:
            self.txtFileName = DirectEntry(
                parent=self.mainFrame,
                relief=DGG.SUNKEN,
                frameColor=(1, 1, 1, 1),
                pad=(0.2, 0.2),
                pos=LPoint3f(-self.screenWidthPxHalf+25, 0, -self.screenHeightPxHalf+25),
                scale=12,
                width=200/12,
                overflow=True,
                command=self.filenameAccept,
                initialText=defaultFilename,
                focusInCommand=base.messenger.send,
                focusInExtraArgs=["unregisterKeyboardEvents"],
                focusOutCommand=base.messenger.send,
                focusOutExtraArgs=["reregisterKeyboardEvents"],
            )

        self.newFolderFrame = DirectFrame(
            parent=self.mainFrame,
            relief=1,
            frameSize=(-self.screenWidthPxHalf+10,self.screenWidthPxHalf-10,-20,20),
            pos=LPoint3f(0, 0, self.screenHeightPxHalf-55),
            frameColor=(0.5,0.5,0.5,1),
        )
        self.txtNewFolderName = DirectLabel(
            parent=self.newFolderFrame,
            text="New Folder Name",
            text_scale=12,
            frameColor=(0,0,0,0),
            text_align=TextNode.ALeft,
            pos=(-self.screenWidthPxHalf+15, 0, -3),
        )
        self.folderName = DirectEntry(
            parent=self.newFolderFrame,
            relief=DGG.SUNKEN,
            frameColor=(1, 1, 1, 1),
            pad=(0.2, 0.2),
            pos=LPoint3f(-self.screenWidthPxHalf+25 + self.txtNewFolderName.getWidth(), 0, -4),
            scale=12,
            width=((self.screenWidthPxHalf-25)*2-self.txtNewFolderName.getWidth() - 100)/12,
            overflow=True,
            command=self.entryAccept,
            initialText="New Folder",
            focusInCommand=base.messenger.send,
            focusInExtraArgs=["unregisterKeyboardEvents"],
            focusOutCommand=base.messenger.send,
            focusOutExtraArgs=["reregisterKeyboardEvents"],
        )
        self.btnCreate = DirectButton(
            parent=self.newFolderFrame,
            relief=1,
            frameColor = (
                (0.8, 0.8, 0.8, 1), # Normal
                (0.9, 0.9, 1, 1), # Click
                (0.8, 0.8, 1, 1), # Hover
                (0.5, 0.5, 0.5, 1)), # Disabled
            frameSize=(-45, 45, -6, 14),
            pos=LPoint3f(self.screenWidthPxHalf-65, 0, -4),
            text = "Create",
            text_scale=12,
            command=self.folderCreate,
            extraArgs=[0]
        )
        self.newFolderFrame.hide()

        self.folderReload()

        # handle window resizing
        self.prevScreenSize = base.getSize()
        self.accept("window-event", self.windowEventHandler)

    def show(self):
        self.mainFrame.show()
        self.accept("window-event", self.windowEventHandler)

    def hide(self):
        self.ignore("window-event")
        self.mainFrame.hide()

    def destroy(self):
        self.ignore("window-event")
        self.mainFrame.destroy()

    def scroll(self, scrollStep, event):
        self.container.verticalScroll.scrollStep(scrollStep)

    def get(self):
        if self.showFiles:
            return os.path.join(self.currentPath, self.txtFileName.get(True))
        return self.currentPath

    def filenameAccept(self, filename):
        self.command(1)

    def entryAccept(self, path):
        self.folderReload()

    def folderReload(self):

        for element in self.container.getCanvas().getChildren():
            element.removeNode()

        path = self.pathEntry.get(True)
        path = os.path.expanduser(path)
        path = os.path.expandvars(path)
        if not os.path.exists(path): return
        self.currentPath = path

        try:
            content = os.scandir(path)
        except PermissionError:
            base.messenger.send("showWarning", ["Access denied!"])
            self.pathEntry.set(self.previousPath)
            self.currentPath = self.previousPath
            self.folderReload()
            return

        # start position for the folders and files
        xPos = -self.screenWidthPxHalf + 20 + 50 - 110
        zPos = self.screenHeightPxHalf-60-40

        dirList = []
        fileList = []
        unkList = []

        for entry in content:
            if entry.name.startswith(".") and not self.showHidden:
                continue
            if entry.is_dir():
                dirList.append(entry)
            elif entry.is_file() and self.showFiles:
                if len(self.fileExtensions) > 0:
                    if os.path.splitext(entry.name)[1] in self.fileExtensions:
                        fileList.append(entry)
                else:
                    fileList.append(entry)
            elif self.showFiles:
                unkList.append(entry)

        def moveNext(entry):
            nonlocal xPos
            nonlocal zPos
            if entry.is_dir() or self.showFiles:
                if xPos + 110 > self.screenWidthPxHalf - 45:
                    # move to the next line if we hit the right border (incl. scrollbar size)
                    xPos = -self.screenWidthPxHalf + 20 + 50
                    zPos -= 110
                else:
                    # move right the next position
                    xPos += 110

        def getKey(item):
            return item.name.lower()

        for entry in sorted(dirList, key=getKey):
            moveNext(entry)
            self.__createFolder(entry, xPos, zPos)
        for entry in sorted(fileList, key=getKey):
            moveNext(entry)
            self.__createFile(entry.name, xPos, zPos)
        for entry in sorted(unkList, key=getKey):
            moveNext(entry)
            self.__createUnknown(entry.name, xPos, zPos)

        # recalculate the canvas size
        self.container["canvasSize"] = (-self.screenWidthPxHalf+31, self.screenWidthPxHalf-15, zPos-90, self.screenHeightPxHalf-50)
        self.container.setCanvasSize()

    def folderUp(self):
        self.previousPath = self.currentPath
        self.currentPath = os.path.normpath(os.path.join(self.currentPath, ".."))
        self.pathEntry.set(self.currentPath)
        self.folderReload()

    def folderMoveIn(self, path):
        path = os.path.expanduser(path)
        path = os.path.expandvars(path)
        self.previousPath = self.currentPath
        self.currentPath = path
        self.pathEntry.set(path)
        self.folderReload()
        self.container.verticalScroll["value"] = 0

    def folderNew(self):
        if self.newFolderFrame.isHidden():
            self.newFolderFrame.show()
        else:
            self.newFolderFrame.hide()

    def folderShowHidden(self):
        self.showHidden = not self.showHidden
        self.folderReload()

    def folderCreate(self, path=""):
        try:
            os.makedirs(os.path.join(self.currentPath, self.folderName.get(True)))
        except:
            base.messenger.send("showWarning", ["Can't create folder"])
        self.newFolderFrame.hide()
        self.folderReload()

    def __createFolder(self, entry, xPos, zPos):
        name = entry.name
        if len(entry.name) > 10:
            name = ""
            for i in range(max(math.ceil(len(entry.name)/10), 4)):
                name += entry.name[i*10:i*10+10]+"\n"
            name = name[:-1]
            if math.ceil(len(entry.name)/10) > 4:
                name += "..."
        btn = DirectButton(
            parent=self.container.getCanvas(),
            image="icons/Folder.png",
            image_scale=35,
            relief=1,
            frameColor = (
                (0.9, 0.9, 0.9, 0), # Normal
                (0.95, 0.95, 1, 1), # Click
                (0.9, 0.9, 1, 1), # Hover
                (0.5, 0.5, 0.5, 1)), # Disabled
            frameSize=(-40, 40, -40, 40),
            pos=LPoint3f(xPos, 0, zPos),
            text = name,
            text_scale=12,
            text_pos=(0,-40),
            command=self.folderMoveIn,
            extraArgs=[entry.path]
        )
        btn.bind(DGG.MWDOWN, self.scroll, [0.01])
        btn.bind(DGG.MWUP, self.scroll, [-0.01])
        btn.setTransparency(TransparencyAttrib.M_multisample)

    def __createFile(self, filename, xPos, zPos):
        name = filename
        if len(filename) > 10:
            name = ""
            for i in range(min(math.ceil(len(filename)/10), 4)):
                name += filename[i*10:i*10+10]+"\n"
            name = name[:-1]
            if math.ceil(len(filename)/10) > 4:
                name += "..."
        btn = DirectButton(
            parent=self.container.getCanvas(),
            image="icons/File.png",
            image_scale=35,
            relief=1,
            frameColor = (
                (0.9, 0.9, 0.9, 0), # Normal
                (0.95, 0.95, 1, 1), # Click
                (0.9, 0.9, 1, 1), # Hover
                (0.5, 0.5, 0.5, 1)), # Disabled
            frameSize=(-40, 40, -40, 40),
            pos=LPoint3f(xPos, 0, zPos),
            text = name,
            text_scale=12,
            text_pos=(0,-40),
            command=self.txtFileName.set,
            extraArgs=[filename]
        )
        btn.bind(DGG.MWDOWN, self.scroll, [0.01])
        btn.bind(DGG.MWUP, self.scroll, [-0.01])
        btn.setTransparency(TransparencyAttrib.M_multisample)

    def __createUnknown(self, filename, xPos, zPos):
        name = filename
        if len(filename) > 10:
            name = ""
            for i in range(math.ceil(len(filename)/10)):
                name += filename[i*10:i*10+10]+"\n"
            name = name[:-1]
        lbl = DirectLabel(
            parent=self.container.getCanvas(),
            image="icons/File.png",
            image_scale=35,
            image_color=(0.9,0.5,0.5,1),
            relief=1,
            frameColor = (0.7, 0.7, 0.7, 0),
            frameSize=(-40, 40, -40, 40),
            pos=LPoint3f(xPos, 0, zPos),
            text = name,
            text_scale=12,
            text_pos=(0,-40),
        )
        lbl.bind(DGG.MWDOWN, self.scroll, [0.01])
        lbl.bind(DGG.MWUP, self.scroll, [-0.01])
        lbl.setTransparency(TransparencyAttrib.M_multisample)


    def windowEventHandler(self, window=None):
        if window != base.win:
            # This event isn't about our window.
            return


        if window is not None: # window is none if panda3d is not started
            if self.prevScreenSize == base.getSize():
                return
            self.prevScreenSize = base.getSize()
            self.screenWidthPx = base.getSize()[0]
            self.screenWidthPxHalf = self.screenWidthPx * 0.5
            self.screenHeightPx = base.getSize()[1]
            self.screenHeightPxHalf = self.screenHeightPx * 0.5

            # reposition and resize all gui elements
            self.mainFrame.setPos(self.screenWidthPx/2, 0, -self.screenHeightPx/2)
            self.mainFrame["frameSize"] = (-self.screenWidthPxHalf,self.screenWidthPxHalf,-self.screenHeightPxHalf,self.screenHeightPxHalf)

            self.pathEntryWidth = self.screenWidthPx - self.pathRightMargin
            self.pathEntry.setPos(LPoint3f(-self.screenWidthPxHalf + 15, 0, self.screenHeightPxHalf - 25))
            self.pathEntry["width"] = self.pathEntryWidth/12
            self.pathEntry.resetFrameSize()

            # reposition top right icons
            x = self.pathEntryWidth/2-28
            self.btnReload.setPos(LPoint3f(x, 0, self.screenHeightPxHalf - 25))
            x += 28
            self.btnFolderUp.setPos(pos=LPoint3f(x, 0, self.screenHeightPxHalf - 25))
            x += 28
            self.btnFolderNew.setPos(pos=LPoint3f(x, 0, self.screenHeightPxHalf - 25))
            x += 28
            self.btnFolderShowHidden.setPos(pos=LPoint3f(x, 0, self.screenHeightPxHalf - 25))

            # resize the browsing area
            self.container["frameSize"] = (-self.screenWidthPxHalf+10, self.screenWidthPxHalf-10, -self.screenHeightPxHalf+50, self.screenHeightPxHalf-50)
            # Note: canvas size of the container will be reset in the
            #       folder Reload call at the end of this function
            self.btnOk.setPos(LPoint3f(self.screenWidthPxHalf-160, 0, -self.screenHeightPxHalf+25))
            self.btnCancel.setPos(LPoint3f(self.screenWidthPxHalf-55, 0, -self.screenHeightPxHalf+25))
            if self.showFiles:
                self.txtFileName.setPos(LPoint3f(-self.screenWidthPxHalf+25, 0, -self.screenHeightPxHalf+25))
            self.newFolderFrame.setPos(LPoint3f(0, 0, self.screenHeightPxHalf-55))
            self.newFolderFrame["frameSize"] = (-self.screenWidthPxHalf+10,self.screenWidthPxHalf-10,-20,20)
            self.txtNewFolderName.setPos(-self.screenWidthPxHalf+15, 0, -3)
            self.folderName.setPos(LPoint3f(-self.screenWidthPxHalf+25 + self.txtNewFolderName.getWidth(), 0, -4))
            self.folderName["width"]=((self.screenWidthPxHalf-25)*2-self.txtNewFolderName.getWidth() - 100)/12
            self.btnCreate.setPos(LPoint3f(self.screenWidthPxHalf-65, 0, -4))

            self.folderReload()
Esempio n. 9
0
def load(args):
    """Sets up the GUI for the in game pause menu.
    Arguments:
        args[0] -- The function for the 'resume' button.
        args[1] -- The function for the 'settings' button.
        args[2] -- The function for the 'exit' button.
    """
    # GUI should do what they are told, they should get data sent to them, not request it.

    global pauseText
    global backFrame
    global menuFrame
    global resumeButton

    font_digital = loader.loadFont("digital.egg")

    backFrame = DirectFrame()
    backFrame["frameSize"] = (2, -2, 2, -2)
    backFrame.setPos(0, 0, 0)

    backFrame["frameColor"] = (0, 0, 0, 0.5)
    menuFrame = DirectFrame()
    menuFrame.reparentTo(backFrame)
    menuFrame["frameColor"] = (1, 1, 1, 0.5)
    menuFrame["frameSize"] = (0.5, -0.5, 0.5, -0.5)
    menuFrame.setPos(0, 0, 0)

    buttonClickSound = loader.loadSfx("sound/buttonClick.wav")
    buttonRollSound = loader.loadSfx("sound/buttonRoll.wav")

    resumeButton = DirectButton()
    resumeButton.reparentTo(menuFrame)
    resumeButton["text"] = "Resume"
    resumeButton["text_scale"] = 0.1
    resumeButton["text_pos"] = (0, -0.03)
    resumeButton["frameVisibleScale"] = (2, 0.5, 0)
    resumeButton["frameColor"] = (1, 1, 1, 0)
    resumeButton["command"] = resume
    resumeButton["rolloverSound"] = buttonRollSound
    resumeButton["clickSound"] = buttonClickSound
    resumeButton.setPos(0, 0, 0.4)

    settingsButton = DirectButton()
    settingsButton.reparentTo(menuFrame)
    settingsButton["text"] = "Settings"
    settingsButton["text_scale"] = 0.1
    settingsButton["text_pos"] = (0, -0.03)
    settingsButton["frameVisibleScale"] = (2, 0.5, 0)
    settingsButton["frameColor"] = (1, 1, 1, 0)
    settingsButton["rolloverSound"] = buttonRollSound
    settingsButton["clickSound"] = buttonClickSound
    settingsButton["command"] = messenger.send  # Command to run
    settingsButton["extraArgs"] = ("switch_gui", [gui.menu.pause, gui.menu.pause_options])  # Args to send
    settingsButton.setPos(0, 0, 0.2)

    exitButton = DirectButton()
    exitButton.reparentTo(menuFrame)
    exitButton["text"] = "Exit"
    exitButton["text_scale"] = 0.1
    exitButton["text_pos"] = (0, -0.03)
    exitButton["frameVisibleScale"] = (2, 0.5, 0)
    exitButton["frameColor"] = (1, 1, 1, 0)
    exitButton["rolloverSound"] = buttonRollSound
    exitButton["clickSound"] = buttonClickSound
    exitButton["command"] = exit
    exitButton.setPos(0, 0, 0)

    pauseText = OnscreenText()
    pauseText["text"] = "PAUSED"
    pauseText["scale"] = 0.1
    pauseText["font"] = font_digital
    pauseText["fg"] = (1, 1, 1, 1)
    pauseText.setPos(0, 0.9)
Esempio n. 10
0
class Character(DirectButton):
    def __init__(self, rootParent, pos, charFolder, charEvt):

        self.btn = DirectButton(
            image="characters/{}/idle_l1.png".format(charFolder),
            frameColor=(0, 0, 0, 0),
            frameSize=(-0.5, 0.5, -1, 1),
            scale=0.15,
            pos=pos,
            parent=rootParent,
            command=base.messenger.send,
            extraArgs=[charEvt],
            pressEffect=True)
        self.btn.setTransparency(1)
        self.animation = None
        self.charFolder = charFolder
        self.movement = None

    def stop(self):
        if self.animation is not None:
            self.animation.finish()
        if self.movement is not None:
            self.movement.finish()

    def destroy(self):
        self.stop()
        self.btn.destroy()

    def setStart(self, newPos):
        if self.movement is not None:
            self.movement.finish()

        self.btn.setPos(newPos)

    def animate(self, animation, direction, framecount, stopMovement=False):
        if stopMovement and self.movement is not None:
            self.movement.finish()

        if self.animation is not None:
            self.animation.finish()
        self.animation = self.getAnimation(animation, direction, framecount)
        self.animation.loop()

    def getAnimation(self, animationName, direction, framecount):
        delay = Wait(0.3)
        animation = Sequence()

        for i in range(1, framecount):
            path = "characters/{}/{}_{}{}.png".format(self.charFolder,
                                                      animationName, direction,
                                                      i)
            animation.append(Func(self.setFrame, path))
            animation.append(delay)

        return animation

    def setFrame(self, path):
        self.btn.setImage(path)
        tex = self.btn.component("image0").getTexture()
        tex.setMagfilter(SamplerState.FT_nearest)
        tex.setMinfilter(SamplerState.FT_nearest)

    def moveTo(self, newPos):
        self.animation.finish()
        direction = ""
        if newPos[0] > self.btn.getX():
            direction = "r"
        else:
            direction = "l"
        self.movement = Sequence(
            Func(self.animate, "run", direction, 4),
            self.btn.posInterval(3.0, newPos),
            Func(self.animate, "idle", direction, 3),
        )
        self.movement.start()
Esempio n. 11
0
class DirectFolderBrowser(DirectObject):
    def __init__(self,
                 command,
                 fileBrowser=False,
                 defaultPath="~",
                 defaultFilename="unnamed.txt",
                 fileExtensions=[],
                 tooltip=None,
                 iconDir=None,
                 parent=None,
                 theme=None):
        """
        A simple file and folder browser

        command: The command that will be called on closing the browser
        fileBrowser: If set to True the browser will show files, otherwise it will only show folders
        defaultPath: The initial path the browser will be set to show
        defaultFilename: The filename that will be set by default, only usefull if fileBrowser is True
        fileExtensions: A list of extensions. Only files with those extensions will be shown. Only usefull if fileBrowser is True
        tooltip: An instance of the Tooltip class to display tooltips for certain parts of the editor
        iconDir: A directory path that contains replacement images. It must contain all required images which are:
            File.png
            Folder.png
            FolderNew.png
            FolderShowHidden.png
            FolderUp.png
            Reload.png
        parent: Another DirectGUI element which has pixel2d as root parent.
            The browser frame is placed centered so a frame for example should have equal sizes in horizontal and vertical directions
            e.g. frameSize=(-250,250,-200,200)
        """
        self.theme = theme if theme is not None else LightTheme()
        self.tt = tooltip
        self.command = command
        self.showFiles = fileBrowser
        self.fileExtensions = fileExtensions
        self.showHidden = False
        self.parent = parent

        self.imageOpts = LoaderOptions()
        self.imageOpts.set_auto_texture_scale(ATS_none)

        if self.theme.icon_dir is not None:
            self.iconDir = self.theme.icon_dir
        elif iconDir is None:
            fn = Filename.fromOsSpecific(os.path.dirname(__file__))
            fn.makeTrueCase()
            self.iconDir = str(fn) + "/icons"
        else:
            self.iconDir = iconDir
        self.selectedViewType = "Symbol"

        self.currentPath = os.path.expanduser(defaultPath)
        if not os.path.exists(self.currentPath):
            self.currentPath = os.path.expanduser("~")
        self.previousPath = self.currentPath

        if self.parent is None:
            self.parent = base.pixel2d
            self.screenWidthPx = base.getSize()[0]
            self.screenHeightPx = base.getSize()[1]
            self.position = LPoint3f(base.getSize()[0] / 2, 0,
                                     -base.getSize()[1] / 2)
        else:
            self.screenWidthPx = self.parent.getWidth()
            self.screenHeightPx = self.parent.getHeight()
            self.position = LPoint3f(0)
        self.screenWidthPxHalf = self.screenWidthPx * 0.5
        self.screenHeightPxHalf = self.screenHeightPx * 0.5

        self.mainFrame = DirectFrame(
            relief=1,
            frameSize=(-self.screenWidthPxHalf, self.screenWidthPxHalf,
                       -self.screenHeightPxHalf, self.screenHeightPxHalf),
            frameColor=self.theme.main_background,
            pos=self.position,
            parent=self.parent,
            state=DGG.NORMAL,
        )

        self.pathRightMargin = 155  # NOTE: Add 28 for each button to the right + 15px margin
        self.pathEntryWidth = self.screenWidthPx - self.pathRightMargin - 28

        # The path entry on top of the window
        self.pathEntry = DirectEntry(
            text_fg=self.theme.default_text_color,
            parent=self.mainFrame,
            relief=DGG.SUNKEN,
            frameColor=self.theme.entry_background,
            pad=(0.2, 0.2),
            pos=LPoint3f(-self.screenWidthPxHalf + 15, 0,
                         self.screenHeightPxHalf - 25),
            scale=12,
            width=self.pathEntryWidth / 12,
            overflow=True,
            command=self.entryAccept,
            initialText=self.currentPath,
            focusInCommand=base.messenger.send,
            focusInExtraArgs=["unregisterKeyboardEvents"],
            focusOutCommand=base.messenger.send,
            focusOutExtraArgs=["reregisterKeyboardEvents"],
        )

        # ----------------
        # CONTROL BUTTONS
        # ----------------
        x = self.screenWidthPxHalf - self.pathRightMargin + 18

        # RELOAD
        self.btnReload = DirectButton(
            parent=self.mainFrame,
            relief=1,
            frameColor=self.theme.icon_button_background,
            frameSize=(-14, 14, -10, 18),
            pos=LPoint3f(x, 0, self.screenHeightPxHalf - 25),
            command=self.folderReload,
            image=loader.load_texture(f"{self.iconDir}/Reload.png",
                                      loaderOptions=self.imageOpts),
            image_scale=14,
            image_pos=(0, 0, 4),
        )
        self.btnReload.setTransparency(TransparencyAttrib.M_multisample)
        if self.tt is not None:
            self.btnReload.bind(DGG.ENTER, self.tt.show, ["Reload Folder"])
            self.btnReload.bind(DGG.EXIT, self.tt.hide)

        # MOVE UP ONE FOLDER
        x += 28
        self.btnFolderUp = DirectButton(
            parent=self.mainFrame,
            relief=1,
            frameColor=self.theme.icon_button_background,
            frameSize=(-14, 14, -10, 18),
            pos=LPoint3f(x, 0, self.screenHeightPxHalf - 25),
            command=self.folderUp,
            image=loader.load_texture(f"{self.iconDir}/FolderUp.png",
                                      loaderOptions=self.imageOpts),
            image_scale=14,
            image_pos=(0, 0, 4),
        )
        self.btnFolderUp.setTransparency(TransparencyAttrib.M_multisample)
        if self.tt is not None:
            self.btnFolderUp.bind(DGG.ENTER, self.tt.show,
                                  ["Move up one level"])
            self.btnFolderUp.bind(DGG.EXIT, self.tt.hide)

        # CREATE NEW FOLDER
        x += 28
        self.btnFolderNew = DirectButton(
            parent=self.mainFrame,
            relief=1,
            frameColor=self.theme.icon_button_background,
            frameSize=(-14, 14, -10, 18),
            pos=LPoint3f(x, 0, self.screenHeightPxHalf - 25),
            command=self.folderNew,
            image=loader.load_texture(f"{self.iconDir}/FolderNew.png",
                                      loaderOptions=self.imageOpts),
            image_scale=14,
            image_pos=(0, 0, 4),
        )
        self.btnFolderNew.setTransparency(TransparencyAttrib.M_multisample)
        if self.tt is not None:
            self.btnFolderNew.bind(DGG.ENTER, self.tt.show,
                                   ["Create new folder"])
            self.btnFolderNew.bind(DGG.EXIT, self.tt.hide)

        # SHOW HIDDEN FOLDERS
        x += 28
        self.btnFolderShowHidden = DirectButton(
            parent=self.mainFrame,
            relief=1,
            frameColor=self.theme.icon_button_background,
            frameSize=(-14, 14, -10, 18),
            pos=LPoint3f(x, 0, self.screenHeightPxHalf - 25),
            command=self.folderShowHidden,
            image=loader.load_texture(f"{self.iconDir}/FolderShowHidden.png",
                                      loaderOptions=self.imageOpts),
            image_scale=14,
            image_pos=(0, 0, 4),
        )
        self.btnFolderShowHidden.setTransparency(
            TransparencyAttrib.M_multisample)
        if self.tt is not None:
            self.btnFolderShowHidden.bind(
                DGG.ENTER, self.tt.show,
                ["Show/Hide hidden files and folders"])
            self.btnFolderShowHidden.bind(DGG.EXIT, self.tt.hide)

        # TOGGLE VIEW TYPE
        x += 28
        self.btnViewType = DirectButton(
            parent=self.mainFrame,
            relief=1,
            frameColor=self.theme.icon_button_background,
            frameSize=(-14, 14, -10, 18),
            pos=LPoint3f(x, 0, self.screenHeightPxHalf - 25),
            command=self.toggleViewType,
            image=loader.load_texture(f"{self.iconDir}/ViewTypeSymbol.png",
                                      loaderOptions=self.imageOpts),
            image_scale=14,
            image_pos=(0, 0, 4),
        )
        self.btnViewType.setTransparency(TransparencyAttrib.M_multisample)
        if self.tt is not None:
            self.btnViewType.bind(
                DGG.ENTER, self.tt.show,
                ["Toggle view between Symbols and Detail list"])
            self.btnViewType.bind(DGG.EXIT, self.tt.hide)

        # --------------
        # CONTENT FRAME
        # --------------
        color = self.theme.scrollbar_controlls_color
        self.container = DirectScrolledFrame(
            relief=DGG.RIDGE,
            borderWidth=(2, 2),
            frameColor=self.theme.main_background,
            frameSize=(-self.screenWidthPxHalf + 10,
                       self.screenWidthPxHalf - 10,
                       -self.screenHeightPxHalf + 50,
                       self.screenHeightPxHalf - 50),
            canvasSize=(-self.screenWidthPxHalf + 31,
                        self.screenWidthPxHalf - 10,
                        -self.screenHeightPxHalf + 50,
                        self.screenHeightPxHalf - 50),
            pos=LPoint3f(0, 0, 0),
            parent=self.mainFrame,
            scrollBarWidth=20,
            verticalScroll_scrollSize=20,
            verticalScroll_thumb_relief=DGG.FLAT,
            verticalScroll_incButton_relief=DGG.FLAT,
            verticalScroll_decButton_relief=DGG.FLAT,
            verticalScroll_thumb_frameColor=color,
            verticalScroll_incButton_frameColor=color,
            verticalScroll_decButton_frameColor=color,
            verticalScroll_frameColor=self.theme.scroll_background,
            horizontalScroll_thumb_relief=DGG.FLAT,
            horizontalScroll_incButton_relief=DGG.FLAT,
            horizontalScroll_decButton_relief=DGG.FLAT,
            horizontalScroll_thumb_frameColor=color,
            horizontalScroll_incButton_frameColor=color,
            horizontalScroll_decButton_frameColor=color,
            horizontalScroll_frameColor=self.theme.scroll_background,
            state=DGG.NORMAL,
        )
        self.container.bind(DGG.MWDOWN, self.scroll, [0.01])
        self.container.bind(DGG.MWUP, self.scroll, [-0.01])

        # ACCEPT BUTTON
        self.btnOk = DirectButton(
            parent=self.mainFrame,
            relief=1,
            frameColor=self.theme.text_button_background,
            frameSize=(-45, 45, -6, 14),
            pos=LPoint3f(self.screenWidthPxHalf - 160, 0,
                         -self.screenHeightPxHalf + 25),
            text="ok",
            text_scale=12,
            text_fg=self.theme.default_text_color,
            command=command,
            extraArgs=[1],
        )

        # CANCEL BUTTON
        self.btnCancel = DirectButton(
            parent=self.mainFrame,
            relief=1,
            frameColor=self.theme.text_button_background,
            frameSize=(-45, 45, -6, 14),
            pos=LPoint3f(self.screenWidthPxHalf - 55, 0,
                         -self.screenHeightPxHalf + 25),
            text="Cancel",
            text_scale=12,
            text_fg=self.theme.default_text_color,
            command=command,
            extraArgs=[0])

        # SELECTED FILE ENTRY FIELD
        if self.showFiles:
            self.txtFileName = DirectEntry(
                text_fg=self.theme.default_text_color,
                parent=self.mainFrame,
                relief=DGG.SUNKEN,
                frameColor=self.theme.entry_background,
                pad=(0.2, 0.2),
                pos=LPoint3f(-self.screenWidthPxHalf + 25, 0,
                             -self.screenHeightPxHalf + 25),
                scale=12,
                width=200 / 12,
                overflow=True,
                command=self.filenameAccept,
                initialText=defaultFilename,
                focusInCommand=base.messenger.send,
                focusInExtraArgs=["unregisterKeyboardEvents"],
                focusOutCommand=base.messenger.send,
                focusOutExtraArgs=["reregisterKeyboardEvents"],
            )

        # ------------------
        # CREATE NEW FOLDER
        # ------------------
        # FRAME FOR CREATING NEW FOLDER
        self.newFolderFrame = DirectFrame(
            parent=self.mainFrame,
            relief=1,
            frameSize=(-self.screenWidthPxHalf + 10,
                       self.screenWidthPxHalf - 10, -20, 20),
            pos=LPoint3f(0, 0, self.screenHeightPxHalf - 55),
            frameColor=self.theme.popup_frame_background,
        )

        # LABEL FOR NEW FOLDER NAME ENTRY
        self.txtNewFolderName = DirectLabel(
            parent=self.newFolderFrame,
            text="New Folder Name",
            text_scale=12,
            text_fg=self.theme.default_text_color,
            frameColor=(0, 0, 0, 0),
            text_align=TextNode.ALeft,
            pos=(-self.screenWidthPxHalf + 15, 0, -3),
        )

        # ENTRY FOR THE NEW FOLDER NAME
        self.folderName = DirectEntry(
            text_fg=self.theme.default_text_color,
            parent=self.newFolderFrame,
            relief=DGG.SUNKEN,
            frameColor=self.theme.entry_background,
            pad=(0.2, 0.2),
            pos=LPoint3f(
                -self.screenWidthPxHalf + 25 +
                self.txtNewFolderName.getWidth(), 0, -4),
            scale=12,
            width=((self.screenWidthPxHalf - 25) * 2 -
                   self.txtNewFolderName.getWidth() - 100) / 12,
            overflow=True,
            command=self.entryAccept,
            initialText="New Folder",
            focusInCommand=base.messenger.send,
            focusInExtraArgs=["unregisterKeyboardEvents"],
            focusOutCommand=base.messenger.send,
            focusOutExtraArgs=["reregisterKeyboardEvents"],
        )

        # ACCEPT BUTTON FOR THE CREATE NEW FOLDER
        self.btnCreate = DirectButton(
            parent=self.newFolderFrame,
            relief=1,
            frameColor=self.theme.text_button_background,
            frameSize=(-45, 45, -6, 14),
            pos=LPoint3f(self.screenWidthPxHalf - 65, 0, -4),
            text="Create",
            text_scale=12,
            text_fg=self.theme.default_text_color,
            command=self.folderCreate,
            extraArgs=[0])
        # Hide the create new folder frame by default
        self.newFolderFrame.hide()

        # ---------------
        # UPDATE CONTENT
        # ---------------
        # Initial loading of the files and folders of the current path
        self.folderReload()

        # handle window resizing
        self.prevScreenSize = base.getSize()
        if self.parent is base.pixel2d:
            self.accept("window-event", self.windowEventHandler)

    def show(self):
        self.mainFrame.show()
        if self.parent is None:
            self.accept("window-event", self.windowEventHandler)

    def hide(self):
        self.ignore("window-event")
        self.mainFrame.hide()

    def destroy(self):
        self.ignore("window-event")
        self.mainFrame.destroy()

    def scroll(self, scrollStep, event):
        self.container.verticalScroll.scrollStep(scrollStep)

    def get(self):
        if self.showFiles:
            return os.path.join(self.currentPath, self.txtFileName.get(True))
        return self.currentPath

    def filenameAccept(self, filename):
        self.command(1)

    def entryAccept(self, path):
        self.folderReload()

    def folderReload(self):

        for element in self.container.getCanvas().getChildren():
            element.removeNode()

        path = self.pathEntry.get(True)
        path = os.path.expanduser(path)
        path = os.path.expandvars(path)
        if not os.path.exists(path): return
        self.currentPath = path

        try:
            content = os.scandir(path)
        except PermissionError:
            base.messenger.send("showWarning", ["Access denied!"])
            self.pathEntry.set(self.previousPath)
            self.currentPath = self.previousPath
            self.folderReload()
            return

        # start position for the folders and files
        VIEWTYPE[self.selectedViewType](self, content)

    def folderUp(self):
        self.previousPath = self.currentPath
        self.currentPath = os.path.normpath(
            os.path.join(self.currentPath, ".."))
        self.pathEntry.set(self.currentPath)
        self.folderReload()

    def folderMoveIn(self, path):
        path = os.path.expanduser(path)
        path = os.path.expandvars(path)
        self.previousPath = self.currentPath
        self.currentPath = path
        self.pathEntry.set(path)
        self.folderReload()
        self.container.verticalScroll["value"] = 0

    def folderNew(self):
        if self.newFolderFrame.isHidden():
            self.newFolderFrame.show()
        else:
            self.newFolderFrame.hide()

    def folderShowHidden(self):
        self.showHidden = not self.showHidden
        self.folderReload()

    def toggleViewType(self):
        if self.selectedViewType == "Symbol":
            self.selectedViewType = "Detail"
            self.btnViewType["image"] = loader.load_texture(
                f"{self.iconDir}/ViewTypeDetail.png",
                loaderOptions=self.imageOpts)
        else:
            self.selectedViewType = "Symbol"
            self.btnViewType["image"] = loader.load_texture(
                f"{self.iconDir}/ViewTypeSymbol.png",
                loaderOptions=self.imageOpts)

        self.folderReload()

    def folderCreate(self, path=""):
        try:
            os.makedirs(
                os.path.join(self.currentPath, self.folderName.get(True)))
        except:
            base.messenger.send("showWarning", ["Can't create folder"])
        self.newFolderFrame.hide()
        self.folderReload()

    def windowEventHandler(self, window=None):
        if window != base.win:
            # This event isn't about our window.
            return

        if window is not None:  # window is none if panda3d is not started
            if self.prevScreenSize == base.getSize():
                return
            self.prevScreenSize = base.getSize()
            self.screenWidthPx = base.getSize()[0]
            self.screenWidthPxHalf = self.screenWidthPx * 0.5
            self.screenHeightPx = base.getSize()[1]
            self.screenHeightPxHalf = self.screenHeightPx * 0.5

            # reposition and resize all gui elements
            self.mainFrame.setPos(self.screenWidthPx / 2, 0,
                                  -self.screenHeightPx / 2)
            self.mainFrame["frameSize"] = (-self.screenWidthPxHalf,
                                           self.screenWidthPxHalf,
                                           -self.screenHeightPxHalf,
                                           self.screenHeightPxHalf)

            self.pathEntryWidth = self.screenWidthPx - self.pathRightMargin - 28
            self.pathEntry.setPos(
                LPoint3f(-self.screenWidthPxHalf + 15, 0,
                         self.screenHeightPxHalf - 25))
            self.pathEntry["width"] = self.pathEntryWidth / 12
            self.pathEntry.resetFrameSize()

            # reposition top right icons
            x = self.screenWidthPxHalf - self.pathRightMargin + 14
            self.btnReload.setPos(LPoint3f(x, 0, self.screenHeightPxHalf - 25))
            x += 28
            self.btnFolderUp.setPos(
                pos=LPoint3f(x, 0, self.screenHeightPxHalf - 25))
            x += 28
            self.btnFolderNew.setPos(
                pos=LPoint3f(x, 0, self.screenHeightPxHalf - 25))
            x += 28
            self.btnFolderShowHidden.setPos(
                pos=LPoint3f(x, 0, self.screenHeightPxHalf - 25))
            x += 28
            self.btnViewType.setPos(
                pos=LPoint3f(x, 0, self.screenHeightPxHalf - 25))

            # resize the browsing area
            self.container["frameSize"] = (-self.screenWidthPxHalf + 10,
                                           self.screenWidthPxHalf - 10,
                                           -self.screenHeightPxHalf + 50,
                                           self.screenHeightPxHalf - 50)
            # Note: canvas size of the container will be reset in the
            #       folder Reload call at the end of this function
            self.btnOk.setPos(
                LPoint3f(self.screenWidthPxHalf - 160, 0,
                         -self.screenHeightPxHalf + 25))
            self.btnCancel.setPos(
                LPoint3f(self.screenWidthPxHalf - 55, 0,
                         -self.screenHeightPxHalf + 25))
            if self.showFiles:
                self.txtFileName.setPos(
                    LPoint3f(-self.screenWidthPxHalf + 25, 0,
                             -self.screenHeightPxHalf + 25))
            self.newFolderFrame.setPos(
                LPoint3f(0, 0, self.screenHeightPxHalf - 55))
            self.newFolderFrame["frameSize"] = (-self.screenWidthPxHalf + 10,
                                                self.screenWidthPxHalf - 10,
                                                -20, 20)
            self.txtNewFolderName.setPos(-self.screenWidthPxHalf + 15, 0, -3)
            self.folderName.setPos(
                LPoint3f(
                    -self.screenWidthPxHalf + 25 +
                    self.txtNewFolderName.getWidth(), 0, -4))
            self.folderName["width"] = (
                (self.screenWidthPxHalf - 25) * 2 -
                self.txtNewFolderName.getWidth() - 100) / 12
            self.btnCreate.setPos(LPoint3f(self.screenWidthPxHalf - 65, 0, -4))

            self.folderReload()