class KoScreen(DirectObject): def __init__(self): self.frameMain = DirectFrame( frameSize = (base.a2dLeft, base.a2dRight, base.a2dTop, base.a2dBottom), frameColor = (0, 0, 0, 0.75)) self.frameMain.setTransparency(1) self.lbl_KO = DirectLabel( text = "K.O.", text_fg = (1,1,1,1), scale = 1, pos = (0, 0, 0), frameColor = (0,0,0,0)) self.lbl_KO.setTransparency(1) self.lbl_KO.reparentTo(self.frameMain) self.lbl_PlayerXWon = DirectLabel( text = "PLAYER X WON", text_fg = (1,1,1,1), scale = 0.25, pos = (0, 0, -0.5), frameColor = (0,0,0,0)) self.lbl_PlayerXWon.setTransparency(1) self.lbl_PlayerXWon.reparentTo(self.frameMain) self.btnContinue = DirectButton( text = "CONTINUE", text_fg = (1,1,1,1), scale = 0.1, pad = (0.15, 0.15), pos = (0, 0, -0.8), frameColor = ( (0.2,0.2,0.2,0.8), (0.4,0.4,0.4,0.8), (0.4,0.4,0.4,0.8), (0.1,0.1,0.1,0.8), ), relief = 1, command = base.messenger.send, extraArgs = ["KoScreen-Back"], pressEffect = False, rolloverSound = None, clickSound = None) self.btnContinue.setTransparency(1) self.btnContinue.reparentTo(self.frameMain) self.hide() def show(self, succseedingPlayer): self.frameMain.show() self.lbl_PlayerXWon["text"] = "PLAYER %d WON" % succseedingPlayer def hide(self): self.frameMain.hide()
class LoadingScreen(): def __init__(self): # a fill panel so the player doesn't see how everything # gets loaded in the background self.frameMain = DirectFrame( # size of the frame frameSize = (base.a2dLeft, base.a2dRight, base.a2dTop, base.a2dBottom), image = "Logo.png", image_scale = (0.612/2.0, 1, 0.495/2.0), image_pos = (0, 0, 0.7), # tramsparent bg color frameColor = (0, 0, 0, 1)) self.frameMain.setTransparency(1) # the text Loading... on top self.lblLoading = DirectLabel( scale = 0.25, pos = (0, 0, 0), frameColor = (0, 0, 0, 0), text = _("Loading..."), text_align = TextNode.ACenter, text_fg = (1,1,1,1)) self.lblLoading.reparentTo(self.frameMain) # the waitbar on the bottom self.wbLoading = DirectWaitBar( text = "0%", text_fg = (1,1,1,1), value = 0, pos = (0, 0, -0.5), barColor = (0.5, 0.4, 0.1, 1), frameColor = (0.1, 0.1, 0.1, 1)) self.wbLoading.reparentTo(self.frameMain) def show(self): self.frameMain.show() # and render two frames so the loading screen # is realy shown on screen base.graphicsEngine.renderFrame() base.graphicsEngine.renderFrame() def hide(self): self.frameMain.hide() def setLoadingValue(self, value): """Set the waitbar value to the given value, where value has to be a integer from 0 to 100""" if value > 100: value = 100 if value < 0: value = 0 self.wbLoading["value"] = value self.wbLoading["text"] = "{0}%".format(value) base.graphicsEngine.renderFrame() base.graphicsEngine.renderFrame()
def __makeListItem(self, action, event, index): def dummy(): pass if index % 2 == 0: bg = self.listBGEven else: bg = self.listBGOdd item = DirectFrame( text=action, geom=bg, geom_scale=(base.a2dRight-0.05, 1, 0.1), frameSize=VBase4(base.a2dLeft+0.05, base.a2dRight-0.05, -0.05, 0.05), frameColor=VBase4(1,0,0,0), text_align=TextNode.ALeft, text_scale=0.05, text_fg=VBase4(1,1,1,1), text_pos=(base.a2dLeft + 0.3, -0.015), text_shadow=VBase4(0, 0, 0, 0.35), text_shadowOffset=Vec2(-0.05, -0.05), pos=(0.05, 0, -(0.10 * index))) item.setTransparency(True) lbl = DirectLabel( text=event, text_fg=VBase4(1, 1, 1, 1), text_scale=0.05, text_pos=Vec2(0, -0.015), frameColor=VBase4(0, 0, 0, 0), ) lbl.reparentTo(item) lbl.setTransparency(True) self.actionLabels[action] = lbl buttonScale = 0.15 btn = DirectButton( text="Change", geom=self.buttonGeom, scale=buttonScale, text_scale=0.25, text_align=TextNode.ALeft, text_fg=VBase4(0.898, 0.839, 0.730, 1.0), text_pos=Vec2(-0.9, -0.085), relief=1, pad=Vec2(0.01, 0.01), frameColor=VBase4(0, 0, 0, 0), frameSize=VBase4(-1.0, 1.0, -0.25, 0.25), pos=(base.a2dRight-(0.898*buttonScale+0.3), 0, 0), pressEffect=False, command=self.changeMapping, extraArgs=[action]) btn.setTransparency(True) btn.reparentTo(item) return item
class LoadingScreen(): """Show a directWaitbar to display the current loading state of the application""" def __init__(self): # a fill panel so the player doesn't see how everything # gets loaded in the background self.frameMain = DirectFrame( image="gui/MenuBackground.png", image_scale=(1.7778, 1, 1), #image_pos=(0, 0, 0.25), frameSize=( base.a2dLeft, base.a2dRight, base.a2dTop, base.a2dBottom), frameColor=(0,0,0,0)) self.frameMain.setTransparency(True) self.frameMain.setBin("fixed", 6000) self.frameMain.setDepthWrite(False) self.logo = DirectFrame( image="Logo.png", image_scale=0.25, image_pos=(0, 0, 0.55), frameSize=( base.a2dLeft, base.a2dRight, base.a2dTop, base.a2dBottom), frameColor=(0,0,0,0)) self.logo.reparentTo(self.frameMain) # the text Loading... self.lblLoading = DirectLabel( scale=0.10, pos=(0, 0, -0.15), frameColor=(0, 0, 0, 0), text=_("Loading..."), text_align=TextNode.ACenter, text_fg=(1, 1, 1, 1)) self.lblLoading.reparentTo(self.frameMain) self.stop() def start(self): self.frameMain.show() base.graphicsEngine.renderFrame() base.graphicsEngine.renderFrame() def stop(self): self.frameMain.hide()
class Mainmenu(): def __init__(self): self.frameMain = DirectFrame( image="gui/MenuBackground.png", image_scale=(1.7778, 1, 1), #image_pos=(0, 0, 0.25), frameSize=( base.a2dLeft, base.a2dRight, base.a2dTop, base.a2dBottom), frameColor=(0,0,0,0)) self.frameMain.setTransparency(True) self.logo = DirectFrame( image="Logo.png", image_scale=0.45, image_pos=(0, 0, 0.35), frameSize=( base.a2dLeft, base.a2dRight, base.a2dTop, base.a2dBottom), frameColor=(0,0,0,0)) self.logo.reparentTo(self.frameMain) btnGeom = "gui/button" self.btnStart = menuHelper.createButton(_("Start"), btnGeom, 0, -0.7, ["menu_start"]) self.btnStart.reparentTo(self.frameMain) self.btnOptions = menuHelper.createButton(_("Options"), btnGeom, -1.0, -0.7, ["menu_options"]) self.btnOptions.reparentTo(self.frameMain) self.btnQuit = menuHelper.createButton(_("Quit"), btnGeom, 1.0, -0.7, ["menu_quit"]) self.btnQuit.reparentTo(self.frameMain) self.hide() def show(self): self.frameMain.show() def hide(self): self.frameMain.hide()
class OptionsMenu(): def __init__(self): self.frameMain = DirectFrame(image="optionsmenu.png", image_scale=(1.7778, 1, 1), frameSize=(base.a2dLeft, base.a2dRight, base.a2dBottom, base.a2dTop), frameColor=(0, 0, 0, 0)) self.frameMain.setTransparency(True) volume = base.musicManager.getVolume() self.sliderMusicVolume = DirectSlider( scale=0.5, pos=(0, 0, -0.1), range=(0, 1), scrollSize=0.01, text="Music Volume: %d%%" % volume * 100, text_scale=0.15, text_align=TextNode.ACenter, text_pos=(.0, 0.15), text_fg=(240 / 255.0, 255 / 255.0, 240 / 255.0, 1), thumb_frameColor=(0.8, 0, 1, 0.75), thumb_relief=DGG.FLAT, frameColor=(0.25, 0.25, 0.55, 1), value=volume, command=self.sliderMusicVolume_ValueChanged) self.sliderMusicVolume.reparentTo(self.frameMain) volume = base.sfxManagerList[0].getVolume() self.sliderSFXVolume = DirectSlider( scale=0.5, pos=(0, 0, -0.3), range=(0, 1), scrollSize=0.01, text="SFX Volume: %d%%" % volume * 100, text_scale=0.15, text_align=TextNode.ACenter, text_pos=(.0, 0.15), text_fg=(240 / 255.0, 255 / 255.0, 240 / 255.0, 1), thumb_frameColor=(0.8, 0, 1, 0.75), thumb_relief=DGG.FLAT, frameColor=(0.25, 0.25, 0.55, 1), value=volume, command=self.sliderSFXVolume_ValueChanged) self.sliderSFXVolume.reparentTo(self.frameMain) isChecked = not base.AppHasAudioFocus img = None imgON = "AudioSwitch_on.png" imgOFF = "AudioSwitch_off.png" if base.AppHasAudioFocus: img = imgON else: img = imgOFF self.cbVolumeMute = DirectCheckBox( scale=0.5, text="Mute Audio", text_scale=0.15, text_align=TextNode.ACenter, text_pos=(0.0, 0.15), text_fg=(240 / 255.0, 255 / 255.0, 240 / 255.0, 1), pos=(0, 0, -0.5), command=self.cbVolumeMute_CheckedChanged, rolloverSound=None, clickSound=None, relief=None, pressEffect=False, isChecked=isChecked, image=img, image_scale=0.1, checkedImage=imgOFF, uncheckedImage=imgON) self.cbVolumeMute.setTransparency(True) self.cbVolumeMute.setImage() self.cbVolumeMute.reparentTo(self.frameMain) radio = base.loader.loadModel("radioBtn") radioGeom = (radio.find("**/RadioButtonReady"), radio.find("**/RadioButtonChecked")) self.lblDifficulty = DirectLabel(text="Difficulty", text_fg=(240 / 255.0, 255 / 255.0, 240 / 255.0, 1), text_scale=0.6, scale=0.15, frameColor=(0, 0, 0, 0), pos=(-0.5, 0, -0.6)) self.lblDifficulty.reparentTo(self.frameMain) self.difficulty = [base.difficulty] def createDifficultyDRB(self, text, value, initialValue, xPos): drb = DirectRadioButton( text=text, text_fg=(240 / 255.0, 255 / 255.0, 240 / 255.0, 1), variable=self.difficulty, value=value, indicatorValue=initialValue, boxGeom=radioGeom, boxGeomScale=0.5, #indicator_pad = (0.1, 0.1), scale=0.05, frameColor=(0.5, 0.5, 0.5, 1), pressEffect=False, relief=1, pad=(0.5, 0, 0.5, 0.5), pos=(xPos, 0, -0.6), command=self.rbDifficulty_ValueChanged) drb.indicator.setX(drb.indicator.getX() + 0.1) drb.indicator.setZ(drb.indicator.getZ() + 0.1) drb.reparentTo(self.frameMain) return drb self.difficultyButtons = [ createDifficultyDRB(self, "Easy", [0], 1 if base.difficulty == 0 else 0, 0.5 - 0.3), createDifficultyDRB(self, "Medium", [1], 1 if base.difficulty == 1 else 0, 0.5), createDifficultyDRB(self, "Hard", [2], 1 if base.difficulty == 2 else 0, 0.5 + 0.3) ] for button in self.difficultyButtons: button.setOthers(self.difficultyButtons) self.btnBack = DirectButton(text="Back", scale=0.15, text_pos=(-0.3, -0.2), text_scale=0.6, text_fg=(240 / 255.0, 255 / 255.0, 240 / 255.0, 1), frameColor=(0, 0, 0, 0), image=("btnExit.png", "btnExit_hover.png", "btnExit_hover.png", "btnExit_hover.png"), image_scale=(1, 1, 0.5), pos=(0, 0, -0.8), command=base.messenger.send, extraArgs=["menu_Back"]) self.btnBack.setTransparency(True) self.btnBack.reparentTo(self.frameMain) self.hide() def show(self): self.frameMain.show() def hide(self): self.frameMain.hide() def cbVolumeMute_CheckedChanged(self, checked): if checked: base.disableAllAudio() else: base.enableAllAudio() def sliderMusicVolume_ValueChanged(self): volume = round(self.sliderMusicVolume["value"], 2) self.sliderMusicVolume["text"] = "Music Volume: %d%%" % int( volume * 100) base.musicManager.setVolume(volume) def sliderSFXVolume_ValueChanged(self): volume = round(self.sliderSFXVolume["value"], 2) self.sliderSFXVolume["text"] = "SFX Volume: %d%%" % int(volume * 100) base.sfxManagerList[0].setVolume(volume) def rbDifficulty_ValueChanged(self): base.difficulty = self.difficulty[0]
class Menu(DirectObject): def __init__(self): self.accept("window-event", self.recalcAspectRatio) self.frameMain = DirectFrame( # size of the frame frameSize=(base.a2dLeft, base.a2dRight, base.a2dTop, base.a2dBottom), # position of the frame image="LogoTextGlow.png", image_scale=(1.06, 1, 0.7), image_pos=(0, 0, 0.25), pos=(0, 0, 0), # tramsparent bg color frameColor=(0, 0, 0, 0), sortOrder=0, ) self.frameMain.setTransparency(1) self.frameMain.setBin("fixed", 100) btnGeom = None self.btnStart = self.createButton(_("Start"), btnGeom, -0.6, self.btnStart_Click) self.btnStart.reparentTo(self.frameMain) self.btnOptions = self.createButton(_("Options"), btnGeom, 0, self.btnOptions_Click) self.btnOptions.reparentTo(self.frameMain) self.btnQuit = self.createButton(_("Quit"), btnGeom, 0.6, self.btnQuit_Click) self.btnQuit.reparentTo(self.frameMain) self.recalcAspectRatio(base.win) # hide all buttons at startup self.hide() def show(self): self.frameMain.show() self.recalcAspectRatio(base.win) def hide(self): self.frameMain.hide() def recalcAspectRatio(self, window): """get the new aspect ratio to resize the mainframe""" screenResMultiplier = window.getXSize() / window.getYSize() self.frameMain["frameSize"] = (base.a2dLeft, base.a2dRight, base.a2dTop, base.a2dBottom) self.btnQuit["text_scale"] = (0.5 * screenResMultiplier, 0.5, 0.5) self.btnStart["text_scale"] = (0.5 * screenResMultiplier, 0.5, 0.5) def createButton(self, text, btnGeom, xPos, command): btn = DirectButton( scale=(0.25, 0.25, 0.25), # some temp text text=text, text_scale=(0.5, 0.5, 0.5), # set the alignment to right text_align=TextNode.ACenter, # put the text on the right side of the button text_pos=(0, -0.15), # set the text color to black text_fg=(1, 1, 1, 1), text_shadow=(0.3, 0.3, 0.1, 1), text_shadowOffset=(0.05, 0.05), # set the buttons images # geom = btnGeom, relief=1, frameColor=(0, 0, 0, 0), pressEffect=False, pos=(xPos, 0, -0.65), command=command, rolloverSound=None, clickSound=None, ) btn.setTransparency(1) return btn def btnStart_Click(self): base.messenger.send("menu_start") def btnOptions_Click(self): base.messenger.send("menu_options") def btnQuit_Click(self): base.messenger.send("menu_quit")
class MainMenu(): def __init__(self): self.frameMain = DirectFrame(image="mainmenu.png", image_scale=(1.7778, 1, 1), frameSize=(base.a2dLeft, base.a2dRight, base.a2dBottom, base.a2dTop), frameColor=(0, 0, 0, 0)) self.frameMain.setTransparency(True) self.btnStart = DirectButton( text="Enter", scale=0.15, text_pos=(0, 1.1), text_scale=0.5, text_fg=(240 / 255.0, 255 / 255.0, 240 / 255.0, 1), frameColor=(0, 0, 0, 0), image=("btnEnter.png", "btnEnter_hover.png", "btnEnter_hover.png", "btnEnter_hover.png"), pos=(0, 0, -0.3), command=base.messenger.send, extraArgs=["menu_StartGame"]) self.btnStart.setTransparency(True) self.btnStart.reparentTo(self.frameMain) self.btnOptions = DirectButton(text="Options", scale=0.1, text_fg=(240 / 255.0, 255 / 255.0, 240 / 255.0, 1), frameColor=(0, 0, 0, 0), image=("settings.png"), image_scale=1.2, text_pos=(0, -0.2), pos=(base.a2dRight - 0.3, 0, base.a2dBottom + 0.25), command=base.messenger.send, extraArgs=["menu_Options"]) self.btnOptions.setTransparency(True) self.btnOptions.reparentTo(self.frameMain) self.btnQuit = DirectButton( text="Exit", scale=0.15, text_pos=(-0.3, -0.25), text_scale=0.75, text_fg=(240 / 255.0, 255 / 255.0, 240 / 255.0, 1), frameColor=(0, 0, 0, 0), image=("btnExit.png", "btnExit_hover.png", "btnExit_hover.png", "btnExit_hover.png"), image_scale=(1, 1, 0.5), pos=(base.a2dLeft + 0.3, 0, base.a2dBottom + 0.25), command=base.messenger.send, extraArgs=["menu_QuitGame"]) self.btnQuit.setTransparency(True) self.btnQuit.reparentTo(self.frameMain) self.imgBouncer = OnscreenImage(image="bouncer.png", scale=(0.75 * 0.25, 1 * 0.25, 1 * 0.25), pos=(-0.25, 0, -0.3)) self.imgBouncer.setTransparency(True) self.imgBouncer.reparentTo(self.frameMain) self.imgBadDude1 = OnscreenImage(image="badDude1.png", scale=(0.25, 0.25, 0.25), pos=(-0.75, 0, -0.4)) self.imgBadDude1.setTransparency(True) self.imgBadDude1.reparentTo(self.frameMain) img = self.imgBadDude1 up = img.posInterval(3.0, Point3(img.getX(), img.getY(), img.getZ() + 0.01), bakeInStart=0) left = img.posInterval(3.0, Point3(img.getX() - 0.01, img.getY(), img.getZ()), bakeInStart=0) right = img.posInterval(3.0, Point3(img.getX() + 0.01, img.getY(), img.getZ()), bakeInStart=0) down = img.posInterval(3.0, Point3(img.getX(), img.getY(), img.getZ() - 0.01), bakeInStart=0) rotForward = img.hprInterval(3.0, Point3(0, 0, 2.5), bakeInStart=0) rotBackward = img.hprInterval(3.0, Point3(0, 0, -2.5), bakeInStart=0) rotCenter = img.hprInterval(3.0, Point3(0, 0, 0), bakeInStart=0) self.ivalBadDude1 = Sequence(Parallel(rotCenter, up), Parallel(rotBackward, left), down, Parallel(rotCenter, up), Parallel(rotForward, right), down) self.imgGoodGal1 = OnscreenImage(image="goodGal1.png", scale=(0.6 * 0.25, 0.25, 0.25), pos=(-0.95, 0, -0.43)) self.imgGoodGal1.setTransparency(True) self.imgGoodGal1.reparentTo(self.frameMain) img = self.imgGoodGal1 up = img.posInterval(3.0, Point3(img.getX(), img.getY(), img.getZ() + 0.01), bakeInStart=0) left = img.posInterval(3.0, Point3(img.getX() - 0.01, img.getY(), img.getZ()), bakeInStart=0) right = img.posInterval(3.0, Point3(img.getX() + 0.01, img.getY(), img.getZ()), bakeInStart=0) down = img.posInterval(3.0, Point3(img.getX(), img.getY(), img.getZ() - 0.01), bakeInStart=0) rotForward = img.hprInterval(3.0, Point3(0, 0, 2.5), bakeInStart=0) rotBackward = img.hprInterval(3.0, Point3(0, 0, -2.5), bakeInStart=0) rotCenter = img.hprInterval(3.0, Point3(0, 0, 0), bakeInStart=0) self.ivalGoodGal1 = Sequence(left, right, left, down, up) self.imgGoodDude1 = OnscreenImage(image="goodDude1.png", scale=(0.25, 0.25, 0.25), pos=(0.95, 0, 0)) self.imgGoodDude1.setTransparency(True) self.imgGoodDude1.reparentTo(self.frameMain) img = self.imgGoodDude1 up = img.posInterval(3.0, Point3(img.getX(), img.getY(), img.getZ() + 0.02), bakeInStart=0) left = img.posInterval(3.0, Point3(img.getX() - 0.02, img.getY(), img.getZ()), bakeInStart=0) right = img.posInterval(3.0, Point3(img.getX() + 0.02, img.getY(), img.getZ()), bakeInStart=0) down = img.posInterval(3.0, Point3(img.getX(), img.getY(), img.getZ() - 0.02), bakeInStart=0) rotForward = img.hprInterval(3.0, Point3(0, 0, 4), bakeInStart=0) rotBackward = img.hprInterval(3.0, Point3(0, 0, -4), bakeInStart=0) rotCenter = img.hprInterval(3.0, Point3(0, 0, 0), bakeInStart=0) self.ivalGoodDude1 = Sequence(Parallel(up, rotCenter), Parallel(right, rotForward), Parallel(down, rotCenter), Parallel(left, rotBackward)) self.hide() def show(self): self.frameMain.show() self.ivalBadDude1.loop() self.ivalGoodGal1.loop() self.ivalGoodDude1.loop() def hide(self): self.frameMain.hide() self.ivalBadDude1.finish() self.ivalGoodGal1.finish() self.ivalGoodDude1.finish()
class LegendaryFish(Fish): def __init__(self, fishManager, myData, index): Fish.__init__(self, fishManager, myData, index) self.fsm = LegendaryFishFSM(self) self.actor.setScale(self.myData['scaleRange'][0]) self.staminaValue = self.myData['stamina'] self.aboutToBitingInterval = None self.fishChaseLureSequence = Sequence() self.lfStruggleSequence = Sequence() self.initFishStaminaBar() self.lurePosition = None def initFishStaminaBar(self): self.legendaryGui = loader.loadModel('models/minigames/pir_m_gam_fsh_legendaryGui') self.iconBaseFrame = DirectFrame(relief = None, state = DGG.DISABLED, pos = (0, 0, 0), sortOrder = 30, image = self.legendaryGui.find('**/pir_t_gui_fsh_fishPortraitFrame'), image_scale = 0.17999999999999999, image_pos = (0, 0, 0)) self.iconBaseFrame.setTransparency(TransparencyAttrib.MAlpha) self.fishUINodePath = NodePath(self.iconBaseFrame) self.fishUINodePath.setPos(-0.29999999999999999, 0.0, 0.82999999999999996) self.fishUINodePath.reparentTo(hidden) self.iconCard = loader.loadModel('models/gui/treasure_gui') self.iconBaseFrame.iconImage = OnscreenImage(parent = self.iconBaseFrame, image = self.iconCard.find('**/%s*' % CollectionMap.Assets[self.myData['id']]), scale = 0.34999999999999998, hpr = (0, 0, 0), pos = (0.0, 0, 0.0)) self.fishNameLabel = TextNode('fishNameLabel') name = self.getName().split('_') self.fishNameLabel.setText(name[0]) self.fishNameLabel.setTextColor(1.0, 1.0, 1.0, 1.0) self.fishNameLabelNodePath = NodePath(self.fishNameLabel) self.fishNameLabelNodePath.setPos(0.29999999999999999, 0, 0.040000000000000001) self.fishNameLabelNodePath.setScale(0.044999999999999998) self.fishNameLabelNodePath.reparentTo(self.iconBaseFrame) self.fishStaminaBar = DirectWaitBar(parent = self.iconBaseFrame, relief = DGG.FLAT, state = DGG.DISABLED, range = 100, value = 0, sortOrder = 20, frameColor = (0, 0, 0, 1.0), pos = (0.070000000000000007, 0.0, -0.014999999999999999), hpr = (0, 0, 0), frameSize = (0, 0.71999999999999997, 0, 0.028000000000000001)) self.fishStaminaBar['value'] = self.staminaValue self.fishStaminaBar['barColor'] = FishingGlobals.fishingStaminaBarColor[int((self.staminaValue / 100.0) * (len(FishingGlobals.fishingStaminaBarColor) - 1))] self.fishStaminaValueLabel = TextNode('fishStaminaValueLabel') self.fishStaminaValueLabel.setText(str(self.staminaValue) + '//' + str(self.staminaValue)) self.fishStaminaValueLabel.setTextColor(1.0, 1.0, 1.0, 1.0) self.fishStaminaValueLabelNodePath = NodePath(self.fishStaminaValueLabel) self.fishStaminaValueLabelNodePath.setPos(0.66000000000000003, 0, -0.059999999999999998) self.fishStaminaValueLabelNodePath.setScale(0.044999999999999998) self.fishStaminaValueLabelNodePath.reparentTo(self.iconBaseFrame) self.fishStaminaBarFrame = DirectLabel(parent = self.iconBaseFrame, relief = None, state = DGG.DISABLED, frameColor = (1, 1, 1, 0.10000000000000001), pos = (0.44, 0.0, 0.0), hpr = (0, 0, 0), sortOrder = 25, image = self.legendaryGui.find('**/pir_t_gui_fsh_staminaBarForeground'), image_scale = (1.0, 0.0, 0.050000000000000003), image_pos = (0.0, 0.0, 0.0), image_hpr = (0.0, 0.0, 0.0)) self.fishStaminaBarFrame.setTransparency(TransparencyAttrib.MAlpha) self.fishStaminaBarFrame.setDepthTest(True) self.fishStaminaBarFrame.setDepthWrite(True) def cleanFishData(self): self.staminaValue = self.myData['stamina'] self.fishStaminaBar['value'] = self.staminaValue self.fishStaminaValueLabel.setText(str(int(self.staminaValue)) + ' / ' + str(100)) self.fishStaminaBar['barColor'] = FishingGlobals.fishingStaminaBarColor[int((self.staminaValue / 100.0) * (len(FishingGlobals.fishingStaminaBarColor) - 1))] self.hideStaminaBar() taskMgr.remove('updateFishStaminaTask') self.lurePosition = None self.fishChaseLureSequence.pause() self.fishChaseLureSequence.clearToInitial() self.lfStruggleSequence.pause() self.lfStruggleSequence.clearToInitial() if self.aboutToBitingInterval is None: return None self.aboutToBitingInterval.pause() def destroy(self): self.fishUINodePath.removeNode() Fish.destroy(self) def updateFishStaminaTask(self, task = None): if self.staminaValue <= 1: return Task.done self.staminaValue = max(1, self.staminaValue - FishingGlobals.staminaReduceValue) self.fishStaminaValueLabel.setText(str(int(self.staminaValue)) + ' / ' + str(100)) self.fishStaminaBar['value'] = self.staminaValue self.fishStaminaBar['barColor'] = FishingGlobals.fishingStaminaBarColor[int((self.staminaValue / 100.0) * (len(FishingGlobals.fishingStaminaBarColor) - 1))] return Task.cont def updateFishStaminaBar(self): self.fishStaminaBar['value'] = self.staminaValue def fishStaminaConsume(self): taskMgr.add(self.updateFishStaminaTask, 'updateFishStaminaTask') def staminaPercentage(self): return self.staminaValue / self.myData['stamina'] def showStaminaBar(self): self.fishUINodePath.reparentTo(aspect2d) def hideStaminaBar(self): self.fishUINodePath.reparentTo(hidden) def performStraightBehavior(self, lurePos, dt): newX = self.getX() + self.velocity[0] * dt + self.accel[0] * dt * dt newZ = self.getZ() + self.velocity[2] * dt + self.accel[2] * dt * dt return (newX, newZ)
class OptionsMenu(DirectObject): def __init__(self): """Default constructor""" # create a main frame as big as the window self.frameMain = DirectFrame( # set framesize the same size as the window frameSize = (base.a2dLeft, base.a2dRight, base.a2dTop, base.a2dBottom), image = "LogoTextGlow.png", image_scale = (1.06/2.0, 1, 0.7/2.0), image_pos = (0, 0, 0.7), # position center pos = (0, 0, 0), # set tramsparent background color frameColor = (0, 0, 0, 0)) self.frameMain.setTransparency(1) self.frameMain.setBin("fixed", 100) sliderscale = 0.5 buttonScale = 0.25 textscale = 0.1 checkboxscale = 0.05 left = -0.5 right = 0.5 self.sliderTextspeed = DirectSlider( scale = sliderscale, pos = (left, 0, 0.2), range = (0.2,0.01), scrollSize = 0.01, text = _("Textspeed %0.1f%%")%(base.textWriteSpeed * 10), text_scale = textscale, text_align = TextNode.ACenter, text_pos = (0.0, 0.15), text_fg = (1,1,1,1), thumb_frameColor = (0.65, 0.65, 0.0, 1), thumb_relief = DGG.FLAT, frameColor = (0.15, 0.15, 0.15, 1), value = base.textWriteSpeed, command = self.sliderTextspeed_ValueChanged) self.sliderTextspeed.reparentTo(self.frameMain) self.cbParticles = DirectCheckButton( text = _(" Enable Particles"), text_fg = (1, 1, 1, 1), text_shadow = (0, 0, 0, 0.35), pos = (left, 0, -0.0), scale = checkboxscale, frameColor = (0,0,0,0), command = self.cbParticles_CheckedChanged, rolloverSound = None, clickSound = None, pressEffect = False, boxPlacement = "below", boxBorder = 0.8, boxRelief = DGG.FLAT, indicator_scale = 1.5, indicator_text_fg = (0.65, 0.65, 0.0, 1), indicator_text_shadow = (0, 0, 0, 0.35), indicator_frameColor = (0.15, 0.15, 0.15, 1), indicatorValue = base.particleMgrEnabled ) self.cbParticles.indicator['text'] = (' ', 'x') self.cbParticles.indicator['text_pos'] = (0, 0.1) #self.cbParticles.indicator.setX(self.cbParticles.indicator, -0.5) #self.cbParticles.indicator.setZ(self.cbParticles.indicator, -0.1) #self.cbParticles.setFrameSize() self.cbParticles.setTransparency(1) self.cbParticles.reparentTo(self.frameMain) volume = base.musicManager.getVolume() self.sliderVolume = DirectSlider( scale = sliderscale, pos = (left, 0, -0.35), range = (0,1), scrollSize = 0.01, text = _("Volume %d%%")%volume*100, text_scale = textscale, text_align = TextNode.ACenter, text_pos = (.0, 0.15), text_fg = (1,1,1,1), thumb_frameColor = (0.65, 0.65, 0.0, 1), thumb_relief = DGG.FLAT, frameColor = (0.15, 0.15, 0.15, 1), value = volume, command = self.sliderVolume_ValueChanged) self.sliderVolume.reparentTo(self.frameMain) self.lblControltype = DirectLabel( text = _("Control type"), text_fg = (1, 1, 1, 1), text_shadow = (0, 0, 0, 0.35), frameColor = (0, 0, 0, 0), scale = textscale/2, pos = (right, 0, 0.27)) self.lblControltype.setTransparency(1) self.lblControltype.reparentTo(self.frameMain) selectedControlType = 0 if base.controlType == "MouseAndKeyboard": selectedControlType = 1 self.controltype = DirectOptionMenu( pos = (right, 0, 0.18), text_fg = (1, 1, 1, 1), scale = 0.1, items = [_("Keyboard"),_("Keyboard + Mouse")], initialitem = selectedControlType, frameColor = (0.15, 0.15, 0.15, 1), popupMarker_frameColor = (0.65, 0.65, 0.0, 1), popupMarker_relief = DGG.FLAT, highlightColor = (0.65, 0.65, 0.0, 1), relief = DGG.FLAT, command=self.controlType_Changed) self.controltype.reparentTo(self.frameMain) b = self.controltype.getBounds() xPos = right - ((b[1] - b[0]) / 2.0 * 0.1) self.controltype.setX(xPos) setItems(self.controltype) self.controltype.setItems = setItems self.controltype.showPopupMenu = showPopupMenu self.controltype.popupMarker.unbind(DGG.B1PRESS) self.controltype.popupMarker.bind(DGG.B1PRESS, showPopupMenu) self.controltype.unbind(DGG.B1PRESS) self.controltype.bind(DGG.B1PRESS, showPopupMenuExtra, [self.controltype]) isChecked = not base.AppHasAudioFocus img = None if base.AppHasAudioFocus: img = "AudioSwitch_on.png" else: img = "AudioSwitch_off.png" self.cbVolumeMute = DirectCheckBox( text = _("Mute Audio"), text_scale = 0.5, text_align = TextNode.ACenter, text_pos = (0.0, 0.65), text_fg = (1,1,1,1), pos = (right, 0, -0.35), scale = 0.21/2.0, command = self.cbVolumeMute_CheckedChanged, rolloverSound = None, clickSound = None, relief = None, pressEffect = False, isChecked = isChecked, image = img, image_scale = 0.5, checkedImage = "AudioSwitch_off.png", uncheckedImage = "AudioSwitch_on.png") self.cbVolumeMute.setTransparency(1) self.cbVolumeMute.setImage() self.cbVolumeMute.reparentTo(self.frameMain) sensitivity = base.mouseSensitivity self.sliderSensitivity = DirectSlider( scale = sliderscale, pos = (right, 0, -0.075), range = (0.5,2), scrollSize = 0.01, text = _("Mouse Sensitivity %0.1fx")%sensitivity, text_scale = textscale, text_align = TextNode.ACenter, text_pos = (.0, 0.15), text_fg = (1,1,1,1), thumb_frameColor = (0.65, 0.65, 0.0, 1), thumb_relief = DGG.FLAT, frameColor = (0.15, 0.15, 0.15, 1), value = sensitivity, command = self.sliderSensitivity_ValueChanged) self.sliderSensitivity.reparentTo(self.frameMain) if base.controlType == "Gamepad": self.sliderSensitivity.hide() # create the back button self.btnBack = DirectButton( scale = buttonScale, # position on the window pos = (0, 0, base.a2dBottom + 0.15), frameColor = (0,0,0,0), # text properties text = _("Back"), text_scale = 0.5, text_fg = (1,1,1,1), text_pos = (0.0, -0.15), text_shadow = (0, 0, 0, 0.35), text_shadowOffset = (-0.05, -0.05), # sounds that should be played rolloverSound = None, clickSound = None, pressEffect = False, relief = None, # the event which is thrown on clickSound command = lambda: base.messenger.send("options_back")) self.btnBack.setTransparency(1) self.btnBack.reparentTo(self.frameMain) self.hide() def show(self, enableResume=False): self.frameMain.show() def hide(self): self.frameMain.hide() def cbVolumeMute_CheckedChanged(self, checked): if checked: base.disableAllAudio() else: base.enableAllAudio() def sliderVolume_ValueChanged(self): volume = round(self.sliderVolume["value"], 2) self.sliderVolume["text"] = _("Volume %d%%") % int(volume * 100) base.sfxManagerList[0].setVolume(volume) base.musicManager.setVolume(volume) def sliderSensitivity_ValueChanged(self): sensitivity = round(self.sliderSensitivity["value"], 2) self.sliderSensitivity["text"] = _("Mouse Sensitivity %0.1fx") % sensitivity base.mouseSensitivity = sensitivity def sliderTextspeed_ValueChanged(self): newSpeed = round(self.sliderTextspeed["value"], 2) displaySpeed = 1.0 / newSpeed self.sliderTextspeed["text"] = _("Textspeed %0.1f%%")%displaySpeed base.textWriteSpeed = newSpeed def cbParticles_CheckedChanged(self, unchecked): if unchecked: base.enableParticles() else: base.disableParticles() def controlType_Changed(self, arg): if arg == _("Keyboard"): self.sliderSensitivity.hide() base.controlType = "Gamepad" elif arg == _("Keyboard + Mouse"): self.sliderSensitivity.show() base.controlType = "MouseAndKeyboard"
class CharacterSelection: def __init__(self): self.frameMain = DirectFrame( frameSize = (base.a2dLeft, base.a2dRight, base.a2dTop, base.a2dBottom), frameColor = (0.05, 0.05, 0.05, 1)) self.frameMain.setTransparency(1) width = abs(base.a2dLeft) + base.a2dRight red = loader.loadTexture("assets/gui/CharRedBG.png") red.setWrapU(Texture.WM_repeat) red.setWrapV(Texture.WM_repeat) self.char1Frame = DirectFrame( text = "Player 1", text_fg = (1,1,1,1), text_scale = 0.1, text_pos = (0, base.a2dTop - 0.2), frameSize = (-width/6.0, width/6.0, base.a2dTop, base.a2dBottom), frameTexture = red, pos = (base.a2dLeft+width/6.0, 0, 0)) self.char1Frame.updateFrameStyle() self.char1Frame.setTransparency(1) self.char1Frame.reparentTo(self.frameMain) blue = loader.loadTexture("assets/gui/CharBlueBG.png") blue.setWrapU(Texture.WM_repeat) blue.setWrapV(Texture.WM_repeat) self.char2Frame = DirectFrame( text = "Player 2", text_fg = (1,1,1,1), text_scale = 0.1, text_pos = (0, base.a2dTop - 0.2), frameSize = (-width/6.0, width/6.0, base.a2dTop, base.a2dBottom), frameTexture = blue, pos = (base.a2dRight-width/6.0, 0, 0)) self.char2Frame.setTransparency(1) self.char2Frame.reparentTo(self.frameMain) self.footerFrame = DirectFrame( text = "PLAYER 1 - CHOOSE YOUR CHARACTER", text_fg = (1,1,1,1), text_scale = 0.08, text_pos = (0, -0.03), frameSize = (base.a2dLeft, base.a2dRight, -0.1, 0.1), pos = (0, 0, base.a2dBottom + 0.2), frameColor = (0, 0, 0, 0.5)) self.footerFrame.setTransparency(1) self.footerFrame.reparentTo(self.frameMain) self.charSelectFrame = DirectFrame( text = "VS", text_fg = (1,1,1,1), text_scale = 0.1, text_pos = (0, base.a2dTop - 0.2), frameSize = (-width/6.0, width/6.0, base.a2dTop, base.a2dBottom), frameColor = (0,0,0,0)) self.charSelectFrame.reparentTo(self.frameMain) self.btnChar1 = self.createCharacterButton( (-0.2, 0, 0), "assets/gui/Char1Button.png", 1) self.btnChar1.reparentTo(self.charSelectFrame) self.btnChar2 = self.createCharacterButton( (0.2, 0, 0), "assets/gui/Char2Button.png", 2) self.btnChar2.reparentTo(self.charSelectFrame) self.btnBack = DirectButton( text = "BACK", text_fg = (1,1,1,1), text_align = TextNode.ALeft, scale = 0.1, pad = (0.15, 0.15), pos = (base.a2dLeft + 0.08, 0, -0.03), frameColor = ( (0.2,0.2,0.2,0.8), (0.4,0.4,0.4,0.8), (0.4,0.4,0.4,0.8), (0.1,0.1,0.1,0.8)), relief = 1, command = base.messenger.send, extraArgs = ["CharSelection-Back"], pressEffect = False, rolloverSound = None, clickSound = None) self.btnBack.setTransparency(1) self.btnBack.reparentTo(self.footerFrame) self.btnStart = DirectButton( text = "START", text_fg = (1,1,1,1), text_align = TextNode.ARight, scale = 0.1, pad = (0.15, 0.15), pos = (base.a2dRight - 0.08, 0, -0.03), relief = 1, frameColor = ( (0.2,0.2,0.2,0.8), (0.4,0.4,0.4,0.8), (0.4,0.4,0.4,0.8), (0.1,0.1,0.1,0.8)), command = base.messenger.send, extraArgs = ["CharSelection-Start"], pressEffect = False, rolloverSound = None, clickSound = None) self.btnStart.setTransparency(1) self.btnStart.reparentTo(self.footerFrame) self.btnStart["state"] = DGG.DISABLED self.hide() def createCharacterButton(self, pos, image, charNr): btn = DirectButton( scale = 0.1, relief = 0, frameColor = (0,0,0,0), pos = pos, image = image, command = self.selectCharacter, extraArgs = [charNr], rolloverSound = None, clickSound = None) btn.setTransparency(1) return btn def selectCharacter(self, charNr): if self.char1Frame["image"] == None: self.char1Frame["image"] = "assets/gui/Char%d_L.png" % charNr self.char1Frame["image_scale"] = (0.5,1, 1) self.selectedCharacter1 = charNr self.footerFrame["text"] = "PLAYER 2 - CHOOSE YOUR CHARACTER" elif self.char2Frame["image"] == None: self.char2Frame["image"] = "assets/gui/Char%d_R.png" % charNr self.char2Frame["image_scale"] = (0.5,1, 1) self.selectedCharacter2 = charNr self.btnStart["state"] = DGG.NORMAL self.footerFrame["text"] = "START THE FIGHT >" def show(self): self.selectedCharacter1 = None self.selectedCharacter2 = None self.char1Frame["image"] = None self.char2Frame["image"] = None self.footerFrame["text"] = "PLAYER 1 - CHOOSE YOUR CHARACTER" self.btnStart["state"] = DGG.DISABLED self.frameMain.show() def hide(self): self.frameMain.hide()
class Journal: """Captain's journal GUI object. Args: winned (bool): Flag, saying if the player already won the game. """ def __init__(self, winned=False): self._is_shown = False self._read_coordinates = False self._winned = winned self._opened_num = None self._main_fr = DirectFrame( parent=base.a2dTopLeft, # noqa: F821 frameSize=(-0.37, 0.38, -0.6, 0.6), state=DGG.NORMAL, pos=(0.37, 0, -1), frameTexture="gui/tex/paper1.png", ) self._main_fr.setTransparency(TransparencyAttrib.MAlpha) self._main_fr.hide() self._fr = DirectScrolledFrame( parent=self._main_fr, frameSize=(-0.35, 0.3, -0.46, 0.5), frameColor=(0, 0, 0, 0), canvasSize=(-0.31, 0.3, -3, 1.5), state=DGG.NORMAL, pos=(0, 0, -0.1), verticalScroll_frameSize=(-0.003, 0.003, -0.5, 0.5), verticalScroll_frameColor=(0.46, 0.41, 0.37, 1), verticalScroll_thumb_frameColor=(0.31, 0.26, 0.22, 1), verticalScroll_incButton_relief=None, verticalScroll_decButton_relief=None, horizontalScroll_relief=None, horizontalScroll_thumb_relief=None, horizontalScroll_incButton_relief=None, horizontalScroll_decButton_relief=None, ) DirectLabel( # Journal parent=self._main_fr, text=base.labels.JOURNAL[0], # noqa: F821 text_font=base.cursive_font, # noqa: F821 text_scale=0.053, text_bg=(0, 0, 0, 0), text_fg=(0, 0, 0.25, 1), frameSize=(0.1, 0.1, 0.1, 0.1), pos=(-0.34, 0, 0.52), text_align=TextNode.ALeft, ) DirectButton( parent=self._main_fr, text="<", text_scale=0.06, text_bg=(0, 0, 0, 0), text_fg=(0, 0, 0.25, 1), pos=(-0.15, 0, 0.45), frameSize=(-0.2, 0.2, -0.2, 0.2), relief=None, command=self._open_page, extraArgs=[-1], ) DirectButton( parent=self._main_fr, text=">", text_scale=0.06, text_bg=(0, 0, 0, 0), text_fg=(0, 0, 0.25, 1), pos=(0.15, 0, 0.45), frameSize=(-0.2, 0.2, -0.2, 0.2), relief=None, command=self._open_page, extraArgs=[1], ) self._page_title = DirectLabel( parent=self._main_fr, text="", text_scale=0.043, text_font=base.cursive_font, # noqa: F821 text_fg=(0, 0, 0.25, 1), frameSize=(-0.02, 0.02, -3.5, 0.5), frameColor=(0, 0, 0, 0), pos=(0, 0, 0.45), ) self._page_text = DirectLabel( parent=self._fr.getCanvas(), text="", text_scale=0.045, text_font=base.cursive_font, # noqa: F821 text_align=TextNode.ALeft, text_fg=(0, 0, 0.25, 1), frameSize=(-0.02, 0.02, -3.5, 0.5), frameColor=(0, 0, 0, 0), pos=(-0.27, 0, 1.45), ) self._pages = [] self._open_snd = loader.loadSfx("sounds/GUI/journal.ogg") # noqa: F821 self._page_snd = loader.loadSfx("sounds/GUI/journal_page.ogg") # noqa: F821 self._close_snd = loader.loadSfx("sounds/GUI/journal_close.ogg") # noqa: F821 @property def winned(self): """The flag indicating if the player already won. Returns: bool: True if the player already won, False otherwise. """ return self._winned def _open_page(self, shift): """Open the given page of the journal. Args: shift (int): Page number shift. """ if self._opened_num is None: return if ( self._opened_num + shift > len(self._pages) - 1 or self._opened_num + shift < 0 ): return self._opened_num += shift self._page_text["text"] = self._pages[self._opened_num]["page"] self._page_title["text"] = self._pages[self._opened_num]["title"] self._page_snd.play() if self._opened_num == 7: self._read_coordinates = True def add_page(self, num): """Add a page into the journal. Args: num (int): The page number. """ type_, title, page_text = base.labels.JOURNAL_PAGES[num] # noqa: F821 page_rec = {"page": page_text, "type": type_, "title": title} self._pages.append(page_rec) if self._opened_num is None: self._opened_num = 0 self._page_text["text"] = self._pages[self._opened_num]["page"] self._page_title["text"] = self._pages[self._opened_num]["title"] def show(self): """Show/hide the journal GUI.""" if self._is_shown: self._main_fr.hide() self._close_snd.play() if not self._winned and self._read_coordinates: self._winned = True page = DirectFrame( frameSize=(-0.73, 0.73, -0.9, 0.9), frameTexture="gui/tex/paper1.png", state=DGG.NORMAL, ) page.setDepthTest(False) page.setTransparency(TransparencyAttrib.MAlpha) page.show() DirectLabel( parent=page, text=base.labels.UNTERRIFF_DISCOVERED_TITLE, # noqa: F821 text_font=base.main_font, # noqa: F821 frameSize=(0.6, 0.6, 0.6, 0.6), text_scale=0.043, pos=(0, 0, 0.65), ) DirectLabel( parent=page, text=base.labels.UNTERRIFF_DISCOVERED, # noqa: F821 text_font=base.main_font, # noqa: F821 frameSize=(0.6, 0.6, 0.6, 0.6), text_scale=0.037, pos=(0, 0, 0.55), ) DirectButton( # Done parent=page, pos=(0, 0, -0.77), text=base.labels.DISTINGUISHED[6], # noqa: F821 text_font=base.main_font, # noqa: F821 text_fg=RUST_COL, text_shadow=(0, 0, 0, 1), frameColor=(0, 0, 0, 0), command=page.destroy, extraArgs=[], scale=(0.05, 0, 0.05), clickSound=base.main_menu.click_snd, # noqa: F821 ) self._read_coordinates = False else: self._main_fr.show() self._open_snd.play() self._is_shown = not self._is_shown
class TraitsGUI: """GUI to praise/scold characters. This GUI gives players an opportunity to control their characters' traits. """ def __init__(self): self._cur_char = None self._ind_chosen = None self._new_chosen = False self._need_update = False self.is_shown = False self._cur_traits = [] self._new_traits = [] self._open_snd = loader.loadSfx("sounds/GUI/paper1.ogg") # noqa: F821 self._close_snd = loader.loadSfx("sounds/GUI/paper2.ogg") # noqa: F821 self._scold_snd = loader.loadSfx("sounds/GUI/scold.ogg") # noqa: F821 self._praise_snd = loader.loadSfx( "sounds/GUI/praise.ogg") # noqa: F821 self._list = DirectFrame( frameSize=(-0.75, 0.75, -0.77, 0.77), frameTexture=GUI_PIC + "paper1.png", state=DGG.NORMAL, ) self._list.setDepthTest(False) self._list.setTransparency(TransparencyAttrib.MAlpha) self._list.hide() DirectLabel( # List of distinguished parent=self._list, text=base.labels.DISTINGUISHED[0], # noqa: F821 text_font=base.main_font, # noqa: F821 frameSize=(0.4, 0.4, 0.4, 0.4), text_scale=0.045, pos=(-0.35, 0, 0.65), ) DirectLabel( # the praise/scold mechanisms description parent=self._list, text=base.labels.DISTINGUISHED[1], # noqa: F821 text_font=base.main_font, # noqa: F821 frameSize=(0.3, 0.3, 0.3, 0.3), text_scale=0.035, text_bg=(0, 0, 0, 0), pos=(0, 0, 0.54), ) self._char_chooser = CharacterChooser(is_shadowed=True) DirectLabel( # Cohesion points: parent=self._list, text=base.labels.DISTINGUISHED[2], # noqa: F821 text_font=base.main_font, # noqa: F821 frameSize=(0.1, 0.1, 0.1, 0.1), text_scale=0.035, text_bg=(0, 0, 0, 0), pos=(0.3, 0, 0.065), ) self._cohesion_pts = DirectLabel( parent=self._list, text="", frameSize=(0.1, 0.1, 0.1, 0.1), text_scale=0.035, text_bg=(0, 0, 0, 0), pos=(0.47, 0, 0.065), ) self._cur_traits_num = DirectLabel( # Current traits parent=self._list, text="", text_font=base.main_font, # noqa: F821 frameSize=(0.1, 0.1, 0.1, 0.1), text_scale=0.032, text_bg=(0, 0, 0, 0), pos=(0.3, 0, -0.08), ) DirectLabel( # New traits: parent=self._list, text=base.labels.DISTINGUISHED[3], # noqa: F821 text_font=base.main_font, # noqa: F821 frameSize=(0.1, 0.1, 0.1, 0.1), text_scale=0.032, text_bg=(0, 0, 0, 0), pos=(-0.35, 0, -0.08), ) traits_fr = DirectFrame( parent=self._list, frameSize=(-0.65, 0.6, -0.18, 0.2), pos=(0, 0, -0.32), frameColor=(0, 0, 0, 0.3), ) shift = 0.15 for index in range(3): self._cur_traits.append(( DirectButton( pos=(0.3, 0, shift), text="", text_fg=SILVER_COL, text_scale=0.032, text_font=base.main_font, # noqa: F821 parent=traits_fr, frameSize=(-0.2, 0.2, -0.05, 0.05), relief=None, command=self._choose_trait, extraArgs=[self._cur_traits, self._new_traits, index], ), DirectButton( pos=(0.3, 0, shift - 0.045), text="", text_fg=SILVER_COL, text_scale=0.027, text_font=base.main_font, # noqa: F821 parent=traits_fr, frameSize=(-0.2, 0.2, -0.05, 0.05), relief=None, command=self._choose_trait, extraArgs=[self._cur_traits, self._new_traits, index], ), )) self._new_traits.append(( DirectButton( pos=(-0.35, 0, shift), text="", text_fg=SILVER_COL, text_scale=0.032, text_font=base.main_font, # noqa: F821 parent=traits_fr, frameSize=(-0.2, 0.2, -0.05, 0.05), relief=None, command=self._choose_trait, extraArgs=[self._new_traits, self._cur_traits, index], ), DirectButton( pos=(-0.35, 0, shift - 0.045), text="", text_fg=SILVER_COL, text_scale=0.027, text_font=base.main_font, # noqa: F821 parent=traits_fr, frameSize=(-0.2, 0.2, -0.05, 0.05), relief=None, command=self._choose_trait, extraArgs=[self._new_traits, self._cur_traits, index], ), )) shift -= 0.12 self._add_but = DirectButton( pos=(0, 0, 0), text=">", text_fg=SILVER_COL, parent=traits_fr, frameColor=(0, 0, 0, 0), relief=None, scale=(0.06, 0, 0.07), clickSound=base.main_menu.click_snd, # noqa: F821 ) self._praise_but = DirectButton( pos=(-0.35, 0, -0.57), text=base.labels.DISTINGUISHED[4], # noqa: F821 text_font=base.main_font, # noqa: F821 text_fg=RUST_COL, text_shadow=(0, 0, 0, 1), frameColor=(0, 0, 0, 0), parent=self._list, command=self._gen_new_traits, scale=(0.04, 0, 0.04), clickSound=base.main_menu.click_snd, # noqa: F821 ) self._scold_but = DirectButton( pos=(0.3, 0, -0.57), text=base.labels.DISTINGUISHED[5], # noqa: F821 text_font=base.main_font, # noqa: F821 text_fg=SILVER_COL, text_shadow=(0, 0, 0, 1), frameColor=(0, 0, 0, 0), parent=self._list, scale=(0.04, 0, 0.04), clickSound=base.main_menu.click_snd, # noqa: F821 ) DirectButton( pos=(-0.02, 0, -0.7), text=base.labels.DISTINGUISHED[6], # noqa: F821 text_font=base.main_font, # noqa: F821 text_fg=RUST_COL, text_shadow=(0, 0, 0, 1), frameColor=(0, 0, 0, 0), parent=self._list, scale=(0.04, 0, 0.04), clickSound=base.main_menu.click_snd, # noqa: F821 command=self.hide, ) def _add_trait(self): """Add the chosen new trait to character's traits.""" if not self._new_chosen or self._ind_chosen is None: return char = self._char_chooser.chosen_item if len(char.traits) == 3: return self._praise_snd.play() char.traits.append(self._new_traits[self._ind_chosen][0]["text"]) for but_pair in self._new_traits: but_pair[0]["text"] = "" but_pair[1]["text"] = "" self._add_but["text_fg"] = SILVER_COL self._add_but["command"] = None self._need_update = True self._ind_chosen = None base.char_gui.move_status_label(-1) # noqa: F821 def _choose_trait(self, traits, clear_traits, ch_index): """Highlight the trait on which the player clicked. Args: traits (list): List of traits, one of which was chosen. clear_traits (list): List of traits, which highlight must be dropped. ch_index (int): Index of the chosen trait. """ self._ind_chosen = ch_index self._new_chosen = traits == self._new_traits if self._new_chosen: self._add_but["text_fg"] = RUST_COL self._add_but["command"] = self._add_trait self._scold_but["text_fg"] = SILVER_COL self._scold_but["command"] = None else: self._scold_but["text_fg"] = RUST_COL self._scold_but["command"] = self._scold self._add_but["text_fg"] = SILVER_COL self._add_but["command"] = None for index in range(len(traits)): clear_traits[index][0]["text_fg"] = SILVER_COL clear_traits[index][1]["text_fg"] = SILVER_COL if index == ch_index: traits[index][0]["text_fg"] = RUST_COL traits[index][1]["text_fg"] = RUST_COL else: traits[index][0]["text_fg"] = SILVER_COL traits[index][1]["text_fg"] = SILVER_COL def _gen_new_traits(self): """Generate new traits on praise. One of these traits player can choose to add to the character's traits list. """ if base.team.cohesion < 5: # noqa: F821 return char = self._char_chooser.chosen_item pos_traits = list(base.labels.TRAIT_DESC.keys()) # noqa: F821 for trait in char.traits + char.disabled_traits: pos_traits.remove(trait) for index in range(3): new_trait = take_random(pos_traits) self._new_traits[index][0]["text"] = new_trait self._new_traits[index][0]["text_fg"] = SILVER_COL self._new_traits[index][1][ "text"] = base.labels.TRAIT_DESC[ # noqa: F821 new_trait] self._new_traits[index][1]["text_fg"] = SILVER_COL base.team.spend_cohesion(4) # noqa: F821 def _scold(self): """Erase the chosen character's trait.""" if self._new_chosen or base.team.cohesion < 4: # noqa: F821 return self._scold_snd.play() trait = self._cur_traits[self._ind_chosen][0]["text"] char = self._char_chooser.chosen_item if trait in char.traits: char.traits.remove(trait) if trait in char.disabled_traits: char.disabled_traits.remove(trait) self._ind_chosen = None self._need_update = True base.char_gui.move_status_label(1) # noqa: F821 self._scold_but["text_fg"] = SILVER_COL self._scold_but["command"] = None base.team.spend_cohesion(4) # noqa: F821 def _update_traits(self, task): """Update the list of the character's traits.""" self._cohesion_pts["text"] = str(int(base.team.cohesion)) # noqa: F821 if self._char_chooser.chosen_item == self._cur_char and not self._need_update: return task.again self._need_update = False self._cur_char = self._char_chooser.chosen_item self._scold_but["text_fg"] = SILVER_COL self._scold_but["command"] = None traits = self._cur_char.traits + self._cur_char.disabled_traits self._cur_traits_num["text"] = "{label} ({num}/3):".format( label=base.labels.DISTINGUISHED[7], num=str(len(traits)) # noqa: F821 ) if len(traits) == 3: self._praise_but["text_fg"] = SILVER_COL self._praise_but["command"] = None else: self._praise_but["text_fg"] = RUST_COL self._praise_but["command"] = self._gen_new_traits for index in range(3): if index + 1 <= len(traits): trait = traits[index] self._cur_traits[index][0]["text"] = trait self._cur_traits[index][0]["text_fg"] = SILVER_COL self._cur_traits[index][1][ "text"] = base.labels.TRAIT_DESC[ # noqa: F821 trait] self._cur_traits[index][1]["text_fg"] = SILVER_COL else: self._cur_traits[index][0]["text"] = "" self._cur_traits[index][0]["text_fg"] = SILVER_COL self._cur_traits[index][1]["text"] = "" self._cur_traits[index][1]["text_fg"] = SILVER_COL return task.again def hide(self): """Hide the GUI.""" if self.is_shown: taskMgr.remove("update_traits_ctrl") # noqa: F821 base.char_gui.clear_char_info() # noqa: F821 self._list.hide() self.is_shown = False taskMgr.doMethodLater( # noqa: F821 0.07, self._close_snd.play, "play_close_snd", extraArgs=[]) def show(self): """Show the GUI.""" if (self.is_shown or base.world.outings_mgr.gui_is_shown # noqa: F821 or base.world.rails_scheme.is_shown # noqa: F821 ): return self._open_snd.play() self.is_shown = True char_id = base.char_gui.char.id # noqa: F821 base.common_ctrl.deselect() # noqa: F821 self._char_chooser.prepare( self._list, (-0.25, 0, 0.08), base.team.chars, # noqa: F821 list(base.team.chars.keys()).index(char_id), # noqa: F821 ) self._list.show() taskMgr.doMethodLater( # noqa: F821 0.25, self._update_traits, "update_traits_ctrl")
class ClassPicker(): """ A user interface that lets the character choose a class. 4 Classes are drawn and only one at a time can be toggled/selected """ def __init__(self, classSelectionMenu): self._classSelectionMenu = classSelectionMenu self._font = loader.loadFont(PIERCEROMAN_FONT) self._selectedClass = None self._containFrame = None self._infoText = None self._draw() def _draw(self): winWidth = base.getAspectRatio() * 2 winHeight = 2 # Draw main container: cFSizeX, cFSizeY = winWidth / 4, winHeight * (3 / 4) self._containFrame = DirectFrame(pos=(0, 0, cFSizeY * (2 / 3)), frameSize=(-cFSizeX, cFSizeX, -cFSizeY, 0), frameTexture=UI_WINDOW) self._containFrame.setTransparency(TransparencyAttrib.MAlpha) # Title: titleWidth, titleHeight = cFSizeX - CPKR_CONTROL_SIDES_MARGIN,\ cFSizeY*CPKR_TITLE_HEIGHT_RATIO titleFontSize = (0.15, 0.15) title = DirectLabel(parent=self._containFrame, pos=(0, 0, -CPKR_CONTROL_TOP_MARGIN), frameSize=(-titleWidth, titleWidth, -titleHeight, 0), text_align=TextNode.ACenter, text_font=self._font, text_scale=titleFontSize, text_pos=CPKR_PIERCEROMAN_OFFSET_TC, text="Choose a Class!", frameTexture=IMG_GRADIENT_1) # Information Box: infoHeight = cFSizeY * CPKR_INFO_HEIGHT_RATIO # Calculate Button Frame vertical size first! bFSizeY = cFSizeY - (CPKR_CONTROL_TOP_MARGIN*2 + titleHeight\ + infoHeight) self._infoText = DirectLabel(parent=self._containFrame, pos=(0, 0, -CPKR_CONTROL_TOP_MARGIN - titleHeight - bFSizeY), frameSize=(-titleWidth, titleWidth,\ -infoHeight, 0), text_align=TextNode.ALeft, text_font=self._font, text_scale=CPKR_INFO_FONT_SIZE_DEFAULT, text_pos=CPKR_PIERCEROMAN_OFFSET_TL, text_wordwrap=CPKR_INFO_WRAP_DEFAULT, frameColor=(1,1,1,0.8), text="Please select a class above") # Class Radio Button Frame: bFColor = (0.25, 0.25, 0.25, 0.5) bFWidth = self._containFrame.getWidth()\ *CPKR_BUTTONCONTAINER_WIDTH_PERCENTAGE buttonFrame = DirectFrame(parent=self._containFrame, pos=(0, 0, -CPKR_CONTROL_TOP_MARGIN - titleHeight), frameSize=(-bFWidth / 2, bFWidth / 2, -bFSizeY, 0), frameColor=bFColor) # Create Class Radio Buttons: (Buttons are height dependent) bSizeY = (buttonFrame.getHeight() - CPKR_BUTTONCONTAINER_MARGIN*2)\ / len(CPKR_CLASSES_LIST) bSizeX = (buttonFrame.getWidth() - CPKR_BUTTONCONTAINER_MARGIN*2)\ / len(CPKR_CLASSES_LIST[0]) for row in range(len(CPKR_CLASSES_LIST)): for col in range(len(CPKR_CLASSES_LIST[row])): buttonClass = CPKR_CLASSES_LIST[row][col] buttonImage = buttonClass.classIcon buttonID = buttonClass.classID verticalPos = -CPKR_BUTTONCONTAINER_MARGIN - bSizeY * col horizontalPos = -CPKR_BUTTONCONTAINER_MARGIN * 2 + bSizeX * row newButton = DirectButton(parent=buttonFrame, pos=(horizontalPos, 0, verticalPos), frameSize=(-bSizeX / 2, bSizeX / 2, -bSizeY, 0), frameTexture=buttonImage, relief=DGG.FLAT, command=self._selectClass, extraArgs=[buttonID]) def _selectClass(self, chosenClass): """ Selects the given class and updates the info text """ self._selectedClass = chosenClass # Just the ID actualClass = CLASSES_DICT[self._selectedClass] self._infoText['text'] = actualClass.classDesc self._infoText['text_scale'] = actualClass.classDescFontSize self._infoText['text_wordwrap'] = actualClass.classDescWrap self._classSelectionMenu.syncInfo(cClass=self._selectedClass) def getSelected(self): return self._selectedClass def close(self): self._containFrame.destroy() # Destroy root UI del self # Destroy this instance
class Menu(DirectObject): def __init__(self): self.accept("window-event", self.recalcAspectRatio) self.frameMain = DirectFrame( # size of the frame frameSize = (base.a2dLeft, base.a2dRight, base.a2dTop, base.a2dBottom), # position of the frame image = "LogoTextGlow.png", image_scale = (1.06, 1, 0.7), image_pos = (0, 0, 0.25), pos = (0, 0, 0), # tramsparent bg color frameColor = (0, 0, 0, 0), sortOrder = 0) self.frameMain.setTransparency(1) self.frameMain.setBin("fixed", 100) btnGeom = None self.btnStart = self.createButton(_("Start"), btnGeom, -0.6, self.btnStart_Click) self.btnStart.reparentTo(self.frameMain) self.btnOptions = self.createButton(_("Options"), btnGeom, 0, self.btnOptions_Click) self.btnOptions.reparentTo(self.frameMain) self.btnQuit = self.createButton(_("Quit"), btnGeom, 0.6, self.btnQuit_Click) self.btnQuit.reparentTo(self.frameMain) self.recalcAspectRatio(base.win) # hide all buttons at startup self.hide() def show(self): self.frameMain.show() self.recalcAspectRatio(base.win) def hide(self): self.frameMain.hide() def recalcAspectRatio(self, window): """get the new aspect ratio to resize the mainframe""" screenResMultiplier = window.getXSize() / window.getYSize() self.frameMain["frameSize"] = ( base.a2dLeft, base.a2dRight, base.a2dTop, base.a2dBottom) self.btnQuit["text_scale"] = (0.5*screenResMultiplier, 0.5, 0.5) self.btnStart["text_scale"] = (0.5*screenResMultiplier, 0.5, 0.5) def createButton(self, text, btnGeom, xPos, command): btn = DirectButton( scale = (0.25, 0.25, 0.25), # some temp text text = text, text_scale = (0.5, 0.5, 0.5), # set the alignment to right text_align = TextNode.ACenter, # put the text on the right side of the button text_pos = (0, -0.15), # set the text color to black text_fg = (1,1,1,1), text_shadow = (0.3, 0.3, 0.1, 1), text_shadowOffset = (0.05, 0.05), # set the buttons images #geom = btnGeom, relief = 1, frameColor = (0,0,0,0), pressEffect = False, pos = (xPos, 0, -0.65), command = command, rolloverSound = None, clickSound = None) btn.setTransparency(1) return btn def btnStart_Click(self): base.messenger.send("menu_start") def btnOptions_Click(self): base.messenger.send("menu_options") def btnQuit_Click(self): base.messenger.send("menu_quit")
class CityGUI: """City GUI. Includes several services: healing and regaining energy of the player characters, recruiting new characters, repairing the locomotive, buying the locomotive upgrades. """ def __init__(self): self._temp_wids = [] self._recruits = [] self._reward_fr = None self.visit_num = 1 self._amb_snd = loader.loadSfx( "sounds/hangar_ambient.ogg") # noqa: F821 self._amb_snd.setVolume(0) self._amb_snd.setLoop(True) self._coins_s_snd = loader.loadSfx( "sounds/GUI/coins_short.ogg") # noqa: F821 self._coins_l_snd = loader.loadSfx( "sounds/GUI/coins_long.ogg") # noqa: F821 self._toot_snd = loader.loadSfx("sounds/train/toot1.ogg") # noqa: F821 self._add_upgrade_snd = loader.loadSfx( # noqa: F821 "sounds/GUI/install_upgrade.ogg") self.write_snd = loader.loadSfx("sounds/GUI/write.ogg") # noqa: F821 self._fr = DirectFrame( parent=base.a2dTopLeft, # noqa: F821 frameSize=(-0.35, 0.35, -0.4, 0.7), pos=(0.85, 0, -0.82), frameTexture=GUI_PIC + "metal1.png", state=DGG.NORMAL, ) self._fr.setTransparency(TransparencyAttrib.MAlpha) self._fr.hide() DirectLabel( # Services parent=self._fr, text=base.labels.CITY[0], # noqa: F821 text_font=base.main_font, # noqa: F821 frameSize=(0.1, 0.1, 0.1, 0.1), text_scale=0.045, text_fg=RUST_COL, pos=(0, 0, 0.62), ) self._party_but = DirectButton( # Party parent=self._fr, text_scale=0.035, text_fg=SILVER_COL, text=base.labels.CITY[1], # noqa: F821 text_font=base.main_font, # noqa: F821 relief=None, command=self._show_party, extraArgs=[0.56], pos=(-0.1, 0, 0.56), clickSound=base.main_menu.click_snd, # noqa: F821 ) base.main_menu.bind_button(self._party_but) # noqa: F821 self._train_but = DirectButton( # Train parent=self._fr, text_scale=0.035, text_fg=RUST_COL, text=base.labels.CITY[2], # noqa: F821 text_font=base.main_font, # noqa: F821 relief=None, command=self._show_train, extraArgs=[0.56], pos=(0.1, 0, 0.56), clickSound=base.main_menu.click_snd, # noqa: F821 ) base.main_menu.bind_button(self._train_but) # noqa: F821 base.main_menu.bind_button( # noqa: F821 DirectButton( # Exit city parent=self._fr, pos=(-0.205, 0, -0.35), text_fg=RUST_COL, text=base.labels.CITY[3], # noqa: F821 text_font=base.main_font, # noqa: F821 relief=None, text_scale=0.035, command=self._exit_city, )) base.main_menu.bind_button( # noqa: F821 DirectButton( # Turn around and exit parent=self._fr, pos=(0.1, 0, -0.35), text_fg=RUST_COL, text=base.labels.CITY[4], # noqa: F821 text_font=base.main_font, # noqa: F821 relief=None, text_scale=0.035, command=self._exit_city, extraArgs=[True], )) def _show_train(self, z_coor): """Show the locomotive management GUI tab. Args: z_coor (float): Z-coordinate for widgets. """ clear_wids(self._temp_wids) self._party_but["text_fg"] = RUST_COL self._train_but["text_fg"] = SILVER_COL z_coor -= 0.07 self._temp_wids.append( DirectLabel( # Locomotive parent=self._fr, text=base.labels.CITY[5], # noqa: F821 text_font=base.main_font, # noqa: F821 frameSize=(0.1, 0.1, 0.1, 0.1), text_scale=0.035, text_align=TextNode.ALeft, text_fg=RUST_COL, pos=(-0.3, 0, z_coor), )) z_coor -= 0.08 self._temp_wids.append( DirectLabel( # Repair parent=self._fr, frameColor=(0, 0, 0, 0.3), text_fg=SILVER_COL, text=base.labels.CITY[6], # noqa: F821 text_font=base.main_font, # noqa: F821 text_align=TextNode.ALeft, text_scale=0.03, pos=(-0.25, 0, z_coor), )) self._temp_wids.append( DirectButton( parent=self._fr, pos=(-0.05, 0, z_coor + 0.015), text_fg=SILVER_COL, text="+50\n10$", scale=(0.075, 0, 0.075), relief=None, text_scale=0.45, command=self._repair, extraArgs=[50], )) self._temp_wids.append( DirectButton( parent=self._fr, pos=(0.07, 0, z_coor + 0.015), text_fg=SILVER_COL, text="+200\n40$", scale=(0.075, 0, 0.075), relief=None, text_scale=0.45, command=self._repair, extraArgs=[200], )) z_coor -= 0.09 self._temp_wids.append( DirectLabel( # Upgrade parent=self._fr, text=base.labels.CITY[7], # noqa: F821 text_font=base.main_font, # noqa: F821 text_align=TextNode.ALeft, frameSize=(0.1, 0.1, 0.1, 0.1), text_scale=0.035, text_fg=RUST_COL, pos=(-0.3, 0, z_coor), )) up_desc = DirectLabel( parent=self._fr, text="", text_font=base.main_font, # noqa: F821 frameSize=(0.1, 0.1, 0.1, 0.1), text_scale=0.03, text_fg=SILVER_COL, pos=(-0.1, 0, z_coor - 0.14), ) self._temp_wids.append(up_desc) up_cost = DirectLabel( parent=self._fr, text="", frameSize=(0.1, 0.1, 0.1, 0.1), text_scale=0.035, text_fg=SILVER_COL, pos=(0.23, 0, z_coor - 0.17), ) self._temp_wids.append(up_cost) but = DirectButton( # Purchase parent=self._fr, pos=(0.2, 0, z_coor - 0.3), text_fg=RUST_COL, text=base.labels.CITY[8], # noqa: F821 text_font=base.main_font, # noqa: F821 relief=None, text_scale=0.035, command=self._purchase_upgrade, ) self._temp_wids.append(but) base.main_menu.bind_button(but) # noqa: F821 z_coor -= 0.05 self._up_chooser = UpgradeChooser(up_desc, up_cost) self._up_chooser.prepare( self._fr, (0, 0, z_coor), base.train.possible_upgrades(self.visit_num), # noqa: F821 ) self._temp_wids.append(self._up_chooser) def _purchase_upgrade(self): """Buy the chosen upgrade and install it on to the locomotive.""" upgrade = self._up_chooser.chosen_item if upgrade is None or not base.res_gui.check_enough_money( # noqa: F821 int(upgrade["cost"][:-1])): return base.main_menu.click_snd.play() # noqa: F821 self._add_upgrade_snd.play() base.dollars -= int(upgrade["cost"][:-1]) # noqa: F821 base.train.install_upgrade(upgrade) # noqa: F821 self._up_chooser.pop_upgrade(upgrade["name"]) def _show_party(self, shift): """Show units management tab. Args: shift (float): Z-coordinate. """ clear_wids(self._temp_wids) self._party_but["text_fg"] = SILVER_COL self._train_but["text_fg"] = RUST_COL shift -= 0.07 # the crew GUI self._temp_wids.append( DirectLabel( # Crew parent=self._fr, text=base.labels.CITY[9], # noqa: F821 text_font=base.main_font, # noqa: F821 text_align=TextNode.ALeft, frameSize=(0.1, 0.1, 0.1, 0.1), text_scale=0.035, text_fg=RUST_COL, pos=(-0.3, 0, shift), )) self._char_chooser = CharacterChooser() self._char_chooser.prepare( self._fr, (0, 0, 0.45), base.team.chars # noqa: F821 ) self._temp_wids.append(self._char_chooser) shift -= 0.14 self._temp_wids.append( DirectLabel( # Health parent=self._fr, frameColor=(0, 0, 0, 0.3), text_fg=SILVER_COL, text=base.labels.CHARACTERS[2], # noqa: F821 text_font=base.main_font, # noqa: F821 text_scale=0.03, pos=(-0.2, 0, shift), )) self._temp_wids.append( DirectButton( parent=self._fr, pos=(-0.05, 0, shift + 0.02), text_fg=SILVER_COL, text="+10\n10$", scale=(0.075, 0, 0.075), relief=None, text_scale=0.45, command=self._heal, extraArgs=[10], )) self._temp_wids.append( DirectButton( parent=self._fr, pos=(0.07, 0, shift + 0.02), text_fg=SILVER_COL, text="+50\n50$", scale=(0.075, 0, 0.075), relief=None, text_scale=0.45, command=self._heal, extraArgs=[50], )) shift -= 0.1 self._temp_wids.append( DirectLabel( # Energy parent=self._fr, frameColor=(0, 0, 0, 0.3), text_fg=SILVER_COL, text=base.labels.CHARACTERS[3], # noqa: F821 text_font=base.main_font, # noqa: F821 text_scale=0.03, pos=(-0.2, 0, shift), )) self._temp_wids.append( DirectButton( parent=self._fr, pos=(-0.05, 0, shift + 0.02), text_fg=SILVER_COL, text="+10\n5$", scale=(0.075, 0, 0.075), relief=None, text_scale=0.45, command=self._rest, extraArgs=[10], )) self._temp_wids.append( DirectButton( parent=self._fr, pos=(0.07, 0, shift + 0.02), text_fg=SILVER_COL, text="+50\n25$", scale=(0.075, 0, 0.075), relief=None, text_scale=0.45, command=self._rest, extraArgs=[50], )) shift -= 0.08 self._temp_wids.append( DirectButton( # Leave unit parent=self._fr, pos=(0.2, 0, shift), text_fg=SILVER_COL, text=base.labels.CITY[12], # noqa: F821 text_font=base.main_font, # noqa: F821 scale=(0.075, 0, 0.075), relief=None, text_scale=0.45, command=self._send_away, )) shift -= 0.08 # recruits gui self._temp_wids.append( DirectLabel( # Recruits parent=self._fr, text=base.labels.CITY[10], # noqa: F821 text_font=base.main_font, # noqa: F821 text_align=TextNode.ALeft, frameSize=(0.1, 0.1, 0.1, 0.1), text_scale=0.035, text_fg=RUST_COL, pos=(-0.3, 0, shift), )) shift -= 0.13 hire_but = DirectButton( # Hire unit parent=self._fr, pos=(0.2, 0, shift), text_fg=SILVER_COL, text=base.labels.CITY[13], # noqa: F821 text_font=base.main_font, # noqa: F821 scale=(0.075, 0, 0.075), relief=None, text_scale=0.45, command=self._hire, ) self._temp_wids.append(hire_but) self._recruit_chooser = RecruitChooser(hire_but) self._recruit_chooser.prepare(self._fr, (0, 0, 0.05), self._recruits) self._temp_wids.append(self._recruit_chooser) shift -= 0.08 # expendable resources self._temp_wids.append( DirectLabel( # Resources parent=self._fr, text=base.labels.CITY[11], # noqa: F821 text_font=base.main_font, # noqa: F821 text_align=TextNode.ALeft, frameSize=(0.1, 0.1, 0.1, 0.1), text_scale=0.035, text_fg=RUST_COL, pos=(-0.3, 0, shift), )) shift -= 0.12 buy_res_but = DirectButton( # Buy parent=self._fr, pos=(0.08, 0, shift), text_fg=SILVER_COL, text=base.labels.CITY[15], # noqa: F821 text_font=base.main_font, # noqa: F821 scale=(0.075, 0, 0.075), relief=None, text_scale=0.45, command=self._buy_supply, ) self._temp_wids.append(buy_res_but) sell_res_but = DirectButton( # Sell parent=self._fr, pos=(-0.08, 0, shift), text_fg=SILVER_COL, text=base.labels.CITY[14], # noqa: F821 text_font=base.main_font, # noqa: F821 scale=(0.075, 0, 0.075), relief=None, text_scale=0.45, command=self._sell_supply, ) self._temp_wids.append(sell_res_but) self._res_chooser = ResourceChooser(buy_res_but, sell_res_but) self._res_chooser.prepare( self._fr, (0, 0, -0.165), { base.labels.RESOURCES[1]: "medicine_boxes", # noqa: F821 base.labels.RESOURCES[5]: "stimulators", # noqa: F821 base.labels.RESOURCES[3]: "smoke_filters", # noqa: F821 }, ) self._temp_wids.append(self._res_chooser) def _buy_supply(self): """Buy the chosen resource.""" if not base.res_gui.check_enough_money( # noqa: F821 self._res_chooser.chosen_resource_cost): return random.choice((self._coins_s_snd, self._coins_l_snd)).play() base.dollars -= self._res_chooser.chosen_resource_cost # noqa: F821 base.plus_resource(self._res_chooser.chosen_item, 1) # noqa: F821 def _clear(self, turn_around): """Remove hangar scene and hide city GUI. Args: turn_around (bool): True, if the Train should be turned around. """ self._fr.hide() base.char_gui.clear_char_info() # noqa: F821 base.world.unload_hangar_scene(turn_around) # noqa: F821 def _sell_supply(self): """Sell the chosen resource.""" if not base.resource(self._res_chooser.chosen_item): # noqa: F821 return random.choice((self._coins_s_snd, self._coins_l_snd)).play() base.dollars += self._res_chooser.chosen_resource_cost # noqa: F821 base.plus_resource(self._res_chooser.chosen_item, -1) # noqa: F821 def _exit_city(self, turn_around=False): """Exit the current city. Hide city GUI, remove the hangar scene, return the Train back on railway. Args: turn_around (bool): True, if the Train should be turned around. """ self._toot_snd.play() self.visit_num += 1 taskMgr.remove("increase_city_snd") # noqa: F821 base.train.clear_upgrade_preview() # noqa: F821 taskMgr.doMethodLater(0.3, self._dec_amb_snd, "decrease_city_snd") # noqa: F821 taskMgr.doMethodLater( # noqa: F821 0.1, base.effects_mgr.fade_out_screen, "fade_out_screen" # noqa: F821 ) taskMgr.doMethodLater( # noqa: F821 3.1, self._clear, "clear_city_gui", extraArgs=[turn_around]) taskMgr.doMethodLater( # noqa: F821 2, base.train.resume_smoke, "resume_train_smoke" # noqa: F821 ) def _send_away(self): """Send the chosen unit away. The unit will leave the crew and can never be restored. """ if len(base.team.chars) == 1: # noqa: F821 return self.write_snd.play() char = self._char_chooser.chosen_item char.leave() taskMgr.doMethodLater( # noqa: F821 0.1, self._char_chooser.leave_unit, char.id + "_leave", extraArgs=[char.id]) def _hire(self): """Hire the chosen unit.""" cost = self._recruit_chooser.chosen_recruit_cost if not base.res_gui.check_enough_money(cost): # noqa: F821 return char = self._recruit_chooser.chosen_item if char is None: return if not base.res_gui.check_has_cell(): # noqa: F821 return self.write_snd.play() base.dollars -= cost # noqa: F821 base.team.chars[char.id] = char # noqa: F821 self._recruit_chooser.leave_unit(char.id) char.prepare() base.train.place_recruit(char) # noqa: F821 base.res_gui.update_chars() # noqa: F821 if not char.current_part.name == "part_rest": char.rest() def _repair(self, value): """Repair the locomotive. Spends money. Args: value (int): Points of the Train durability to repair. """ spent = 10 if value == 50 else 40 if not base.res_gui.check_enough_money(spent): # noqa: F821 return random.choice((self._coins_s_snd, self._coins_l_snd)).play() base.train.get_damage(-value) # noqa: F821 base.dollars -= spent # noqa: F821 def _heal(self, value): """Heal the chosen character. Spends money. Args: value (int): Points to heal. """ if not base.res_gui.check_enough_money(value): # noqa: F821 return random.choice((self._coins_s_snd, self._coins_l_snd)).play() self._char_chooser.chosen_item.health += value base.dollars -= value # noqa: F821 def _rest(self, value): """Regain energy of the chosen character. Spends money. Args: value (int): Points to regain. """ spent = 5 if value == 10 else 25 if not base.res_gui.check_enough_money(spent): # noqa: F821 return random.choice((self._coins_s_snd, self._coins_l_snd)).play() self._char_chooser.chosen_item.energy += value base.dollars -= spent # noqa: F821 def _inc_amb_snd(self, task): """Increase hangar ambient sound.""" cur_vol = round(self._amb_snd.getVolume(), 2) if cur_vol == 1: return task.done self._amb_snd.setVolume(cur_vol + 0.05) return task.again def _dec_amb_snd(self, task): """Decrease hangar ambient sound.""" cur_vol = round(self._amb_snd.getVolume(), 2) if cur_vol == 0: self._amb_snd.stop() return task.done self._amb_snd.setVolume(cur_vol - 0.05) return task.again def _show_headhunting_reward(self): """Show a reward GUI. When getting into a city, player gains money as a reward for destroying enemies. Money amount depends on what enemies were destroyed. """ heads_cost = { "MotoShooter": 5, "BrakeThrower": 5, "StunBombThrower": 10, "DodgeShooter": 25, "Kamikaze": 15, } if not base.heads: # noqa: F821 return self._reward_fr = DirectFrame( frameSize=(-0.3, 0.3, -0.45, 0.45), frameTexture="gui/tex/paper1.png", state=DGG.NORMAL, pos=(0.9, 0, -0.15), ) self._reward_fr.setDepthTest(False) self._reward_fr.setTransparency(TransparencyAttrib.MAlpha) heads_list = "" costs_list = "" total = 0 for head, num in base.heads.items(): # noqa: F821 heads_list += head + " x" + str(num) + "\n" costs_list += str(num * heads_cost[head]) + "$\n" total += num * heads_cost[head] reward_desc = DirectLabel( parent=self._reward_fr, frameColor=(0, 0, 0, 0), frameSize=(-0.3, 0.3, -0.1, 0.1), text=base.labels.CITY[16] # noqa: F821 + "\n" * 13 + base.labels.CITY[17] # noqa: F821 + str(total) + "$", text_font=base.main_font, # noqa: F821 text_scale=0.03, pos=(0, 0, 0.35), ) heads_list = DirectLabel( parent=self._reward_fr, frameColor=(0, 0, 0, 0), frameSize=(-0.3, 0.3, -0.1, 0.1), text=heads_list, text_scale=0.03, text_align=TextNode.ALeft, pos=(-0.21, 0, 0.08), ) costs_list = DirectLabel( parent=self._reward_fr, frameColor=(0, 0, 0, 0), frameSize=(-0.3, 0.3, -0.1, 0.1), text=costs_list, text_scale=0.03, text_align=TextNode.ALeft, pos=(0.16, 0, 0.08), ) DirectButton( parent=self._reward_fr, pos=(0, 0, -0.38), text="Acquire", text_fg=RUST_COL, text_shadow=(0, 0, 0, 1), frameColor=(0, 0, 0, 0), command=self._acquire_reward, extraArgs=[total, reward_desc, heads_list, costs_list], scale=(0.04, 0, 0.04), ) def _acquire_reward(self, dollars, reward_desc, heads_list, costs_list): """Claim a reward, given by a city for destroying enemies. Args: dollars (int): Gained dollars amount. reward_desc (direct.gui.DirectGui.DirectLabel): Reward description widget. heads_list (direct.gui.DirectGui.DirectLabel): List of taken heads widget. costs_list (direct.gui.DirectGui.DirectLabel): Money got for the heads list widget. """ self._coins_l_snd.play() base.dollars += dollars # noqa: F821 if base.helped_children: # noqa: F821 reward_desc["text"] = base.labels.CITY[18] # noqa: F821 base.train.get_damage(-250) # noqa: F821 heads_list.destroy() costs_list.destroy() base.helped_children = False # noqa: F821 return self._reward_fr.destroy() self._reward_fr = None base.clear_heads() # noqa: F821 def show(self): """Show city GUI.""" self._amb_snd.play() taskMgr.doMethodLater(0.3, self._inc_amb_snd, "increase_city_snd") # noqa: F821 self._recruits = base.team.gen_recruits() # noqa: F821 self._fr.show() self._show_train(0.56) self._show_headhunting_reward()
class NamePicker(): """ A UI element that lets the players pick their name. Also has a confirmation element to the right of the entry box. """ def __init__(self, classSelectionMenu): self._classSelectionMenu = classSelectionMenu self._nameEntry = None self._confirmButton = None self._rootFrame = None self._font = loader.loadFont(PIERCEROMAN_FONT) self._draw() def _draw(self): winWidth = base.getAspectRatio() * 2 winHeight = 2 # Draw container: frameHeight = winHeight * NPKR_HEIGHT_PERCENTAGE frameWidth = winWidth * NPKR_WIDTH_PERCENTAGE cFCenterY = -winHeight / 2 + frameHeight / 2 self._rootFrame = DirectFrame( pos=(0, 0, cFCenterY), frameSize=(-frameWidth / 2, frameWidth / 2, -frameHeight / 2, frameHeight / 2), frameTexture=IMG_GRADIENT_1) self._rootFrame.setTransparency(TransparencyAttrib.MAlpha) # Draw Name Entry: entryWidth = self._rootFrame.getWidth() * NPKR_ENTRY_WIDTH_PERCENTAGE entryHeight = self._rootFrame.getHeight() entryCX = -(self._rootFrame.getWidth() - entryWidth) / 2 self._nameEntry = DirectEntry( parent=self._rootFrame, pos=(entryCX, 0, 0), frameSize=(-entryWidth / 2, entryWidth / 2, -entryHeight / 2, entryHeight / 2), frameColor=(0.25, 0.25, 0.25, 1), text_align=TextNode.ACenter, text_font=self._font, text_scale=NPKR_ENTRY_FONT_SIZE, text_pos=NPKR_ENTRY_FONT_OFFSET, initialText=NPKR_ENTRY_INITIAL_TEXT, numLines=1, focusOutCommand=self._syncName, focusInCommand=self._checkPlaceholderText, command=self._syncName, frameTexture=UI_WINDOW) # Draw Confirm Button: confirmWidth = self._rootFrame.getWidth()\ * (1-NPKR_ENTRY_WIDTH_PERCENTAGE) confirmHeight = self._rootFrame.getHeight() confirmCX = (self._rootFrame.getWidth() - confirmWidth) / 2 self._confirmButton = DirectButton( parent=self._rootFrame, pos=(confirmCX, 0, 0), frameSize=(-confirmWidth / 2, confirmWidth / 2, -confirmHeight / 2, confirmHeight / 2), command=self._onConfirmPressed, text_font=self._font, text_scale=NPKR_BUTTON_FONT_SIZE, text_pos=NPKR_BUTTON_FONT_OFFSET, text="Create Character", borderWidth=NPKR_BUTTON_BORDER_WIDTH) def getName(self): return str(self._nameEntry.get()) def _onConfirmPressed(self): """ Reroutes this input to the parent ClassSelectionMenu """ self._classSelectionMenu.createCharacter() def _checkPlaceholderText(self): """ Makes the nameEntry behave more like a real name entry by removing the placeholder text when the player begins to interact. """ # If the text entered is the placeholder text, simply remove it: if self._nameEntry.get() == NPKR_ENTRY_INITIAL_TEXT: self._nameEntry.set("") def _syncName(self, extraArgs=None): """ Syncs name with this game's host/client manager """ self._classSelectionMenu.syncInfo(cName=self.getName()) def close(self): self._rootFrame.destroy() # Destroy ui del self # Destroy this instance
class Option: """docstring for Option""" def __init__(self): self.testMusic = loader.loadMusic("Audio/click.wav") self.testSfx = loader.loadSfx("Audio/click.wav") self.frameOption = DirectFrame(image="gui/BackGround_o.png", image_scale=(1.7778, 1, 1), frameSize=(base.a2dLeft, base.a2dRight, base.a2dBottom, base.a2dTop), frameColor=(0, 0, 0, 0)) self.frameOption.setTransparency(1) self.title = DirectLabel(scale=0.15, text_align=TextNode.ALeft, pos=(-0.3, 0, 0.5), frameColor=(0, 0, 0, 0), text="", text_fg=(1, 1, 1, 1)) self.title.setTransparency(1) self.title.reparentTo(self.frameOption) self.title_volume = DirectLabel(scale=0.1, text_align=TextNode.ALeft, pos=(base.a2dLeft + 1.3, 0, -0.2), frameColor=(0, 0, 0, 0), text="Music", text_fg=(1, 1, 1, 1)) self.title_volume.setTransparency(1) self.title_volume.reparentTo(self.frameOption) self.slider_volume = DirectSlider(pos=(base.a2dLeft + 2.2, 0, -0.2), value=50, range=(0, 100), pageSize=5, scale=0.5, command=base.messenger.send, extraArgs=["ChangeVolume"]) self.slider_volume.reparentTo(self.frameOption) self.testMusicBtn = self.createButton(-0.2, self.testMusic) self.title_sound = DirectLabel(scale=0.1, text_align=TextNode.ALeft, pos=(base.a2dLeft + 1.3, 0, -0.4), frameColor=(0, 0, 0, 0), text="Sfx", text_fg=(1, 1, 1, 1)) self.title_sound.setTransparency(1) self.title_sound.reparentTo(self.frameOption) self.slider_sound = DirectSlider( pos=(base.a2dLeft + 2.2, 0, -0.4), value=50, range=(0, 100), pageSize=5, #frameSize = (1,1,1,1) scale=0.5, command=base.messenger.send, extraArgs=["ChangeSound"]) self.slider_sound.reparentTo(self.frameOption) self.testSfxBtn = self.createButton(-0.4, self.testSfx) # self.title_leapmotion = DirectLabel( # scale = 0.1, # text_align = TextNode.ALeft, # pos = (base.a2dLeft + 0.6 , 0, -0.6), # frameColor = (0, 0, 0, 0), # text = "Leapmotion", # text_fg = (1,1,1,1)) # self.title_leapmotion.reparentTo(self.frameOption) # self.cbtn_leapmotion = DirectCheckButton( # text = "needed",text_fg=(1,1,1,1), # scale = .1, # pos = (base.a2dLeft + 1.5 , 0, -0.6), # command = base.messenger.send, # extraArgs = ["ChangeLeapmotion"]) # self.cbtn_leapmotion.reparentTo(self.frameOption) self.hide() def createButton(self, verticalPos, eventArgs): maps = loader.loadModel("gui/button_map") btnGeom = (maps.find("**/btn_ready"), maps.find("**/btn_click"), maps.find("**/btn_rollover"), maps.find("**/btn_disabled")) btn = DirectButton(text="apply", text_fg=(1, 1, 1, 1), text_scale=0.05, text_pos=(0.15, -0.013), text_align=TextNode.ALeft, scale=2, geom=btnGeom, pos=(base.a2dRight - 0.7, 0, verticalPos), relief=0, frameColor=(1, 1, 1, 1), command=self.testPlay, extraArgs=[ eventArgs, ], pressEffect=True, rolloverSound=None) btn.reparentTo(self.frameOption) btn.setTransparency(1) return btn def testPlay(self, sound): sound.play() def show(self): self.frameOption.show() def hide(self): self.frameOption.hide()
class ResourcesGUI: """GUI to track player's resources. Includes money, expendable resources and cohesion. """ def __init__(self): self._coh_desc_wids = [] self._coh_desc_shown = False self._res_desc_wids = [] self._res_desc_shown = False self._resources = {} self._blink_step = 0 self._reload_ico = None self._reload_min = None self._err_snd = loader.loadSfx("sounds/GUI/error.ogg") # noqa: F821 self._res_frame = DirectFrame( parent=base.a2dTopLeft, # noqa: F821 frameSize=(-0.37, 0.37, -0.03, 0.028), pos=(0.37, 0, -0.028), frameTexture=GUI_PIC + "metal1.png", ) self._res_frame.setTransparency(TransparencyAttrib.MAlpha) DirectFrame( parent=self._res_frame, # noqa: F821 frameSize=(-0.023, 0.023, -0.023, 0.023), pos=(-0.34, 0, 0), frameTexture=GUI_PIC + "dollar.png", ) self._resources["dollars"] = DirectLabel( parent=self._res_frame, text="", frameSize=(0.1, 0.1, 0.1, 0.1), text_scale=0.035, text_fg=RUST_COL, pos=(-0.27, 0, -0.008), ) DirectFrame( parent=self._res_frame, # noqa: F821 frameSize=(-0.018, 0.018, -0.018, 0.018), pos=(-0.18, 0, 0), frameTexture=GUI_PIC + "chars.png", ) self._resources["chars"] = DirectLabel( parent=self._res_frame, text="{}/{}".format(len(base.team.chars), base.train.cells), # noqa: F821 frameSize=(0.1, 0.1, 0.1, 0.1), text_scale=0.035, text_fg=RUST_COL, pos=(-0.12, 0, -0.008), ) but = DirectButton( parent=self._res_frame, frameSize=(-0.023, 0.023, -0.023, 0.023), relief="flat", pos=(-0.06, 0, 0), frameTexture=GUI_PIC + "medicine.png", command=base.team.use_medicine, # noqa: F821 ) but.bind(DGG.ENTER, self._highlight_res_but, extraArgs=[but, "medicine_boxes"]) but.bind(DGG.EXIT, self._dehighlight_but, extraArgs=[but]) self._resources["medicine_boxes"] = DirectLabel( parent=self._res_frame, text="0", frameSize=(0.1, 0.1, 0.1, 0.1), text_scale=0.035, text_fg=RUST_COL, pos=(-0.02, 0, -0.008), ) but = DirectButton( parent=self._res_frame, frameSize=(-0.023, 0.023, -0.023, 0.023), relief="flat", pos=(0.035, 0, 0), frameTexture=GUI_PIC + "smoke_filter.png", command=base.train.use_smoke_filter, # noqa: F821 ) but.bind(DGG.ENTER, self._highlight_res_but, extraArgs=[but, "smoke_filters"]) but.bind(DGG.EXIT, self._dehighlight_but, extraArgs=[but]) self._resources["smoke_filters"] = DirectLabel( parent=self._res_frame, text="0", frameSize=(0.1, 0.1, 0.1, 0.1), text_scale=0.035, text_fg=RUST_COL, pos=(0.075, 0, -0.008), ) but = DirectButton( parent=self._res_frame, frameSize=(-0.014, 0.014, -0.021, 0.021), relief="flat", pos=(0.12, 0, 0), frameTexture=GUI_PIC + "stimulator.png", command=base.team.use_stimulator, # noqa: F821 ) but.bind(DGG.ENTER, self._highlight_res_but, extraArgs=[but, "stimulators"]) but.bind(DGG.EXIT, self._dehighlight_but, extraArgs=[but]) self._resources["stimulators"] = DirectLabel( parent=self._res_frame, text="0", frameSize=(0.1, 0.1, 0.1, 0.1), text_scale=0.035, text_fg=RUST_COL, pos=(0.16, 0, -0.008), ) DirectButton( parent=self._res_frame, frameSize=(-0.014, 0.014, -0.021, 0.021), relief="flat", pos=(0.2, 0, 0), frameTexture=GUI_PIC + "places_of_interest.png", ) self._resources["places_of_interest"] = DirectLabel( parent=self._res_frame, text="0/10", frameSize=(0.1, 0.1, 0.1, 0.1), text_scale=0.035, text_fg=RUST_COL, pos=(0.27, 0, -0.008), ) DirectButton( parent=self._res_frame, pos=(0.34, 0, -0.013), command=self._show_expendable_resources, clickSound=base.main_menu.click_snd, # noqa: F821 **ABOUT_BUT_PARAMS, ).setTransparency(TransparencyAttrib.MAlpha) self._coh_frame = DirectFrame( parent=base.a2dBottomRight, # noqa: F821 frameSize=(-0.55, 0.55, -0.05, 0.05), pos=(-0.6, 0, 1.95), frameTexture=GUI_PIC + "metal1.png", state=DGG.NORMAL, ) self._coh_frame.setTransparency(TransparencyAttrib.MAlpha) self._cohesion = DirectWaitBar( parent=self._coh_frame, frameSize=(-0.45, 0.45, -0.002, 0.002), frameColor=(0.35, 0.35, 0.35, 1), value=0, barColor=SILVER_COL, pos=(0, 0, 0.02), ) recall_ico = DirectButton( parent=self._coh_frame, frameSize=(-0.023, 0.023, -0.023, 0.023), frameTexture=GUI_PIC + "ny_recall.png", pos=(-0.27, 0, -0.02), relief="flat", command=base.team.cohesion_recall, # noqa: F821 ) recall_ico.setTransparency(TransparencyAttrib.MAlpha) recall_ico.bind(DGG.ENTER, self._highlight_coh_but, extraArgs=[recall_ico]) recall_ico.bind(DGG.EXIT, self._dehighlight_but, extraArgs=[recall_ico]) cover_ico = DirectButton( parent=self._coh_frame, frameSize=(-0.035, 0.035, -0.035, 0.035), frameTexture=GUI_PIC + "ny_cover.png", pos=(-0.09, 0, -0.01), relief="flat", command=base.team.cohesion_cover_fire, # noqa: F821 ) cover_ico.setTransparency(TransparencyAttrib.MAlpha) cover_ico.bind(DGG.ENTER, self._highlight_coh_but, extraArgs=[cover_ico]) cover_ico.bind(DGG.EXIT, self._dehighlight_but, extraArgs=[cover_ico]) heal_ico = DirectButton( parent=self._coh_frame, frameSize=(-0.023, 0.023, -0.023, 0.023), frameTexture=GUI_PIC + "ny_heal.png", pos=(0.09, 0, -0.015), relief="flat", command=base.team.cohesion_heal_wounded, # noqa: F821 ) heal_ico.setTransparency(TransparencyAttrib.MAlpha) heal_ico.bind(DGG.ENTER, self._highlight_coh_but, extraArgs=[heal_ico]) heal_ico.bind(DGG.EXIT, self._dehighlight_but, extraArgs=[heal_ico]) rage_ico = DirectButton( parent=self._coh_frame, frameSize=(-0.035, 0.035, -0.035, 0.035), frameTexture=GUI_PIC + "ny_rage.png", pos=(0.27, 0, -0.015), relief="flat", command=base.team.cohesion_rage, # noqa: F821 ) rage_ico.setTransparency(TransparencyAttrib.MAlpha) rage_ico.bind(DGG.ENTER, self._highlight_coh_but, extraArgs=[rage_ico]) rage_ico.bind(DGG.EXIT, self._dehighlight_but, extraArgs=[rage_ico]) heart_ico = DirectButton( parent=self._coh_frame, frameSize=(-0.035, 0.035, -0.035, 0.035), frameTexture=GUI_PIC + "ny_heart.png", pos=(0.445, 0, -0.015), relief="flat", command=base.team.cohesion_hold_together, # noqa: F821 ) heart_ico.setTransparency(TransparencyAttrib.MAlpha) heart_ico.bind(DGG.ENTER, self._highlight_coh_but, extraArgs=[heart_ico]) heart_ico.bind(DGG.EXIT, self._dehighlight_but, extraArgs=[heart_ico]) self._coh_icons = ( {"wid": recall_ico, "file": "recall.png", "value": 20}, {"wid": cover_ico, "file": "cover.png", "value": 40}, {"wid": heal_ico, "file": "heal.png", "value": 60}, {"wid": rage_ico, "file": "rage.png", "value": 80}, {"wid": heart_ico, "file": "heart.png", "value": 100}, ) DirectButton( parent=self._coh_frame, pos=(-0.5, 0, -0.028), command=self._show_cohesion_abilities, clickSound=base.main_menu.click_snd, # noqa: F821 **ABOUT_BUT_PARAMS, ).setTransparency(TransparencyAttrib.MAlpha) def _dehighlight_but(self, button, _): """Dehighlight button. Args: button (panda3d.gui.DirectGui.DirectButton): Button to dehighlight. """ if "hover_" in button["frameTexture"]: button["frameTexture"] = button["frameTexture"].replace("hover_", "") def _highlight_coh_but(self, button, _): """Highlight cohesion skill button, if it can be used. Args: button (panda3d.gui.DirectGui.DirectButton): Button to highlight. """ if "ny_" not in button["frameTexture"]: button["frameTexture"] = ( GUI_PIC + "hover_" + button["frameTexture"].split("/")[-1] ) def _highlight_res_but(self, button, resource, _): """Highlight resource button, if it can be used. Args: button (panda3d.gui.DirectGui.DirectButton): Button to highlight. resource (str): Name of the resource. """ if base.resource(resource): # noqa: F821 button["frameTexture"] = ( GUI_PIC + "hover_" + button["frameTexture"].split("/")[-1] ) def _show_cohesion_abilities(self): """Show/hide cohesion abilities description.""" if self._coh_desc_shown: self._coh_frame["frameSize"] = (-0.55, 0.55, -0.05, 0.05) clear_wids(self._coh_desc_wids) self._coh_desc_shown = False return self._coh_desc_shown = True self._coh_frame["frameSize"] = (-0.55, 0.55, -0.61, 0.05) self._coh_desc_wids.append( DirectLabel( parent=self._coh_frame, text=base.labels.COHESION[0], # noqa: F821 text_font=base.main_font, # noqa: F821 frameSize=(0.1, 0.1, 0.1, 0.1), text_scale=0.033, text_fg=SILVER_COL, pos=(0, 0, -0.08), ) ) self._coh_desc_wids.append( DirectButton( parent=self._coh_frame, frameSize=(-0.035, 0.035, -0.035, 0.035), frameTexture=GUI_PIC + "recall.png", pos=(-0.45, 0, -0.13), relief="flat", ) ) x_coor = -0.39 self._coh_desc_wids.append( DirectLabel( parent=self._coh_frame, text=base.labels.COHESION[1], # noqa: F821 text_font=base.main_font, # noqa: F821 text_align=TextNode.ALeft, frameSize=(0.1, 0.1, 0.1, 0.1), text_scale=0.029, text_fg=SILVER_COL, pos=(x_coor, 0, -0.117), ) ) self._coh_desc_wids.append( DirectLabel( parent=self._coh_frame, text=base.labels.COHESION[2], # noqa: F821 text_font=base.main_font, # noqa: F821 text_align=TextNode.ALeft, frameSize=(0.1, 0.1, 0.1, 0.1), text_scale=0.028, text_fg=SILVER_COL, pos=(x_coor, 0, -0.155), ) ) self._coh_desc_wids.append( DirectButton( parent=self._coh_frame, frameSize=(-0.045, 0.045, -0.045, 0.045), frameTexture=GUI_PIC + "cover.png", pos=(-0.45, 0, -0.22), relief="flat", ) ) self._coh_desc_wids.append( DirectLabel( parent=self._coh_frame, text=base.labels.COHESION[3], # noqa: F821 text_font=base.main_font, # noqa: F821 text_align=TextNode.ALeft, frameSize=(0.1, 0.1, 0.1, 0.1), text_scale=0.029, text_fg=SILVER_COL, pos=(x_coor, 0, -0.217), ) ) self._coh_desc_wids.append( DirectLabel( parent=self._coh_frame, text=base.labels.COHESION[4], # noqa: F821 text_font=base.main_font, # noqa: F821 text_align=TextNode.ALeft, frameSize=(0.1, 0.1, 0.1, 0.1), text_scale=0.028, text_fg=SILVER_COL, pos=(x_coor, 0, -0.255), ) ) self._coh_desc_wids.append( DirectButton( parent=self._coh_frame, frameSize=(-0.035, 0.035, -0.035, 0.035), frameTexture=GUI_PIC + "heal.png", pos=(-0.45, 0, -0.33), relief="flat", ) ) self._coh_desc_wids.append( DirectLabel( parent=self._coh_frame, text=base.labels.COHESION[5], # noqa: F821 text_font=base.main_font, # noqa: F821 text_align=TextNode.ALeft, frameSize=(0.1, 0.1, 0.1, 0.1), text_scale=0.029, text_fg=SILVER_COL, pos=(x_coor, 0, -0.317), ) ) self._coh_desc_wids.append( DirectLabel( parent=self._coh_frame, text=base.labels.COHESION[6], # noqa: F821 text_font=base.main_font, # noqa: F821 text_align=TextNode.ALeft, frameSize=(0.1, 0.1, 0.1, 0.1), text_scale=0.028, text_fg=SILVER_COL, pos=(x_coor, 0, -0.355), ) ) self._coh_desc_wids.append( DirectButton( parent=self._coh_frame, frameSize=(-0.045, 0.045, -0.045, 0.045), frameTexture=GUI_PIC + "rage.png", pos=(-0.45, 0, -0.43), relief="flat", ) ) self._coh_desc_wids.append( DirectLabel( parent=self._coh_frame, text=base.labels.COHESION[7], # noqa: F821 text_font=base.main_font, # noqa: F821 text_align=TextNode.ALeft, frameSize=(0.1, 0.1, 0.1, 0.1), text_scale=0.029, text_fg=SILVER_COL, pos=(x_coor, 0, -0.417), ) ) self._coh_desc_wids.append( DirectLabel( parent=self._coh_frame, text=base.labels.COHESION[8], # noqa: F821 text_font=base.main_font, # noqa: F821 text_align=TextNode.ALeft, frameSize=(0.1, 0.1, 0.1, 0.1), text_scale=0.028, text_fg=SILVER_COL, pos=(x_coor, 0, -0.455), ) ) self._coh_desc_wids.append( DirectButton( parent=self._coh_frame, frameSize=(-0.043, 0.043, -0.043, 0.043), frameTexture=GUI_PIC + "heart.png", pos=(-0.45, 0, -0.53), relief="flat", ) ) self._coh_desc_wids.append( DirectLabel( parent=self._coh_frame, text=base.labels.COHESION[9], # noqa: F821 text_font=base.main_font, # noqa: F821 text_align=TextNode.ALeft, frameSize=(0.1, 0.1, 0.1, 0.1), text_scale=0.029, text_fg=SILVER_COL, pos=(x_coor, 0, -0.517), ) ) self._coh_desc_wids.append( DirectLabel( parent=self._coh_frame, text=base.labels.COHESION[10], # noqa: F821 text_font=base.main_font, # noqa: F821 text_align=TextNode.ALeft, frameSize=(0.1, 0.1, 0.1, 0.1), text_scale=0.028, text_fg=SILVER_COL, pos=(x_coor, 0, -0.555), ) ) def _show_expendable_resources(self): """Show/hide expendable resources description.""" if self._res_desc_shown: self._res_frame["frameSize"] = (-0.37, 0.37, -0.03, 0.028) clear_wids(self._res_desc_wids) self._res_desc_shown = False return self._res_desc_shown = True self._res_frame["frameSize"] = (-0.37, 0.37, -0.51, 0.028) self._res_desc_wids.append( DirectLabel( parent=self._res_frame, text=base.labels.RESOURCES[0], # noqa: F821 text_font=base.main_font, # noqa: F821 frameSize=(0.1, 0.1, 0.1, 0.1), text_scale=0.033, text_fg=SILVER_COL, pos=(0, 0, -0.08), ) ) self._res_desc_wids.append( DirectButton( parent=self._res_frame, frameSize=(-0.03, 0.03, -0.03, 0.03), frameTexture=GUI_PIC + "medicine.png", pos=(-0.29, 0, -0.15), relief="flat", ) ) self._res_desc_wids.append( DirectLabel( parent=self._res_frame, text=base.labels.RESOURCES[1], # noqa: F821 text_font=base.main_font, # noqa: F821 frameSize=(0.1, 0.1, 0.1, 0.1), text_scale=0.03, text_align=TextNode.ALeft, text_fg=SILVER_COL, pos=(-0.235, 0, -0.137), ) ) self._res_desc_wids.append( DirectLabel( parent=self._res_frame, text=base.labels.RESOURCES[2], # noqa: F821 text_font=base.main_font, # noqa: F821 frameSize=(0.1, 0.1, 0.1, 0.1), text_scale=0.029, text_align=TextNode.ALeft, text_fg=SILVER_COL, pos=(-0.235, 0, -0.175), ) ) self._res_desc_wids.append( DirectButton( parent=self._res_frame, frameSize=(-0.03, 0.03, -0.03, 0.03), frameTexture=GUI_PIC + "smoke_filter.png", pos=(-0.29, 0, -0.24), relief="flat", ) ) self._res_desc_wids.append( DirectLabel( parent=self._res_frame, text=base.labels.RESOURCES[3], # noqa: F821 text_font=base.main_font, # noqa: F821 frameSize=(0.1, 0.1, 0.1, 0.1), text_scale=0.03, text_align=TextNode.ALeft, text_fg=SILVER_COL, pos=(-0.235, 0, -0.233), ) ) self._res_desc_wids.append( DirectLabel( parent=self._res_frame, text=base.labels.RESOURCES[4], # noqa: F821 text_font=base.main_font, # noqa: F821 frameSize=(0.1, 0.1, 0.1, 0.1), text_scale=0.029, text_align=TextNode.ALeft, text_fg=SILVER_COL, pos=(-0.235, 0, -0.27), ) ) self._res_desc_wids.append( DirectButton( parent=self._res_frame, frameSize=(-0.018, 0.018, -0.028, 0.028), frameTexture=GUI_PIC + "stimulator.png", pos=(-0.29, 0, -0.339), relief="flat", ) ) self._res_desc_wids.append( DirectLabel( parent=self._res_frame, text=base.labels.RESOURCES[5], # noqa: F821 text_font=base.main_font, # noqa: F821 frameSize=(0.1, 0.1, 0.1, 0.1), text_scale=0.03, text_align=TextNode.ALeft, text_fg=SILVER_COL, pos=(-0.235, 0, -0.327), ) ) self._res_desc_wids.append( DirectLabel( parent=self._res_frame, text=base.labels.RESOURCES[6], # noqa: F821 text_font=base.main_font, # noqa: F821 frameSize=(0.1, 0.1, 0.1, 0.1), text_scale=0.029, text_align=TextNode.ALeft, text_fg=SILVER_COL, pos=(-0.235, 0, -0.365), ) ) self._res_desc_wids.append( DirectButton( parent=self._res_frame, frameSize=(-0.03, 0.03, -0.03, 0.03), frameTexture=GUI_PIC + "places_of_interest.png", pos=(-0.29, 0, -0.438), relief="flat", ) ) self._res_desc_wids.append( DirectLabel( parent=self._res_frame, text=base.labels.RESOURCES[8], # noqa: F821 text_font=base.main_font, # noqa: F821 frameSize=(0.1, 0.1, 0.1, 0.1), text_scale=0.03, text_align=TextNode.ALeft, text_fg=SILVER_COL, pos=(-0.235, 0, -0.426), ) ) self._res_desc_wids.append( DirectLabel( parent=self._res_frame, text=base.labels.RESOURCES[9], # noqa: F821 text_font=base.main_font, # noqa: F821 frameSize=(0.1, 0.1, 0.1, 0.1), text_scale=0.029, text_align=TextNode.ALeft, text_fg=SILVER_COL, pos=(-0.235, 0, -0.464), ) ) def _blink_widget(self, widget, task): """Make the given widget blinking. Args: widget (str): Name of the widget to blink. """ self._blink_step += 1 if self._blink_step in (2, 4): self._resources[widget]["text_bg"] = (0, 0, 0, 0) self._resources[widget]["text_fg"] = RUST_COL else: self._resources[widget]["text_bg"] = (0.6, 0, 0, 1) self._resources[widget]["text_fg"] = (0, 0, 0, 1) if self._blink_step == 4: self._blink_step = 0 return task.done return task.again def check_enough_money(self, ch_sum): """Ensure that player have enough money for a buy. Make the money widget blink if player doesn't have enough money. Args: ch_sum (int): Buy cost. Returns: bool: True, if player has enough money. """ if ch_sum > base.dollars: # noqa: F821 taskMgr.doMethodLater( # noqa: F821 0.4, self._blink_widget, "blink_money_widget", extraArgs=["dollars"], appendTask=True, ) self._err_snd.play() return False return True def check_has_cell(self): """Check that the Train has at least one cell. Make the characters number widget blink, if there are not free cells. """ if not base.train.has_cell(): # noqa: F821 taskMgr.doMethodLater( # noqa: F821 0.4, self._blink_widget, "blink_money_widget", extraArgs=["chars"], appendTask=True, ) self._err_snd.play() return False return True def disable_cohesion(self): """Disable all the cohesion abilities.""" for icon in self._coh_icons: icon["wid"]["frameTexture"] = GUI_PIC + "ny_" + icon["file"] self._reload_ico = DirectButton( parent=self._coh_frame, frameSize=(-0.023, 0.023, -0.023, 0.023), frameTexture=GUI_PIC + "reload.png", pos=(-0.433, 0, -0.017), relief="flat", ) self._reload_ico.setTransparency(TransparencyAttrib.MAlpha) self._reload_min = DirectLabel( parent=self._coh_frame, frameSize=(0.1, 0.1, 0.1, 0.1), frameColor=(0, 0, 0, 0), text="? min", text_fg=SILVER_COL, text_scale=0.025, pos=(-0.37, 0, -0.025), ) def finish_reload(self): """Hide reloading timer widgets.""" self._reload_ico.destroy() self._reload_min.destroy() self._reload_ico = None self._reload_min = None def show_reload_min(self, min_num): """Update reloading timer. Args: min_num (int): Number of minutes left in the reloading delay. """ self._reload_min["text"] = str(min_num) + " min" def update_chars(self): """Update characters number widget.""" self._resources["chars"]["text"] = "{current}/{maximum}".format( current=len(base.team.chars), maximum=base.train.cells # noqa: F821 ) def update_cohesion(self, new_value): """Update cohesion indicator with the given value. Args: new_value (int): New amount of the cohesion points. """ self._cohesion["value"] = new_value if base.team.cohesion_cooldown: # noqa: F821 return for icon in self._coh_icons: if "hover_" in icon["wid"]["frameTexture"]: continue if new_value >= icon["value"]: icon["wid"]["frameTexture"] = GUI_PIC + icon["file"] else: icon["wid"]["frameTexture"] = GUI_PIC + "ny_" + icon["file"] def update_resource(self, name, value): """Update the indicator with the given value. Args: name (str): The indicator name. value (Any): The new indicator value. """ self._resources[name]["text"] = str(value)
class Transitions: # These may be reassigned before the fade or iris transitions are # actually invoked to change the models that will be used. IrisModelName = "models/misc/iris" FadeModelName = "models/misc/fade" def __init__(self, loader, model=None, scale=3.0, pos=Vec3(0, 0, 0)): self.transitionIval = None self.letterboxIval = None self.iris = None self.fade = None self.letterbox = None self.fadeModel = model self.imagePos = pos if model: self.alphaOff = Vec4(1, 1, 1, 0) self.alphaOn = Vec4(1, 1, 1, 1) model.setTransparency(1) self.lerpFunc = LerpColorScaleInterval else: self.alphaOff = Vec4(0, 0, 0, 0) self.alphaOn = Vec4(0, 0, 0, 1) self.lerpFunc = LerpColorInterval self.irisTaskName = "irisTask" self.fadeTaskName = "fadeTask" self.letterboxTaskName = "letterboxTask" def __del__(self): if self.fadeModel: self.fadeModel.removeNode() self.fadeModel = None ################################################## # Fade ################################################## # We can set a custom model for the fade before using it for the first time def setFadeModel(self, model, scale=1.0): self.fadeModel = model # We have to change some default parameters for a custom fadeModel self.alphaOn = Vec4(1, 1, 1, 1) # Reload fade if its already been created if self.fade: self.fade.destroy() self.fade = None self.loadFade() def loadFade(self): if self.fade is None: # We create a DirectFrame for the fade polygon, instead of # simply loading the polygon model and using it directly, # so that it will also obscure mouse events for objects # positioned behind it. self.fade = DirectFrame( parent = hidden, guiId = 'fade', relief = None, image = self.fadeModel, image_scale = (4, 2, 2), state = DGG.NORMAL, ) if not self.fadeModel: # No fade model was given, so we make this the fade model. self.fade["relief"] = DGG.FLAT self.fade["frameSize"] = (-2, 2, -1, 1) self.fade["frameColor"] = (0, 0, 0, 1) self.fade.setTransparency(TransparencyAttrib.MAlpha) self.fade.setBin('unsorted', 0) self.fade.setColor(0,0,0,0) def getFadeInIval(self, t=0.5, finishIval=None): """ Returns an interval without starting it. This is particularly useful in cutscenes, so when the cutsceneIval is escaped out of we can finish the fade immediately """ #self.noTransitions() masad: this creates a one frame pop, is it necessary? self.loadFade() transitionIval = Sequence(Func(self.fade.reparentTo, aspect2d, DGG.FADE_SORT_INDEX), Func(self.fade.showThrough), # in case aspect2d is hidden for some reason self.lerpFunc(self.fade, t, self.alphaOff, # self.alphaOn, ), Func(self.fade.detachNode), name = self.fadeTaskName, ) if finishIval: transitionIval.append(finishIval) return transitionIval def getFadeOutIval(self, t=0.5, finishIval=None): """ Create a sequence that lerps the color out, then parents the fade to hidden """ self.noTransitions() self.loadFade() transitionIval = Sequence(Func(self.fade.reparentTo,aspect2d,DGG.FADE_SORT_INDEX), Func(self.fade.showThrough), # in case aspect2d is hidden for some reason self.lerpFunc(self.fade, t, self.alphaOn, # self.alphaOff, ), name = self.fadeTaskName, ) if finishIval: transitionIval.append(finishIval) return transitionIval def fadeIn(self, t=0.5, finishIval=None): """ Play a fade in transition over t seconds. Places a polygon on the aspect2d plane then lerps the color from black to transparent. When the color lerp is finished, it parents the fade polygon to hidden. """ gsg = base.win.getGsg() if gsg: # If we're about to fade in from black, go ahead and # preload all the textures etc. base.graphicsEngine.renderFrame() render.prepareScene(gsg) render2d.prepareScene(gsg) if (t == 0): # Fade in immediately with no lerp #print "transitiosn: fadeIn 0.0" self.noTransitions() self.loadFade() self.fade.detachNode() else: # Create a sequence that lerps the color out, then # parents the fade to hidden self.transitionIval = self.getFadeInIval(t, finishIval) self.transitionIval.start() def fadeOut(self, t=0.5, finishIval=None): """ Play a fade out transition over t seconds. Places a polygon on the aspect2d plane then lerps the color from transparent to full black. When the color lerp is finished, it leaves the fade polygon covering the aspect2d plane until you fadeIn or call noFade. lerp """ if (t == 0): # Fade out immediately with no lerp self.noTransitions() self.loadFade() self.fade.reparentTo(aspect2d, DGG.FADE_SORT_INDEX) self.fade.setColor(self.alphaOn) elif ConfigVariableBool('no-loading-screen', False): if finishIval: self.transitionIval = finishIval self.transitionIval.start() else: # Create a sequence that lerps the color out, then # parents the fade to hidden self.transitionIval = self.getFadeOutIval(t,finishIval) self.transitionIval.start() def fadeOutActive(self): return self.fade and self.fade.getColor()[3] > 0 def fadeScreen(self, alpha=0.5): """ Put a semitransparent screen over the camera plane to darken out the world. Useful for drawing attention to a dialog box for instance """ #print "transitiosn: fadeScreen" self.noTransitions() self.loadFade() self.fade.reparentTo(aspect2d, DGG.FADE_SORT_INDEX) self.fade.setColor(self.alphaOn[0], self.alphaOn[1], self.alphaOn[2], alpha) def fadeScreenColor(self, color): """ Put a semitransparent screen over the camera plane to darken out the world. Useful for drawing attention to a dialog box for instance """ #print "transitiosn: fadeScreenColor" self.noTransitions() self.loadFade() self.fade.reparentTo(aspect2d, DGG.FADE_SORT_INDEX) self.fade.setColor(color) def noFade(self): """ Removes any current fade tasks and parents the fade polygon away """ #print "transitiosn: noFade" if self.transitionIval: self.transitionIval.pause() self.transitionIval = None if self.fade: # Make sure to reset the color, since fadeOutActive() is looking at it self.fade.setColor(self.alphaOff) self.fade.detachNode() def setFadeColor(self, r, g, b): self.alphaOn.set(r, g, b, 1) self.alphaOff.set(r, g, b, 0) ################################################## # Iris ################################################## def loadIris(self): if self.iris == None: self.iris = loader.loadModel(self.IrisModelName) self.iris.setPos(0, 0, 0) def irisIn(self, t=0.5, finishIval=None): """ Play an iris in transition over t seconds. Places a polygon on the aspect2d plane then lerps the scale of the iris polygon up so it looks like we iris in. When the scale lerp is finished, it parents the iris polygon to hidden. """ self.noTransitions() self.loadIris() if (t == 0): self.iris.detachNode() else: self.iris.reparentTo(aspect2d, DGG.FADE_SORT_INDEX) self.transitionIval = Sequence(LerpScaleInterval(self.iris, t, scale = 0.18, startScale = 0.01), Func(self.iris.detachNode), name = self.irisTaskName, ) if finishIval: self.transitionIval.append(finishIval) self.transitionIval.start() def irisOut(self, t=0.5, finishIval=None): """ Play an iris out transition over t seconds. Places a polygon on the aspect2d plane then lerps the scale of the iris down so it looks like we iris out. When the scale lerp is finished, it leaves the iris polygon covering the aspect2d plane until you irisIn or call noIris. """ self.noTransitions() self.loadIris() self.loadFade() # we need this to cover up the hole. if (t == 0): self.iris.detachNode() self.fadeOut(0) else: self.iris.reparentTo(aspect2d, DGG.FADE_SORT_INDEX) self.transitionIval = Sequence(LerpScaleInterval(self.iris, t, scale = 0.01, startScale = 0.18), Func(self.iris.detachNode), # Use the fade to cover up the hole that the iris would leave Func(self.fadeOut, 0), name = self.irisTaskName, ) if finishIval: self.transitionIval.append(finishIval) self.transitionIval.start() def noIris(self): """ Removes any current iris tasks and parents the iris polygon away """ if self.transitionIval: self.transitionIval.pause() self.transitionIval = None if self.iris != None: self.iris.detachNode() # Actually we need to remove the fade too, # because the iris effect uses it. self.noFade() def noTransitions(self): """ This call should immediately remove any and all transitions running """ self.noFade() self.noIris() # Letterbox is not really a transition, it is a screen overlay # self.noLetterbox() ################################################## # Letterbox ################################################## def loadLetterbox(self): if not self.letterbox: # We create a DirectFrame for the fade polygon, instead of # simply loading the polygon model and using it directly, # so that it will also obscure mouse events for objects # positioned behind it. self.letterbox = NodePath("letterbox") # Allow fade in and out of the bars self.letterbox.setTransparency(1) # Allow DirectLabels to be parented to the letterbox sensibly self.letterbox.setBin('unsorted', 0) # Allow a custom look to the letterbox graphic. # TODO: This model isn't available everywhere. We should # pass it in as a parameter. button = loader.loadModel('models/gui/toplevel_gui', okMissing = True) barImage = None if button: barImage = button.find('**/generic_button') self.letterboxTop = DirectFrame( parent = self.letterbox, guiId = 'letterboxTop', relief = DGG.FLAT, state = DGG.NORMAL, frameColor = (0, 0, 0, 1), borderWidth = (0, 0), frameSize = (-1, 1, 0, 0.2), pos = (0, 0, 0.8), image = barImage, image_scale = (2.25,1,.5), image_pos = (0,0,.1), image_color = (0.3,0.3,0.3,1), sortOrder = 0, ) self.letterboxBottom = DirectFrame( parent = self.letterbox, guiId = 'letterboxBottom', relief = DGG.FLAT, state = DGG.NORMAL, frameColor = (0, 0, 0, 1), borderWidth = (0, 0), frameSize = (-1, 1, 0, 0.2), pos = (0, 0, -1), image = barImage, image_scale = (2.25,1,.5), image_pos = (0,0,.1), image_color = (0.3,0.3,0.3,1), sortOrder = 0, ) # masad: always place these at the bottom of render self.letterboxTop.setBin('sorted',0) self.letterboxBottom.setBin('sorted',0) self.letterbox.reparentTo(render2d, -1) self.letterboxOff(0) def noLetterbox(self): """ Removes any current letterbox tasks and parents the letterbox polygon away """ if self.letterboxIval: self.letterboxIval.pause() self.letterboxIval = None if self.letterbox: self.letterbox.stash() def letterboxOn(self, t=0.25, finishIval=None): """ Move black bars in over t seconds. """ self.noLetterbox() self.loadLetterbox() self.letterbox.unstash() if (t == 0): self.letterboxBottom.setPos(0, 0, -1) self.letterboxTop.setPos(0, 0, 0.8) else: self.letterboxIval = Sequence(Parallel( LerpPosInterval(self.letterboxBottom, t, pos = Vec3(0, 0, -1), #startPos = Vec3(0, 0, -1.2), ), LerpPosInterval(self.letterboxTop, t, pos = Vec3(0, 0, 0.8), # startPos = Vec3(0, 0, 1), ), ), name = self.letterboxTaskName, ) if finishIval: self.letterboxIval.append(finishIval) self.letterboxIval.start() def letterboxOff(self, t=0.25, finishIval=None): """ Move black bars away over t seconds. """ self.noLetterbox() self.loadLetterbox() self.letterbox.unstash() if (t == 0): self.letterbox.stash() else: self.letterboxIval = Sequence(Parallel( LerpPosInterval(self.letterboxBottom, t, pos = Vec3(0, 0, -1.2), # startPos = Vec3(0, 0, -1), ), LerpPosInterval(self.letterboxTop, t, pos = Vec3(0, 0, 1), # startPos = Vec3(0, 0, 0.8), ), ), Func(self.letterbox.stash), Func(messenger.send,'letterboxOff'), name = self.letterboxTaskName, ) if finishIval: self.letterboxIval.append(finishIval) self.letterboxIval.start()
class AchievementGui(DirectFrame): def __init__(self): DirectFrame.__init__(self, relief=None, sortOrder=50) self.initialiseoptions(AchievementGui) self.queue = [] self.currentShowingAward = -1 def earnAchievement(self, achievementId): if self.queue == []: sound = loader.loadSfx('phase_3.5/audio/sfx/AV_levelup.ogg') sound.play() self.queue.append(achievementId) self.showAchievement() else: self.queue.append(achievementId) def showAchievement(self): if self.queue != []: if self.currentShowingAward == -1: self.currentShowingAward = self.queue[0] self.displayAchievement() self.frameSequence() def displayAchievement(self): currentAchievement = AchievementsGlobals.AchievementImages[ self.currentShowingAward] self.frame = DirectFrame(relief=None, geom='phase_3/models/gui/dialog_box_gui', geom_scale=(1.5, 0.5, 0.5), scale=(1, 1, 1), parent=self, pos=(0, 0, 0.7)) self.image = DirectFrame(relief=None, image=currentAchievement, scale=0.2, parent=self.frame) self.image.setTransparency(TransparencyAttrib.MAlpha) self.title = DirectLabel(parent=self.frame, relief=None, pos=(0, 0, 0.2), text=TTLocalizer.EarnedAchievement, text_scale=0.08, text_font=ToontownGlobals.getInterfaceFont()) self.achievementName = DirectLabel( parent=self.frame, relief=None, pos=(0, 0, 0.1), text=TTLocalizer.Achievements[self.currentShowingAward], text_scale=0.07, text_font=ToontownGlobals.getMinnieFont()) self.details = DirectLabel( parent=self.frame, relief=None, pos=(0, 0, -0.2), text=TTLocalizer.AchievementsDesc[self.currentShowingAward], text_scale=0.05, text_font=ToontownGlobals.getInterfaceFont()) def frameSequence(self): self.seq = Sequence() self.seq.append( LerpScaleInterval(self.frame, 0.25, (1, 1, 1), (0.01, 0.01, 0.01))) self.seq.append(Wait(3)) self.seq.append( LerpScaleInterval(self.frame, 0.25, (0.01, 0.01, 0.01), (1, 1, 1))) self.seq.append(Func(self.cleanupCurrentFrame)) self.seq.append(Wait(1)) self.seq.start() def cleanupCurrentFrame(self): self.image.destroy() del self.image self.title.destroy() del self.title self.achievementName.destroy() del self.achievementName self.details.destroy() del self.details self.frame.destroy() del self.frame del self.queue[0] self.currentShowingAward = -1 self.showAchievement()
class InventoryUI(UIBase): ''' This is the UI of inventory ''' def __init__(self,world): ''' Constructor ''' UIBase.__init__(self, world) maps = self.world.loader.loadModel("./LEGameAssets/Models/button") self.inventory_window_frame = None self.window_show = True self.inventory_window = None self.frame = None self.canvas = None self.inventories= [] self.canvas_size = (0.3, 1.25, 0.015, 0.75) self.frame_size = (0.3, 1.25, 0.015, 0.75) self.count = [0,0,0,0] self.icon_count = 0 self.top_line = 0.15 self.longest_line = 0 self.buttons_1 = [] self.page_canvas_size= (0,0,0,0) b = DirectButton( text = ("Inventory", "click!!!", "rolling over", "disabled"), #geom = (maps.find("**/ok"),maps.find("**/click"),maps.find("**/rolling_over"),maps.find("**/disable")), text_scale = (0.15,0.15), pos = (0.6, 0, 0.85), relief=None, scale=0.4, command=self.popoutWindow) #b = DirectButton( text = ("Inventory", "click!!!", "rolling over", "disabled"), # text_scale = (0.15,0.15), pos = (0.6, 0, 0.85), relief=None, scale=0.4, command=self.popoutWindow) def update(self): pass #Create a window def popoutWindow(self): if self.window_show: self.createWindow() else: self.destroyWindow() self.window_show = not self.window_show def createWindow(self): self.longest_line = 0 self.count = [0,0,0,0] self.inventory_window_frame = DirectFrame(frameColor=(0, 0, 0, 0.2),frameSize=(0.28, 1.27, -0.005, 0.77)) self.inventory_window = DirectScrolledFrame(canvasSize = (self.canvas_size), frameSize = (self.frame_size),frameColor=(0, 0, 0, 0.2), autoHideScrollBars = True, manageScrollBars = True, parent = self.inventory_window_frame ) #self.changeSkin() self.canvas= self.inventory_window.getCanvas() self.createMenu() self.showMenu() def destroyWindow(self): self.inventory_window_frame.destroy() # if the button list has been detached when the parent(inventory_window) is destroyed, them won't be destroyed for button in self.buttons_1: button.destroy() # clean up the button list for i in range(len(self.buttons_1)): self.buttons_1.pop() def hideButton(self, page): for button in page: button.detachNode() def showButton(self, page): for button in page: button.reparentTo(self.canvas) def addButton(self, text, position, scale, img_file, func_call): button = DirectButton(text = (""),pos =(position),text_scale = (scale), image = (img_file), image_scale = (0.1,0,0.1), relief = None,command=func_call) if(self.icon_count == 0): self.count[0] = self.canvas_size[0] self.longest_line = position[0] + button.getWidth()/2.0 self.count[2] = position[2]-button.getHeight()/2.0 if(position[0] + button.getWidth()/2.0 >= self.longest_line): self.count[1] = position[0] + button.getWidth()/2.0 #right self.longest_line = self.count[1] ''' add 0.06 to bottom ''' self.count[2] = position[2]-button.getHeight()/2.0-0.06#bottom self.inventory_window['canvasSize']=(self.count[0],self.count[1],self.count[2],self.count[3]) button.detachNode() #make sure your button won't be shown at the first time it is created self.buttons_1.append(button) self.page_canvas_size = (self.count[0],self.count[1],self.count[2],self.count[3]) if(self.icon_count == 2): self.icon_count = 0 else: self.icon_count += 1 def createMenu(self): #initialize value for the beginning line, this will never change self.count[3]= self.top_line #add button down_offset = 0 right_offset = 0 button_count = 0 self.inventories=["title1","title1","title1","title1","title1","title1"] for inventory in self.inventories: self.addButton(inventory,(0.45+right_offset, 0, -0.02+down_offset),(0.05,0.05),"./LEGameAssets/Textures/inventory_placeholder.png",self.doSomething) if(button_count == 2): down_offset += -0.3 button_count = 0 right_offset = 0 else: button_count +=1 right_offset += 0.3 def showMenu(self): self.showButton(self.buttons_1) def doSomething(self): pass def changeSkin(self): self.inventory_window['image']=("../textures/background.png") self.inventory_window['image_scale']=(0.43,0,0.43) self.inventory_window['image_pos']=(0.75,0,0.33) self.inventory_window.setTransparency(1) self.inventory_window['frameColor']=(0,0,0,0) self.inventory_window_frame['image']=("../textures/background.png") self.inventory_window_frame['image_scale']=(0.44,0,0.44) self.inventory_window_frame['image_pos']=(0.75,0,0.33) self.inventory_window_frame.setTransparency(1) self.inventory_window_frame['frameColor']=(0,0,0,0)
class Optionsmenu(): def __init__(self): self.frameMain = DirectFrame( image="gui/MenuBackground.png", image_scale=(1.7778, 1, 1), #image_pos=(0, 0, 0.25), frameSize=( base.a2dLeft, base.a2dRight, base.a2dTop, base.a2dBottom), frameColor=(0,0,0,0)) self.frameMain.setTransparency(True) self.logo = DirectFrame( image="Logo.png", image_scale=0.25, image_pos=(0, 0, 0.55), frameSize=( base.a2dLeft, base.a2dRight, base.a2dTop, base.a2dBottom), frameColor=(0,0,0,0)) self.logo.reparentTo(self.frameMain) btnGeom = "gui/button" self.btnBack = menuHelper.createButton(_("Back"), btnGeom, 0, -0.7, ["options_back"]) self.btnBack.reparentTo(self.frameMain) volume = base.musicManager.getVolume() self.sliderVolume = DirectSlider( scale=0.5, pos=(-0.5, 0, 0), range=(0, 1), scrollSize=0.01, text=_("Volume %d%%") % volume*100, text_scale=0.1, text_pos=(0, 0.15), text_fg=(1, 1, 1, 1), thumb_frameColor=(0,0.75, 0.25, 1), frameColor=(0.35, 0.15, 0.05, 1), value=volume, command=self.sliderVolume_ValueChanged) self.sliderVolume.reparentTo(self.frameMain) isChecked = not base.AppHasAudioFocus img = None imgON = "gui/AudioSwitch_on.png" imgOFF = "gui/AudioSwitch_off.png" if base.AppHasAudioFocus: img = imgON else: img = imgOFF self.cbVolumeMute = DirectCheckBox( text=_("Mute Audio"), text_scale=0.5, text_align=TextNode.ACenter, text_pos=(0, 0.65), text_fg=(1, 1, 1, 1), scale=0.105, pos=(0.5, 0, 0), command=self.cbVolumeMute_CheckedChanged, relief=None, pressEffect=False, isChecked=isChecked, image=img, image_scale=0.5, checkedImage=imgOFF, uncheckedImage=imgON) self.cbVolumeMute.setTransparency(True) self.cbVolumeMute.setImage() self.cbVolumeMute.reparentTo(self.frameMain) prcPath = os.path.join(basedir, "%s.prc"%appName) self.advancedOptions = DirectLabel( text=_("Advanced options can be made in the following text file\n%s")%prcPath, text_scale=0.5, text_fg=(1, 1, 1, 1), scale=0.1, pos=(0, 0, -0.25), frameColor=(0, 0, 0, 0)) self.advancedOptions.setTransparency(True) self.advancedOptions.reparentTo(self.frameMain) self.hide() def show(self): self.frameMain.show() def hide(self): self.frameMain.hide() def cbVolumeMute_CheckedChanged(self, checked): if checked: base.disableAllAudio() else: base.enableAllAudio() def sliderVolume_ValueChanged(self): volume = round(self.sliderVolume["value"], 2) self.sliderVolume["text"] = _("Volume %d%%") % int(volume * 100) base.sfxManagerList[0].setVolume(volume) base.musicManager.setVolume(volume)
def _draw(self): """ Draws this JoinGameDialogue """ winWidth = base.getAspectRatio() * 2 winHeight = 2 # Draw translucent background frame to block clicks: blockingFrame = DirectFrame(parent=base.a2dTopLeft, frameSize=(0, winWidth, -winHeight, 0), frameColor=(0, 0, 0, 0.5)) # Draw Main Dialogue Frame: dFOffsetY = 0.05 dFSizeX, dFSizeY = winWidth * (3 / 5), winHeight * (2 / 3) dialogueFrame = DirectFrame(pos=(-dFSizeX / 2, 0, dFSizeY / 2 + dFOffsetY), frameSize=(0, dFSizeX, -dFSizeY, 0), frameTexture=UI_WINDOW) dialogueFrame.setTransparency(TransparencyAttrib.MAlpha) # Draw Title Text: verticalMargin = 0.102 titleWidth = dFSizeX titleHeight = 0.15 titleFontSize = (0.15, 0.15) dialogueTitle = DirectLabel(parent=dialogueFrame, pos=(dFSizeX / 2, 0, -verticalMargin), frameSize=(-titleWidth / 2, titleWidth / 2, -titleHeight / 2, titleHeight / 2), frameTexture=IMG_GRADIENT_1, text_align=TextNode.ACenter, text_font=self._font, text_scale=titleFontSize, text_pos=PIERCEROMAN_OFFSET_MC, text="Join Party Configuration") self._drawControls(dialogueFrame) # Draw options for the pop-up frame. # Draw Back Button: buttonVerticalMargin = 0.203 buttonHeight = 0.2 buttonPosY = -1 - buttonVerticalMargin sidesMargin = 0.1 buttonWidth = dFSizeX / 2 - sidesMargin / 2 backButton = DirectButton(parent=dialogueFrame, pos=(dFSizeX / 2 - buttonWidth / 2, 0, -1 - buttonVerticalMargin), frameSize=(-buttonWidth / 2, buttonWidth / 2, -buttonHeight / 2, buttonHeight / 2), command=self.close, text="Back", text_font=self._font, text_scale=JOPTS_BUTON_FONT_SIZE, text_pos=JOPTS_BUTON_FONT_OFFSET, borderWidth=JOPTS_BUTTON_BORDER_WIDTH) # Draw Connect Button: connButton = DirectButton(parent=dialogueFrame, pos=(dFSizeX / 2 + buttonWidth / 2, 0, -1 - buttonVerticalMargin), frameSize=(-buttonWidth / 2, buttonWidth / 2, -buttonHeight / 2, buttonHeight / 2), command=self._onConnectButton, text_font=self._font, text="Connect", text_scale=JOPTS_BUTON_FONT_SIZE, text_pos=JOPTS_BUTON_FONT_OFFSET, borderWidth=JOPTS_BUTTON_BORDER_WIDTH) # Add parent elements to be deleted in self.close() self._elements.extend([blockingFrame, dialogueFrame])
class LegendaryFish(Fish): def __init__(self, fishManager, myData, index): Fish.__init__(self, fishManager, myData, index) self.fsm = LegendaryFishFSM(self) self.actor.setScale(self.myData['scaleRange'][0]) self.staminaValue = self.myData['stamina'] self.aboutToBitingInterval = None self.fishChaseLureSequence = Sequence() self.lfStruggleSequence = Sequence() self.initFishStaminaBar() self.lurePosition = None return def initFishStaminaBar(self): self.legendaryGui = loader.loadModel('models/minigames/pir_m_gam_fsh_legendaryGui') self.iconBaseFrame = DirectFrame(relief=None, state=DGG.DISABLED, pos=(0, 0, 0), sortOrder=30, image=self.legendaryGui.find('**/pir_t_gui_fsh_fishPortraitFrame'), image_scale=0.18, image_pos=(0, 0, 0)) self.iconBaseFrame.setTransparency(TransparencyAttrib.MAlpha) self.fishUINodePath = NodePath(self.iconBaseFrame) self.fishUINodePath.setPos(-0.3, 0.0, 0.83) self.fishUINodePath.reparentTo(hidden) self.iconCard = loader.loadModel('models/gui/treasure_gui') self.iconBaseFrame.iconImage = OnscreenImage(parent=self.iconBaseFrame, image=self.iconCard.find('**/%s*' % CollectionMap.Assets[self.myData['id']]), scale=0.35, hpr=(0, 0, 0), pos=(0.0, 0, 0.0)) self.fishNameLabel = TextNode('fishNameLabel') name = self.getName().split('_') self.fishNameLabel.setText(name[0]) self.fishNameLabel.setTextColor(1.0, 1.0, 1.0, 1.0) self.fishNameLabelNodePath = NodePath(self.fishNameLabel) self.fishNameLabelNodePath.setPos(0.3, 0, 0.04) self.fishNameLabelNodePath.setScale(0.045) self.fishNameLabelNodePath.reparentTo(self.iconBaseFrame) self.fishStaminaBar = DirectWaitBar(parent=self.iconBaseFrame, relief=DGG.FLAT, state=DGG.DISABLED, range=100, value=0, sortOrder=20, frameColor=(0, 0, 0, 1.0), pos=(0.07, 0.0, -0.015), hpr=(0, 0, 0), frameSize=(0, 0.72, 0, 0.028)) self.fishStaminaBar['value'] = self.staminaValue self.fishStaminaBar['barColor'] = FishingGlobals.fishingStaminaBarColor[int(self.staminaValue / 100.0 * (len(FishingGlobals.fishingStaminaBarColor) - 1))] self.fishStaminaValueLabel = TextNode('fishStaminaValueLabel') self.fishStaminaValueLabel.setText(str(self.staminaValue) + '//' + str(self.staminaValue)) self.fishStaminaValueLabel.setTextColor(1.0, 1.0, 1.0, 1.0) self.fishStaminaValueLabelNodePath = NodePath(self.fishStaminaValueLabel) self.fishStaminaValueLabelNodePath.setPos(0.66, 0, -0.06) self.fishStaminaValueLabelNodePath.setScale(0.045) self.fishStaminaValueLabelNodePath.reparentTo(self.iconBaseFrame) self.fishStaminaBarFrame = DirectLabel(parent=self.iconBaseFrame, relief=None, state=DGG.DISABLED, frameColor=(1, 1, 1, 0.1), pos=(0.44, 0.0, 0.0), hpr=(0, 0, 0), sortOrder=25, image=self.legendaryGui.find('**/pir_t_gui_fsh_staminaBarForeground'), image_scale=(1.0, 0.0, 0.05), image_pos=(0.0, 0.0, 0.0), image_hpr=(0.0, 0.0, 0.0)) self.fishStaminaBarFrame.setTransparency(TransparencyAttrib.MAlpha) self.fishStaminaBarFrame.setDepthTest(True) self.fishStaminaBarFrame.setDepthWrite(True) return def cleanFishData(self): self.staminaValue = self.myData['stamina'] self.fishStaminaBar['value'] = self.staminaValue self.fishStaminaValueLabel.setText(str(int(self.staminaValue)) + ' / ' + str(100)) self.fishStaminaBar['barColor'] = FishingGlobals.fishingStaminaBarColor[int(self.staminaValue / 100.0 * (len(FishingGlobals.fishingStaminaBarColor) - 1))] self.hideStaminaBar() taskMgr.remove('updateFishStaminaTask') self.lurePosition = None self.fishChaseLureSequence.pause() self.fishChaseLureSequence.clearToInitial() self.lfStruggleSequence.pause() self.lfStruggleSequence.clearToInitial() if self.aboutToBitingInterval is None: return self.aboutToBitingInterval.pause() return def destroy(self): self.fishUINodePath.removeNode() Fish.destroy(self) def updateFishStaminaTask(self, task=None): if self.staminaValue <= 1: return Task.done self.staminaValue = max(1, self.staminaValue - FishingGlobals.staminaReduceValue) self.fishStaminaValueLabel.setText(str(int(self.staminaValue)) + ' / ' + str(100)) self.fishStaminaBar['value'] = self.staminaValue self.fishStaminaBar['barColor'] = FishingGlobals.fishingStaminaBarColor[int(self.staminaValue / 100.0 * (len(FishingGlobals.fishingStaminaBarColor) - 1))] return Task.cont def updateFishStaminaBar(self): self.fishStaminaBar['value'] = self.staminaValue def fishStaminaConsume(self): taskMgr.add(self.updateFishStaminaTask, 'updateFishStaminaTask') def staminaPercentage(self): return self.staminaValue / self.myData['stamina'] def showStaminaBar(self): self.fishUINodePath.reparentTo(aspect2d) def hideStaminaBar(self): self.fishUINodePath.reparentTo(hidden) def performStraightBehavior(self, lurePos, dt): newX = self.getX() + self.velocity[0] * dt + self.accel[0] * dt * dt newZ = self.getZ() + self.velocity[2] * dt + self.accel[2] * dt * dt return ( newX, newZ)
class Archive: """docstring for Archive""" def __init__(self): self.archivesShotMsg = [] self.frameArchive = DirectFrame(image="gui/BackGround_a.png", image_scale=(1.7778, 1, 1), frameSize=(base.a2dLeft, base.a2dRight, base.a2dBottom, base.a2dTop), frameColor=(0, 0, 0, 0)) self.frameArchive.setTransparency(1) ArchiveFrameTexture = loader.loadTexture("gui/ArchiveFrameBG.png") self.frameArchive1 = DirectFrame( frameTexture=ArchiveFrameTexture, frameSize=(-1.4, -0.6, base.a2dBottom + 0.5, base.a2dTop - 0.4), frameColor=(1, 1, 1, 0.5), ) self.frameArchive1.reparentTo(self.frameArchive) self.frameArchive2 = DirectFrame(frameSize=(-0.4, 0.4, base.a2dBottom + 0.5, base.a2dTop - 0.4), frameColor=(1, 1, 1, 0.5), frameTexture=ArchiveFrameTexture) self.frameArchive2.reparentTo(self.frameArchive) self.frameArchive3 = DirectFrame(frameSize=(0.6, 1.4, base.a2dBottom + 0.5, base.a2dTop - 0.4), frameColor=(1, 1, 1, 0.5), frameTexture=ArchiveFrameTexture) self.frameArchive3.reparentTo(self.frameArchive) self.v = [0] self.archiveImg = loader.loadTexture("gui/ArchiveImg.png") self.questionMark = loader.loadTexture("gui/QuestionMark.jpg") self.pictures = [ DirectFrame(frameSize=(-1.3, -0.7, base.a2dBottom + 0.9, base.a2dTop - 0.5), frameColor=(1, 1, 1, 1), frameTexture=self.questionMark), DirectFrame(frameSize=(-0.3, 0.3, base.a2dBottom + 0.9, base.a2dTop - 0.5), frameColor=(1, 1, 1, 1), frameTexture=self.questionMark), DirectFrame(frameSize=(0.7, 1.3, base.a2dBottom + 0.9, base.a2dTop - 0.5), frameColor=(1, 1, 1, 1), frameTexture=self.questionMark) ] self.pictures[0].reparentTo(self.frameArchive1) self.pictures[1].reparentTo(self.frameArchive2) self.pictures[2].reparentTo(self.frameArchive3) self.buttons = [ DirectRadioButton(variable=self.v, value=[0], scale=0.05, pos=(-0.98, 0, base.a2dTop - 1.4), command=self.updateUI), DirectRadioButton(variable=self.v, value=[1], scale=0.05, pos=(0.02, 0, base.a2dTop - 1.4), command=self.updateUI), DirectRadioButton(variable=self.v, value=[2], scale=0.05, pos=(1.02, 0, base.a2dTop - 1.4), command=self.updateUI) ] self.buttons[0].reparentTo(self.frameArchive1) self.buttons[1].reparentTo(self.frameArchive2) self.buttons[2].reparentTo(self.frameArchive3) for button in self.buttons: button.setOthers(self.buttons) titles0 = [ OnscreenText(scale=.05, align=TextNode.ACenter, pos=(-1.0, base.a2dBottom + 0.85), text="time", fg=(0, 0, 0, 1)), OnscreenText(scale=.05, align=TextNode.ACenter, pos=(-1.0, base.a2dBottom + 0.8), text="room", fg=(0, 0, 0, 1)), # DirectLabel(frameColor = (0, 0, 0, 0),scale = .05, align = TextNode.ALeft, pos=(-1.1, 0, base.a2dBottom+0.75), text="attribute", fg = (0,0,0,1)) ] titles0[0].hide() titles0[1].hide() # titles0[0].reparentTo(self.frameArchive1) # titles0[1].reparentTo(self.frameArchive1) # titles0[2].reparentTo(self.frameArchive1) titles1 = [ OnscreenText(scale=.05, align=TextNode.ACenter, pos=(-0.0, base.a2dBottom + 0.85), text="time", fg=(0, 0, 0, 1)), OnscreenText(scale=.05, align=TextNode.ACenter, pos=(-0.0, base.a2dBottom + 0.8), text="room", fg=(0, 0, 0, 1)), # DirectLabel(frameColor = (0, 0, 0, 0),scale = .05, align = TextNode.ALeft, pos=(-0.1, 0, base.a2dBottom+0.75), text="attribute", fg = (0,0,0,1)) ] titles1[0].hide() titles1[1].hide() # titles1[0].reparentTo(self.frameArchive2) # titles1[1].reparentTo(self.frameArchive2) # titles1[2].reparentTo(self.frameArchive2) titles2 = [ OnscreenText(scale=.05, align=TextNode.ACenter, pos=(1, base.a2dBottom + 0.85), text="time", fg=(0, 0, 0, 1)), OnscreenText(scale=.05, align=TextNode.ACenter, pos=(1, base.a2dBottom + 0.8), text="room", fg=(0, 0, 0, 1)), # DirectLabel(frameColor = (0, 0, 0, 0),scale = .05, align = TextNode.ALeft, pos=(0.9, 0, base.a2dBottom+0.75), text="attribute", fg = (0,0,0,1)) ] titles2[0].hide() titles2[1].hide() # titles2[0].reparentTo(self.frameArchive3) # titles2[1].reparentTo(self.frameArchive3) # titles2[2].reparentTo(self.frameArchive3) self.title = [titles0, titles1, titles2] self.btn_load = self.createButton("Load", -0.6, ["LoadArchive"]) self.btn_delete = self.createButton("Delete", -0.8, ["DeleteArchive"]) self.btn_newgame = self.createButton("NewGame", -0.7, ["NewGame"]) self.hide() def createButton(self, text, horizontalPos, eventArgs): sound = loader.loadSfx("Audio/click.wav") maps = loader.loadModel("gui/button_map") btnGeom = (maps.find("**/btn_ready"), maps.find("**/btn_click"), maps.find("**/btn_rollover"), maps.find("**/btn_disabled")) btn = DirectButton( text=text, text_fg=(1, 1, 1, 1), text_scale=0.05, text_pos=(0.125, -0.013), text_align=TextNode.ALeft, scale=2, geom=btnGeom, pos=(base.a2dRight - 0.6, 0, horizontalPos), # pos = (horizontalPos, 0, -.7), relief=0, frameColor=(0, 0, 0, 0), command=base.messenger.send, extraArgs=eventArgs, pressEffect=True, rolloverSound=None, clickSound=sound) btn.reparentTo(self.frameArchive) return btn def updateUI(self): if len(self.archivesShotMsg) == 0: base.messenger.send("UpdateArchive") else: if len(self.archivesShotMsg[self.v[0]]) == 0: self.btn_delete.hide() self.btn_load.hide() self.btn_newgame.show() else: self.btn_delete.show() self.btn_load.show() self.btn_newgame.hide() def show(self, archiveListShortMsg): self.archivesShotMsg = archiveListShortMsg for index in range(3): self.title[index][0].show() self.title[index][1].show() if len(self.archivesShotMsg[index]) == 0: self.pictures[index]["frameTexture"] = self.questionMark self.title[index][0].setText("?") self.title[index][1].setText("?") else: self.pictures[index]["frameTexture"] = self.archiveImg self.title[index][0].setText( "createTime : " + str(archiveListShortMsg[index]["timestamp"])) self.title[index][1].setText( "currRoom : " + str(archiveListShortMsg[index]["currRoom"])) self.updateUI() self.frameArchive.show() def hide(self): for index in range(3): self.title[index][0].hide() self.title[index][1].hide() self.frameArchive.hide()
class Menu: def __init__(self): self.frameMain = DirectFrame( image = "gui/MenuBackground.png", image_scale = (1.7778, 1, 1), frameSize = (base.a2dLeft, base.a2dRight, base.a2dTop, base.a2dBottom), frameColor = (0, 0, 0, 0)) self.frameMain.setTransparency(1) self.title = DirectLabel( scale = 0.15, text_align = TextNode.ALeft, pos = (base.a2dLeft + 0.2, 0, 0), frameColor = (0, 0, 0, 0), text = "Main Menu", text_fg = (1,1,1,1)) self.title.setTransparency(1) self.title.reparentTo(self.frameMain) self.btnStart = self.createButton( "Start", -.10, ["Menu-Start"]) self.btnStart = self.createButton( "Credits", -.25, ["Menu-Credits"]) self.btnExit = self.createButton( "Quit", -.40, ["Menu-Quit"]) self.hide() def createButton(self, text, verticalPos, eventArgs): maps = loader.loadModel("gui/button_map") btnGeom = (maps.find("**/btn_ready"), maps.find("**/btn_click"), maps.find("**/btn_rollover"), maps.find("**/btn_disabled")) btn = DirectButton( text = text, text_fg = (0,0,0,1), text_scale = 0.05, text_pos = (0.02, -0.015), text_align = TextNode.ALeft, scale = 2, pos = (base.a2dLeft + 0.2, 0, verticalPos), geom = btnGeom, relief = 0, frameColor = (0,0,0,0), command = base.messenger.send, extraArgs = eventArgs, pressEffect = False, rolloverSound = None, clickSound = None) btn.reparentTo(self.frameMain) def show(self): self.frameMain.show() def hide(self): self.frameMain.hide()
class MechanicDesc: """Teaching description of a game mechanic. Are shown on particular world blocks on the game start. Args: mechanic (str): The name of the game mechanic to be explained. """ def __init__(self, mechanic): self._page = 0 self._fr = DirectFrame( frameSize=(-0.5, 0.5, -0.5, 0.5), frameColor=(0.14, 0.14, 0.14, 0.82), state=DGG.NORMAL, ) DirectLabel( parent=self._fr, text=base.labels.MAIN_MENU[23] + " " + mechanic, # noqa: F821 text_fg=RUST_COL, text_font=base.main_font, # noqa: F821 text_scale=0.038, pos=(0, 0, 0.44), frameColor=(0, 0, 0, 0), ) self._preview = DirectFrame( # an image describing the mechanic parent=self._fr, frameTexture="teach_shots/{}.png".format( base.labels.MECHANIC_DESC[mechanic]["previews"][ # noqa: F821 self._page]), pos=(0, 0, 0.15), frameSize=(-0.39, 0.39, -0.24, 0.24), ) self._preview.setTransparency(TransparencyAttrib.MAlpha) self._desc = DirectLabel( # the mechanic description parent=self._fr, pos=(0, 0, -0.18), frameColor=(0, 0, 0, 0), text_fg=SILVER_COL, text_scale=0.035, text=base.labels.MECHANIC_DESC[mechanic]["descs"][ self._page], # noqa: F821 text_font=base.main_font, # noqa: F821 ) is_last_page = self._page + 1 == len( base.labels.MECHANIC_DESC[mechanic]["descs"] # noqa: F821 ) self._but = DirectButton( parent=self._fr, text=base.labels.MECHANIC_BUTS[1] # noqa: F821 if is_last_page else base.labels.MECHANIC_BUTS[0], # noqa: F821 text_font=base.main_font, # noqa: F821 text_scale=0.04, relief=None, pos=(0, 0, -0.45), text_fg=RUST_COL, command=self._hide if is_last_page else self._next_page, extraArgs=[] if is_last_page else [mechanic], clickSound=base.main_menu.click_snd, # noqa: F821 ) base.main_menu.bind_button(self._but) # noqa: F821 base.train.ctrl.pause_movement() # noqa: F821 def _hide(self): """Destroy the teaching note.""" self._fr.destroy() base.train.ctrl.start_move() # noqa: F821 def _next_page(self, mechanic): """Show the next page of the mechanic tutorial. Args: mechanic (str): The explained mechanic name. """ self._page += 1 if self._page + 1 == len( base.labels.MECHANIC_DESC[mechanic]["descs"] # noqa: F821 ): self._but["text"] = base.labels.MECHANIC_BUTS[1] # noqa: F821 self._but["command"] = self._hide self._but["extraArgs"] = [] self._preview["frameTexture"] = "teach_shots/{}.png".format( base.labels.MECHANIC_DESC[mechanic]["previews"][ self._page] # noqa: F821 ) self._desc["text"] = base.labels.MECHANIC_DESC[mechanic][ "descs"][ # noqa: F821 self._page]
class Transitions: # These may be reassigned before the fade or iris transitions are # actually invoked to change the models that will be used. IrisModelName = "models/misc/iris" FadeModelName = "models/misc/fade" def __init__(self, loader, model=None, scale=3.0, pos=Vec3(0, 0, 0)): self.transitionIval = None self.letterboxIval = None self.iris = None self.fade = None self.letterbox = None self.fadeModel = model self.imagePos = pos if model: self.alphaOff = Vec4(1, 1, 1, 0) self.alphaOn = Vec4(1, 1, 1, 1) model.setTransparency(1) self.lerpFunc = LerpColorScaleInterval else: self.alphaOff = Vec4(0, 0, 0, 0) self.alphaOn = Vec4(0, 0, 0, 1) self.lerpFunc = LerpColorInterval self.irisTaskName = "irisTask" self.fadeTaskName = "fadeTask" self.letterboxTaskName = "letterboxTask" def __del__(self): if self.fadeModel: self.fadeModel.removeNode() self.fadeModel = None ################################################## # Fade ################################################## # We can set a custom model for the fade before using it for the first time def setFadeModel(self, model, scale=1.0): self.fadeModel = model # We have to change some default parameters for a custom fadeModel self.alphaOn = Vec4(1, 1, 1, 1) # Reload fade if its already been created if self.fade: self.fade.destroy() self.fade = None self.loadFade() def loadFade(self): if self.fade is None: # We create a DirectFrame for the fade polygon, instead of # simply loading the polygon model and using it directly, # so that it will also obscure mouse events for objects # positioned behind it. self.fade = DirectFrame( parent=hidden, guiId='fade', relief=None, image=self.fadeModel, image_scale=(4, 2, 2), state=DGG.NORMAL, ) if not self.fadeModel: # No fade model was given, so we make this the fade model. self.fade["relief"] = DGG.FLAT self.fade["frameSize"] = (-2, 2, -1, 1) self.fade["frameColor"] = (0, 0, 0, 1) self.fade.setTransparency(TransparencyAttrib.MAlpha) self.fade.setBin('unsorted', 0) self.fade.setColor(0, 0, 0, 0) def getFadeInIval(self, t=0.5, finishIval=None): """ Returns an interval without starting it. This is particularly useful in cutscenes, so when the cutsceneIval is escaped out of we can finish the fade immediately """ #self.noTransitions() masad: this creates a one frame pop, is it necessary? self.loadFade() transitionIval = Sequence( Func(self.fade.reparentTo, aspect2d, DGG.FADE_SORT_INDEX), Func(self.fade.showThrough ), # in case aspect2d is hidden for some reason self.lerpFunc( self.fade, t, self.alphaOff, # self.alphaOn, ), Func(self.fade.detachNode), name=self.fadeTaskName, ) if finishIval: transitionIval.append(finishIval) return transitionIval def getFadeOutIval(self, t=0.5, finishIval=None): """ Create a sequence that lerps the color out, then parents the fade to hidden """ self.noTransitions() self.loadFade() transitionIval = Sequence( Func(self.fade.reparentTo, aspect2d, DGG.FADE_SORT_INDEX), Func(self.fade.showThrough ), # in case aspect2d is hidden for some reason self.lerpFunc( self.fade, t, self.alphaOn, # self.alphaOff, ), name=self.fadeTaskName, ) if finishIval: transitionIval.append(finishIval) return transitionIval def fadeIn(self, t=0.5, finishIval=None): """ Play a fade in transition over t seconds. Places a polygon on the aspect2d plane then lerps the color from black to transparent. When the color lerp is finished, it parents the fade polygon to hidden. """ gsg = base.win.getGsg() if gsg: # If we're about to fade in from black, go ahead and # preload all the textures etc. base.graphicsEngine.renderFrame() render.prepareScene(gsg) render2d.prepareScene(gsg) if (t == 0): # Fade in immediately with no lerp #print "transitiosn: fadeIn 0.0" self.noTransitions() self.loadFade() self.fade.detachNode() else: # Create a sequence that lerps the color out, then # parents the fade to hidden self.transitionIval = self.getFadeInIval(t, finishIval) self.transitionIval.start() def fadeOut(self, t=0.5, finishIval=None): """ Play a fade out transition over t seconds. Places a polygon on the aspect2d plane then lerps the color from transparent to full black. When the color lerp is finished, it leaves the fade polygon covering the aspect2d plane until you fadeIn or call noFade. lerp """ if (t == 0): # Fade out immediately with no lerp self.noTransitions() self.loadFade() self.fade.reparentTo(aspect2d, DGG.FADE_SORT_INDEX) self.fade.setColor(self.alphaOn) elif ConfigVariableBool('no-loading-screen', False): if finishIval: self.transitionIval = finishIval self.transitionIval.start() else: # Create a sequence that lerps the color out, then # parents the fade to hidden self.transitionIval = self.getFadeOutIval(t, finishIval) self.transitionIval.start() def fadeOutActive(self): return self.fade and self.fade.getColor()[3] > 0 def fadeScreen(self, alpha=0.5): """ Put a semitransparent screen over the camera plane to darken out the world. Useful for drawing attention to a dialog box for instance """ #print "transitiosn: fadeScreen" self.noTransitions() self.loadFade() self.fade.reparentTo(aspect2d, DGG.FADE_SORT_INDEX) self.fade.setColor(self.alphaOn[0], self.alphaOn[1], self.alphaOn[2], alpha) def fadeScreenColor(self, color): """ Put a semitransparent screen over the camera plane to darken out the world. Useful for drawing attention to a dialog box for instance """ #print "transitiosn: fadeScreenColor" self.noTransitions() self.loadFade() self.fade.reparentTo(aspect2d, DGG.FADE_SORT_INDEX) self.fade.setColor(color) def noFade(self): """ Removes any current fade tasks and parents the fade polygon away """ #print "transitiosn: noFade" if self.transitionIval: self.transitionIval.pause() self.transitionIval = None if self.fade: # Make sure to reset the color, since fadeOutActive() is looking at it self.fade.setColor(self.alphaOff) self.fade.detachNode() def setFadeColor(self, r, g, b): self.alphaOn.set(r, g, b, 1) self.alphaOff.set(r, g, b, 0) ################################################## # Iris ################################################## def loadIris(self): if self.iris == None: self.iris = loader.loadModel(self.IrisModelName) self.iris.setPos(0, 0, 0) def irisIn(self, t=0.5, finishIval=None): """ Play an iris in transition over t seconds. Places a polygon on the aspect2d plane then lerps the scale of the iris polygon up so it looks like we iris in. When the scale lerp is finished, it parents the iris polygon to hidden. """ self.noTransitions() self.loadIris() if (t == 0): self.iris.detachNode() else: self.iris.reparentTo(aspect2d, DGG.FADE_SORT_INDEX) self.transitionIval = Sequence( LerpScaleInterval(self.iris, t, scale=0.18, startScale=0.01), Func(self.iris.detachNode), name=self.irisTaskName, ) if finishIval: self.transitionIval.append(finishIval) self.transitionIval.start() def irisOut(self, t=0.5, finishIval=None): """ Play an iris out transition over t seconds. Places a polygon on the aspect2d plane then lerps the scale of the iris down so it looks like we iris out. When the scale lerp is finished, it leaves the iris polygon covering the aspect2d plane until you irisIn or call noIris. """ self.noTransitions() self.loadIris() self.loadFade() # we need this to cover up the hole. if (t == 0): self.iris.detachNode() self.fadeOut(0) else: self.iris.reparentTo(aspect2d, DGG.FADE_SORT_INDEX) self.transitionIval = Sequence( LerpScaleInterval(self.iris, t, scale=0.01, startScale=0.18), Func(self.iris.detachNode), # Use the fade to cover up the hole that the iris would leave Func(self.fadeOut, 0), name=self.irisTaskName, ) if finishIval: self.transitionIval.append(finishIval) self.transitionIval.start() def noIris(self): """ Removes any current iris tasks and parents the iris polygon away """ if self.transitionIval: self.transitionIval.pause() self.transitionIval = None if self.iris != None: self.iris.detachNode() # Actually we need to remove the fade too, # because the iris effect uses it. self.noFade() def noTransitions(self): """ This call should immediately remove any and all transitions running """ self.noFade() self.noIris() # Letterbox is not really a transition, it is a screen overlay # self.noLetterbox() ################################################## # Letterbox ################################################## def loadLetterbox(self): if not self.letterbox: # We create a DirectFrame for the fade polygon, instead of # simply loading the polygon model and using it directly, # so that it will also obscure mouse events for objects # positioned behind it. self.letterbox = NodePath("letterbox") # Allow fade in and out of the bars self.letterbox.setTransparency(1) # Allow DirectLabels to be parented to the letterbox sensibly self.letterbox.setBin('unsorted', 0) # Allow a custom look to the letterbox graphic. # TODO: This model isn't available everywhere. We should # pass it in as a parameter. button = loader.loadModel('models/gui/toplevel_gui', okMissing=True) barImage = None if button: barImage = button.find('**/generic_button') self.letterboxTop = DirectFrame( parent=self.letterbox, guiId='letterboxTop', relief=DGG.FLAT, state=DGG.NORMAL, frameColor=(0, 0, 0, 1), borderWidth=(0, 0), frameSize=(-1, 1, 0, 0.2), pos=(0, 0, 0.8), image=barImage, image_scale=(2.25, 1, .5), image_pos=(0, 0, .1), image_color=(0.3, 0.3, 0.3, 1), sortOrder=0, ) self.letterboxBottom = DirectFrame( parent=self.letterbox, guiId='letterboxBottom', relief=DGG.FLAT, state=DGG.NORMAL, frameColor=(0, 0, 0, 1), borderWidth=(0, 0), frameSize=(-1, 1, 0, 0.2), pos=(0, 0, -1), image=barImage, image_scale=(2.25, 1, .5), image_pos=(0, 0, .1), image_color=(0.3, 0.3, 0.3, 1), sortOrder=0, ) # masad: always place these at the bottom of render self.letterboxTop.setBin('sorted', 0) self.letterboxBottom.setBin('sorted', 0) self.letterbox.reparentTo(render2d, -1) self.letterboxOff(0) def noLetterbox(self): """ Removes any current letterbox tasks and parents the letterbox polygon away """ if self.letterboxIval: self.letterboxIval.pause() self.letterboxIval = None if self.letterbox: self.letterbox.stash() def letterboxOn(self, t=0.25, finishIval=None): """ Move black bars in over t seconds. """ self.noLetterbox() self.loadLetterbox() self.letterbox.unstash() if (t == 0): self.letterboxBottom.setPos(0, 0, -1) self.letterboxTop.setPos(0, 0, 0.8) else: self.letterboxIval = Sequence( Parallel( LerpPosInterval( self.letterboxBottom, t, pos=Vec3(0, 0, -1), #startPos = Vec3(0, 0, -1.2), ), LerpPosInterval( self.letterboxTop, t, pos=Vec3(0, 0, 0.8), # startPos = Vec3(0, 0, 1), ), ), name=self.letterboxTaskName, ) if finishIval: self.letterboxIval.append(finishIval) self.letterboxIval.start() def letterboxOff(self, t=0.25, finishIval=None): """ Move black bars away over t seconds. """ self.noLetterbox() self.loadLetterbox() self.letterbox.unstash() if (t == 0): self.letterbox.stash() else: self.letterboxIval = Sequence( Parallel( LerpPosInterval( self.letterboxBottom, t, pos=Vec3(0, 0, -1.2), # startPos = Vec3(0, 0, -1), ), LerpPosInterval( self.letterboxTop, t, pos=Vec3(0, 0, 1), # startPos = Vec3(0, 0, 0.8), ), ), Func(self.letterbox.stash), Func(messenger.send, 'letterboxOff'), name=self.letterboxTaskName, ) if finishIval: self.letterboxIval.append(finishIval) self.letterboxIval.start()
class Hud(): def __init__(self): wp = base.win.getProperties() aspX = 1.0 aspY = 1.0 wpXSize = wp.getXSize() wpYSize = wp.getYSize() aspect = wpXSize / float(wpYSize) paneWidth = 0.4444445 self.frameMain = DirectFrame( image="hudBackground.png", image_scale=(paneWidth, 1, 1), image_pos=(paneWidth, 0, 0), frameSize=( 0, base.a2dRight/2.0, base.a2dBottom, base.a2dTop), frameColor=(0, 0, 0, 0), pos=(base.a2dLeft, 0, 0)) self.frameMain.setTransparency(True) self.frameRightPane = DirectFrame( image="hudBackgroundRight.png", image_scale=(paneWidth, 1, 1), image_pos=(-paneWidth, 0, 0), frameSize=( base.a2dLeft/2.0, 0, base.a2dBottom, base.a2dTop), frameColor=(0, 0, 0, 0), pos=(base.a2dRight, 0, 0)) self.frameRightPane.setTransparency(True) self.hide() self.lblScore = DirectLabel( text="Scoreboard", text_fg=(240/255.0,255/255.0,240/255.0,1), scale=0.1, pos=(paneWidth,0,0.8), frameColor=(0,0,0,0),) self.lblScore.setTransparency(True) self.lblScore.reparentTo(self.frameMain) self.lblReds = DirectLabel( text="Bad dudes: 0", text_fg=(240/255.0,255/255.0,240/255.0,1), text_align=TextNode.ALeft, scale=0.08, pos=(0.1,0,0.5), frameColor=(0,0,0,0),) self.lblReds.setTransparency(True) self.lblReds.reparentTo(self.frameMain) self.lblBlues = DirectLabel( text="Good dudes: 0", text_fg=(240/255.0,255/255.0,240/255.0,1), text_align=TextNode.ALeft, scale=0.08, pos=(0.1,0,0.3), frameColor=(0,0,0,0),) self.lblBlues.setTransparency(True) self.lblBlues.reparentTo(self.frameMain) self.hide() txt = "" if base.difficulty == 0: txt = "Get 25 good dudes.\nIf you have more red\ndudes than blue,\nyou loose." elif base.difficulty == 1: txt = "Get 50 good dudes.\nIf you have more red\ndudes than blue,\nyou loose." else: txt = "Get 100 good dudes.\nIf you have more red\ndudes than blue,\nyou loose." self.lblInfoWinCondition = DirectLabel( text=txt, text_fg=(240/255.0,255/255.0,240/255.0,1), text_align=TextNode.ALeft, scale=0.08, pos=(0.1,0,0.0), frameColor=(0,0,0,0),) self.lblInfoWinCondition.setTransparency(True) self.lblInfoWinCondition.reparentTo(self.frameMain) self.hide() self.lblInfo = DirectLabel( text="Controlls", text_fg=(240/255.0,255/255.0,240/255.0,1), scale=0.1, pos=(-paneWidth,0,0.8), frameColor=(0,0,0,0),) self.lblInfo.setTransparency(True) self.lblInfo.reparentTo(self.frameRightPane) self.lblRight = DirectLabel( text="~ Right Door ~\nRight Arrow\nRight Alt\nRight Ctrl\n/", text_fg=(240/255.0,255/255.0,240/255.0,1), scale=0.05, pos=(-paneWidth,0,0.7), frameColor=(0,0,0,0), sortOrder = 0) self.lblRight.setTransparency(True) self.lblRight.reparentTo(self.frameRightPane) self.lblLeft = DirectLabel( text="~ Left Door ~\nLeft Arrow\nLeft Alt\nLeft Ctrl\nZ", text_fg=(240/255.0,255/255.0,240/255.0,1), scale=0.05, pos=(-paneWidth,0,0.4), frameColor=(0,0,0,0),) self.lblLeft.setTransparency(True) self.lblLeft.reparentTo(self.frameRightPane) def show(self): self.frameMain.show() self.frameRightPane.show() def hide(self): self.frameMain.hide() self.frameRightPane.hide() def update(self, redDudes, blueDudes): self.lblReds["text"] = "Bad dudes: {}".format(redDudes) self.lblBlues["text"] = "Good dudes: {}".format(blueDudes)
class CharacterSelection: def __init__(self): self.frameMain = DirectFrame( frameSize = (base.a2dLeft, base.a2dRight, base.a2dBottom, base.a2dTop), frameColor = (0.05, 0.05, 0.05, 1)) self.frameMain.setTransparency(1) width = abs(base.a2dLeft) + base.a2dRight red = loader.loadTexture("assets/gui/CharRedBG.png") red.setWrapU(Texture.WM_repeat) red.setWrapV(Texture.WM_repeat) self.char1Frame = DirectFrame( text = "Player 1", text_fg = (1,1,1,1), text_scale = 0.1, text_pos = (0, base.a2dTop - 0.2), frameSize = (-width/6.0, width/6.0, base.a2dBottom, base.a2dTop), frameTexture = red, pos = (base.a2dLeft+width/6.0, 0, 0)) self.char1Frame.updateFrameStyle() self.char1Frame.setTransparency(1) self.char1Frame.reparentTo(self.frameMain) blue = loader.loadTexture("assets/gui/CharBlueBG.png") blue.setWrapU(Texture.WM_repeat) blue.setWrapV(Texture.WM_repeat) self.char2Frame = DirectFrame( text = "Player 2", text_fg = (1,1,1,1), text_scale = 0.1, text_pos = (0, base.a2dTop - 0.2), frameSize = (-width/6.0, width/6.0, base.a2dBottom, base.a2dTop), frameTexture = blue, pos = (base.a2dRight-width/6.0, 0, 0)) self.char2Frame.setTransparency(1) self.char2Frame.reparentTo(self.frameMain) self.footerFrame = DirectFrame( text = "PLAYER 1 - CHOOSE YOUR CHARACTER", text_fg = (1,1,1,1), text_scale = 0.08, text_pos = (0, -0.03), frameSize = (base.a2dLeft, base.a2dRight, 0.1, -0.1), pos = (0, 0, base.a2dBottom + 0.2), frameColor = (0, 0, 0, 0.5)) self.footerFrame.setTransparency(1) self.footerFrame.reparentTo(self.frameMain) self.charSelectFrame = DirectFrame( text = "VS", text_fg = (1,1,1,1), text_scale = 0.1, text_pos = (0, base.a2dTop - 0.2), frameSize = (-width/6.0, width/6.0, base.a2dBottom, base.a2dTop), frameColor = (0,0,0,0)) self.charSelectFrame.reparentTo(self.frameMain) self.btnChar1 = self.createCharacterButton( (-0.2, 0, 0), "assets/gui/Char1Button.png", 1) self.btnChar1.reparentTo(self.charSelectFrame) self.btnChar2 = self.createCharacterButton( (0.2, 0, 0), "assets/gui/Char2Button.png", 2) self.btnChar2.reparentTo(self.charSelectFrame) self.btnBack = DirectButton( text = "BACK", text_fg = (1,1,1,1), text_align = TextNode.ALeft, scale = 0.1, pad = (0.15, 0.15), pos = (base.a2dLeft + 0.08, 0, -0.03), frameColor = ( (0.2,0.2,0.2,0.8), (0.4,0.4,0.4,0.8), (0.4,0.4,0.4,0.8), (0.1,0.1,0.1,0.8)), relief = 1, command = base.messenger.send, extraArgs = ["CharSelection-Back"], pressEffect = False, rolloverSound = None, clickSound = None) self.btnBack.setTransparency(1) self.btnBack.reparentTo(self.footerFrame) self.btnStart = DirectButton( text = "START", text_fg = (1,1,1,1), text_align = TextNode.ARight, scale = 0.1, pad = (0.15, 0.15), pos = (base.a2dRight - 0.08, 0, -0.03), relief = 1, frameColor = ( (0.2,0.2,0.2,0.8), (0.4,0.4,0.4,0.8), (0.4,0.4,0.4,0.8), (0.1,0.1,0.1,0.8)), command = base.messenger.send, extraArgs = ["CharSelection-Start"], pressEffect = False, rolloverSound = None, clickSound = None) self.btnStart.setTransparency(1) self.btnStart.reparentTo(self.footerFrame) self.btnStart["state"] = DGG.DISABLED self.hide() def createCharacterButton(self, pos, image, charNr): btn = DirectButton( scale = 0.1, relief = 0, frameColor = (0,0,0,0), pos = pos, image = image, command = self.selectCharacter, extraArgs = [charNr], rolloverSound = None, clickSound = None) btn.setTransparency(1) return btn def selectCharacter(self, charNr): if self.char1Frame["image"] == None: self.char1Frame["image"] = "assets/gui/Char{}_L.png".format(charNr) self.char1Frame["image_scale"] = (0.5,1, 1) self.selectedCharacter1 = charNr self.footerFrame["text"] = "PLAYER 2 - CHOOSE YOUR CHARACTER" elif self.char2Frame["image"] == None: self.char2Frame["image"] = "assets/gui/Char{}_R.png".format(charNr) self.char2Frame["image_scale"] = (0.5,1, 1) self.selectedCharacter2 = charNr self.btnStart["state"] = DGG.NORMAL self.footerFrame["text"] = "START THE FIGHT >" def show(self): self.selectedCharacter1 = None self.selectedCharacter2 = None self.char1Frame["image"] = None self.char2Frame["image"] = None self.footerFrame["text"] = "PLAYER 1 - CHOOSE YOUR CHARACTER" self.btnStart["state"] = DGG.DISABLED self.frameMain.show() def hide(self): self.frameMain.hide()
def __init__(self): self._weapon_buts = {} self._turn_snd = loader.loadSfx( # noqa: F821 "sounds/train/railroad_switch.ogg" ) frame = DirectFrame( parent=base.a2dBottomRight, # noqa: F821 frameSize=(-0.09, 0.09, -0.28, 0.28), pos=(-0.09, 0, 0.28), frameTexture=GUI_PIC + "metal1.png", ) frame.setTransparency(TransparencyAttrib.MAlpha) DirectFrame( # an icon for the locomotive durability parent=frame, frameSize=(-0.023, 0.023, -0.023, 0.023), pos=(0.05, 0, 0.24), frameTexture=GUI_PIC + "train.png", ).setTransparency(TransparencyAttrib.MAlpha) DirectFrame( # an icon for the locomotive speed parent=frame, frameSize=(-0.028, 0.028, -0.023, 0.023), pos=(-0.012, 0, 0.24), frameTexture=GUI_PIC + "speed.png", ).setTransparency(TransparencyAttrib.MAlpha) self._durability = DirectWaitBar( parent=frame, frameSize=(-0.225, 0.225, -0.002, 0.002), frameColor=(0.35, 0.35, 0.35, 1), range=1000, value=1000, barColor=(0.42, 0.42, 0.8, 1), pos=(0.05, 0, -0.025), ) self._durability.setR(-90) self._speed = DirectWaitBar( parent=frame, frameSize=(-0.225, 0.225, -0.002, 0.002), frameColor=(0.35, 0.35, 0.35, 1), range=1, value=1, barColor=(1, 0.63, 0, 0.6), pos=(-0.012, 0, -0.025), ) self._speed.setR(-90) DirectLabel( # speed gauge scale parent=frame, pos=(-0.05, 0, 0.19), frameSize=(-0.25, 0.25, -0.01, 0.01), frameColor=(0, 0, 0, 0), text="40-\n\n-\n\n-\n\n-\n\n20-\n\n-\n\n-\n\n-\n\n0-", text_scale=0.028, text_fg=SILVER_COL, ) frame_miles = DirectFrame( frameSize=(-0.115, 0.115, -0.06, 0.05), pos=(0, 0, -0.95), frameTexture=GUI_PIC + "metal1.png", sortOrder=-1, ) frame_miles.set_transparency(TransparencyAttrib.MAlpha) but = DirectButton( parent=frame_miles, frameSize=(-0.015, 0.015, -0.025, 0.025), frameTexture=GUI_PIC + "grenade.png", pos=(-0.075, 0, 0.015), relief="flat", ) but.setTransparency(TransparencyAttrib.MAlpha) but.bind(DGG.ENTER, self._highlight_weapon_but, extraArgs=[but]) but.bind(DGG.EXIT, self._dehighlight_weapon_but, extraArgs=[but]) self._weapon_buts["Grenade Launcher"] = { "but": but, "reload_step": 0, "dis_command": None, "reloading_len": 13, "frame": DirectFrame( parent=frame_miles, frameColor=(0, 0, 0, 0.25), pos=(-0.075, 0, -0.01), frameSize=(-0.013, 0.013, 0, 0.05), ), } but = DirectButton( parent=frame_miles, frameSize=(-0.015, 0.015, -0.025, 0.025), frameTexture=GUI_PIC + "machine_gun.png", pos=(0, 0, 0.015), relief="flat", ) but.setTransparency(TransparencyAttrib.MAlpha) but.bind(DGG.ENTER, self._highlight_weapon_but, extraArgs=[but]) but.bind(DGG.EXIT, self._dehighlight_weapon_but, extraArgs=[but]) self._weapon_buts["Machine Gun"] = { "but": but, "reload_step": 0, "dis_command": None, "reloading_len": 22, "frame": DirectFrame( parent=frame_miles, frameColor=(0, 0, 0, 0.25), pos=(0, 0, -0.01), frameSize=(-0.013, 0.013, 0, 0.05), ), } but = DirectButton( parent=frame_miles, frameSize=(-0.015, 0.015, -0.025, 0.025), frameTexture=GUI_PIC + "cluster_rocket.png", pos=(0.075, 0, 0.015), relief="flat", ) but.setTransparency(TransparencyAttrib.MAlpha) but.bind(DGG.ENTER, self._highlight_weapon_but, extraArgs=[but]) but.bind(DGG.EXIT, self._dehighlight_weapon_but, extraArgs=[but]) self._weapon_buts["Cluster Howitzer"] = { "but": but, "reload_step": 0, "dis_command": None, "reloading_len": 45, "frame": DirectFrame( parent=frame_miles, frameColor=(0, 0, 0, 0.25), pos=(0.075, 0, -0.01), frameSize=(-0.013, 0.013, 0, 0.05), ), } self._miles_meter = DirectLabel( parent=frame_miles, text="0000000", text_font=base.main_font, # noqa: F821 frameSize=(0.1, 0.1, 0.15, 0.15), text_scale=(0.033, 0.031), text_fg=RUST_COL, pos=(0, 0, -0.04), ) taskMgr.doMethodLater( # noqa: F821 0.25, self._update_speed, "update_speed_indicator" ) self._fork_lab = None
class OptionsMenu(DirectObject): def __init__(self): """Default constructor""" # create a main frame as big as the window self.frameMain = DirectFrame( # set framesize the same size as the window frameSize=(base.a2dLeft, base.a2dRight, base.a2dTop, base.a2dBottom), image="LogoTextGlow.png", image_scale=(1.06 / 2.0, 1, 0.7 / 2.0), image_pos=(0, 0, 0.7), # position center pos=(0, 0, 0), # set tramsparent background color frameColor=(0, 0, 0, 0)) self.frameMain.setTransparency(1) self.frameMain.setBin("fixed", 100) sliderscale = 0.5 buttonScale = 0.25 textscale = 0.1 checkboxscale = 0.05 left = -0.5 right = 0.5 self.sliderTextspeed = DirectSlider( scale=sliderscale, pos=(left, 0, 0.2), range=(0.2, 0.01), scrollSize=0.01, text=_("Textspeed %0.1f%%") % (base.textWriteSpeed * 10), text_scale=textscale, text_align=TextNode.ACenter, text_pos=(0.0, 0.15), text_fg=(1, 1, 1, 1), thumb_frameColor=(0.65, 0.65, 0.0, 1), thumb_relief=DGG.FLAT, frameColor=(0.15, 0.15, 0.15, 1), value=base.textWriteSpeed, command=self.sliderTextspeed_ValueChanged) self.sliderTextspeed.reparentTo(self.frameMain) self.cbParticles = DirectCheckButton( text=_(" Enable Particles"), text_fg=(1, 1, 1, 1), text_shadow=(0, 0, 0, 0.35), pos=(left, 0, -0.0), scale=checkboxscale, frameColor=(0, 0, 0, 0), command=self.cbParticles_CheckedChanged, rolloverSound=None, clickSound=None, pressEffect=False, boxPlacement="below", boxBorder=0.8, boxRelief=DGG.FLAT, indicator_scale=1.5, indicator_text_fg=(0.65, 0.65, 0.0, 1), indicator_text_shadow=(0, 0, 0, 0.35), indicator_frameColor=(0.15, 0.15, 0.15, 1), indicatorValue=base.particleMgrEnabled) self.cbParticles.indicator['text'] = (' ', 'x') self.cbParticles.indicator['text_pos'] = (0, 0.1) #self.cbParticles.indicator.setX(self.cbParticles.indicator, -0.5) #self.cbParticles.indicator.setZ(self.cbParticles.indicator, -0.1) #self.cbParticles.setFrameSize() self.cbParticles.setTransparency(1) self.cbParticles.reparentTo(self.frameMain) volume = base.musicManager.getVolume() self.sliderVolume = DirectSlider( scale=sliderscale, pos=(left, 0, -0.35), range=(0, 1), scrollSize=0.01, text=_("Volume %d%%") % volume * 100, text_scale=textscale, text_align=TextNode.ACenter, text_pos=(.0, 0.15), text_fg=(1, 1, 1, 1), thumb_frameColor=(0.65, 0.65, 0.0, 1), thumb_relief=DGG.FLAT, frameColor=(0.15, 0.15, 0.15, 1), value=volume, command=self.sliderVolume_ValueChanged) self.sliderVolume.reparentTo(self.frameMain) self.lblControltype = DirectLabel(text=_("Control type"), text_fg=(1, 1, 1, 1), text_shadow=(0, 0, 0, 0.35), frameColor=(0, 0, 0, 0), scale=textscale / 2, pos=(right, 0, 0.27)) self.lblControltype.setTransparency(1) self.lblControltype.reparentTo(self.frameMain) selectedControlType = 0 if base.controlType == "MouseAndKeyboard": selectedControlType = 1 self.controltype = DirectOptionMenu( pos=(right, 0, 0.18), text_fg=(1, 1, 1, 1), scale=0.1, items=[_("Keyboard"), _("Keyboard + Mouse")], initialitem=selectedControlType, frameColor=(0.15, 0.15, 0.15, 1), popupMarker_frameColor=(0.65, 0.65, 0.0, 1), popupMarker_relief=DGG.FLAT, highlightColor=(0.65, 0.65, 0.0, 1), relief=DGG.FLAT, command=self.controlType_Changed) self.controltype.reparentTo(self.frameMain) b = self.controltype.getBounds() xPos = right - ((b[1] - b[0]) / 2.0 * 0.1) self.controltype.setX(xPos) setItems(self.controltype) self.controltype.setItems = setItems self.controltype.showPopupMenu = showPopupMenu self.controltype.popupMarker.unbind(DGG.B1PRESS) self.controltype.popupMarker.bind(DGG.B1PRESS, showPopupMenu) self.controltype.unbind(DGG.B1PRESS) self.controltype.bind(DGG.B1PRESS, showPopupMenuExtra, [self.controltype]) isChecked = not base.AppHasAudioFocus img = None if base.AppHasAudioFocus: img = "AudioSwitch_on.png" else: img = "AudioSwitch_off.png" self.cbVolumeMute = DirectCheckBox( text=_("Mute Audio"), text_scale=0.5, text_align=TextNode.ACenter, text_pos=(0.0, 0.65), text_fg=(1, 1, 1, 1), pos=(right, 0, -0.35), scale=0.21 / 2.0, command=self.cbVolumeMute_CheckedChanged, rolloverSound=None, clickSound=None, relief=None, pressEffect=False, isChecked=isChecked, image=img, image_scale=0.5, checkedImage="AudioSwitch_off.png", uncheckedImage="AudioSwitch_on.png") self.cbVolumeMute.setTransparency(1) self.cbVolumeMute.setImage() self.cbVolumeMute.reparentTo(self.frameMain) sensitivity = base.mouseSensitivity self.sliderSensitivity = DirectSlider( scale=sliderscale, pos=(right, 0, -0.075), range=(0.5, 2), scrollSize=0.01, text=_("Mouse Sensitivity %0.1fx") % sensitivity, text_scale=textscale, text_align=TextNode.ACenter, text_pos=(.0, 0.15), text_fg=(1, 1, 1, 1), thumb_frameColor=(0.65, 0.65, 0.0, 1), thumb_relief=DGG.FLAT, frameColor=(0.15, 0.15, 0.15, 1), value=sensitivity, command=self.sliderSensitivity_ValueChanged) self.sliderSensitivity.reparentTo(self.frameMain) if base.controlType == "Gamepad": self.sliderSensitivity.hide() # create the back button self.btnBack = DirectButton( scale=buttonScale, # position on the window pos=(0, 0, base.a2dBottom + 0.15), frameColor=(0, 0, 0, 0), # text properties text=_("Back"), text_scale=0.5, text_fg=(1, 1, 1, 1), text_pos=(0.0, -0.15), text_shadow=(0, 0, 0, 0.35), text_shadowOffset=(-0.05, -0.05), # sounds that should be played rolloverSound=None, clickSound=None, pressEffect=False, relief=None, # the event which is thrown on clickSound command=lambda: base.messenger.send("options_back")) self.btnBack.setTransparency(1) self.btnBack.reparentTo(self.frameMain) self.hide() def show(self, enableResume=False): self.frameMain.show() def hide(self): self.frameMain.hide() def cbVolumeMute_CheckedChanged(self, checked): if checked: base.disableAllAudio() else: base.enableAllAudio() def sliderVolume_ValueChanged(self): volume = round(self.sliderVolume["value"], 2) self.sliderVolume["text"] = _("Volume %d%%") % int(volume * 100) base.sfxManagerList[0].setVolume(volume) base.musicManager.setVolume(volume) def sliderSensitivity_ValueChanged(self): sensitivity = round(self.sliderSensitivity["value"], 2) self.sliderSensitivity["text"] = _( "Mouse Sensitivity %0.1fx") % sensitivity base.mouseSensitivity = sensitivity def sliderTextspeed_ValueChanged(self): newSpeed = round(self.sliderTextspeed["value"], 2) displaySpeed = 1.0 / newSpeed self.sliderTextspeed["text"] = _("Textspeed %0.1f%%") % displaySpeed base.textWriteSpeed = newSpeed def cbParticles_CheckedChanged(self, unchecked): if unchecked: base.enableParticles() else: base.disableParticles() def controlType_Changed(self, arg): if arg == _("Keyboard"): self.sliderSensitivity.hide() base.controlType = "Gamepad" elif arg == _("Keyboard + Mouse"): self.sliderSensitivity.show() base.controlType = "MouseAndKeyboard"
class DirectWindow(DirectFrame): def __init__( self, pos=(-.5, .5), title='Title', curSize=(1, 1), maxSize=(1, 1), minSize=(.5, .5), backgroundColor=(1, 1, 1, 1), borderColor=(1, 1, 1, 1), titleColor=(1, 1, 1, 1), borderSize=0.04, titleSize=0.06, closeButton=False, windowParent=aspect2d, preserve=True, preserveWhole=True, ): self.preserve = preserve self.preserveWhole = preserveWhole self.windowParent = windowParent self.windowPos = pos DirectFrame.__init__( self, parent=windowParent, pos=(self.windowPos[0], 0, self.windowPos[1]), frameColor=(0, 0, 0, 0), frameTexture=loader.loadTexture(DIRECTORY + 'transparent.png')) self.setTransparency(True) # the title part of the window, drag around to move the window self.headerHeight = titleSize h = -self.headerHeight self.windowHeaderLeft = DirectButton( parent=self, frameTexture=DEFAULT_TITLE_GEOM_LEFT, frameSize=(-.5, .5, -.5, .5), borderWidth=(0, 0), relief=DGG.FLAT, frameColor=titleColor, ) self.windowHeaderCenter = DirectButton( parent=self, frameTexture=DEFAULT_TITLE_GEOM_CENTER, frameSize=(-.5, .5, -.5, .5), borderWidth=(0, 0), relief=DGG.FLAT, frameColor=titleColor, ) if closeButton: rightTitleGeom = DEFAULT_TITLE_GEOM_RIGHT_CLOSE command = self.destroy else: rightTitleGeom = DEFAULT_TITLE_GEOM_RIGHT command = None self.windowHeaderRight = DirectButton(parent=self, frameTexture=rightTitleGeom, frameSize=(-.5, .5, -.5, .5), borderWidth=(0, 0), relief=DGG.FLAT, frameColor=titleColor, command=command) self.windowHeaderLeft.setTransparency(True) self.windowHeaderCenter.setTransparency(True) self.windowHeaderRight.setTransparency(True) self.windowHeaderLeft.bind(DGG.B1PRESS, self.startWindowDrag) self.windowHeaderCenter.bind(DGG.B1PRESS, self.startWindowDrag) self.windowHeaderRight.bind(DGG.B1PRESS, self.startWindowDrag) # this is not handled correctly, if a window is dragged which has been # created before another it will not be released # check the bugfixed startWindowDrag function #self.windowHeader.bind(DGG.B1RELEASE,self.stopWindowDrag) text = TextNode('WindowTitleTextNode') text.setText(title) text.setAlign(TextNode.ACenter) text.setTextColor(0, 0, 0, 1) text.setShadow(0.05, 0.05) text.setShadowColor(1, 1, 1, 1) self.textNodePath = self.attachNewNode(text) self.textNodePath.setScale(self.headerHeight * 0.8) # the content part of the window, put stuff beneath # contentWindow.getCanvas() to put it into it self.maxVirtualSize = maxSize self.minVirtualSize = minSize self.resizeSize = borderSize self.contentWindow = DirectScrolledFrame( parent=self, pos=(0, 0, -self.headerHeight), canvasSize=(0, self.maxVirtualSize[0], 0, self.maxVirtualSize[1]), frameColor=( 0, 0, 0, 0), # defines the background color of the resize-button relief=DGG.FLAT, borderWidth=(0, 0), verticalScroll_frameSize=[0, self.resizeSize, 0, 1], horizontalScroll_frameSize=[0, 1, 0, self.resizeSize], # resize the scrollbar according to window size verticalScroll_resizeThumb=False, horizontalScroll_resizeThumb=False, # define the textures for the scrollbars verticalScroll_frameTexture=VERTICALSCROLL_FRAMETEXTURE, verticalScroll_incButton_frameTexture= VERTICALSCROLL_INCBUTTON_FRAMETEXTURE, verticalScroll_decButton_frameTexture= VERTICALSCROLL_DECBUTTON_FRAMETEXTURE, verticalScroll_thumb_frameTexture=VERTICALSCROLL_TUMB_FRAMETEXTURE, horizontalScroll_frameTexture=HORIZONTALSCROLL_FRAMETEXTURE, horizontalScroll_incButton_frameTexture= HORIZONTALSCROLL_INCBUTTON_FRAMETEXTURE, horizontalScroll_decButton_frameTexture= HORIZONTALSCROLL_DECBUTTON_FRAMETEXTURE, horizontalScroll_thumb_frameTexture= HORIZONTALSCROLL_TUMB_FRAMETEXTURE, # make all flat, so the texture is as we want it verticalScroll_relief=DGG.FLAT, verticalScroll_thumb_relief=DGG.FLAT, verticalScroll_decButton_relief=DGG.FLAT, verticalScroll_incButton_relief=DGG.FLAT, horizontalScroll_relief=DGG.FLAT, horizontalScroll_thumb_relief=DGG.FLAT, horizontalScroll_decButton_relief=DGG.FLAT, horizontalScroll_incButton_relief=DGG.FLAT, # colors verticalScroll_frameColor=borderColor, verticalScroll_incButton_frameColor=borderColor, verticalScroll_decButton_frameColor=borderColor, verticalScroll_thumb_frameColor=borderColor, horizontalScroll_frameColor=borderColor, horizontalScroll_incButton_frameColor=borderColor, horizontalScroll_decButton_frameColor=borderColor, horizontalScroll_thumb_frameColor=borderColor, ) self.contentWindow.setTransparency(True) # background color self.backgroundColor = DirectFrame( parent=self.contentWindow.getCanvas(), frameSize=(0, self.maxVirtualSize[0], 0, self.maxVirtualSize[1]), frameColor=backgroundColor, relief=DGG.FLAT, borderWidth=(.01, .01), ) self.backgroundColor.setTransparency(True) # Add a box self.box = boxes.VBox(parent=self.getCanvas()) # is needed for some nicer visuals of the resize button (background) self.windowResizeBackground = DirectButton( parent=self, frameSize=(-.5, .5, -.5, .5), borderWidth=(0, 0), scale=(self.resizeSize, 1, self.resizeSize), relief=DGG.FLAT, frameColor=backgroundColor, ) # the resize button of the window self.windowResize = DirectButton( parent=self, frameSize=(-.5, .5, -.5, .5), borderWidth=(0, 0), scale=(self.resizeSize, 1, self.resizeSize), relief=DGG.FLAT, frameTexture=DEFAULT_RESIZE_GEOM, frameColor=borderColor, ) self.windowResize.setTransparency(True) self.windowResize.bind(DGG.B1PRESS, self.startResizeDrag) self.windowResize.bind(DGG.B1RELEASE, self.stopResizeDrag) # offset then clicking on the resize button from the mouse to the resizebutton # position, required to calculate the position / scaling self.offset = None self.taskName = "resizeTask-%s" % str(hash(self)) # do sizing of the window (minimum) #self.resize( Vec3(0,0,0), Vec3(0,0,0) ) # maximum #self.resize( Vec3(100,0,-100), Vec3(0,0,0) ) self.resize(Vec3(curSize[0], 0, -curSize[1]), Vec3(0, 0, 0)) def getCanvas(self): return self.contentWindow.getCanvas() # dragging functions def startWindowDrag(self, param): self.wrtReparentTo(aspect2dMouseNode) self.ignoreAll() self.accept('mouse1-up', self.stopWindowDrag) def stopWindowDrag(self, param=None): # this is called 2 times (bug), so make sure it's not already parented to aspect2d if self.getParent() != self.windowParent: self.wrtReparentTo(self.windowParent) if self.preserve: if self.preserveWhole: if self.getZ() > 1: self.setZ(1) elif self.getZ() < -1 - self.getHeight(): self.setZ(-1 - self.getHeight()) if self.getX() > base.a2dRight - self.getWidth(): self.setX(base.a2dRight - self.getWidth()) elif self.getX() < base.a2dLeft: self.setX(base.a2dLeft) else: if self.getZ() > 1: self.setZ(1) elif self.getZ() < -1 + self.headerHeight: self.setZ(-1 + self.headerHeight) if self.getX() > base.a2dRight - self.headerHeight: self.setX(base.a2dRight - self.headerHeight) elif self.getX( ) < base.a2dLeft + self.headerHeight - self.getWidth(): self.setX(base.a2dLeft + self.headerHeight - self.getWidth()) #else: #Window moved beyond reach. Destroy window? # resize functions def resize(self, mPos, offset): mXPos = max(min(mPos.getX(), self.maxVirtualSize[0]), self.minVirtualSize[0]) mZPos = max(min(mPos.getZ(), -self.minVirtualSize[1]), -self.maxVirtualSize[1] - self.headerHeight) self.windowResize.setPos(mXPos - self.resizeSize / 2., 0, mZPos + self.resizeSize / 2.) self.windowResizeBackground.setPos(mXPos - self.resizeSize / 2., 0, mZPos + self.resizeSize / 2.) self['frameSize'] = (0, mXPos, 0, mZPos) self.windowHeaderLeft.setPos(self.headerHeight / 2., 0, -self.headerHeight / 2.) self.windowHeaderLeft.setScale(self.headerHeight, 1, self.headerHeight) self.windowHeaderCenter.setPos(mXPos / 2., 0, -self.headerHeight / 2.) self.windowHeaderCenter.setScale(mXPos - self.headerHeight * 2., 1, self.headerHeight) self.windowHeaderRight.setPos(mXPos - self.headerHeight / 2., 0, -self.headerHeight / 2.) self.windowHeaderRight.setScale(self.headerHeight, 1, self.headerHeight) self.contentWindow['frameSize'] = (0, mXPos, mZPos + self.headerHeight, 0) self.textNodePath.setPos(mXPos / 2., 0, -self.headerHeight / 3. * 2.) # show and hide that small background for the window sizer if mXPos == self.maxVirtualSize[0] and \ mZPos == -self.maxVirtualSize[1]-self.headerHeight: self.windowResizeBackground.hide() else: self.windowResizeBackground.show() def resizeTask(self, task=None): mPos = aspect2dMouseNode.getPos(self) + self.offset self.resize(mPos, self.offset) return task.cont def startResizeDrag(self, param): self.offset = self.windowResize.getPos(aspect2dMouseNode) taskMgr.remove(self.taskName) taskMgr.add(self.resizeTask, self.taskName) def stopResizeDrag(self, param): taskMgr.remove(self.taskName) # get the window to the front self.wrtReparentTo(self.windowParent) def addHorizontal(self, widgets): """ Accepts a list of directgui objects which are added to a horizontal box, which is then added to the vertical stack. """ hbox = boxes.HBox() for widget in widgets: hbox.pack(widget) self.box.pack(hbox) self.updateMaxSize() def addVertical(self, widgets): """ Accepts a list of directgui objects which are added to a vertical box, which is then added to the vertical stack. May cause funky layout results. """ #vbox = boxes.VBox() for widget in widgets: self.box.pack(widget) self.updateMaxSize() def add(self, widgets): """Shortcut function for addVertical""" self.addVertical(widgets) def updateMaxSize(self): """Updates the max canvas size to include all items packed. Window is resized to show all contents.""" bottomLeft, topRight = self.box.getTightBounds() self.maxVirtualSize = (topRight[0], -bottomLeft[2]) self.contentWindow['canvasSize'] = (0, self.maxVirtualSize[0], -self.maxVirtualSize[1], 0) self.backgroundColor['frameSize'] = (0, self.maxVirtualSize[0], -self.maxVirtualSize[1], 0) #perhaps this should be optional -- automatically resize for new elements self.reset() def reset(self): """Poorly named function that resizes window to fit all contents""" self.resize( Vec3(self.maxVirtualSize[0], 0, -self.maxVirtualSize[1] - self.headerHeight), Vec3(0, 0, 0))
class Scenario: """The game scenario orchestrator. Tracks on which part of the scenario the player is, controls the next scenario steps and performs choice consequences effects. One scenario chapter includes a situation in which the player has to make a decision. Decision will have consequences, positive or negative, but in any case the player will become one step closer to figuring out the way to survive the Stench. After every chapter the player will also get a note written in a diary fashion. The note will give the player more info about the Stench, Captain, the Adjutant and how the cataclysm started to destroy the World. Args: current_chapter (int): The chapter number to start with. """ def __init__(self, current_chapter=None): if current_chapter is not None: # saved game self.current_chapter = current_chapter else: # game start self.current_chapter = -1 self._list = DirectFrame( frameSize=(-0.73, 0.73, -0.9, 0.9), frameTexture=GUI_PIC + "paper1.png", state=DGG.NORMAL, ) self._list.setDepthTest(False) self._list.setTransparency(TransparencyAttrib.MAlpha) self._list.hide() self._name = DirectLabel( parent=self._list, text="", text_font=base.main_font, # noqa: F821 frameSize=(0.4, 0.4, 0.4, 0.4), text_scale=0.05, pos=(-0.4, 0, 0.7), ) self._type = DirectLabel( parent=self._list, text=base.labels.SCENARIO_LABELS[1], # noqa: F821 text_font=base.main_font, # noqa: F821 frameSize=(0.4, 0.4, 0.4, 0.4), text_scale=0.035, pos=(-0.13, 0, 0.699), ) self._desc = DirectLabel( parent=self._list, text="", text_font=base.main_font, # noqa: F821 frameSize=(0.6, 0.6, 0.6, 0.6), text_scale=0.037, pos=(0, 0, 0.55), ) self._buts = [] z_coor = -0.6 for _ in range(3): self._buts.append( DirectButton( parent=self._list, text="Text", text_font=base.main_font, # noqa: F821 text_fg=RUST_COL, text_shadow=(0, 0, 0, 1), frameColor=(0, 0, 0, 0), frameSize=(-9, 9, -0.3, 0.7), scale=(0.047, 0, 0.047), clickSound=base.main_menu.click_snd, # noqa: F821 pos=(0, 0, z_coor), )) z_coor -= 0.08 self._done_but = DirectButton( parent=self._list, text=base.labels.DISTINGUISHED[6], # noqa: F821 text_font=base.main_font, # noqa: F821 text_fg=RUST_COL, text_shadow=(0, 0, 0, 1), frameColor=(0, 0, 0, 0), frameSize=(-9, 9, -0.3, 0.7), scale=(0.05, 0, 0.05), clickSound=base.main_menu.click_snd, # noqa: F821 pos=(0, 0, -0.8), command=self.hide_chapter, ) def _choose_variant(self, var): """Process the player's choice and do consequences. Args: var (str): Variant id. """ consequences = base.labels.SCENARIO[ self.current_chapter][ # noqa: F821 "variants"][var] for but in self._buts: but.hide() self._desc["text"] = consequences["desc"] for effect in consequences["effects"]: getattr(self, effect[0])(*effect[1]) base.journal.add_page(self.current_chapter) # noqa: F821 self._done_but.show() base.res_gui.update_resource( # noqa: F821 "places_of_interest", str(self.current_chapter + 1) + "/10") base.decisions["decision_" + str(self.current_chapter)] = { # noqa: F821 "decision": var, "goodness": consequences["goodness"], } def finish_game(self): """Completely finish the game.""" self.hide_chapter() taskMgr.doMethodLater( # noqa: F821 1, base.effects_mgr.fade_out_screen, "fade_out" # noqa: F821 ) taskMgr.doMethodLater( # noqa: F821 4, base.main_menu.show_credits, "show_credits", # noqa: F821 ) taskMgr.doMethodLater( # noqa: F821 4.5, base.effects_mgr.fade_in_screen, "fade_in" # noqa: F821 ) taskMgr.doMethodLater( # noqa: F821 76, base.restart_game, "restart_game", extraArgs=[] # noqa: F821 ) base.train.ctrl.unset_controls() # noqa: F821 base.effects_mgr.stench_effect.stop() # noqa: F821 for task in ( "update_physics", "sun_look_at_train", "collide_mouse", "move_camera_with_mouse", "update_speed_indicator", "disease", "show_teaching_note", "calc_cohesion", "track_ambient_sounds", "stench_step", "check_train_contacts", "change_sun_color", ): base.taskMgr.remove(task) # noqa: F821 base.sound_mgr.disable() # noqa: F821 base.world.drown_ambient_snds() # noqa: F821 def do_build_camp_effect(self): """Do effects for building a camp for orphans choice.""" base.helped_children = True # noqa: F821 def do_spend_cohesion(self, value): """Do effect of decreasing the crew cohesion. Args: value (int): The amount of the cohesion change. """ base.team.spend_cohesion(value) # noqa: F821 def do_get_money(self, money): """Get or lose the given amount of money. Args: money (int): Money amount to get/lose. """ base.dollars += money # noqa: F821 def do_plus_resource(self, name, value): """Change the given resource amount. Args: name (str): Resource name. value (int): Amount delta. """ base.plus_resource(name, value) # noqa: F821 def do_enemy_inc_effect(self): """Make enemy stronger effect.""" base.world.enemy.score += 3 # noqa: F821 def do_character_effect(self, char, effect): """Do choice consequences effect to the given character. Args: char (units.crew.character.Character): The character to do effect to. effect (dict): The effect description. """ for key, value in effect.items(): setattr(char, key, getattr(char, key) + value) def do_characters_effect(self, effect, to_one=False): """Do choice consequences effects to the crew. Args: effect (dict): Effect description. to_one (bool): Effect targets only one random character. """ if to_one: self.do_character_effect( random.choice(list(base.team.chars.values())), effect # noqa: F821 ) return for char in base.team.chars.values(): # noqa: F821 self.do_character_effect(char, effect) def do_locomotive_damage(self, damage): """Do some damage to the Adjutant. Args: damage (int): Amount of damage to do. """ base.train.get_damage(damage) # noqa: F821 def do_no_effect(self): """No choice consequences method.""" pass def do_stench_moves_effect(self, steps): """Move the Stench frontier several miles deeper into the Silewer. Args: steps (int): Number of miles to cover with the Stench. """ for _ in range(steps): base.world.make_stench_step() # noqa: F821 def do_transfusion_effect(self): """Do blood transfusion effect of Chapter 9.""" char = None chars = list(base.team.chars.values()) # noqa: F821 if chars: char = take_random(chars) char.health -= 30 if chars: take_random(chars).health -= 30 elif char: char.health -= 30 def do_medicine_save(self): """Do save with medicines effect of Chapter 9.""" if base.resource("medicine_boxes"): # noqa: F821 base.plus_resource("medicine_boxes", -1) # noqa: F821 else: chars = list(base.team.chars.values()) # noqa: F821 if chars: take_random(chars).energy -= 40 def hide_chapter(self): """Hide the scenario GUI.""" self._list.hide() def start_chapter(self, task): """Start a new scenario chapter.""" self.current_chapter += 1 base.train.ctrl.set_controls(base.train) # noqa: F821 base.camera_ctrl.enable_ctrl_keys() # noqa: F821 base.world.outings_mgr.hide_outing() # noqa: F821 base.traits_gui.hide() # noqa: F821 if self.current_chapter <= 9: self.show_chapter_situation() # noqa: F821 base.world.drop_place_of_interest() # noqa: F821 return task.done def show_chapter_situation(self): """Show the situation description and the possible variants.""" self._done_but.hide() self._name[ "text"] = base.labels.SCENARIO_LABELS[0] + str( # noqa: F821 self.current_chapter + 1) self._desc["text"] = base.labels.SCENARIO[ self.current_chapter][ # noqa: F821 "intro"] if (len(base.labels.SCENARIO[self.current_chapter] ["variants"]) # noqa: F821 == 3): for index, var in enumerate(base.labels.SCENARIO[ self.current_chapter]["variants"] # noqa: F821 ): self._buts[index]["text"] = var self._buts[index]["extraArgs"] = [var] self._buts[index]["command"] = self._choose_variant self._buts[index].show() else: self._buts[0].hide() self._buts[1].hide() for var in base.labels.SCENARIO[ self.current_chapter][ # noqa: F821 "variants"]: self._buts[2]["text"] = var self._buts[2]["extraArgs"] = [var] self._buts[2]["command"] = self._choose_variant self._buts[2].show() self._done_but["command"] = self.finish_game self._list.show()
class CharacterGUI: """Widget with the selected character info.""" def __init__(self): self.char = None # the chosen character self.rest_list_shown = False self._status_lab = None self._rest_buttons = {} self._char_desc_wids = [] self._char_desc_shown = False self._fr = DirectFrame( parent=base.a2dTopLeft, # noqa: F821 frameSize=(-0.31, 0.31, -0.1, 0.115), pos=(0.31, 0, -1.9), frameTexture=GUI_PIC + "metal1.png", state=DGG.NORMAL, ) self._fr.setTransparency(TransparencyAttrib.MAlpha) # a "?" button to open a detailed description of the character self._char_desc_but = DirectButton( parent=self._fr, pos=(0.27, 0, 0.0675), command=self._show_char_desc, clickSound=base.main_menu.click_snd, # noqa: F821 **ABOUT_BUT_PARAMS, ) DirectLabel( # Name: parent=self._fr, text=base.labels.CHARACTERS[0], # noqa: F821 text_font=base.main_font, # noqa: F821 frameSize=(0.1, 0.1, 0.1, 0.1), text_scale=0.03, text_fg=RUST_COL, pos=(-0.22, 0, 0.07), ) self._char_name = DirectLabel( parent=self._fr, text="", frameSize=(0.1, 0.1, 0.1, 0.1), text_scale=0.03, text_fg=SILVER_COL, pos=(-0.09, 0, 0.069), ) self._traits = DirectLabel( parent=self._fr, text="", frameSize=(0.1, 0.1, 0.1, 0.1), text_scale=(0.028, 0.028), text_fg=SILVER_COL, text_font=base.main_font, # noqa: F821 pos=(0, 0, 0.025), ) DirectLabel( # Class: parent=self._fr, text=base.labels.CHARACTERS[1], # noqa: F821 text_font=base.main_font, # noqa: F821 frameSize=(0.1, 0.1, 0.1, 0.1), text_scale=0.03, text_fg=RUST_COL, pos=(0.05, 0, 0.07), ) self._char_class = DirectLabel( parent=self._fr, text="", frameSize=(0.1, 0.1, 0.1, 0.1), text_scale=0.03, text_fg=SILVER_COL, pos=(0.17, 0, 0.068), ) DirectLabel( # Health parent=self._fr, text=base.labels.CHARACTERS[2], # noqa: F821 text_font=base.main_font, # noqa: F821 frameSize=(0.1, 0.1, 0.1, 0.1), text_scale=0.03, text_fg=RUST_COL, pos=(-0.22, 0, -0.015), ) self._char_health = DirectWaitBar( parent=self._fr, frameSize=(-0.17, 0.17, -0.002, 0.002), frameColor=(0.35, 0.35, 0.35, 1), value=0, barColor=(0.85, 0.2, 0.28, 1), pos=(0.07, 0, -0.008), ) DirectLabel( # Energy parent=self._fr, text=base.labels.CHARACTERS[3], # noqa: F821 text_font=base.main_font, # noqa: F821 frameSize=(0.1, 0.1, 0.1, 0.1), text_scale=0.03, text_fg=RUST_COL, pos=(-0.216, 0, -0.06), ) self._char_energy = DirectWaitBar( parent=self._fr, frameSize=(-0.17, 0.17, -0.002, 0.002), frameColor=(0.35, 0.35, 0.35, 1), value=0, barColor=(0.46, 0.61, 0.53, 1), pos=(0.07, 0, -0.053), ) self._tip = OnscreenText( parent=base.render2d, # noqa: F821 text="", font=base.main_font, # noqa: F821 scale=(0.021, 0.027), fg=SILVER_COL, bg=(0, 0, 0, 0.4), ) self._tip.hide() self._disease = DirectFrame( parent=self._fr, frameSize=(-0.02, 0.02, -0.02, 0.02), pos=(0.27, 0, -0.008), frameTexture=GUI_PIC + "disease.png", ) self._disease.setTransparency(TransparencyAttrib.MAlpha) self.clear_char_info() def _update_char_info(self, task): """Track the chosen character parameters in the GUI.""" if self.char.is_dead: self.clear_char_info() return task.done self._char_health["value"] = self.char.health self._char_energy["value"] = self.char.energy self._traits["text"] = ", ".join(self.char.traits) if self.char.is_diseased: self._disease.show() else: self._disease.hide() if self._char_desc_shown: self._update_desc() return task.again def _update_desc(self): """Update the chosen character description.""" to_del = [] for wid in self._char_desc_wids: if wid["text"] not in ( # Traits base.labels.CHARACTERS[5], # noqa: F821 # Status base.labels.CHARACTERS[4], # noqa: F821 "", ): wid.destroy() to_del.append(wid) for del_wid in to_del: self._char_desc_wids.remove(del_wid) self._fill_status(self._fill_traits(0.64)) def _fill_traits(self, shift): """Fill the chosen character traits. Args: shift (float): Z-coor for the new widgets. Returns: float: Z-coor including the new widgets shift. """ shift -= 0.03 for trait in self.char.traits + self.char.disabled_traits: self._char_desc_wids.append( DirectLabel( parent=self._fr, text=trait, frameSize=(0.1, 0.1, 0.1, 0.1), text_scale=0.03, text_font=base.main_font, # noqa: F821 text_fg=SILVER_COL if trait in self.char.traits else (0.3, 0.3, 0.3, 1), pos=(0, 0, shift), ) ) self._char_desc_wids.append( DirectLabel( parent=self._fr, text=base.labels.TRAIT_DESC[trait], # noqa: F821 text_font=base.main_font, # noqa: F821 frameSize=(0.1, 0.1, 0.1, 0.1), text_scale=0.029, text_fg=SILVER_COL if trait in self.char.traits else (0.3, 0.3, 0.3, 1), pos=(0, 0, shift - 0.045), ) ) shift -= 0.1 return shift def _fill_status(self, shift): """Fill the chosen character status. Args: shift (float): Z-coor for the new widgets. """ shift -= 0.04 for status in self.char.statuses: self._char_desc_wids.append( DirectLabel( parent=self._fr, text=status, text_font=base.main_font, # noqa: F821 frameSize=(0.1, 0.1, 0.1, 0.1), text_scale=0.029, text_fg=SILVER_COL, pos=(0, 0, shift), ) ) shift -= 0.045 def _show_char_desc(self): """Show detailed character description. Includes description of every character's trait and their current status. """ if self._char_desc_shown: self._fr["frameSize"] = (-0.31, 0.31, -0.1, 0.115) clear_wids(self._char_desc_wids) self._status_lab = None else: shift = 0.7 self._fr["frameSize"] = (-0.31, 0.31, -0.1, shift) shift -= 0.06 self._char_desc_wids.append( DirectLabel( parent=self._fr, # Traits text=base.labels.CHARACTERS[5], # noqa: F821, text_font=base.main_font, # noqa: F821, frameSize=(0.1, 0.1, 0.1, 0.1), text_scale=0.03, text_fg=RUST_COL, pos=(-0.225, 0, shift), ) ) if self.char.id in base.team.chars.keys(): # noqa: F821 traits_but = DirectButton( parent=self._fr, text="", frameSize=(-0.025, 0.025, -0.025, 0.025), frameTexture=GUI_PIC + "like.png", relief="flat", pos=(0.265, 0, shift + 0.013), command=base.traits_gui.show, # noqa: F821 ) traits_but.bind( DGG.ENTER, self._highlight_traits_but, extraArgs=[traits_but] ) traits_but.bind( DGG.EXIT, self._dehighlight_traits_but, extraArgs=[traits_but] ) self._char_desc_wids.append(traits_but) shift = self._fill_traits(shift) self._status_lab = DirectLabel( # Status parent=self._fr, # Status text=base.labels.CHARACTERS[4], # noqa: F821 text_font=base.main_font, # noqa: F821 frameSize=(0.1, 0.1, 0.1, 0.1), text_scale=0.03, text_fg=RUST_COL, pos=(-0.221, 0, shift), ) self._char_desc_wids.append(self._status_lab) self._fill_status(shift) self._char_desc_shown = not self._char_desc_shown def _dehighlight_traits_but(self, button, _): """Dehighlight traits tweaking button. Args: button (panda3d.gui.DirectGui.DirectButton): Button to dehighlight. """ button["frameTexture"] = GUI_PIC + "like.png" def _highlight_traits_but(self, button, _): """Hightlight traits tweaking button. Args: button (panda3d.gui.DirectGui.DirectButton): Button to highlight. """ button["frameTexture"] = GUI_PIC + "hover_like.png" def clear_char_info(self, clear_resting=True): """Clear the character GUI. Args: clear_resting (bool): Optional. A flag indicating if the list of the resting characters should also be closed. """ for wid in ( self._char_name, self._char_class, self._char_health, self._char_energy, self._traits, self._char_desc_but, self._disease, ): wid.hide() if self._char_desc_shown: self._show_char_desc() taskMgr.remove("track_char_info") # noqa: F821 self.char = None if clear_resting: for but in self._rest_buttons.values(): but.destroy() self.rest_list_shown = False def destroy_char_button(self, char_id): """Hide the given character button from the resting characters list. Args: char_id (str): Character id. """ if char_id in self._rest_buttons.keys(): self._rest_buttons[char_id].destroy() self._rest_buttons.pop(char_id) def hide_tip(self): """Hide the tooltip.""" self._tip.hide() def show_char_info(self, char): """Show the given character status. Args: char (units.crew.character.Character): The chosen character object. """ self._char_name["text"] = char.name self._char_class["text"] = char.class_.capitalize() self._traits["text"] = ", ".join(char.traits) self._char_health["range"] = char.class_data["health"] self._char_health["value"] = char.health self._char_energy["value"] = char.energy if char.is_diseased: self._disease.show() else: self._disease.hide() self.char = char self._char_name.show() self._char_class.show() self._char_health.show() self._char_energy.show() self._traits.show() self._char_desc_but.show() if self._char_desc_shown: self._show_char_desc() self._show_char_desc() taskMgr.doMethodLater( # noqa: F821 0.5, self._update_char_info, "track_char_info" ) def show_tooltip(self, text): """Show tooltip with the given text. Args: text (str): Text to show in the tooltip. """ if not base.mouseWatcherNode.hasMouse(): # noqa: F821 return if self.rest_list_shown and text == "Rest zone": return self._tip.setText(text) self._tip.setX(base.mouseWatcherNode.getMouseX()) # noqa: F821 self._tip.setY(base.mouseWatcherNode.getMouseY()) # noqa: F821 self._tip.show() def show_resting_chars(self, part): """Show a list of the characters resting in this part. Args: part (Train.RestPart): Rest part of the Train. """ if self.rest_list_shown: return self._tip.hide() self.rest_list_shown = True x = base.mouseWatcherNode.getMouseX() # noqa: F821 z = base.mouseWatcherNode.getMouseY() # noqa: F821 self._rest_buttons["title"] = DirectButton( pos=(x, 0, z), text=base.labels.TIPS[0], # noqa: F821 text_fg=RUST_COL, text_font=base.main_font, # noqa: F821 frameColor=(0, 0, 0, 0.6), scale=(0.04, 0, 0.03), ) shift = -0.039 for char in part.chars: if char.is_dead: continue self._rest_buttons[char.id] = DirectButton( pos=(x, 0, z + shift), text=char.name, text_fg=SILVER_COL, frameColor=(0, 0, 0, 0.6), command=base.common_ctrl.choose_char, # noqa: F821 extraArgs=[char.id], scale=(0.04, 0, 0.03), ) shift -= 0.033 def move_status_label(self, place): """Move the status label widget. Args: place (int): Place to shift the widget. """ if self._status_lab is not None: self._status_lab.setZ(self._status_lab.getZ() + place / 10) def update_resting_chars(self, part): """Update the list of the resting characters. Args: part (train.part.TrainPart): Rest train part. """ for key, but in self._rest_buttons.items(): if key != "title": but.destroy() self._rest_buttons[key] = None x, _, z = self._rest_buttons["title"].getPos() shift = -0.039 for char in part.chars: self._rest_buttons[char.id] = DirectButton( pos=(x, 0, z + shift), text=char.name, text_fg=SILVER_COL, frameColor=(0, 0, 0, 0.6), command=base.common_ctrl.choose_char, # noqa: F821 extraArgs=[char.id], scale=(0.04, 0, 0.03), ) shift -= 0.033
class DirectWindow( DirectFrame ): def __init__( self, pos = ( -.5, .5), title = 'Title', curSize = ( 1, 1), maxSize = ( 1, 1 ), minSize = ( .5, .5 ), backgroundColor = ( 1, 1, 1, 1 ), borderColor = ( 1, 1, 1, 1 ), titleColor = ( 1, 1, 1, 1 ), borderSize = 0.04, titleSize = 0.06, closeButton = False, windowParent = aspect2d, preserve = True, preserveWhole = True, ): self.preserve = preserve self.preserveWhole = preserveWhole self.windowParent = windowParent self.windowPos = pos DirectFrame.__init__( self, parent = windowParent, pos = ( self.windowPos[0], 0, self.windowPos[1] ), frameColor = ( 0, 0, 0, 0 ), frameTexture = loader.loadTexture( DIRECTORY+'transparent.png' ) ) self.setTransparency(True) # the title part of the window, drag around to move the window self.headerHeight = titleSize h = -self.headerHeight self.windowHeaderLeft = DirectButton( parent = self, frameTexture = DEFAULT_TITLE_GEOM_LEFT, frameSize = ( -.5, .5, -.5, .5 ), borderWidth = ( 0, 0 ), relief = DGG.FLAT, frameColor = titleColor, ) self.windowHeaderCenter = DirectButton( parent = self, frameTexture = DEFAULT_TITLE_GEOM_CENTER, frameSize = ( -.5, .5, -.5, .5 ), borderWidth = ( 0, 0 ), relief = DGG.FLAT, frameColor = titleColor, ) if closeButton: rightTitleGeom = DEFAULT_TITLE_GEOM_RIGHT_CLOSE command = self.destroy else: rightTitleGeom = DEFAULT_TITLE_GEOM_RIGHT command = None self.windowHeaderRight = DirectButton( parent = self, frameTexture = rightTitleGeom, frameSize = ( -.5, .5, -.5, .5 ), borderWidth = ( 0, 0 ), relief = DGG.FLAT, frameColor = titleColor, command = command ) self.windowHeaderLeft.setTransparency(True) self.windowHeaderCenter.setTransparency(True) self.windowHeaderRight.setTransparency(True) self.windowHeaderLeft.bind( DGG.B1PRESS, self.startWindowDrag ) self.windowHeaderCenter.bind( DGG.B1PRESS, self.startWindowDrag ) self.windowHeaderRight.bind( DGG.B1PRESS, self.startWindowDrag ) # this is not handled correctly, if a window is dragged which has been # created before another it will not be released # check the bugfixed startWindowDrag function #self.windowHeader.bind(DGG.B1RELEASE,self.stopWindowDrag) text = TextNode('WindowTitleTextNode') text.setText(title) text.setAlign(TextNode.ACenter) text.setTextColor( 0, 0, 0, 1 ) text.setShadow(0.05, 0.05) text.setShadowColor( 1, 1, 1, 1 ) self.textNodePath = self.attachNewNode(text) self.textNodePath.setScale(self.headerHeight*0.8) # the content part of the window, put stuff beneath # contentWindow.getCanvas() to put it into it self.maxVirtualSize = maxSize self.minVirtualSize = minSize self.resizeSize = borderSize self.contentWindow = DirectScrolledFrame( parent = self, pos = ( 0, 0, -self.headerHeight ), canvasSize = ( 0, self.maxVirtualSize[0], 0, self.maxVirtualSize[1] ), frameColor = ( 0, 0, 0, 0), # defines the background color of the resize-button relief = DGG.FLAT, borderWidth = (0, 0), verticalScroll_frameSize = [0, self.resizeSize, 0, 1], horizontalScroll_frameSize = [0, 1, 0, self.resizeSize], # resize the scrollbar according to window size verticalScroll_resizeThumb = False, horizontalScroll_resizeThumb = False, # define the textures for the scrollbars verticalScroll_frameTexture = VERTICALSCROLL_FRAMETEXTURE, verticalScroll_incButton_frameTexture = VERTICALSCROLL_INCBUTTON_FRAMETEXTURE, verticalScroll_decButton_frameTexture = VERTICALSCROLL_DECBUTTON_FRAMETEXTURE, verticalScroll_thumb_frameTexture = VERTICALSCROLL_TUMB_FRAMETEXTURE, horizontalScroll_frameTexture = HORIZONTALSCROLL_FRAMETEXTURE, horizontalScroll_incButton_frameTexture = HORIZONTALSCROLL_INCBUTTON_FRAMETEXTURE, horizontalScroll_decButton_frameTexture = HORIZONTALSCROLL_DECBUTTON_FRAMETEXTURE, horizontalScroll_thumb_frameTexture = HORIZONTALSCROLL_TUMB_FRAMETEXTURE, # make all flat, so the texture is as we want it verticalScroll_relief = DGG.FLAT, verticalScroll_thumb_relief = DGG.FLAT, verticalScroll_decButton_relief = DGG.FLAT, verticalScroll_incButton_relief = DGG.FLAT, horizontalScroll_relief = DGG.FLAT, horizontalScroll_thumb_relief = DGG.FLAT, horizontalScroll_decButton_relief = DGG.FLAT, horizontalScroll_incButton_relief = DGG.FLAT, # colors verticalScroll_frameColor = borderColor, verticalScroll_incButton_frameColor = borderColor, verticalScroll_decButton_frameColor = borderColor, verticalScroll_thumb_frameColor = borderColor, horizontalScroll_frameColor = borderColor, horizontalScroll_incButton_frameColor = borderColor, horizontalScroll_decButton_frameColor = borderColor, horizontalScroll_thumb_frameColor = borderColor, ) self.contentWindow.setTransparency(True) # background color self.backgroundColor = DirectFrame( parent = self.contentWindow.getCanvas(), frameSize = ( 0, self.maxVirtualSize[0], 0, self.maxVirtualSize[1] ), frameColor = backgroundColor, relief = DGG.FLAT, borderWidth = ( .01, .01), ) self.backgroundColor.setTransparency(True) # Add a box self.box = boxes.VBox(parent = self.getCanvas()) # is needed for some nicer visuals of the resize button (background) self.windowResizeBackground = DirectButton( parent = self, frameSize = ( -.5, .5, -.5, .5 ), borderWidth = ( 0, 0 ), scale = ( self.resizeSize, 1, self.resizeSize ), relief = DGG.FLAT, frameColor = backgroundColor, ) # the resize button of the window self.windowResize = DirectButton( parent = self, frameSize = ( -.5, .5, -.5, .5 ), borderWidth = ( 0, 0 ), scale = ( self.resizeSize, 1, self.resizeSize ), relief = DGG.FLAT, frameTexture = DEFAULT_RESIZE_GEOM, frameColor = borderColor, ) self.windowResize.setTransparency(True) self.windowResize.bind(DGG.B1PRESS,self.startResizeDrag) self.windowResize.bind(DGG.B1RELEASE,self.stopResizeDrag) # offset then clicking on the resize button from the mouse to the resizebutton # position, required to calculate the position / scaling self.offset = None self.taskName = "resizeTask-%s" % str(hash(self)) # do sizing of the window (minimum) #self.resize( Vec3(0,0,0), Vec3(0,0,0) ) # maximum #self.resize( Vec3(100,0,-100), Vec3(0,0,0) ) self.resize( Vec3(curSize[0], 0, -curSize[1]), Vec3(0,0,0)) def getCanvas(self): return self.contentWindow.getCanvas() # dragging functions def startWindowDrag( self, param ): self.wrtReparentTo( aspect2dMouseNode ) self.ignoreAll() self.accept( 'mouse1-up', self.stopWindowDrag ) def stopWindowDrag( self, param=None ): # this is called 2 times (bug), so make sure it's not already parented to aspect2d if self.getParent() != self.windowParent: self.wrtReparentTo( self.windowParent ) if self.preserve: if self.preserveWhole: if self.getZ() > 1: self.setZ(1) elif self.getZ() < -1 - self.getHeight(): self.setZ(-1 - self.getHeight()) if self.getX() > base.a2dRight - self.getWidth(): self.setX(base.a2dRight - self.getWidth()) elif self.getX() < base.a2dLeft: self.setX(base.a2dLeft) else: if self.getZ() > 1: self.setZ(1) elif self.getZ() < -1 + self.headerHeight: self.setZ(-1 + self.headerHeight) if self.getX() > base.a2dRight - self.headerHeight: self.setX(base.a2dRight - self.headerHeight) elif self.getX() < base.a2dLeft + self.headerHeight - self.getWidth(): self.setX(base.a2dLeft + self.headerHeight - self.getWidth()) #else: #Window moved beyond reach. Destroy window? # resize functions def resize( self, mPos, offset ): mXPos = max( min( mPos.getX(), self.maxVirtualSize[0] ), self.minVirtualSize[0]) mZPos = max( min( mPos.getZ(), -self.minVirtualSize[1] ), -self.maxVirtualSize[1]-self.headerHeight) self.windowResize.setPos( mXPos-self.resizeSize/2., 0, mZPos+self.resizeSize/2. ) self.windowResizeBackground.setPos( mXPos-self.resizeSize/2., 0, mZPos+self.resizeSize/2. ) self['frameSize'] = (0, mXPos, 0, mZPos) self.windowHeaderLeft.setPos( self.headerHeight/2., 0, -self.headerHeight/2. ) self.windowHeaderLeft.setScale( self.headerHeight, 1, self.headerHeight ) self.windowHeaderCenter.setPos( mXPos/2., 0, -self.headerHeight/2. ) self.windowHeaderCenter.setScale( mXPos - self.headerHeight*2., 1, self.headerHeight ) self.windowHeaderRight.setPos( mXPos-self.headerHeight/2., 0, -self.headerHeight/2. ) self.windowHeaderRight.setScale( self.headerHeight, 1, self.headerHeight ) self.contentWindow['frameSize'] = ( 0, mXPos, mZPos+self.headerHeight, 0) self.textNodePath.setPos( mXPos/2., 0, -self.headerHeight/3.*2. ) # show and hide that small background for the window sizer if mXPos == self.maxVirtualSize[0] and \ mZPos == -self.maxVirtualSize[1]-self.headerHeight: self.windowResizeBackground.hide() else: self.windowResizeBackground.show() def resizeTask( self, task=None ): mPos = aspect2dMouseNode.getPos( self )+self.offset self.resize( mPos, self.offset ) return task.cont def startResizeDrag( self, param ): self.offset = self.windowResize.getPos( aspect2dMouseNode ) taskMgr.remove( self.taskName ) taskMgr.add( self.resizeTask, self.taskName ) def stopResizeDrag( self, param ): taskMgr.remove( self.taskName ) # get the window to the front self.wrtReparentTo( self.windowParent ) def addHorizontal(self, widgets): """ Accepts a list of directgui objects which are added to a horizontal box, which is then added to the vertical stack. """ hbox = boxes.HBox() for widget in widgets: hbox.pack(widget) self.box.pack(hbox) self.updateMaxSize() def addVertical(self, widgets): """ Accepts a list of directgui objects which are added to a vertical box, which is then added to the vertical stack. May cause funky layout results. """ #vbox = boxes.VBox() for widget in widgets: self.box.pack(widget) self.updateMaxSize() def add(self, widgets): """Shortcut function for addVertical""" self.addVertical(widgets) def updateMaxSize(self): """Updates the max canvas size to include all items packed. Window is resized to show all contents.""" bottomLeft, topRight = self.box.getTightBounds() self.maxVirtualSize = (topRight[0], -bottomLeft[2]) self.contentWindow['canvasSize'] = ( 0, self.maxVirtualSize[0], -self.maxVirtualSize[1], 0) self.backgroundColor['frameSize'] = ( 0, self.maxVirtualSize[0], -self.maxVirtualSize[1], 0 ) #perhaps this should be optional -- automatically resize for new elements self.reset() def reset(self): """Poorly named function that resizes window to fit all contents""" self.resize( Vec3(self.maxVirtualSize[0], 0, -self.maxVirtualSize[1]-self.headerHeight), Vec3(0,0,0))
class JournalUI(UIBase): ''' This is the UI of journal ''' def __init__(self,world): ''' Constructor ''' UIBase.__init__(self, world) ''' init variables ''' #load skin of journal button and scrollbar as egg files self.button_maps = self.world.loader.loadModel("./LEGameAssets/Models/button") self.scrollbar_maps = self.world.loader.loadModel("./LEGameAssets/Models/scrollbar") #skin for the journal tray self.img_files = ["./LEGameAssets/Textures/journal_rollout_tray.png"] #variables that store the UI elements which are going to be created self.journal_window_frame = None self.window_show = True self.journal_window = None self.frame = None self.canvas = None #variables that store list of title and statement of journal from journalMrg self.journal_entries= [] self.quest_text = [] #size of the screen self.screen_size_x = base.win.getXSize() self.screen_size_y = base.win.getYSize() #variables that help to make the popout window and arrange the text self.count = [0,0,0,0] self.char_size = 0.05 self.last_char_size = None self.line_space = 0.2 self.top_line = 0.1 self.longest_line = {"menu":[0,0],"quest":[0,0]} self.buttons_1 = [] self.buttons_2 = [] self.page_canvas_size= {"menu": (0,0,0,0), "quest": (0,0,0,0)} self.page_buttons = {"menu": self.buttons_1, "quest": self.buttons_2} self.showing_page = "menu" #set the default canvas size and frame size self.canvas_size = (0.3, 1.25, 0.015, 0.75) self.frame_size = (0.3, 1.25, 0.015, 0.75) #add button self.b = DirectButton( geom = (self.button_maps.find("**/ok"),self.button_maps.find("**/click"),self.button_maps.find("**/rolling_over"),self.button_maps.find("**/disable")), text_scale = (0.15,0.15), pos = (-0.23, 0, -0.12), relief=None, scale=0.38, command=self.popoutWindow, parent= base.a2dTopRight) def update(self): self.journal_entries = self.world.journalMgr.getOpenedJournalEntries() #self.journal_entries = [("title1","Now if I take out the task argument all is fine obviously. However I need a way to access the time the task runs.This will give you a scrollbar at the lower left side of the screen. If you want to parent the scrollbar to a determined frame, you add the keyword parent to the set of keyboards like so.DirectScrollBar is available beginning in Panda3D 1.1. It consists of a long trough, a thumb that slides along the trough, and a pair of buttons on either side of the trough to scroll one line at a time. A DirectScrollBar can be oriented either vertically or horizontally."),("title2","Completed"),("title3","statement3")] #print base.win.getXSize(),base.win.getYSize() #print "update" #Create a popout window def popoutWindow(self): if self.window_show: self.longest_line = {"menu":[0,0],"quest":[0,0]} self.count = [0,0,0,0] self.update() self.journal_window_frame = DirectFrame(frameColor=(0, 0, 0, 0.12),frameSize=(0.28, 1.27, -0.005, 0.77), parent= base.a2dTopRight, pos = (-1.3,0,-1)) self.journal_window = DirectScrolledFrame(canvasSize = (self.canvas_size), frameSize = (self.frame_size),frameColor=(0, 0, 0, 0.12), autoHideScrollBars = True, manageScrollBars = True, parent = self.journal_window_frame ) self.changeSkin(self.img_files) self.changeScrollbarSkin() self.canvas= self.journal_window.getCanvas() self.createMenu() self.createQuest() self.showMenu() self.changeButtonColor() else: self.destroy() self.window_show = not self.window_show #destroy the popout window def destroy(self): self.journal_window_frame.destroy() # if the button list has been detached when the parent(journal_window) is destroyed, them won't be destroyed for button in self.buttons_1: button.destroy() for button in self.buttons_2: button.destroy() for label in self.quest_text: label.destroy() # clean up the button list for i in range(len(self.buttons_1)): self.buttons_1.pop() for j in range(len(self.buttons_2)): self.buttons_2.pop() for k in range(len(self.quest_text)): self.quest_text.pop() ''' These functions are for the other parts to call to hide/show the JournalUI ''' #---------------------------------------------- def hideAll(self): self.b.hide() if not self.window_show: self.journal_window_frame.hide() def showAll(self): self.b.show() if not self.window_show: self.journal_window_frame.show() #------------------------------------------------- def destroyAll(self): self.destroy() self.b.destroy() def createAll(self): pass #----------------------------------------------------------------------------------------- def switchPage(self, page): self.journal_window['canvasSize']=(self.page_canvas_size[page]) self.hideButton(self.page_buttons[self.showing_page]) self.showButton(self.page_buttons[page]) self.showing_page = page #------------quest------------------ if page == "quest": for label in self.quest_text: label.reparentTo(self.canvas) else : self.hideText() def hideButton(self, page): for button in page: button.detachNode() def showButton(self, page): for button in page: button.reparentTo(self.canvas) def hideText(self): for label in self.quest_text: label.detachNode() for k in range(len(self.quest_text)): self.quest_text.pop() def showMenu(self): self.switchPage("menu") def showQuest(self, tag): for entry in self.journal_entries: if entry[0] == tag: temp_text = entry[1] self.addText(temp_text, 0.05, "quest") break self.switchPage("quest") def addButton(self, text, position, scale, func_call, type, page): if type == 1: button = DirectButton(text = (text),text_fg =(1,0,0,1),text_bg =(0,0,0,0),pos =(position),text_scale = (scale), relief = None,command=func_call, extraArgs = [text]) else: button = DirectButton(text = (text),text_fg =(1,0,0,1),text_bg =(0,0,0,0),pos =(position),text_scale = (scale), relief = None,command=func_call) if(position[0] - button.getWidth()/2.0 < self.longest_line[page][0]): ''' something different here -0.02 for the right side ''' self.count[0] = position[0] - button.getWidth()/2.0 - 0.02 #right self.longest_line[page][0] = self.count[0] if(position[1] + button.getWidth()/2.0 > self.longest_line[page][1]): self.count[1] = position[1] + button.getWidth()/2.0 #left self.longest_line[page][1] = self.count[1] self.count[2] = position[2]-button.getHeight()#bottom self.journal_window['canvasSize']=(self.count[0],self.count[1],self.count[2],self.count[3]) button.detachNode() #make sure buttons won't be shown at the first time it is created self.page_buttons[page].append(button) self.page_canvas_size[page] = (self.count[0],self.count[1],self.count[2],self.count[3]) def addText(self, show_text, text_scale, page): self.page_canvas_size[page]=(self.canvas_size) max_window_width = abs(self.canvas_size[1] - self.canvas_size[0]) # the width of the DirectLabel object is only changing with the length of the string in text attribute, but this width is different from the width of the DriectFrame and DriectButton, # so I don't know what is the unit of this DriectLable width, if you change the scale of the label, the width is not going to change, and the text will going out of the boundary, # I should change the max number of character with scale text_len = len(show_text) offset = text_scale - 0.05 if(offset > 0): max_text_len = 35 - offset * 500 if(offset <= 0): max_text_len = 35 + abs(offset) * 500 text_lines = [] if text_len > max_text_len: wrapper = TextWrapper(initial_indent="* ", width = max_text_len) text_lines = wrapper.wrap(show_text) else: text_lines.append(show_text) line_space = 0.0 for t in text_lines: temp_text = DirectLabel(text = t,pos = (0.75,0,0.52-line_space),scale = text_scale, text_bg = (0,1,1,0.0),text_fg=(0,0,0,1),frameColor=(0,0,0,0)) self.quest_text.append(temp_text) if (0.5 - line_space)< self.canvas_size[2]: self.page_canvas_size[page]=(self.canvas_size[0],self.canvas_size[1]-0.1, 0.48 - line_space,self.canvas_size[3]) line_space +=0.08 for label in self.quest_text: label.detachNode() def createMenu(self): #initialize value for the beginning line, this will never change self.count[3]= self.top_line #add button offset = 0 #self.journal_entries= [("title1","Now if I take out the task argument all is fine obviously. However I need a way to access the time the task runs."),("title2","statement2"),("title3","statement3")] for entry in self.journal_entries: self.addButton(entry[0],(-0.08, 0, -0.02+offset),(0.05,0.05),self.showQuest,1 ,"menu") offset += -0.08 def createQuest(self): self.addButton("Back",(0.45, 0, 0.62),(0.08,0.08),self.showMenu,0,"quest" ) def changeSkin(self, img_files): if len(img_files) == 1: self.journal_window['image']=(img_files[0]) #self.journal_window['image_scale']=(0.43,0,0.43) #old scale without size 800*600 #self.journal_window['image_pos']=(0.75,0,0.33) #old position without size 800*600 self.journal_window['image_scale']=(1.335,1,1) self.journal_window['image_pos']=(0,0,0) self.journal_window.setTransparency(1) self.journal_window['frameColor']=(0,0,0,0) if len (img_files) == 2: self.journal_window_frame['image']=(img_files[1]) #self.journal_window_frame['image_scale']=(0.44,0,0.44)#old scale without size 800*600 #self.journal_window_frame['image_pos']=(0.75,0,0.33)#old position without size 800*600 self.journal_window_frame['image_scale']=(1.335,1,1) self.journal_window_frame['image_pos']=(0,0,0) self.journal_window_frame.setTransparency(1) self.journal_window_frame['frameColor']=(0,0,0,0) def changeScrollbarSkin(self): self.journal_window['verticalScroll_relief']= None# Relief appearance of the frame self.journal_window['verticalScroll_image']= ("./LEGameAssets/Textures/journal_scrollbar.png") self.journal_window.verticalScroll['image_pos']=(1.21,0.1,0.36) self.journal_window.verticalScroll['image_scale']=(0.05,0.1,0.38) self.journal_window.verticalScroll.incButton['geom']=(self.scrollbar_maps.find("**/journal_scrollbutton_down")) self.journal_window.verticalScroll.incButton['relief']=None# Relief appearance of the frame self.journal_window.verticalScroll.incButton['geom_scale']=(0.15,0.15,0.15) self.journal_window.verticalScroll.decButton['geom']=(self.scrollbar_maps.find("**/journal_scrollbutton_up")) self.journal_window.verticalScroll.decButton['relief']=None# Relief appearance of the frame self.journal_window.verticalScroll.decButton['geom_scale']=(0.15,0.15,0.15) self.journal_window.verticalScroll.thumb['geom']=(self.scrollbar_maps.find("**/journal_scroll_button_updown")) self.journal_window.verticalScroll.thumb['relief']=None# Relief appearance of the frame self.journal_window.verticalScroll.thumb['geom_scale']=(0.2,0.2,0.2) self.journal_window.verticalScroll.thumb['frameVisibleScale']=(0.5,0.25)#Relative scale of the visible frame to its clickable bounds. Useful for creating things like the paging region of a slider, which is visibly smaller than the acceptable click region self.journal_window.verticalScroll['resizeThumb']=(True) self.journal_window.verticalScroll['scrollSize']=(0.1) #change the amount to jump the thumb when user click up/right and down/left self.journal_window.verticalScroll['range']=(-1,1)# change the (min, max) range of the thumb #--------UI feedback----------------- def changeButtonColor(self): for entry in self.journal_entries: if (entry[1] == "Completed"): for b in self.buttons_1: if (b['text'] == entry[0]): b['text_fg'] = (0,1,0,1) def flashJournalButton(self,task): if task.time <= 0.5: self.b['geom_scale']=(0.01,0.01,0.01) return task.cont elif task.time <=1.0: self.b['geom_scale']=(1.0,1.0,1.0) return task.cont elif self.window_show != True: return task.done else: return task.again def startFlash(self): self.task = taskMgr.add(self.flashJournalButton, 'flashJournalButton')
class Credits: def __init__(self): self.frameMain = DirectFrame(frameSize=(base.a2dLeft, base.a2dRight, base.a2dBottom, base.a2dTop), frameColor=(0.05, 0.05, 0.05, 1)) self.frameMain.setTransparency(1) tpBig = TextProperties() tpBig.setTextScale(1.5) tpSmall = TextProperties() tpSmall.setTextScale(0.75) tpUs = TextProperties() tpUs.setUnderscore(True) tpMgr = TextPropertiesManager.getGlobalPtr() tpMgr.setProperties("big", tpBig) tpMgr.setProperties("small", tpSmall) tpMgr.setProperties("us", tpUs) creditsText = "" with open("credits.txt") as f: creditsText = f.read() self.lblCredits = DirectLabel(text=creditsText, text_fg=(1, 1, 1, 1), text_bg=(0, 0, 0, 0), frameColor=(0, 0, 0, 0), text_align=TextNode.ACenter, scale=0.1, pos=(0, 0, base.a2dTop - 0.2)) self.lblCredits.setTransparency(1) self.lblCredits.reparentTo(self.frameMain) self.creditsScroll = LerpPosInterval(self.lblCredits, 12.0, (0, 0, base.a2dTop + 3.5), startPos=(0, 0, base.a2dBottom), name="CreditsScroll") self.btnBack = DirectButton(text="BACK", text_fg=(1, 1, 1, 1), text_align=TextNode.ALeft, scale=0.1, pad=(0.15, 0.15), pos=(base.a2dLeft + 0.08, 0, base.a2dBottom + 0.05), frameColor=( (0.2, 0.2, 0.2, 0.8), (0.4, 0.4, 0.4, 0.8), (0.4, 0.4, 0.4, 0.8), (0.1, 0.1, 0.1, 0.8), ), relief=1, command=base.messenger.send, extraArgs=["Credits-Back"], pressEffect=False, rolloverSound=None, clickSound=None) self.btnBack.setTransparency(1) self.btnBack.reparentTo(self.frameMain) self.hide() def show(self): self.frameMain.show() self.creditsScroll.loop() def hide(self): self.frameMain.hide() self.creditsScroll.finish()
class GameOverScreen(): def __init__(self): # a fill panel so the player doesn't see how everything # gets loaded in the background self.frameMain = DirectFrame( # size of the frame frameSize = (base.a2dLeft, base.a2dRight, base.a2dTop, base.a2dBottom), image = "Logo.png", image_scale = (0.612/2.0, 1, 0.495/2.0), image_pos = (0, 0, 0.7), # tramsparent bg color frameColor = (0, 0, 0, 1)) self.frameMain.setTransparency(1) self.lblWin = DirectLabel( scale = 0.25, pos = (0, 0, 0.25), frameColor = (0, 0, 0, 0), text = _("You Succeeded"), text_align = TextNode.ACenter, text_fg = (1,1,1,1)) self.lblWin.reparentTo(self.frameMain) self.lblTime = DirectLabel( scale = 0.07, pos = (0, 0, 0.00), frameColor = (0, 0, 0, 0), text = "your time", text_align = TextNode.ACenter, text_fg = (1,1,1,1)) self.lblTime.reparentTo(self.frameMain) self.lblResult = DirectLabel( scale = 0.40, pos = (0, 0, -0.25), frameColor = (0, 0, 0, 0), text = "00:00", text_align = TextNode.ACenter, text_fg = (1,1,1,1)) self.lblResult.reparentTo(self.frameMain) self.btnContinue = DirectButton( scale = (0.25, 0.25, 0.25), # some temp text text = _("Continue..."), text_scale = (0.5, 0.5, 0.5), # set the alignment to right text_align = TextNode.ACenter, # put the text on the right side of the button text_pos = (0, 0), # set the text color to black text_fg = (1,1,1,1), text_shadow = (0.3, 0.3, 0.1, 1), text_shadowOffset = (0.05, 0.05), relief = 1, frameColor = (0,0,0,0), pressEffect = False, pos = (0, 0, -0.65), command = lambda: base.messenger.send("Exit"), rolloverSound = None, clickSound = None) self.btnContinue.setTransparency(1) self.btnContinue.reparentTo(self.frameMain) self.hide() def show(self, winLoose, resulttime): if winLoose == "win": timestring = "%d:%02d" % (resulttime/60, resulttime%60) self.lblResult["text"] = timestring self.lblTime.show() self.lblResult.show() else: self.lblWin["text"] = _("You Loose") self.lblTime.hide() self.lblResult.hide() self.frameMain.show() def hide(self): self.frameMain.hide()
class LevelSelection: def __init__(self): self.frameMain = DirectFrame(frameSize=(base.a2dLeft, base.a2dRight, base.a2dBottom, base.a2dTop), frameColor=(0.05, 0.05, 0.05, 1)) self.frameMain.setTransparency(1) self.btnLevel1 = self.createLevelButton( (-0.6, 0, 0.15), "assets/gui/Level1Button.png", 1) self.btnLevel1.reparentTo(self.frameMain) self.btnLevel2 = self.createLevelButton( (0.6, 0, 0.15), "assets/gui/Level2Button.png", 2) self.btnLevel2.reparentTo(self.frameMain) self.footerFrame = DirectFrame(text="SELECT THE ARENA", text_fg=(1, 1, 1, 1), text_scale=0.08, text_pos=(0, -0.03), frameSize=(base.a2dLeft, base.a2dRight, 0.1, -0.1), pos=(0, 0, base.a2dBottom + 0.2), frameColor=(0, 0, 0, 0.5)) self.footerFrame.setTransparency(1) self.footerFrame.reparentTo(self.frameMain) self.btnBack = DirectButton(text="BACK", text_fg=(1, 1, 1, 1), text_align=TextNode.ALeft, scale=0.1, pad=(0.15, 0.15), pos=(base.a2dLeft + 0.08, 0, -0.03), frameColor=( (0.2, 0.2, 0.2, 0.8), (0.4, 0.4, 0.4, 0.8), (0.4, 0.4, 0.4, 0.8), (0.1, 0.1, 0.1, 0.8), ), relief=1, command=base.messenger.send, extraArgs=["LevelSelection-Back"], pressEffect=False, rolloverSound=None, clickSound=None) self.btnBack.setTransparency(1) self.btnBack.reparentTo(self.footerFrame) self.hide() def createLevelButton(self, pos, image, levelNr): btn = DirectButton(scale=(0.5, 1, 0.75), relief=0, frameColor=(0, 0, 0, 0), pos=pos, image=image, command=self.selectLevel, extraArgs=[levelNr], rolloverSound=None, clickSound=None) btn.setTransparency(1) return btn def selectLevel(self, level): self.selectedLevel = level base.messenger.send("LevelSelection-Start") def show(self): self.frameMain.show() def hide(self): self.frameMain.hide()
class Credits: def __init__(self): self.frameMain = DirectFrame( frameSize = (base.a2dLeft, base.a2dRight, base.a2dBottom, base.a2dTop), frameColor = (0.05, 0.05, 0.05, 1)) self.frameMain.setTransparency(1) tpBig = TextProperties() tpBig.setTextScale(1.5) tpSmall = TextProperties() tpSmall.setTextScale(0.75) tpUs = TextProperties() tpUs.setUnderscore(True) tpMgr = TextPropertiesManager.getGlobalPtr() tpMgr.setProperties("big", tpBig) tpMgr.setProperties("small", tpSmall) tpMgr.setProperties("us", tpUs) creditsText = "" with open("credits.txt") as f: creditsText = f.read() self.lblCredits = DirectLabel( text = creditsText, text_fg = (1,1,1,1), text_bg = (0,0,0,0), frameColor = (0,0,0,0), text_align = TextNode.ACenter, scale = 0.1, pos = (0, 0, base.a2dTop - 0.2)) self.lblCredits.setTransparency(1) self.lblCredits.reparentTo(self.frameMain) self.creditsScroll = LerpPosInterval( self.lblCredits, 12.0, (0, 0, base.a2dTop + 3.5), startPos=(0, 0, base.a2dBottom), name="CreditsScroll") self.btnBack = DirectButton( text = "BACK", text_fg = (1,1,1,1), text_align = TextNode.ALeft, scale = 0.1, pad = (0.15, 0.15), pos = (base.a2dLeft + 0.08, 0, base.a2dBottom + 0.05), frameColor = ( (0.2,0.2,0.2,0.8), (0.4,0.4,0.4,0.8), (0.4,0.4,0.4,0.8), (0.1,0.1,0.1,0.8), ), relief = 1, command = base.messenger.send, extraArgs = ["Credits-Back"], pressEffect = False, rolloverSound = None, clickSound = None) self.btnBack.setTransparency(1) self.btnBack.reparentTo(self.frameMain) self.hide() def show(self): self.frameMain.show() self.creditsScroll.loop() def hide(self): self.frameMain.hide() self.creditsScroll.finish()
class JournalUI(UIBase): ''' This is the UI of journal ''' def __init__(self, world): ''' Constructor ''' UIBase.__init__(self, world) ''' init variables ''' #load skin of journal button and scrollbar as egg files self.button_maps = self.world.loader.loadModel( "./LEGameAssets/Models/button") self.scrollbar_maps = self.world.loader.loadModel( "./LEGameAssets/Models/scrollbar") #skin for the journal tray self.img_files = ["./LEGameAssets/Textures/journal_rollout_tray.png"] #variables that store the UI elements which are going to be created self.journal_window_frame = None self.window_show = True self.journal_window = None self.frame = None self.canvas = None #variables that store list of title and statement of journal from journalMrg self.journal_entries = [] self.quest_text = [] #size of the screen self.screen_size_x = base.win.getXSize() self.screen_size_y = base.win.getYSize() #variables that help to make the popout window and arrange the text self.count = [0, 0, 0, 0] self.char_size = 0.05 self.last_char_size = None self.line_space = 0.2 self.top_line = 0.1 self.longest_line = {"menu": [0, 0], "quest": [0, 0]} self.buttons_1 = [] self.buttons_2 = [] self.page_canvas_size = {"menu": (0, 0, 0, 0), "quest": (0, 0, 0, 0)} self.page_buttons = {"menu": self.buttons_1, "quest": self.buttons_2} self.showing_page = "menu" #set the default canvas size and frame size self.canvas_size = (0.3, 1.25, 0.015, 0.75) self.frame_size = (0.3, 1.25, 0.015, 0.75) #add button self.b = DirectButton(geom=(self.button_maps.find("**/ok"), self.button_maps.find("**/click"), self.button_maps.find("**/rolling_over"), self.button_maps.find("**/disable")), text_scale=(0.15, 0.15), pos=(-0.23, 0, -0.12), relief=None, scale=0.38, command=self.popoutWindow, parent=base.a2dTopRight) def update(self): self.journal_entries = self.world.journalMgr.getOpenedJournalEntries() #self.journal_entries = [("title1","Now if I take out the task argument all is fine obviously. However I need a way to access the time the task runs.This will give you a scrollbar at the lower left side of the screen. If you want to parent the scrollbar to a determined frame, you add the keyword parent to the set of keyboards like so.DirectScrollBar is available beginning in Panda3D 1.1. It consists of a long trough, a thumb that slides along the trough, and a pair of buttons on either side of the trough to scroll one line at a time. A DirectScrollBar can be oriented either vertically or horizontally."),("title2","Completed"),("title3","statement3")] #print base.win.getXSize(),base.win.getYSize() #print "update" #Create a popout window def popoutWindow(self): if self.window_show: self.longest_line = {"menu": [0, 0], "quest": [0, 0]} self.count = [0, 0, 0, 0] self.update() self.journal_window_frame = DirectFrame(frameColor=(0, 0, 0, 0.12), frameSize=(0.28, 1.27, -0.005, 0.77), parent=base.a2dTopRight, pos=(-1.3, 0, -1)) self.journal_window = DirectScrolledFrame( canvasSize=(self.canvas_size), frameSize=(self.frame_size), frameColor=(0, 0, 0, 0.12), autoHideScrollBars=True, manageScrollBars=True, parent=self.journal_window_frame) self.changeSkin(self.img_files) self.changeScrollbarSkin() self.canvas = self.journal_window.getCanvas() self.createMenu() self.createQuest() self.showMenu() self.changeButtonColor() else: self.destroy() self.window_show = not self.window_show #destroy the popout window def destroy(self): self.journal_window_frame.destroy() # if the button list has been detached when the parent(journal_window) is destroyed, them won't be destroyed for button in self.buttons_1: button.destroy() for button in self.buttons_2: button.destroy() for label in self.quest_text: label.destroy() # clean up the button list for i in range(len(self.buttons_1)): self.buttons_1.pop() for j in range(len(self.buttons_2)): self.buttons_2.pop() for k in range(len(self.quest_text)): self.quest_text.pop() ''' These functions are for the other parts to call to hide/show the JournalUI ''' #---------------------------------------------- def hideAll(self): self.b.hide() if not self.window_show: self.journal_window_frame.hide() def showAll(self): self.b.show() if not self.window_show: self.journal_window_frame.show() #------------------------------------------------- def destroyAll(self): self.destroy() self.b.destroy() def createAll(self): pass #----------------------------------------------------------------------------------------- def switchPage(self, page): self.journal_window['canvasSize'] = (self.page_canvas_size[page]) self.hideButton(self.page_buttons[self.showing_page]) self.showButton(self.page_buttons[page]) self.showing_page = page #------------quest------------------ if page == "quest": for label in self.quest_text: label.reparentTo(self.canvas) else: self.hideText() def hideButton(self, page): for button in page: button.detachNode() def showButton(self, page): for button in page: button.reparentTo(self.canvas) def hideText(self): for label in self.quest_text: label.detachNode() for k in range(len(self.quest_text)): self.quest_text.pop() def showMenu(self): self.switchPage("menu") def showQuest(self, tag): for entry in self.journal_entries: if entry[0] == tag: temp_text = entry[1] self.addText(temp_text, 0.05, "quest") break self.switchPage("quest") def addButton(self, text, position, scale, func_call, type, page): if type == 1: button = DirectButton(text=(text), text_fg=(1, 0, 0, 1), text_bg=(0, 0, 0, 0), pos=(position), text_scale=(scale), relief=None, command=func_call, extraArgs=[text]) else: button = DirectButton(text=(text), text_fg=(1, 0, 0, 1), text_bg=(0, 0, 0, 0), pos=(position), text_scale=(scale), relief=None, command=func_call) if (position[0] - button.getWidth() / 2.0 < self.longest_line[page][0]): ''' something different here -0.02 for the right side ''' self.count[ 0] = position[0] - button.getWidth() / 2.0 - 0.02 #right self.longest_line[page][0] = self.count[0] if (position[1] + button.getWidth() / 2.0 > self.longest_line[page][1]): self.count[1] = position[1] + button.getWidth() / 2.0 #left self.longest_line[page][1] = self.count[1] self.count[2] = position[2] - button.getHeight() #bottom self.journal_window['canvasSize'] = (self.count[0], self.count[1], self.count[2], self.count[3]) button.detachNode( ) #make sure buttons won't be shown at the first time it is created self.page_buttons[page].append(button) self.page_canvas_size[page] = (self.count[0], self.count[1], self.count[2], self.count[3]) def addText(self, show_text, text_scale, page): self.page_canvas_size[page] = (self.canvas_size) max_window_width = abs(self.canvas_size[1] - self.canvas_size[0]) # the width of the DirectLabel object is only changing with the length of the string in text attribute, but this width is different from the width of the DriectFrame and DriectButton, # so I don't know what is the unit of this DriectLable width, if you change the scale of the label, the width is not going to change, and the text will going out of the boundary, # I should change the max number of character with scale text_len = len(show_text) offset = text_scale - 0.05 if (offset > 0): max_text_len = 35 - offset * 500 if (offset <= 0): max_text_len = 35 + abs(offset) * 500 text_lines = [] if text_len > max_text_len: wrapper = TextWrapper(initial_indent="* ", width=max_text_len) text_lines = wrapper.wrap(show_text) else: text_lines.append(show_text) line_space = 0.0 for t in text_lines: temp_text = DirectLabel(text=t, pos=(0.75, 0, 0.52 - line_space), scale=text_scale, text_bg=(0, 1, 1, 0.0), text_fg=(0, 0, 0, 1), frameColor=(0, 0, 0, 0)) self.quest_text.append(temp_text) if (0.5 - line_space) < self.canvas_size[2]: self.page_canvas_size[page] = (self.canvas_size[0], self.canvas_size[1] - 0.1, 0.48 - line_space, self.canvas_size[3]) line_space += 0.08 for label in self.quest_text: label.detachNode() def createMenu(self): #initialize value for the beginning line, this will never change self.count[3] = self.top_line #add button offset = 0 #self.journal_entries= [("title1","Now if I take out the task argument all is fine obviously. However I need a way to access the time the task runs."),("title2","statement2"),("title3","statement3")] for entry in self.journal_entries: self.addButton(entry[0], (-0.08, 0, -0.02 + offset), (0.05, 0.05), self.showQuest, 1, "menu") offset += -0.08 def createQuest(self): self.addButton("Back", (0.45, 0, 0.62), (0.08, 0.08), self.showMenu, 0, "quest") def changeSkin(self, img_files): if len(img_files) == 1: self.journal_window['image'] = (img_files[0]) #self.journal_window['image_scale']=(0.43,0,0.43) #old scale without size 800*600 #self.journal_window['image_pos']=(0.75,0,0.33) #old position without size 800*600 self.journal_window['image_scale'] = (1.335, 1, 1) self.journal_window['image_pos'] = (0, 0, 0) self.journal_window.setTransparency(1) self.journal_window['frameColor'] = (0, 0, 0, 0) if len(img_files) == 2: self.journal_window_frame['image'] = (img_files[1]) #self.journal_window_frame['image_scale']=(0.44,0,0.44)#old scale without size 800*600 #self.journal_window_frame['image_pos']=(0.75,0,0.33)#old position without size 800*600 self.journal_window_frame['image_scale'] = (1.335, 1, 1) self.journal_window_frame['image_pos'] = (0, 0, 0) self.journal_window_frame.setTransparency(1) self.journal_window_frame['frameColor'] = (0, 0, 0, 0) def changeScrollbarSkin(self): self.journal_window[ 'verticalScroll_relief'] = None # Relief appearance of the frame self.journal_window['verticalScroll_image'] = ( "./LEGameAssets/Textures/journal_scrollbar.png") self.journal_window.verticalScroll['image_pos'] = (1.21, 0.1, 0.36) self.journal_window.verticalScroll['image_scale'] = (0.05, 0.1, 0.38) self.journal_window.verticalScroll.incButton['geom'] = ( self.scrollbar_maps.find("**/journal_scrollbutton_down")) self.journal_window.verticalScroll.incButton[ 'relief'] = None # Relief appearance of the frame self.journal_window.verticalScroll.incButton['geom_scale'] = (0.15, 0.15, 0.15) self.journal_window.verticalScroll.decButton['geom'] = ( self.scrollbar_maps.find("**/journal_scrollbutton_up")) self.journal_window.verticalScroll.decButton[ 'relief'] = None # Relief appearance of the frame self.journal_window.verticalScroll.decButton['geom_scale'] = (0.15, 0.15, 0.15) self.journal_window.verticalScroll.thumb['geom'] = ( self.scrollbar_maps.find("**/journal_scroll_button_updown")) self.journal_window.verticalScroll.thumb[ 'relief'] = None # Relief appearance of the frame self.journal_window.verticalScroll.thumb['geom_scale'] = (0.2, 0.2, 0.2) self.journal_window.verticalScroll.thumb['frameVisibleScale'] = ( 0.5, 0.25 ) #Relative scale of the visible frame to its clickable bounds. Useful for creating things like the paging region of a slider, which is visibly smaller than the acceptable click region self.journal_window.verticalScroll['resizeThumb'] = (True) self.journal_window.verticalScroll['scrollSize'] = ( 0.1 ) #change the amount to jump the thumb when user click up/right and down/left self.journal_window.verticalScroll['range'] = ( -1, 1) # change the (min, max) range of the thumb #--------UI feedback----------------- def changeButtonColor(self): for entry in self.journal_entries: if (entry[1] == "Completed"): for b in self.buttons_1: if (b['text'] == entry[0]): b['text_fg'] = (0, 1, 0, 1) def flashJournalButton(self, task): if task.time <= 0.5: self.b['geom_scale'] = (0.01, 0.01, 0.01) return task.cont elif task.time <= 1.0: self.b['geom_scale'] = (1.0, 1.0, 1.0) return task.cont elif self.window_show != True: return task.done else: return task.again def startFlash(self): self.task = taskMgr.add(self.flashJournalButton, 'flashJournalButton')
def windowMaker(base, label): # find an open slot, if none, return false windict = dict() grid = None for i in range(grid_size[0]): for j in range(grid_size[1]): if occupied[i][j] == False: grid = (i, j) occupied[i][j] = True break else: continue break if not grid: return False windict['grid'] = grid position = grid_to_screen_pos(*grid) #open window newwin = base.openWindow(name=label) newwin.setWindowEvent(label + "-event") listener.accept(newwin.getWindowEvent(), windowEvent) windict['win'] = newwin #format window wp = WindowProperties() wp.setOrigin(*position) wp.setSize(*ws) newwin.requestProperties(wp) #make 3d-mousewatcher display region displayRegion = newwin.getDisplayRegion(0) displayRegion.setDimensions(.3, 1, 0, 1) mkNode = MouseAndKeyboard(newwin, 0, label + "_keyboard_mouse") mk = base.dataRoot.attachNewNode(mkNode) windict['mk'] = mk modis = ModifierButtons() modis.addButton(ButtonHandle('shift')) modis.addButton(ButtonHandle('control')) mwNode = MouseWatcher(label) mwNode.setModifierButtons(modis) mwNode.setDisplayRegion(displayRegion) mw = mk.attachNewNode(mwNode) windict['mw'] = mw bt = ButtonThrower(label + "_button_thrower") bt.setModifierButtons(modis) windict['bt'] = bt bt.setPrefix(label + "_") mw.attachNewNode(bt) #listen for default button events for button in buttons: listener.accept(bt.prefix + button, buttons[button]) #format render display region render_dr = newwin.getDisplayRegion(1) windict['render_dr'] = render_dr render_dr.setDimensions(.3, 1, 0, 1) #create a display region for Gui Elements gui_dr = newwin.makeDisplayRegion(0, .3, .3, 1) # gui_dr.setSort(20) mwNodegui = MouseWatcher(label + "gui") mwNodegui.setDisplayRegion(gui_dr) mwgui = mk.attachNewNode(mwNodegui) #create a 2d render/aspect for gui rendergui = NodePath('render2d') rendergui.setDepthWrite(0) rendergui.setMaterialOff(1) rendergui.setTwoSided(1) #set up aspect2d aspectgui = rendergui.attachNewNode(PGTop('aspectgui')) aspectgui.node().setMouseWatcher(mwgui.node()) #set up camera camNodegui = Camera("camNode2d") cameragui = rendergui.attachNewNode(camNodegui) cameragui.setPos(0, 0, 0) cameragui.setDepthTest(False) cameragui.setDepthWrite(False) lens = OrthographicLens() lens.setFilmSize(2, 2) lens.setNearFar(-1000, 1000) cameragui.node().setLens(lens) gui_dr.setCamera(cameragui) #make frame for gui frame = DirectFrame(frameSize=(-1, 1, -1, 1), frameColor=(.5, .5, .5, 1), relief='ridge') frame.reparentTo(aspectgui) frame.setTransparency(0) windict['gui_frame'] = frame #create Gui elements guibuttons = dict() # guibuttons['Create'] = label+"_mode_create" guibuttons['Preview'] = label + "_preview" # createButton(base, frame, .7, "Create", label+"_mode_create") createButton(base, frame, .7, "Preview", label + "_preview") windict['guibuttons'] = guibuttons #create a display region for math data preview preview_dr = newwin.makeDisplayRegion(0, .3, 0, .3) windict['preview_dr'] = preview_dr # preview_label = label+"_preview" # preview_mwNode = MouseWatcher(preview_label) # preview_mwNode.setDisplayRegion(preview_dr) # preview_mw = mk.attachNewNode(preview_mwNode) # preview_bt = ButtonThrower(preview_label+"_button_thrower") # preview_bt.setPrefix(preview_label+"_") # preview_mw.attachNewNode(preview_bt) # preview_dr.setSort(30) win_to_windict[newwin] = windict return windict
class LevelSelection: def __init__(self): self.frameMain = DirectFrame( frameSize = (base.a2dLeft, base.a2dRight, base.a2dTop, base.a2dBottom), frameColor = (0.05, 0.05, 0.05, 1)) self.frameMain.setTransparency(1) self.btnLevel1 = self.createLevelButton( (-0.6, 0, 0.15), "assets/gui/Level1Button.png", 1) self.btnLevel1.reparentTo(self.frameMain) self.btnLevel2 = self.createLevelButton( (0.6, 0, 0.15), "assets/gui/Level2Button.png", 2) self.btnLevel2.reparentTo(self.frameMain) self.footerFrame = DirectFrame( text = "SELECT THE ARENA", text_fg = (1,1,1,1), text_scale = 0.08, text_pos = (0, -0.03), frameSize = (base.a2dLeft, base.a2dRight, -0.1, 0.1), pos = (0, 0, base.a2dBottom + 0.2), frameColor = (0, 0, 0, 0.5)) self.footerFrame.setTransparency(1) self.footerFrame.reparentTo(self.frameMain) self.btnBack = DirectButton( text = "BACK", text_fg = (1,1,1,1), text_align = TextNode.ALeft, scale = 0.1, pad = (0.15, 0.15), pos = (base.a2dLeft + 0.08, 0, -0.03), frameColor = ( (0.2,0.2,0.2,0.8), (0.4,0.4,0.4,0.8), (0.4,0.4,0.4,0.8), (0.1,0.1,0.1,0.8), ), relief = 1, command = base.messenger.send, extraArgs = ["LevelSelection-Back"], pressEffect = False, rolloverSound = None, clickSound = None) self.btnBack.setTransparency(1) self.btnBack.reparentTo(self.footerFrame) self.hide() def createLevelButton(self, pos, image, levelNr): btn = DirectButton( scale = (0.5, 1, 0.75), relief = 0, frameColor = (0,0,0,0), pos = pos, image = image, command = self.selectLevel, extraArgs = [levelNr], rolloverSound = None, clickSound = None) btn.setTransparency(1) return btn def selectLevel(self, level): self.selectedLevel = level base.messenger.send("LevelSelection-Start") def show(self): self.frameMain.show() def hide(self): self.frameMain.hide()