def generate(self, gender, head, headtype, color, doId, name, valueLabel = 1): gui = loader.loadModel("phase_3/models/gui/pick_a_toon_gui.bam") bg = gui.find('**/av-chooser_Square_UP') container = DirectFrame(relief=None, scale=0.3, parent=base.a2dTopLeft) container['image'] = bg container['image_color'] = self.frameColors[len(self.frameList)] container.setBin('gui-popup', 60) container.setPos(self.framePositions[len(self.frameList)]) headframe = container.attachNewNode('head') headframe.setPosHprScale(0, 5, -0.1, 180, 0, 0, 0.24, 0.24, 0.24) toon = ToonHead(None) toon.generateHead(gender, head, headtype) r, g, b = color color = (r, g, b, 1.0) toon.setHeadColor(color) toon.setDepthWrite(1) toon.setDepthTest(1) toon.reparentTo(headframe) nameLbl = DirectLabel(text=name, text_wordwrap=7.0, parent=container, text_scale=0.13, text_fg=(1,1,1,1), text_shadow=(0,0,0,1), relief=None, pos=(0, 0, 0.25)) if valueLabel: someValueToBroadcast = DirectLabel(text="0", parent=container, text_scale=0.15, text_fg=(1,1,1,1), text_shadow=(0,0,0,1), relief=None, pos=(0.26, 0, -0.28)) self.frameList.append(container) if valueLabel: self.doId2Frame[doId] = tuple((container, headframe, toon, nameLbl, someValueToBroadcast)) else: self.doId2Frame[doId] = tuple((container, headframe, toon, nameLbl))
def __init__(self): ShowBase.__init__(self) # Load the environment model. self.environ = self.loader.loadModel("models/environment") # Reparent the model to render. self.environ.reparentTo(self.render) # Apply scale and position transforms on the model. self.environ.setScale(0.25, 0.25, 0.25) self.environ.setPos(-8, 42, 0) # Add the spinCameraTask procedure to the task manager. self.taskMgr.add(self.spinCameraTask, "SpinCameraTask") # Load and transform the panda actor. self.pandaActor = Actor("models/panda-model", {"walk": "models/panda-walk4"}) self.pandaActor.setScale(0.005, 0.005, 0.005) self.pandaActor.reparentTo(self.render) # Loop its animation. self.pandaActor.loop("walk") myFrame = DirectFrame(frameColor=(0, 0, 0, 1), frameSize=(-1, 1, -1, 1)) myFrame.setPos(-0.5, 0, -0.5)
def generateOtherPlayerGui(self): for avId in self.doId2Frame.keys(): self.avId2otherPlayerAvIds2otherPlayerHeadsFrame[avId] = {} headNumber = -1 frame = self.doId2Frame[avId][0] otherPlayerHeadsFrame = DirectFrame(relief=None, scale=0.85, parent=frame) otherPlayerHeadsFrame['image'] = frame['image'] otherPlayerHeadsFrame['image_color'] = frame['image_color'] otherPlayerHeadsFrame[ 'image_scale'] = self.otherPlayerHeadHolderTransforms['scale'] otherPlayerHeadsFrame.setPos( self.otherPlayerHeadHolderTransforms['pos']) otherPlayerHeadsFrame.setBin('gui-popup', 70) self.frameList.append(otherPlayerHeadsFrame) for otherAvId in self.doId2Frame.keys(): if otherAvId != avId: headNumber += 1 otherAv = base.cr.doId2do.get(otherAvId) headFrame = otherPlayerHeadsFrame.attachNewNode( 'otherPlayerHeadFrame') headFrame.setPosHprScale( self.otherPlayerHeadXValues[headNumber], 5, -0.1, 180, 0, 0, 0.2, 0.2, 0.2) headFrame.setColorScale(self.state2Color[0]) head = ToonGlobals.generateGuiHead(otherAv) head.reparentTo(headFrame) self.avId2otherPlayerAvIds2otherPlayerHeadsFrame[avId][ otherAvId] = headFrame
def __init__(self): ShowBase.__init__(self) # Load the environment model. self.environ = self.loader.loadModel("models/environment") # Reparent the model to render. self.environ.reparentTo(self.render) # Apply scale and position transforms on the model. self.environ.setScale(0.25, 0.25, 0.25) self.environ.setPos(-8, 42, 0) # Add the spinCameraTask procedure to the task manager. self.taskMgr.add(self.spinCameraTask, "SpinCameraTask") # Load and transform the panda actor. self.pandaActor = Actor("models/panda-model", {"walk": "models/panda-walk4"}) self.pandaActor.setScale(0.005, 0.005, 0.005) self.pandaActor.reparentTo(self.render) # Loop its animation. self.pandaActor.loop("walk") myFrame = DirectFrame(frameColor=(0, 0, 0, 1), frameSize=(-1, 1, -1, 1)) myFrame.setPos(-0.5, 0, -0.5)
class Layout(object): def __init__(self, width, height, parent=None, frameColor=(1, 1, 1, 1), frameSize=(0, 0.5, -0.5, 0)): self.width = width self.height = height if parent is None: parent = aspect2d self.parent = parent self.frame = DirectFrame(parent=parent, frameColor=frameColor, frameSize=frameSize, state=DGG.DISABLED) self.frame.setPos(0, 0, 0) self.children = [[None for y in range(self.height)] for x in range(self.width)] self.children_width = [[0.0 for y in range(self.height)] for x in range(self.width)] self.children_height = [[0.0 for y in range(self.height)] for x in range(self.width)] def set_child(self, x, y, child): if x >= self.width or y >= self.height: return child.reparent_to(self.frame) self.children[x][y] = child bounds = child.getBounds() if bounds is not None: width = bounds[1] - bounds[0] height = bounds[3] - bounds[2] self.children_width[x][y] = width self.children_height[x][y] = height else: self.children_width[x][y] = 0 self.children_height[x][y] = 0 def recalc_positions(self): max_widths = [] for x in range(self.width): max_width = 0.0 for y in range(self.height): max_width = max(max_width, self.children_width[x][y]) max_widths.append(max_width) max_heights = [] for y in range(self.height): max_height = 0.0 for x in range(self.width): max_height = max(max_height, self.children_height[x][y]) max_heights.append(max_height) pos_x = 0.0 for x in range(self.width): pos_y = 0.0 for y in range(self.height): pos_y -= max_heights[y] child = self.children[x][y] if child is not None: child.setPos(pos_x, 0, pos_y) pos_x += max_widths[x] self.frame['frameSize']= [0, pos_x, 0, pos_y] def destroy(self): self.frame.destroy() def reparent_to(self, parent): self.frame.reparent_to(parent)
def generateOtherPlayerGui(self): for avId in self.doId2Frame.keys(): self.avId2otherPlayerAvIds2otherPlayerHeadsFrame[avId] = {} headNumber = -1 frame = self.doId2Frame[avId][0] otherPlayerHeadsFrame = DirectFrame(relief=None, scale=0.85, parent=frame) otherPlayerHeadsFrame['image'] = frame['image'] otherPlayerHeadsFrame['image_color'] = frame['image_color'] otherPlayerHeadsFrame[ 'image_scale'] = self.otherPlayerHeadHolderTransforms['scale'] otherPlayerHeadsFrame.setPos( self.otherPlayerHeadHolderTransforms['pos']) otherPlayerHeadsFrame.setBin('gui-popup', 70) self.frameList.append(otherPlayerHeadsFrame) for otherAvId in self.doId2Frame.keys(): if otherAvId != avId: headNumber += 1 otherAv = base.cr.doId2do.get(otherAvId) gender = otherAv.getGender() head, color = otherAv.getHeadStyle() animal = otherAv.getAnimal() headFrame = otherPlayerHeadsFrame.attachNewNode( 'otherPlayerHeadFrame') headFrame.setPosHprScale( self.otherPlayerHeadXValues[headNumber], 5, -0.1, 180, 0, 0, 0.2, 0.2, 0.2) headFrame.setColorScale(self.state2Color[0]) toon = ToonHead(None) toon.generateHead(gender, animal, head) r, g, b, _ = color color = (r, g, b, 1.0) toon.setHeadColor(color) toon.setDepthWrite(1) toon.setDepthTest(1) toon.reparentTo(headFrame) self.avId2otherPlayerAvIds2otherPlayerHeadsFrame[avId][ otherAvId] = headFrame
def generate(self, gender, head, headtype, color, doId, name, valueLabel = 1): gui = loader.loadModel('phase_3/models/gui/pick_a_toon_gui.bam') bg = gui.find('**/av-chooser_Square_UP') container = DirectFrame(relief=None, scale=0.3, parent=base.a2dTopLeft) container['image'] = bg container['image_color'] = self.frameColors[len(self.frameList)] container.setBin('gui-popup', 60) container.setPos(self.framePositions[len(self.frameList)]) headframe = container.attachNewNode('head') headframe.setPosHprScale(0, 5, -0.1, 180, 0, 0, 0.24, 0.24, 0.24) toon = ToonHead(None) toon.generateHead(gender, head, headtype) r, g, b = color color = (r, g, b, 1.0) toon.setHeadColor(color) toon.setDepthWrite(1) toon.setDepthTest(1) toon.reparentTo(headframe) nameLbl = DirectLabel(text=name, text_wordwrap=7.0, parent=container, text_scale=0.13, text_fg=(1, 1, 1, 1), text_shadow=(0, 0, 0, 1), relief=None, pos=(0, 0, 0.25)) if valueLabel: someValueToBroadcast = DirectLabel(text='0', parent=container, text_scale=0.15, text_fg=(1, 1, 1, 1), text_shadow=(0, 0, 0, 1), relief=None, pos=(0.26, 0, -0.28)) self.frameList.append(container) if valueLabel: self.doId2Frame[doId] = tuple((container, headframe, toon, nameLbl, someValueToBroadcast)) else: self.doId2Frame[doId] = tuple((container, headframe, toon, nameLbl)) return
def generateOtherPlayerGui(self): for avId in self.doId2Frame.keys(): self.avId2otherPlayerAvIds2otherPlayerHeadsFrame[avId] = {} headNumber = -1 frame = self.doId2Frame[avId][0] otherPlayerHeadsFrame = DirectFrame(relief=None, scale=0.85, parent=frame) otherPlayerHeadsFrame['image'] = frame['image'] otherPlayerHeadsFrame['image_color'] = frame['image_color'] otherPlayerHeadsFrame['image_scale'] = self.otherPlayerHeadHolderTransforms['scale'] otherPlayerHeadsFrame.setPos(self.otherPlayerHeadHolderTransforms['pos']) otherPlayerHeadsFrame.setBin('gui-popup', 70) self.frameList.append(otherPlayerHeadsFrame) for otherAvId in self.doId2Frame.keys(): if otherAvId != avId: headNumber += 1 otherAv = base.cr.doId2do.get(otherAvId) gender = otherAv.getGender() head, color = otherAv.getHeadStyle() animal = otherAv.getAnimal() headFrame = otherPlayerHeadsFrame.attachNewNode('otherPlayerHeadFrame') headFrame.setPosHprScale(self.otherPlayerHeadXValues[headNumber], 5, -0.1, 180, 0, 0, 0.2, 0.2, 0.2) headFrame.setColorScale(self.state2Color[0]) toon = ToonHead(None) toon.generateHead(gender, animal, head) r, g, b, _ = color color = (r, g, b, 1.0) toon.setHeadColor(color) toon.setDepthWrite(1) toon.setDepthTest(1) toon.reparentTo(headFrame) self.avId2otherPlayerAvIds2otherPlayerHeadsFrame[avId][otherAvId] = headFrame return
class MainMenu(): def __init__(self): print("MainMenu object created") self.bk_text = "This is my Demo" self.textObject = OnscreenText(text=self.bk_text, pos=(0.95, -0.95), scale=0.07, fg=(1, 0.5, 0.5, 1), align=TextNode.ACenter, mayChange=1) self.f = DirectFrame(frameColor=(1, 0, 0, 1), frameSize=(-1, 1, -1, 1)) self.f.setPos(-0.5, 0, -0.5) self.t = DirectLabel(self.f, text="Glorious title", scale=0.1, pos=(0, 0, 0.9)) self.b = DirectButton(self.f, text=("Exit", "click!", "rolling over", "disabled"), scale=.15, pos=(0, 0, 0.1), text_scale=0.5, command=self.setText) self.ttb = DirectButton(self.f, text=("Terrain Test"), scale=.15, pos=(0, 0, 0.2), text_scale=0.5, command=self.request_state, extraArgs=["TerrainTest"]) self.ccb = DirectButton(self.f, text=("CharGen Test"), scale=.15, pos=(0, 0, 0.3), text_scale=0.5, command=self.request_state, extraArgs=["CharGen"]) self.nt = DirectButton(self.f, text=("Network Test"), scale=.15, pos=(0, 0, 0.4), text_scale=0.5, command=self.request_state, extraArgs=["NetworkTest"]) #self.nt def setText(self): self.bk_text = "Button Clicked" self.textObject.setText(self.bk_text) self.f.destroy() Globals.game_states.request("None") sys.exit() def request_state(self, name): self.f.destroy() self.textObject.destroy() #Globals.game_states.request("TerrainTest") Globals.game_states.request(name)
class Menu(UIItem): def __init__(self, list=[]): self.__menuContainer = DirectFrame( #text_pos=(0,1), pos=(0, 0, 0), text_scale=1.5, text_fg=(0, 0, 0, 0), relief=DGG.FLAT, frameColor=(1, 1, 1, 0.5)) self.__menuContainer.hide() self.__menuItems = [] self.selectedItem = 0 self.addItems(list) def addItem(self, text, action): self.__menuItems.append( DirectButton( text=text, command=self.pressEnter, extraArgs=[len(self.__menuItems)], text_align=TextNode.ALeft, scale=0.1, #left/right, forward/back, up/down pos=Vec3(-0.38, 0, 0.5 - (len(self.__menuItems) * 0.15)), text_fg=(1, 1, 1, 1), rolloverSound=None, clickSound=None, pressEffect=0, relief=None, textMayChange=True #text_font=base.fontLoader.load('Arial Bold.ttf') )) self.__menuItems[-1].reparentTo(self.__menuContainer) self.__menuItems[-1].setPythonTag('action', action) self.__menuItems[-1].setPythonTag('text', text) def addItems(self, list): for k, v in list: self.addItem(k, v) def hasItem(self, text): for i in self.__menuItems: if (i['text'] == text): return True return False def __del__(self): self.ignoreAll() def pressEnter(self, item=None): if (item != None): self.selectedItem = item logging.info("pressEnter:: selectedItem = %s" % str(self.selectedItem)) action = self.__menuItems[self.selectedItem].getPythonTag('action') text = self.__menuItems[self.selectedItem].getPythonTag('text') logging.info("pressEnter:: action = %s" % str(action)) if (action != None): #function #self.hide() action(text) #call the function in 'action' def enter(self): """ Press the enter key to select the current menu item. """ self.pressEnter() UIItem.enter(self) def up(self): """Move one item up in the menu.""" newItem = self.selectedItem - 1 if (newItem < 0): newItem = len(self.__menuItems) - 1 self.select(newItem) UIItem.up(self) def down(self): """Move one item down in the menu.""" newItem = self.selectedItem + 1 if (newItem >= len(self.__menuItems)): newItem = 0 self.select(newItem) UIItem.down(self) def select(self, item): self.__menuItems[self.selectedItem]['text_fg'] = (1, 1, 1, 1) self.__menuItems[self.selectedItem]['text_bg'] = (0, 0, 0, 0) self.selectedItem = item self.__menuItems[self.selectedItem]['text_fg'] = (0, 0, 0.5, 1) self.__menuItems[self.selectedItem]['text_bg'] = (1, 1, 1, 1) def show(self): assert len(self.__menuItems) > 0 self.select(0) #make the first item selected if (self.__menuContainer.isHidden()): Sequence( Func(self.__menuContainer.setAlphaScale, 0.0), Func(self.__menuContainer.show), LerpFunctionInterval(self.__menuContainer.setAlphaScale, toData=1.0, fromData=0.0, duration=1.0)).start() def hide(self): self.ignoreAll() if (not self.__menuContainer.isHidden()): Sequence( LerpFunctionInterval(self.__menuContainer.setAlphaScale, toData=0.0, fromData=1.0, duration=1.0), Func(self.__menuContainer.hide), Func(self.__menuContainer.setAlphaScale, 1.0)).start() #now, hide all dialogs referred to: for i in self.__menuItems: a = i.getPythonTag('action') if (isinstance(a, Menu)): a.hide() def setParent(self, parent): self.__menuContainer.reparentTo(parent) def setPos(self, x, y, z): self.__menuContainer.setPos(x, y, z)
class QuestMap(DirectFrame): def __init__(self, av, **kw): DirectFrame.__init__(self, relief=None, sortOrder=50) self.initialiseoptions(QuestMap) self.container = DirectFrame(parent=self, relief=None) self.marker = DirectFrame(parent=self.container, relief=None) self.cogInfoFrame = DirectFrame(parent=self.container, relief=None) cm = CardMaker('bg') cm.setFrame(-0.5, 0.5, -0.5, 0.5) bg = self.cogInfoFrame.attachNewNode(cm.generate()) bg.setTransparency(1) bg.setColor(0.5, 0.5, 0.5, 0.5) bg.setBin('fixed', 0) self.cogInfoFrame['geom'] = bg self.cogInfoFrame['geom_pos'] = (0, 0, 0) self.cogInfoFrame['geom_scale'] = (6, 1, 2) self.cogInfoFrame.setScale(0.05) self.cogInfoFrame.setPos(0, 0, 0.6) self.buildingMarkers = [] self.av = av self.wantToggle = False if base.config.GetBool('want-toggle-quest-map', True): self.wantToggle = True self.updateMarker = True self.cornerPosInfo = None self.hqPosInfo = None self.fishingSpotInfo = None self.load() self.setScale(1.5) bg.removeNode() self.hoodId = None self.zoneId = None self.suitPercentage = {} for currHoodInfo in SuitPlannerBase.SuitPlannerBase.SuitHoodInfo: tracks = currHoodInfo[ SuitPlannerBase.SuitPlannerBase.SUIT_HOOD_INFO_TRACK] self.suitPercentage[currHoodInfo[ SuitPlannerBase.SuitPlannerBase.SUIT_HOOD_INFO_ZONE]] = tracks return def load(self): gui = loader.loadModel('phase_4/models/questmap/questmap_gui') icon = gui.find('**/tt_t_gui_qst_arrow') iconNP = aspect2d.attachNewNode('iconNP') icon.reparentTo(iconNP) icon.setR(90) self.marker['geom'] = iconNP self.marker['image'] = iconNP self.marker.setScale(0.05) iconNP.removeNode() self.mapOpenButton = DirectButton( image=(gui.find('**/tt_t_gui_qst_mapClose'), gui.find('**/tt_t_gui_qst_mapClose'), gui.find('**/tt_t_gui_qst_mapTryToOpen')), relief=None, pos=(-0.084, 0, 0.37), parent=base.a2dBottomRight, scale=0.205, command=self.show) self.mapCloseButton = DirectButton( image=(gui.find('**/tt_t_gui_qst_mapOpen'), gui.find('**/tt_t_gui_qst_mapOpen'), gui.find('**/tt_t_gui_qst_mapTryToClose')), relief=None, pos=(-0.084, 0, 0.37), parent=base.a2dBottomRight, scale=0.205, command=self.hide) self.mapOpenButton.hide() self.mapCloseButton.hide() gui.removeNode() icons = loader.loadModel('phase_3/models/gui/cog_icons') cIcon = icons.find('**/CorpIcon') lIcon = icons.find('**/LegalIcon') mIcon = icons.find('**/MoneyIcon') sIcon = icons.find('**/SalesIcon') cogInfoTextColor = (0.2, 0.2, 0.2, 1) textPos = (1.2, -0.2) textScale = 0.8 self.cInfo = DirectLabel(parent=self.cogInfoFrame, text='', text_fg=cogInfoTextColor, text_pos=textPos, text_scale=textScale, geom=cIcon, geom_pos=(-0.2, 0, 0), geom_scale=0.8, relief=None) self.cInfo.setPos(-2.2, 0, 0.5) self.lInfo = DirectLabel(parent=self.cogInfoFrame, text_fg=cogInfoTextColor, text='', text_pos=textPos, text_scale=textScale, geom=lIcon, geom_pos=(-0.2, 0, 0), geom_scale=0.8, relief=None) self.lInfo.setPos(-2.2, 0, -0.5) self.mInfo = DirectLabel(parent=self.cogInfoFrame, text_fg=cogInfoTextColor, text='', text_pos=textPos, text_scale=textScale, geom=mIcon, geom_pos=(-0.2, 0, 0), geom_scale=0.8, relief=None) self.mInfo.setPos(0.8, 0, 0.5) self.sInfo = DirectLabel(parent=self.cogInfoFrame, text_fg=cogInfoTextColor, text='', text_pos=textPos, text_scale=textScale, geom=sIcon, geom_pos=(-0.2, 0, 0), geom_scale=0.8, relief=None) self.sInfo.setPos(0.8, 0, -0.5) icons.removeNode() return def updateCogInfo(self): currPercentage = self.suitPercentage.get(self.zoneId) if currPercentage is None: return self.cInfo['text'] = '%s%%' % currPercentage[0] self.lInfo['text'] = '%s%%' % currPercentage[1] self.mInfo['text'] = '%s%%' % currPercentage[2] self.sInfo['text'] = '%s%%' % currPercentage[3] return def destroy(self): self.ignore('questPageUpdated') self.mapOpenButton.destroy() self.mapCloseButton.destroy() del self.mapOpenButton del self.mapCloseButton DirectFrame.destroy(self) def putBuildingMarker(self, pos, hpr=(0, 0, 0), mapIndex=None): marker = DirectLabel(parent=self.container, text='', text_pos=(-0.05, -0.15), text_fg=(1, 1, 1, 1), relief=None) gui = loader.loadModel( 'phase_4/models/parties/schtickerbookHostingGUI') icon = gui.find('**/startPartyButton_inactive') iconNP = aspect2d.attachNewNode('iconNP') icon.reparentTo(iconNP) icon.setX(-12.0792 / 30.48) icon.setZ(-9.7404 / 30.48) marker['text'] = '%s' % mapIndex marker['text_scale'] = 0.7 marker['image'] = iconNP marker['image_color'] = (1, 0, 0, 1) marker['image_scale'] = 6 marker.setScale(0.05) relX, relY = self.transformAvPos(pos) marker.setPos(relX, 0, relY) self.buildingMarkers.append(marker) iconNP.removeNode() gui.removeNode() return def updateQuestInfo(self): for marker in self.buildingMarkers: marker.destroy() self.buildingMarkers = [] dnaStore = base.cr.playGame.dnaStore for questIndex in self.av.questPage.quests.keys(): questDesc = self.av.questPage.quests.get(questIndex) if questDesc is None: continue mapIndex = questIndex + 1 questId, fromNpcId, toNpcId, rewardId, toonProgress = questDesc quest = Quests.getQuest(questId) fComplete = quest.getCompletionStatus(self.av, questDesc) == Quests.COMPLETE if not fComplete: if quest.getType() == Quests.RecoverItemQuest: if quest.getHolder() == Quests.AnyFish: self.putBuildingMarker(self.fishingSpotInfo, mapIndex=mapIndex) continue elif quest.getType( ) != Quests.DeliverGagQuest and quest.getType( ) != Quests.DeliverItemQuest and quest.getType( ) != Quests.VisitQuest and quest.getType( ) != Quests.TrackChoiceQuest: continue if toNpcId == Quests.ToonHQ: self.putBuildingMarker(self.hqPosInfo, mapIndex=mapIndex) else: npcZone = NPCToons.getNPCZone(toNpcId) hoodId = ZoneUtil.getCanonicalHoodId(npcZone) branchId = ZoneUtil.getCanonicalBranchZone(npcZone) if self.hoodId == hoodId and self.zoneId == branchId: for blockIndex in xrange(dnaStore.getNumBlockTitles()): blockNumber = dnaStore.getTitleBlockAt(blockIndex) zone = dnaStore.getZoneFromBlockNumber(blockNumber) branchZone = zone - zone % 100 finalZone = branchZone + 500 + blockNumber buildingType = dnaStore.getBlockBuildingType( blockNumber) if npcZone == finalZone: self.putBuildingMarker( dnaStore.getDoorPosHprFromBlockNumber( blockNumber).getPos(), dnaStore.getDoorPosHprFromBlockNumber( blockNumber).getHpr(), mapIndex=mapIndex) return def transformAvPos(self, pos): if self.cornerPosInfo is None: return (0, 0) topRight = self.cornerPosInfo[0] bottomLeft = self.cornerPosInfo[1] relativeX = (pos.getX() - bottomLeft.getX()) / ( topRight.getX() - bottomLeft.getX()) - 0.5 relativeY = (pos.getY() - bottomLeft.getY()) / ( topRight.getY() - bottomLeft.getY()) - 0.5 return (relativeX, relativeY) def update(self, task): if self.av: if self.updateMarker: relX, relY = self.transformAvPos(self.av.getPos()) self.marker.setPos(relX, 0, relY) self.marker.setHpr(0, 0, -180 - self.av.getH()) i = 0 for buildingMarker in self.buildingMarkers: buildingMarker.setScale( (math.sin(task.time * 16.0 + i * math.pi / 3.0) + 1) * 0.005 + 0.04) i = i + 1 return Task.cont def updateMap(self): if self.av: try: hoodId = ZoneUtil.getCanonicalHoodId(self.av.getLocation()[1]) zoneId = ZoneUtil.getCanonicalBranchZone( self.av.getLocation()[1]) mapsGeom = loader.loadModel('phase_4/models/questmap/%s_maps' % ToontownGlobals.dnaMap[hoodId]) mapImage = mapsGeom.find( '**/%s_%s_english' % (ToontownGlobals.dnaMap[hoodId], zoneId)) if not mapImage.isEmpty(): self.container['image'] = mapImage self.resetFrameSize() self.cornerPosInfo = QuestMapGlobals.CornerPosTable.get( '%s_%s_english' % (ToontownGlobals.dnaMap[hoodId], zoneId)) self.hqPosInfo = QuestMapGlobals.HQPosTable.get( '%s_%s_english' % (ToontownGlobals.dnaMap[hoodId], zoneId)) self.fishingSpotInfo = QuestMapGlobals.FishingSpotPosTable.get( '%s_%s_english' % (ToontownGlobals.dnaMap[hoodId], zoneId)) self.cogInfoPos = QuestMapGlobals.CogInfoPosTable.get( '%s_%s_english' % (ToontownGlobals.dnaMap[hoodId], zoneId)) self.cogInfoFrame.setPos(self.cogInfoPos) self.hide() self.hoodId = hoodId self.zoneId = zoneId self.updateQuestInfo() self.updateCogInfo() taskMgr.add(self.update, 'questMapUpdate') else: self.stop() mapsGeom.removeNode() except: self.stop() def start(self): self.container.show() self.accept('questPageUpdated', self.updateMap) self.handleMarker() self.updateMap() def initMarker(self, task): if self.av: if not hasattr(base.cr.playGame.getPlace(), 'isInterior' ) or not base.cr.playGame.getPlace().isInterior: relX, relY = self.transformAvPos(self.av.getPos()) self.marker.setPos(relX, 0, relY) self.marker.setHpr(0, 0, -180 - self.av.getH()) self.marker['geom_scale'] = 1.4 * task.time % 0.5 * 10 + 1 self.marker['geom_color'] = (1, 1, 1, 0.8 - 1.4 * task.time % 0.5 * 2 / 0.8 + 0.2) if task.time < 1: return Task.cont else: self.marker['geom_color'] = (1, 1, 1, 0) return Task.done def show(self): taskMgr.add(self.initMarker, 'questMapInit') DirectFrame.show(self) self.mapOpenButton.hide() if self.container['image']: self.mapCloseButton.show() def hide(self): taskMgr.remove('questMapInit') DirectFrame.hide(self) if self.container['image']: self.mapOpenButton.show() self.mapCloseButton.hide() def toggle(self): if self.isHidden(): self.show() else: self.hide() def obscureButton(self): self.mapOpenButton.hide() self.mapCloseButton.hide() def stop(self): self.container['image'] = None for marker in self.buildingMarkers: marker.destroy() self.buildingMarkers = [] self.container.hide() self.hide() self.obscureButton() self.ignore('questPageUpdated') taskMgr.remove('questMapUpdate') return def handleMarker(self): if hasattr(base.cr.playGame.getPlace(), 'isInterior') and base.cr.playGame.getPlace().isInterior: self.updateMarker = False else: self.updateMarker = True def acceptOnscreenHooks(self): if self.wantToggle: self.accept(ToontownGlobals.MapHotkey, self.toggle) else: self.accept(ToontownGlobals.MapHotkeyOn, self.show) self.accept(ToontownGlobals.MapHotkeyOff, self.hide) self.updateMap() def ignoreOnscreenHooks(self): self.ignore(ToontownGlobals.MapHotkey) self.ignore(ToontownGlobals.MapHotkeyOn) self.ignore(ToontownGlobals.MapHotkeyOff) self.obscureButton()
class IssueFrameV2(IssueFrame.IssueFrame): notify = DirectNotifyGlobal.directNotify.newCategory('IssueFrameV2') SectionIdents = ['hom', 'new', 'evt', 'tot', 'att', 'tnr', 'ext'] def __init__(self, parent, newsDir, dateStr, myIssueIndex, numIssues, strFilenames, newsIndexEntries): self.newsIndexEntries = newsIndexEntries self.dateStr = dateStr self.calcActualSectionsInThisIssue() IssueFrame.IssueFrame.__init__(self, parent, newsDir, dateStr, myIssueIndex, numIssues, strFilenames) self.notify.debug('version2 %s' % dateStr) def load(self): self.guiNavV2 = loader.loadModel( 'phase_3.5/models/gui/tt_m_gui_ign_directNewsGuiNavV2') IssueFrame.IssueFrame.load(self) def calcActualSectionsInThisIssue(self): self.actualSectionIdents = [] for ident in self.SectionIdents: identTest = self.dateStr + '_' + ident + '1' if self.isSectionInIndex(identTest): self.actualSectionIdents.append(ident) continue def isSectionInIndex(self, sectionIdent): for name in self.newsIndexEntries: if sectionIdent in name and self.dateStr in name: return True continue return False def parseNewsContent(self): existingSectionIndex = 0 for (section, ident) in enumerate(self.SectionIdents): subSectionList = [] curSubSection = 0 endSearch = False while not endSearch: justName = self.ContentPattern % (self.dateStr, ident, curSubSection + 1) fullName = Filename(self.newsDir + '/' + justName) if self.strFilenames: if justName in self.strFilenames: subSectionList.append(fullName) self.flatSubsectionList.append( (existingSectionIndex, curSubSection)) curSubSection += 1 else: endSearch = True justName in self.strFilenames theFile = vfs.getFile(Filename(fullName), status_only=1) if theFile: subSectionList.append(fullName) self.flatSubsectionList.append( (existingSectionIndex, curSubSection)) curSubSection += 1 continue if curSubSection == 0 and self.isSectionInIndex(ident): self.notify.warning('could not find %s' % fullName) subSectionList.append(fullName) self.flatSubsectionList.append( (existingSectionIndex, curSubSection)) endSearch = True if not subSectionList: continue self.sectionList.append(subSectionList) existingSectionIndex += 1 self.notify.debug('IssueFrameV2 self.sectionList=%s' % self.sectionList) def loadHomePageButtons(self, section, subsection, pageFrame): self.notify.debug('Doing nothing for loadNavButtons') if section == 0 and subsection == 0: self.loadNavButtons(pageFrame) self.parentOfWeekNav = DirectFrame(frameColor=(1, 1, 1, 0), relief=DGG.FLAT, parent=pageFrame) self.loadWeekNavButtons(self.parentOfWeekNav) self.parentOfWeekNav.setPos(-1.9399999999999999, 0, 0) def loadNavButtons(self, pageFrame): identToButtonNames = { 'hom': 'tt_i_art_btn_NavHom2', 'new': 'tt_i_art_btn_NavNew2', 'evt': 'tt_i_art_btn_NavEvt2', 'tot': 'tt_i_art_btn_NavTot2', 'att': 'tt_i_art_btn_NavAtt2', 'tnr': 'tt_i_art_btn_NavTnr2', 'ext': 'tt_i_art_btn_NavExt2' } identToRolloverButtonNames = { 'hom': 'tt_i_art_btn_NavHomRo2', 'new': 'tt_i_art_btn_NavNewRo2', 'evt': 'tt_i_art_btn_NavEvtRo2', 'tot': 'tt_i_art_btn_NavTotRo2', 'att': 'tt_i_art_btn_NavAttRo2', 'tnr': 'tt_i_art_btn_NavTnrRo2', 'ext': 'tt_i_art_btn_NavExtRo2' } xPos = 1.2466699999999999 positions = [(xPos, 0, 0.62333300000000003), (xPos, 0, 0.536663), (xPos, 0, 0.45000000000000001), (xPos, 0, 0.36332999999999999), (xPos, 0, 0.276667), (xPos, 0, 0.19), (xPos, 0, 0.080000000000000002)] xSize1 = 177 desiredXSize1 = 90 image_scale1 = float(desiredXSize1) / xSize1 image_scale = 1 xSize2 = 300 desiredXSize2 = 152 image_scale2 = float(desiredXSize2) / xSize2 image_scale2 *= 30.0 / 30.0 rolloverPositions = [(1.0449999999999999, 0, 0.62333300000000003), (1.0449999999999999, 0, 0.53333299999999995), (1.0449999999999999, 0, 0.44333299999999998), (1.0449999999999999, 0, 0.35333300000000001), (1.0449999999999999, 0, 0.26333400000000001), (1.0449999999999999, 0, 0.17333299999999999), (1.0449999999999999, 0, 0.089999999999999997)] imageScales = [ image_scale2, image_scale2, image_scale2, image_scale2, image_scale2, image_scale2, image_scale2 ] frameSizeAdj1 = 0.10000000000000001 frameSize1 = (-0.040000000000000001 + frameSizeAdj1, 0.040000000000000001 + frameSizeAdj1, -0.040000000000000001, 0.040000000000000001) frameSizeAdj2 = 0.20999999999999999 frameSize2 = (-0.040000000000000001 + frameSizeAdj2, 0.040000000000000001 + frameSizeAdj2, -0.040000000000000001, 0.040000000000000001) frameSizes = (frameSize2, frameSize2, frameSize2, frameSize2, frameSize2, frameSize2, frameSize2) self.sectionBtns = [] for (section, ident) in enumerate(self.actualSectionIdents): image = self.guiNavV2.find('**/%s' % identToButtonNames[ident]) rolloverImage = self.guiNavV2.find( '**/%s' % identToRolloverButtonNames[ident]) if image.isEmpty(): self.notify.error('cant find %s' % identToButtonNames[ident]) sectionBtn = DirectButton(relief=None, parent=pageFrame, frameSize=frameSizes[section], image=(image, rolloverImage, rolloverImage, image), image_scale=imageScales[section], command=self.gotoPage, extraArgs=(section, 0), enableEdit=1, pos=rolloverPositions[section])
class GuiConsole(DirectObject.DirectObject): def __init__(self, class_parent, parent, h_size, v_size, aspect, hugpos): self.h_size = h_size self.v_size = v_size self.scale = 0.04 self.parent = class_parent self.numlines = int(v_size / self.scale - 2) self.pos_min_x = 0 self.pos_min_y = 0 self.pos_max_x = self.h_size self.pos_max_y = 0.7 if aspect > 0: self.pos_max_x /= aspect else: self.pos_max_y *= aspect self.consoleFrame = DirectFrame(relief=DGG.RIDGE, frameColor=(0, 0, 0, 0), scale=self.scale, frameSize=(0, self.h_size / self.scale, 0, self.v_size / self.scale)) if parent == base.a2dBottomLeft: #@UndefinedVariable self.pos_min_x -= 1 self.pos_min_y -= 1 self.pos_max_x -= 1 self.pos_max_y -= 1 if hugpos == "bottom": self.consoleFrame.setPos(0, 0, GUI_BOTTOM_OFFSET - 0.085) self.pos_min_x = 0 self.pos_min_y = GUI_BOTTOM_OFFSET - 0.085 - 0.07 self.pos_max_x = self.h_size self.pos_max_y = GUI_BOTTOM_OFFSET - 0.085 fixedWidthFont = loader.loadFont(GUI_FONT) #@UndefinedVariable #fixedWidthFont.setPixelsPerUnit(60) #fixedWidthFont.setRenderMode(fixedWidthFont.RMSolid) if not fixedWidthFont.isValid(): print "pandaInteractiveConsole.py :: could not load the defined font %s" % str( self.font) fixedWidthFont = DGG.getDefaultFont() #fixedWidthFont.setPageSize(512,512) #fixedWidthFont.setPixelsPerUnit(60) self.consoleEntry = DirectEntry( self.consoleFrame, text="", command=self.onEnterPress #, width = self.h_size/self.scale -2 , pos=(0.01, 0, 0.02), initialText="Enter text...", numLines=1, focus=0, entryFont=fixedWidthFont, scale=1, frameColor=(0, 0, 0, 0.2), text_fg=(0, 1, 0, 1), text_shadow=(0, 0, 0, 1)) #self.consoleEntry = DirectEntry(self.consoleFrame) self.consoleEntry["frameSize"] = (0, self.h_size / self.scale, 0, 1) self.consoleEntry["width"] = self.h_size / self.scale self.consoleEntry["focusInCommand"] = self.focusInCallback self.consoleEntry["focusOutCommand"] = self.focusOutCallback self.consoleFrame.reparentTo(parent) self.textBuffer = list() self.textBufferLength = 100 for i in xrange(self.textBufferLength): self.textBuffer.append(['', (100, 100, 100, 1)]) self.textBufferPos = self.textBufferLength - self.numlines # output lines self.consoleOutputList = list() for i in xrange(self.numlines): label = OnscreenText(parent=self.consoleFrame, text="", pos=(0, i + 1.5), align=TextNode.ALeft, mayChange=1, scale=1.0, fg=(100, 100, 100, 1), shadow=(0, 0, 0, 1)) # , frame = (200,0,0,1) ) label.setFont(fixedWidthFont) self.consoleOutputList.append(label) self.linelength = 57 self.linewrap = textwrap.TextWrapper() self.linewrap.width = self.linelength self.toggleConsole() def focusInCallback(self): self.parent.parent.camera_manager.disableKeyMovement() def focusOutCallback(self): self.parent.parent.camera_manager.enableKeyMovement() def show(self): if self.consoleFrame.isHidden(): self.consoleFrame.toggleVis() def hide(self): pass #if not self.consoleFrame.isHidden(): # self.consoleFrame.toggleVis() def toggleConsole(self): self.consoleFrame.toggleVis() hidden = self.consoleFrame.isHidden() #self.consoleEntry['focus'] != hidden if hidden: #self.ignoreAll() self.accept('control', self.toggleConsole) self.accept('enter', self.manageFocus) self.accept('escape', self.unfocus) else: #self.ignoreAll() #self.accept( 'page_up', self.scroll, [-5] ) #self.accept( 'page_up-repeat', self.scroll, [-5] ) #self.accept( 'page_down', self.scroll, [5] ) #self.accept( 'page_down-repeat', self.scroll, [5] ) #self.accept( 'window-event', self.windowEvent) #self.accept( 'arrow_up' , self.scrollCmd, [ 1] ) #self.accept( 'arrow_down', self.scrollCmd, [-1] ) self.accept('control', self.toggleConsole) self.accept('enter', self.manageFocus) self.accept('escape', self.unfocus) #self.accept( self.autocomplete_key, self.autocomplete ) #self.accept( self.autohelp_key, self.autohelp ) # accept v, c and x, where c & x copy's the whole console text #messenger.toggleVerbose() #for osx use ('meta') #if sys.platform == 'darwin': # self.accept( 'meta', self.unfocus ) # self.accept( 'meta-up', self.focus ) # self.accept( 'meta-c', self.copy ) # self.accept( 'meta-x', self.cut ) # self.accept( 'meta-v', self.paste ) #for windows use ('control') #if sys.platform == 'win32' or sys.platform == 'linux2': # self.accept( 'control', self.unfocus ) # self.accept( 'control-up', self.focus ) # self.accept( 'control-c', self.copy ) # self.accept( 'control-x', self.cut ) # self.accept( 'control-v', self.paste ) def onEnterPress(self, textEntered): # set to last message self.textBufferPos = self.textBufferLength - self.numlines # clear line self.consoleEntry.enterText('') self.consoleOutput(textEntered, utils.CONSOLE_PLAYER1_TEXT) ClientMsg.chat(textEntered) self.focus() def manageFocus(self): if self.consoleFrame.isHidden(): self.consoleFrame.toggleVis() if self.consoleEntry["focus"] == 0: self.focus() def consoleOutput(self, printString, msgType): if msgType == utils.CONSOLE_SYSTEM_ERROR: self.write(printString, utils.CONSOLE_SYSTEM_ERROR_TEXT_COLOR) elif msgType == utils.CONSOLE_SYSTEM_MESSAGE: self.write(printString, utils.CONSOLE_SYSTEM_MESSAGE_TEXT_COLOR) elif msgType == utils.CONSOLE_PLAYER1_TEXT: self.write(printString, utils.CONSOLE_PLAYER1_TEXT_COLOR) else: self.write(printString, utils.CONSOLE_PLAYER2_TEXT_COLOR) def write(self, printString, color=(100, 100, 100, 0.5)): # remove not printable characters (which can be input by console input) printString = re.sub(r'[^%s]' % re.escape(string.printable[:95]), "", printString) splitLines = self.linewrap.wrap(printString) for line in splitLines: self.textBuffer.append([line, color]) self.textBuffer.pop(0) self.updateOutput() def updateOutput(self): for lineNumber in xrange(self.numlines): lineText, color = self.textBuffer[lineNumber + self.textBufferPos] self.consoleOutputList[self.numlines - lineNumber - 1].setText(lineText) self.consoleOutputList[self.numlines - lineNumber - 1]['fg'] = color def focus(self): self.consoleEntry['focus'] = 1 def unfocus(self): self.consoleEntry['focus'] = 0 def getTightBounds(self): l, r, b, t = self.consoleFrame.getBounds() print l, r, b, t bottom_left = Point3(l, 0, b) top_right = Point3(r, 0, t) return (bottom_left, top_right)
class IssueFrameV2(IssueFrame.IssueFrame): notify = DirectNotifyGlobal.directNotify.newCategory('IssueFrameV2') SectionIdents = ['hom', 'new', 'evt', 'tot', 'att', 'tnr', 'ext'] def __init__(self, parent, newsDir, dateStr, myIssueIndex, numIssues, strFilenames, newsIndexEntries): self.newsIndexEntries = newsIndexEntries self.dateStr = dateStr self.calcActualSectionsInThisIssue() IssueFrame.IssueFrame.__init__(self, parent, newsDir, dateStr, myIssueIndex, numIssues, strFilenames) self.notify.debug('version2 %s' % dateStr) def load(self): self.guiNavV2 = loader.loadModel('phase_3.5/models/gui/tt_m_gui_ign_directNewsGuiNavV2') IssueFrame.IssueFrame.load(self) def calcActualSectionsInThisIssue(self): self.actualSectionIdents = [] for ident in self.SectionIdents: identTest = self.dateStr + '_' + ident + '1' if self.isSectionInIndex(identTest): self.actualSectionIdents.append(ident) def isSectionInIndex(self, sectionIdent): for name in self.newsIndexEntries: if sectionIdent in name and self.dateStr in name: return True return False def parseNewsContent(self): existingSectionIndex = 0 for section, ident in enumerate(self.SectionIdents): subSectionList = [] curSubSection = 0 endSearch = False while not endSearch: justName = self.ContentPattern % (self.dateStr, ident, curSubSection + 1) fullName = Filename(self.newsDir + '/' + justName) if self.strFilenames: if justName in self.strFilenames: subSectionList.append(fullName) self.flatSubsectionList.append((existingSectionIndex, curSubSection)) curSubSection += 1 else: endSearch = True else: theFile = vfs.getFile(Filename(fullName), status_only=1) if theFile: subSectionList.append(fullName) self.flatSubsectionList.append((existingSectionIndex, curSubSection)) curSubSection += 1 else: if curSubSection == 0 and self.isSectionInIndex(ident): self.notify.warning('could not find %s' % fullName) subSectionList.append(fullName) self.flatSubsectionList.append((existingSectionIndex, curSubSection)) endSearch = True if not subSectionList: pass else: self.sectionList.append(subSectionList) existingSectionIndex += 1 self.notify.debug('IssueFrameV2 self.sectionList=%s' % self.sectionList) def loadHomePageButtons(self, section, subsection, pageFrame): self.notify.debug('Doing nothing for loadNavButtons') if section == 0 and subsection == 0: self.loadNavButtons(pageFrame) self.parentOfWeekNav = DirectFrame(frameColor=(1, 1, 1, 0), relief=DGG.FLAT, parent=pageFrame) self.loadWeekNavButtons(self.parentOfWeekNav) self.parentOfWeekNav.setPos(-1.94, 0, 0) def loadNavButtons(self, pageFrame): identToButtonNames = {'hom': 'tt_i_art_btn_NavHom2', 'new': 'tt_i_art_btn_NavNew2', 'evt': 'tt_i_art_btn_NavEvt2', 'tot': 'tt_i_art_btn_NavTot2', 'att': 'tt_i_art_btn_NavAtt2', 'tnr': 'tt_i_art_btn_NavTnr2', 'ext': 'tt_i_art_btn_NavExt2'} identToRolloverButtonNames = {'hom': 'tt_i_art_btn_NavHomRo2', 'new': 'tt_i_art_btn_NavNewRo2', 'evt': 'tt_i_art_btn_NavEvtRo2', 'tot': 'tt_i_art_btn_NavTotRo2', 'att': 'tt_i_art_btn_NavAttRo2', 'tnr': 'tt_i_art_btn_NavTnrRo2', 'ext': 'tt_i_art_btn_NavExtRo2'} xPos = 1.24667 positions = [(xPos, 0, 0.623333), (xPos, 0, 0.536663), (xPos, 0, 0.45), (xPos, 0, 0.36333), (xPos, 0, 0.276667), (xPos, 0, 0.19), (xPos, 0, 0.08)] xSize1 = 177 desiredXSize1 = 90 image_scale1 = float(desiredXSize1) / xSize1 image_scale = 1 xSize2 = 300 desiredXSize2 = 152 image_scale2 = float(desiredXSize2) / xSize2 image_scale2 *= 30.0 / 30.0 rolloverPositions = [(1.045, 0, 0.623333), (1.045, 0, 0.533333), (1.045, 0, 0.443333), (1.045, 0, 0.353333), (1.045, 0, 0.263334), (1.045, 0, 0.173333), (1.045, 0, 0.09)] imageScales = [image_scale2, image_scale2, image_scale2, image_scale2, image_scale2, image_scale2, image_scale2] frameSizeAdj1 = 0.1 frameSize1 = (-0.04 + frameSizeAdj1, 0.04 + frameSizeAdj1, -0.04, 0.04) frameSizeAdj2 = 0.21 frameSize2 = (-0.04 + frameSizeAdj2, 0.04 + frameSizeAdj2, -0.04, 0.04) frameSizes = (frameSize2, frameSize2, frameSize2, frameSize2, frameSize2, frameSize2, frameSize2) self.sectionBtns = [] for section, ident in enumerate(self.actualSectionIdents): image = self.guiNavV2.find('**/%s' % identToButtonNames[ident]) rolloverImage = self.guiNavV2.find('**/%s' % identToRolloverButtonNames[ident]) if image.isEmpty(): self.notify.error('cant find %s' % identToButtonNames[ident]) sectionBtn = DirectButton(relief=None, parent=pageFrame, frameSize=frameSizes[section], image=(image, rolloverImage, rolloverImage, image), image_scale=imageScales[section], command=self.gotoPage, extraArgs=(section, 0), enableEdit=1, pos=rolloverPositions[section]) return
class RailsScheme: """Rails scheme GUI. Represents the railways map, which can be used by players to choose the right way across the game world. Args: world_map (list): All the world blocks. """ def __init__(self, world_map): self.is_shown = False self._temp_wids = [] self._open_snd = loader.loadSfx("sounds/GUI/paper1.ogg") # noqa: F821 self._close_snd = loader.loadSfx("sounds/GUI/paper2.ogg") # noqa: F821 self._world_map = world_map self._list = DirectFrame( frameSize=(-1.2, 1.2, -0.6, 0.6), frameTexture="gui/tex/paper2.png", state=DGG.NORMAL, ) self._list.setDepthTest(False) self._list.setTransparency(TransparencyAttrib.MAlpha) self._list.hide() DirectLabel( # Silewer Railways Scheme parent=self._list, text=base.labels.SCHEME[0], # noqa: F821 text_font=base.main_font, # noqa: F821 frameSize=(0.2, 0.2, 0.2, 0.2), text_scale=0.035, pos=(0, 0, 0.5), ) self._scheme = DirectFrame( parent=self._list, frameSize=(-1.1, 1.1, -0.3, 0.3), frameTexture="gui/tex/world_scheme.png", ) self._scheme.setTransparency(TransparencyAttrib.MAlpha) self._arrow = DirectFrame( parent=self._scheme, frameSize=(-0.02, 0.02, -0.02, 0.02), frameTexture="gui/tex/train_dir.png", pos=(-0.96, 0, 0.07), ) self._build_legend() def _build_legend(self): """Build the scheme legend GUI.""" lab_opts = { "parent": self._list, "text_scale": 0.033, "frameColor": (0, 0, 0, 0), "frameSize": (-0.1, 0.1, -0.1, 0.1), } DirectLabel( # Legend text=base.labels.SCHEME[1], # noqa: F821 text_font=base.main_font, # noqa: F821 text_align=TextNode.ALeft, pos=(-1, 0, -0.35), **lab_opts, ) DirectFrame( parent=self._scheme, frameTexture="gui/tex/city.png", frameSize=(-0.04, 0.04, -0.04, 0.04), pos=(-0.39, 0, -0.41), ) DirectLabel( # city text=base.labels.SCHEME[2], # noqa: F821 text_font=base.main_font, # noqa: F821 pos=(-0.3, 0, -0.42), **lab_opts, ) DirectFrame( parent=self._scheme, frameTexture="gui/tex/dash.png", frameSize=(-0.004, 0.004, -0.06, 0.06), frameColor=(0, 0, 0, 0.2), pos=(0.09, 0, -0.37), ).setR(90) DirectLabel( text=base.labels.SCHEME[3], # noqa: F821 text_font=base.main_font, # noqa: F821 pos=(0.29, 0, -0.38), **lab_opts, ) DirectFrame( parent=self._scheme, frameColor=(0.71, 0.25, 0.05, 0.2), frameSize=(-0.06, 0.06, -0.02, 0.02), pos=(0.09, 0, -0.45), ) DirectLabel( text=base.labels.SCHEME[4], # noqa: F821 text_font=base.main_font, # noqa: F821 pos=(0.26, 0, -0.46), **lab_opts, ) def _fill_branches(self): """Paint railway branches on the railways scheme.""" for branch in base.world.branches: # noqa: F821 start = -0.96 + self._world_map[branch["start"]].id * 0.0032 self._temp_wids.append( DirectFrame( parent=self._scheme, frameTexture="gui/tex/dash.png", frameSize=(-0.004, 0.004, -0.1, 0.1), frameColor=(0, 0, 0, 0.2), pos=(start, 0, 0.1 if branch["side"] == "l" else -0.1), )) end = -0.96 + self._world_map[branch["end"]].id * 0.0032 self._temp_wids.append( DirectFrame( parent=self._scheme, frameTexture="gui/tex/dash.png", frameSize=(-0.004, 0.004, -0.1, 0.1), frameColor=(0, 0, 0, 0.2), pos=(end, 0, 0.1 if branch["side"] == "l" else -0.1), )) x_coor = (start + end) / 2 horiz = DirectFrame( parent=self._scheme, frameTexture="gui/tex/dash.png", frameSize=(-0.004, 0.004, -(x_coor - start), end - x_coor), frameColor=(0, 0, 0, 0.2), pos=(x_coor, 0, 0.2 if branch["side"] == "l" else -0.2), ) horiz.setR(90) self._temp_wids.append(horiz) outs = "" for block in branch["blocks"][1:-1]: if block.outing_available: outs += block.outing_available[0] if block.is_station: outs += "i" if outs: outs = outs.lower() self._temp_wids.append( DirectLabel( parent=self._scheme, text=outs, text_scale=0.035, text_bg=(0, 0, 0, 0), text_fg=(0, 0, 0, 0.5), frameColor=(0, 0, 0, 0), pos=(x_coor, 0, 0.25 if branch["side"] == "l" else -0.27), )) def _fill_scheme(self): """Fill the railways scheme with the world data. Shows cities, outings and railway branches on the scheme. """ self._fill_branches() outs = None cities = 0 for block in self._world_map[:601]: if block.id % 100 == 0: if outs: self._temp_wids.append( DirectLabel( parent=self._scheme, text=outs, text_scale=0.035, text_bg=(0, 0, 0, 0), frameColor=(0, 0, 0, 0), pos=(-0.96 + (block.id - 50) * 0.0032, 0, -0.1), )) outs = "" if block.outing_available: outs += block.outing_available[0].lower() if block.is_station: outs += "i" if block.is_city: self._temp_wids.append( DirectFrame( parent=self._scheme, frameTexture="gui/tex/city.png", frameSize=(-0.04, 0.04, -0.04, 0.04), pos=(-0.96 + block.id * 0.0032, 0, 0), )) self._temp_wids.append( DirectLabel( parent=self._scheme, text=base.labels.CITY_NAMES[cities], # noqa: F821 text_font=base.main_font, # noqa: F821 text_scale=0.032, text_bg=(0, 0, 0, 0), frameColor=(0, 0, 0, 0), pos=(-0.96 + block.id * 0.0032, 0, 0.1), )) cities += 1 self._temp_wids.append( DirectFrame( parent=self._scheme, frameColor=(0.71, 0.25, 0.05, 0.2), frameSize=( 0, base.world.stench_step * 0.0032, # noqa: F821 -0.22, 0.22, ), pos=(-0.96, 0, 0), )) def _update_arrow(self, task): """Update the Train position on the scheme.""" blocks = base.world.current_blocks # noqa: F821 if blocks and blocks[0] != -1: z_shift = 0 if not base.world.is_near_fork: # noqa: F821 if base.world.current_block.branch == "l": # noqa: F821 z_shift = 0.155 elif base.world.current_block.branch == "r": # noqa: F821 z_shift = -0.295 if blocks[0] < 600: x = -0.96 + blocks[0] * 0.0032 else: x = self._arrow.getX() self._arrow.setPos(x, 0, 0.07 + z_shift) if blocks[0] < blocks[1]: self._arrow["frameTexture"] = "gui/tex/train_dir.png" else: self._arrow["frameTexture"] = "gui/tex/train_dir_op.png" task.delayTime = 5 return task.again def show(self): """Show/hide railways scheme GUI.""" if (self.is_shown or base.world.outings_mgr.gui_is_shown # noqa: F821 or base.traits_gui.is_shown # noqa: F821 ): self._close_snd.play() self._list.hide() taskMgr.remove("update_scheme_arrow") # noqa: F821 clear_wids(self._temp_wids) else: if base.world.is_on_et: # noqa: F821 return self._open_snd.play() taskMgr.doMethodLater( # noqa: F821 0.2, self._update_arrow, "update_scheme_arrow") self._fill_scheme() self._list.show() base.char_gui.clear_char_info(True) # noqa: F821 self.is_shown = not self.is_shown
class panda3dIOClass(DirectObject.DirectObject): # set gui key to None if you want to call toggleConsole from outside this class gui_key = PANDA3D_CONSOLE_TOGGLE_KEY autocomplete_key = PANDA3D_CONSOLE_AUTOCOMPLETE_KEY autohelp_key = PANDA3d_CONSOLE_AUTOHELP_KEY # change size of text and number of characters on one line # scale of frame ( must be small (0.0x) scale = PANDA3D_CONSOLE_SCALE # to define a special font, if loading fails the default font is used (without warning) font = PANDA3D_CONSOLE_FONT fontWidth = PANDA3D_CONSOLE_FONT_WIDTH # frame position and size (vertical & horizontal) h_pos = PANDA3D_CONSOLE_HORIZONTAL_POS h_size = PANDA3D_CONSOLE_HORIZONTAL_SIZE # v_size + v_pos should not exceed 2.0, else parts of the interface will not be visible # space above the frame ( must be below 2.0, best between 0.0 and 1.0 ) v_pos = PANDA3D_CONSOLE_VERTICAL_POS # vertical size of the frame ( must be at max 2.0, best between 0.5 and 2.0 ) v_size = PANDA3D_CONSOLE_VERTICAL_SIZE linelength = int((h_size / scale - 5) / fontWidth) print "max number of characters on a length:", linelength numlines = int(v_size / scale - 5) defaultTextColor = (0.0, 0.0, 0.0, 1.0) autoCompleteColor = (0.9, 0.9, 0.9, 1.0) def __init__(self, parent): self.parent = parent # line wrapper self.linewrap = textwrap.TextWrapper() self.linewrap.width = self.linelength # calculate window size left = (self.h_pos) / self.scale right = (self.h_pos + self.h_size) / self.scale bottom = (self.v_pos) / self.scale top = (self.v_pos + self.v_size) / self.scale # panda3d interface self.consoleFrame = DirectFrame( relief=DGG.GROOVE, frameColor=(200, 200, 200, 0.5), scale=self.scale, frameSize=(0, self.h_size / self.scale, 0, self.v_size / self.scale), ) self.windowEvent(base.win) # try to load the defined font fixedWidthFont = loader.loadFont(self.font) # if font is not valid use default font if not fixedWidthFont.isValid(): if self.font is None: print "pandaInteractiveConsole.py :: could not load the defined font %s" % str(self.font) fixedWidthFont = DGG.getDefaultFont() # text entry line self.consoleEntry = DirectEntry( self.consoleFrame, text="", command=self.onEnterPress, width=self.h_size / self.scale - 2, pos=(1, 0, 1.5), initialText="", numLines=1, focus=1, entryFont=fixedWidthFont, ) # output lines self.consoleOutputList = list() for i in xrange(self.numlines): label = OnscreenText( parent=self.consoleFrame, text="", pos=(1, -i + 3 + self.numlines), align=TextNode.ALeft, mayChange=1, scale=1.0, fg=self.defaultTextColor, ) label.setFont(fixedWidthFont) self.consoleOutputList.append(label) # list of the last commands of the user self.userCommandList = list() self.userCommandListLength = 100 for i in xrange(self.userCommandListLength): self.userCommandList.append("") self.userCommandPos = 0 # buffer for data self.textBuffer = list() self.textBufferLength = 1000 for i in xrange(self.textBufferLength): self.textBuffer.append(["", DEFAULT_COLOR]) self.textBufferPos = self.textBufferLength - self.numlines # toggle the window at least once to activate the events self.toggleConsole() self.toggleConsole() self.help() def help(self): # output some info text about this module infoTxt = """ ------ Panda3dConsole ------ - press F10 to toggle it on/off - use the usual copy, cut & paste keys - page_up : scrolls up - page_down : scrolls down - arrow_up : previous command - arrow_down : next command - BUGS : if you paste a to long text, the entry blocks FIX : use cut to remove the whole line""" # for line in infoTxt.split('\n'): # self.write( line, color=DEFAULT_COLOR ) return infoTxt # write a string to the panda3d console def write(self, printString, color=defaultTextColor): # remove not printable characters (which can be input by console input) printString = re.sub(r"[^%s]" % re.escape(string.printable[:95]), "", printString) splitLines = self.linewrap.wrap(printString) for line in splitLines: self.textBuffer.append([line, color]) self.textBuffer.pop(0) self.updateOutput() def updateOutput(self): for lineNumber in xrange(self.numlines): lineText, color = self.textBuffer[lineNumber + self.textBufferPos] self.consoleOutputList[lineNumber].setText(lineText) self.consoleOutputList[lineNumber]["fg"] = color # toggle the gui console def toggleConsole(self): self.consoleFrame.toggleVis() hidden = self.consoleFrame.isHidden() self.consoleEntry["focus"] != hidden if hidden: self.ignoreAll() self.accept(self.gui_key, self.toggleConsole) else: self.ignoreAll() self.accept("page_up", self.scroll, [-5]) self.accept("page_up-repeat", self.scroll, [-5]) self.accept("page_down", self.scroll, [5]) self.accept("page_down-repeat", self.scroll, [5]) self.accept("window-event", self.windowEvent) self.accept("arrow_up", self.scrollCmd, [1]) self.accept("arrow_down", self.scrollCmd, [-1]) self.accept(self.gui_key, self.toggleConsole) self.accept(self.autocomplete_key, self.autocomplete) self.accept(self.autohelp_key, self.autohelp) # accept v, c and x, where c & x copy's the whole console text # messenger.toggleVerbose() # for osx use ('meta') if sys.platform == "darwin": self.accept("meta", self.unfocus) self.accept("meta-up", self.focus) self.accept("meta-c", self.copy) self.accept("meta-x", self.cut) self.accept("meta-v", self.paste) # for windows use ('control') if sys.platform == "win32" or sys.platform == "linux2": self.accept("control", self.unfocus) self.accept("control-up", self.focus) self.accept("control-c", self.copy) self.accept("control-x", self.cut) self.accept("control-v", self.paste) def autocomplete(self): currentText = self.consoleEntry.get() currentPos = self.consoleEntry.guiItem.getCursorPosition() newText = self.parent.autocomplete(currentText, currentPos) if newText != currentText: self.consoleEntry.set(newText) self.consoleEntry.setCursorPosition(len(newText)) def autohelp(self): currentText = self.consoleEntry.get() currentPos = self.consoleEntry.guiItem.getCursorPosition() self.parent.autohelp(currentText, currentPos) def focus(self): self.consoleEntry["focus"] = 1 def unfocus(self): self.consoleEntry["focus"] = 0 def copy(self): copy = self.consoleEntry.get() clipboard.setText(copy) def paste(self): oldCursorPos = self.consoleEntry.guiItem.getCursorPosition() clipboardText = clipboard.getText() # compose new text line oldText = self.consoleEntry.get() newText = oldText[0:oldCursorPos] + clipboardText + oldText[oldCursorPos:] clipboardTextLines = newText.split(os.linesep) for i in xrange(len(clipboardTextLines) - 1): currentLine = clipboardTextLines[i] # we only want printable characters currentLine = re.sub(r"[^" + re.escape(string.printable[:95]) + "]", "", currentLine) # set new text and position self.consoleEntry.set(currentLine) self.onEnterPress(currentLine) currentLine = clipboardTextLines[-1] currentLine = re.sub(r"[^" + re.escape(string.printable[:95]) + "]", "", currentLine) self.consoleEntry.set(currentLine) self.consoleEntry.setCursorPosition(len(self.consoleEntry.get())) self.focus() def cut(self): clipboard.setText(self.consoleEntry.get()) self.consoleEntry.enterText("") self.focus() def scroll(self, step): self.textBufferPos += step self.textBufferPos = min(self.textBufferLength - self.numlines, max(0, self.textBufferPos)) self.updateOutput() def scrollCmd(self, step): oldCmdPos = self.userCommandPos self.userCommandPos += step self.userCommandPos = min(self.userCommandListLength - 1, max(0, self.userCommandPos)) self.userCommandList[oldCmdPos] = self.consoleEntry.get() newCmd = self.userCommandList[self.userCommandPos] self.consoleEntry.set(newCmd) self.consoleEntry.setCursorPosition(len(newCmd)) def onEnterPress(self, textEntered): # set to last message self.textBufferPos = self.textBufferLength - self.numlines # clear line self.consoleEntry.enterText("") self.focus() # add text entered to user command list & remove oldest entry self.userCommandList.insert(1, textEntered) self.userCommandList[0] = "" self.userCommandList.pop(-1) self.userCommandPos = 0 # call our parent self.parent.push(textEntered) def windowEvent(self, window): """ This is a special callback. It is called when the panda window is modified. """ wp = window.getProperties() width = wp.getXSize() / float(wp.getYSize()) height = wp.getYSize() / float(wp.getXSize()) if width > height: height = 1.0 else: width = 1.0 # aligned to center consolePos = Vec3(-self.h_size / 2, 0, -self.v_size / 2) # aligned to left bottom # consolePos = Vec3(-width+self.h_pos, 0, -height+self.v_pos) # aligned to right top # consolePos = Vec3(width-self.h_size, 0, height-self.v_size) # set position self.consoleFrame.setPos(consolePos)
class Window(): texture = None def __init__(self, title, scale, parent=None, child=None, transparent=False, owner=None): self.scale = scale self.owner = owner self.last_pos = None self.title_text = title self.title_color = (1, 1, 1, 1) self.title_pad = tuple(self.scale * 2) if parent is None: parent = aspect2d self.parent = parent if transparent: frameColor = (0, 0, 0, 0) else: frameColor = (0, 0, 0, 1) self.pad = 0 # if Window.texture is None: # Window.texture = loader.loadTexture('textures/futureui1.png') # image_scale = (scale[0] * Window.texture.get_x_size(), 1, scale[1] * Window.texture.get_y_size()) self.frame = DirectFrame( parent=parent, state=DGG.NORMAL, frameColor=frameColor ) #, image=self.texture, image_scale=image_scale) self.title_frame = DirectFrame(parent=self.frame, state=DGG.NORMAL, frameColor=(.5, .5, .5, 1)) self.title = OnscreenText(text=self.title_text, style=Plain, fg=self.title_color, scale=tuple(self.scale * 14), parent=self.title_frame, pos=(0, 0), align=TextNode.ALeft, font=None, mayChange=True) bounds = self.title.getTightBounds() self.title_frame['frameSize'] = [ 0, bounds[1][0] - bounds[0][0] + self.title_pad[0] * 2, 0, bounds[1][2] - bounds[0][2] + self.title_pad[1] * 2 ] self.title.setPos(-bounds[0][0] + self.title_pad[0], -bounds[0][2] + self.title_pad[1]) self.close_frame = DirectFrame(parent=self.frame, state=DGG.NORMAL, frameColor=(.5, .5, .5, 1)) self.close = OnscreenText(text='X', style=Plain, fg=self.title_color, scale=tuple(self.scale * 14), parent=self.close_frame, pos=(0, 0), align=TextNode.ACenter, font=None, mayChange=True) bounds = self.close.getTightBounds() self.close_frame['frameSize'] = [ 0, bounds[1][0] - bounds[0][0] + self.title_pad[0] * 2, self.title_frame['frameSize'][2], self.title_frame['frameSize'][3] ] self.close.setPos(-bounds[0][0] + self.title_pad[0], -bounds[0][2] + self.title_pad[1]) self.frame.setPos(0, 0, 0) self.title_frame.bind(DGG.B1PRESS, self.start_drag) self.title_frame.bind(DGG.B1RELEASE, self.stop_drag) self.close_frame.bind(DGG.B1PRESS, self.close_window) self.set_child(child) def set_child(self, child): if child is not None: self.child = child child.reparent_to(self.frame) self.update() def update(self): if self.child is not None: frame_size = self.child.frame['frameSize'] if frame_size is not None: frame_size[0] -= self.pad frame_size[1] += self.pad frame_size[2] += self.pad frame_size[3] -= self.pad self.frame['frameSize'] = frame_size if self.frame['frameSize'] is not None: width = self.frame['frameSize'][1] - self.frame['frameSize'][0] title_size = self.title_frame['frameSize'] title_size[0] = 0 title_size[1] = width self.title_frame['frameSize'] = title_size self.close_frame.setPos(width - self.close_frame['frameSize'][1], 0, 0) def start_drag(self, event): if base.mouseWatcherNode.has_mouse(): mpos = base.mouseWatcherNode.get_mouse() self.drag_start = self.frame.parent.get_relative_point( render2d, Point3(mpos.get_x(), 0, mpos.get_y())) - self.frame.getPos() taskMgr.add(self.drag, "drag", -1) def drag(self, task): if base.mouseWatcherNode.has_mouse(): mpos = base.mouseWatcherNode.get_mouse() current_pos = self.frame.parent.get_relative_point( render2d, Point3(mpos.get_x(), 0, mpos.get_y())) self.frame.set_pos(current_pos - self.drag_start) return task.again def close_window(self, event=None): if self.owner is not None: self.owner.window_closed(self) self.destroy() def stop_drag(self, event): taskMgr.remove("drag") self.last_pos = self.frame.getPos() def destroy(self): if self.frame is not None: self.frame.destroy() self.frame = None def getPos(self): return self.frame.getPos() def setPos(self, pos): self.frame.setPos(pos)
class ItemChooser(metaclass=abc.ABCMeta): """The base class for choose-one-of widgets. Args: is_shadowed (bool): Optional. If True, a shadowed font color will be used for this widget. """ def __init__(self, is_shadowed=False): font = (0, 0, 0, 0.3 if is_shadowed else 0) self._ind = 0 self._items = None self._chosen_item = None self._fr = DirectFrame(frameSize=(-0.11, 0.12, -0.025, 0.024), frameColor=font) self._name = DirectLabel( parent=self._fr, frameColor=(0, 0, 0, 0.3), text_fg=SILVER_COL, text_font=base.main_font, # noqa: F821 text="", text_scale=0.03, pos=(0, 0, -0.01), ) but_params = { "parent": self._fr, "text_fg": SILVER_COL, "frameColor": font, "scale": (0.075, 0, 0.075), } DirectButton(pos=(0.15, 0, -0.015), text=">", command=self._next, **but_params) DirectButton(pos=(-0.15, 0, -0.015), text="<", command=self._prev, **but_params) self._fr.hide() @abc.abstractmethod def _show_info(self): """Show the chosen item info.""" raise NotImplementedError("Chooser class must have _show_info() method.") @property def chosen_item(self): """The item chosen with this widget. Returns: object: The chosen object. """ return self._chosen_item def _next(self): """Choose the next item from the list.""" self._ind += 1 self._show_info() def _prev(self): """Choose the previous item from the list.""" self._ind -= 1 self._show_info() def destroy(self): """Clear this widget.""" self._fr.destroy() self._ind = 0 self._chosen_item = None self._items = None def prepare(self, parent, pos, items, init_ind=None): """Set this widget's parent and position. Args: parent (panda3d.core.NodePath): Parent widget. pos (tuple): New widget position. items (dict): Items to iterate through. init_ind (int): Index of the initial value. """ self._items = items self._fr.reparentTo(parent) self._fr.setPos(pos) self._fr.show() if init_ind is not None: self._ind = init_ind self._show_info()
class ToonPanel(DirectFrame): notify = directNotify.newCategory('ToonPanel') animal2HeadData = {'dog': (0.125, 0.04), 'duck': (0.1, 0.025), 'cat': (0.115, 0.04), 'rabbit': (0.115, 0.04), 'horse': (0.115, 0.06), 'monkey': (0.115, 0.06), 'pig': (0.115, 0.07), 'mouse': (0.09, 0.02), 'bear': (0.125, 0.05)} State2Text = {'status': ('Seeing if %s is available...', '%s is busy right now; try again later.'), 'teleport': ('Trying to go to %s...', 'Could not go to %s.'), 'friend': ('Asking %s to be your friend...', '%s said no, thank you.', 'You are now friends with %s!'), 'remove': ('Are you sure you want to remove %s from your friends list?', '%s left your friends list.')} def __init__(self): DirectFrame.__init__(self, scale=1.2) self['image'] = DGG.getDefaultDialogGeom() self['image_hpr'] = (0, 0, -90) self['image_scale'] = (0.62, 0.9, 0.325) self['image_color'] = (1, 1, 0.75, 1) self['image_pos'] = (0, 0, -0.065) self['relief'] = None self.reparentTo(base.a2dTopRight) self.setPos(-0.235, 0.0, -0.325) self.hide() self.head = None self.laffMeter = None self.exitButton = None self.friendButton = None self.teleportButton = None self.nameText = None self.actionFrame = None self.actionFrameText = None self.actionFrameButton = None self.actionFrameButton2 = None self.avatarInfo = None self.action = None self.fsm = ClassicFSM.ClassicFSM('ToonPanel', [State.State('off', self.enterOff, self.exitOff), State.State('waitOnAvatarInfoResponse', self.enterWaitOnAvatarInfoResponse, self.exitWaitOnAvatarInfoResponse, ['panel']), State.State('panel', self.enterPanel, self.exitPanel, ['off'])], 'off', 'off') self.fsm.enterInitialState() self.actionFSM = ClassicFSM.ClassicFSM('ToonPanelActionFSM', [State.State('off', self.enterOff, self.exitOff), State.State('waitOnAvatarStatusResponse', self.enterWaitOnAvatarStatusResponse, self.exitWaitOnAvatarStatusResponse, ['waitOnAvatarTeleportResponse', 'waitOnAvatarFriendListResponse', 'avatarBusy', 'off']), State.State('avatarBusy', self.enterAvatarBusy, self.exitAvatarBusy, ['off']), State.State('waitOnAvatarTeleportResponse', self.enterWaitOnAvatarTeleportResponse, self.exitWaitOnAvatarTeleportResponse, ['unableToTP']), State.State('unableToTP', self.enterUnableToTP, self.exitUnableToTP, ['off']), State.State('waitOnAvatarFriendListResponse', self.enterWaitOnAvatarFriendListResponse, self.exitWaitOnAvatarFriendListResponse, ['fRequestA', 'fRequestR']), State.State('fRequestA', self.enterFriendRequestAccepted, self.exitFriendRequestAccepted, ['off']), State.State('fRequestR', self.enterFriendRequestRejected, self.exitFriendRequestRejected, ['off']), State.State('removeFriendConfirm', self.enterRemoveFriendConfirm, self.exitRemoveFriendConfirm, ['off', 'removedFriend']), State.State('removedFriend', self.enterRemovedFriend, self.exitRemovedFriend, ['off'])], 'off', 'off') self.actionFSM.enterInitialState() return def maybeUpdateFriendButton(self): if self.friendButton: if self.avatarInfo: if self.avatarInfo[0] not in base.localAvatar.friends: self.friendButton['text'] = 'Add Friend' self.friendButton['extraArgs'] = ['waitOnAvatarFriendListResponse'] else: self.friendButton['text'] = 'Remove Friend' self.friendButton['extraArgs'] = ['removeFriendConfirm'] def enterOff(self): pass def exitOff(self): pass def enterUnableToTP(self): pass def exitUnableToTP(self): pass def enterWaitOnAvatarTeleportResponse(self): self.setActionText(self.State2Text['teleport'][0] % self.getAvatarName()) self.makeButtons('Cancel') self.acceptOnce('gotAvatarTeleportResponse', self.handleTeleportResponse) base.cr.friendsManager.d_iWantToTeleportToAvatar(self.avatarInfo[0]) def handleTeleportResponse(self, avatarId, shardId, zoneId): if self.avatarInfo[0] == avatarId: requestStatus = {} whereName = ZoneUtil.getWhereName(zoneId) loaderName = ZoneUtil.getLoaderName(zoneId) requestStatus['zoneId'] = zoneId if base.localAvatar.parentId == shardId: requestStatus['shardId'] = None else: requestStatus['shardId'] = shardId requestStatus['hoodId'] = ZoneUtil.getHoodId(zoneId, 1) requestStatus['where'] = whereName requestStatus['loader'] = loaderName requestStatus['how'] = 'teleportIn' requestStatus['avId'] = avatarId base.cr.playGame.getPlace().fsm.request('teleportOut', [requestStatus]) self.cleanup() return def exitWaitOnAvatarTeleportResponse(self): self.ignore('gotAvatarTeleportResponse') self.clearActionText() self.clearActionButtons() def setActionText(self, text): self.actionFrameText.setText(text) def clearActionText(self): self.actionFrameText.setText('') def makeButtons(self, button1, button2 = None): button2GeomFunc = {'Cancel': CIGlobals.getCancelBtnGeom, 'No': CIGlobals.getCancelBtnGeom, 'Okay': CIGlobals.getOkayBtnGeom, 'Yes': CIGlobals.getOkayBtnGeom} if button1 and not button2: button1Pos = (0, 0, -0.1) elif button1 and button2: button1Pos = (-0.1, 0, -0.1) button2Pos = (0.1, 0, -0.1) if button1: self.actionFrameButton = DirectButton(text=button1, geom=button2GeomFunc[button1](), parent=self.actionFrame, pos=button1Pos, text_scale=0.045, text_pos=(0, -0.08), command=self.actionButtonPressed, extraArgs=[1], relief=None, geom_scale=0.75) if button2: self.actionFrameButton2 = DirectButton(text=button2, geom=button2GeomFunc[button2](), parent=self.actionFrame, pos=button2Pos, text_scale=0.045, text_pos=(0, -0.08), command=self.actionButtonPressed, extraArgs=[2], relief=None, geom_scale=0.75) return def actionButtonPressed(self, buttonNum): currentState = self.actionFSM.getCurrentState().getName() if buttonNum == 1: if currentState in ('waitOnAvatarStatusResponse', 'waitOnAvatarTeleportResponse', 'waitOnAvatarFriendListResponse', 'avatarBusy', 'unableToTP', 'fRequestA', 'fRequestR', 'removeFriendConfirm', 'removedFriend'): if currentState == 'waitOnAvatarFriendListResponse': base.cr.friendsManager.d_iCancelledFriendRequest(self.avatarInfo[0]) elif currentState == 'removeFriendConfirm': self.actionFSM.request('removedFriend') return self.actionFSM.request('off') self.removeActionPanel() self.action = None elif buttonNum == 2: self.actionFSM.request('off') self.removeActionPanel() self.action = None return def clearActionButtons(self): if self.actionFrameButton2: self.actionFrameButton2.destroy() self.actionFrameButton2 = None if self.actionFrameButton: self.actionFrameButton.destroy() self.actionFrameButton = None return def enterAvatarBusy(self): self.setActionText(self.State2Text['status'][1] % self.getAvatarName()) self.makeButtons('Okay') def exitAvatarBusy(self): self.clearActionText() self.clearActionButtons() def getAvatarName(self): if self.avatarInfo: return self.avatarInfo[1] def enterWaitOnAvatarStatusResponse(self): self.acceptOnce('gotAvatarStatus', self.handleAvatarStatusResponse) base.cr.friendsManager.d_requestAvatarStatus(self.avatarInfo[0]) self.setActionText(self.State2Text['status'][0] % self.getAvatarName()) self.makeButtons('Cancel') def handleAvatarStatusResponse(self, avatarId, status): if avatarId == self.avatarInfo[0]: if status == 1: self.actionFSM.request('avatarBusy') else: self.actionFSM.request(self.action) else: self.acceptOnce('gotAvatarStatus', self.handleAvatarStatusResponse) def exitWaitOnAvatarStatusResponse(self): self.ignore('gotAvatarStatus') self.clearActionText() self.clearActionButtons() def enterWaitOnAvatarFriendListResponse(self): self.acceptOnce('friendRequestAccepted', self.handleFriendRequestAccepted) self.acceptOnce('friendRequestRejected', self.handleFriendRequestRejected) base.cr.friendsManager.d_askAvatarToBeFriends(self.avatarInfo[0]) self.setActionText(self.State2Text['friend'][0] % self.getAvatarName()) self.makeButtons('Cancel') def handleFriendRequestAccepted(self): self.actionFSM.request('fRequestA') def handleFriendRequestRejected(self): self.actionFSM.request('fRequestR') def exitWaitOnAvatarFriendListResponse(self): self.ignore('friendRequestAccepted') self.ignore('friendRequestRejected') self.clearActionText() self.clearActionButtons() def enterFriendRequestAccepted(self): self.setActionText(self.State2Text['friend'][2] % self.getAvatarName()) self.makeButtons('Okay') def exitFriendRequestAccepted(self): self.clearActionText() self.clearActionButtons() def enterFriendRequestRejected(self): self.setActionText(self.State2Text['friend'][1] % self.getAvatarName()) self.makeButtons('Okay') def exitFriendRequestRejected(self): self.clearActionText() self.clearActionButtons() def enterRemoveFriendConfirm(self): self.setActionText(self.State2Text['remove'][0] % self.getAvatarName()) self.makeButtons('Yes', 'No') def exitRemoveFriendConfirm(self): self.clearActionText() self.clearActionButtons() def enterRemovedFriend(self): base.cr.friendsManager.d_iRemovedFriend(self.avatarInfo[0]) self.setActionText(self.State2Text['remove'][1] % self.getAvatarName()) self.makeButtons('Okay') def exitRemovedFriend(self): self.clearActionText() self.clearActionButtons() def makeActionPanel(self): self.actionFrame = DirectFrame(image=DGG.getDefaultDialogGeom(), image_scale=(0.7, 0.5, 0.45), image_color=(1, 1, 0.75, 1), relief=None) self.actionFrame.reparentTo(base.a2dTopRight) self.actionFrame.setPos(-0.815, 0, -0.31) self.actionFrameText = OnscreenText(text='', parent=self.actionFrame, scale=0.05, wordwrap=12, pos=(0, 0.1)) return def removeActionPanel(self): self.clearActionButtons() if self.actionFrameText: self.actionFrameText.destroy() self.actionFrameText = None if self.actionFrame: self.actionFrame.destroy() self.actionFrame = None return def doAction(self, action): self.action = action self.actionFSM.requestFinalState() self.removeActionPanel() self.makeActionPanel() if action != 'removeFriendConfirm': self.actionFSM.request('waitOnAvatarStatusResponse') else: self.actionFSM.request(action) def enterWaitOnAvatarInfoResponse(self): self.label = OnscreenText(text='Retrieving Toon\ndetails...', parent=self, scale=0.04) self.acceptOnce('avatarInfoResponse', self.handleAvatarInfoResponse) base.cr.friendsManager.d_requestAvatarInfo(self.avatarInfo[0]) def handleAvatarInfoResponse(self, name, dna, maxHealth, health): if self.avatarInfo: self.avatarInfo.append(name) self.avatarInfo.append(dna) self.avatarInfo.append(maxHealth) self.avatarInfo.append(health) self.fsm.request('panel') def exitWaitOnAvatarInfoResponse(self): self.label.destroy() del self.label self.ignore('avatarInfoResponse') def makePanel(self, avId): if self.avatarInfo: if self.avatarInfo[0] == avId: return self.cleanup() base.localAvatar.hideFriendButton() self.show() self.avatarInfo = [] self.avatarInfo.append(avId) self.fsm.request('waitOnAvatarInfoResponse') def exitClicked(self): self.cleanup() base.localAvatar.showFriendButton() def cleanup(self): self.actionFSM.requestFinalState() self.fsm.requestFinalState() self.avatarInfo = None return def enterPanel(self): self.nameText = OnscreenText(text=self.avatarInfo[1], parent=self, pos=(0, 0.2), scale=0.035, wordwrap=8) self.nameText.setBin('gui-popup', 60) dna = ToonDNA.ToonDNA() dna.setDNAStrand(self.avatarInfo[2]) self.head = ToonHead.ToonHead(base.cr) self.head.generateHead(dna.gender, dna.animal, dna.head, 1) self.head.setHeadColor(dna.headcolor) self.head.reparentTo(self) self.head.setDepthWrite(1) self.head.setDepthTest(1) self.head.setH(180) self.head.setScale(self.animal2HeadData[dna.animal][0]) self.head.setZ(self.animal2HeadData[dna.animal][1]) self.laffMeter = LaffOMeter() r, g, b, _ = dna.headcolor self.laffMeter.generate(r, g, b, dna.animal, self.avatarInfo[3], self.avatarInfo[4]) self.laffMeter.reparentTo(self) self.laffMeter.setBin('gui-popup', 60) self.laffMeter.setScale(0.045) self.laffMeter.setPos(0, 0, -0.1) self.friendButton = DirectButton(geom=CIGlobals.getDefaultBtnGeom(), text='Add Friend', scale=0.58, relief=None, text_scale=0.058, geom_scale=(1.25, 0, 0.9), text_pos=(0, -0.0125), parent=self, pos=(0, 0, -0.12), command=self.doAction, extraArgs=['waitOnAvatarFriendListResponse']) self.friendButton.setPos(0, 0.0, -0.225) self.maybeUpdateFriendButton() self.teleportButton = DirectButton(geom=CIGlobals.getDefaultBtnGeom(), text='Teleport', scale=0.58, relief=None, text_scale=0.058, geom_scale=(1.25, 0, 0.9), text_pos=(0, -0.0125), parent=self, pos=(0, 0, -0.12), command=self.doAction, extraArgs=['waitOnAvatarTeleportResponse']) self.teleportButton.setPos(0, 0, -0.275) self.exitButton = DirectButton(geom=CIGlobals.getCancelBtnGeom(), parent=self, relief=None, scale=0.6, pos=(-0.127, 0.0, -0.3425), command=self.exitClicked) return def exitPanel(self): if self.actionFSM.getCurrentState().getName() == 'waitOnAvatarFriendListResponse': if self.avatarInfo: base.cr.friendsManager.d_iCancelledFriendRequest(self.avatarInfo[0]) self.actionFSM.requestFinalState() self.action = None self.avatarInfo = None self.removeActionPanel() self.hide() if self.nameText: self.nameText.destroy() self.nameText = None if self.head: self.head.removeNode() self.head.delete() self.head = None if self.laffMeter: self.laffMeter.disable() self.laffMeter.delete() self.laffMeter = None if self.friendButton: self.friendButton.destroy() self.friendButton = None if self.teleportButton: self.teleportButton.destroy() self.teleportButton = None if self.exitButton: self.exitButton.destroy() self.exitButton = None return
class GuiUnitPanel: def __init__(self, aspect, unit_id, panel_pos, unit_type, default_hp, hp, default_ap, ap): self.unit_id = unit_id self.frameWidth = 0.30 self.frameHeight = 0.06 self.frame = DirectFrame( # relief = DGG.FLAT scale = 1 , frameSize = (0, self.frameWidth, 0, -self.frameHeight) , frameColor = (0.2, 0.2, 0.2, 0.8) , parent = base.a2dTopLeft )#@UndefinedVariable self.pos = Point3(0, 0, -GUI_TOP_OFFSET-0.05 - (0.069*panel_pos)) self.frame.setPos(self.pos) self.ap_bar = DirectWaitBar(parent = self.frame , text = "" , range = default_ap , value = ap , pos = (0.2,0,-0.045) , barColor = (0,0,1,1) , frameColor = (0,0,0.5,0.2) , scale = (0.1,0.5,0.1)) self.hp_bar = DirectWaitBar(parent = self.frame , text = "" , range = default_hp , value = hp , pos = (0.2,0,-0.015) , barColor = (0,1,0,1) , frameColor = (1,0,0,0.9) , scale = (0.1,0.5,0.08)) self.insignia = OnscreenImage(parent = self.frame ,image = "unit_" + unit_type + "_big_transparent_32.png" ,pos = (0.035,0,-0.03) ,scale = 0.025) self.insignia.setTransparency(TransparencyAttrib.MAlpha) self.all_icons = {} self.visible_icons = {} self.addIcon("overwatch") self.addIcon("set_up") self.getBounds(aspect) def addIcon(self, name): self.all_icons[name] = OnscreenImage(parent = self.frame ,image = name + "_icon.png" #,pos = offset + (0,0,-0.1) ,scale = 0.035) self.all_icons[name].setTransparency(TransparencyAttrib.MAlpha) self.all_icons[name].hide() def refreshBars(self, hp, ap): self.ap_bar['value'] = ap self.hp_bar['value'] = hp self.ap_bar.setValue() self.hp_bar.setValue() def refreshIcons(self): count = len(self.visible_icons) start_pos = 0.34 for icon in self.all_icons: if icon in self.visible_icons: self.visible_icons[icon].setPos((start_pos, 0, -0.032)) self.visible_icons[icon].show() start_pos += 0.07 else: self.all_icons[icon].hide() def hideOverwatch(self): if "overwatch" in self.visible_icons: self.visible_icons.pop("overwatch") self.refreshIcons() def showOverwatch(self): self.visible_icons["overwatch"] = self.all_icons["overwatch"] self.refreshIcons() def hideSetUp(self): if "set_up" in self.visible_icons: self.visible_icons.pop("set_up") self.refreshIcons() def showSetUp(self): self.visible_icons["set_up"] = self.all_icons["set_up"] self.refreshIcons() def getBounds(self, aspect): posx, posy = self.frame.getTightBounds() self.pos_min_x = -1 self.pos_min_y = self.pos.getZ() + 1 - self.frameHeight self.pos_max_x = -1 + self.frameWidth/aspect self.pos_max_y = self.pos.getZ() + 1
class GuiTextFrame: def __init__(self, offset, h_size, v_size, numLines, hugpos): self.numLines = numLines #if hugpos == "statusbar": # color = (0,0,0,1) #else: # color = (0.2, 0.2, 0.2, 0.8) color = (0.2, 0.2, 0.2, 0.9) self.frame = DirectFrame( relief = DGG.FLAT , frameColor = color , scale = 1 , frameSize = (0, h_size, 0, -v_size) ) self.v_size = v_size self.hugpos = hugpos self.offset = offset if hugpos == "top": self.frame.reparentTo(base.a2dTopLeft)#@UndefinedVariable self.frame.setPos(self.offset.getX(), 0, self.offset.getZ() - GUI_TOP_OFFSET) elif hugpos == "bottom": self.frame.reparentTo(base.a2dBottomLeft)#@UndefinedVariable self.frame.setPos(self.offset.getX(), 0, self.offset.getZ() + GUI_BOTTOM_OFFSET -0.085) elif hugpos == "statusbar": self.frame.reparentTo(base.a2dTopLeft)#@UndefinedVariable self.frame.setPos(self.offset.getX(), 0, self.offset.getZ()) fixedWidthFont = loader.loadFont(GUI_FONT)#@UndefinedVariable if not fixedWidthFont.isValid(): print "pandaInteractiveConsole.py :: could not load the defined font %s" % str(self.font) fixedWidthFont = DGG.getDefaultFont() if numLines == 1: self.lineHeight = 0.05 else: self.lineHeight = v_size*0.9 / numLines # output lines self.frameOutputList = list() for i in xrange( self.numLines ): label = OnscreenText( parent = self.frame , text = "" , pos = (0.005, -(i+1)*self.lineHeight) , align=TextNode.ALeft , mayChange=1 , scale=0.04 , fg = (1,1,1,1) , shadow = (0, 0, 0, 1)) #, frame = (200,0,0,1) ) label.setFont( fixedWidthFont ) self.frameOutputList.append( label ) def write(self, lineNumber, text): if lineNumber > self.numLines: return self.frameOutputList[lineNumber - 1].setText(text) def redraw(self, aspect): if self.hugpos == "top": p = base.a2dTopLeft.getPos()#@UndefinedVariable p.setX(p.getX() + self.offset.getX() + 0.05) p.setZ(p.getZ() + self.offset.getZ() - GUI_TOP_OFFSET - 0.05) self.frame.setPos(p) elif self.hugpos == "bottom": p = base.a2dBottomLeft.getPos()#@UndefinedVariable p.setX(p.getX() + self.offset.getX() + 0.05) p.setZ(p.getZ() + self.offset.getZ() + GUI_BOTTOM_OFFSET - 0.05) self.frame.setPos(p) elif self.hugpos == "statusbar": self.frame["frameSize"] = (0, 2*aspect, 0, -self.v_size) self.frame.resetFrameSize()
class GuiButton2: def __init__(self, hugpos, offset, aspect, plane, name): self.enabled = True self.name = name self.frame = DirectFrame( relief = DGG.FLAT , frameColor = (0, 0, 0, 0) , scale = 1 , frameSize = (-0.3, 0.3, -0.3, 0.3) ) #32/600=0.05333 self.frame.setScale(0.0533) self.imageObject = OnscreenImage(image = name+".png", pos = (0, 0, 0)) self.imageObject.setTransparency(TransparencyAttrib.MAlpha) self.imageObject.setAlphaScale(1) self.imageObject.reparentTo(self.frame) self.hugpos = hugpos self.offset = offset self.redraw(aspect) def redraw(self, aspect, flag="wide"): if self.hugpos == "top": p = base.a2dTopLeft.getPos()#@UndefinedVariable p.setX(p.getX() + self.offset.getX() + 0.05) p.setZ(p.getZ() + self.offset.getZ() - GUI_TOP_OFFSET - 0.05) elif self.hugpos == "bottom": p = base.a2dBottomLeft.getPos()#@UndefinedVariable p.setX(p.getX() + self.offset.getX() + 0.05) p.setZ(p.getZ() + self.offset.getZ() + GUI_BOTTOM_OFFSET - 0.05) elif self.hugpos == "right": p = base.a2dBottomRight.getPos()#@UndefinedVariable p.setX(p.getX() + self.offset.getX() + 0.05) p.setZ(p.getZ() + self.offset.getZ() + GUI_BOTTOM_OFFSET - 0.05) self.frame.setPos(p) if flag == "wide": posx, posy = self.frame.getTightBounds() self.pos_min_x = posx.getX() / aspect self.pos_min_y = posx.getZ() self.pos_max_x = posy.getX() / aspect self.pos_max_y = posy.getZ() elif flag == "tall": posx, posy = self.frame.getTightBounds() self.pos_min_x = posx.getX() self.pos_min_y = posx.getZ() / aspect self.pos_max_x = posy.getX() self.pos_max_y = posy.getZ() / aspect def turnOn(self): self.imageObject.setImage(self.name+"_on.png")#@UndefinedVariable self.imageObject.setTransparency(TransparencyAttrib.MAlpha) def turnOff(self): self.imageObject.setImage(self.name+".png")#@UndefinedVariable self.imageObject.setTransparency(TransparencyAttrib.MAlpha) def enable(self): self.imageObject.setImage(self.name+".png")#@UndefinedVariable self.imageObject.setTransparency(TransparencyAttrib.MAlpha) self.enabled = True def disable(self): self.imageObject.setImage("empty.png")#@UndefinedVariable self.imageObject.setTransparency(TransparencyAttrib.MAlpha) self.enabled = False def removeNode(self): self.frame.removeNode() def setAbility(self, ability): self.name = ability self.imageObject.setImage(self.name+".png") self.imageObject.setTransparency(TransparencyAttrib.MAlpha) self.imageObject.setAlphaScale(1)
class IssueFrameV2(IssueFrame.IssueFrame): notify = DirectNotifyGlobal.directNotify.newCategory("IssueFrameV2") # home page is considered one section, must always be first # home, news, events, talk of the town, ask toontown, toon resistance, extra SectionIdents = ['hom', 'new', 'evt', 'tot', 'att', 'tnr', 'ext'] def __init__(self, parent, newsDir, dateStr, myIssueIndex, numIssues, strFilenames, newsIndexEntries): self.newsIndexEntries = newsIndexEntries self.dateStr = dateStr self.calcActualSectionsInThisIssue() IssueFrame.IssueFrame.__init__(self, parent, newsDir, dateStr, myIssueIndex, numIssues, strFilenames, ) self.notify.debug("version2 %s" % dateStr) def load(self): self.guiNavV2 = loader.loadModel("phase_3.5/models/gui/tt_m_gui_ign_directNewsGuiNavV2") IssueFrame.IssueFrame.load(self) def calcActualSectionsInThisIssue(self): self.actualSectionIdents = [] for ident in self.SectionIdents: identTest = self.dateStr + "_" + ident + "1" if self.isSectionInIndex(identTest): self.actualSectionIdents.append(ident) def isSectionInIndex(self, sectionIdent): for name in self.newsIndexEntries: if sectionIdent in name and self.dateStr in name: return True return False def parseNewsContent(self): """Open up the directory, read all the files, and figure out the structure.""" existingSectionIndex = 0 for section, ident in enumerate(self.SectionIdents): subSectionList = [] curSubSection = 0 endSearch = False while not endSearch: justName = self.ContentPattern % (self.dateStr, ident, curSubSection +1) fullName = Filename(self.newsDir + '/' + justName) if self.strFilenames: # we already have a list of filenames, check if it's in there if justName in self.strFilenames: subSectionList.append(fullName) self.flatSubsectionList.append((existingSectionIndex, curSubSection)) curSubSection += 1 else: endSearch = True else: theFile = vfs.getFile(Filename(fullName), status_only=1) if theFile: subSectionList.append(fullName) self.flatSubsectionList.append((existingSectionIndex, curSubSection)) curSubSection += 1 else: if curSubSection == 0 and self.isSectionInIndex(ident): self.notify.warning('could not find %s' % fullName) subSectionList.append(fullName) self.flatSubsectionList.append((existingSectionIndex, curSubSection)) endSearch = True if not subSectionList: pass else: self.sectionList.append(subSectionList) existingSectionIndex += 1 self.notify.debug("IssueFrameV2 self.sectionList=%s" % self.sectionList) def loadHomePageButtons(self, section, subsection, pageFrame): self.notify.debug('Doing nothing for loadNavButtons') if section == 0 and subsection == 0: self.loadNavButtons(pageFrame) self.parentOfWeekNav = DirectFrame(frameColor = (1, 1, 1, 0), relief = DGG.FLAT, parent = pageFrame, ) self.loadWeekNavButtons(self.parentOfWeekNav) self.parentOfWeekNav.setPos(-1.94, 0, 0) def loadNavButtons(self, pageFrame): identToButtonNames = {'hom' : 'tt_i_art_btn_NavHom2', 'new' : 'tt_i_art_btn_NavNew2', 'evt' : 'tt_i_art_btn_NavEvt2', 'tot' : 'tt_i_art_btn_NavTot2', 'att' : 'tt_i_art_btn_NavAtt2', 'tnr' : 'tt_i_art_btn_NavTnr2', 'ext' : 'tt_i_art_btn_NavExt2', } identToRolloverButtonNames = {'hom' : 'tt_i_art_btn_NavHomRo2', 'new' : 'tt_i_art_btn_NavNewRo2', 'evt' : 'tt_i_art_btn_NavEvtRo2', 'tot' : 'tt_i_art_btn_NavTotRo2', 'att' : 'tt_i_art_btn_NavAttRo2', 'tnr' : 'tt_i_art_btn_NavTnrRo2', 'ext' : 'tt_i_art_btn_NavExtRo2', } xPos = 1.24667 positions = [ (xPos, 0, 0.623333), (xPos, 0, 0.536663), (xPos, 0, 0.45), (xPos, 0, 0.36333), (xPos, 0, 0.276667), (xPos, 0, 0.19), (xPos, 0, 0.08), ] # values captured using direct screen captures xSize1 = 177 desiredXSize1 = 90 image_scale1 = float(desiredXSize1) / xSize1 image_scale = 1 xSize2 = 300 desiredXSize2 = 152 image_scale2 = float(desiredXSize2) / xSize2 image_scale2 *= 30.0 / 30.0 rolloverPositions = [ (1.045, 0, 0.623333), (1.045, 0, 0.533333), (1.045, 0, 0.443333), (1.045, 0, 0.353333), (1.045, 0, 0.263334), (1.045, 0, 0.173333), (1.045, 0, 0.09), ] imageScales = [ image_scale2, image_scale2, image_scale2, image_scale2, image_scale2, image_scale2, image_scale2, ] frameSizeAdj1 = 0.1 frameSize1 = (-0.04 + frameSizeAdj1, 0.04 + frameSizeAdj1, -0.04, 0.04) frameSizeAdj2 = 0.21 frameSize2 = (-0.04 + frameSizeAdj2, 0.04 + frameSizeAdj2, -0.04, 0.04) frameSizes = ( frameSize2, frameSize2, frameSize2, frameSize2, frameSize2, frameSize2, frameSize2) # TODO get from Teani normal state buttons same size as rollover self.sectionBtns = [] for section, ident in enumerate(self.actualSectionIdents): image = self.guiNavV2.find('**/%s' % identToButtonNames[ident]) rolloverImage = self.guiNavV2.find('**/%s' % identToRolloverButtonNames[ident]) if image.isEmpty(): self.notify.error('cant find %s' % identToButtonNames[ident]) sectionBtn = DirectButton( relief = None, parent = pageFrame, frameSize = frameSizes[section], image = (image, rolloverImage, rolloverImage, image), image_scale = imageScales[section], command = self.gotoPage, extraArgs = (section, 0), enableEdit = 1, pos = rolloverPositions[section], )
class ConsoleWindow(DirectObject.DirectObject): console_output = None gui_key = PANDA3D_CONSOLE_TOGGLE_KEY autocomplete_key = PANDA3D_CONSOLE_AUTOCOMPLETE_KEY autohelp_key = PANDA3D_CONSOLE_AUTOHELP_KEY # change size of text and number of characters on one line # scale of frame (must be small (0.0x) scale = PANDA3D_CONSOLE_SCALE # to define a special font, if loading fails the default font is used # (without warning) font = PANDA3D_CONSOLE_FONT fontWidth = PANDA3D_CONSOLE_FONT_WIDTH # frame position and size (vertical & horizontal) h_pos = PANDA3D_CONSOLE_HORIZONTAL_POS h_size = PANDA3D_CONSOLE_HORIZONTAL_SIZE # v_size + v_pos should not exceed 2.0, else parts of the interface # will not be visible # space above the frame (must be below 2.0, best between 0.0 and 1.0) v_pos = PANDA3D_CONSOLE_VERTICAL_POS # vertical size of the frame (must be at max 2.0, best between 0.5 and 2.0) v_size = PANDA3D_CONSOLE_VERTICAL_SIZE linelength = int((h_size / scale - 5) / fontWidth) textBuffer = list() MAX_BUFFER_LINES = 5000 commandPos = 0 _iconsole = None _commandBuffer = '' logger.debug("max number of characters on a length:", linelength) numlines = int(v_size / scale - 5) defaultTextColor = (0.0, 0.0, 0.0, 1.0) autoCompleteColor = (0.9, 0.9, 0.9, 1.0) consoleFrame = None commandList = [] maxCommandHistory = 10000 textBufferPos = -1 clipboardTextLines = None clipboardTextRaw = None def __init__(self, parent): global base if not logger.isEnabledFor(logging.DEBUG): global CONSOLE_MESSAGE CONSOLE_MESSAGE = ''' ----------------- Ship's Interface version 3.0.9_749 ------------------- Direct Ship Interface Enabled. Please use caution. Irresponsible use of this console may result in the ship's AI refusing access to this interface. type 'help' for basic commands. -------------------------------------------------------------------------''' # change up from parent/IC self.parent = parent localenv = globals() localenv['gameroot'] = self.parent self._iconsole = customConsoleClass(localsEnv=localenv) # line wrapper self.linewrap = textwrap.TextWrapper() self.linewrap.width = self.linelength # calculate window size # left = (self.h_pos) / self.scale # right = (self.h_pos + self.h_size) / self.scale # bottom = (self.v_pos) / self.scale # top = (self.v_pos + self.v_size) /self.scale # panda3d interface self.consoleFrame = DirectFrame(relief=DGG.GROOVE, frameColor=(200, 200, 200, 0.5), scale=self.scale, frameSize=(0, self.h_size / self.scale, 0, self.v_size / self.scale)) self.windowEvent(base.win) fixedWidthFont = None try: # try to load the defined font fixedWidthFont = parent.loader.loadFont(self.font) except Exception: traceback.print_exc() # if font is not valid use default font logger.warn('could not load the defined font %s" % str(self.font') fixedWidthFont = DGG.getDefaultFont() # text lines self._visibleLines = list( OnscreenText(parent=self.consoleFrame, text="", pos=(1, -i + 3 + self.numlines), align=TextNode.ALeft, mayChange=1, scale=1.0, fg=self.defaultTextColor) for i in range(self.numlines)) map(lambda x: x.setFont(fixedWidthFont), self._visibleLines) # text entry line self.consoleEntry = DirectEntry(self.consoleFrame, text="", command=self.submitTrigger, width=self.h_size / self.scale - 2, pos=(1, 0, 1.5), initialText="", numLines=1, focus=1, entryFont=fixedWidthFont) # self.console_output = ConsoleOutput(testme=True) self.echo(CONSOLE_MESSAGE) self.clipboard = pyperclip def windowEvent(self, window): """ This is a special callback. It is called when the panda window is modified. """ wp = window.getProperties() width = wp.getXSize() / float(wp.getYSize()) height = wp.getYSize() / float(wp.getXSize()) if width > height: height = 1.0 else: width = 1.0 # aligned to center consolePos = Vec3(-self.h_size / 2, 0, -self.v_size / 2) # aligned to left bottom # consolePos = Vec3(-width+self.h_pos, 0, -height+self.v_pos) # aligned to right top # consolePos = Vec3(width-self.h_size, 0, height-self.v_size) # set position self.consoleFrame.setPos(consolePos) def submitTrigger(self, cmdtext): # set to last message # clear line self.consoleEntry.enterText('') self.focus() # add text entered to user command list & remove oldest entry self.commandList.append(cmdtext) self.commandPos += 1 self._commandBuffer = '' logger.debug('CP {}'.format(self.commandPos)) # push to interp for text, pre, color in self._iconsole.push(cmdtext): self.echo(text, pre, color) # set up console controls def mapControls(self): hidden = self.consoleFrame.isHidden() self.consoleEntry['focus'] != hidden if hidden: self.ignoreAll() else: self.accept('page_up', self.scroll, [-5]) self.accept('page_up-repeat', self.scroll, [-5]) self.accept('page_down', self.scroll, [5]) self.accept('page_down-repeat', self.scroll, [5]) self.accept('window-event', self.windowEvent) self.accept('arrow_up', self.scrollCmd, [-1]) self.accept('arrow_down', self.scrollCmd, [1]) self.accept(self.gui_key, self.toggleConsole) self.accept('escape', self.toggleConsole) self.accept(self.autocomplete_key, self.autocomplete) self.accept(self.autohelp_key, self.autohelp) # accept v, c and x, where c & x copy's the whole console text # messenger.toggleVerbose() # for osx use ('meta') if sys.platform == 'darwin': self.accept('meta', self.unfocus) self.accept('meta-up', self.focus) self.accept('meta-c', self.copy) self.accept('meta-x', self.cut) self.accept('meta-v', self.paste) # for windows use ('control') if sys.platform == 'win32' or sys.platform == 'linux2': self.accept('control', self.unfocus) self.accept('control-up', self.focus) self.accept('control-c', self.copy) self.accept('control-x', self.cut) self.accept('control-v', self.paste) # toggle the gui console def toggleConsole(self, hide=False): if hide: self.consoleFrame.hide() self.ignoreAll() # express hide, don't call setControls() return if self.consoleFrame.is_hidden(): self.consoleFrame.show() self.parent.setControls(self) else: self.consoleFrame.hide() self.ignoreAll() self.parent.setControls() def scroll(self, step): newpos = self.textBufferPos + step if newpos < 0 or newpos >= len(self.textBuffer): # no... no... I no think so return self.textBufferPos = newpos self.redrawConsole() def redrawConsole(self): windowstart = max(self.textBufferPos - len(self._visibleLines) + 1, 0) windowend = min( len(self._visibleLines) + windowstart, len(self.textBuffer)) logger.debug('windowS: {} WindowE: {}'.format(windowstart, windowend)) for lineNumber, (lineText, color) in \ enumerate(self.textBuffer[ windowstart: windowend]): logger.debug("LN {}, LEN {}".format(lineNumber, len(self.textBuffer))) self._visibleLines[lineNumber].setText(lineText) self._visibleLines[lineNumber]['fg'] = color def scrollCmd(self, step): if not self.commandList: # 0 or null - nothing to scroll return # should we update a temp buffer? if self.commandPos == len(self.commandList): if step > 0: self.consoleEntry.set(self._commandBuffer) return else: tmp = self.consoleEntry.get() if self.commandList[-1] != tmp: self._commandBuffer = tmp self.commandPos += step if self.commandPos >= len(self.commandList): self.commandPos = len(self.commandList) - 1 self.consoleEntry.set(self._commandBuffer) self.consoleEntry.setCursorPosition( len(self.commandList[self.commandPos])) elif self.commandPos < 0: self.commandPos = -1 # No need to change anything, can't go past the beginning return # finally, just set it self.consoleEntry.set(self.commandList[self.commandPos]) self.consoleEntry.setCursorPosition( len(self.commandList[self.commandPos])) def autocomplete(self): currentText = self.consoleEntry.get() currentPos = self.consoleEntry.guiItem.getCursorPosition() newText = self._iconsole.autocomplete(currentText, currentPos) if newText[-1] and newText[-1] != currentText: self.consoleEntry.set(newText[-1]) self.consoleEntry.setCursorPosition(len(newText)) def autohelp(self): currentText = self.consoleEntry.get() currentPos = self.consoleEntry.guiItem.getCursorPosition() self.parent.autohelp(currentText, currentPos) def unfocus(self): self.consoleEntry['focus'] = 0 def focus(self): self.consoleEntry['focus'] = 1 def copy(self): copy = self.consoleEntry.get() pyperclip.copy(copy) def paste(self): oldCursorPos = self.consoleEntry.guiItem.getCursorPosition() self.clipboardTextRaw = pyperclip.paste() # compose new text line oldText = self.consoleEntry.get() newText = oldText[0:oldCursorPos] + self.clipboardTextRaw + oldText[ oldCursorPos:] self.clipboardTextLines = newText.split(os.linesep) for i in range(len(self.clipboardTextLines) - 1): currentLine = self.clipboardTextLines[i] # we only want printable characters currentLine = re.sub( r'[^' + re.escape(string.printable[:95]) + ']', "", currentLine) # set new text and position self.consoleEntry.set(currentLine) self.submitTrigger(currentLine) currentLine = self.clipboardTextLines[-1] currentLine = re.sub(r'[^' + re.escape(string.printable[:95]) + ']', "", currentLine) self.consoleEntry.set(currentLine) self.consoleEntry.setCursorPosition(len(self.consoleEntry.get())) self.focus() def cut(self): pyperclip.copy(self.consoleEntry.get()) self.consoleEntry.enterText('') self.focus() def echo(self, output, pre='*', color=defaultTextColor): if logger.isEnabledFor(logging.DEBUG): logger.debug('output: {}'.format(pprint.pformat(output))) for line in output.split('\n'): fmtline = "{}{}".format(pre, line) logger.debug(fmtline) if len(line) > 0: self.write_to_panel(fmtline, color) def write_to_panel(self, output, color=defaultTextColor): # remove not printable characters (which can be input by console input) output = re.sub(r'[^%s]' % re.escape(string.printable[:95]), "", output) logger.debug('write_to_panel: output="{}"'.format(output)) splitLines = self.linewrap.wrap(output) logger.debug('write_to_panel: splitLines="{}"'.format(splitLines)) for line in splitLines: self.textBuffer.append([line, color]) if len(self.textBuffer) > self.MAX_BUFFER_LINES: self.textBuffer.pop(0) else: self.textBufferPos += 1 self.redrawConsole()
class InventoryGui(DirectObject): directNotify = DirectNotify().newCategory('InventoryGui') HiddenPos = (0.2, 0, 0) VisiblePos = (-0.1725, 0, 0) SwitchTime = 0.3 AutoShowTime = 1.5 DELETED = False def __init__(self): DirectObject.__init__(self) self.backpack = base.localAvatar.backpack if not self.backpack: return self.backpack.loadoutGUI = self self.oneSlotPos = [(0, 0, 0)] self.twoSlotsPos = [(0, 0, 0.3), (0, 0, -0.2)] self.threeSlotsPos = [(0, 0, 0.5), (0, 0, 0), (0, 0, -0.5)] self.fourSlotPos = [(0, 0, 0.5), (0, 0, 0.15), (0, 0, -0.2), (0, 0, -0.55)] self.availableSlot = 0 self.slots = [] self.activeSlot = None self.defaultSlots = 3 self.prevSlot = None self.ammoLabel = None self.inventoryFrame = DirectFrame(parent=base.a2dRightCenter, pos=(-0.1725, 0, 0)) self.visibilityBtn = DirectButton(text='', relief=None, text_bg=(1, 1, 1, 0), parent=base.a2dRightCenter, pos=(-0.1725, 0, 0), frameSize=(-0.2, 0.2, -0.725, 0.7), clickSound=None, rolloverSound=None) self.visibilityBtn.bind(DGG.WITHIN, self.__handleVisEnter) self.visibilityBtn.bind(DGG.WITHOUT, self.__handleVisExit) self.visibilityBtn.setBin('background', 10) self.visibilityBtn = None self.visibilityBtnStatus = 0 self.switchSound = True self.switchSoundSfx = base.loadSfx( 'phase_3/audio/sfx/GUI_balloon_popup.ogg') self.visibilityFSM = ClassicFSM('InventoryGui-VisibilityFSM', [ State('off', self.enterOff, self.exitOff), State('hidden', self.enterHidden, self.exitHidden), State('hidden2visible', self.enterHidden2Visible, self.exitHidden2Visible), State('visible', self.enterVisible, self.exitVisible), State('visible2hidden', self.enterVisible2Hidden, self.exitVisible2Hidden) ], 'off', 'off') self.visibilityFSM.enterInitialState() self.visibilityFSM.request('hidden') return def enterOff(self): pass def exitOff(self): pass def enterHidden(self): self.inventoryFrame.setPos(InventoryGui.HiddenPos) self.inventoryFrame.hide() def exitHidden(self): pass def enterVisible(self, autoShow=False): self.inventoryFrame.setPos(InventoryGui.VisiblePos) self.inventoryFrame.show() if self.visibilityBtnStatus == 0: if autoShow is False: self.visibilityFSM.request('visible2hidden') def exitVisible(self): pass def enterHidden2Visible(self, autoShow=False): self.inventoryFrame.show() self.moveIval = LerpPosInterval(self.inventoryFrame, duration=InventoryGui.SwitchTime, pos=InventoryGui.VisiblePos, startPos=InventoryGui.HiddenPos) self.moveIval.setDoneEvent('hidden2visible') self.acceptOnce('hidden2visible', self.visibilityFSM.request, ['visible', [autoShow]]) self.moveIval.start() def exitHidden2Visible(self): self.ignore('hidden2visible') self.moveIval.finish() del self.moveIval def enterVisible2Hidden(self): self.moveIval = LerpPosInterval(self.inventoryFrame, duration=InventoryGui.SwitchTime, pos=InventoryGui.HiddenPos, startPos=InventoryGui.VisiblePos) self.moveIval.setDoneEvent('visible2hidden') self.acceptOnce('visible2hidden', self.visibilityFSM.request, ['hidden']) self.moveIval.start() def exitVisible2Hidden(self): self.ignore('visible2hidden') self.moveIval.finish() del self.moveIval def click_setWeapon(self, slot, cmd): self.setWeapon(slot, playSound=False) def setWeapon(self, slot, playSound=True, showUpIfHidden=False): if isinstance(slot, str): for iSlot in self.slots: if iSlot.getGag(): if iSlot.getGag().getID() == slot: slot = iSlot if self.activeSlot and slot != self.activeSlot: self.activeSlot.setOutlineImage('idle') self.prevSlot = self.activeSlot if slot.getGag() and self.backpack.getSupply(slot.getGag().getID( )) > 0 and not slot.getGag().getState() == GagState.RECHARGING: if self.activeSlot != slot: gagId = slot.getGag().getID() base.localAvatar.needsToSwitchToGag = gagId if base.localAvatar.gagsTimedOut == False: base.localAvatar.b_equip(gagId) base.localAvatar.enableGagKeys() slot.setOutlineImage('selected') self.activeSlot = slot else: if self.activeSlot == slot and slot.getGag().getState() in [ GagState.LOADED, GagState.RECHARGING ]: base.localAvatar.needsToSwitchToGag = 'unequip' if base.localAvatar.gagsTimedOut == False: base.localAvatar.b_unEquip() base.localAvatar.enableGagKeys() self.activeSlot = None self.update() if self.switchSound and playSound: base.playSfx(self.switchSoundSfx) if showUpIfHidden: base.taskMgr.remove('showUpIfHidden') self.__autoVisEnter() base.taskMgr.doMethodLater(InventoryGui.AutoShowTime, self.__autoVisExitTask, 'showUpIfHidden') return def __autoVisExitTask(self, task): if self.visibilityBtnStatus == 0: self.__handleVisExit(None, updateBtnStatus=False) return task.done def __autoVisEnter(self): self.__handleVisEnter(None, True, False) return def __handleVisEnter(self, foo, autoShow=False, updateBtnStatus=True): if updateBtnStatus: self.visibilityBtnStatus = 1 if self.visibilityFSM.getCurrentState().getName() == 'hidden': self.visibilityFSM.request('hidden2visible', [autoShow]) else: if self.visibilityFSM.getCurrentState().getName( ) == 'visible2hidden': self.visibilityFSM.request('visible') def __handleVisExit(self, foo, updateBtnStatus=True): if updateBtnStatus: self.visibilityBtnStatus = 0 base.taskMgr.remove('showUpIfHidden') if self.visibilityFSM.getCurrentState().getName() == 'visible': self.visibilityFSM.request('visible2hidden') def createGui(self): self.deleteGui() posGroup = self.threeSlotsPos if self.defaultSlots == 4: posGroup = self.fourSlotPos for slot in range(len(posGroup) + 1): if slot == 3: posGroup = self.fourSlotPos slotObj = Slot(self, slot + 1, posGroup[slot], self.inventoryFrame) self.slots.append(slotObj) if slot == 3: slotObj.hide() self.ammoLabel = DirectLabel(text='Ammo: 0', text_fg=(1, 1, 1, 1), relief=None, text_shadow=(0, 0, 0, 1), text_scale=0.08, pos=(0.2, 0, 0.35), parent=base.a2dBottomLeft) self.ammoLabel.hide() self.enableWeaponSwitch() self.resetScroll() self.update() return def deleteGui(self): self.disableWeaponSwitch() for slot in self.slots: slot.destroy() self.slots = [] if self.ammoLabel: self.ammoLabel.destroy() self.ammoLabel = None self.DELETED = True return def resetScroll(self): nextGag = 0 prevGag = -1 curGag = -1 if self.prevSlot: prevGag = self.slots.index(self.prevSlot) if self.activeSlot: curGag = self.slots.index(self.activeSlot) if curGag == len(self.slots) - 1: nextGag = 0 prevGag = curGag - 1 else: if curGag == 0: nextGag = 1 prevGag = len(self.slots) - 1 else: if curGag == -1: prevGag = len(self.slots) - 1 else: nextGag = curGag + 1 prevGag = curGag - 1 self.accept('wheel_down', self.setWeapon, extraArgs=[self.slots[nextGag], True, True]) self.accept('wheel_up', self.setWeapon, extraArgs=[self.slots[prevGag], True, True]) def update(self): if not self.backpack: return for element in [self.ammoLabel, self.inventoryFrame]: if not element: return updateSlots = list(self.slots) for slot in self.slots: gag = slot.getGag() if not gag: updateSlots.remove(slot) slot.hide() continue supply = self.backpack.getSupply(gag.getID()) index = self.slots.index(slot) if not gag and len(self.backpack.getGags()) - 1 >= index: gag = self.backpack.getGagByIndex(index) slot.setGag(gag) if self.backpack.getSupply(gag.getID( )) > 0 and not gag.getState() == GagState.RECHARGING: slot.setOutlineImage('idle') else: slot.setOutlineImage('no_ammo') elif slot == self.activeSlot: self.ammoLabel['text_fg'] = (1, 1, 1, 1) if supply > 0 and not gag.getState() == GagState.RECHARGING: slot.setOutlineImage('selected') else: if supply <= 0: self.ammoLabel['text_fg'] = (0.9, 0, 0, 1) slot.setOutlineImage('no_ammo') self.activeSlot = None self.ammoLabel.show() self.ammoLabel['text'] = 'Ammo: %s' % self.backpack.getSupply( slot.getGag().getID()) elif self.backpack.getSupply(slot.getGag().getID( )) > 0 and not gag.getState() == GagState.RECHARGING: slot.setOutlineImage('idle') else: slot.setOutlineImage('no_ammo') numSlots = len(updateSlots) posGroup = { 1: self.oneSlotPos, 2: self.twoSlotsPos, 3: self.threeSlotsPos, 4: self.fourSlotPos }.get(numSlots) for i in xrange(len(updateSlots)): updateSlots[i].setPos(posGroup[i]) updateSlots[i].show() if self.activeSlot == None: self.ammoLabel.hide() self.ammoLabel['text'] = 'Ammo: 0' self.resetScroll() return def setBackpack(self, backpack): self.backpack = backpack def updateLoadout(self): if self.backpack: loadout = self.backpack.getLoadout() if len(loadout) <= 3: self.reseatSlots() else: if len(loadout) == 4: self.reseatSlots(slots=4) for i in range(len(self.slots)): slot = self.slots[i] if i < len(loadout): slot.setGag(loadout[i]) else: slot.setGag(None) self.update() return def reseatSlots(self, slots=3): for slot in range(len(self.slots) - 1): if slots == 4: self.slots[slot].setPos(self.fourSlotPos[slot]) else: self.slots[slot].setPos(self.threeSlotsPos[slot]) def enableWeaponSwitch(self): for index in range(len(self.slots)): self.accept(str(index + 1), self.setWeapon, extraArgs=[self.slots[index], True, True]) def disableWeaponSwitch(self): for key in ['1', '2', '3', '4', 'wheel_down', 'wheel_up']: self.ignore(key) def getSlots(self): return self.slots def getActiveSlot(self): return self.activeSlot def isDeleted(self): return self.DELETED
class Window(): texture = None def __init__(self, title_text, scale, parent=None, child=None, transparent=False, owner=None): self.title_text = title_text self.scale = scale self.title_size = settings.ui_font_size self.owner = owner self.child = None self.last_pos = None self.title_color = (1, 1, 1, 1) self.title_pad = tuple(self.scale * 2) if parent is None: parent = aspect2d self.parent = parent if transparent: frameColor = (0, 0, 0, 0) else: frameColor = (0.5, 0.5, 0.5, 1) self.pad = 0 self.event_handler = DirectObject() self.button_thrower = base.buttonThrowers[0].node() self.event_handler.accept("wheel_up-up", self.mouse_wheel_event, extraArgs = [-1]) self.event_handler.accept("wheel_down-up", self.mouse_wheel_event, extraArgs = [1]) self.scrollers = [] # if Window.texture is None: # Window.texture = loader.loadTexture('textures/futureui1.png') # image_scale = (scale[0] * Window.texture.get_x_size(), 1, scale[1] * Window.texture.get_y_size()) self.frame = DirectFrame(parent=parent, state=DGG.NORMAL, frameColor=frameColor)#, image=self.texture, image_scale=image_scale) self.title_frame = DirectFrame(parent=self.frame, state=DGG.NORMAL, frameColor=(.5, .5, .5, 1)) self.title = OnscreenText(text=self.title_text, style=Plain, fg=self.title_color, scale=tuple(self.scale * self.title_size), parent=self.title_frame, pos=(0, 0), align=TextNode.ALeft, font=None, mayChange=True) bounds = self.title.getTightBounds() self.title_frame['frameSize'] = [0, bounds[1][0] - bounds[0][0] + self.title_pad[0] * 2, 0, bounds[1][2] - bounds[0][2] + self.title_pad[1] * 2] self.title.setPos( -bounds[0][0] + self.title_pad[0], -bounds[0][2] + self.title_pad[1]) self.close_frame = DirectFrame(parent=self.frame, state=DGG.NORMAL, frameColor=(.5, .5, .5, 1)) self.close = OnscreenText(text='X', style=Plain, fg=self.title_color, scale=tuple(self.scale * self.title_size), parent=self.close_frame, pos=(0, 0), align=TextNode.ACenter, font=None, mayChange=True) bounds = self.close.getTightBounds() self.close_frame['frameSize'] = [0, bounds[1][0] - bounds[0][0] + self.title_pad[0] * 2, self.title_frame['frameSize'][2], self.title_frame['frameSize'][3]] self.close.setPos( -bounds[0][0] + self.title_pad[0], -bounds[0][2] + self.title_pad[1]) self.frame.setPos(0, 0, 0) self.title_frame.bind(DGG.B1PRESS, self.start_drag) self.title_frame.bind(DGG.B1RELEASE, self.stop_drag) self.close_frame.bind(DGG.B1PRESS, self.close_window) self.set_child(child) def set_child(self, child): if child is not None: self.child = child child.reparent_to(self.frame) self.update() def update(self): if self.child is not None: frame_size = list(self.child.frame['frameSize']) if frame_size is not None: frame_size[0] -= self.pad frame_size[1] += self.pad frame_size[2] += self.pad frame_size[3] -= self.pad self.frame['frameSize'] = frame_size if self.frame['frameSize'] is not None: width = self.frame['frameSize'][1] - self.frame['frameSize'][0] title_size = self.title_frame['frameSize'] title_size[0] = 0 title_size[1] = width self.title_frame['frameSize'] = title_size self.close_frame.setPos(width - self.close_frame['frameSize'][1], 0, 0) def register_scroller(self, scroller): self.scrollers.append(scroller) def mouse_wheel_event(self, dir): # If the user is scrolling a scroll-bar, don't try to scroll the scrolled-frame too. region = base.mouseWatcherNode.getOverRegion() if region is not None: widget = base.render2d.find("**/*{0}".format(region.name)) if widget.is_empty() or isinstance(widget.node(), PGSliderBar) or isinstance(widget.getParent().node(), PGSliderBar): return # Get the mouse-position if not base.mouseWatcherNode.hasMouse(): return mouse_pos = base.mouseWatcherNode.getMouse() found_scroller = None # Determine whether any of the scrolled-frames are under the mouse-pointer for scroller in self.scrollers: bounds = scroller['frameSize'] pos = scroller.get_relative_point(base.render2d, Point3(mouse_pos.get_x() ,0, mouse_pos.get_y())) if pos.x > bounds[0] and pos.x < bounds[1] and \ pos.z > bounds[2] and pos.z < bounds[3]: found_scroller = scroller break if found_scroller is not None: if not found_scroller.verticalScroll.isHidden(): self.do_mouse_scroll(found_scroller.verticalScroll, dir, None) else: self.do_mouse_scroll(found_scroller.horizontalScroll, dir, None) def do_mouse_scroll(self, obj, dir, data): if isinstance(obj, DirectSlider) or isinstance(obj, DirectScrollBar): obj.setValue(obj.getValue() + dir * obj["pageSize"] * 0.1) def start_drag(self, event): if base.mouseWatcherNode.has_mouse(): mpos = base.mouseWatcherNode.get_mouse() self.drag_start = self.frame.parent.get_relative_point(render2d, Point3(mpos.get_x() ,0, mpos.get_y())) - self.frame.getPos() taskMgr.add(self.drag, "drag", -1) def drag(self, task): if base.mouseWatcherNode.has_mouse(): mpos = base.mouseWatcherNode.get_mouse() current_pos = self.frame.parent.get_relative_point(render2d, Point3(mpos.get_x() ,0, mpos.get_y())) self.frame.set_pos(current_pos - self.drag_start) return task.again def close_window(self, event=None): if self.owner is not None: self.owner.window_closed(self) self.destroy() def stop_drag(self, event): taskMgr.remove("drag") self.last_pos = self.frame.getPos() def destroy(self): if self.frame is not None: self.frame.destroy() self.frame = None self.scrollers = [] self.event_handler.ignore_all() def getPos(self): return self.frame.getPos() def setPos(self, pos): self.frame.setPos(pos)
class QuestPoster(DirectFrame): notify = directNotify.newCategory('QuestPoster') def __init__(self, quest, parent = aspect2d, **kw): self.quest = quest # Let's begin building the quest poster. bookModel = loader.loadModel('phase_3.5/models/gui/stickerbook_gui.bam') questCard = bookModel.find('**/questCard') optiondefs = (('relief', None, None), ('image', questCard, None), ('image_scale', (0.8, 1.0, 0.58), None), ('state', DGG.NORMAL, None)) self.defineoptions(kw, optiondefs) DirectFrame.__init__(self, relief = None) self.initialiseoptions(QuestPoster) self.questFrame = DirectFrame(parent = self, relief = None) # Quest title text self.headline = DirectLabel(parent = self.questFrame, 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)) # Quest information self.questInfo = DirectLabel(parent = self.questFrame, relief = None, text = '', text_font = CIGlobals.getToonFont(), text_fg = QuestGlobals.TEXT_COLOR, text_scale = 0.04, text_align = TextNode.ACenter, text_wordwrap = TEXT_WORDWRAP, textMayChange = 1, pos = (QuestGlobals.DEFAULT_INFO_POS)) self.questInfo.hide() self.questInfo02 = DirectLabel(parent = self.questFrame, relief = None, text = '', text_font = CIGlobals.getToonFont(), text_fg = QuestGlobals.TEXT_COLOR, text_scale = 0.04, text_align = TextNode.ACenter, text_wordwrap = TEXT_WORDWRAP, textMayChange = 1, pos = (QuestGlobals.DEFAULT_INFO2_POS)) self.questInfo02.hide() self.locationInfo = DirectLabel(parent = self.questFrame, relief = None, text = 'N/A', text_font = CIGlobals.getToonFont(), text_fg = QuestGlobals.TEXT_COLOR, text_scale = TEXT_SCALE, text_align = TextNode.ACenter, text_wordwrap = TEXT_WORDWRAP, textMayChange = 1, pos = (0, 0, -0.115)) self.locationInfo.hide() # C'mon Brian this one is obvious self.rewardText = DirectLabel(parent = self.questFrame, relief = None, text = '', text_fg = QuestGlobals.REWARD_RED, text_scale = 0.0425, text_align = TextNode.ALeft, text_wordwrap = 17.0, textMayChange = 1, pos = (-0.36, 0, -0.26)) self.rewardText.hide() self.lPictureFrame = DirectFrame(parent = self.questFrame, 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 = TEXT_SCALE, text_align = TextNode.ACenter, text_wordwrap = 11.0, pos = (QuestGlobals.DEFAULT_LEFT_PICTURE_POS), textMayChange = 1) self.lPictureFrame.hide() self.rPictureFrame = DirectFrame(parent = self.questFrame, 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 = TEXT_SCALE, text_align = TextNode.ACenter, text_wordwrap = 11.0, textMayChange = 1, pos = (QuestGlobals.DEFAULT_RIGHT_PICTURE_POS)) self.rPictureFrame['image_color'] = Vec4(*QuestGlobals.GREEN) self.rPictureFrame.hide() self.lQuestIcon = DirectFrame(parent = self.lPictureFrame, 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.lQuestIcon.setColorOff(-1) self.rQuestIcon = DirectFrame(parent = self.rPictureFrame, 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.rQuestIcon.setColorOff(-1) head = SuitBank.PennyPincher.getHead().generate() head.setDepthTest(True) head.setDepthWrite(True) head.setScale(0.25) for part in head.getChildren(): part.setDepthTest(True) part.setDepthWrite(True) self.fitGeometry(head, fFlip = 1) self.rQuestIcon['geom'] = head self.rQuestIcon['geom_scale'] = QuestGlobals.IMAGE_SCALE_SMALL self.rQuestIcon['geom_pos'] = Point3(0, 10, -0.05) self.rQuestIcon['geom_hpr'] = Point3(180, 0, 0) self.rQuestIcon.initialiseoptions(DirectFrame) self.auxText = DirectLabel(parent = self.questFrame, relief = None, text = 'Recover', text_font = CIGlobals.getToonFont(), text_scale = QuestGlobals.QPauxText, text_fg = QuestGlobals.TEXT_COLOR, text_align = TextNode.ACenter, pos = (QuestGlobals.DEFAULT_AUX_POS), textMayChange=1) self.auxText.hide() self.middleText = DirectLabel(parent = self.questFrame, relief = None, text = 'from:', text_font = CIGlobals.getToonFont(), text_scale = QuestGlobals.QPauxText, text_fg = QuestGlobals.TEXT_COLOR, text_align = TextNode.ACenter, pos = (QuestGlobals.DEFAULT_MIDDLE_POS), textMayChange=1) self.middleText.hide() self.questProgress = DirectWaitBar(parent = self.questFrame, 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), #-0.02 pos = (0, 0, -0.2425)) self.questProgress.hide() rewardFrameGeom = loader.loadModel('phase_4/models/gui/gag_shop_purchase_gui.bam') self.rewardFrame = DirectFrame(parent = self.questFrame, relief = None, geom = rewardFrameGeom.find('**/Goofys_Sign'), geom_scale = (0.615, 0, 0.4), pos = (-0.01, 0, -0.25) ) jellybeanJar = QuestGlobals.getFilmIcon() self.lRewardFrame = DirectFrame(parent = self.rewardFrame, relief = None, geom = jellybeanJar, geom_scale = QuestGlobals.TP_ACCESS_SCALE, sortOrder = 1, pos = (QuestGlobals.LEFT_TP_ACCESS_POS)) self.lRewardFrame.setBin('gui-popup', 30) self.lRewardAmt = DirectFrame(parent = self.questFrame, relief = None, geom = rewardFrameGeom.find('**/Char_Pnl'), geom_scale = (0.15, 0, 0.1275), text = '#1', text_font = CIGlobals.getToonFont(), text_scale = 0.04, text_fg = (0, 0, 0, 1), text_align = TextNode.ACenter, text_pos = (0, -0.01), sortOrder = 2, pos = (-0.285, 0, -0.255)) self.lRewardAmt.setBin('gui-popup', 40) self.rRewardFrame = DirectFrame(parent = self.rewardFrame, relief = None, geom = QuestGlobals.getJBIcon(), geom_scale = QuestGlobals.JB_JAR_SCALE, pos = QuestGlobals.RIGHT_JB_JAR_POS) self.rRewardAmt = DirectFrame(parent = self.questFrame, relief = None, geom = rewardFrameGeom.find('**/Char_Pnl'), geom_scale = (0.15, 0, 0.1275), text = '25', text_font = CIGlobals.getToonFont(), text_scale = 0.04, text_fg = (0, 0, 0, 1), text_align = TextNode.ACenter, text_pos = (0, -0.01), pos = (0.2725, 0, -0.255)) self.rRewardAmt.setBin('gui-popup', 40) rewardFrameGeom.removeNode() # This is the rotated text on the side. self.sideInfo = DirectLabel(parent = self.questFrame, 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) self.sideInfo.hide() bookModel.removeNode() self.laffMeter = None self.hide() return def handleIcon(self, objective, geom, scale, icon): 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) if isinstance(objective, VisitNPCObjective) and icon == self.rQuestIcon: icon.setPos(icon.getX(), icon.getY(), icon.getZ() + 0.05) icon.setH(180) elif isinstance(objective, CogObjective): icon.setScale(QuestGlobals.IMAGE_SCALE_SMALL) icon.setPos(icon.getX(), icon.getY(), icon.getZ() - 0.04) if icon == self.lQuestIcon: icon.setH(180) icon['geom'] = geom icon['geom_scale'] = QuestGlobals.IMAGE_SCALE_SMALL else: icon['geom'] = geom icon['geom_scale'] = scale def update(self): objective = self.quest.getCurrentObjective() objective.updateInfo() # Let's setup the quest info. self.questInfo.setPos(self.quest.getInfoPos()) self.questInfo['text'] = self.quest.getInfoText() self.questInfo02.setPos(self.quest.getInfo02Pos()) self.questInfo02['text'] = self.quest.getInfo02Text() # Let's move the picture frames to the positions we want them in. self.lPictureFrame.setPos(self.quest.getLeftPicturePos()) self.rPictureFrame.setPos(self.quest.getRightPicturePos()) editLeftAtr = isinstance(objective, VisitNPCObjective) or isinstance(objective, CogObjective) if editLeftAtr and objective.getDidEditLeft() or not editLeftAtr: geom = self.quest.getLeftIconGeom() scale = self.quest.getLeftIconScale() icon = self.lQuestIcon self.handleIcon(objective, geom, scale, icon) self.handleIcon(objective, self.quest.getRightIconGeom(), self.quest.getRightIconScale(), self.rQuestIcon) else: geom = self.quest.getRightIconGeom() scale = self.quest.getRightIconScale() icon = self.rQuestIcon self.handleIcon(objective, geom, scale, icon) self.handleIcon(objective, self.quest.getLeftIconGeom(), self.quest.getLeftIconScale(), self.lQuestIcon) if self.questInfo02['text'] == '': self.rPictureFrame.hide() self.questInfo02.hide() else: self.rPictureFrame.show() self.questInfo02.show() self.middleText['text'] = self.quest.getMiddleText() if not self.middleText['text'] == '': self.middleText.show() self.questInfo.show() self.lPictureFrame.show() # Let's set the location text. self.locationInfo['text'] = self.quest.getLocationText() self.locationInfo['text_pos'] = (0, self.quest.getLocationY()) self.locationInfo.show() # Let's set the progress bar up. self.questProgress['text'] = self.quest.getProgressText() if len(self.questProgress['text']) > 0 and not objective.finished(): self.questProgress.show() self.questProgress['range'] = objective.getNeededAmount() self.questProgress['value'] = objective.getProgress() & pow(2, 16) - 1 else: self.questProgress.hide() # Let's setup the aux text. self.auxText.setPos(self.quest.getAuxPos()) self.auxText['text'] = self.quest.getAuxText() self.auxText.show() maxHP = base.localAvatar.getMaxHealth() # Let's setup the rewards. for i in xrange(0, len(self.quest.getRewards())): reward = self.quest.getRewards()[i] frame = self.lRewardFrame if (i == 0) else self.rRewardFrame info = self.lRewardAmt if (i == 0) else self.rRewardAmt rType = reward.getType() if(rType == RewardType.JELLYBEANS): frame['pos'] = QuestGlobals.LEFT_JB_JAR_POS if (i == 0) else QuestGlobals.RIGHT_JB_JAR_POS frame['geom'] = QuestGlobals.getJBIcon() frame['geom_scale'] = QuestGlobals.JB_JAR_SCALE info['text'] = str(reward.getModifier()) elif(rType == RewardType.TELEPORT_ACCESS or rType == RewardType.GAG_FRAME): frame['pos'] = QuestGlobals.LEFT_TP_ACCESS_POS if(i == 0) else QuestGlobals.RIGHT_TP_ACCESS_POS frame['geom'] = QuestGlobals.getTPAccessIcon() if(rType == RewardType.TELEPORT_ACCESS) else QuestGlobals.getFilmIcon() frame['geom_scale'] = QuestGlobals.TP_ACCESS_SCALE info['text'] = 'N/A' if(rType == RewardType.TELEPORT_ACCESS) else '#%s' % (str(reward.getModifier())) elif(rType == RewardType.LAFF_POINTS): frame.initialiseoptions(DirectFrame) r, g, b, _ = base.localAvatar.getHeadColor() pos = QuestGlobals.LEFT_LAFF_METER_POS if(i == 0) else QuestGlobals.RIGHT_LAFF_METER_POS # Create the laff meter with the new health. hp = maxHP + reward.getModifier() laffMeter = LaffOMeter() laffMeter.generate(r, g, b, base.localAvatar.getAnimal(), maxHP = hp, initialHP = hp) # Let's position the laff meter. frame['geom'] = laffMeter frame['geom_scale'] = QuestGlobals.LAFF_METER_SCALE frame.setPos(pos) info['text'] = '+%s' % (str(reward.getModifier())) laffMeter.destroy() laffMeter = None # Hide or show the other reward depending on if there's 2 rewards. if(len(self.quest.getRewards()) == 1): self.rRewardFrame.hide() self.rRewardAmt.hide() else: self.rRewardFrame.show() self.rRewardAmt.show() if objective.finished(): self.setColor(Vec4(*QuestGlobals.LIGHT_GREEN)) self.sideInfo['text'] = 'Completed!' self.sideInfo.show() self.questInfo.initialiseoptions(DirectLabel) self.questInfo02.initialiseoptions(DirectLabel) self.locationInfo.initialiseoptions(DirectLabel) self.lPictureFrame.initialiseoptions(DirectFrame) self.rPictureFrame.initialiseoptions(DirectFrame) self.lQuestIcon.initialiseoptions(DirectFrame) self.rQuestIcon.initialiseoptions(DirectFrame) self.auxText.initialiseoptions(DirectLabel) self.middleText.initialiseoptions(DirectLabel) self.sideInfo.initialiseoptions(DirectLabel) self.lPictureFrame['image_color'] = self.quest.getPictureFrameColor() self.rPictureFrame['image_color'] = self.quest.getPictureFrameColor() 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): self._deleteGeoms() DirectFrame.destroy(self) def _deleteGeoms(self): for icon in (self.lQuestIcon, self.rQuestIcon): geom = icon['geom'] if geom and hasattr(geom, 'delete'): geom.delete() def getQuest(self): return self.quest
class panda3dIOClass( DirectObject.DirectObject ): # set gui key to None if you want to call toggleConsole from outside this class gui_key = CONSOLE_TOGGLE_KEY autocomplete_key = CONSOLE_AUTOCOMPLETE_KEY autohelp_key = CONSOLE_AUTOHELP_KEY scroll_up_repeat_key = CONSOLE_SCROLL_UP_KEY + "-repeat" scroll_down_repeat_key = CONSOLE_SCROLL_DOWN_KEY + "-repeat" # change size of text and number of characters on one line # scale of frame ( must be small (0.0x) scale = PANDA3D_CONSOLE_SCALE # to define a special font, if loading fails the default font is used (without warning) font = PANDA3D_CONSOLE_FONT fontWidth = PANDA3D_CONSOLE_FONT_WIDTH # frame position and size (vertical & horizontal) h_pos = PANDA3D_CONSOLE_HORIZONTAL_POS h_size = PANDA3D_CONSOLE_HORIZONTAL_SIZE # v_size + v_pos should not exceed 2.0, else parts of the interface will not be visible # space above the frame ( must be below 2.0, best between 0.0 and 1.0 ) v_pos = PANDA3D_CONSOLE_VERTICAL_POS # vertical size of the frame ( must be at max 2.0, best between 0.5 and 2.0 ) v_size = PANDA3D_CONSOLE_VERTICAL_SIZE linelength = int((h_size/scale - 5) / fontWidth) print "max number of characters on a length:", linelength numlines = int(v_size/scale - 5) defaultTextColor = (0.0,0.0,0.0,1.0) autoCompleteColor = (0.9,0.9,0.9,1.0) def __init__( self, parent ): self.parent = parent # line wrapper self.linewrap = textwrap.TextWrapper() self.linewrap.width = self.linelength # calculate window size left = (self.h_pos) / self.scale right = (self.h_pos + self.h_size) / self.scale bottom = (self.v_pos) / self.scale top = (self.v_pos + self.v_size) /self.scale # panda3d interface self.consoleFrame = DirectFrame ( relief = DGG.GROOVE , frameColor = (200, 200, 200, 0.5) , scale=self.scale , frameSize = (0, self.h_size / self.scale, 0, self.v_size / self.scale) ) self.windowEvent( base.win ) # try to load the defined font try: fixedWidthFont = loader.loadFont(self.font) except: print "pandaInteractiveConsole.py :: could not load the defined font %s" % str(self.font) fixedWidthFont = DGG.getDefaultFont() # if font is not valid use default font if not fixedWidthFont.isValid(): if self.font is None: print "pandaInteractiveConsole.py :: could not load the defined font %s" % str(self.font) fixedWidthFont = DGG.getDefaultFont() # text entry line self.consoleEntry = DirectEntry ( self.consoleFrame , text = "" , command = self.onEnterPress , width = self.h_size/self.scale - 2 , pos = (1, 0, 1.5) , initialText = "" , numLines = 1 , focus = 1 , entryFont = fixedWidthFont) # output lines self.consoleOutputList = list() for i in xrange( self.numlines ): label = OnscreenText( parent = self.consoleFrame , text = "" , pos = (1, -i+3+self.numlines) , align=TextNode.ALeft , mayChange=1 , scale=1.0 , fg = self.defaultTextColor ) label.setFont( fixedWidthFont ) self.consoleOutputList.append( label ) # list of the last commands of the user self.userCommandList = list() self.userCommandListLength = 100 for i in xrange(self.userCommandListLength): self.userCommandList.append('') self.userCommandPos = 0 # buffer for data self.textBuffer = list() self.textBufferLength = 1000 for i in xrange(self.textBufferLength): self.textBuffer.append(['', DEFAULT_COLOR]) self.textBufferPos = self.textBufferLength-self.numlines # toggle the window at least once to activate the events self.toggleConsole() self.toggleConsole() # call the help-command on start self.onEnterPress("help") # write a string to the panda3d console def write( self, printString, color=defaultTextColor ): # remove not printable characters (which can be input by console input) printString = re.sub( r'[^%s]' % re.escape(string.printable[:95]), "", printString) splitLines = self.linewrap.wrap(printString) for line in splitLines: self.textBuffer.append( [line, color] ) self.textBuffer.pop(0) self.updateOutput() def updateOutput( self ): for lineNumber in xrange(self.numlines): lineText, color = self.textBuffer[lineNumber + self.textBufferPos] self.consoleOutputList[lineNumber].setText( lineText ) self.consoleOutputList[lineNumber]['fg'] = color # toggle the gui console def toggleConsole( self ): self.consoleFrame.toggleVis() hidden = self.consoleFrame.isHidden() self.consoleEntry['focus'] != hidden if hidden: self.ignoreAll() self.accept( self.gui_key, self.toggleConsole ) #playerController.enableInput() #unpause("v") else: self.ignoreAll() #playerController.disableInput() #pause("v") self.accept( CONSOLE_SCROLL_UP_KEY, self.scroll, [-5] ) self.accept( self.scroll_up_repeat_key, self.scroll, [-5] ) self.accept( CONSOLE_SCROLL_DOWN_KEY, self.scroll, [5] ) self.accept( self.scroll_down_repeat_key, self.scroll, [5] ) self.accept( 'window-event', self.windowEvent) self.accept( CONSOLE_PREVIOUS_COMMAND_KEY , self.scrollCmd, [ 1] ) self.accept( CONSOLE_NEXT_COMMAND_KEY, self.scrollCmd, [-1] ) self.accept( self.gui_key, self.toggleConsole ) #self.accept( self.autocomplete_key, self.autocomplete ) #self.accept( self.autohelp_key, self.autohelp ) # accept v, c and x, where c & x copy's the whole console text #messenger.toggleVerbose() #for osx use ('meta') if sys.platform == 'darwin': self.accept( 'meta', self.unfocus ) self.accept( 'meta-up', self.focus ) self.accept( 'meta-c', self.copy ) self.accept( 'meta-x', self.cut ) self.accept( 'meta-v', self.paste ) #for windows use ('control') if sys.platform == 'win32' or sys.platform == 'linux2': self.accept( 'control', self.unfocus ) self.accept( 'control-up', self.focus ) self.accept( 'control-c', self.copy ) self.accept( 'control-x', self.cut ) self.accept( 'control-v', self.paste ) # def autohelp( self ): # currentText = self.consoleEntry.get() # currentPos = self.consoleEntry.guiItem.getCursorPosition() # self.parent.autohelp( currentText, currentPos ) def focus( self ): self.consoleEntry['focus'] = 1 def unfocus( self ): self.consoleEntry['focus'] = 0 def copy( self ): copy = self.consoleEntry.get() clipboard.setText( copy ) def paste( self ): oldCursorPos = self.consoleEntry.guiItem.getCursorPosition() clipboardText = clipboard.getText() # compose new text line oldText = self.consoleEntry.get() newText = oldText[0:oldCursorPos] + clipboardText + oldText[oldCursorPos:] clipboardTextLines = newText.split(os.linesep) for i in xrange( len(clipboardTextLines)-1 ): currentLine = clipboardTextLines[i] # we only want printable characters currentLine = re.sub( r'[^' + re.escape(string.printable[:95]) + ']', "", currentLine) # set new text and position self.consoleEntry.set( currentLine ) self.onEnterPress( currentLine ) currentLine = clipboardTextLines[-1] currentLine = re.sub( r'[^' + re.escape(string.printable[:95]) + ']', "", currentLine) self.consoleEntry.set( currentLine ) self.consoleEntry.setCursorPosition( len(self.consoleEntry.get()) ) self.focus() def cut( self ): clipboard.setText( self.consoleEntry.get() ) self.consoleEntry.enterText('') self.focus() def scroll( self, step ): self.textBufferPos += step self.textBufferPos = min( self.textBufferLength-self.numlines, max( 0, self.textBufferPos ) ) self.updateOutput() def scrollCmd( self, step ): oldCmdPos = self.userCommandPos self.userCommandPos += step self.userCommandPos = min( self.userCommandListLength-1, max( 0, self.userCommandPos ) ) self.userCommandList[oldCmdPos] = self.consoleEntry.get() newCmd = self.userCommandList[self.userCommandPos] self.consoleEntry.set( newCmd ) self.consoleEntry.setCursorPosition( len(newCmd) ) def onEnterPress( self, textEntered ): # set to last message self.textBufferPos = self.textBufferLength-self.numlines # clear line self.consoleEntry.enterText('') self.focus() # add text entered to user command list & remove oldest entry self.userCommandList.insert( 1, textEntered ) self.userCommandList[0] = '' self.userCommandList.pop( -1 ) self.userCommandPos = 0 # call the interpreter to handle the input interpreter = cliClass() result = interpreter.interpreter(textEntered) # write the entered text to the output self.write(textEntered, (0.0, 0.0, 1, 1)) print textEntered # write each line seperately to the output for line in result.split('\n'): line = " " + line self.write(line, (0, 0, 0, 1)) print line def windowEvent( self, window ): """ This is a special callback. It is called when the panda window is modified. """ wp = window.getProperties() width = wp.getXSize() / float(wp.getYSize()) height = wp.getYSize() / float(wp.getXSize()) if width > height: height = 1.0 else: width = 1.0 # aligned to center consolePos = Vec3(-self.h_size/2, 0, -self.v_size/2) # aligned to left bottom #consolePos = Vec3(-width+self.h_pos, 0, -height+self.v_pos) # aligned to right top #consolePos = Vec3(width-self.h_size, 0, height-self.v_size) # set position self.consoleFrame.setPos( consolePos )
class ToonPanel(DirectFrame): notify = directNotify.newCategory("ToonPanel") animal2HeadData = { 'dog': (0.125, 0.04), 'duck': (0.1, 0.025), 'cat': (0.115, 0.04), 'rabbit': (0.115, 0.04), 'horse': (0.115, 0.06), 'monkey': (0.115, 0.06), 'pig': (0.115, 0.07), 'mouse': (0.09, 0.02), 'bear': (0.125, 0.05) } State2Text = { 'status': ('Seeing if %s is available...', '%s is busy right now; try again later.'), 'teleport': ('Trying to go to %s...', 'Could not go to %s.'), 'friend': ('Asking %s to be your friend...', '%s said no, thank you.', 'You are now friends with %s!'), 'remove': ('Are you sure you want to remove %s from your friends list?', '%s left your friends list.') } def __init__(self): DirectFrame.__init__(self, scale=1.2) self['image'] = DGG.getDefaultDialogGeom() self['image_hpr'] = (0, 0, -90) self['image_scale'] = (0.67, 0.9, 0.325) self['image_color'] = (1, 1, 0.75, 1) self['image_pos'] = (0, 0, -0.09) self['relief'] = None self.reparentTo(base.a2dTopRight) self.setPos(-0.235, 0.0, -0.325) self.hide() self.head = None self.laffMeter = None self.exitButton = None self.friendButton = None self.teleportButton = None self.whisperButton = None self.nameText = None self.actionFrame = None self.actionFrameText = None self.actionFrameButton = None self.actionFrameButton2 = None self.avatarInfo = None self.action = None self.locationText = None self.shardText = None self.detailsExitBtn = None self.fsm = ClassicFSM.ClassicFSM('ToonPanel', [ State.State('off', self.enterOff, self.exitOff), State.State('waitOnAvatarInfoResponse', self.enterWaitOnAvatarInfoResponse, self.exitWaitOnAvatarInfoResponse, ['panel']), State.State('panel', self.enterPanel, self.exitPanel, ['off']) ], 'off', 'off') self.fsm.enterInitialState() self.actionFSM = ClassicFSM.ClassicFSM('ToonPanelActionFSM', [ State.State('off', self.enterOff, self.exitOff), State.State( 'waitOnAvatarStatusResponse', self.enterWaitOnAvatarStatusResponse, self.exitWaitOnAvatarStatusResponse, [ 'waitOnAvatarTeleportResponse', 'waitOnAvatarFriendListResponse', 'avatarBusy', 'off' ]), State.State('avatarBusy', self.enterAvatarBusy, self.exitAvatarBusy, ['off']), State.State('waitOnAvatarTeleportResponse', self.enterWaitOnAvatarTeleportResponse, self.exitWaitOnAvatarTeleportResponse, ['unableToTP']), State.State('unableToTP', self.enterUnableToTP, self.exitUnableToTP, ['off']), State.State('waitOnAvatarFriendListResponse', self.enterWaitOnAvatarFriendListResponse, self.exitWaitOnAvatarFriendListResponse, ['fRequestA', 'fRequestR']), State.State('fRequestA', self.enterFriendRequestAccepted, self.exitFriendRequestAccepted, ['off']), State.State('fRequestR', self.enterFriendRequestRejected, self.exitFriendRequestRejected, ['off']), State.State('removeFriendConfirm', self.enterRemoveFriendConfirm, self.exitRemoveFriendConfirm, ['off', 'removedFriend']), State.State('removedFriend', self.enterRemovedFriend, self.exitRemovedFriend, ['off']) ], 'off', 'off') self.actionFSM.enterInitialState() def makeMoreDetailsPanel(self): self.actionFSM.request('off') self.removeMoreDetailsPanel() self.removeActionPanel() self.makeActionPanel() zoneId = self.avatarInfo[5] shardId = self.avatarInfo[6] isOnline = self.avatarInfo[7] shardName = 'Unknown District' hoodName = ZoneUtil.getHoodId(zoneId, 1) for district in base.cr.activeDistricts.values(): if district.doId == shardId: shardName = district.getDistrictName() break if not isOnline: hoodName = 'Offline' shardName = 'Offline' self.locationText = OnscreenText('Location: {0}'.format(hoodName), parent=self.actionFrame, pos=(-0.3, 0.05, 0), align=TextNode.ALeft, scale=0.04) self.shardText = OnscreenText('District: {0}'.format(shardName), parent=self.actionFrame, pos=(-0.3, 0.0, 0), align=TextNode.ALeft, scale=0.04) self.detailsExitBtn = DirectButton(geom=CIGlobals.getCancelBtnGeom(), parent=self.actionFrame, relief=None, scale=0.8, pos=(-0.3, 0.0, -0.175), command=self.removeMoreDetailsPanel) def removeMoreDetailsPanel(self): if self.locationText: self.locationText.destroy() self.locationText = None if self.shardText: self.shardText.destroy() self.shardText = None if self.detailsExitBtn: self.detailsExitBtn.destroy() self.detailsExitBtn = None self.removeActionPanel() def maybeUpdateFriendButton(self): if self.friendButton: if self.avatarInfo: if not self.avatarInfo[0] in base.localAvatar.friends: self.friendButton['text'] = 'Add Friend' self.friendButton['extraArgs'] = [ 'waitOnAvatarFriendListResponse' ] else: self.friendButton['text'] = 'Remove Friend' self.friendButton['extraArgs'] = ['removeFriendConfirm'] def enterOff(self): pass def exitOff(self): pass def enterUnableToTP(self): pass def exitUnableToTP(self): pass def enterWaitOnAvatarTeleportResponse(self): self.setActionText(self.State2Text['teleport'][0] % self.getAvatarName()) self.makeButtons('Cancel') self.acceptOnce('gotAvatarTeleportResponse', self.handleTeleportResponse) base.cr.friendsManager.d_iWantToTeleportToAvatar(self.avatarInfo[0]) def handleTeleportResponse(self, avatarId, shardId, zoneId): if self.avatarInfo[0] == avatarId: requestStatus = {} whereName = ZoneUtil.getWhereName(zoneId) loaderName = ZoneUtil.getLoaderName(zoneId) requestStatus['zoneId'] = zoneId if base.localAvatar.parentId == shardId: requestStatus['shardId'] = None else: requestStatus['shardId'] = shardId requestStatus['hoodId'] = ZoneUtil.getHoodId(zoneId, 1) requestStatus['where'] = whereName requestStatus['loader'] = loaderName requestStatus['how'] = 'teleportIn' requestStatus['avId'] = avatarId base.cr.playGame.getPlace().fsm.request('teleportOut', [requestStatus]) self.cleanup() def exitWaitOnAvatarTeleportResponse(self): self.ignore('gotAvatarTeleportResponse') self.clearActionText() self.clearActionButtons() def setActionText(self, text): self.actionFrameText.setText(text) def clearActionText(self): self.actionFrameText.setText("") def makeButtons(self, button1, button2=None): button2GeomFunc = { 'Cancel': CIGlobals.getCancelBtnGeom, 'No': CIGlobals.getCancelBtnGeom, 'Okay': CIGlobals.getOkayBtnGeom, 'Yes': CIGlobals.getOkayBtnGeom } if button1 and not button2: button1Pos = (0, 0, -0.1) elif button1 and button2: button1Pos = (-0.1, 0, -0.1) button2Pos = (0.1, 0, -0.1) if button1: self.actionFrameButton = DirectButton( text=button1, geom=button2GeomFunc[button1](), parent=self.actionFrame, pos=button1Pos, text_scale=0.045, text_pos=(0, -0.08), command=self.actionButtonPressed, extraArgs=[1], relief=None, geom_scale=0.75) if button2: self.actionFrameButton2 = DirectButton( text=button2, geom=button2GeomFunc[button2](), parent=self.actionFrame, pos=button2Pos, text_scale=0.045, text_pos=(0, -0.08), command=self.actionButtonPressed, extraArgs=[2], relief=None, geom_scale=0.75) def actionButtonPressed(self, buttonNum): currentState = self.actionFSM.getCurrentState().getName() if buttonNum == 1: if currentState in [ 'waitOnAvatarStatusResponse', 'waitOnAvatarTeleportResponse', 'waitOnAvatarFriendListResponse', 'avatarBusy', 'unableToTP', 'fRequestA', 'fRequestR', 'removeFriendConfirm', 'removedFriend' ]: if currentState == 'waitOnAvatarFriendListResponse': base.cr.friendsManager.d_iCancelledFriendRequest( self.avatarInfo[0]) elif currentState == 'removeFriendConfirm': self.actionFSM.request('removedFriend') return self.actionFSM.request('off') self.removeActionPanel() self.action = None elif buttonNum == 2: self.actionFSM.request('off') self.removeActionPanel() self.action = None def clearActionButtons(self): if self.actionFrameButton2: self.actionFrameButton2.destroy() self.actionFrameButton2 = None if self.actionFrameButton: self.actionFrameButton.destroy() self.actionFrameButton = None def enterAvatarBusy(self): self.setActionText(self.State2Text['status'][1] % self.getAvatarName()) self.makeButtons('Okay') def exitAvatarBusy(self): self.clearActionText() self.clearActionButtons() def getAvatarName(self): if self.avatarInfo: return self.avatarInfo[1] def enterWaitOnAvatarStatusResponse(self): self.acceptOnce('gotAvatarStatus', self.handleAvatarStatusResponse) base.cr.friendsManager.d_requestAvatarStatus(self.avatarInfo[0]) self.setActionText(self.State2Text['status'][0] % self.getAvatarName()) self.makeButtons('Cancel') def handleAvatarStatusResponse(self, avatarId, status): if avatarId == self.avatarInfo[0]: # Busy if status == 1: self.actionFSM.request('avatarBusy') # Not busy else: self.actionFSM.request(self.action) else: self.acceptOnce('gotAvatarStatus', self.handleAvatarStatusResponse) def exitWaitOnAvatarStatusResponse(self): self.ignore('gotAvatarStatus') self.clearActionText() self.clearActionButtons() def enterWaitOnAvatarFriendListResponse(self): self.acceptOnce('friendRequestAccepted', self.handleFriendRequestAccepted) self.acceptOnce('friendRequestRejected', self.handleFriendRequestRejected) base.cr.friendsManager.d_askAvatarToBeFriends(self.avatarInfo[0]) self.setActionText(self.State2Text['friend'][0] % self.getAvatarName()) self.makeButtons('Cancel') def handleFriendRequestAccepted(self): self.actionFSM.request('fRequestA') def handleFriendRequestRejected(self): self.actionFSM.request('fRequestR') def exitWaitOnAvatarFriendListResponse(self): self.ignore('friendRequestAccepted') self.ignore('friendRequestRejected') self.clearActionText() self.clearActionButtons() def enterFriendRequestAccepted(self): self.setActionText(self.State2Text['friend'][2] % self.getAvatarName()) self.makeButtons('Okay') def exitFriendRequestAccepted(self): self.clearActionText() self.clearActionButtons() def enterFriendRequestRejected(self): self.setActionText(self.State2Text['friend'][1] % self.getAvatarName()) self.makeButtons('Okay') def exitFriendRequestRejected(self): self.clearActionText() self.clearActionButtons() def enterRemoveFriendConfirm(self): self.setActionText(self.State2Text['remove'][0] % self.getAvatarName()) self.makeButtons('Yes', 'No') def exitRemoveFriendConfirm(self): self.clearActionText() self.clearActionButtons() def enterRemovedFriend(self): base.cr.friendsManager.d_iRemovedFriend(self.avatarInfo[0]) self.setActionText(self.State2Text['remove'][1] % self.getAvatarName()) self.makeButtons('Okay') def exitRemovedFriend(self): self.clearActionText() self.clearActionButtons() def makeActionPanel(self): self.actionFrame = DirectFrame(image=DGG.getDefaultDialogGeom(), image_scale=(0.7, 0.5, 0.45), image_color=(1, 1, 0.75, 1), relief=None) self.actionFrame.reparentTo(base.a2dTopRight) self.actionFrame.setPos(-0.815, 0, -0.31) self.actionFrameText = OnscreenText(text="", parent=self.actionFrame, scale=0.05, wordwrap=12, pos=(0, 0.1)) def removeActionPanel(self): self.clearActionButtons() if self.actionFrameText: self.actionFrameText.destroy() self.actionFrameText = None if self.actionFrame: self.actionFrame.destroy() self.actionFrame = None def doAction(self, action): self.action = action self.actionFSM.requestFinalState() self.removeMoreDetailsPanel() self.removeActionPanel() self.makeActionPanel() if action != 'removeFriendConfirm': self.actionFSM.request('waitOnAvatarStatusResponse') else: self.actionFSM.request(action) def enterWaitOnAvatarInfoResponse(self): self.label = OnscreenText(text='Retrieving Toon\ndetails...', parent=self, scale=0.04) self.acceptOnce('avatarInfoResponse', self.handleAvatarInfoResponse) base.cr.friendsManager.d_requestAvatarInfo(self.avatarInfo[0]) def handleAvatarInfoResponse(self, name, dna, maxHealth, health, zoneId, shardId, isOnline, adminToken): if self.avatarInfo: self.avatarInfo.append(name) self.avatarInfo.append(dna) self.avatarInfo.append(maxHealth) self.avatarInfo.append(health) self.avatarInfo.append(zoneId) self.avatarInfo.append(shardId) self.avatarInfo.append(isOnline) self.avatarInfo.append(adminToken) self.fsm.request('panel') def exitWaitOnAvatarInfoResponse(self): self.label.destroy() del self.label self.ignore('avatarInfoResponse') def makePanel(self, avId): if self.avatarInfo: if self.avatarInfo[0] == avId: # They clicked on the same toon without closing the # previous panel, maybe they're spamming? return self.cleanup() base.localAvatar.hideFriendButton() self.show() self.avatarInfo = [] self.avatarInfo.append(avId) self.fsm.request('waitOnAvatarInfoResponse') def exitClicked(self): self.cleanup() base.localAvatar.showFriendButton() def cleanup(self): self.actionFSM.requestFinalState() self.fsm.requestFinalState() self.avatarInfo = None def enterPanel(self): adminToken = self.avatarInfo[8] text_color = CIGlobals.TextColorByAdminToken[adminToken] self.nameText = OnscreenText(text=self.avatarInfo[1], parent=self, pos=(0, 0.2), scale=0.035, wordwrap=8, fg=text_color) self.nameText.setBin('gui-popup', 60) dna = ToonDNA.ToonDNA() dna.setDNAStrand(self.avatarInfo[2]) self.head = ToonHead.ToonHead(base.cr) self.head.generateHead(dna.gender, dna.animal, dna.head, 1) self.head.setHeadColor(dna.headcolor) self.head.reparentTo(self) self.head.setDepthWrite(1) self.head.setDepthTest(1) self.head.setH(180) self.head.setScale(self.animal2HeadData[dna.animal][0]) self.head.setZ(self.animal2HeadData[dna.animal][1]) self.laffMeter = LaffOMeter() r, g, b, _ = dna.headcolor self.laffMeter.generate(r, g, b, dna.animal, self.avatarInfo[3], self.avatarInfo[4]) self.laffMeter.reparentTo(self) self.laffMeter.setBin('gui-popup', 60) self.laffMeter.setScale(0.045) self.laffMeter.setPos(0, 0, -0.1) self.friendButton = DirectButton( geom=CIGlobals.getDefaultBtnGeom(), text="Add Friend", scale=0.58, relief=None, text_scale=0.058, geom_scale=(1.25, 0, 0.9), text_pos=(0, -0.0125), parent=self, pos=(0, 0, -0.12), command=self.doAction, extraArgs=['waitOnAvatarFriendListResponse']) self.friendButton.setPos(0, 0.0, -0.225) self.maybeUpdateFriendButton() self.teleportButton = DirectButton( geom=CIGlobals.getDefaultBtnGeom(), text="Teleport", scale=0.58, relief=None, text_scale=0.058, geom_scale=(1.25, 0, 0.9), text_pos=(0, -0.0125), parent=self, pos=(0, 0, -0.12), command=self.doAction, extraArgs=['waitOnAvatarTeleportResponse']) self.teleportButton.setPos(0, 0, -0.275) self.whisperButton = DirectButton( geom=CIGlobals.getDefaultBtnGeom(), text="Whisper", scale=0.58, relief=None, text_scale=0.058, geom_scale=(1.25, 0, 0.9), text_pos=(0, -0.0125), parent=self, pos=(0, 0, -0.12), command=base.localAvatar.handleClickedWhisper, extraArgs=[self.avatarInfo[1], self.avatarInfo[0], 1]) self.whisperButton.setPos(0, 0, -0.325) self.exitButton = DirectButton(geom=CIGlobals.getCancelBtnGeom(), parent=self, relief=None, scale=0.6, pos=(0, 0.0, -0.39), command=self.exitClicked) gui = loader.loadModel("phase_3.5/models/gui/friendslist_gui.bam") self.moreDetailsBtn = DirectButton( geom=(gui.find('**/Horiz_Arrow_UP'), gui.find('**/Horiz_Arrow_DN'), gui.find('**/Horiz_Arrow_Rllvr'), gui.find('**/Horiz_Arrow_UP')), relief=None, parent=self, pos=(-0.127, 0.0, -0.39), geom_hpr=(180, 0, 0), command=self.makeMoreDetailsPanel, scale=0.77, text=('', 'More Details', 'More Details', ''), text_scale=0.045, text_fg=(1, 1, 1, 1), text_shadow=(0, 0, 0, 1), text_pos=(-0.08, -0.01), text_align=TextNode.ARight) def exitPanel(self): if self.actionFSM.getCurrentState().getName( ) == 'waitOnAvatarFriendListResponse': if self.avatarInfo: base.cr.friendsManager.d_iCancelledFriendRequest( self.avatarInfo[0]) self.actionFSM.requestFinalState() self.action = None self.avatarInfo = None self.removeActionPanel() self.removeMoreDetailsPanel() self.hide() if self.nameText: self.nameText.destroy() self.nameText = None if self.head: self.head.removeNode() self.head.delete() self.head = None if self.laffMeter: self.laffMeter.disable() self.laffMeter.delete() self.laffMeter = None if self.friendButton: self.friendButton.destroy() self.friendButton = None if self.teleportButton: self.teleportButton.destroy() self.teleportButton = None if self.whisperButton: self.whisperButton.destroy() self.whisperButton = None if self.exitButton: self.exitButton.destroy() self.exitButton = None if self.moreDetailsBtn: self.moreDetailsBtn.destroy() self.moreDetailsBtn = None
def setPos(self, *args, **kwargs): DirectFrame.setPos(self, *args, **kwargs) self.resetArcBall()
class Transitions: # These may be reassigned before the fade or iris transitions are # actually invoked to change the models that will be used. IrisModelName = "models/misc/iris" FadeModelName = "models/misc/fade" def __init__(self, loader, model=None, scale=3.0, pos=Vec3(0, 0, 0)): self.transitionIval = None self.letterboxIval = None self.iris = None self.fade = None self.letterbox = None self.fadeModel = model self.imagePos = pos if model: self.alphaOff = Vec4(1, 1, 1, 0) self.alphaOn = Vec4(1, 1, 1, 1) model.setTransparency(1) self.lerpFunc = LerpColorScaleInterval else: self.alphaOff = Vec4(0, 0, 0, 0) self.alphaOn = Vec4(0, 0, 0, 1) self.lerpFunc = LerpColorInterval self.irisTaskName = "irisTask" self.fadeTaskName = "fadeTask" self.letterboxTaskName = "letterboxTask" def __del__(self): if self.fadeModel: self.fadeModel.removeNode() self.fadeModel = None ################################################## # Fade ################################################## # We can set a custom model for the fade before using it for the first time def setFadeModel(self, model, scale=1.0): self.fadeModel = model # We have to change some default parameters for a custom fadeModel self.alphaOn = Vec4(1, 1, 1, 1) # Reload fade if its already been created if self.fade: self.fade.destroy() self.fade = None self.loadFade() def loadFade(self): if self.fade is None: # We create a DirectFrame for the fade polygon, instead of # simply loading the polygon model and using it directly, # so that it will also obscure mouse events for objects # positioned behind it. self.fade = DirectFrame( parent=hidden, guiId='fade', relief=None, image=self.fadeModel, image_scale=(4, 2, 2), state=DGG.NORMAL, ) if not self.fadeModel: # No fade model was given, so we make this the fade model. self.fade["relief"] = DGG.FLAT self.fade["frameSize"] = (-2, 2, -1, 1) self.fade["frameColor"] = (0, 0, 0, 1) self.fade.setTransparency(TransparencyAttrib.MAlpha) self.fade.setBin('unsorted', 0) self.fade.setColor(0, 0, 0, 0) def getFadeInIval(self, t=0.5, finishIval=None): """ Returns an interval without starting it. This is particularly useful in cutscenes, so when the cutsceneIval is escaped out of we can finish the fade immediately """ #self.noTransitions() masad: this creates a one frame pop, is it necessary? self.loadFade() transitionIval = Sequence( Func(self.fade.reparentTo, aspect2d, DGG.FADE_SORT_INDEX), Func(self.fade.showThrough ), # in case aspect2d is hidden for some reason self.lerpFunc( self.fade, t, self.alphaOff, # self.alphaOn, ), Func(self.fade.detachNode), name=self.fadeTaskName, ) if finishIval: transitionIval.append(finishIval) return transitionIval def getFadeOutIval(self, t=0.5, finishIval=None): """ Create a sequence that lerps the color out, then parents the fade to hidden """ self.noTransitions() self.loadFade() transitionIval = Sequence( Func(self.fade.reparentTo, aspect2d, DGG.FADE_SORT_INDEX), Func(self.fade.showThrough ), # in case aspect2d is hidden for some reason self.lerpFunc( self.fade, t, self.alphaOn, # self.alphaOff, ), name=self.fadeTaskName, ) if finishIval: transitionIval.append(finishIval) return transitionIval def fadeIn(self, t=0.5, finishIval=None): """ Play a fade in transition over t seconds. Places a polygon on the aspect2d plane then lerps the color from black to transparent. When the color lerp is finished, it parents the fade polygon to hidden. """ gsg = base.win.getGsg() if gsg: # If we're about to fade in from black, go ahead and # preload all the textures etc. base.graphicsEngine.renderFrame() render.prepareScene(gsg) render2d.prepareScene(gsg) if (t == 0): # Fade in immediately with no lerp #print "transitiosn: fadeIn 0.0" self.noTransitions() self.loadFade() self.fade.detachNode() else: # Create a sequence that lerps the color out, then # parents the fade to hidden self.transitionIval = self.getFadeInIval(t, finishIval) self.transitionIval.start() def fadeOut(self, t=0.5, finishIval=None): """ Play a fade out transition over t seconds. Places a polygon on the aspect2d plane then lerps the color from transparent to full black. When the color lerp is finished, it leaves the fade polygon covering the aspect2d plane until you fadeIn or call noFade. lerp """ if (t == 0): # Fade out immediately with no lerp self.noTransitions() self.loadFade() self.fade.reparentTo(aspect2d, DGG.FADE_SORT_INDEX) self.fade.setColor(self.alphaOn) elif ConfigVariableBool('no-loading-screen', False): if finishIval: self.transitionIval = finishIval self.transitionIval.start() else: # Create a sequence that lerps the color out, then # parents the fade to hidden self.transitionIval = self.getFadeOutIval(t, finishIval) self.transitionIval.start() def fadeOutActive(self): return self.fade and self.fade.getColor()[3] > 0 def fadeScreen(self, alpha=0.5): """ Put a semitransparent screen over the camera plane to darken out the world. Useful for drawing attention to a dialog box for instance """ #print "transitiosn: fadeScreen" self.noTransitions() self.loadFade() self.fade.reparentTo(aspect2d, DGG.FADE_SORT_INDEX) self.fade.setColor(self.alphaOn[0], self.alphaOn[1], self.alphaOn[2], alpha) def fadeScreenColor(self, color): """ Put a semitransparent screen over the camera plane to darken out the world. Useful for drawing attention to a dialog box for instance """ #print "transitiosn: fadeScreenColor" self.noTransitions() self.loadFade() self.fade.reparentTo(aspect2d, DGG.FADE_SORT_INDEX) self.fade.setColor(color) def noFade(self): """ Removes any current fade tasks and parents the fade polygon away """ #print "transitiosn: noFade" if self.transitionIval: self.transitionIval.pause() self.transitionIval = None if self.fade: # Make sure to reset the color, since fadeOutActive() is looking at it self.fade.setColor(self.alphaOff) self.fade.detachNode() def setFadeColor(self, r, g, b): self.alphaOn.set(r, g, b, 1) self.alphaOff.set(r, g, b, 0) ################################################## # Iris ################################################## def loadIris(self): if self.iris == None: self.iris = loader.loadModel(self.IrisModelName) self.iris.setPos(0, 0, 0) def irisIn(self, t=0.5, finishIval=None): """ Play an iris in transition over t seconds. Places a polygon on the aspect2d plane then lerps the scale of the iris polygon up so it looks like we iris in. When the scale lerp is finished, it parents the iris polygon to hidden. """ self.noTransitions() self.loadIris() if (t == 0): self.iris.detachNode() else: self.iris.reparentTo(aspect2d, DGG.FADE_SORT_INDEX) self.transitionIval = Sequence( LerpScaleInterval(self.iris, t, scale=0.18, startScale=0.01), Func(self.iris.detachNode), name=self.irisTaskName, ) if finishIval: self.transitionIval.append(finishIval) self.transitionIval.start() def irisOut(self, t=0.5, finishIval=None): """ Play an iris out transition over t seconds. Places a polygon on the aspect2d plane then lerps the scale of the iris down so it looks like we iris out. When the scale lerp is finished, it leaves the iris polygon covering the aspect2d plane until you irisIn or call noIris. """ self.noTransitions() self.loadIris() self.loadFade() # we need this to cover up the hole. if (t == 0): self.iris.detachNode() self.fadeOut(0) else: self.iris.reparentTo(aspect2d, DGG.FADE_SORT_INDEX) self.transitionIval = Sequence( LerpScaleInterval(self.iris, t, scale=0.01, startScale=0.18), Func(self.iris.detachNode), # Use the fade to cover up the hole that the iris would leave Func(self.fadeOut, 0), name=self.irisTaskName, ) if finishIval: self.transitionIval.append(finishIval) self.transitionIval.start() def noIris(self): """ Removes any current iris tasks and parents the iris polygon away """ if self.transitionIval: self.transitionIval.pause() self.transitionIval = None if self.iris != None: self.iris.detachNode() # Actually we need to remove the fade too, # because the iris effect uses it. self.noFade() def noTransitions(self): """ This call should immediately remove any and all transitions running """ self.noFade() self.noIris() # Letterbox is not really a transition, it is a screen overlay # self.noLetterbox() ################################################## # Letterbox ################################################## def loadLetterbox(self): if not self.letterbox: # We create a DirectFrame for the fade polygon, instead of # simply loading the polygon model and using it directly, # so that it will also obscure mouse events for objects # positioned behind it. self.letterbox = NodePath("letterbox") # Allow fade in and out of the bars self.letterbox.setTransparency(1) # Allow DirectLabels to be parented to the letterbox sensibly self.letterbox.setBin('unsorted', 0) # Allow a custom look to the letterbox graphic. # TODO: This model isn't available everywhere. We should # pass it in as a parameter. button = loader.loadModel('models/gui/toplevel_gui', okMissing=True) barImage = None if button: barImage = button.find('**/generic_button') self.letterboxTop = DirectFrame( parent=self.letterbox, guiId='letterboxTop', relief=DGG.FLAT, state=DGG.NORMAL, frameColor=(0, 0, 0, 1), borderWidth=(0, 0), frameSize=(-1, 1, 0, 0.2), pos=(0, 0, 0.8), image=barImage, image_scale=(2.25, 1, .5), image_pos=(0, 0, .1), image_color=(0.3, 0.3, 0.3, 1), sortOrder=0, ) self.letterboxBottom = DirectFrame( parent=self.letterbox, guiId='letterboxBottom', relief=DGG.FLAT, state=DGG.NORMAL, frameColor=(0, 0, 0, 1), borderWidth=(0, 0), frameSize=(-1, 1, 0, 0.2), pos=(0, 0, -1), image=barImage, image_scale=(2.25, 1, .5), image_pos=(0, 0, .1), image_color=(0.3, 0.3, 0.3, 1), sortOrder=0, ) # masad: always place these at the bottom of render self.letterboxTop.setBin('sorted', 0) self.letterboxBottom.setBin('sorted', 0) self.letterbox.reparentTo(render2d, -1) self.letterboxOff(0) def noLetterbox(self): """ Removes any current letterbox tasks and parents the letterbox polygon away """ if self.letterboxIval: self.letterboxIval.pause() self.letterboxIval = None if self.letterbox: self.letterbox.stash() def letterboxOn(self, t=0.25, finishIval=None): """ Move black bars in over t seconds. """ self.noLetterbox() self.loadLetterbox() self.letterbox.unstash() if (t == 0): self.letterboxBottom.setPos(0, 0, -1) self.letterboxTop.setPos(0, 0, 0.8) else: self.letterboxIval = Sequence( Parallel( LerpPosInterval( self.letterboxBottom, t, pos=Vec3(0, 0, -1), #startPos = Vec3(0, 0, -1.2), ), LerpPosInterval( self.letterboxTop, t, pos=Vec3(0, 0, 0.8), # startPos = Vec3(0, 0, 1), ), ), name=self.letterboxTaskName, ) if finishIval: self.letterboxIval.append(finishIval) self.letterboxIval.start() def letterboxOff(self, t=0.25, finishIval=None): """ Move black bars away over t seconds. """ self.noLetterbox() self.loadLetterbox() self.letterbox.unstash() if (t == 0): self.letterbox.stash() else: self.letterboxIval = Sequence( Parallel( LerpPosInterval( self.letterboxBottom, t, pos=Vec3(0, 0, -1.2), # startPos = Vec3(0, 0, -1), ), LerpPosInterval( self.letterboxTop, t, pos=Vec3(0, 0, 1), # startPos = Vec3(0, 0, 0.8), ), ), Func(self.letterbox.stash), Func(messenger.send, 'letterboxOff'), name=self.letterboxTaskName, ) if finishIval: self.letterboxIval.append(finishIval) self.letterboxIval.start()
class Transitions: # These may be reassigned before the fade or iris transitions are # actually invoked to change the models that will be used. IrisModelName = "models/misc/iris" FadeModelName = "models/misc/fade" def __init__(self, loader, model=None, scale=3.0, pos=Vec3(0, 0, 0)): self.transitionIval = None self.letterboxIval = None self.iris = None self.fade = None self.letterbox = None self.fadeModel = model self.imagePos = pos if model: self.alphaOff = Vec4(1, 1, 1, 0) self.alphaOn = Vec4(1, 1, 1, 1) model.setTransparency(1) self.lerpFunc = LerpColorScaleInterval else: self.alphaOff = Vec4(0, 0, 0, 0) self.alphaOn = Vec4(0, 0, 0, 1) self.lerpFunc = LerpColorInterval self.irisTaskName = "irisTask" self.fadeTaskName = "fadeTask" self.letterboxTaskName = "letterboxTask" def __del__(self): if self.fadeModel: self.fadeModel.removeNode() self.fadeModel = None ################################################## # Fade ################################################## # We can set a custom model for the fade before using it for the first time def setFadeModel(self, model, scale=1.0): self.fadeModel = model # We have to change some default parameters for a custom fadeModel self.alphaOn = Vec4(1, 1, 1, 1) # Reload fade if its already been created if self.fade: self.fade.destroy() self.fade = None self.loadFade() def loadFade(self): if self.fade is None: # We create a DirectFrame for the fade polygon, instead of # simply loading the polygon model and using it directly, # so that it will also obscure mouse events for objects # positioned behind it. self.fade = DirectFrame( parent = hidden, guiId = 'fade', relief = None, image = self.fadeModel, image_scale = (4, 2, 2), state = DGG.NORMAL, ) if not self.fadeModel: # No fade model was given, so we make this the fade model. self.fade["relief"] = DGG.FLAT self.fade["frameSize"] = (-2, 2, -1, 1) self.fade["frameColor"] = (0, 0, 0, 1) self.fade.setTransparency(TransparencyAttrib.MAlpha) self.fade.setBin('unsorted', 0) self.fade.setColor(0,0,0,0) def getFadeInIval(self, t=0.5, finishIval=None): """ Returns an interval without starting it. This is particularly useful in cutscenes, so when the cutsceneIval is escaped out of we can finish the fade immediately """ #self.noTransitions() masad: this creates a one frame pop, is it necessary? self.loadFade() transitionIval = Sequence(Func(self.fade.reparentTo, aspect2d, DGG.FADE_SORT_INDEX), Func(self.fade.showThrough), # in case aspect2d is hidden for some reason self.lerpFunc(self.fade, t, self.alphaOff, # self.alphaOn, ), Func(self.fade.detachNode), name = self.fadeTaskName, ) if finishIval: transitionIval.append(finishIval) return transitionIval def getFadeOutIval(self, t=0.5, finishIval=None): """ Create a sequence that lerps the color out, then parents the fade to hidden """ self.noTransitions() self.loadFade() transitionIval = Sequence(Func(self.fade.reparentTo,aspect2d,DGG.FADE_SORT_INDEX), Func(self.fade.showThrough), # in case aspect2d is hidden for some reason self.lerpFunc(self.fade, t, self.alphaOn, # self.alphaOff, ), name = self.fadeTaskName, ) if finishIval: transitionIval.append(finishIval) return transitionIval def fadeIn(self, t=0.5, finishIval=None): """ Play a fade in transition over t seconds. Places a polygon on the aspect2d plane then lerps the color from black to transparent. When the color lerp is finished, it parents the fade polygon to hidden. """ gsg = base.win.getGsg() if gsg: # If we're about to fade in from black, go ahead and # preload all the textures etc. base.graphicsEngine.renderFrame() render.prepareScene(gsg) render2d.prepareScene(gsg) if (t == 0): # Fade in immediately with no lerp #print "transitiosn: fadeIn 0.0" self.noTransitions() self.loadFade() self.fade.detachNode() else: # Create a sequence that lerps the color out, then # parents the fade to hidden self.transitionIval = self.getFadeInIval(t, finishIval) self.transitionIval.start() def fadeOut(self, t=0.5, finishIval=None): """ Play a fade out transition over t seconds. Places a polygon on the aspect2d plane then lerps the color from transparent to full black. When the color lerp is finished, it leaves the fade polygon covering the aspect2d plane until you fadeIn or call noFade. lerp """ if (t == 0): # Fade out immediately with no lerp self.noTransitions() self.loadFade() self.fade.reparentTo(aspect2d, DGG.FADE_SORT_INDEX) self.fade.setColor(self.alphaOn) elif ConfigVariableBool('no-loading-screen', False): if finishIval: self.transitionIval = finishIval self.transitionIval.start() else: # Create a sequence that lerps the color out, then # parents the fade to hidden self.transitionIval = self.getFadeOutIval(t,finishIval) self.transitionIval.start() def fadeOutActive(self): return self.fade and self.fade.getColor()[3] > 0 def fadeScreen(self, alpha=0.5): """ Put a semitransparent screen over the camera plane to darken out the world. Useful for drawing attention to a dialog box for instance """ #print "transitiosn: fadeScreen" self.noTransitions() self.loadFade() self.fade.reparentTo(aspect2d, DGG.FADE_SORT_INDEX) self.fade.setColor(self.alphaOn[0], self.alphaOn[1], self.alphaOn[2], alpha) def fadeScreenColor(self, color): """ Put a semitransparent screen over the camera plane to darken out the world. Useful for drawing attention to a dialog box for instance """ #print "transitiosn: fadeScreenColor" self.noTransitions() self.loadFade() self.fade.reparentTo(aspect2d, DGG.FADE_SORT_INDEX) self.fade.setColor(color) def noFade(self): """ Removes any current fade tasks and parents the fade polygon away """ #print "transitiosn: noFade" if self.transitionIval: self.transitionIval.pause() self.transitionIval = None if self.fade: # Make sure to reset the color, since fadeOutActive() is looking at it self.fade.setColor(self.alphaOff) self.fade.detachNode() def setFadeColor(self, r, g, b): self.alphaOn.set(r, g, b, 1) self.alphaOff.set(r, g, b, 0) ################################################## # Iris ################################################## def loadIris(self): if self.iris == None: self.iris = loader.loadModel(self.IrisModelName) self.iris.setPos(0, 0, 0) def irisIn(self, t=0.5, finishIval=None): """ Play an iris in transition over t seconds. Places a polygon on the aspect2d plane then lerps the scale of the iris polygon up so it looks like we iris in. When the scale lerp is finished, it parents the iris polygon to hidden. """ self.noTransitions() self.loadIris() if (t == 0): self.iris.detachNode() else: self.iris.reparentTo(aspect2d, DGG.FADE_SORT_INDEX) self.transitionIval = Sequence(LerpScaleInterval(self.iris, t, scale = 0.18, startScale = 0.01), Func(self.iris.detachNode), name = self.irisTaskName, ) if finishIval: self.transitionIval.append(finishIval) self.transitionIval.start() def irisOut(self, t=0.5, finishIval=None): """ Play an iris out transition over t seconds. Places a polygon on the aspect2d plane then lerps the scale of the iris down so it looks like we iris out. When the scale lerp is finished, it leaves the iris polygon covering the aspect2d plane until you irisIn or call noIris. """ self.noTransitions() self.loadIris() self.loadFade() # we need this to cover up the hole. if (t == 0): self.iris.detachNode() self.fadeOut(0) else: self.iris.reparentTo(aspect2d, DGG.FADE_SORT_INDEX) self.transitionIval = Sequence(LerpScaleInterval(self.iris, t, scale = 0.01, startScale = 0.18), Func(self.iris.detachNode), # Use the fade to cover up the hole that the iris would leave Func(self.fadeOut, 0), name = self.irisTaskName, ) if finishIval: self.transitionIval.append(finishIval) self.transitionIval.start() def noIris(self): """ Removes any current iris tasks and parents the iris polygon away """ if self.transitionIval: self.transitionIval.pause() self.transitionIval = None if self.iris != None: self.iris.detachNode() # Actually we need to remove the fade too, # because the iris effect uses it. self.noFade() def noTransitions(self): """ This call should immediately remove any and all transitions running """ self.noFade() self.noIris() # Letterbox is not really a transition, it is a screen overlay # self.noLetterbox() ################################################## # Letterbox ################################################## def loadLetterbox(self): if not self.letterbox: # We create a DirectFrame for the fade polygon, instead of # simply loading the polygon model and using it directly, # so that it will also obscure mouse events for objects # positioned behind it. self.letterbox = NodePath("letterbox") # Allow fade in and out of the bars self.letterbox.setTransparency(1) # Allow DirectLabels to be parented to the letterbox sensibly self.letterbox.setBin('unsorted', 0) # Allow a custom look to the letterbox graphic. # TODO: This model isn't available everywhere. We should # pass it in as a parameter. button = loader.loadModel('models/gui/toplevel_gui', okMissing = True) barImage = None if button: barImage = button.find('**/generic_button') self.letterboxTop = DirectFrame( parent = self.letterbox, guiId = 'letterboxTop', relief = DGG.FLAT, state = DGG.NORMAL, frameColor = (0, 0, 0, 1), borderWidth = (0, 0), frameSize = (-1, 1, 0, 0.2), pos = (0, 0, 0.8), image = barImage, image_scale = (2.25,1,.5), image_pos = (0,0,.1), image_color = (0.3,0.3,0.3,1), sortOrder = 0, ) self.letterboxBottom = DirectFrame( parent = self.letterbox, guiId = 'letterboxBottom', relief = DGG.FLAT, state = DGG.NORMAL, frameColor = (0, 0, 0, 1), borderWidth = (0, 0), frameSize = (-1, 1, 0, 0.2), pos = (0, 0, -1), image = barImage, image_scale = (2.25,1,.5), image_pos = (0,0,.1), image_color = (0.3,0.3,0.3,1), sortOrder = 0, ) # masad: always place these at the bottom of render self.letterboxTop.setBin('sorted',0) self.letterboxBottom.setBin('sorted',0) self.letterbox.reparentTo(render2d, -1) self.letterboxOff(0) def noLetterbox(self): """ Removes any current letterbox tasks and parents the letterbox polygon away """ if self.letterboxIval: self.letterboxIval.pause() self.letterboxIval = None if self.letterbox: self.letterbox.stash() def letterboxOn(self, t=0.25, finishIval=None): """ Move black bars in over t seconds. """ self.noLetterbox() self.loadLetterbox() self.letterbox.unstash() if (t == 0): self.letterboxBottom.setPos(0, 0, -1) self.letterboxTop.setPos(0, 0, 0.8) else: self.letterboxIval = Sequence(Parallel( LerpPosInterval(self.letterboxBottom, t, pos = Vec3(0, 0, -1), #startPos = Vec3(0, 0, -1.2), ), LerpPosInterval(self.letterboxTop, t, pos = Vec3(0, 0, 0.8), # startPos = Vec3(0, 0, 1), ), ), name = self.letterboxTaskName, ) if finishIval: self.letterboxIval.append(finishIval) self.letterboxIval.start() def letterboxOff(self, t=0.25, finishIval=None): """ Move black bars away over t seconds. """ self.noLetterbox() self.loadLetterbox() self.letterbox.unstash() if (t == 0): self.letterbox.stash() else: self.letterboxIval = Sequence(Parallel( LerpPosInterval(self.letterboxBottom, t, pos = Vec3(0, 0, -1.2), # startPos = Vec3(0, 0, -1), ), LerpPosInterval(self.letterboxTop, t, pos = Vec3(0, 0, 1), # startPos = Vec3(0, 0, 0.8), ), ), Func(self.letterbox.stash), Func(messenger.send,'letterboxOff'), name = self.letterboxTaskName, ) if finishIval: self.letterboxIval.append(finishIval) self.letterboxIval.start()
class QuestPoster(DirectFrame): notify = directNotify.newCategory('QuestPoster') # We need to declare and initialize these variables here # because some methods use them as default arguments. auxIcon = None # Requires one parameter, quest, this must be a Quest instance. # The next argument, parent, is where to reparent the DirectFrame to. # The next arguments are simply additional options when setting up the DirectFrame. def __init__(self, quest, parent=aspect2d, **kw): # The quest this poster is representing. self.quest = quest self.accessibleObjectives = quest.accessibleObjectives if quest else [] self.viewObjective = quest.accessibleObjectives.seek( ) if quest else None isObjComplete = False if not quest else ( self.accessibleObjectives.isComplete() or quest.isComplete()) # Let's define our options for the DirectFrame. bookModel = loader.loadModel( 'phase_3.5/models/gui/stickerbook_gui.bam') optiondefs = (('relief', None, None), ('image', bookModel.find('**/questCard'), None), ('image_scale', (0.8, 1.0, 0.58), None), ('image_color', (1.0, 1.0, 1.0, 1.0) if not isObjComplete else Vec4( *QuestGlobals.LIGHT_GREEN), None), ('state', DGG.NORMAL, None)) self.defineoptions(kw, optiondefs) # Finally, initialize the DirectFrame. DirectFrame.__init__(self, parent, relief=None) self.initialiseoptions(QuestPoster) # Let's declare and initialize our barebone GUI element variables. questTitle = '' if not self.quest else self.quest.name self.titleLabel = DirectLabel(parent=self, relief=None, text=questTitle, text_font=CIGlobals.getMinnieFont(), text_fg=QuestGlobals.TEXT_COLOR, text_scale=0.05, text_align=TextNode.ACenter, text_wordwrap=25.0, textMayChange=1, pos=(0, 0, 0.23)) ########################################################################## # THE FOLLOWING ELEMENTS BELOW ARE GROUPED TOGETHER # ########################################################################## # The background frame where the objective image is displayed. # This is the colored background frame. circleGui = loader.loadModel( 'phase_4/models/gui/CircleIconBackgroundGui.bam') self.auxFrame = DirectFrame( parent=self, relief=None, image=circleGui.find('**/circle_display_interior'), image_scale=0.18, text='', text_pos=(0, -0.11), text_fg=QuestGlobals.TEXT_COLOR, text_scale=QuestGlobals.QPtextScale, text_align=TextNode.ACenter, text_wordwrap=11.0, pos=QuestGlobals.DEFAULT_LEFT_PICTURE_POS) if self.quest and len( self.quest.accessibleObjectives) > 1 and not isObjComplete: # We can only use arrows when we have more than one objective available. arrowGui = loader.loadModel('phase_4/models/gui/QuestArrowGui.bam') self.prevObjArrow = DirectButton( parent=self.auxFrame, relief=None, geom=((arrowGui.find('**/quest_arrow_enabled'), arrowGui.find('**/quest_arrow_click'), arrowGui.find('**/quest_arrow_mouseover'), arrowGui.find('**/quest_arrow_disabled'))), scale=0.08, command=self.switchObjective, extraArgs=[0], hpr=(180, 0, 0), pos=QuestGlobals.DEFAULT_LEFT_ARROW_POS) self.nextObjArrow = DirectButton( parent=self.auxFrame, relief=None, geom=((arrowGui.find('**/quest_arrow_enabled'), arrowGui.find('**/quest_arrow_click'), arrowGui.find('**/quest_arrow_mouseover'), arrowGui.find('**/quest_arrow_disabled'))), scale=0.08, command=self.switchObjective, pos=QuestGlobals.DEFAULT_RIGHT_ARROW_POS) # The icon that goes on top of the aux frame. self.auxIcon = DirectFrame(parent=self.auxFrame, relief=None, text=' ', text_font=CIGlobals.getSuitFont(), text_pos=(0, -0.03), text_fg=QuestGlobals.TEXT_COLOR, text_scale=0.13, text_align=TextNode.ACenter, text_wordwrap=13.0, textMayChange=1) self.auxIcon.setColorOff(-1) self.auxOutline = DirectLabel( parent=self.auxFrame, relief=None, image=circleGui.find('**/circle_display_outline'), image_scale=0.18) # The aux text saying: DEFEAT, RECOVER, etc. self.auxText = DirectLabel(parent=self, relief=None, text=QuestGlobals.RECOVER, text_font=CIGlobals.getToonFont(), text_scale=QuestGlobals.QPauxText, text_fg=QuestGlobals.TEXT_COLOR, text_align=TextNode.ACenter, textMayChange=1, pos=QuestGlobals.DEFAULT_AUX_POS) self.auxText.hide() ########################################################################## # Information displayed about the objective. self.objectiveInfo = DirectLabel( parent=self, relief=None, text='', text_font=CIGlobals.getToonFont(), text_fg=QuestGlobals.TEXT_COLOR, text_scale=0.04, text_align=TextNode.ACenter, text_wordwrap=QuestGlobals.QPtextWordwrap, textMayChange=1, pos=(QuestGlobals.DEFAULT_INFO_POS)) self.objectiveInfo.hide() # Information displayed showing the location. self.locationInfo = DirectLabel( parent=self, relief=None, text='N/A', text_font=CIGlobals.getToonFont(), text_fg=QuestGlobals.TEXT_COLOR, text_scale=QuestGlobals.QPtextScale, text_align=TextNode.ACenter, text_wordwrap=QuestGlobals.QPtextWordwrap, textMayChange=1, pos=(0, 0, -0.115)) self.locationInfo.hide() # The progress bar showing the objective's progress self.progressBar = DirectWaitBar(parent=self, relief=DGG.SUNKEN, frameSize=(-0.95, 0.95, -0.1, 0.12), borderWidth=(0.025, 0.025), scale=0.2, frameColor=(0.945, 0.875, 0.706, 1.0), barColor=(0.5, 0.7, 0.5, 1), text='0/0', text_font=CIGlobals.getToonFont(), text_scale=0.19, text_fg=(0.05, 0.14, 0.4, 1), text_align=TextNode.ACenter, text_pos=(0, -0.05), pos=(0, 0, -0.2425)) self.progressBar.hide() # The wood panel at the bottom where rewards are displayed. rewardFrameGeom = loader.loadModel( 'phase_4/models/gui/gag_shop_purchase_gui.bam') self.rewardFrame = DirectFrame( parent=self, relief=None, geom=rewardFrameGeom.find('**/Goofys_Sign'), geom_scale=(0.62, 0, 0.4), pos=(-0.015, 0, -0.25)) # Let's setup our reward frames. reward = None if self.quest and len(self.quest.rewards) > 0: reward = self.quest.rewards[0] self.lReward = QuestRewardFrame(self, reward) # The text displayed on the right side of the frame with additional information, if necessary. self.sideInfo = DirectLabel(parent=self, relief=None, text=QuestGlobals.JUST_FOR_FUN, text_fg=(0.0, 0.439, 1.0, 1.0), text_shadow=(0, 0, 0, 1), pos=(-0.2825, 0, 0.2), scale=0.03) self.sideInfo.setR(-30) # This side information is usually not needed, let's hide it. self.sideInfo.hide() # Remove the nodes of the loaded models we no longer need. circleGui.removeNode() bookModel.removeNode() rewardFrameGeom.removeNode() # We are only removing this node if we generated arrows. if hasattr(self, 'arrowGui'): arrowGui.removeNode() # Let's hide this until it is needed. self.hide() return def switchObjective(self, forward=1): if forward: self.accessibleObjectives.nextObjective() else: self.accessibleObjectives.lastObjective() self.viewObjective = self.accessibleObjectives.seek() self.setup() def setup(self): if self.quest: objective = self.viewObjective complete = self.accessibleObjectives.isComplete() # Let's reset our positioning of elements. self.auxFrame.setPos(QuestGlobals.DEFAULT_LEFT_PICTURE_POS) self.auxText.setPos(QuestGlobals.DEFAULT_AUX_POS) self.objectiveInfo.setPos(QuestGlobals.DEFAULT_INFO_POS) # Let's reset our icon. self.auxIcon.setScale(1, 1, 1) self.auxIcon.setPos(0, 0, 0) self.auxIcon.setHpr(0, 0, 0) self.objectiveInfo.show() self.auxFrame.show() # Let's setup the quest progress bar progress = objective.progress if hasattr(objective, 'progress') else None if objective.goal > 1: self.progressBar['range'] = objective.goal self.progressBar['value'] = progress & pow(2, 16) - 1 if objective.HasProgress and objective.goal > 1 and not complete: self.progressBar.show() self.auxText.show() # Let's handle the objectives. if not complete: if objective.__class__ == CogObjective: self.handleCogObjective() elif objective.__class__ == CogBuildingObjective: self.handleCogBuildingObjective() elif objective.__class__ == MinigameObjective: self.handleMinigameObjective() elif objective.__class__ == VisitNPCObjective: self.handleNPCObjective() else: bgColor = QuestGlobals.RED if objective.type in DefeatObjectives: bgColor = QuestGlobals.BLUE self.handleNPCObjective(auxText=QuestGlobals.RETURN + ' to', frameColor=bgColor) self.lReward.setup() newLineInObjInfo = '\n' in self.objectiveInfo['text'] isShopLoc = QuestGlobals.isShopLocation( objective.area) if not complete else True if complete: locationText = QuestGlobals.getLocationText(None, objective) else: locationText = QuestGlobals.getLocationText(objective.area) self.locationInfo['text'] = locationText self.locationInfo['text_pos'] = (0.0, (0.025 if isShopLoc else ( -0.025 if newLineInObjInfo else 0.0))) self.locationInfo.show() else: # We want to be able to show empty quest posters. self.titleLabel.hide() self.auxFrame.hide() self.auxIcon.hide() self.titleLabel.initialiseoptions(DirectLabel) self.auxIcon.initialiseoptions(DirectFrame) self.auxText.initialiseoptions(DirectLabel) self.objectiveInfo.initialiseoptions(DirectLabel) self.locationInfo.initialiseoptions(DirectLabel) self.rewardFrame.initialiseoptions(DirectFrame) self.sideInfo.initialiseoptions(DirectLabel) self.lReward.initialiseoptions(DirectFrame) # Handle arrow stuff if necessary. if hasattr(self, 'prevObjArrow'): index = self.accessibleObjectives.seeker self.prevObjArrow['state'] = DGG.NORMAL self.nextObjArrow['state'] = DGG.NORMAL self.prevObjArrow.setPos(QuestGlobals.DEFAULT_LEFT_ARROW_POS) self.nextObjArrow.setPos(QuestGlobals.DEFAULT_RIGHT_ARROW_POS) if index == 0: self.prevObjArrow['state'] = DGG.DISABLED elif index == len(self.accessibleObjectives) - 1: self.nextObjArrow['state'] = DGG.DISABLED self.prevObjArrow.initialiseoptions(DirectButton) self.nextObjArrow.initialiseoptions(DirectButton) # Changes geometry and scale of an icon. def handleSimpleIcon(self, geom, scale, icon): icon['geom'] = geom icon['geom_scale'] = scale def handleComplexIcon(self, geom, icon, scale=QuestGlobals.IMAGE_SCALE_SMALL): geom.setDepthWrite(1) geom.setDepthTest(1) self.fitGeometry(geom, fFlip=1) self.handleSimpleIcon(geom, scale, icon) # We have to rotate the head and set the scale of the icon. if CIGlobals.Suit in geom.getName(): cogName = geom.getPythonTag('Settings') data = QuestGlobals.Suit2PosterZNDScale.get(cogName) zOffset = data[0] headScale = data[1] icon.setScale(headScale) icon.setZ(icon.getZ() + zOffset) icon.setH(180) else: icon.setZ(icon.getZ() - 0.01) def handleCogObjective(self, iconElement=auxIcon, auxText=QuestGlobals.DEFEAT, frameColor=QuestGlobals.BLUE): objective = self.viewObjective infoText = objective.getTaskInfo() if objective.__class__ == RecoverItemObjective: infoText = CIGlobals.makePlural(objective.cog) if not iconElement: iconElement = self.auxIcon # Let's make sure we have a current objective that is # an instance of the CogObjective class and this poster isn't destroyed. if not objective or not hasattr(self, 'titleLabel') or not isinstance( objective, CogObjective): return if objective.dept: icons = loader.loadModel('phase_3/models/gui/cog_icons.bam') deptIcon = None if objective.dept == Dept.BOSS: deptIcon = icons.find('**/CorpIcon') else: deptIcon = icons.find('**/%sIcon' % objective.dept.getTie().title()) # Correct the medallion color. deptIcon.setColor(SuitGlobals.medallionColors[objective.dept]) # Setup the icon and remove the icons node. self.handleSimpleIcon(deptIcon, 0.13, iconElement) icons.removeNode() elif objective.cog == QuestGlobals.Any: # We aren't fighting a Cog in particular. cogIcon = QuestGlobals.getCogIcon() self.handleSimpleIcon(cogIcon, 0.13, iconElement) # We're fighting a Cog in particular. if not objective.cog == QuestGlobals.Any: cogHeadInstance = SuitBank.getSuitByName(objective.cog).getHead() cogHead = cogHeadInstance.generate() cogHead.setName('%sHead' % CIGlobals.Suit) cogHead.setPythonTag('Settings', cogHeadInstance.head) cogHead.setScale(2) cogHead.setLightOff() self.handleComplexIcon(cogHead, iconElement) # HACK FIX: Corrects the buggy Flunky glasses. glasses = cogHead.find('**/glasses') if glasses and not glasses.isEmpty(): glasses.setScale(1) glasses.reparentTo(cogHead) if not iconElement is self.auxIcon: if hasattr(self, 'goalInfo'): # We're working with the second frame, on the right. # Let's update the information pertaining to this side. self.goalInfo['text'] = infoText self.goalInfo.setPos(QuestGlobals.RECOVER_INFO2_POS) self.auxText.setPos(QuestGlobals.RECOVER_AUX_POS) else: raise AttributeError( 'Attempted to setup DoubleFrame information for poster using default style.' ) else: self.objectiveInfo['text'] = infoText # Let's set the progress bar text pgBarText = '%d of %d %s' % (objective.progress, objective.goal, CIGlobals.makePastTense(auxText)) self.progressBar['text'] = pgBarText self.auxText['text'] = auxText # Let's set the color of the poster. frame = self.auxFrame if iconElement is self.auxIcon else self.goalFrame frame['image_color'] = Vec4(*frameColor) def handleCogBuildingObjective(self, iconElement=auxIcon, auxText=QuestGlobals.DEFEAT, frameColor=QuestGlobals.BLUE): objective = self.viewObjective infoText = objective.getTaskInfo() if not iconElement: iconElement = self.auxIcon # Let's make sure we have a current objective that is # an instance of the CogBuildingObjective class and this poster isn't destroyed. if not objective or not hasattr(self, 'titleLabel') or not isinstance( objective, CogBuildingObjective): return # If we aren't looking for any specific department of building. if objective.dept == QuestGlobals.Any: # Let's just use the good ol' generic building icon. self.handleSimpleIcon(QuestGlobals.getCogBuildingIcon(), QuestGlobals.SIMPLE_IMAGE_SCALE, iconElement) else: # Ah geez, we're looking for a specific department. # Bossbot tie names are messed up, so we need this if statement. dept = objective.dept.getTie( ) if not objective.dept == Dept.BOSS else 'corp' bldgMdl = loader.loadModel( 'phase_4/models/modules/suit_landmark_%s.bam' % dept) # Next, we need to load the building elevator. elevator = loader.loadModel('phase_4/models/modules/elevator.bam') elevator.reparentTo(bldgMdl.find('**/*_door_origin')) self.handleComplexIcon(bldgMdl, iconElement) # Let's set the progress bar text pgBarText = '%d of %d %s' % (objective.progress, objective.goal, CIGlobals.makePastTense(auxText)) self.progressBar['text'] = pgBarText self.objectiveInfo['text'] = infoText self.auxText['text'] = auxText self.auxFrame['image_color'] = Vec4(*frameColor) def handleMinigameObjective(self, iconElement=auxIcon, auxText=QuestGlobals.PLAY, frameColor=QuestGlobals.RED): objective = self.viewObjective infoText = objective.getTaskInfo() if not iconElement: iconElement = self.auxIcon # Let's make sure we have a current objective that is # an instance of the MinigameObjective class and this poster isn't destroyed. if not objective or not hasattr(self, 'titleLabel') or not isinstance( objective, MinigameObjective): return # Let's set the icon to the minigame icon. self.handleSimpleIcon(QuestGlobals.getTrolleyIcon(), QuestGlobals.SIMPLE_IMAGE_SCALE, iconElement) # Let's set the progress bar text pgBarText = '%d of %d %s' % (objective.progress, objective.goal, CIGlobals.makePastTense(auxText)) self.progressBar['text'] = pgBarText self.objectiveInfo['text'] = infoText self.auxText['text'] = auxText self.auxFrame['image_color'] = Vec4(*frameColor) def handleNPCObjective(self, iconElement=auxIcon, auxText=QuestGlobals.VISIT, frameColor=QuestGlobals.BROWN): objective = self.viewObjective npcId = 0 if self.accessibleObjectives.isComplete() and not hasattr( objective, 'npcId'): npcId = objective.assigner elif hasattr(objective, 'npcId'): npcId = objective.npcId if npcId == 0: infoText = 'A %s' % NPCGlobals.lHQOfficerF else: infoText = NPCGlobals.NPCToonNames[npcId] if not iconElement: iconElement = self.auxIcon # Let's generate the head. if not npcId == 0: dna = ToonDNA() dna.setDNAStrand(NPCGlobals.NPCToonDict.get(npcId)[2]) head = ToonGlobals.generateGuiHead(dna) self.handleComplexIcon(head, iconElement, scale=QuestGlobals.IMAGE_SCALE_SMALL - 0.01) else: self.handleSimpleIcon(QuestGlobals.getHQIcon(), QuestGlobals.SIMPLE_IMAGE_SCALE, iconElement) self.auxText['text'] = auxText if not iconElement is self.auxIcon: if hasattr(self, 'goalInfo'): # We're working with the second frame, on the right. # Let's update the information pertaining to this side. self.goalInfo['text'] = infoText self.goalInfo.setPos(QuestGlobals.RECOVER_INFO2_POS) self.auxText.setPos(QuestGlobals.RECOVER_AUX_POS) self.goalFrame['image_color'] = frameColor else: raise AttributeError( 'Attempted to setup DoubleFrame information for poster using default style.' ) else: self.objectiveInfo['text'] = infoText self.auxFrame['image_color'] = frameColor def fitGeometry(self, geom, fFlip=0, dimension=0.8): p1 = Point3() p2 = Point3() geom.calcTightBounds(p1, p2) if fFlip: t = p1[0] p1.setX(-p2[0]) p2.setX(-t) d = p2 - p1 biggest = max(d[0], d[2]) s = dimension / biggest mid = (p1 + d / 2.0) * s geomXform = hidden.attachNewNode('geomXform') for child in geom.getChildren(): child.reparentTo(geomXform) geomXform.setPosHprScale(-mid[0], -mid[1] + 1, -mid[2], 180, 0, 0, s, s, s) geomXform.reparentTo(geom) def destroy(self): if hasattr(self, 'titleLabel'): self.titleLabel.destroy() self.auxFrame.destroy() self.auxIcon.destroy() self.auxOutline.destroy() self.auxText.destroy() self.objectiveInfo.destroy() self.locationInfo.destroy() self.progressBar.destroy() self.rewardFrame.destroy() self.sideInfo.destroy() self.lReward.destroy() # We need to cleanup our arrows if they were created. if hasattr(self, 'prevObjArrow'): self.prevObjArrow.destroy() self.nextObjArrow.destroy() del self.prevObjArrow del self.nextObjArrow del self.titleLabel del self.auxFrame del self.auxIcon del self.auxOutline del self.auxText del self.objectiveInfo del self.locationInfo del self.progressBar del self.rewardFrame del self.sideInfo del self.lReward del self.accessibleObjectives del self.viewObjective DirectFrame.destroy(self) self.notify.debug('Destroyed all elements.')
class NameValueList(UIItem): """ A NameValueList is a list of name and value pairs. This is commonly used in the settings screen where the user has a list of items and can edit them at any point in time. This is just a generic UI element to keep all of the data and logic within the game subsystem """ def __init__(self, items=[], lines_to_show=5): # items is a tuple consisting of (text name of item, selection values, current selection) self._items = [] self._lines_to_show = lines_to_show self.__menuContainer = DirectFrame( #text_pos=(0,1), pos=(-0.6, 0, 0.3), text_scale=1.5, text_align=TextNode.ALeft, text_fg=(0, 0, 0, 0), relief=DGG.FLAT, frameColor=(1, 1, 1, 0), #left,right,bottom,top frameSize=(-0.5, 0.5, -0.5, 0.5)) self.__menuContainer.hide() self.selectedItem = 0 self.editing = False self.blink = False self.blinkTask = None for item in items: self.addItem(item[0], item[1], item[2]) def setPos(self, x, y, z): self.__menuContainer.setPos(x, y, z) def addItem(self, text_name, selection_values, current_selection_idx=-1): """ Adds an item to the list display. text_name - The string representation of the list item selection_values - A list of available values for selection in this field current_selection - The currently selected item """ pos_name = Vec3(-0.47, 0, 0.4 - (len(self._items) * 0.15)) pos_value = Vec3(1.0, 0, 0.4 - (len(self._items) * 0.15)) length = len(self._items) selection_text = "" if current_selection_idx != -1: selection_text = str(selection_values[current_selection_idx]) name_display = DirectButton( text=text_name, command=None, extraArgs=[len(self._items)], text_align=TextNode.ALeft, scale=0.1, #left/right, forward/back, up/down pos=pos_name, text_fg=(1, 1, 1, 1), rolloverSound=None, clickSound=None, pressEffect=0, relief=None, textMayChange=True #text_font=base.fontLoader.load('Arial Bold.ttf') ) name_display.reparentTo(self.__menuContainer) value_display = DirectButton( text=str(selection_text), command=None, extraArgs=[len(self._items)], text_align=TextNode.ALeft, scale=0.1, #left/right, forward/back, up/down pos=pos_value, text_fg=(1, 1, 1, 1), rolloverSound=None, clickSound=None, pressEffect=0, relief=None, textMayChange=True #text_font=base.fontLoader.load('Arial Bold.ttf') ) value_display.reparentTo(self.__menuContainer) v = {} v['name'] = text_name v['name_display'] = name_display v['value_display'] = value_display v['selection_values'] = selection_values v['current_selection_idx'] = current_selection_idx self._items.append(v) def up(self): """Move one item up in the menu.""" if self.editing: current_item = self._items[self.selectedItem] current_item['current_selection_idx'] = ( current_item['current_selection_idx'] + 1) % len( current_item['selection_values']) current_item['value_display']['text'] = current_item[ 'selection_values'][current_item['current_selection_idx']] else: newItem = self.selectedItem - 1 if (newItem < 0): newItem = len(self._items) - 1 self.select(newItem) UIItem.up(self) def down(self): """Move one item down in the menu.""" if self.editing: current_item = self._items[self.selectedItem] current_item['current_selection_idx'] = ( current_item['current_selection_idx'] - 1) % len( current_item['selection_values']) current_item['value_display']['text'] = current_item[ 'selection_values'][current_item['current_selection_idx']] else: newItem = self.selectedItem + 1 if (newItem >= len(self._items)): newItem = 0 self.select(newItem) UIItem.down(self) def show(self): if (self.__menuContainer.isHidden()): Sequence( Func(self.__menuContainer.setAlphaScale, 0.0), Func(self.__menuContainer.show), LerpFunctionInterval(self.__menuContainer.setAlphaScale, toData=1.0, fromData=0.0, duration=1.0)).start() def hide(self): self.ignoreAll() if (not self.__menuContainer.isHidden()): Sequence( LerpFunctionInterval(self.__menuContainer.setAlphaScale, toData=0.0, fromData=1.0, duration=1.0), Func(self.__menuContainer.hide), Func(self.__menuContainer.setAlphaScale, 1.0)).start() def setParent(self, parent): self.__menuContainer.reparentTo(parent) def select(self, item): self._items[self.selectedItem]['name_display']['text_fg'] = (1, 1, 1, 1) self._items[self.selectedItem]['name_display']['text_bg'] = (0, 0, 0, 0) self._items[self.selectedItem]['value_display']['text_fg'] = (1, 1, 1, 1) self._items[self.selectedItem]['value_display']['text_bg'] = (0, 0, 0, 0) self.selectedItem = item self._items[self.selectedItem]['name_display']['text_fg'] = (0, 0, 0.5, 1) self._items[self.selectedItem]['name_display']['text_bg'] = (1, 1, 1, 1) self._items[self.selectedItem]['value_display']['text_fg'] = (0, 0, 0.5, 1) self._items[self.selectedItem]['value_display']['text_bg'] = (1, 1, 1, 1) def toggleEdit(self): self.editing = not self.editing if self.editing: # Start blinking self.blinkTask = base.taskMgr.doMethodLater( 0.4, self._doBlink, 'nvBlinkTask') else: # Stop blinking if self.blinkTask != None: base.taskMgr.remove(self.blinkTask) def _doBlink(self, task): self.blink = not self.blink if self.blink: self._items[self.selectedItem]['value_display']['text_fg'] = (0, 0, 0, 1) self._items[self.selectedItem]['value_display']['text_bg'] = (1, 1, 1, 1) else: self._items[self.selectedItem]['value_display']['text_fg'] = (1, 1, 1, 1) self._items[self.selectedItem]['value_display']['text_bg'] = (0, 0, 0, 0) return Task.again
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 GuiFrame(DirectObject, HasKeybinds): #should be able to show/hide, do conditional show hide #position where you want #parent to other frames TEXT_MAGIC_NUMBER = .833333333334 #5/6 ?!? DRAW_ORDER = { 'frame': ('unsorted', 0), 'frame_bg': ('unsorted', 0), 'items': ('unsorted', 0), 'title': ('unsorted', 0), 'border': ('unsorted', 0), } def __init__( self, title, shortcut=None, # XXX obsolete, but needs a non deco replacement x=0, y=.1, width=.2, height=.8, #scale = .05, # there is some black magic here :/ bdr_thickness=2, bdr_color=(.1, .1, .1, 1), bg_color=(.7, .7, .7, .5), text_color=(0, 0, 0, 1), text_font=TextNode.getDefaultFont(), #text_h = .05, # do not use directly text_height_mm=4, items=tuple(), ): #item_w_pad = 1 #item_h_pad = 1 self.title = title self.do_xywh(x, y, width, height) self.bdr_thickness = bdr_thickness # FIXME ?? self.bdr_color = bdr_color self.bg_color = bg_color self.text_color = text_color self.text_font = text_font self.text_height_mm = text_height_mm #set up variables self.__winx__ = base.win.getXSize() self.__winy__ = base.win.getYSize() self.__ar__ = base.camLens.getAspectRatio() self.__was_dragging__ = False self.__first_item__ = None self.__add_head__ = None self.items = OrderedDict() # ordered dict to allow sequential addition #self.BT = buttonThrower if buttonThrower else base.buttonThrowers[0].node() self.BT = base.buttonThrowers[0].node() # get our aspect ratio, and pixels per mm self.pixels_per_mm = render.getPythonTag('system_data')['max_ppmm'] self.getWindowData() self.accept('window-event', self.getWindowData) #set the text height using the above data self.setTextHeight() # get the root for all frames in the scene self.frameRoot = aspect2d.find('frameRoot') if not self.frameRoot: self.frameRoot = aspect2d.attachNewNode('frameRoot') # create the parent node for this frame #parent = self.frameRoot.find('frame-*') #if not parent: #parent = self.frameRoot self.frame = self.frameRoot.attachNewNode('frame-%s-%s' % (title, id(self))) self.frame.setBin(*self.DRAW_ORDER['frame']) # background l, r, b, t = 0, self.width, 0, self.height self.frame_bg = DirectFrame( parent=self.frame, frameColor=self.bg_color, pos=LVecBase3f(self.x, 0, self.y), frameSize=(l, r, b, t), state=DGG.NORMAL, # FIXME framesize is >_< suppressMouse=1) self.frame_bg.setBin(*self.DRAW_ORDER['frame_bg']) # border self.__make_border__(self.frame_bg, self.bdr_thickness, self.bdr_color, l, r, b, t) # setup for items self.itemsParent = self.frame_bg.attachNewNode('items parent') # title self.title_button = self.__create_item__(title, self.title_toggle_vis) # add any items that we got for item in items: self.__create_item__( *item ) # FIXME when we call frame adjust we will loose the record of any data items # dragging self.title_button.bind(DGG.B1PRESS, self.__startDrag) self.title_button.bind(DGG.B1RELEASE, self.__stopDrag) # raise if we click the frame background self.frame_bg.bind(DGG.B1PRESS, self.raise_) #self.frame_bg.bind(DGG.B1RELEASE, self.__stopDrag) # this can cause problems w/ was dragging # toggle vis if shortcut: self.accept(shortcut, self.toggle_vis) # adjust the frame self.frame_adjust() @property def text_s(self): return self.text_h * self.TEXT_MAGIC_NUMBER def setTextHeight(self): h_units = 2 * base.a2dTop units_per_pixel = h_units / self.__winy__ text_h = self.text_height_mm * self.pixels_per_mm * units_per_pixel self.text_h = text_h def do_xywh(self, x, y, w, h): """ makes negative wneg xidths and heights work as well as negative x and y (bottom right is 0) """ if x < 0: x = 1 + x if y < 0: y = 1 + y if w < 0: x, w = x + w, -w if h < 0: y, h = y + h, -h self.x = self.fix_x(x) # for top left self.y = self.fix_y(y) # for top left self.width = self.fix_w(w) self.height = self.fix_h(h) def getWindowData(self, window=None): x = base.win.getXSize() y = base.win.getYSize() if x != self.__winx__ or y != self.__winy__: self.__ar__ = base.camLens.getAspectRatio() # w/h self.__winx__ = x self.__winy__ = y self.frame_adjust() def raise_(self, *args): """ function that raises windows call FIRST inside any function that should raise """ self.frame.reparentTo( self.frameRoot) # self.frame doesn't move so no wrt def frame_adjust( self ): # FIXME sometimes this fails to call, also calls too often at startup self.setTextHeight() MI = self.getMaxItems() # does not count title >_< LI = len(self.items) DI = MI - LI if DI >= 0: for i in range(DI + 1): self.__create_item__(' blank') else: for i in range(-(DI + 1)): k, v = self.items.popitem() # remove the last nodes in order v.removeNode() # FIXME consider keeping these around? for k, b in self.items.items(): if k == 'title': if self.frame_bg.isHidden(): x, y, z = self.frame_bg.getPos() self.title_button.setPos(LVecBase3f(x, y, z - self.text_h)) else: self.title_button.setPos(LVecBase3f(0, 0, -self.text_h)) elif k == self.__first_item__: b.setPos(LVecBase3f(0, 0, -(self.text_h * 2))) else: b.setPos(LVecBase3f(0, 0, -self.text_h)) b['frameSize'] = 0, self.width, 0, self.text_h b['text_scale'] = self.text_s, self.text_s b['text_pos'] = 0, self.text_h - self.TEXT_MAGIC_NUMBER * self.text_s def getWindowSize(self, event=None): # TODO see if we really need this self.__winx__ = base.win.getXSize() self.__winy__ = base.win.getYSize() m = max(self.__winx__, self.__winy__) self.__xscale__ = self.__winx__ / m self.__yscale__ = self.__winy__ / m # put origin in top left and positive down and right @staticmethod def fix_x(x): return (x - .5) * 2 # TODO * base.a2dLeft? @staticmethod def fix_y(y): return (y - .5) * -2 # TODO * base.a2dTop? @staticmethod def fix_w(n): return n * 2 @staticmethod def fix_h(n): return -n * 2 def add_item(self, text, command=None, args=tuple()): args = list(args) if text[0] != ' ': text = ' ' + text items = list(self.items) last_slot = len(self.items) if self.__add_head__ == last_slot: print('all slots are full, cannot add item to %s' % self) return None button = self.items[items[self.__add_head__]] button['text'] = text button['command'] = command button['extraArgs'] = args + button[ 'extraArgs'] # blank buttons always have [self,id] self.__add_head__ += 1 def __create_item__(self, text, command=None, args=tuple()): args = list(args) #if not len(self.items): #parent = self.frame if len(self.items) <= 1: parent = self.itemsParent #everyone else parents off 2nd text else: parent = list(self.items.values())[-1] if command != None: def cmd(*args): """ any item should raise """ self.raise_() command(*args) else: cmd = self.raise_ b = DirectButton( parent=parent, frameColor=(1, 1, 1, .0), # a = 0 => no border overlap frameSize=(0, self.width, 0, self.text_h), text=' ' + text, # hack to keep spacing from border text_font=self.text_font, text_fg=self.text_color, text_scale=self.text_s, text_pos=(0, self.text_h - self.TEXT_MAGIC_NUMBER * self.text_s), command=cmd, relief=DGG.FLAT, text_align=TextNode.ALeft, ) b.setPos(LVecBase3f(0, 0, -self.text_h)) b.setName('DirectButton-' + text) if not len(self.items): self.items['title'] = b b.setBin(*self.DRAW_ORDER['title']) else: b['extraArgs'] = args + [self, id(b)] b.node().setPythonTag('id', id(b)) b.setBin(*self.DRAW_ORDER['items']) if len(self.items) is 1: # the first item that is not the title b.setPos(LVecBase3f(0, 0, -(self.text_h * 2))) self.__first_item__ = id(b) self.items[id(b)] = b if text == ' blank': if self.__add_head__ is None: self.__add_head__ = 1 return b def del_all(self): if self.__first_item__ != None: for id_, button in self.items.items(): if id_ != 'title': button['text'] = ' blank' button['command'] = None button['extraArgs'] = [self, id_] self.__add_head__ = 1 def del_item(self, text): # FIXME uniqueness problems #d = self.itemsParent.find('*%s*'%text) if text[0] != ' ': text = ' ' + text d = [i for i in self.items.values() if i.getName().count(text)] try: self.__del_item__(d[0].getPythonTag('id')) except IndexError: print('that item does not seem to exist') # if we have a name then there shouldn't be key errors def __del_item__(self, index): """ I have no idea how this is going to work """ out = self.items[index] p = out.getParent() if out.getNumChildren(): # avoid the printing of the AssertionError :/ c = out.getChild(0) c.reparentTo(p) if index == self.__first_item__: # XXX is fails, ints from id != c.setPos(LVecBase3f(out.getPos())) id_ = c.getPythonTag('id') self.__first_item__ = id_ out.setPos(LVecBase3f(0, 0, -self.text_h)) self.items.pop(index) parent = list(self.items.values())[-1] out['text'] = ' del blank' #out['command'] = None out['extraArgs'] = [self, index] out.reparentTo(parent) self.items[index] = out if self.__add_head__ > 1: # title is always at 0 self.__add_head__ -= 1 @classmethod def __make_border__(cls, parent, thickness, color, l, r, b, t): moveto_drawto = ( ((l, 0, t), (l, 0, b)), ((r, 0, t), (r, 0, b)), ((l, 0, b), (r, 0, b)), ((l, 0, t), (r, 0, t)), ) for moveto, drawto in moveto_drawto: Border = LineSegs() Border.setThickness(thickness) Border.setColor(*color) Border.moveTo(*moveto) Border.drawTo(*drawto) b = parent.attachNewNode(Border.create()) b.setBin(*cls.DRAW_ORDER['border']) def getMaxItems(self): return int(abs(self.height / self.text_h) - 1) @event_callback def toggle_vis(self): if self.frame_bg.isHidden(): self.frame_bg.show() self.raise_() else: self.frame_bg.hide() def title_toggle_vis(self): if not self.__was_dragging__: self.toggle_vis() if self.frame_bg.isHidden(): self.title_button.wrtReparentTo(self.frame) self.title_button['frameColor'] = (1, 1, 1, .5) # TODO else: self.title_button.wrtReparentTo(self.frame_bg) self.title_button['frameColor'] = (1, 1, 1, 0) # TODO else: self.__was_dragging__ = False def __startDrag(self, crap): self.raise_() self._ox, self._oy = base.mouseWatcherNode.getMouse() taskMgr.add(self.__drag, 'dragging %s' % self.title) self.origBTprefix = self.BT.getPrefix() self.BT.setPrefix('dragging frame') def __drag(self, task): if base.mouseWatcherNode.hasMouse(): x, y = base.mouseWatcherNode.getMouse() if x != self._ox or y != self._oy: m_old = aspect2d.getRelativePoint( render2d, Point3(self._ox, self._oy, 0)) m_new = aspect2d.getRelativePoint(render2d, Point3(x, y, 0)) dx, dy, _ = m_new - m_old self.setPos(self.x + dx, self.y + dy) self._ox = x self._oy = y self.__was_dragging__ = True return task.cont def __stopDrag(self, crap): taskMgr.remove('dragging %s' % self.title) self.BT.setPrefix(self.origBTprefix) def setPos(self, x, y): """ actually sets the title button position since it is really the parent node """ self.x = x self.y = y #- self.text_h # FIXME is hard :/ self.frame_bg.setPos(LVecBase3f(x, 0, y)) if self.frame_bg.isHidden(): self.title_button.setPos(LVecBase3f(x, 0, y - self.text_h)) def __enter__(self): #load the position #load other saved state pass def __exit__(self): #save the position! #save other state pass
class DirectWindow( DirectFrame ): def __init__( self, pos = ( -.5, .5), title = 'Title', curSize = (1, 1), maxSize = ( 1, 1 ), minSize = ( .5, .5 ), backgroundColor = ( 0, 0, 1, .6), borderColor = ( 1, 1, 1, 1 ), titleColor = ( 1, 1, 1, 1 ), borderSize = 0.04, titleSize = 0.06, closeButton = False, resizeButton = True, windowParent = aspect2d, preserve = True, preserveWhole = True, ): self.preserve = preserve self.preserveWhole = preserveWhole self.windowParent = windowParent self.windowPos = pos DirectFrame.__init__( self, parent = aspect2d, pos = ( self.windowPos[0], 0, self.windowPos[1] ), frameColor = ( 0, 0, 0, 0 ), frameTexture = loader.loadTexture( DIRECTORY+'transparent.png' ) ) self.setTransparency(True) # the title part of the window, drag around to move the window self.headerHeight = titleSize h = -self.headerHeight self.windowHeaderLeft = DirectButton( parent = self, frameTexture = DEFAULT_TITLE_GEOM_LEFT, frameSize = ( -.5, .5, -.5, .5 ), borderWidth = ( 0, 0 ), relief = DGG.FLAT, frameColor = titleColor, ) self.windowHeaderCenter = DirectButton( parent = self, frameTexture = DEFAULT_TITLE_GEOM_CENTER, frameSize = ( -.5, .5, -.5, .5 ), borderWidth = ( 0, 0 ), relief = DGG.FLAT, frameColor = titleColor, ) if closeButton: rightTitleGeom = DEFAULT_TITLE_GEOM_RIGHT_CLOSE command = self.destroy else: rightTitleGeom = DEFAULT_TITLE_GEOM_RIGHT command = None self.windowHeaderRight = DirectButton( parent = self, frameTexture = rightTitleGeom, frameSize = ( -.5, .5, -.5, .5 ), borderWidth = ( 0, 0 ), relief = DGG.FLAT, frameColor = titleColor, command = command ) self.windowHeaderLeft.setTransparency(True) self.windowHeaderCenter.setTransparency(True) self.windowHeaderRight.setTransparency(True) self.windowHeaderLeft.bind( DGG.B1PRESS, self.startWindowDrag ) self.windowHeaderCenter.bind( DGG.B1PRESS, self.startWindowDrag ) self.windowHeaderRight.bind( DGG.B1PRESS, self.startWindowDrag ) # this is not handled correctly, if a window is dragged which has been # created before another it will not be released # check the bugfixed startWindowDrag function #self.windowHeader.bind(DGG.B1RELEASE,self.stopWindowDrag) text = TextNode('WindowTitleTextNode') text.setText(title) text.setAlign(TextNode.ACenter) text.setTextColor( 0, 0, 0, 1 ) text.setShadow(0.05, 0.05) text.setShadowColor( 1, 1, 1, 1 ) self.textNodePath = self.attachNewNode(text) self.textNodePath.setScale(self.headerHeight*0.8) # the content part of the window, put stuff beneath # contentWindow.getCanvas() to put it into it self.maxVirtualSize = maxSize self.minVirtualSize = minSize self.resizeSize = borderSize self.contentWindow = DirectScrolledFrame( parent = self, pos = ( 0, 0, -self.headerHeight ), canvasSize = ( 0, self.maxVirtualSize[0], 0, self.maxVirtualSize[1] ), frameColor = ( 0, 0, 0, 0), # defines the background color of the resize-button relief = DGG.FLAT, borderWidth = (0, 0), verticalScroll_frameSize = [0, self.resizeSize, 0, 1], horizontalScroll_frameSize = [0, 1, 0, self.resizeSize], # resize the scrollbar according to window size verticalScroll_resizeThumb = False, horizontalScroll_resizeThumb = False, # define the textures for the scrollbars verticalScroll_frameTexture = VERTICALSCROLL_FRAMETEXTURE, verticalScroll_incButton_frameTexture = VERTICALSCROLL_INCBUTTON_FRAMETEXTURE, verticalScroll_decButton_frameTexture = VERTICALSCROLL_DECBUTTON_FRAMETEXTURE, verticalScroll_thumb_frameTexture = VERTICALSCROLL_TUMB_FRAMETEXTURE, horizontalScroll_frameTexture = HORIZONTALSCROLL_FRAMETEXTURE, horizontalScroll_incButton_frameTexture = HORIZONTALSCROLL_INCBUTTON_FRAMETEXTURE, horizontalScroll_decButton_frameTexture = HORIZONTALSCROLL_DECBUTTON_FRAMETEXTURE, horizontalScroll_thumb_frameTexture = HORIZONTALSCROLL_TUMB_FRAMETEXTURE, # make all flat, so the texture is as we want it verticalScroll_relief = DGG.FLAT, verticalScroll_thumb_relief = DGG.FLAT, verticalScroll_decButton_relief = DGG.FLAT, verticalScroll_incButton_relief = DGG.FLAT, horizontalScroll_relief = DGG.FLAT, horizontalScroll_thumb_relief = DGG.FLAT, horizontalScroll_decButton_relief = DGG.FLAT, horizontalScroll_incButton_relief = DGG.FLAT, # colors verticalScroll_frameColor = borderColor, verticalScroll_incButton_frameColor = borderColor, verticalScroll_decButton_frameColor = borderColor, verticalScroll_thumb_frameColor = borderColor, horizontalScroll_frameColor = borderColor, horizontalScroll_incButton_frameColor = borderColor, horizontalScroll_decButton_frameColor = borderColor, horizontalScroll_thumb_frameColor = borderColor, ) self.contentWindow.setTransparency(True) # background color self.backgroundColor = DirectFrame( parent = self.contentWindow.getCanvas(), frameSize = ( 0, self.maxVirtualSize[0], 0, self.maxVirtualSize[1] ), frameColor = backgroundColor, relief = DGG.FLAT, borderWidth = ( .01, .01), ) self.backgroundColor.setTransparency(True) # Add a box self.box = boxes.VBox(parent = self.getCanvas()) # is needed for some nicer visuals of the resize button (background) self.windowResizeBackground = DirectButton( parent = self, frameSize = ( -.5, .5, -.5, .5 ), borderWidth = ( 0, 0 ), scale = ( self.resizeSize, 1, self.resizeSize ), relief = DGG.FLAT, frameColor = backgroundColor, ) # the resize button of the window if resizeButton: self.windowResize = DirectButton( parent = self, frameSize = ( -.5, .5, -.5, .5 ), borderWidth = ( 0, 0 ), scale = ( self.resizeSize, 1, self.resizeSize ), relief = DGG.FLAT, frameTexture = DEFAULT_RESIZE_GEOM, frameColor = borderColor, ) self.windowResize.setTransparency(True) self.windowResize.bind(DGG.B1PRESS,self.startResizeDrag) self.windowResize.bind(DGG.B1RELEASE,self.stopResizeDrag) else: self.windowResize = DirectFrame() # offset then clicking on the resize button from the mouse to the resizebutton # position, required to calculate the position / scaling self.offset = None self.taskName = "resizeTask-%s" % str(hash(self)) # do sizing of the window (minimum) #self.resize( Vec3(0,0,0), Vec3(0,0,0) ) # maximum #self.resize( Vec3(100,0,-100), Vec3(0,0,0) ) self.resize( Vec3(curSize[0], 0, -curSize[1]), Vec3(0,0,0)) self.widgets = [] def getCanvas(self): return self.contentWindow.getCanvas() # dragging functions def startWindowDrag( self, param ): self.wrtReparentTo( aspect2dMouseNode ) self.ignoreAll() self.accept( 'mouse1-up', self.stopWindowDrag ) def stopWindowDrag( self, param=None ): # this is called 2 times (bug), so make sure it's not already parented to aspect2d if self.getParent() != self.windowParent: self.wrtReparentTo( self.windowParent ) if self.preserve: if self.preserveWhole: if self.getZ() > 1: self.setZ(1) elif self.getZ() < -1 - self.getHeight(): self.setZ(-1 - self.getHeight()) if self.getX() > base.a2dRight - self.getWidth(): self.setX(base.a2dRight - self.getWidth()) elif self.getX() < base.a2dLeft: self.setX(base.a2dLeft) else: if self.getZ() > 1: self.setZ(1) elif self.getZ() < -1 + self.headerHeight: self.setZ(-1 + self.headerHeight) if self.getX() > base.a2dRight - self.headerHeight: self.setX(base.a2dRight - self.headerHeight) elif self.getX() < base.a2dLeft + self.headerHeight - self.getWidth(): self.setX(base.a2dLeft + self.headerHeight - self.getWidth()) #else: #Window moved beyond reach. Destroy window? # resize functions def resize( self, mPos, offset ): mXPos = max( min( mPos.getX(), self.maxVirtualSize[0] ), self.minVirtualSize[0]) mZPos = max( min( mPos.getZ(), -self.minVirtualSize[1] ), -self.maxVirtualSize[1]-self.headerHeight) self.windowResize.setPos( mXPos-self.resizeSize/2., 0, mZPos+self.resizeSize/2. ) self.windowResizeBackground.setPos( mXPos-self.resizeSize/2., 0, mZPos+self.resizeSize/2. ) self['frameSize'] = (0, mXPos, 0, mZPos) self.windowHeaderLeft.setPos( self.headerHeight/2., 0, -self.headerHeight/2. ) self.windowHeaderLeft.setScale( self.headerHeight, 1, self.headerHeight ) self.windowHeaderCenter.setPos( mXPos/2., 0, -self.headerHeight/2. ) self.windowHeaderCenter.setScale( mXPos - self.headerHeight*2., 1, self.headerHeight ) self.windowHeaderRight.setPos( mXPos-self.headerHeight/2., 0, -self.headerHeight/2. ) self.windowHeaderRight.setScale( self.headerHeight, 1, self.headerHeight ) self.contentWindow['frameSize'] = ( 0, mXPos, mZPos+self.headerHeight, 0) self.textNodePath.setPos( mXPos/2., 0, -self.headerHeight/3.*2. ) # show and hide that small background for the window sizer if mXPos == self.maxVirtualSize[0] and \ mZPos == -self.maxVirtualSize[1]-self.headerHeight: self.windowResizeBackground.hide() else: self.windowResizeBackground.show() def resizeTask( self, task=None ): mPos = aspect2dMouseNode.getPos( self )+self.offset self.resize( mPos, self.offset ) return task.cont def startResizeDrag( self, param ): self.offset = self.windowResize.getPos( aspect2dMouseNode ) taskMgr.remove( self.taskName ) taskMgr.add( self.resizeTask, self.taskName ) def stopResizeDrag( self, param ): taskMgr.remove( self.taskName ) # get the window to the front self.wrtReparentTo( self.windowParent ) def addHorizontal(self, widgets): """ Accepts a list of directgui objects which are added to a horizontal box, which is then added to the vertical stack. """ hbox = boxes.HBox() for widget in widgets: widget.setScale(0.05) hbox.pack(widget) self.widgets.append(widget) self.box.pack(hbox) self.updateMaxSize() def addVertical(self, widgets): """ Accepts a list of directgui objects which are added to a vertical box, which is then added to the vertical stack. May cause funky layout results. """ for widget in widgets: widget.setScale(0.05) self.box.pack(widget) self.widgets.append(widget) self.updateMaxSize() def add(self, widgets): """Shortcut function for addVertical""" self.addVertical(widgets) def updateMaxSize(self): """Updates the max canvas size to include all items packed. Window is resized to show all contents.""" bottomLeft, topRight = self.box.getTightBounds() self.maxVirtualSize = (topRight[0], -bottomLeft[2]) if self.minVirtualSize[0] > self.maxVirtualSize[0]: self.minVirtualSize = (self.maxVirtualSize[0], self.minVirtualSize[1]) if self.minVirtualSize[1] > self.maxVirtualSize[1]: self.minVirtualSize = (self.minVirtualSize[0], self.maxVirtualSize[1]+self.headerHeight) self.contentWindow['canvasSize'] = ( 0, self.maxVirtualSize[0], -self.maxVirtualSize[1], 0) self.backgroundColor['frameSize'] = ( 0, self.maxVirtualSize[0], -self.maxVirtualSize[1], 0 ) # For CityMania Onlue self.reset() self.center() def reset(self): """Poorly named function that resizes window to fit all contents""" self.resize( Vec3(self.maxVirtualSize[0], 0, -self.maxVirtualSize[1]-self.headerHeight), Vec3(0,0,0)) def center(self): """Centers window on screen""" self.setPos(-self.maxVirtualSize[0]/2.0, 0, (self.maxVirtualSize[1]+self.headerHeight)/2.0) def getEntries(self): """Returns the fields for any entires""" entries = [] for widget in self.widgets: if isinstance(widget, DirectEntry): entries.append(widget.get()) return entries def addScrolledList(self, items, numItemsVisible = 4, itemHeight = 1): '''Adds a list of items into a scrolled list''' scrolled_list = DirectScrolledList( decButton_pos= (0.35, 0, 5), decButton_text = "Up", decButton_borderWidth = (0.005, 0.005), incButton_pos= (0.35, 0, -5), incButton_text = "Down", incButton_borderWidth = (0.005, 0.005), frameSize = (-5, 5, -5, 5), frameColor = (1,0,1,0.5), pos = (-1, 0, 0), items = items, numItemsVisible = numItemsVisible, forceHeight = itemHeight, itemFrame_frameSize = (-5, 5, -5, 5), itemFrame_pos = (0.35, 0, 0.4), scale = (0.05), #parent = (aspect2d), ) scrolled_list.updateFrameStyle() self.add([scrolled_list])
def add_button(self, text, label_id, pos_x, pos_y, width=0.0, hight=0.1): if width == 0.0: for c in range(len(text) / 2): width += 0.08 ls = LineSegs("lines") ls.setColor(0, 1, 0, 1) ls.drawTo(-width / 2, 0, hight / 2) ls.drawTo(width / 2, 0, hight / 2) ls.drawTo(width / 2, 0, -hight / 2) ls.drawTo(-width / 2, 0, -hight / 2) ls.drawTo(-width / 2, 0, hight / 2) border = ls.create(False) border.setTag('back_ground', '1') array = GeomVertexArrayFormat() array.addColumn("vertex", 4, Geom.NTFloat32, Geom.CPoint) arr_format = GeomVertexFormat() arr_format.addArray(array) arr_format = GeomVertexFormat.registerFormat(arr_format) vdata = GeomVertexData('fill', arr_format, Geom.UHStatic) vdata.setNumRows(4) vertex = GeomVertexWriter(vdata, 'vertex') vertex.addData3f(-width / 2, 0, hight / 2) vertex.addData3f(width / 2, 0, hight / 2) vertex.addData3f(-width / 2, 0, -hight / 2) vertex.addData3f(width / 2, 0, -hight / 2) prim = GeomTristrips(Geom.UHStatic) prim.addVertex(0) prim.addVertex(1) prim.addVertex(2) prim.addVertex(3) geom = Geom(vdata) geom.addPrimitive(prim) node = GeomNode('gnode') node.addGeom(geom) nodePath = NodePath("button") nodePath.attachNewNode(node) nodePath.setPos(0, 0, 0) nodePath.setTag('button', '1') nodePath.setBin("unsorted", 0) nodePath.setDepthTest(False) nodePath.setColor(0, 0, 0, 1) nodePath.attachNewNode(border) nodePath1 = NodePath("button") nodePath1.attachNewNode(node) nodePath1.setPos(0, 0, 0) nodePath1.setTag('button1', '1') nodePath1.setBin("unsorted", 0) nodePath1.setDepthTest(False) nodePath1.setColor(0, 1, 0, 1) nodePath1.attachNewNode(border) button = DirectFrame(enableEdit=1, text=text, geom=nodePath, text_scale=0.05, text_fg=(0, 1, 0, 1), borderWidth=(1, 1), relief=None, text_pos=(0, -0.01, 0), textMayChange=1, state=DGG.NORMAL, parent=aspect2d) button.setPos(pos_x, 0, pos_y) button.bind(DGG.B1PRESS, button_click, [button]) button.bind(DGG.WITHIN, button_hover, [button]) button.bind(DGG.WITHOUT, button_no_hover, [button]) # button.resetFrameSize() # self.button.bind(DGG.WITHIN, self.onMouseHoverInFunction, [button, some_value1]) defines.ENTITIES[defines.ENTITY_ID] = { 'CATEGORY': 'button', 'BUTTON': button, 'NODE': nodePath, 'LABEL': label_id, 'STATUS': 0 } defines.ENTITY_ID += 1
def setPos(self, *args, **kwargs): DirectFrame.setPos(self, *args, **args) self.resetArcBall()
class GuiFrame(DirectObject, HasKeybinds): #should be able to show/hide, do conditional show hide #position where you want #parent to other frames TEXT_MAGIC_NUMBER = .833333333334 #5/6 ?!? DRAW_ORDER={ 'frame':('unsorted',0), 'frame_bg':('unsorted', 0), 'items':('unsorted', 0), 'title':('unsorted', 0), 'border':('unsorted', 0), } def __init__(self, title, shortcut = None, # XXX obsolete, but needs a non deco replacement x = 0, y = .1, width = .2, height = .8, #scale = .05, # there is some black magic here :/ bdr_thickness = 2, bdr_color = (.1, .1, .1, 1), bg_color = (.7, .7, .7, .5), text_color = (0, 0, 0, 1), text_font = TextNode.getDefaultFont(), #text_h = .05, # do not use directly text_height_mm = 4, items = tuple(), ): #item_w_pad = 1 #item_h_pad = 1 self.title = title self.do_xywh(x, y, width, height) self.bdr_thickness = bdr_thickness # FIXME ?? self.bdr_color = bdr_color self.bg_color = bg_color self.text_color = text_color self.text_font = text_font self.text_height_mm = text_height_mm #set up variables self.__winx__ = base.win.getXSize() self.__winy__ = base.win.getYSize() self.__ar__ = base.camLens.getAspectRatio() self.__was_dragging__ = False self.__first_item__ = None self.__add_head__ = None self.items = OrderedDict() # ordered dict to allow sequential addition #self.BT = buttonThrower if buttonThrower else base.buttonThrowers[0].node() self.BT = base.buttonThrowers[0].node() # get our aspect ratio, and pixels per mm self.pixels_per_mm = render.getPythonTag('system_data')['max_ppmm'] self.getWindowData() self.accept('window-event', self.getWindowData) #set the text height using the above data self.setTextHeight() # get the root for all frames in the scene self.frameRoot = aspect2d.find('frameRoot') if not self.frameRoot: self.frameRoot = aspect2d.attachNewNode('frameRoot') # create the parent node for this frame #parent = self.frameRoot.find('frame-*') #if not parent: #parent = self.frameRoot self.frame = self.frameRoot.attachNewNode('frame-%s-%s'%(title, id(self))) self.frame.setBin(*self.DRAW_ORDER['frame']) # background l,r,b,t = 0, self.width, 0, self.height self.frame_bg = DirectFrame(parent=self.frame, frameColor=self.bg_color, pos=LVecBase3f(self.x, 0, self.y), frameSize=(l,r,b,t), state=DGG.NORMAL, # FIXME framesize is >_< suppressMouse=1) self.frame_bg.setBin(*self.DRAW_ORDER['frame_bg']) # border self.__make_border__(self.frame_bg, self.bdr_thickness, self.bdr_color, l, r, b, t) # setup for items self.itemsParent = self.frame_bg.attachNewNode('items parent') # title self.title_button = self.__create_item__(title, self.title_toggle_vis) # add any items that we got for item in items: self.__create_item__(*item) # FIXME when we call frame adjust we will loose the record of any data items # dragging self.title_button.bind(DGG.B1PRESS, self.__startDrag) self.title_button.bind(DGG.B1RELEASE, self.__stopDrag) # raise if we click the frame background self.frame_bg.bind(DGG.B1PRESS, self.raise_) #self.frame_bg.bind(DGG.B1RELEASE, self.__stopDrag) # this can cause problems w/ was dragging # toggle vis if shortcut: self.accept(shortcut, self.toggle_vis) # adjust the frame self.frame_adjust() @property def text_s(self): return self.text_h * self.TEXT_MAGIC_NUMBER def setTextHeight(self): h_units = 2 * base.a2dTop units_per_pixel = h_units / self.__winy__ text_h = self.text_height_mm * self.pixels_per_mm * units_per_pixel self.text_h = text_h def do_xywh(self, x, y, w, h): """ makes negative wneg xidths and heights work as well as negative x and y (bottom right is 0) """ if x < 0: x = 1 + x if y < 0: y = 1 + y if w < 0: x, w = x + w, -w if h < 0: y, h = y + h, -h self.x = self.fix_x(x) # for top left self.y = self.fix_y(y) # for top left self.width = self.fix_w(w) self.height = self.fix_h(h) def getWindowData(self, window=None): x = base.win.getXSize() y = base.win.getYSize() if x != self.__winx__ or y != self.__winy__: self.__ar__ = base.camLens.getAspectRatio() # w/h self.__winx__ = x self.__winy__ = y self.frame_adjust() def raise_(self, *args): """ function that raises windows call FIRST inside any function that should raise """ self.frame.reparentTo(self.frameRoot) # self.frame doesn't move so no wrt def frame_adjust(self): # FIXME sometimes this fails to call, also calls too often at startup self.setTextHeight() MI = self.getMaxItems() # does not count title >_< LI = len(self.items) DI = MI - LI if DI >= 0: for i in range(DI+1): self.__create_item__(' blank') else: for i in range(-(DI+1)): k,v = self.items.popitem() # remove the last nodes in order v.removeNode() # FIXME consider keeping these around? for k,b in self.items.items(): if k == 'title': if self.frame_bg.isHidden(): x, y, z = self.frame_bg.getPos() self.title_button.setPos(LVecBase3f(x, y , z-self.text_h)) else: self.title_button.setPos(LVecBase3f(0, 0, -self.text_h)) elif k == self.__first_item__: b.setPos(LVecBase3f(0, 0, -(self.text_h * 2))) else: b.setPos(LVecBase3f(0, 0, -self.text_h)) b['frameSize'] = 0, self.width, 0, self.text_h b['text_scale'] = self.text_s, self.text_s b['text_pos'] = 0, self.text_h - self.TEXT_MAGIC_NUMBER * self.text_s def getWindowSize(self, event=None): # TODO see if we really need this self.__winx__ = base.win.getXSize() self.__winy__ = base.win.getYSize() m = max(self.__winx__, self.__winy__) self.__xscale__ = self.__winx__ / m self.__yscale__ = self.__winy__ / m # put origin in top left and positive down and right @staticmethod def fix_x(x): return (x - .5) * 2 # TODO * base.a2dLeft? @staticmethod def fix_y(y): return (y - .5) * -2 # TODO * base.a2dTop? @staticmethod def fix_w(n): return n * 2 @staticmethod def fix_h(n): return -n * 2 def add_item(self, text, command = None, args = tuple()): args = list(args) if text[0] != ' ': text = ' '+text items = list(self.items) last_slot = len(self.items) if self.__add_head__ == last_slot: print('all slots are full, cannot add item to %s'%self) return None button = self.items[items[self.__add_head__]] button['text'] = text button['command'] = command button['extraArgs'] = args + button['extraArgs'] # blank buttons always have [self,id] self.__add_head__ += 1 def __create_item__(self, text, command = None, args = tuple()): args = list(args) #if not len(self.items): #parent = self.frame if len(self.items) <= 1: parent = self.itemsParent #everyone else parents off 2nd text else: parent = list(self.items.values())[-1] if command != None: def cmd(*args): """ any item should raise """ self.raise_() command(*args) else: cmd = self.raise_ b = DirectButton( parent=parent, frameColor=(1,1,1,.0), # a = 0 => no border overlap frameSize=(0, self.width, 0, self.text_h), text=' '+text, # hack to keep spacing from border text_font=self.text_font, text_fg=self.text_color, text_scale=self.text_s, text_pos=(0, self.text_h - self.TEXT_MAGIC_NUMBER * self.text_s), command=cmd, relief=DGG.FLAT, text_align=TextNode.ALeft, ) b.setPos(LVecBase3f(0, 0, -self.text_h)) b.setName('DirectButton-'+text) if not len(self.items): self.items['title'] = b b.setBin(*self.DRAW_ORDER['title']) else: b['extraArgs'] = args+[self, id(b)] b.node().setPythonTag('id', id(b)) b.setBin(*self.DRAW_ORDER['items']) if len(self.items) is 1: # the first item that is not the title b.setPos(LVecBase3f(0, 0, -(self.text_h * 2))) self.__first_item__ = id(b) self.items[id(b)] = b if text == ' blank': if self.__add_head__ is None: self.__add_head__ = 1 return b def del_all(self): if self.__first_item__ != None: for id_, button in self.items.items(): if id_ != 'title': button['text'] = ' blank' button['command'] = None button['extraArgs'] = [self, id_] self.__add_head__ = 1 def del_item(self, text): # FIXME uniqueness problems #d = self.itemsParent.find('*%s*'%text) if text[0] != ' ': text = ' '+text d = [i for i in self.items.values() if i.getName().count(text)] try: self.__del_item__(d[0].getPythonTag('id')) except IndexError: print('that item does not seem to exist') # if we have a name then there shouldn't be key errors def __del_item__(self, index): """ I have no idea how this is going to work """ out = self.items[index] p = out.getParent() if out.getNumChildren(): # avoid the printing of the AssertionError :/ c = out.getChild(0) c.reparentTo(p) if index == self.__first_item__: # XXX is fails, ints from id != c.setPos(LVecBase3f(out.getPos())) id_ = c.getPythonTag('id') self.__first_item__ = id_ out.setPos(LVecBase3f(0, 0, -self.text_h)) self.items.pop(index) parent = list(self.items.values())[-1] out['text'] = ' del blank' #out['command'] = None out['extraArgs'] = [self, index] out.reparentTo(parent) self.items[index] = out if self.__add_head__ > 1: # title is always at 0 self.__add_head__ -= 1 @classmethod def __make_border__(cls, parent, thickness, color, l, r , b, t): moveto_drawto = ( ((l,0,t), (l,0,b)), ((r,0,t), (r,0,b)), ((l,0,b), (r,0,b)), ((l,0,t), (r,0,t)), ) for moveto, drawto in moveto_drawto: Border = LineSegs() Border.setThickness(thickness) Border.setColor(*color) Border.moveTo(*moveto) Border.drawTo(*drawto) b = parent.attachNewNode(Border.create()) b.setBin(*cls.DRAW_ORDER['border']) def getMaxItems(self): return int(abs(self.height / self.text_h) - 1) @event_callback def toggle_vis(self): if self.frame_bg.isHidden(): self.frame_bg.show() self.raise_() else: self.frame_bg.hide() def title_toggle_vis(self): if not self.__was_dragging__: self.toggle_vis() if self.frame_bg.isHidden(): self.title_button.wrtReparentTo(self.frame) self.title_button['frameColor'] = (1, 1, 1, .5) # TODO else: self.title_button.wrtReparentTo(self.frame_bg) self.title_button['frameColor'] = (1, 1, 1, 0) # TODO else: self.__was_dragging__ = False def __startDrag(self, crap): self.raise_() self._ox, self._oy = base.mouseWatcherNode.getMouse() taskMgr.add(self.__drag,'dragging %s'%self.title) self.origBTprefix=self.BT.getPrefix() self.BT.setPrefix('dragging frame') def __drag(self, task): if base.mouseWatcherNode.hasMouse(): x, y = base.mouseWatcherNode.getMouse() if x != self._ox or y != self._oy: m_old = aspect2d.getRelativePoint(render2d, Point3(self._ox, self._oy, 0)) m_new = aspect2d.getRelativePoint(render2d, Point3(x, y, 0)) dx, dy, _ = m_new - m_old self.setPos(self.x + dx, self.y + dy) self._ox = x self._oy = y self.__was_dragging__ = True return task.cont def __stopDrag(self,crap): taskMgr.remove('dragging %s'%self.title) self.BT.setPrefix(self.origBTprefix) def setPos(self, x, y): """ actually sets the title button position since it is really the parent node """ self.x = x self.y = y #- self.text_h # FIXME is hard :/ self.frame_bg.setPos(LVecBase3f(x, 0, y)) if self.frame_bg.isHidden(): self.title_button.setPos(LVecBase3f(x, 0, y - self.text_h)) def __enter__(self): #load the position #load other saved state pass def __exit__(self): #save the position! #save other state pass
class CharGen(): def __init__(self): self.text = "CharGen" self.textObject = OnscreenText(text=self.text, pos=(0.95, -0.95), scale=0.07, fg=(1, 0.5, 0.5, 1), align=TextNode.ACenter, mayChange=1) self.f = DirectFrame(frameColor=(1, 1, 1, 0.5), frameSize=(-1, 1, -0.4, 0.4)) self.f.setPos(-0.5, 0, -0.5) self.flavorText = OnscreenText("Primary Colour", pos=(0, 0, 0.4), scale=0.07, align=TextNode.ACenter, mayChange=1, fg=(1, 1, 1, 1)) self.flavorText.reparent_to(self.f) self.flavorText.setPos(0, 0.2) #slider R self.sR = DirectSlider(self.f, range=(0, 1), value=0, pageSize=3, command=self.setCol) self.sR.setScale(0.5, 0.5, 0.5) self.sR.setPos(0, 0, 0) self.sR.setColor(1, 0, 0) #slider G self.sG = DirectSlider(self.f, range=(0, 1), value=0, pageSize=3, command=self.setCol) self.sG.setScale(0.5, 0.5, 0.5) self.sG.setPos(0, 0, -0.1) self.sG.setColor(0, 1, 0) #slider B self.sB = DirectSlider(self.f, range=(0, 1), value=0, pageSize=3, command=self.setCol) self.sB.setScale(0.5, 0.5, 0.5) self.sB.setPos(0, 0, -0.2) self.sB.setColor(0, 0, 1) self.pandaActor = Actor("models/panda-model", {"walk": "models/panda-walk4"}) self.pandaActor.setScale(0.005, 0.005, 0.005) self.pandaActor.setPos(0.8, 12, -0.5) self.pandaActor.reparentTo(base.render) def setCol(self): #print(self.s['value']) self.pandaActor.setColor(self.sR['value'], self.sG['value'], self.sB['value'])
def add_button(self, text, label_id, pos_x, pos_y, width=0.0, hight=0.1): if width == 0.0: for c in range(len(text)/2): width += 0.08 ls = LineSegs("lines") ls.setColor(0,1,0,1) ls.drawTo(-width/2, 0, hight/2) ls.drawTo(width/2, 0, hight/2) ls.drawTo(width/2, 0,-hight/2) ls.drawTo(-width/2, 0,-hight/2) ls.drawTo(-width/2, 0, hight/2) border = ls.create(False) border.setTag('back_ground', '1') array = GeomVertexArrayFormat() array.addColumn("vertex", 4, Geom.NTFloat32, Geom.CPoint) arr_format = GeomVertexFormat() arr_format.addArray(array) arr_format = GeomVertexFormat.registerFormat(arr_format) vdata = GeomVertexData('fill', arr_format, Geom.UHStatic) vdata.setNumRows(4) vertex = GeomVertexWriter(vdata, 'vertex') vertex.addData3f(-width/2, 0, hight/2) vertex.addData3f(width/2, 0, hight/2) vertex.addData3f(-width/2, 0,-hight/2) vertex.addData3f(width/2, 0,-hight/2) prim = GeomTristrips(Geom.UHStatic) prim.addVertex(0) prim.addVertex(1) prim.addVertex(2) prim.addVertex(3) geom = Geom(vdata) geom.addPrimitive(prim) node = GeomNode('gnode') node.addGeom(geom) nodePath = NodePath("button") nodePath.attachNewNode(node) nodePath.setPos(0,0,0) nodePath.setTag('button', '1') nodePath.setBin("unsorted", 0) nodePath.setDepthTest(False) nodePath.setColor(0,0,0,1) nodePath.attachNewNode(border) nodePath1 = NodePath("button") nodePath1.attachNewNode(node) nodePath1.setPos(0,0,0) nodePath1.setTag('button1', '1') nodePath1.setBin("unsorted", 0) nodePath1.setDepthTest(False) nodePath1.setColor(0,1,0,1) nodePath1.attachNewNode(border) button=DirectFrame( enableEdit=1, text=text, geom=nodePath, text_scale=0.05, text_fg=(0,1,0,1), borderWidth=(1,1), relief = None, text_pos=(0,-0.01,0), textMayChange=1, state=DGG.NORMAL, parent=aspect2d ) button.setPos(pos_x,0,pos_y) button.bind(DGG.B1PRESS, button_click, [button]) button.bind(DGG.WITHIN, button_hover, [button]) button.bind(DGG.WITHOUT, button_no_hover, [button]) # button.resetFrameSize() # self.button.bind(DGG.WITHIN, self.onMouseHoverInFunction, [button, some_value1]) defines.ENTITIES[defines.ENTITY_ID] = {'CATEGORY':'button', 'BUTTON':button, 'NODE':nodePath, 'LABEL':label_id,'STATUS': 0} defines.ENTITY_ID += 1