class Vehicle: """A moving 'vehicle' represented by a circle and with a floating text label that changes over time. Each vehicle uses its own Draw object, and moves itself around by moving the NodePath to which the Draw object is attached. A DirectLabel is attached to the same NodePath for textual annotation.""" def __init__(self): """Initialise the vehicle.""" # Draw a circle to represent this vehicle. d = Draw() d.drawXYCircle(pos = Vec3(0,0,0)) node = d.create() self.np = NodePath(node) self.np.reparentTo(render) # Add a text label above and to the side of this vehicle. self.label=DirectLabel( parent=self.np, text="Hello! :)", text_wordwrap=10, relief=None, text_scale=(0.5,0.5), text_frame=(0,0,0,0), text_bg=(0,0,0,0), color=(0.88,0,0.88,1)) self.label.setPos(2,4,2) # Offset text a little from vehicle. self.label.setBillboardAxis() # Compute a random direction for this vehicle to move in. self.direction = Vec3(random.random()-0.5,random.random()-0.5,0) self.direction.normalize() # Add a task to move this vehicle around. self.prevtime = 0 taskMgr.add(self.move,"moveTask") def move(self,task): """Move the vehicle around by moving it's NodePath.""" speed = 5 elapsed = task.time - self.prevtime # A hard-coded ugly hack to make the vehicle bounce around inside # the grid. self.np.setPos(self.np.getPos()+((self.direction*speed)*elapsed)) text = 'X: ' + str(self.np.getPos().getX()) + '\n' text += 'Y: ' + str(self.np.getPos().getY()) + '\n' self.label['text'] = text if (self.np.getPos().getX() < -50 or self.np.getPos().getX() > 50 or self.np.getPos().getY() < -50 or self.np.getPos().getY() > 50 ): self.direction = -self.direction self.prevtime = task.time return Task.cont
def activate(self): # create main dialog frame # Note: frame position references the CENTER of the frame self.frm = DirectFrame( pos = (0,0,0), frameSize = (self.frmLeft, self.frmRight,self.frmBottom, self.frmTop), relief = DGG.RIDGE, borderWidth = (0.01, 0.01), frameColor = (0.6, 0.6, 0.6, 1.0)) self.frm.reparentTo(base.aspect2d) # Note: wonderfully enough, label position on the other hand # references the CENTER of the LEFT border of the label! titleLabel = DirectLabel(text = self.title, scale = 0.04, frameColor = (0.5, 0.5, 0.5, 1), relief = DGG.RIDGE, borderWidth = (0.01, 0.01), text_align = TextNode.ALeft) titleLabel.setPos(-self.frmWidth/2+.02, 0, self.frmHeight/2-.045) titleLabel.reparentTo(self.frm) sc = .04 self.dir_edit_field = DirectEntry( text = '', # prompt text scale = sc, frameColor = (0.65, 0.65, 0.65, 1), command=self.setText, width = 32, numLines = 1, focus = 1, focusInCommand=self.efFocusIn, ) self.dir_edit_field.setPos(-self.frmWidth/2+.02, 0, self.frmHeight/2-.13) self.dir_edit_field.reparentTo(self.frm) self.statusLabel = DirectLabel(text = self.initial_status, scale = 0.04, frameColor = (0.6, 0.6, 0.6, 1), # relief = DGG.RIDGE, # borderWidth = (0.01, 0.01), text_align = TextNode.ALeft) self.statusLabel.setPos(-self.frmWidth/2+.02, 0, self.frmHeight/2-.2) self.statusLabel.reparentTo(self.frm)
def putBuildingMarker(self, pos, hpr = (0, 0, 0), mapIndex = None): marker = DirectLabel(parent=self.container, text='', text_pos=(-0.05, -0.15), text_fg=(1, 1, 1, 1), relief=None) gui = loader.loadModel('phase_4/models/parties/schtickerbookHostingGUI') icon = gui.find('**/startPartyButton_inactive') iconNP = aspect2d.attachNewNode('iconNP') icon.reparentTo(iconNP) icon.setX(-12.0792 / 30.48) icon.setZ(-9.7404 / 30.48) marker['text'] = '%s' % mapIndex marker['text_scale'] = 0.7 marker['image'] = iconNP marker['image_color'] = (1, 0, 0, 1) marker['image_scale'] = 6 marker.setScale(0.05) relX, relY = self.transformAvPos(pos) marker.setPos(relX, 0, relY) self.buildingMarkers.append(marker) iconNP.removeNode() gui.removeNode()
class MainMenu(DirectObject): """This class represents the main menu as seen directly after the application has been started""" def __init__(self): # loading music self.menuMusic = loader.loadMusic("music/01Menu.mp3") self.menuMusic.setLoop(True) # create a main frame as big as the window self.frameMain = DirectFrame( # set framesize the same size as the window frameSize = (base.a2dLeft, base.a2dRight, base.a2dTop, base.a2dBottom), # position center pos = (0, 0, 0), # set tramsparent background color frameColor = (0.15, 0.15, 0.15, 1)) #self.frameMain.reparentTo(render2d) self.menuBackground = OnscreenImage( image = 'gui/Background.png', scale = (1.66, 1, 1), pos = (0, 0, 0)) self.menuBackground.reparentTo(self.frameMain) self.defaultBtnMap = base.loader.loadModel("gui/button_map") self.buttonGeom = ( self.defaultBtnMap.find("**/button_ready"), self.defaultBtnMap.find("**/button_click"), self.defaultBtnMap.find("**/button_rollover"), self.defaultBtnMap.find("**/button_disabled")) self.defaultTxtMap = base.loader.loadModel("gui/textbox_map") self.textboxGeom = self.defaultTxtMap.find("**/textbox") monospace = loader.loadFont('gui/DejaVuSansMono.ttf') defaultFont = loader.loadFont('gui/eufm10.ttf') # create the title self.textscale = 0.25 self.title = DirectLabel( # scale and position scale = self.textscale, pos = (0.0, 0.0, base.a2dTop - self.textscale), # frame frameColor = (0, 0, 0, 0), # Text text = "Dungeon Crawler", text_align = TextNode.ACenter, text_fg = (0.82,0.85,0.87,1), text_shadow = (0, 0, 0, 1), text_shadowOffset = (-0.02, -0.02), text_font = defaultFont) self.title.setTransparency(1) self.title.reparentTo(self.frameMain) # create a host button self.btnHostPos = Vec3(0, 0, .45) self.btnHostScale = 0.25 self.btnHost = DirectButton( # Scale and position scale = self.btnHostScale, pos = self.btnHostPos, # Text text = "Host", text_scale = 0.8, text_pos = (0, -0.2), text_fg = (0.82,0.85,0.87,1), text_shadow = (0, 0, 0, 1), text_shadowOffset = (-0.02, -0.02), text_font = defaultFont, # Frame geom = self.buttonGeom, frameColor = (0, 0, 0, 0), relief = 0, pressEffect = False, # Functionality command = self.host, rolloverSound = None, clickSound = None) self.btnHost.setTransparency(1) self.btnHost.reparentTo(self.frameMain) # create a join button self.btnJoinPos = Vec3(0, 0, 0) self.btnJoinScale = 0.25 self.btnJoin = DirectButton( scale = self.btnJoinScale, pos = self.btnJoinPos, text = "Join", text_scale = 0.8, text_pos = (0, -0.2), text_fg = (0.82,0.85,0.87,1), text_shadow = (0, 0, 0, 1), text_shadowOffset = (-0.02, -0.02), text_font = defaultFont, geom = self.buttonGeom, frameColor = (0, 0, 0, 0), relief = 0, pressEffect = False, command = self.join, rolloverSound = None, clickSound = None) self.btnJoin.setTransparency(1) self.btnJoin.reparentTo(self.frameMain) # create the IP input field self.txtIPPos = Vec3(0, 0, -.30) self.txtIPScale = 0.25 self.txtIPWidth = 9 self.txtIP = DirectEntry( # scale and position pos = self.txtIPPos, scale = self.txtIPScale, width = self.txtIPWidth, # Text entryFont = monospace, text_align = TextNode.ACenter, text = "", text_scale = 0.5, text_pos = (0, -0.2), text_fg = (0.82,0.85,0.87,1), text_shadow = (0, 0, 0, 1), text_shadowOffset = (0.04, 0.04), initialText = "127.0.0.1", numLines = 1, # Frame geom = self.textboxGeom, frameColor = (0, 0, 0, 0), relief = 0, # Functionality command = self.join, focusInCommand = self.clearText) self.txtIP.reparentTo(self.frameMain) # create an exit button self.btnExitPos = Vec3(0, 0, -.75) self.btnExitScale = 0.25 self.btnExit = DirectButton( scale = self.btnExitScale, pos = self.btnExitPos, text = "Exit", text_scale = 0.8, text_pos = (0, -0.2), text_fg = (0.82,0.85,0.87,1), text_shadow = (0, 0, 0, 1), text_shadowOffset = (-0.02, -0.02), text_font = defaultFont, geom = self.buttonGeom, frameColor = (0, 0, 0, 0), relief = 0, pressEffect = False, command = lambda: base.messenger.send("escape"), rolloverSound = None, clickSound = None) self.btnExit.setTransparency(1) self.btnExit.reparentTo(self.frameMain) # create a mute checkbox self.cbVolumeMute = DirectCheckBox( # set size scale = (0.1, 0.1, 0.1), frameSize = (-1, 1, 1, -1), # functionality and visuals command = self.cbVolumeMute_CheckedChanged, isChecked = True, checkedImage = "gui/SoundSwitch_off.png", uncheckedImage = "gui/SoundSwitch_on.png", # mouse behaviour relief = 0, pressEffect = False, rolloverSound = None, clickSound = None ) self.cbVolumeMute.setTransparency(1) self.cbVolumeMute.reparentTo(self.frameMain) self.cbVolumeMute.commandFunc(None) # catch window resizes and recalculate the aspectration self.accept("window-event", self.recalcAspectRatio) self.accept("showerror", self.showError) # show the menu right away self.show() def host(self): """Function which will be called by pressing the host button""" self.hide() base.messenger.send("start_server") def join(self, ip=None): """Function which will be called by pressing the join button""" if ip == None: ip = self.txtIP.get(True) if ip == "": return self.hide() base.messenger.send("start_client", [ip]) def showError(self, msg): self.show() self.dialog = OkDialog( dialogName="ErrorDialog", text="Error: {}".format(msg), command=self.closeDialog) def closeDialog(self, args): self.dialog.hide() def show(self): """Show the GUI""" self.frameMain.show() self.menuMusic.play() def hide(self): """Hide the GUI""" self.frameMain.hide() self.menuMusic.stop() def clearText(self): """Function to clear the text that was previously entered in the IP input field""" self.txtIP.enterText("") def cbVolumeMute_CheckedChanged(self, checked): if bool(checked): base.disableAllAudio() else: base.enableAllAudio() def recalcAspectRatio(self, window): """get the new aspect ratio to resize the mainframe""" # set the mainframe size to the window borders again self.frameMain["frameSize"] = ( base.a2dLeft, base.a2dRight, base.a2dTop, base.a2dBottom) # calculate new aspec tratio wp = window.getProperties() aspX = 1.0 aspY = 1.0 wpXSize = wp.getXSize() wpYSize = wp.getYSize() if wpXSize > wpYSize: aspX = wpXSize / float(wpYSize) else: aspY = wpYSize / float(wpXSize) # calculate new position/size/whatever of the gui items self.title.setPos(0.0, 0.0, base.a2dTop - self.textscale) self.menuBackground.setScale(1.0 * aspX, 1.0, 1.0 * aspY) self.cbVolumeMute.setPos(base.a2dRight - 0.15, 0, base.a2dBottom + 0.15)
class RepairGameButton(GuiButton): def __init__(self, parent, **kw): optiondefs = (('nodePath', None, None), ('image_scale', (1.0, 1.0, 1.0), None)) self.defineoptions(kw, optiondefs) GuiButton.__init__(self, parent) self.initialiseoptions(RepairGameButton) self.disabledStateNode = self.stateNodePath[3].getChild(0) self.downStateNode = self.stateNodePath[1].getChild(0) self.overStateNode = self.stateNodePath[2].getChild(0) self.inProgress = False self._initGUI() def _initGUI(self): self.setBin('fixed', 33) mainGui = loader.loadModel('models/gui/gui_main') gui = loader.loadModel('models/gui/toplevel_gui') self.checkMark = gui.find('**/generic_check') self.checkMark.reparentTo(self) self.checkMark.stash() self.checkMark.setScale(1.0) self.checkMark.setColorScale(0.0, 1.0, 0.0, 1.0) self.checkMark.setPos(0.02, 0.0, 0.02) self.checkMark.setBin('fixed', 34) self.skillRing = DialMeter(self, wantCover = False, dangerRatio = 0.0, meterColor = Vec4(0.90000000000000002, 0.90000000000000002, 0.10000000000000001, 1.0), baseColor = Vec4(0.14999999999999999, 0.070000000000000007, 0.029999999999999999, 1.0), completeColor = Vec4(0.10000000000000001, 0.90000000000000002, 0.10000000000000001, 1.0)) self.skillRing.reparentTo(self) self.skillRing.setScale(0.28499999999999998, 0.29999999999999999, 0.26500000000000001) self.skillRing.setBin('fixed', 32) self.skillGlow = OnscreenImage(parent = self, image = mainGui.find('**/icon_glow'), scale = (1.0, 1.0, 1.0), color = (1.0, 1.0, 0.59999999999999998, 1.0)) self.glow = OnscreenImage(parent = self, image = mainGui.find('**/icon_glow'), scale = (1.0, 1.0, 1.0), color = (1.0, 1.0, 0.59999999999999998, 1.0)) self.skillGlow.reparentTo(self) self.skillGlow.setBin('fixed', 31) self.skillGlow.stash() self.pirateNameBox = None self.pirateNameLabel = None def showGlow(self): self.inProgress = False if self.pirateNameLabel == None and self.checkMark.isStashed(): self.skillGlow.unstash() def hideGlow(self): self.inProgress = True self.skillGlow.stash() def setProgress(self, percent): self.skillGlow.stash() ratio = max(0.0, percent / 100.0) if ratio >= 1.0: if self.checkMark.isStashed(): self.checkMark.unstash() elif not self.checkMark.isStashed(): self.checkMark.stash() if self.pirateNameLabel == None and not (self.inProgress): self.skillGlow.unstash() self.skillRing.update(ratio, 1.0) self.skillRing.wrtReparentTo(self.getParent()) self.reparentTo(self.getParent()) def updatePirateNameBox(self, pirateName): if self.pirateNameLabel != None and self.pirateNameLabel['text'] != pirateName: if self.pirateNameBox: self.pirateNameBox.destroy() if self.pirateNameLabel: self.pirateNameLabel.destroy() self.pirateNameBox = None self.pirateNameLabel = None if pirateName != '': if self.pirateNameBox: pass if not (self.pirateNameLabel['text'] == pirateName): self.createPirateNameBox(pirateName) def createPirateNameBox(self, pirateName): self.pirateNameLabel = DirectLabel(relief = None, state = DGG.DISABLED, text = pirateName, text_align = TextNode.ACenter, text_scale = PiratesGuiGlobals.TextScaleMed, text_fg = PiratesGuiGlobals.TextFG1, text_wordwrap = 12, textMayChange = 0, sortOrder = 91) self.pirateNameLabel.setBin('fixed', 33) height = self.pirateNameLabel.getHeight() width = self.pirateNameLabel.getWidth() + 0.050000000000000003 pos = [ 0.0, 0.0, height / 2 - 0.035000000000000003] fs = [ -(width / 2 + 0.01), width / 2 + 0.01, -(height / 2 + 0.014999999999999999), height / 2 + 0.014999999999999999] self.pirateNameBox = BorderFrame(parent = self, state = DGG.DISABLED, frameSize = (fs[0], fs[1], fs[2], fs[3]), modelName = 'general_frame_f', pos = (0.0, 0.0, 0.0)) self.pirateNameLabel.reparentTo(self.pirateNameBox) self.pirateNameLabel.setPos(pos[0], pos[1], pos[2]) self.pirateNameBox.setClipPlaneOff() pos = self.pirateNameBox.getPos(aspect2d) x = min(pos[0], base.a2dRight - width) z = max(pos[2], base.a2dBottom - height) self.pirateNameBox.setPos(aspect2d, x, 0, z - 0.17499999999999999) self.pirateNameBox.flattenLight() self.pirateNameBox.setBin('fixed', 32) self.pirateNameBox.reparentTo(self)
class QuestMap(DirectFrame): def __init__(self, av, **kw): DirectFrame.__init__(self, relief=None, sortOrder=50) self.initialiseoptions(QuestMap) self.container = DirectFrame(parent=self, relief=None) self.marker = DirectFrame(parent=self.container, relief=None) self.cogInfoFrame = DirectFrame(parent=self.container, relief=None) cm = CardMaker('bg') cm.setFrame(-0.5, 0.5, -0.5, 0.5) bg = self.cogInfoFrame.attachNewNode(cm.generate()) bg.setTransparency(1) bg.setColor(0.5, 0.5, 0.5, 0.5) bg.setBin('fixed', 0) self.cogInfoFrame['geom'] = bg self.cogInfoFrame['geom_pos'] = (1.2, 0, 0) self.cogInfoFrame['geom_scale'] = (9, 1, 2) self.cogInfoFrame.setScale(0.05) self.cogInfoFrame.setPos(0, 0, 0.6) self.buildingMarkers = [] self.suitBuildingMarkers = [] self.questBlocks = [] self.av = av self.wantToggle = False if base.config.GetBool('want-toggle-quest-map', True): self.wantToggle = True self.updateMarker = True self.cornerPosInfo = None self.hqPosInfo = None self.fishingSpotInfo = None self.load() self.setScale(1.5) bg.removeNode() self.hoodId = None self.zoneId = None self.suitPercentage = {} for currHoodInfo in SuitPlannerBase.SuitPlannerBase.SuitHoodInfo: tracks = currHoodInfo[SuitPlannerBase.SuitPlannerBase.SUIT_HOOD_INFO_TRACK] self.suitPercentage[currHoodInfo[SuitPlannerBase.SuitPlannerBase.SUIT_HOOD_INFO_ZONE]] = tracks return def load(self): gui = loader.loadModel('phase_4/models/questmap/questmap_gui') icon = gui.find('**/tt_t_gui_qst_arrow') iconNP = aspect2d.attachNewNode('iconNP') icon.reparentTo(iconNP) icon.setR(90) self.marker['geom'] = iconNP self.marker['image'] = iconNP self.marker.setScale(0.05) iconNP.removeNode() self.mapOpenButton = DirectButton(image=(gui.find('**/tt_t_gui_qst_mapClose'), gui.find('**/tt_t_gui_qst_mapClose'), gui.find('**/tt_t_gui_qst_mapTryToOpen')), relief=None, pos=(-0.08, 0, 0.37), parent=base.a2dBottomRight, scale=0.205, command=self.show) self.mapCloseButton = DirectButton(image=(gui.find('**/tt_t_gui_qst_mapOpen'), gui.find('**/tt_t_gui_qst_mapOpen'), gui.find('**/tt_t_gui_qst_mapTryToClose')), relief=None, pos=(-0.08, 0, 0.37), parent=base.a2dBottomRight, scale=0.205, command=self.hide) self.mapOpenButton.hide() self.mapCloseButton.hide() gui.removeNode() icons = loader.loadModel('phase_3/models/gui/cog_icons') cIcon = icons.find('**/CorpIcon') lIcon = icons.find('**/LegalIcon') mIcon = icons.find('**/MoneyIcon') sIcon = icons.find('**/SalesIcon') gIcon = icons.find('**/BoardIcon') cogInfoTextColor = (0.2, 0.2, 0.2, 1) textPos = (1.2, -0.2) textScale = 0.8 self.cInfo = DirectLabel(parent=self.cogInfoFrame, text='', text_fg=cogInfoTextColor, text_pos=textPos, text_scale=textScale, geom=cIcon, geom_pos=(0, 0, 0), geom_scale=0.6, relief=None) self.cInfo.setPos(-2.2, 0, 0.5) self.lInfo = DirectLabel(parent=self.cogInfoFrame, text_fg=cogInfoTextColor, text='', text_pos=textPos, text_scale=textScale, geom=lIcon, geom_pos=(0, 0, 0), geom_scale=0.6, relief=None) self.lInfo.setPos(-2.2, 0, -0.5) self.mInfo = DirectLabel(parent=self.cogInfoFrame, text_fg=cogInfoTextColor, text='', text_pos=textPos, text_scale=textScale, geom=mIcon, geom_pos=(0, 0, 0), geom_scale=0.6, relief=None) self.mInfo.setPos(0.8, 0, 0.5) self.sInfo = DirectLabel(parent=self.cogInfoFrame, text_fg=cogInfoTextColor, text='', text_pos=textPos, text_scale=textScale, geom=sIcon, geom_pos=(0, 0, 0), geom_scale=0.6, relief=None) self.sInfo.setPos(0.8, 0, -0.5) self.gInfo = DirectLabel(parent=self.cogInfoFrame, text_fg=cogInfoTextColor, text='', text_pos=textPos, text_scale=textScale, geom=gIcon, geom_pos=(0, 0, 0), geom_scale=0.6, relief=None) self.gInfo.setPos(3.2, 0, 0.5) icons.removeNode() return def updateCogInfo(self): currPercentage = self.suitPercentage.get(self.zoneId) if currPercentage is None: return self.cInfo['text'] = '%s%%' % currPercentage[0] self.lInfo['text'] = '%s%%' % currPercentage[1] self.mInfo['text'] = '%s%%' % currPercentage[2] self.sInfo['text'] = '%s%%' % currPercentage[3] self.gInfo['text'] = '%s%%' % currPercentage[4] return def destroy(self): self.ignore('questPageUpdated') self.mapOpenButton.destroy() self.mapCloseButton.destroy() del self.mapOpenButton del self.mapCloseButton DirectFrame.destroy(self) def putBuildingMarker(self, pos, hpr = (0, 0, 0), mapIndex = None, isSuitBlock=False): marker = DirectLabel(parent = self.container, text='', text_pos = (-0.05, -0.15), text_fg = (1, 1, 1, 1), relief = None) gui = loader.loadModel('phase_4/models/parties/schtickerbookHostingGUI') icon = gui.find('**/startPartyButton_inactive') iconNP = aspect2d.attachNewNode('iconNP') icon.reparentTo(iconNP) icon.setX(-12.0792 / 30.48) icon.setZ(-9.7404 / 30.48) marker['text'] = '%s' % mapIndex marker['text_scale'] = 0.7 marker['image'] = iconNP if isSuitBlock: # Make the bubble appear gray if a cog took over a task building marker['image_color'] = (0.5, 0.5, 0.5, 1) else: marker['image_color'] = (1, 0, 0, 1) marker['image_scale'] = 6 marker.setScale(0.05) relX, relY = self.transformAvPos(pos) marker.setPos(relX, 0, relY) self.buildingMarkers.append(marker) iconNP.removeNode() gui.removeNode() return def putSuitBuildingMarker(self, pos, hpr = (0, 0, 0), blockNumber = None, track = None): if base.localAvatar.buildingRadar[SuitDNA.suitDepts.index(track)]: marker = DirectLabel(parent = self.container, text = '', text_pos = (-0.05, -0.15), text_fg = (1, 1, 1, 1), relief = None) icon = self.getSuitIcon(track) iconNP = aspect2d.attachNewNode('suitBlock-%s' % blockNumber) icon.reparentTo(iconNP) marker['image'] = iconNP marker['image_scale'] = 1 marker.setScale(0.05) relX, relY = self.transformAvPos(pos) marker.setPos(relX, 0, relY) self.suitBuildingMarkers.append(marker) iconNP.removeNode() else: pass def putCogdoBuildingMarker(self, pos, hpr = (0, 0, 0), blockNumber = None, track = None): if base.localAvatar.buildingRadar[SuitDNA.suitDepts.index(track)]: marker = DirectLabel(parent = self.container, text = '', relief = None) marker['image'] = self.getCogdoIcon(track) marker['image_scale'] = .5 marker.setTransparency(1) marker.setScale(0.05) relX, relY = self.transformAvPos(pos) marker.setPos(relX, 0, relY) self.suitBuildingMarkers.append(marker) else: pass def getSuitIcon(self, dept): icons = loader.loadModel('phase_3/models/gui/cog_icons') if dept == 'c': corpIcon = icons.find('**/CorpIcon') elif dept == 's': corpIcon = icons.find('**/SalesIcon') elif dept == 'l': corpIcon = icons.find('**/LegalIcon') elif dept == 'm': corpIcon = icons.find('**/MoneyIcon') elif dept == 'g': corpIcon = icons.find('**/BoardIcon') else: corpIcon = None icons.removeNode() return corpIcon def getCogdoIcon(self, dept): if dept == 's': image = 'phase_3.5/maps/sbfo.png' if dept == 'l': image = 'phase_3.5/maps/lbfo.png' else: image = None return image def updateQuestInfo(self): for marker in self.buildingMarkers: marker.destroy() self.buildingMarkers = [] self.questBlocks = [] for (i, questDesc) in enumerate(self.av.quests): mapIndex = i + 1 quest = Quests.getQuest(questDesc[0]) toNpcId = questDesc[2] if quest is None: return completed = quest.getCompletionStatus(self.av, questDesc) == Quests.COMPLETE if not completed: if quest.getType() == Quests.RecoverItemQuest: if quest.getHolder() == Quests.AnyFish: self.putBuildingMarker(self.fishingSpotInfo, mapIndex=mapIndex) continue elif quest.getType() not in ( Quests.DeliverGagQuest, Quests.DeliverItemQuest, Quests.VisitQuest, Quests.TrackChoiceQuest): continue if toNpcId == Quests.ToonHQ: self.putBuildingMarker(self.hqPosInfo, mapIndex=mapIndex) continue npcZoneId = NPCToons.getNPCZone(toNpcId) hoodId = ZoneUtil.getCanonicalHoodId(npcZoneId) branchId = ZoneUtil.getCanonicalBranchZone(npcZoneId) if (self.hoodId != hoodId) or (self.zoneId != branchId): continue for blockIndex in xrange(base.cr.playGame.dnaStore.getNumBlockNumbers()): blockNumber = base.cr.playGame.dnaStore.getBlockNumberAt(blockIndex) zoneId = base.cr.playGame.dnaStore.getZoneFromBlockNumber(blockNumber) interiorZoneId = (zoneId - (zoneId%100)) + 500 + blockNumber if npcZoneId == interiorZoneId: self.questBlocks.append(blockNumber) self.putBuildingMarker( base.cr.playGame.dnaStore.getDoorPosHprFromBlockNumber(blockNumber).getPos(render), base.cr.playGame.dnaStore.getDoorPosHprFromBlockNumber(blockNumber).getHpr(render), mapIndex=mapIndex, isSuitBlock=base.cr.playGame.dnaStore.isSuitBlock(blockNumber)) continue for blockIndex in xrange(base.cr.playGame.dnaStore.getNumBlockNumbers()): blockNumber = base.cr.playGame.dnaStore.getBlockNumberAt(blockIndex) if base.cr.playGame.dnaStore.isSuitBlock(blockNumber) and blockNumber not in self.questBlocks: self.putSuitBuildingMarker( base.cr.playGame.dnaStore.getDoorPosHprFromBlockNumber(blockNumber).getPos(render), base.cr.playGame.dnaStore.getDoorPosHprFromBlockNumber(blockNumber).getHpr(render), blockNumber, base.cr.playGame.dnaStore.getSuitBlockTrack(blockNumber)) if base.cr.playGame.dnaStore.isCogdoBlock(blockNumber) and blockNumber not in self.questBlocks: self.putCogdoBuildingMarker( base.cr.playGame.dnaStore.getDoorPosHprFromBlockNumber(blockNumber).getPos(render), base.cr.playGame.dnaStore.getDoorPosHprFromBlockNumber(blockNumber).getHpr(render), blockNumber, base.cr.playGame.dnaStore.getCogdoBlockTrack(blockNumber)) continue def transformAvPos(self, pos): if self.cornerPosInfo is None: return (0, 0) topRight = self.cornerPosInfo[0] bottomLeft = self.cornerPosInfo[1] relativeX = (pos.getX() - bottomLeft.getX()) / (topRight.getX() - bottomLeft.getX()) - 0.5 relativeY = (pos.getY() - bottomLeft.getY()) / (topRight.getY() - bottomLeft.getY()) - 0.5 return (relativeX, relativeY) def update(self, task): if self.av: if self.updateMarker: relX, relY = self.transformAvPos(self.av.getPos()) self.marker.setPos(relX, 0, relY) self.marker.setHpr(0, 0, -180 - self.av.getH()) i = 0 for buildingMarker in self.buildingMarkers: if not buildingMarker.isEmpty(): buildingMarker.setScale((math.sin(task.time * 16.0 + i * math.pi / 3.0) + 1) * 0.005 + 0.04) i = i + 1 for buildingMarker in self.suitBuildingMarkers: if not buildingMarker.isEmpty(): buildingMarker.setScale((math.sin(task.time * 16.0 + i * math.pi / 3.0) + 1) * 0.005 + 0.04) i = i + 1 return Task.cont def updateMap(self): if self.av: hoodId = ZoneUtil.getCanonicalHoodId(self.av.getLocation()[1]) zoneId = ZoneUtil.getCanonicalBranchZone(self.av.getLocation()[1]) try: mapsGeom = loader.loadModel('phase_4/models/questmap/%s_maps' % ToontownGlobals.dnaMap[hoodId]) except: self.stop() return mapImage = mapsGeom.find('**/%s_%s_english' % (ToontownGlobals.dnaMap[hoodId], zoneId)) if not mapImage.isEmpty(): self.container['image'] = mapImage self.resetFrameSize() self.cornerPosInfo = QuestMapGlobals.CornerPosTable.get('%s_%s_english' % (ToontownGlobals.dnaMap[hoodId], zoneId)) self.hqPosInfo = QuestMapGlobals.HQPosTable.get('%s_%s_english' % (ToontownGlobals.dnaMap[hoodId], zoneId)) self.fishingSpotInfo = QuestMapGlobals.FishingSpotPosTable.get('%s_%s_english' % (ToontownGlobals.dnaMap[hoodId], zoneId)) self.cogInfoPos = QuestMapGlobals.CogInfoPosTable.get('%s_%s_english' % (ToontownGlobals.dnaMap[hoodId], zoneId)) self.cogInfoFrame.setPos(self.cogInfoPos) self.hide() self.hoodId = hoodId self.zoneId = zoneId self.updateQuestInfo() self.updateCogInfo() taskMgr.add(self.update, 'questMapUpdate') else: self.stop() mapsGeom.removeNode() def start(self): self.container.show() self.accept('questPageUpdated', self.updateMap) self.handleMarker() self.updateMap() def initMarker(self, task): if self.av: if not hasattr(base.cr.playGame.getPlace(), 'isInterior') or not base.cr.playGame.getPlace().isInterior: relX, relY = self.transformAvPos(self.av.getPos()) self.marker.setPos(relX, 0, relY) self.marker.setHpr(0, 0, -180 - self.av.getH()) self.marker['geom_scale'] = 1.4 * task.time % 0.5 * 10 + 1 self.marker['geom_color'] = (1, 1, 1, 0.8 - 1.4 * task.time % 0.5 * 2 / 0.8 + 0.2) if task.time < 1: return Task.cont else: self.marker['geom_color'] = (1, 1, 1, 0) return Task.done def show(self): taskMgr.add(self.initMarker, 'questMapInit') DirectFrame.show(self) self.mapOpenButton.hide() if self.container['image']: self.mapCloseButton.show() def hide(self): taskMgr.remove('questMapInit') DirectFrame.hide(self) if self.container['image']: self.mapOpenButton.show() self.mapCloseButton.hide() def toggle(self): if self.isHidden(): self.show() else: self.hide() def obscureButton(self): self.mapOpenButton.hide() self.mapCloseButton.hide() def stop(self): self.container['image'] = None for marker in self.buildingMarkers: marker.destroy() for marker in self.suitBuildingMarkers: marker.destroy() self.buildingMarkers = [] self.suitBuildingMarkers = [] self.questBlocks = [] self.container.hide() self.hide() self.obscureButton() self.ignore('questPageUpdated') taskMgr.remove('questMapUpdate') return def handleMarker(self): if hasattr(base.cr.playGame.getPlace(), 'isInterior') and base.cr.playGame.getPlace().isInterior: self.updateMarker = False else: self.updateMarker = True def acceptOnscreenHooks(self): if self.wantToggle: self.accept(ToontownGlobals.MapHotkey, self.toggle) else: self.accept(ToontownGlobals.MapHotkeyOn, self.show) self.accept(ToontownGlobals.MapHotkeyOff, self.hide) self.updateMap() def ignoreOnscreenHooks(self): self.ignore(ToontownGlobals.MapHotkey) self.ignore(ToontownGlobals.MapHotkeyOn) self.ignore(ToontownGlobals.MapHotkeyOff) self.obscureButton()
def createGui(self): base.cr.renderFrame() self.m = loader.loadFont("phase_3/models/fonts/MickeyFont.bam") self.bg = loader.loadModel( "phase_3/models/gui/tt_m_gui_pat_mainGui.bam") self.qtbtn = loader.loadModel("phase_3/models/gui/quit_button.bam") self.trash_gui = loader.loadModel( "phase_3/models/gui/trashcan_gui.bam") self.bg_img = OnscreenImage( image=self.bg.find('**/tt_t_gui_pat_background')) self.setTitle("Pick A Toon To Play") base.setBackgroundColor(self.BgColor) self.btn1 = DirectButton( geom=self.bg.find('**/tt_t_gui_pat_squareGreen'), relief=None, pos=(0.012, 0, 0.306), text_wordwrap=6, text_fg=(1, 1, 1, 1)) self.btn2 = DirectButton( geom=self.bg.find('**/tt_t_gui_pat_squarePink'), relief=None, pos=(0.01, 0, -0.515), text_wordwrap=6, text_fg=(1, 1, 1, 1)) self.btn3 = DirectButton( geom=self.bg.find('**/tt_t_gui_pat_squareRed'), relief=None, pos=(-0.84, 0, 0.36), text_wordwrap=6, text_fg=(1, 1, 1, 1)) self.btn4 = DirectButton( geom=self.bg.find('**/tt_t_gui_pat_squareYellow'), relief=None, pos=(0.865, 0, -0.45), text_wordwrap=6, text_fg=(1, 1, 1, 1)) self.btn5 = DirectButton( geom=self.bg.find('**/tt_t_gui_pat_squareBlue'), relief=None, pos=(-0.87, 0, -0.44), text_wordwrap=6, text_fg=(1, 1, 1, 1)) self.btn6 = DirectButton( geom=self.bg.find('**/tt_t_gui_pat_squarePurple'), relief=None, pos=(0.873, 0, 0.335), text_wordwrap=6, text_fg=(1, 1, 1, 1)) self.quit_btn = DirectButton(geom=(self.qtbtn.find('**/QuitBtn_RLVR'), self.qtbtn.find('**/QuitBtn_RLVR'), self.qtbtn.find('**/QuitBtn_RLVR')), relief=None, text="Quit", text_font=self.m, text_scale=0.105, text_pos=(0, -0.035), pos=(1.05, 0, -0.9), text_fg=(1, 0.9, 0.1, 1), geom1_scale=(1.02, 1, 1), geom2_scale=(1.02, 1, 1), command=self.quitGame) self.btnList = [] self.btnList.append(self.btn1) self.btnList.append(self.btn2) self.btnList.append(self.btn3) self.btnList.append(self.btn4) self.btnList.append(self.btn5) self.btnList.append(self.btn6) self.headList = [] #datafiler = open("toons/data.txt", "r") #if datafiler.read() == "-": # for btn in self.btnList: # btn['state'] = DGG.DISABLED # self.quit_btn['state'] = DGG.DISABLED # self.tutorial.askTutorial() # datafilew = open("toons/data.txt", "w") # datafilew.write("+") # datafilew.flush() # datafilew.close() #datafiler.close() for slot in range(6): if self.avChooser.hasToonInSlot(slot): notify.info("found existing Toon in slot %s" % (str(slot))) frame = DirectFrame(relief=None, parent=self.btnList[slot], pos=(0, 0, -0.1)) headframe = hidden.attachNewNode('head') headframe.setPosHprScale(0, 5, -0.1, 180, 0, 0, 0.24, 0.24, 0.24) headframe.reparentTo(self.btnList[slot].stateNodePath[0], 20) headframe.instanceTo(self.btnList[slot].stateNodePath[1], 20) headframe.instanceTo(self.btnList[slot].stateNodePath[2], 20) toon = ToonHead(base.cr) self.headList.append(toon) gender, animal, head, headcolor = self.avChooser.getHeadInfo( slot) toon.generateHead(gender, animal, head, 1) toon.getGeomNode().setDepthWrite(1) toon.getGeomNode().setDepthTest(1) toon.startBlink() toon.startLookAround() toon.reparentTo(headframe) toon.setHeadColor(headcolor) toon.flattenLight() name_lbl = DirectLabel(text=self.avChooser.getNameInSlot(slot), text_scale=0.08, text_fg=(1, 1, 1, 1), text_wordwrap=7, relief=None, text_shadow=(0, 0, 0, 1)) name_lbl.reparentTo(self.btnList[slot].stateNodePath[0], 20) name_lbl.instanceTo(self.btnList[slot].stateNodePath[1], 20) name_lbl.instanceTo(self.btnList[slot].stateNodePath[2], 20) name_lbl.setPos(self.name_pos[slot]) name_lbl.setHpr(self.name_hpr[slot]) self.btnList[slot]['text'] = ("", "Play This Toon", "Play This Toon", "") self.btnList[slot]['text_scale'] = 0.1 self.btnList[slot]['text_pos'] = (0, 0) self.btnList[slot]['text_fg'] = (1, 0.9, 0, 1) self.btnList[slot]['text_wordwrap'] = 6 self.btnList[slot]['text_font'] = self.m self.btnList[slot]['command'] = self.fadeMenu self.btnList[slot]['extraArgs'] = ["playGame", slot] delBtn = DirectButton( text=("", "Delete", "Delete", ""), text_scale=0.15, scale=0.5, text_pos=(0, -0.1), text_fg=(1, 1, 1, 1), relief=None, geom=(self.trash_gui.find('**/TrashCan_CLSD'), self.trash_gui.find('**/TrashCan_OPEN'), self.trash_gui.find('**/TrashCan_RLVR')), pos=self.trash_pos[slot], command=self.deleteToon, extraArgs=[ self.avChooser.getAvChoiceBySlot(slot).getAvId() ], text_shadow=(0, 0, 0, 1)) delBtn.reparentTo(self.btnList[slot].stateNodePath[0], 20) delBtn.instanceTo(self.btnList[slot].stateNodePath[1], 20) delBtn.instanceTo(self.btnList[slot].stateNodePath[2], 20) else: self.btnList[slot]['text'] = "Make A Toon" self.btnList[slot]['text_font'] = self.m self.btnList[slot]['text0_scale'] = 0.1 self.btnList[slot]['text1_scale'] = 0.12 self.btnList[slot]['text2_scale'] = 0.12 self.btnList[slot]['text3_scale'] = 0.1 self.btnList[slot]['text0_fg'] = (0, 1, 0.8, 0.5) self.btnList[slot]['text1_fg'] = (0, 1, 0.8, 1) self.btnList[slot]['text2_fg'] = (0.3, 1, 0.9, 1) self.btnList[slot]['text3_fg'] = (0, 1, 0.8, 0.5) self.btnList[slot]['text_font'] = self.m self.btnList[slot]['command'] = self.fadeMenu self.btnList[slot]['extraArgs'] = ["mat", slot] self.btnList[slot]['text_wordwrap'] = 6
class FileDialog(DirectObject): def __init__(self, title, initial_status, callback): self.frmLeft = -.7 self.frmBottom = -.12 self.frmRight = .7 self.frmTop = .12 self.frmWidth = self.frmRight - self.frmLeft self.frmHeight = self.frmTop - self.frmBottom self.title = title self.initial_status = initial_status self.callback = callback self.result = None self.done = 0 def activate(self): # create main dialog frame # Note: frame position references the CENTER of the frame self.frm = DirectFrame( pos = (0,0,0), frameSize = (self.frmLeft, self.frmRight,self.frmBottom, self.frmTop), relief = DGG.RIDGE, borderWidth = (0.01, 0.01), frameColor = (0.6, 0.6, 0.6, 1.0)) self.frm.reparentTo(base.aspect2d) # Note: wonderfully enough, label position on the other hand # references the CENTER of the LEFT border of the label! titleLabel = DirectLabel(text = self.title, scale = 0.04, frameColor = (0.5, 0.5, 0.5, 1), relief = DGG.RIDGE, borderWidth = (0.01, 0.01), text_align = TextNode.ALeft) titleLabel.setPos(-self.frmWidth/2+.02, 0, self.frmHeight/2-.045) titleLabel.reparentTo(self.frm) sc = .04 self.dir_edit_field = DirectEntry( text = '', # prompt text scale = sc, frameColor = (0.65, 0.65, 0.65, 1), command=self.setText, width = 32, numLines = 1, focus = 1, focusInCommand=self.efFocusIn, ) self.dir_edit_field.setPos(-self.frmWidth/2+.02, 0, self.frmHeight/2-.13) self.dir_edit_field.reparentTo(self.frm) self.statusLabel = DirectLabel(text = self.initial_status, scale = 0.04, frameColor = (0.6, 0.6, 0.6, 1), # relief = DGG.RIDGE, # borderWidth = (0.01, 0.01), text_align = TextNode.ALeft) self.statusLabel.setPos(-self.frmWidth/2+.02, 0, self.frmHeight/2-.2) self.statusLabel.reparentTo(self.frm) # call this if you need to run a form before your mainloop starts steppping the taskMgr def run(self): while self.done != 1: taskMgr.step() taskMgr.step() # once more to make the last output from the dialog visible # while we load a zone self.frm.removeNode() def end(self): self.frm.removeNode() # callback function to set text: called by the Panda3d taskMgr when the user # has entered something into the DirectEntry widget def setText(self, textEntered): print 'dir_edit_field::setText:', textEntered self.done = self.callback(textEntered) if self.done != 1: self.dir_edit_field['focus'] = 1 #clear the text def efFocusIn(self): print 'focus in' self.dir_edit_field.enterText('') def setStatus(self, status): self.statusLabel['text'] = status
class RepairGameButton(GuiButton): def __init__(self, parent, **kw): optiondefs = (('nodePath', None, None), ('image_scale', (1.0, 1.0, 1.0), None)) self.defineoptions(kw, optiondefs) GuiButton.__init__(self, parent) self.initialiseoptions(RepairGameButton) self.disabledStateNode = self.stateNodePath[3].getChild(0) self.downStateNode = self.stateNodePath[1].getChild(0) self.overStateNode = self.stateNodePath[2].getChild(0) self.inProgress = False self._initGUI() return def _initGUI(self): self.setBin('fixed', 33) mainGui = loader.loadModel('models/gui/gui_main') gui = loader.loadModel('models/gui/toplevel_gui') self.checkMark = gui.find('**/generic_check') self.checkMark.reparentTo(self) self.checkMark.stash() self.checkMark.setScale(1.0) self.checkMark.setColorScale(0.0, 1.0, 0.0, 1.0) self.checkMark.setPos(0.02, 0.0, 0.02) self.checkMark.setBin('fixed', 34) self.skillRing = DialMeter(self, wantCover=False, dangerRatio=0.0, meterColor=Vec4(0.9, 0.9, 0.1, 1.0), baseColor=Vec4(0.15, 0.07, 0.03, 1.0), completeColor=Vec4(0.1, 0.9, 0.1, 1.0)) self.skillRing.reparentTo(self) self.skillRing.setScale(0.285, 0.3, 0.265) self.skillRing.setBin('fixed', 32) self.skillGlow = self.glow = OnscreenImage( parent=self, image=mainGui.find('**/icon_glow'), scale=(1.0, 1.0, 1.0), color=(1.0, 1.0, 0.6, 1.0)) self.skillGlow.reparentTo(self) self.skillGlow.setBin('fixed', 31) self.skillGlow.stash() self.pirateNameBox = None self.pirateNameLabel = None return def showGlow(self): self.inProgress = False if self.pirateNameLabel == None and self.checkMark.isStashed(): self.skillGlow.unstash() return def hideGlow(self): self.inProgress = True self.skillGlow.stash() def setProgress(self, percent): self.skillGlow.stash() ratio = max(0.0, percent / 100.0) if ratio >= 1.0: if self.checkMark.isStashed(): self.checkMark.unstash() else: if not self.checkMark.isStashed(): self.checkMark.stash() if self.pirateNameLabel == None and not self.inProgress: self.skillGlow.unstash() self.skillRing.update(ratio, 1.0) self.skillRing.wrtReparentTo(self.getParent()) self.reparentTo(self.getParent()) def updatePirateNameBox(self, pirateName): if self.pirateNameLabel != None and self.pirateNameLabel[ 'text'] != pirateName: if self.pirateNameBox: self.pirateNameBox.destroy() if self.pirateNameLabel: self.pirateNameLabel.destroy() self.pirateNameBox = None self.pirateNameLabel = None if pirateName != '' and not (self.pirateNameBox and self.pirateNameLabel['text'] == pirateName): self.createPirateNameBox(pirateName) return def createPirateNameBox(self, pirateName): self.pirateNameLabel = DirectLabel( relief=None, state=DGG.DISABLED, text=pirateName, text_align=TextNode.ACenter, text_scale=PiratesGuiGlobals.TextScaleMed, text_fg=PiratesGuiGlobals.TextFG1, text_wordwrap=12, textMayChange=0, sortOrder=91) self.pirateNameLabel.setBin('fixed', 33) height = self.pirateNameLabel.getHeight() width = self.pirateNameLabel.getWidth() + 0.05 pos = [0.0, 0.0, height / 2 - 0.035] fs = [ -(width / 2 + 0.01), width / 2 + 0.01, -(height / 2 + 0.015), height / 2 + 0.015 ] self.pirateNameBox = BorderFrame(parent=self, state=DGG.DISABLED, frameSize=(fs[0], fs[1], fs[2], fs[3]), modelName='general_frame_f', pos=(0.0, 0.0, 0.0)) self.pirateNameLabel.reparentTo(self.pirateNameBox) self.pirateNameLabel.setPos(pos[0], pos[1], pos[2]) self.pirateNameBox.setClipPlaneOff() pos = self.pirateNameBox.getPos(aspect2d) x = min(pos[0], base.a2dRight - width) z = max(pos[2], base.a2dBottom - height) self.pirateNameBox.setPos(aspect2d, x, 0, z - 0.175) self.pirateNameBox.flattenLight() self.pirateNameBox.setBin('fixed', 32) self.pirateNameBox.reparentTo(self) return
class QuestPoster(DirectFrame): notify = directNotify.newCategory('QuestPoster') # We need to declare and initialize these variables here # because some methods use them as default arguments. auxIcon = None # Requires one parameter, quest, this must be a Quest instance. # The next argument, parent, is where to reparent the DirectFrame to. # The next arguments are simply additional options when setting up the DirectFrame. def __init__(self, quest, parent=aspect2d, **kw): # The quest this poster is representing. self.quest = quest # Let's define our options for the DirectFrame. bookModel = loader.loadModel( 'phase_3.5/models/gui/stickerbook_gui.bam') optiondefs = (('relief', None, None), ('image', bookModel.find('**/questCard'), None), ('image_scale', (0.8, 1.0, 0.58), None), ('state', DGG.NORMAL, None)) self.defineoptions(kw, optiondefs) # Finally, initialize the DirectFrame. DirectFrame.__init__(self, relief=None) self.initialiseoptions(QuestPoster) # Let's declare and initialize our barebone GUI element variables. self.titleLabel = DirectLabel(parent=self, relief=None, text=self.quest.getName(), text_font=CIGlobals.getMinnieFont(), text_fg=QuestGlobals.TEXT_COLOR, text_scale=0.05, text_align=TextNode.ACenter, text_wordwrap=25.0, textMayChange=1, pos=(0, 0, 0.23)) ########################################################################## # THE FOLLOWING ELEMENTS BELOW ARE GROUPED TOGETHER # ########################################################################## # The background frame where the objective image is displayed. # This is the colored background frame. self.auxFrame = DirectFrame( parent=self, relief=None, image=bookModel.find('**/questPictureFrame'), image_scale=QuestGlobals.IMAGE_SCALE_SMALL, text='', text_pos=(0, -0.11), text_fg=QuestGlobals.TEXT_COLOR, text_scale=QuestGlobals.QPtextScale, text_align=TextNode.ACenter, text_wordwrap=11.0, pos=QuestGlobals.DEFAULT_LEFT_PICTURE_POS) # The icon that goes on top of the aux frame. self.auxIcon = DirectFrame(parent=self.auxFrame, relief=None, text=' ', text_font=CIGlobals.getSuitFont(), text_pos=(0, -0.03), text_fg=QuestGlobals.TEXT_COLOR, text_scale=0.13, text_align=TextNode.ACenter, text_wordwrap=13.0, textMayChange=1) self.auxIcon.setColorOff(-1) # The aux text saying: DEFEAT, RECOVER, etc. self.auxText = DirectLabel(parent=self, relief=None, text=QuestGlobals.RECOVER, text_font=CIGlobals.getToonFont(), text_scale=QuestGlobals.QPauxText, text_fg=QuestGlobals.TEXT_COLOR, text_align=TextNode.ACenter, textMayChange=1, pos=QuestGlobals.DEFAULT_AUX_POS) self.auxText.hide() ########################################################################## # Information displayed about the objective. self.objectiveInfo = DirectLabel( parent=self, relief=None, text='', text_font=CIGlobals.getToonFont(), text_fg=QuestGlobals.TEXT_COLOR, text_scale=0.04, text_align=TextNode.ACenter, text_wordwrap=QuestGlobals.QPtextWordwrap, textMayChange=1, pos=(QuestGlobals.DEFAULT_INFO_POS)) self.objectiveInfo.hide() # Information displayed showing the location. self.locationInfo = DirectLabel( parent=self, relief=None, text='N/A', text_font=CIGlobals.getToonFont(), text_fg=QuestGlobals.TEXT_COLOR, text_scale=QuestGlobals.QPtextScale, text_align=TextNode.ACenter, text_wordwrap=QuestGlobals.QPtextWordwrap, textMayChange=1, pos=(0, 0, -0.115)) self.locationInfo.hide() # The progress bar showing the objective's progress self.progressBar = DirectWaitBar(parent=self, relief=DGG.SUNKEN, frameSize=(-0.95, 0.95, -0.1, 0.12), borderWidth=(0.025, 0.025), scale=0.2, frameColor=(0.945, 0.875, 0.706, 1.0), barColor=(0.5, 0.7, 0.5, 1), text='0/0', text_font=CIGlobals.getToonFont(), text_scale=0.19, text_fg=(0.05, 0.14, 0.4, 1), text_align=TextNode.ACenter, text_pos=(0, -0.05), pos=(0, 0, -0.2425)) self.progressBar.hide() # The wood panel at the bottom where rewards are displayed. rewardFrameGeom = loader.loadModel( 'phase_4/models/gui/gag_shop_purchase_gui.bam') self.rewardFrame = DirectFrame( parent=self, relief=None, geom=rewardFrameGeom.find('**/Goofys_Sign'), geom_scale=(0.615, 0, 0.4), pos=(-0.01, 0, -0.25)) # The text displayed on the right side of the frame with additional information, if necessary. self.sideInfo = DirectLabel(parent=self, relief=None, text=QuestGlobals.JUST_FOR_FUN, text_fg=(0.0, 0.439, 1.0, 1.0), text_shadow=(0, 0, 0, 1), pos=(-0.2825, 0, 0.2), scale=0.03) self.sideInfo.setR(-30) # This side information is usually not needed, let's hide it. self.sideInfo.hide() # Remove the nodes of the loaded models we no longer need. bookModel.removeNode() rewardFrameGeom.removeNode() # Let's hide this until it is needed. self.hide() return def setup(self): objective = self.quest.currentObjective objective.updateInfo() self.objectiveInfo.show() self.auxFrame.show() self.locationInfo['text'] = QuestGlobals.getLocationText( objective.location) self.locationInfo['text_pos'] = (0, 0 if not QuestGlobals.isShopLocation( objective.location) else 0.025) self.locationInfo.show() # Let's setup the quest progress bar progress = objective.amount if hasattr(objective, 'amount') else None if progress and objective.neededAmount > 0: self.progressBar['range'] = objective.getNeededAmount() self.progressBar['value'] = progress & pow(2, 16) - 1 if objective.__class__ in [ DeliverItemObjective, CogObjective, RecoverItemObjective ]: self.progressBar.show() self.auxText.show() # Let's handle the objectives. if objective.__class__ == CogObjective: self.handleCogObjective() elif objective.__class__ == VisitNPCObjective: self.handleNPCObjective() self.titleLabel.initialiseoptions(DirectLabel) self.auxIcon.initialiseoptions(DirectFrame) self.auxText.initialiseoptions(DirectLabel) self.objectiveInfo.initialiseoptions(DirectLabel) self.locationInfo.initialiseoptions(DirectLabel) self.rewardFrame.initialiseoptions(DirectFrame) self.sideInfo.initialiseoptions(DirectLabel) # Changes geometry and scale of an icon. def handleSimpleIcon(self, geom, scale, icon): icon['geom'] = geom icon['geom_scale'] = scale def handleComplexIcon(self, geom, icon, scale=QuestGlobals.IMAGE_SCALE_SMALL): isHead = True if type(geom) == ToonHead else geom.getName() == ( '%sHead' % CIGlobals.Suit) if isHead: geom.setDepthWrite(1) geom.setDepthTest(1) self.fitGeometry(geom, fFlip=1) self.handleSimpleIcon(geom, scale, icon) # We have to rotate the head and set the scale of the icon. if CIGlobals.Suit in geom.getName(): cogName = geom.getPythonTag('Settings') data = QuestGlobals.Suit2PosterZNDScale.get(cogName) zOffset = data[0] headScale = data[1] icon.setScale(headScale) icon.setZ(icon.getZ() + zOffset) geom.setH(180) else: raise ValueError( 'Tried to use #handleComplexIcon() on a non-complex icon. Use this method for 3D geometry.' ) def handleCogObjective(self, iconElement=auxIcon, auxText=QuestGlobals.DEFEAT, frameColor=QuestGlobals.BLUE): objective = self.quest.currentObjective infoText = objective.getTaskInfo(speech=False) if objective.__class__ == RecoverItemObjective: infoText = QuestGlobals.makePlural(objective.name) print 'Yep' if not iconElement: iconElement = self.auxIcon # Let's make sure we have a current objective that is # an instance of the CogObjective class and this poster isn't destroyed. if not objective or not hasattr(self, 'titleLabel') or not isinstance( objective, CogObjective): return if objective.dept: icons = loader.loadModel('phase_3/models/gui/cog_icons.bam') deptIcon = None if objective.dept == Dept.BOSS: deptIcon = icons.find('**/CorpIcon') else: deptIcon = icons.find('**/%sIcon' % objective.dept.getTie().title()) # Correct the medallion color. deptIcon.setColor(SuitGlobals.medallionColors[objective.dept]) # Setup the icon and remove the icons node. self.handleSimpleIcon(deptIcon, 0.13, iconElement) icons.removeNode() elif not objective.name: # We aren't fighting a Cog in particular. cogIcon = QuestGlobals.getCogIcon() self.handleSimpleIcon(cogIcon, cogIcon.getScale(), iconElement) # We're fighting a Cog in particular. if objective.name: cogHeadInstance = SuitBank.getSuitByName(objective.name).getHead() cogHead = cogHeadInstance.generate() cogHead.setName('%sHead' % CIGlobals.Suit) cogHead.setPythonTag('Settings', cogHeadInstance.head) cogHeadInstance.setScale(2) self.handleComplexIcon(cogHead, iconElement) if not iconElement is self.auxIcon: if hasattr(self, 'goalInfo'): # We're working with the second frame, on the right. # Let's update the information pertaining to this side. self.goalInfo['text'] = infoText self.goalInfo.setPos(QuestGlobals.RECOVER_INFO2_POS) self.auxText.setPos(QuestGlobals.RECOVER_AUX_POS) else: raise AttributeError( 'Attempted to setup DoubleFrame information for poster using default style.' ) else: self.objectiveInfo['text'] = infoText self.auxText['text'] = auxText # Let's set the progress bar text pgBarText = '%d of %d %s' % (objective.amount, objective.neededAmount, QuestGlobals.makePastTense(auxText)) self.progressBar['text'] = pgBarText # Let's set the color of the poster. frame = self.auxFrame if iconElement is self.auxIcon else self.goalFrame frame['image_color'] = Vec4(*frameColor) def handleNPCObjective(self, iconElement=auxIcon, auxText=QuestGlobals.VISIT, frameColor=QuestGlobals.BROWN): objective = self.quest.currentObjective infoText = CIGlobals.NPCToonNames[objective.npcId] if not iconElement: iconElement = self.auxIcon # Let's make sure we have a current objective that is # an instance of the CogObjective class and this poster isn't destroyed. if not objective or not hasattr(self, 'titleLabel') or not isinstance( objective, VisitNPCObjective): return # Let's generate the head. dna = ToonDNA() dna.setDNAStrand(CIGlobals.NPCToonDict.get(objective.npcId)[2]) head = ToonHead(base.cr) head.generateHead(dna.getGender(), dna.getAnimal(), dna.getHead(), forGui=1) head.setHeadColor(dna.getHeadColor()) self.handleComplexIcon(head, iconElement) self.auxText['text'] = auxText if not iconElement is self.auxIcon: if hasattr(self, 'goalInfo'): # We're working with the second frame, on the right. # Let's update the information pertaining to this side. self.goalInfo['text'] = infoText self.goalInfo.setPos(QuestGlobals.RECOVER_INFO2_POS) self.auxText.setPos(QuestGlobals.RECOVER_AUX_POS) self.goalFrame['image_color'] = frameColor else: raise AttributeError( 'Attempted to setup DoubleFrame information for poster using default style.' ) else: self.objectiveInfo['text'] = infoText self.auxFrame['image_color'] = frameColor def fitGeometry(self, geom, fFlip=0, dimension=0.8): p1 = Point3() p2 = Point3() geom.calcTightBounds(p1, p2) if fFlip: t = p1[0] p1.setX(-p2[0]) p2.setX(-t) d = p2 - p1 biggest = max(d[0], d[2]) s = dimension / biggest mid = (p1 + d / 2.0) * s geomXform = hidden.attachNewNode('geomXform') for child in geom.getChildren(): child.reparentTo(geomXform) geomXform.setPosHprScale(-mid[0], -mid[1] + 1, -mid[2], 180, 0, 0, s, s, s) geomXform.reparentTo(geom) def destroy(self): if hasattr(self, 'titleLabel'): self.titleLabel.destroy() self.auxFrame.destroy() self.auxIcon.destroy() self.auxText.destroy() self.objectiveInfo.destroy() self.locationInfo.destroy() self.progressBar.destroy() self.rewardFrame.destroy() self.sideInfo.destroy() del self.titleLabel del self.auxFrame del self.auxIcon del self.auxText del self.objectiveInfo del self.locationInfo del self.progressBar del self.rewardFrame del self.sideInfo DirectFrame.destroy(self) self.notify.debug('Destroyed all elements.')
class DirectSidebar(DirectFrame): def __init__( self, parent=None, frameSize=(1, 1), dragbarSize=0.05, align=ALIGN_LEFT|ALIGN_TOP, orientation=HORIZONTAL, opendir=RIGHT_OR_DOWN, pos=Vec3(0,0,0), text='', toggleFunc=None, frameColor=(1,1,1,1), ): if parent is None: parent=aspect2d self.dragbarSize=dragbarSize self.align=align self.orientation=orientation self.opendir=opendir self.pos=pos self.frameSize=frameSize self.toggleFunc=toggleFunc self.collapsed=False DirectFrame.__init__( self, parent=parent, frameSize=(0,frameSize[0],0,frameSize[1]), frameColor=frameColor, suppressMouse=1, ) self.initialiseoptions(DirectSidebar) self.resetFrameSize() self.collapseButton = DirectButton( parent=parent, borderWidth=(0, 0), relief=DGG.FLAT, command=self.toggleCollapsed, ) self.label = DirectLabel( parent=self.collapseButton, scale=0.04, text=text, text_align=TextNode.ACenter, frameColor=(0,0,0,0) ) if self.orientation == HORIZONTAL: self.label.setPos(Vec3(frameSize[0]/2.,0,0.015)) if self.orientation == VERTICAL: self.label.setPos(Vec3(0.035,0,frameSize[1]/2.)) self.label.setR(-90) self.accept('window-event', self.update) self.update() def destroy(self): self.label.detachNode() self.collapseButton.detachNode() self.detachNode() self.ignoreAll()#'window-event', self.update) def __del__(self): self.destroy() def update(self, args=None): aspectRatio=base.getAspectRatio() framePos=Vec3(self.pos[0],0,self.pos[2]) if self.align & ALIGN_LEFT: framePos+=Vec3(-aspectRatio,0,0) if self.align & ALIGN_RIGHT: framePos+=Vec3(aspectRatio,0,0) if self.align & ALIGN_TOP: framePos+=Vec3(0,0,1-self.frameSize[1]) if self.align & ALIGN_BOTTOM: framePos+=Vec3(0,0,-1) if self.orientation == HORIZONTAL: if self.align & ALIGN_RIGHT: # a small help for the user framePos-=Vec3(self.frameSize[0],0,0) buttonSize=(0,self.frameSize[0],0,self.dragbarSize) if self.opendir == RIGHT_OR_DOWN: # correct if self.collapsed: buttonPos=framePos+Vec3(0,0,self.frameSize[1]-self.dragbarSize) else: buttonPos=framePos+Vec3(0,0,-self.dragbarSize) elif self.opendir == LEFT_OR_UP: if self.collapsed: buttonPos=framePos else: buttonPos=framePos+Vec3(0,0,self.frameSize[1]) elif self.orientation == VERTICAL: buttonSize=(0,self.dragbarSize,0,self.frameSize[1]) if self.opendir == RIGHT_OR_DOWN: if self.collapsed: buttonPos=framePos else: buttonPos=framePos+Vec3(self.frameSize[0],0,0) elif self.opendir == LEFT_OR_UP: framePos-=Vec3(self.frameSize[0],0,0) # a small help for the user if self.collapsed: buttonPos=framePos+Vec3(self.frameSize[0]-self.dragbarSize,0,0) else: buttonPos=framePos if self.collapsed: self.hide() else: self.show() self.setPos(framePos) self.collapseButton.setPos(buttonPos) self.collapseButton['frameSize']=buttonSize def toggleCollapsed(self,state=None): if state is None: state=not self.collapsed self.collapsed=state if self.toggleFunc: try: self.toggleFunc(state) except: traceback.print_exc() self.update()
class SimpleInteractive(DirectObject): def __init__(self, object, name, proximityText): DirectObject.__init__(self) self.object = object self.proximityText = proximityText self.proximityEvent = name self.enterProximityEvent = 'enter' + name self.exitProximityEvent = 'exit' + name self.useLabel = None self.fader = None self.size = 6 self.disk = None proximitySphere = CollisionSphere(0, 0, 0, self.size) proximitySphere.setTangible(0) proximityNode = CollisionNode(self.proximityEvent) proximityNode.setIntoCollideMask(PiratesGlobals.WallBitmask) proximityNode.addSolid(proximitySphere) self.proximityNodePath = self.object.attachNewNode(proximityNode) self.accept(self.enterProximityEvent, self.approach) self.accept(self.exitProximityEvent, self.leave) def createInteractionDisk(self): self.disk = loader.loadModel('models/effects/selectionCursor') self.disk.setScale(self.size) self.disk.setColorScale(0, 1, 0, 1) self.disk.setP(-90) self.disk.setZ(0.025000000000000001) self.disk.setBillboardAxis(6) self.disk.reparentTo(self.object) self.disk.setBin('shadow', 0) self.disk.setTransparency(TransparencyAttrib.MAlpha) self.disk.setDepthWrite(0) self.disk.setDepthTest(0) def loadUseLabel(self, text): self.useLabel = DirectLabel(parent = aspect2d, frameColor = (0.10000000000000001, 0.10000000000000001, 0.25, 0.20000000000000001), text = text, text_align = TextNode.ACenter, text_scale = 0.059999999999999998, text_pos = (0.02, 0.02), text_fg = (1, 1, 1, 1), text_shadow = (0, 0, 0, 1), textMayChange = 1, text_font = PiratesGlobals.getPirateOutlineFont()) self.useLabel.setPos(0, 0, -0.69999999999999996) self.useLabel.setAlphaScale(0) self.useLabel.hide() def fadeInText(self): if self.fader: self.fader.pause() def interactionAllowed(self, avId): return True def approach(self, collEntry): if not self.interactionAllowed(localAvatar.doId): return None if not self.disk: self.createInteractionDisk() if self.proximityText: if not self.useLabel: self.loadUseLabel(self.proximityText) if self.fader: self.fader.pause() fadeIn = LerpFunctionInterval(self.useLabel.setAlphaScale, fromData = 0, toData = 1, duration = 0.5) self.fader = Sequence(Func(self.useLabel.show), fadeIn) self.fader.start() self.disk.show() self.accept(USE_KEY_EVENT, self.handleUseKey) def requestInteraction(self, avId): pass def handleUseKey(self): self.requestInteraction(localAvatar.doId) def leave(self, collEntry): if self.disk: self.disk.hide() if self.proximityText: if self.fader: self.fader.pause() self.fader = None if self.useLabel: self.useLabel.hide() self.ignore(USE_KEY_EVENT)
class ItemButton(DirectButton): def __init__(self, page, pos): DirectButton.__init__(self, parent=page, relief=None, command=self.handleClick, pos=pos) self.window = page self.item = None self.values = None self.label = DirectLabel(text='', relief=None, parent=self, text_scale=0.05) self.label.initialiseoptions(DirectLabel) self.label.hide() self.hide() def setItem(self, item, values): if values: image = values.get('image') price = values.get('price') text = '' self.item = item self.values = values self['geom'] = image if values.get('type') == ItemType.GAG: gagId = base.cr.attackMgr.getAttackIDByName(item) supply = base.localAvatar.getBackpack().getSupply(gagId) maxSupply = base.localAvatar.getBackpack().getMaxSupply(gagId) self.setScale(1.3) self.label['text_scale'] = 0.05 self.label.setPos(0, 0, -0.11) self.setTransparency(TransparencyAttrib.MNone) elif values.get('type') == ItemType.UPGRADE: upgradeID = values.get('upgradeID') avID = base.localAvatar.getPUInventory()[1] supply = 0 maxSupply = values.get('maxUpgrades') battle = base.localAvatar.getBattleZone() if battle and battle.getTurretManager(): turret = battle.getTurretManager().getTurret() if turret and turret.getGagID() == upgradeID: supply = 1 if avID == upgradeID: dataSupply = base.localAvatar.getPUInventory()[0] if dataSupply > 0: supply = dataSupply self.setScale(0.15) self.label['text_scale'] = 0.3 self.label.setPos(0, 0, -1.2) self.setTransparency(TransparencyAttrib.MNone) elif values.get('type') == ItemType.HEAL: text = '%s\n%s JBS' % ( item, price) if 'showTitle' in values else item self.setTransparency(TransparencyAttrib.MAlpha) self.setScale(0.105) self.label['text_scale'] = 0.55 self.label.setPos(0, 0, -1.6) text = text if text else '%s/%s\n%s JBS' % ( str(supply), str(maxSupply), str(price)) self.label['text'] = text self.label.initialiseoptions(DirectLabel) self.initialiseoptions(ItemButton) self.label.show() self.show() def update(self): money = base.localAvatar.getMoney() if self.values: itemType = self.values.get('type') price = self.values.get('price') self.setColorScale(NORMAL_COLOR) if price > money: self.setColorScale(GRAYED_OUT_COLOR) if itemType == ItemType.GAG: backpack = base.localAvatar.getBackpack() gagId = base.cr.attackMgr.getAttackIDByName(self.item) supply = backpack.getSupply(gagId) maxSupply = backpack.getMaxSupply(gagId) inBackpack = backpack.hasGag(gagId) if not inBackpack or inBackpack and supply >= maxSupply: self.setColorScale(GRAYED_OUT_COLOR) self.label['text'] = '%s/%s\n%s JBS' % ( str(supply), str(maxSupply), str(price)) elif itemType == ItemType.UPGRADE: maxSupply = self.values.get('maxUpgrades') upgradeID = self.values.get('upgradeID') avID = base.localAvatar.getPUInventory()[1] supply = 0 turretCount = 0 hasTurret = False battle = base.localAvatar.getBattleZone() if battle and battle.getTurretManager(): turretCount = battle.getTurretCount() turret = battle.getTurretManager().getTurret() if turret: hasTurret = True if turret.getGagID() == upgradeID: supply = 1 if avID == upgradeID: dataSupply = base.localAvatar.getPUInventory()[0] if dataSupply > 0: supply = dataSupply if supply > 0 or base.localAvatar.getPUInventory( )[0] > 0 or hasTurret or turretCount == CogBattleGlobals.MAX_TURRETS: self.setColorScale(GRAYED_OUT_COLOR) self.label['text'] = '%s\n%s/%s\n%s JBS' % ( self.item, str(supply), str(maxSupply), str(price)) elif itemType == ItemType.HEAL: if base.localAvatar.getHealth( ) == base.localAvatar.getMaxHealth() or self.shop.hasCooldown( self.item): self.setColorScale(GRAYED_OUT_COLOR) def handleClick(self): if self.item: self.window.shop.purchaseItem(self.item) def destroy(self): DirectFrame.destroy(self)
def _parseText(nodePath, parent): notify.debug('creating %s' % nodePath.getName()[len(TEXT_PREFIX) + 1:]) label = DirectLabel(parent = parent, relief = None, text = nodePath.getName()[len(TEXT_PREFIX) + 1:], text_align = TextNode.ACenter, text_scale = 0.10000000000000001, sortOrder = 50) label.setPos(nodePath.getPos() * SCALE_MULTIPLIER) return (nodePath.getName()[len(TEXT_PREFIX) + 1:], label)
class QuestMap(DirectFrame): def __init__(self, av, **kw): DirectFrame.__init__(self, relief=None, sortOrder=50) self.initialiseoptions(QuestMap) self.container = DirectFrame(parent=self, relief=None) self.marker = DirectFrame(parent=self.container, relief=None) self.cogInfoFrame = DirectFrame(parent=self.container, relief=None) cm = CardMaker('bg') cm.setFrame(-0.5, 0.5, -0.5, 0.5) bg = self.cogInfoFrame.attachNewNode(cm.generate()) bg.setTransparency(1) bg.setColor(0.5, 0.5, 0.5, 0.5) bg.setBin('fixed', 0) self.cogInfoFrame['geom'] = bg self.cogInfoFrame['geom_pos'] = (0, 0, 0) self.cogInfoFrame['geom_scale'] = (6, 1, 2) self.cogInfoFrame.setScale(0.05) self.cogInfoFrame.setPos(0, 0, 0.6) self.buildingMarkers = [] self.av = av self.wantToggle = False if ConfigVariableBool('want-toggle-quest-map', True).getValue(): self.wantToggle = True self.updateMarker = True self.cornerPosInfo = None self.hqPosInfo = None self.fishingSpotInfo = None self.load() self.setScale(1.5) bg.removeNode() self.hoodId = None self.zoneId = None self.suitPercentage = {} for currHoodInfo in SuitPlannerBase.SuitPlannerBase.SuitHoodInfo: tracks = currHoodInfo[ SuitPlannerBase.SuitPlannerBase.SUIT_HOOD_INFO_TRACK] self.suitPercentage[currHoodInfo[ SuitPlannerBase.SuitPlannerBase.SUIT_HOOD_INFO_ZONE]] = tracks def load(self): gui = loader.loadModel( 'phase_4/models/questmap/tt_m_gui_qst_questmap_gui') icon = gui.find('**/tt_t_gui_qst_arrow') iconNP = aspect2d.attachNewNode('iconNP') icon.reparentTo(iconNP) icon.setR(90) self.marker['geom'] = iconNP self.marker['image'] = iconNP self.marker.setScale(0.05) iconNP.removeNode() self.mapOpenButton = DirectButton( image=(gui.find('**/tt_t_gui_qst_mapClose'), gui.find('**/tt_t_gui_qst_mapClose'), gui.find('**/tt_t_gui_qst_mapTryToOpen')), relief=None, pos=(-0.084, 0, 0.37), parent=base.a2dBottomRight, scale=0.205, command=self.show, ) self.mapCloseButton = DirectButton( image=(gui.find('**/tt_t_gui_qst_mapOpen'), gui.find('**/tt_t_gui_qst_mapOpen'), gui.find('**/tt_t_gui_qst_mapTryToClose')), relief=None, pos=(-0.084, 0, 0.37), parent=base.a2dBottomRight, scale=0.205, command=self.hide, ) self.mapOpenButton.hide() self.mapCloseButton.hide() gui.removeNode() icons = loader.loadModel('phase_3/models/gui/cog_icons') cIcon = icons.find('**/CorpIcon') lIcon = icons.find('**/LegalIcon') mIcon = icons.find('**/MoneyIcon') sIcon = icons.find('**/SalesIcon') cogInfoTextColor = (0.2, 0.2, 0.2, 1) textPos = (1.2, -0.2) textScale = 0.8 self.cInfo = DirectLabel( parent=self.cogInfoFrame, text="", text_fg=cogInfoTextColor, text_pos=textPos, text_scale=textScale, geom=cIcon, geom_pos=(-0.2, 0, 0), geom_scale=0.8, relief=None, ) self.cInfo.setPos(-2.2, 0, 0.5) self.lInfo = DirectLabel( parent=self.cogInfoFrame, text_fg=cogInfoTextColor, text="", text_pos=textPos, text_scale=textScale, geom=lIcon, geom_pos=(-0.2, 0, 0), geom_scale=0.8, relief=None, ) self.lInfo.setPos(-2.2, 0, -0.5) self.mInfo = DirectLabel( parent=self.cogInfoFrame, text_fg=cogInfoTextColor, text="", text_pos=textPos, text_scale=textScale, geom=mIcon, geom_pos=(-0.2, 0, 0), geom_scale=0.8, relief=None, ) self.mInfo.setPos(0.8, 0, 0.5) self.sInfo = DirectLabel( parent=self.cogInfoFrame, text_fg=cogInfoTextColor, text="", text_pos=textPos, text_scale=textScale, geom=sIcon, geom_pos=(-0.2, 0, 0), geom_scale=0.8, relief=None, ) self.sInfo.setPos(0.8, 0, -0.5) icons.removeNode() def updateCogInfo(self): currPercentage = self.suitPercentage.get(self.zoneId) if currPercentage is None: return self.cInfo['text'] = '%s%%' % currPercentage[0] self.lInfo['text'] = '%s%%' % currPercentage[1] self.mInfo['text'] = '%s%%' % currPercentage[2] self.sInfo['text'] = '%s%%' % currPercentage[3] def destroy(self): self.ignore('questPageUpdated') self.mapOpenButton.destroy() self.mapCloseButton.destroy() del self.mapOpenButton del self.mapCloseButton DirectFrame.destroy(self) def putBuildingMarker(self, pos, hpr=(0, 0, 0), mapIndex=None): marker = DirectLabel(parent=self.container, text='', text_pos=(-0.05, -0.15), text_fg=(1, 1, 1, 1), relief=None) gui = loader.loadModel( 'phase_4/models/parties/schtickerbookHostingGUI') icon = gui.find('**/startPartyButton_inactive') iconNP = aspect2d.attachNewNode('iconNP') icon.reparentTo(iconNP) icon.setX(-12.0792 / 30.48) icon.setZ(-9.7404 / 30.48) marker['text'] = '%s' % mapIndex marker['text_scale'] = 0.7 marker['image'] = iconNP marker['image_color'] = (1, 0, 0, 1) marker['image_scale'] = 6 marker.setScale(0.05) relX, relY = self.transformAvPos(pos) marker.setPos(relX, 0, relY) self.buildingMarkers.append(marker) iconNP.removeNode() gui.removeNode() def updateQuestInfo(self): for marker in self.buildingMarkers: marker.destroy() self.buildingMarkers = [] dnaStore = base.cr.playGame.dnaStore for questIndex in self.av.questPage.quests.keys(): questDesc = self.av.questPage.quests.get(questIndex) if questDesc is None: continue mapIndex = questIndex + 1 questId, fromNpcId, toNpcId, rewardId, toonProgress = questDesc quest = Quests.getQuest(questId) fComplete = quest.getCompletionStatus(self.av, questDesc) == Quests.COMPLETE if not fComplete: if quest.getType() == Quests.RecoverItemQuest: if quest.getHolder() == Quests.AnyFish: self.putBuildingMarker(self.fishingSpotInfo, mapIndex=mapIndex) continue elif quest.getType( ) != Quests.DeliverGagQuest and quest.getType( ) != Quests.DeliverItemQuest and quest.getType( ) != Quests.VisitQuest and quest.getType( ) != Quests.TrackChoiceQuest: continue if toNpcId == Quests.ToonHQ: self.putBuildingMarker(self.hqPosInfo, mapIndex=mapIndex) else: npcZone = NPCToons.getNPCZone(toNpcId) hoodId = ZoneUtil.getCanonicalHoodId(npcZone) branchId = ZoneUtil.getCanonicalBranchZone(npcZone) if self.hoodId == hoodId and self.zoneId == branchId: for blockIndex in range(dnaStore.getNumBlockTitles()): blockNumber = dnaStore.getTitleBlockAt(blockIndex) zone = dnaStore.getZoneFromBlockNumber(blockNumber) branchZone = zone - zone % 100 finalZone = branchZone + 500 + blockNumber buildingType = dnaStore.getBlockBuildingType( blockNumber) if npcZone == finalZone: self.putBuildingMarker( dnaStore.getDoorPosHprFromBlockNumber( blockNumber).getPos(), dnaStore.getDoorPosHprFromBlockNumber( blockNumber).getHpr(), mapIndex=mapIndex) def transformAvPos(self, pos): if self.cornerPosInfo is None: return (0, 0) topRight = self.cornerPosInfo[0] bottomLeft = self.cornerPosInfo[1] relativeX = (pos.getX() - bottomLeft.getX()) / ( topRight.getX() - bottomLeft.getX()) - 0.5 relativeY = (pos.getY() - bottomLeft.getY()) / ( topRight.getY() - bottomLeft.getY()) - 0.5 return (relativeX, relativeY) def update(self, task): if self.av: if self.updateMarker: relX, relY = self.transformAvPos(self.av.getPos()) self.marker.setPos(relX, 0, relY) self.marker.setHpr(0, 0, -180 - self.av.getH()) i = 0 for buildingMarker in self.buildingMarkers: buildingMarker.setScale( (math.sin(task.time * 16.0 + i * math.pi / 3.0) + 1) * 0.005 + 0.04) i = i + 1 return Task.cont def updateMap(self): if self.av: try: hoodId = ZoneUtil.getCanonicalHoodId(self.av.getLocation()[1]) zoneId = ZoneUtil.getCanonicalBranchZone( self.av.getLocation()[1]) mapsGeom = loader.loadModel( 'phase_4/models/questmap/tt_m_gui_qst_%s_maps' % ToontownGlobals.dnaMap[hoodId]) mapImage = mapsGeom.find( '**/tt_t_gui_qst_%s_%s' % (ToontownGlobals.dnaMap[hoodId], zoneId)) if not mapImage.isEmpty(): self.container['image'] = mapImage self.resetFrameSize() self.cornerPosInfo = QuestMapGlobals.CornerPosTable.get( 'tt_t_gui_qst_%s_%s' % (ToontownGlobals.dnaMap[hoodId], zoneId)) self.hqPosInfo = QuestMapGlobals.HQPosTable.get( 'tt_t_gui_qst_%s_%s' % (ToontownGlobals.dnaMap[hoodId], zoneId)) self.fishingSpotInfo = QuestMapGlobals.FishingSpotPosTable.get( 'tt_t_gui_qst_%s_%s' % (ToontownGlobals.dnaMap[hoodId], zoneId)) self.cogInfoPos = QuestMapGlobals.CogInfoPosTable.get( 'tt_t_gui_qst_%s_%s' % (ToontownGlobals.dnaMap[hoodId], zoneId)) self.cogInfoFrame.setPos(self.cogInfoPos) self.hide() self.hoodId = hoodId self.zoneId = zoneId self.updateQuestInfo() self.updateCogInfo() taskMgr.add(self.update, 'questMapUpdate') else: self.stop() mapsGeom.removeNode() except: self.stop() def start(self): self.container.show() self.accept('questPageUpdated', self.updateMap) self.handleMarker() self.updateMap() def initMarker(self, task): if self.av: if not hasattr(base.cr.playGame.getPlace(), 'isInterior' ) or not base.cr.playGame.getPlace().isInterior: relX, relY = self.transformAvPos(self.av.getPos()) self.marker.setPos(relX, 0, relY) self.marker.setHpr(0, 0, -180 - self.av.getH()) self.marker['geom_scale'] = 1.4 * task.time % 0.5 * 10 + 1 self.marker['geom_color'] = (1, 1, 1, 0.8 - 1.4 * task.time % 0.5 * 2 / 0.8 + 0.2) if task.time < 1: return Task.cont else: self.marker['geom_color'] = (1, 1, 1, 0) return Task.done def show(self): taskMgr.add(self.initMarker, 'questMapInit') DirectFrame.show(self) self.mapOpenButton.hide() if self.container['image']: self.mapCloseButton.show() def hide(self): taskMgr.remove('questMapInit') DirectFrame.hide(self) if self.container['image']: self.mapOpenButton.show() self.mapCloseButton.hide() def toggle(self): if self.isHidden(): self.show() else: self.hide() def obscureButton(self): self.mapOpenButton.hide() self.mapCloseButton.hide() def stop(self): self.container['image'] = None for marker in self.buildingMarkers: marker.destroy() self.buildingMarkers = [] self.container.hide() self.hide() self.obscureButton() self.ignore('questPageUpdated') taskMgr.remove('questMapUpdate') def handleMarker(self): if hasattr(base.cr.playGame.getPlace(), 'isInterior') and base.cr.playGame.getPlace().isInterior: self.updateMarker = False else: self.updateMarker = True def acceptOnscreenHooks(self): if self.wantToggle: self.accept(ToontownGlobals.MapHotkey, self.toggle) else: self.accept(ToontownGlobals.MapHotkeyOn, self.show) self.accept(ToontownGlobals.MapHotkeyOff, self.hide) self.updateMap() def ignoreOnscreenHooks(self): self.ignore(ToontownGlobals.MapHotkey) self.ignore(ToontownGlobals.MapHotkeyOn) self.ignore(ToontownGlobals.MapHotkeyOff) self.obscureButton()
class FileDialog(DirectObject): def __init__(self, title, initial_status, callback): self.frmLeft = -.7 self.frmBottom = -.12 self.frmRight = .7 self.frmTop = .12 self.frmWidth = self.frmRight - self.frmLeft self.frmHeight = self.frmTop - self.frmBottom self.title = title self.initial_status = initial_status self.callback = callback self.result = None self.done = 0 def activate(self): # create main dialog frame # Note: frame position references the CENTER of the frame self.frm = DirectFrame( pos = (0,0,0), frameSize = (self.frmLeft, self.frmRight,self.frmBottom, self.frmTop), relief = DGG.RIDGE, borderWidth = (0.01, 0.01), frameColor = (0.6, 0.6, 0.6, 1.0)) self.frm.reparentTo(base.aspect2d) # Note: wonderfully enough, label position on the other hand # references the CENTER of the LEFT border of the label! titleLabel = DirectLabel(text = self.title, scale = 0.04, frameColor = (0.5, 0.5, 0.5, 1), relief = DGG.RIDGE, borderWidth = (0.01, 0.01), text_align = TextNode.ALeft) titleLabel.setPos(-self.frmWidth/2+.02, 0, self.frmHeight/2-.045) titleLabel.reparentTo(self.frm) sc = .04 self.dir_edit_field = DirectEntry( text = '', # prompt text scale = sc, frameColor = (0.65, 0.65, 0.65, 1), command=self.setText, width = 32, numLines = 1, focus = 1, focusInCommand=self.efFocusIn, ) self.dir_edit_field.setPos(-self.frmWidth/2+.02, 0, self.frmHeight/2-.13) self.dir_edit_field.reparentTo(self.frm) self.statusLabel = DirectLabel(text = self.initial_status, scale = 0.04, frameColor = (0.6, 0.6, 0.6, 1), # relief = DGG.RIDGE, # borderWidth = (0.01, 0.01), text_align = TextNode.ALeft) self.statusLabel.setPos(-self.frmWidth/2+.02, 0, self.frmHeight/2-.2) self.statusLabel.reparentTo(self.frm) # call this if you need to run a form before your mainloop starts steppping the taskMgr def run(self): while self.done != 1: taskMgr.step() taskMgr.step() # once more to make the last output from the dialog visible # while we load a zone self.frm.removeNode() def end(self): self.frm.removeNode() # callback function to set text: called by the Panda3d taskMgr when the user # has entered something into the DirectEntry widget def setText(self, textEntered): print 'dir_edit_field::setText:', textEntered self.done = self.callback(textEntered) if self.done != 1: self.dir_edit_field['focus'] = 1 #clear the text def efFocusIn(self): print 'focus in' self.dir_edit_field.enterText('') def setStatus(self, status): self.statusLabel['text'] = status
def _parseText(nodePath, parent): notify.debug('creating %s' % nodePath.getName()[len(TEXT_PREFIX) + 1:]) label = DirectLabel(parent=parent, relief=None, text=nodePath.getName()[len(TEXT_PREFIX) + 1:], text_align=TextNode.ACenter, text_scale=0.1, sortOrder=50) label.setPos(nodePath.getPos() * SCALE_MULTIPLIER) return ( nodePath.getName()[len(TEXT_PREFIX) + 1:], label)
class ZCanvas(object): """The singleton zcanvas represents the infinite and infinitely scalable zoomplane and manages the viewport through which the user sees the zoomplane (including zooming and panning the viewport). If you want to place an object on the zoom plane, you must attach it to the viewport node held by zcanvas. Messages sent by zcanvas (see messager.py to subscribe to these): 'new focus' -- viewport's focused znode has changed. arg: the newly focused znode. 'message started' -- a new text message is being displayed on the overlay. arg: a MessageStarted event object. 'message ended' -- a text message has finished being displayed on the overlay. arg: None. 'zooming to znode' -- the viewport has begun zooming to a znode. arg: the znode being zoomed to. 'zooming to zparent' -- the viewport has begun zooming back to a parent node of the previously focused node. arg: the znode being zoomed to, or None if the viewport is zooming back to its home position. 'zoom done' -- the viewport has finished zooming to a znode. arg: None. 'do drag' -- a drag signal has been received (zcanvas.drag was called). arg: the znode to be dragged. 'do drop' -- a drop signal has been received (zcanvas.drop was called). arg: the znode currently being dragged. """ def __init__(self): """Initialise the singleton zcanvas instance: setup the viewport node, the collision rays for mouse picking, and start the task method used for mouse picking, and other initialisation details. """ # This is the node that is transformed to implement viewport panning and # zooming. self.viewport = aspect2d.attachNewNode('zcanvas') # This is the node that user classes attach nodepaths to if they want # them to be on the zoom plane. self.home = self.viewport.attachNewNode('home') #self.home.showTightBounds() # This interval is used when the viewport is automatically transformed # to focus on a given nodepath, and also when the viewport is zoomed in # or out manually. self._zoomInterval = None # The time (in seconds) that it takes to move the viewport from the # minimum to the maximum position on the Y axis when manually zooming. # (Controls the speed when manually zooming the viewport.) self.zoom_time = 2 # Minimum and maximum positions for the viewport when manually moving on # the Y axis. FIXME: remove these arbitrary limits? self.max_zoom = 4.0 self.min_zoom = .1 # Interval used to manually pan the viewport left and right, and its # speed and minimum and maximum positions. self.pan_x_interval = None self.pan_x_time = 2 self.max_pan_x = 1.33 self.min_pan_x = -1.33 # Interval used to manually pan the viewport up and down, and its # speed and minimum and maximum positions. self.pan_z_interval = None self.pan_z_time = 2 self.max_pan_z = 1.0 self.min_pan_z = -1.0 # The zcanvas' collision ray, collision mask, etc. used for mouse # picking. cn = CollisionNode('zoom collision ray') cn.addSolid(CollisionRay(0,-100,0, 0,1,0)) from pandac.PandaModules import BitMask32 self.mask = BitMask32.bit(0) cn.setFromCollideMask(self.mask) cn.setIntoCollideMask(BitMask32.allOff()) self._cnp = aspect2d.attachNewNode(cn) self._ctrav=CollisionTraverser() self._queue = CollisionHandlerQueue() self._ctrav.addCollider(self._cnp, self._queue) # For debugging only. # self._ctrav.showCollisions(self.viewport) # Attributes that record which zoomable, draggable and highlightable # (if any) the mouse pointer is currently over. self._zoomMouseOver = None self._dragMouseOver = None self._highlightMouseOver = None # The draggable (if any) that is currently being dragged. self._draggee = None # Task method that does the mouse picking. taskMgr.add(self._mouseOverTask,'_mouseOverTask') # The currently focused node. A managed property. self.__focus = None # Catch the 'zoom done' message from panda's messenger system and echo # it to my custom messager system. (Because we use # interval.setDoneEvent to send the 'zoom done' message it must # initially be sent through panda's messenger). base.accept('zoom done',messager.send,['zoom done']) def getfocus(self): return self.__focus def setfocus(self,obj): self.__focus = obj messager.send('new focus',self.focus) # focus is a property whose set method ensures that observer's are notified # whenever it changes. focus = property(fget=getfocus, fset=setfocus, doc ="The viewport's currently focused object.") def message(self,text,duration=5): """Display a text message to the user for a given duration in seconds. """ # If we're already displaying a message, finish it early. if hasattr(self,'help'): self.help.detachNode() self.sequence.finish() # The new message. self.help = DirectLabel(text = text, text_scale=.1, text_fg=(.8,.8,.8,1), frameColor=(.2,.2,.2,0), frameVisibleScale=(1.2,1.2)) self.help.setPos(0,0,-.7) self.help.setAlphaScale(0) # At first the message is fully transparent. # This function is used to fade the message in and out. def fade(t): """Set the alpha of the message to t (multiplied by a constant factor).""" self.help.setAlphaScale(t*.9) self.help.setColor(.2,.2,.2,t*.7) # Create a sequence of intervals to fade in the message, wait for # `duration`, then fade it out. fade_in = LerpFunc(fade, fromData = 0, toData = 1, duration = .5, blendType = 'noBlend', extraArgs = [], name = None) fade_out = LerpFunc(fade, fromData = 1, toData = 0, duration = .5, blendType = 'noBlend', extraArgs = [], name = None) self.sequence = Sequence(fade_in,Wait(duration),fade_out) self.sequence.setDoneEvent('message ended') self.sequence.start() messager.send('message started',MessageStarted(text,duration)) def _mouseOverTask(self,t): """Move the CollisionRay to the position of the mouse pointer, check for collisions, and update various attributes related to what nodes the mouse is over. """ if not base.mouseWatcherNode.hasMouse(): # The mouse is outside of the window, do nothing. return Task.cont # Do the collision test. np = self._findCollision() # The zoomable, draggable, droppable and highlightable classes set # `self` as a python tag on the nodepaths that they wrap. We use these # tags to find out if np is below the nodepath of a zoomable, draggable, # droppable or highlightable in the scene graph. prevHighlightMouseOver = self._highlightMouseOver if self._draggee is not None: # Something is being dragged, so search for a droppable. if np is not None: # Find the nearest droppable that is an ancestor to np, if any. self._highlightMouseOver = np.getNetPythonTag('droppable') else: self._highlightMouseOver = None else: # Nothing is being dragged, so search for a zoomable, a draggable # and a highlightable. # FIXME: zoomable and draggable only really need to be searched for # when the zoom and drag buttons are clicked. if np is not None: # Find the nearest zoomable that is an ancestor of np, if any. self._zoomMouseOver = np.getNetPythonTag('zoomable') # Find the nearest draggable that is an ancestor to np, if any. self._dragMouseOver = np.getNetPythonTag('draggable') # Find the nearest highlightable that is an ancestor to np, if any. self._highlightMouseOver = np.getNetPythonTag('highlightable') else: self._zoomMouseOver = None self._dragMouseOver = None self._highlightMouseOver = None # Highlight and unhighlight nodes as necessary. if prevHighlightMouseOver != self._highlightMouseOver: if prevHighlightMouseOver is not None: prevHighlightMouseOver.unhighlight() if self._highlightMouseOver is not None: self._highlightMouseOver.highlight() return Task.cont def _findCollision(self): """Helper method for _mouseOverTask. Move the CollisionRay ray to be over the mouse pointer, run a collision test, and return the first nodepath that the ray collides with, or None if nothing is hit. Also return None if the mouse is over a DirectGUI object. returns -- NodePath or None. """ # If the mouse is over a DirectGUI object then zcanvas doesn't test # for collisions. (Leave it to DirectGUI to handle mouse-overs of # DirectGUI objects.) if base.mouseWatcherNode.isOverRegion(): return None # Move the CollisionRay's NodePath to where the mouse pointer is. mpos = base.mouseWatcherNode.getMouse() self._cnp.setPos(render2d,mpos[0],0,mpos[1]) # Run the collision test. self._ctrav.traverse(aspect2d) if self._queue.getNumEntries() == 0: # The ray didn't collide with anything. return None # FIXME: what we need to return here is the nodepath, of those in the # queue, that would be rendered last and appear on top of the others, # i.e. the one that is rightmost and lowest in the scene graph. If the # collision system walks the scene graph top-to-bottom and left-to-right # then that should be the last nodepath in the queue. For now, we guess # that that is correct. # # If this breaks down, we can try setting non-zero Y-values on the # nodepaths corresponding to their conceptual Y-order, and see if that # allows us to use queue.sort(), or if that doesn't work, introduce my # own Y-order attribute to my classes. np = self._queue.getEntry(self._queue.getNumEntries()-1).getIntoNodePath() return np def zoomTo(self): """ If the mouse pointer is over a zoomable and we are not already zooming, focus the viewport on the zoomable that the mouse pointer is over. """ if self.isZooming(): # If we are already in the process of zooming we don't want to # initiate another zoom. return elif self._zoomMouseOver is None: # The mouse pointer is not over any zoomable. return else: self._zoomToNodePath(self._zoomMouseOver.np) self.focus = self._zoomMouseOver messager.send('zooming to znode',self._zoomMouseOver) # Rename this to auto_zoom_out? def zoomToParent(self): """ If self.focus is not None and we are not already zooming, focus the viewport on the next zoomable above self.focus in the scene graph, or if there is no such zoomable, move the viewport to it's home position. """ if self.focus is not None and not self.isZooming(): p = self.focus.getParent().getNetPythonTag('zoomable') if p is None: self._zoomToNodePath(self.home) self.focus = None else: self._zoomToNodePath(p.np) self.focus = p messager.send('zooming to zparent',self.focus) def drag(self): """Begin dragging the draggable that is currently under the mouse pointer, if any.""" if self._dragMouseOver is not None: self._draggee = self._dragMouseOver self._dragMouseOver = None self._zoomMouseOver = None messager.send('do drag',self._draggee) self._draggee.drag() def drop(self): """Drop the node currently being dragged, if any.""" if self._draggee is not None: messager.send('do drop',self._draggee) self._draggee.drop() self._draggee = None # FIXME: this should be a module-level utility function somewhere, not an # instance method. def find_center(self,bottom_left,top_right): """Given two points bottom_left and top_right representing opposite corners of a rectangular region (e.g. a bounding box returned by NodePath.getTightBounds()), return a point representing the center of the rectangular region. returns : Point3 """ l = bottom_left.getX() b = bottom_left.getZ() r = top_right.getX() t = top_right.getZ() center_x = l + ((r-l)/2.0) center_z = b + ((t-b)/2.0) center = Point3(center_x,0,center_z) return center def _zoomToNodePath(self,np): """Create and start an interval that will move the viewport to focus on the nodepath np. """ # ynjh_jo's zoom code. posZoom=self.viewport.getRelativePoint(np.getParent(),self.find_center(*np.getTightBounds())) bounds3 = np.getTightBounds() oldScale = self.viewport.getScale() self.viewport.setScale(1,1,1) bounds = render2d.getRelativeVector(np.getParent(),bounds3[1]-bounds3[0]) self.viewport.setScale(oldScale) selfRatio = base.getAspectRatio()*bounds[0]/bounds[2] maxScale = 2./bounds[2*( selfRatio<base.getAspectRatio() )] zoomable = np.getPythonTag('zoomable') if zoomable is not None: maxScale *= zoomable.magnification else: maxScale *= 0.8 # Hard-coded magnification factor for home node. self.zoomInterval = self.viewport.posHprScaleInterval(.5, -posZoom*maxScale, self.viewport.getHpr(), Vec3(maxScale,1,maxScale) ) self.zoomInterval.setDoneEvent('zoom done') self.zoomInterval.start() def _zoomToHome(self): """Create and start an interval that will move the viewport back to its home position. """ # ynjh_jo's code again. self._zoomInterval = self.viewport.posHprScaleInterval( duration = .5, pos = Point3(0,0,0), hpr = self.viewport.getHpr(), scale = Vec3(1,1,1) ) self.zoomInterval.setDoneEvent('zoom done') self._zoomInterval.start() def isZooming(self): """Return True if the viewport is currently zooming in or out, False if it is not. """ if self._zoomInterval is None: return False elif self._zoomInterval.isPlaying(): return True else: return False # Methods for manual panning and zooming. # FIXME. This don't interact nicely with the automatic zooming above, and # they don't generate any events. def zoom_in(self): if self._zoomInterval is not None: if self._zoomInterval.isPlaying(): self._zoomInterval.pause() current_zoom = self.viewport.getScale().getY() duration = ((self.max_zoom-current_zoom)/self.max_zoom)*self.zoom_time self._zoomInterval = self.viewport.scaleInterval( duration=duration, scale=4, name = "zoom_in") self._zoomInterval.start() def zoom_out(self): if self._zoomInterval is not None: if self._zoomInterval.isPlaying(): self._zoomInterval.pause() current_zoom = self.viewport.getScale().getY() duration = ((current_zoom-self.min_zoom)/self.max_zoom)*self.zoom_time self._zoomInterval = self.viewport.scaleInterval( duration=.5, scale=.1, name = "zoom_out") self._zoomInterval.start() def stop_zoom_in(self): if self._zoomInterval is not None: if self._zoomInterval.isPlaying() and self._zoomInterval.getName() == "zoom_in": self._zoomInterval.pause() def stop_zoom_out(self): if self._zoomInterval is not None: if self._zoomInterval.isPlaying() and self._zoomInterval.getName() == "zoom_out": self._zoomInterval.pause() def pan_left(self): if self.pan_x_interval is not None: if self.pan_x_interval.isPlaying(): self.pan_x_interval.pause() current_pan = self.viewport.getPos().getX() duration = ((self.max_pan_x-current_pan)/self.max_pan_x)*self.pan_x_time self.pan_x_interval = self.viewport.posInterval( duration=duration, pos = Vec3(self.max_pan_x,self.viewport.getPos().getY(),self.viewport.getPos().getZ()), name = "pan_left") self.pan_x_interval.start() def pan_right(self): if self.pan_x_interval is not None: if self.pan_x_interval.isPlaying(): self.pan_x_interval.pause() current_pan = self.viewport.getPos().getX() duration = ((current_pan-self.min_pan_x)/self.max_pan_x)*self.pan_x_time self.pan_x_interval = self.viewport.posInterval( duration=duration, pos = Vec3(self.min_pan_x,self.viewport.getPos().getY(),self.viewport.getPos().getZ()), name = "pan_right") self.pan_x_interval.start() def stop_pan_left(self): if self.pan_x_interval is not None: if self.pan_x_interval.isPlaying() and self.pan_x_interval.getName() == "pan_left": self.pan_x_interval.pause() def stop_pan_right(self): if self.pan_x_interval is not None: if self.pan_x_interval.isPlaying() and self.pan_x_interval.getName() == "pan_right": self.pan_x_interval.pause() def pan_down(self): if self.pan_z_interval is not None: if self.pan_z_interval.isPlaying(): self.pan_z_interval.pause() current_pan = self.viewport.getPos().getZ() duration = ((self.max_pan_z-current_pan)/self.max_pan_z)*self.pan_z_time self.pan_z_interval = self.viewport.posInterval( duration=duration, pos = Vec3(self.viewport.getPos().getX(),self.viewport.getPos().getY(),self.max_pan_z), name = "pan_down") self.pan_z_interval.start() def pan_up(self): if self.pan_z_interval is not None: if self.pan_z_interval.isPlaying(): self.pan_z_interval.pause() current_pan = self.viewport.getPos().getZ() duration = ((current_pan-self.min_pan_z)/self.max_pan_z)*self.pan_z_time self.pan_z_interval = self.viewport.posInterval( duration=duration, pos = Vec3(self.viewport.getPos().getX(),self.viewport.getPos().getY(),self.min_pan_z), name = "pan_up") self.pan_z_interval.start() def stop_pan_up(self): if self.pan_z_interval is not None: if self.pan_z_interval.isPlaying() and self.pan_z_interval.getName() == "pan_up": self.pan_z_interval.pause() def stop_pan_down(self): if self.pan_z_interval is not None: if self.pan_z_interval.isPlaying() and self.pan_z_interval.getName() == "pan_down": self.pan_z_interval.pause()
class SimpleInteractive(DirectObject): __module__ = __name__ def __init__(self, object, name, proximityText): DirectObject.__init__(self) self.object = object self.proximityText = proximityText self.proximityEvent = name self.enterProximityEvent = 'enter' + name self.exitProximityEvent = 'exit' + name self.useLabel = None self.fader = None self.size = 6 self.disk = None proximitySphere = CollisionSphere(0, 0, 0, self.size) proximitySphere.setTangible(0) proximityNode = CollisionNode(self.proximityEvent) proximityNode.setIntoCollideMask(PiratesGlobals.WallBitmask) proximityNode.addSolid(proximitySphere) self.proximityNodePath = self.object.attachNewNode(proximityNode) self.accept(self.enterProximityEvent, self.approach) self.accept(self.exitProximityEvent, self.leave) return def createInteractionDisk(self): self.disk = loader.loadModel('models/effects/selectionCursor') self.disk.setScale(self.size) self.disk.setColorScale(0, 1, 0, 1) self.disk.setP(-90) self.disk.setZ(0.025) self.disk.setBillboardAxis(6) self.disk.reparentTo(self.object) self.disk.setBin('shadow', 0) self.disk.setTransparency(TransparencyAttrib.MAlpha) self.disk.setDepthWrite(0) self.disk.setDepthTest(0) def loadUseLabel(self, text): self.useLabel = DirectLabel( parent=aspect2d, frameColor=(0.1, 0.1, 0.25, 0.2), text=text, text_align=TextNode.ACenter, text_scale=0.06, text_pos=(0.02, 0.02), text_fg=(1, 1, 1, 1), text_shadow=(0, 0, 0, 1), textMayChange=1, text_font=PiratesGlobals.getPirateOutlineFont()) self.useLabel.setPos(0, 0, -0.7) self.useLabel.setAlphaScale(0) self.useLabel.hide() def fadeInText(self): if self.fader: self.fader.pause() def interactionAllowed(self, avId): return True def approach(self, collEntry): if not self.interactionAllowed(localAvatar.doId): return if not self.disk: self.createInteractionDisk() if self.proximityText: if not self.useLabel: self.loadUseLabel(self.proximityText) if self.fader: self.fader.pause() fadeIn = LerpFunctionInterval(self.useLabel.setAlphaScale, fromData=0, toData=1, duration=0.5) self.fader = Sequence(Func(self.useLabel.show), fadeIn) self.fader.start() self.disk.show() self.accept(USE_KEY_EVENT, self.handleUseKey) def requestInteraction(self, avId): pass def handleUseKey(self): self.requestInteraction(localAvatar.doId) def leave(self, collEntry): if self.disk: self.disk.hide() if self.proximityText: if self.fader: self.fader.pause() self.fader = None if self.useLabel: self.useLabel.hide() self.ignore(USE_KEY_EVENT) return
class QuestMap(DirectFrame): def __init__(self, av, **kw): DirectFrame.__init__(self, relief=None, sortOrder=50) self.initialiseoptions(QuestMap) self.container = DirectFrame(parent=self, relief=None) self.marker = DirectFrame(parent=self.container, relief=None) self.cogInfoFrame = DirectFrame(parent=self.container, relief=None) cm = CardMaker('bg') cm.setFrame(-0.5, 0.5, -0.5, 0.5) bg = self.cogInfoFrame.attachNewNode(cm.generate()) bg.setTransparency(1) bg.setColor(0.5, 0.5, 0.5, 0.5) bg.setBin('fixed', 0) self.cogInfoFrame['geom'] = bg self.cogInfoFrame['geom_pos'] = (0, 0, 0) self.cogInfoFrame['geom_scale'] = (6, 1, 2) self.cogInfoFrame.setScale(0.05) self.cogInfoFrame.setPos(0, 0, 0.6) self.buildingMarkers = [] self.av = av self.wantToggle = False if base.config.GetBool('want-toggle-quest-map', True): self.wantToggle = True self.updateMarker = True self.cornerPosInfo = None self.hqPosInfo = None self.fishingSpotInfo = None self.load() self.setScale(1.5) bg.removeNode() self.hoodId = None self.zoneId = None self.suitPercentage = {} for currHoodInfo in SuitPlannerBase.SuitPlannerBase.SuitHoodInfo: tracks = currHoodInfo[SuitPlannerBase.SuitPlannerBase.SUIT_HOOD_INFO_TRACK] self.suitPercentage[currHoodInfo[SuitPlannerBase.SuitPlannerBase.SUIT_HOOD_INFO_ZONE]] = tracks return def load(self): gui = loader.loadModel('phase_4/models/questmap/questmap_gui') icon = gui.find('**/tt_t_gui_qst_arrow') iconNP = aspect2d.attachNewNode('iconNP') icon.reparentTo(iconNP) icon.setR(90) self.marker['geom'] = iconNP self.marker['image'] = iconNP self.marker.setScale(0.05) iconNP.removeNode() self.mapOpenButton = DirectButton(image=(gui.find('**/tt_t_gui_qst_mapClose'), gui.find('**/tt_t_gui_qst_mapClose'), gui.find('**/tt_t_gui_qst_mapTryToOpen')), relief=None, pos=(-0.08, 0, 0.37), parent=base.a2dBottomRight, scale=0.205, command=self.show) self.mapCloseButton = DirectButton(image=(gui.find('**/tt_t_gui_qst_mapOpen'), gui.find('**/tt_t_gui_qst_mapOpen'), gui.find('**/tt_t_gui_qst_mapTryToClose')), relief=None, pos=(-0.08, 0, 0.37), parent=base.a2dBottomRight, scale=0.205, command=self.hide) self.mapOpenButton.hide() self.mapCloseButton.hide() gui.removeNode() icons = loader.loadModel('phase_3/models/gui/cog_icons') cIcon = icons.find('**/CorpIcon') lIcon = icons.find('**/LegalIcon') mIcon = icons.find('**/MoneyIcon') sIcon = icons.find('**/SalesIcon') cogInfoTextColor = (0.2, 0.2, 0.2, 1) textPos = (1.2, -0.2) textScale = 0.8 self.cInfo = DirectLabel(parent=self.cogInfoFrame, text='', text_fg=cogInfoTextColor, text_pos=textPos, text_scale=textScale, geom=cIcon, geom_pos=(-0.2, 0, 0), geom_scale=0.8, relief=None) self.cInfo.setPos(-2.2, 0, 0.5) self.lInfo = DirectLabel(parent=self.cogInfoFrame, text_fg=cogInfoTextColor, text='', text_pos=textPos, text_scale=textScale, geom=lIcon, geom_pos=(-0.2, 0, 0), geom_scale=0.8, relief=None) self.lInfo.setPos(-2.2, 0, -0.5) self.mInfo = DirectLabel(parent=self.cogInfoFrame, text_fg=cogInfoTextColor, text='', text_pos=textPos, text_scale=textScale, geom=mIcon, geom_pos=(-0.2, 0, 0), geom_scale=0.8, relief=None) self.mInfo.setPos(0.8, 0, 0.5) self.sInfo = DirectLabel(parent=self.cogInfoFrame, text_fg=cogInfoTextColor, text='', text_pos=textPos, text_scale=textScale, geom=sIcon, geom_pos=(-0.2, 0, 0), geom_scale=0.8, relief=None) self.sInfo.setPos(0.8, 0, -0.5) icons.removeNode() return def updateCogInfo(self): currPercentage = self.suitPercentage.get(self.zoneId) if currPercentage is None: return self.cInfo['text'] = '%s%%' % currPercentage[0] self.lInfo['text'] = '%s%%' % currPercentage[1] self.mInfo['text'] = '%s%%' % currPercentage[2] self.sInfo['text'] = '%s%%' % currPercentage[3] return def destroy(self): self.ignore('questPageUpdated') self.mapOpenButton.destroy() self.mapCloseButton.destroy() del self.mapOpenButton del self.mapCloseButton DirectFrame.destroy(self) def putBuildingMarker(self, pos, hpr = (0, 0, 0), mapIndex = None): marker = DirectLabel(parent=self.container, text='', text_pos=(-0.05, -0.15), text_fg=(1, 1, 1, 1), relief=None) gui = loader.loadModel('phase_4/models/parties/schtickerbookHostingGUI') icon = gui.find('**/startPartyButton_inactive') iconNP = aspect2d.attachNewNode('iconNP') icon.reparentTo(iconNP) icon.setX(-12.0792 / 30.48) icon.setZ(-9.7404 / 30.48) marker['text'] = '%s' % mapIndex marker['text_scale'] = 0.7 marker['image'] = iconNP marker['image_color'] = (1, 0, 0, 1) marker['image_scale'] = 6 marker.setScale(0.05) relX, relY = self.transformAvPos(pos) marker.setPos(relX, 0, relY) self.buildingMarkers.append(marker) iconNP.removeNode() gui.removeNode() return def updateQuestInfo(self): for marker in self.buildingMarkers: marker.destroy() self.buildingMarkers = [] for (i, questDesc) in enumerate(self.av.quests): mapIndex = i + 1 quest = Quests.getQuest(questDesc[0]) toNpcId = questDesc[2] completed = quest.getCompletionStatus(self.av, questDesc) == Quests.COMPLETE if not completed: if quest.getType() == Quests.RecoverItemQuest: if quest.getHolder() == Quests.AnyFish: self.putBuildingMarker(self.fishingSpotInfo, mapIndex=mapIndex) continue elif quest.getType() not in ( Quests.DeliverGagQuest, Quests.DeliverItemQuest, Quests.VisitQuest, Quests.TrackChoiceQuest): continue if toNpcId == Quests.ToonHQ: self.putBuildingMarker(self.hqPosInfo, mapIndex=mapIndex) continue npcZoneId = NPCToons.getNPCZone(toNpcId) hoodId = ZoneUtil.getCanonicalHoodId(npcZoneId) branchId = ZoneUtil.getCanonicalBranchZone(npcZoneId) if (self.hoodId != hoodId) or (self.zoneId != branchId): continue for blockIndex in xrange(base.cr.playGame.dnaStore.getNumBlockNumbers()): blockNumber = base.cr.playGame.dnaStore.getBlockNumberAt(blockIndex) zoneId = base.cr.playGame.dnaStore.getZoneFromBlockNumber(blockNumber) interiorZoneId = (zoneId - (zoneId%100)) + 500 + blockNumber if npcZoneId == interiorZoneId: self.putBuildingMarker( base.cr.playGame.dnaStore.getDoorPosHprFromBlockNumber(blockNumber).getPos(render), base.cr.playGame.dnaStore.getDoorPosHprFromBlockNumber(blockNumber).getHpr(render), mapIndex=mapIndex) def transformAvPos(self, pos): if self.cornerPosInfo is None: return (0, 0) topRight = self.cornerPosInfo[0] bottomLeft = self.cornerPosInfo[1] relativeX = (pos.getX() - bottomLeft.getX()) / (topRight.getX() - bottomLeft.getX()) - 0.5 relativeY = (pos.getY() - bottomLeft.getY()) / (topRight.getY() - bottomLeft.getY()) - 0.5 return (relativeX, relativeY) def update(self, task): if self.av: if self.updateMarker: relX, relY = self.transformAvPos(self.av.getPos()) self.marker.setPos(relX, 0, relY) self.marker.setHpr(0, 0, -180 - self.av.getH()) i = 0 for buildingMarker in self.buildingMarkers: buildingMarker.setScale((math.sin(task.time * 16.0 + i * math.pi / 3.0) + 1) * 0.005 + 0.04) i = i + 1 return Task.cont def updateMap(self): if self.av: hoodId = ZoneUtil.getCanonicalHoodId(self.av.getLocation()[1]) zoneId = ZoneUtil.getCanonicalBranchZone(self.av.getLocation()[1]) try: mapsGeom = loader.loadModel('phase_4/models/questmap/%s_maps' % ToontownGlobals.dnaMap[hoodId]) except: self.stop() return mapImage = mapsGeom.find('**/%s_%s_english' % (ToontownGlobals.dnaMap[hoodId], zoneId)) if not mapImage.isEmpty(): self.container['image'] = mapImage self.resetFrameSize() self.cornerPosInfo = QuestMapGlobals.CornerPosTable.get('%s_%s_english' % (ToontownGlobals.dnaMap[hoodId], zoneId)) self.hqPosInfo = QuestMapGlobals.HQPosTable.get('%s_%s_english' % (ToontownGlobals.dnaMap[hoodId], zoneId)) self.fishingSpotInfo = QuestMapGlobals.FishingSpotPosTable.get('%s_%s_english' % (ToontownGlobals.dnaMap[hoodId], zoneId)) self.cogInfoPos = QuestMapGlobals.CogInfoPosTable.get('%s_%s_english' % (ToontownGlobals.dnaMap[hoodId], zoneId)) self.cogInfoFrame.setPos(self.cogInfoPos) self.hide() self.hoodId = hoodId self.zoneId = zoneId self.updateQuestInfo() self.updateCogInfo() taskMgr.add(self.update, 'questMapUpdate') else: self.stop() mapsGeom.removeNode() def start(self): self.container.show() self.accept('questPageUpdated', self.updateMap) self.handleMarker() self.updateMap() def initMarker(self, task): if self.av: if not hasattr(base.cr.playGame.getPlace(), 'isInterior') or not base.cr.playGame.getPlace().isInterior: relX, relY = self.transformAvPos(self.av.getPos()) self.marker.setPos(relX, 0, relY) self.marker.setHpr(0, 0, -180 - self.av.getH()) self.marker['geom_scale'] = 1.4 * task.time % 0.5 * 10 + 1 self.marker['geom_color'] = (1, 1, 1, 0.8 - 1.4 * task.time % 0.5 * 2 / 0.8 + 0.2) if task.time < 1: return Task.cont else: self.marker['geom_color'] = (1, 1, 1, 0) return Task.done def show(self): taskMgr.add(self.initMarker, 'questMapInit') DirectFrame.show(self) self.mapOpenButton.hide() if self.container['image']: self.mapCloseButton.show() def hide(self): taskMgr.remove('questMapInit') DirectFrame.hide(self) if self.container['image']: self.mapOpenButton.show() self.mapCloseButton.hide() def toggle(self): if self.isHidden(): self.show() else: self.hide() def obscureButton(self): self.mapOpenButton.hide() self.mapCloseButton.hide() def stop(self): self.container['image'] = None for marker in self.buildingMarkers: marker.destroy() self.buildingMarkers = [] self.container.hide() self.hide() self.obscureButton() self.ignore('questPageUpdated') taskMgr.remove('questMapUpdate') return def handleMarker(self): if hasattr(base.cr.playGame.getPlace(), 'isInterior') and base.cr.playGame.getPlace().isInterior: self.updateMarker = False else: self.updateMarker = True def acceptOnscreenHooks(self): if self.wantToggle: self.accept(ToontownGlobals.MapHotkey, self.toggle) else: self.accept(ToontownGlobals.MapHotkeyOn, self.show) self.accept(ToontownGlobals.MapHotkeyOff, self.hide) self.updateMap() def ignoreOnscreenHooks(self): self.ignore(ToontownGlobals.MapHotkey) self.ignore(ToontownGlobals.MapHotkeyOn) self.ignore(ToontownGlobals.MapHotkeyOff) self.obscureButton()
class CharityScreen(DistributedObject): notify = directNotify.newCategory('CharityScreen') def __init__(self, cr): DistributedObject.__init__(self, cr) self.zone2pos = { ToontownGlobals.ToontownCentral: (40, 0, 25), ToontownGlobals.DonaldsDock: (-25, 17, 25), ToontownGlobals.DaisyGardens: (5, 137, 25), ToontownGlobals.MinniesMelodyland: (0, 0, 8), ToontownGlobals.TheBrrrgh: (-111, -44, 25), ToontownGlobals.DonaldsDreamland: (0, 0, 6) } self.bob = None self.screenObject = None self.counter = None def announceGenerate(self): self.cr.chairityEvent = self def start(self, zoneId): threading.Thread(target=taskMgr.add, args=(self.setCount, 'countTask')).start() def startScreen(*args): self.screenObject = args[0] if not self.screenObject: return self.screenObject.reparentTo(render) text = '' # "Welcome to PRE-BETA!\nPlease note that there are bugs.\nReport them to the devs!" if ZoneUtil.getHoodId(zoneId) == ToontownGlobals.MinniesMelodyland: self.screenObject.reparentTo( self.cr.playGame.getPlace().loader.geom.find( '**/center_icon')) self.screenObject.setPos( self.zone2pos.get(ZoneUtil.getHoodId(zoneId), (0, 0, 6))) self.screenObject.setHpr(-90, 0, 0) self.counter = DirectLabel( parent=render, pos=(0, 0, 0), relief=None, text=text, text_scale=1, text_fg=(1, 1, 1, 1), text_align=TextNode.ACenter, text_font=ToontownGlobals.getMinnieFont()) self.counter.reparentTo(self.screenObject) self.counter.setPos( self.screenObject.find("**/front_screen").getPos() + Point3(0.0, -1.5, 0.3)) self.counterback = DirectLabel( parent=render, pos=(0, 0, 0), relief=None, text=text, text_scale=1, text_fg=(1, 1, 1, 1), text_align=TextNode.ACenter, text_font=ToontownGlobals.getMinnieFont()) self.counterback.reparentTo(self.screenObject) self.counterback.setPos( self.screenObject.find("**/back_screen").getPos() + Point3(0.0, 1.5, 0.3)) self.counterback.setHpr(180, 0, 0) self.bob = Sequence( LerpPosInterval(nodePath=self.screenObject, duration=3.2, pos=(self.screenObject.getX(), self.screenObject.getY(), self.screenObject.getZ() + 1.65), blendType='easeInOut'), Sequence( Wait(0.050), LerpPosInterval(nodePath=self.screenObject, duration=3.0, pos=(self.screenObject.getX(), self.screenObject.getY(), self.screenObject.getZ()), blendType='easeInOut'), Sequence(Wait(0.050)))) self.bob.loop() asyncloader.loadModel( "phase_3.5/models/events/charity/flying_screen.bam", callback=startScreen) def setCount(self, task): self.count = base.localAvatar.getStat(ToontownGlobals.STATS_COGS) cash = self.count / 1000.0 cash = '{:,.2f}'.format(cash) if self.counter and self.counterback: self.counter['text'] = ( str(self.count) + "\nCogs Destroyed\nYou've earned %s USD\nfor the Extra Life Charity!" ) % cash self.counterback['text'] = ( str(self.count) + "\nCogs Destroyed\nYou've earned %s USD\nfor the Extra Life Charity!" ) % cash taskMgr.doMethodLater(10, self.setCount, 'countTask') def unload(self): self.notify.debug("Unloading Charity Screen!") self.ignoreAll() if self.bob: self.bob.finish() self.bob = None if self.screenObject: self.screenObject.removeNode() self.screenObject = None def delete(self): self.cr.chairityEvent = None self.notify.debug("Deleting Charity Screen!") taskMgr.remove('countTask') if self.bob: self.bob.finish() self.bob = None if self.screenObject: self.screenObject.removeNode() self.screenObject = None