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)
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)
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')
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.')
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()
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)
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()
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()