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 __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
class InventoryView: """ Renders the inventory screen. """ ButtonStateNormal = 1 ButtonStatePressed = 2 ButtonStateHover = 3 POINTER_NAME = "inventory_pointer" INVENTORY_SCENE_NODE = "inventory_sceneNode" ICONS_NODE = "inventory_icons_node" BACKDROP_NODE = "backdrop" TEXT_NODE = "item_text" def __init__(self, game): self.log = logging.getLogger('pano.inventoryView') self.game = game self.msn = Messenger( self ) # the messenger is used to broadcast user events related to the interface self.inventory = None # the inventory to render self.node = None # the root scenegraph node for inventory rendering nodes self.iconsNode = None # the parent node for all OnscreenImages that render items' icons self.pos = (0.0, 0.0) # position in absolute screen coordinates self.size = (1.0, 1.0) # size in absolute screen coordinates self.textPos = (0.0, 0.0) # position of the item's description text self.textScale = 0.07 # the text scale self.opacity = 1.0 # controls the opacity of all rendering elements included in the inventory self.backdropImage = None # the name of the image to use as a backdrop self.backdropImageObject = None # the OnscreenImage object used to render the backdrop self.backdropNode = None # the scenegraph node that parents the backdrop self.updateIcons = False # if True then we need to update the rendering of the items' icons self.itemText = None # the TextNode used to render the text self.itemTextNode = None # nodepath that acts as a parent to the TextNode self.fontName = None # the name of the font to use when rendering items' descriptions self.font = None # the Panda3D font resource self.fontColor = (1.0, 1.0, 1.0, 1.0 ) # colour of the text for an item's description self.fontBgColor = (0.0, 0.0, 0.0, 1.0 ) # background colour of the text # scrolling and paging buttons are DirectButton instances self.nextPageButton = None self.prevPageButton = None self.scrollNextButton = None self.scrollPrevButton = None # specifies the range of items to be rendered in the next frame as a list [start_item_index, end_item_index] # used for scrolling and paging self.itemsRange = None # number of items displayed per page self.pageSize = 0 # provides the layout of the slots self.slotsLayout = None # stores image objects for each item's icon self.itemIcons = [] self.mousePointer = InventoryView.POINTER_NAME self.debugLayout = False def initialize(self, inventory): """ Initialises the inventory, call this method only once otherwise resources could be leaked and rendering artifacts created. """ if self.node is not None: self.node.removeNode() # self.node.detachNode() self.node = aspect2d.attachNewNode(InventoryView.INVENTORY_SCENE_NODE) self.iconsNode = self.node.attachNewNode(InventoryView.ICONS_NODE) # from here on we just initialize the member fields according to the cvars... cfg = self.game.getConfig() if not self._validateConfig(cfg): self.log.error('Missing or invalid inventory configuration') return view = self.game.getView() if self.backdropImageObject is not None: self.backdropImageObject.destroy() self.backdropImageObject = None self.pos = cfg.getVec2(PanoConstants.CVAR_INVENTORY_POS) if self.pos is None: self.pos = cfg.getVec2(PanoConstants.CVAR_INVENTORY_REL_POS) self.pos = view.relativeToAbsolute(self.pos) self.textPos = cfg.getVec2(PanoConstants.CVAR_INVENTORY_TEXT_POS) if self.textPos is None: self.textPos = cfg.getVec2(PanoConstants.CVAR_INVENTORY_REL_POS) self.textPos = view.relativeToAbsolute(self.textPos) self.pos, self.textPos = PandaUtil.convertScreenToAspectCoords( [self.pos, self.textPos]) self.size = cfg.getVec2(PanoConstants.CVAR_INVENTORY_SIZE, (1.0, 1.0)) self.textScale = cfg.getFloat(PanoConstants.CVAR_INVENTORY_TEXT_SCALE, 0.07) self.opacity = cfg.getFloat(PanoConstants.CVAR_INVENTORY_OPACITY) self.fontName = cfg.get(PanoConstants.CVAR_INVENTORY_FONT) self.fontColor = cfg.getVec4(PanoConstants.CVAR_INVENTORY_FONT_COLOR) if self.fontColor is None: self.fontColor = (1.0, 1.0, 1.0, 1.0) self.fontBgColor = cfg.getVec4( PanoConstants.CVAR_INVENTORY_FONT_BG_COLOR) if self.fontBgColor is None: self.fontBgColor = (0.0, 0.0, 0.0, 0.0) self.mousePointer = cfg.get(PanoConstants.CVAR_INVENTORY_POINTER) layout = cfg.get(PanoConstants.CVAR_INVENTORY_SLOTS) self._parseLayout(layout) slotsCount = self.slotsLayout.getNumSlots() self.log.debug('Setting slots count to %i' % slotsCount) # by default render all items, the controller state can later overridde this self.itemsRange = [0, slotsCount] if cfg.hasVar(PanoConstants.CVAR_INVENTORY_PAGESIZE): self.pageSize = cfg.getInt(PanoConstants.CVAR_INVENTORY_PAGESIZE) else: self.pageSize = slotsCount self.inventory = inventory self.inventory.setSlotsCount(slotsCount) self.backdropImage = cfg.get(PanoConstants.CVAR_INVENTORY_BACKDROP) if self.backdropImage is not None: self._createBackdrop(show=False) # create the scrolling and paging gui buttons self._createButtons(cfg) # force an initial rendering of the icons self.updateIcons = True # start as hidden self.node.hide() def update(self, millis): """ Re-renders anything that has updated. """ if self.isVisible() and self.updateIcons: self._renderItemsIcons() self.updateIcons = False def redraw(self): """ Called to indicate that the underlying inventory has updated its state and now we should redraw it. """ self.updateIcons = True def show(self): """ Shows the inventory. """ self.node.show() if self.nextPageButton: self.nextPageButton.show() if self.prevPageButton: self.prevPageButton.show() if self.scrollNextButton: self.scrollNextButton.show() if self.scrollPrevButton: self.scrollPrevButton.show() if self.debugLayout: self.enableDebugRendering() def hide(self): """ Hides the inventory. """ self.node.hide() if self.nextPageButton: self.nextPageButton.hide() if self.prevPageButton: self.prevPageButton.hide() if self.scrollNextButton: self.scrollNextButton.hide() if self.scrollPrevButton: self.scrollPrevButton.hide() if self.debugLayout: self.disableDebugRendering() def isVisible(self): """ Returns True if the inventory is visible and False if otherwise. """ return (self.node is not None) and (not self.node.isHidden()) def getMousePointerName(self): return self.mousePointer def getSlotAtScreenPos(self, x, y): return self.slotsLayout.getSlotAtScreenPos(x, y) def getBackdropImage(self): return self.backdropImage def setBackdropImage(self, imageName): self.backdropImage = imageName self._createBackdrop() def getText(self): return self.text def setText(self, text): self.text = text self._updateText() def clearText(self): self.text = "" if self.itemTextNode is not None: self.itemTextNode.hide() def getNode(self): return self.node def enableDebugRendering(self): self.slotsLayout.enableDebugRendering(self.game) self.debugLayout = True def disableDebugRendering(self): self.slotsLayout.disableDebugRendering(self.game) self.debugLayout = False def _validateConfig(self, config): return (config.hasVar(PanoConstants.CVAR_INVENTORY_BACKDROP) and (config.hasVar(PanoConstants.CVAR_INVENTORY_POS) or config.hasVar(PanoConstants.CVAR_INVENTORY_REL_POS)) and (config.hasVar(PanoConstants.CVAR_INVENTORY_TEXT_POS) or config.hasVar(PanoConstants.CVAR_INVENTORY_REL_POS)) and config.hasVar(PanoConstants.CVAR_INVENTORY_SIZE) and config.hasVar(PanoConstants.CVAR_INVENTORY_FONT) and config.hasVar(PanoConstants.CVAR_INVENTORY_POINTER) and config.hasVar(PanoConstants.CVAR_INVENTORY_SLOTS)) def _createBackdrop(self, show=True): """ Setups rendering for the inventory's backdrop image. The backdrop image is rendered through a OnscreenImage object and is attached under the scenegraph node named Inventory.BACKDROP_NODE. If the parameter show is True then the backdrop image becomes visible as well, otherwise it is hidden. """ if self.backdropImageObject is not None: self.backdropImageObject.destroy() self.backdropImageObject = None if self.backdropNode is not None: self.backdropNode.removeNode() imagePath = self.game.getResources().getResourceFullPath( PanoConstants.RES_TYPE_TEXTURES, self.backdropImage) self.backdropNode = self.node.attachNewNode( InventoryView.BACKDROP_NODE) self.backdropImageObject = OnscreenImage(parent=self.node, image=imagePath, pos=(self.pos[0], 0.0, self.pos[1]), sort=0) self.backdropImageObject.setTransparency(TransparencyAttrib.MAlpha) self.backdropImageObject.setBin("fixed", PanoConstants.RENDER_ORDER_INVENTORY) if not show: self.backdropNode.hide() def _updateText(self): if self.itemText is not None: self.itemText.destroy() self.itemText = None if self.itemTextNode is None: self.itemTextNode = self.node.attachNewNode(self.TEXT_NODE) self.itemTextNode.setPos(self.textPos[0], 0.0, self.textPos[1]) self.itemTextNode.show() i18n = self.game.getI18n() translated = i18n.translate(self.text) localizedFont = i18n.getLocalizedFont(self.fontName) fontPath = self.game.getResources().getResourceFullPath( PanoConstants.RES_TYPE_FONTS, localizedFont) self.font = loader.loadFont(fontPath) self.itemText = DirectButton( parent=self.itemTextNode, text=translated, text_font=self.font, text_bg=(self.fontBgColor[0], self.fontBgColor[1], self.fontBgColor[2], self.fontBgColor[3]), text_fg=(self.fontColor[0], self.fontColor[1], self.fontColor[2], self.fontColor[3]), text_scale=self.textScale, frameColor=(0, 0, 0, 0), text_wordwrap=None, text_align=TextNode.ALeft, sortOrder=10, pressEffect=0) self.itemText.setBin("fixed", PanoConstants.RENDER_ORDER_INVENTORY_ITEMS) def _parseLayout(self, layoutName): layoutName = layoutName.strip() if layoutName.startswith('grid'): # pos, res, size, offset grid_re = re.compile( r'grid\(\s*(\d+)\D+(\d+)\D+(\d+)\D+(\d+)\D+(\d+)\D+(\d+)\D+(\d+)\D+(\d+)\D+' ) m = grid_re.match(layoutName) self.slotsLayout = GridSlotsLayout( self.game, (int(m.group(1)) + self.pos[0], int(m.group(2)) + self.pos[1]), # position within inventory (int(m.group(3)), int(m.group(4))), # grid resolution (int(m.group(5)), int(m.group(6))), # slot size (int(m.group(7)), int(m.group(8)))) # slots offset elif layoutName.starts_with('image'): self.slotsLayout = ImageBasedSlotsProvider(layoutName) # a default to avoid None else: self.slotsLayout = GridSlotsLayout(self.game, 100, 100, 5, 5, 50, 50) def _renderItemsIcons(self): self.iconsNode.node().removeAllChildren() for icon in self.itemIcons: icon.destroy() self.itemIcons = [] startItem = 0 endItem = self.inventory.getSlotsCount() if self.itemsRange is not None: startItem = self.itemsRange[0] endItem = self.itemsRange[1] for i in xrange(endItem - startItem): itemNum = startItem + i s = self.inventory.getSlotByNum(itemNum) if not s.isFree(): # get slot position and size in aspect2d space p, sz = self.slotsLayout.getRelativeSlotPosSize(s.getNum()) itemImage = s.getItem().getImage() imagePath = self.game.getResources().getResourceFullPath( PanoConstants.RES_TYPE_TEXTURES, itemImage) iconNode = OnscreenImage(parent=self.iconsNode, image=imagePath, pos=(p[0] + sz[0] / 2.0, 0.0, p[1] + sz[1] / 2.0), scale=0.2) iconNode.setTransparency(TransparencyAttrib.MAlpha) iconNode.setBin("fixed", PanoConstants.RENDER_ORDER_INVENTORY_ITEMS) self.itemIcons.append(iconNode) def _createButtons(self, cfg): ''' Creates DirectGui elements for displaying the paging and scrolling buttons. The sprite names are read from the configuration. The create DirectButtons use sprites as images. @param cfg: a ConfigVars instance ''' # button to display next page of items nxPgBtnSprite = cfg.get(PanoConstants.CVAR_INVENTORY_NEXTPAGE_SPRITE) nxPgBtnPressedSprite = cfg.get( PanoConstants.CVAR_INVENTORY_NEXTPAGE_PRESSED_SPRITE) nxPgBtnHoverSprite = cfg.get( PanoConstants.CVAR_INVENTORY_NEXTPAGE_HOVER_SPRITE) nxPgBtnPos = cfg.getVec2(PanoConstants.CVAR_INVENTORY_NEXTPAGE_POS) # button to display previous page of items pvPgBtnSprite = cfg.get(PanoConstants.CVAR_INVENTORY_PREVPAGE_SPRITE) pvPgBtnPressedSprite = cfg.get( PanoConstants.CVAR_INVENTORY_PREVPAGE_PRESSED_SPRITE) pvPgBtnHoverSprite = cfg.get( PanoConstants.CVAR_INVENTORY_PREVPAGE_HOVER_SPRITE) pvPgBtnPos = cfg.getVec2(PanoConstants.CVAR_INVENTORY_PREVPAGE_POS) # button to scroll to next items scrNxBtnSprite = cfg.get( PanoConstants.CVAR_INVENTORY_SCROLLNEXT_SPRITE) scrNxBtnPressedSprite = cfg.get( PanoConstants.CVAR_INVENTORY_SCROLLNEXT_PRESSED_SPRITE) scrNxBtnHoverSprite = cfg.get( PanoConstants.CVAR_INVENTORY_SCROLLNEXT_HOVER_SPRITE) scrNxBtnPos = cfg.getVec2(PanoConstants.CVAR_INVENTORY_SCROLLNEXT_POS) # button to scroll to previous items scrPvBtnSprite = cfg.get( PanoConstants.CVAR_INVENTORY_SCROLLPREV_SPRITE) scrPvBtnPressedSprite = cfg.get( PanoConstants.CVAR_INVENTORY_SCROLLPREV_PRESSED_SPRITE) scrPvBtnHoverSprite = cfg.get( PanoConstants.CVAR_INVENTORY_SCROLLPREV_HOVER_SPRITE) scrPvBtnPos = cfg.getVec2(PanoConstants.CVAR_INVENTORY_SCROLLPREV_POS) sprites = self.game.getView().getSpritesFactory() origin = aspect2d.getRelativePoint(screen2d, VBase3(0, 0, 0)) # for every button define property name, position, callback, list of sprites for normal, pressed and hover state pagingButtons = [ ('nextPageButton', nxPgBtnPos, self._nextPageCallback, [(nxPgBtnSprite, 'next_page_sprite'), (nxPgBtnPressedSprite, 'next_page_pressed_sprite'), (nxPgBtnHoverSprite, 'next_page_hover_sprite')]), ('prevPageButton', pvPgBtnPos, self._previousPageCallback, [(pvPgBtnSprite, 'previous_page_sprite'), (pvPgBtnPressedSprite, 'previous_page_pressed_sprite'), (pvPgBtnHoverSprite, 'previous_page_hover_sprite')]), ('scrollNextButton', scrNxBtnPos, self._scrollNextCallback, [(scrNxBtnSprite, 'scroll_next_sprite'), (scrNxBtnPressedSprite, 'scroll_next_pressed_sprite'), (scrNxBtnHoverSprite, 'scroll_next_hover_sprite')]), ('scrollPrevButton', scrPvBtnPos, self._scrollPreviousCallback, [(scrPvBtnSprite, 'scroll_previous_sprite'), (scrPvBtnPressedSprite, 'scroll_previous_pressed_sprite'), (scrPvBtnHoverSprite, 'scroll_previous_hover_sprite')]), ] for buttonName, buttonPos, buttonCallback, spritesList in pagingButtons: buttonGeoms = [None, None, None, None] btnScrBounds = [0, 0, 0] i = 0 for spriteFile, spriteName in spritesList: print 'adding sprite %s' % spriteName if spriteFile is not None: spr = None if spriteFile.rindex('.') >= 0: ext = spriteFile[spriteFile.rindex('.'):] print ext if ResourcesTypes.isExtensionOfType( ext, PanoConstants.RES_TYPE_IMAGES): spr = Sprite(spriteName) spr.image = spriteFile else: spr = self.game.getResources().loadSprite(spriteFile) if spr: buttonGeoms[i] = sprites.createSprite(spr).nodepath buttonGeoms[i].setScale(1.0) btnScrBounds = aspect2d.getRelativePoint( screen2d, VBase3(spr.width, 1.0, spr.height)) - origin btnScrBounds[2] *= -1 i += 1 if buttonGeoms[0] is not None: b = DirectButton( geom=(buttonGeoms[0], buttonGeoms[1] if buttonGeoms[1] else buttonGeoms[0], buttonGeoms[2] if buttonGeoms[2] else buttonGeoms[0], buttonGeoms[3] if buttonGeoms[3] else buttonGeoms[0]), relief=None) b['geom_pos'] = (0, 0, 0) b.setTransparency(1) # if position is omitted from the configuration, put the button on the upper left corner if buttonPos is not None: b.setPos( aspect2d.getRelativePoint( screen2d, VBase3(buttonPos[0], 1.0, buttonPos[1]))) else: b.setPos(origin[0], 1.0, origin[2]) b.setScale(btnScrBounds[0], 1.0, btnScrBounds[2]) b.setFrameSize((0, btnScrBounds[0], 1.0, btnScrBounds[2])) b['command'] = buttonCallback b['extraArgs'] = (self.msn, ) b.hide() else: b = None setattr(self, buttonName, b) def _nextPageCallback(self, messenger): ''' Callback for next page button which only sends the appropriate message. ''' messenger.sendMessage(PanoConstants.EVENT_ITEMS_NEXT_PAGE) def _previousPageCallback(self, messenger): messenger.sendMessage(PanoConstants.EVENT_ITEMS_PREV_PAGE) def _scrollNextCallback(self, messenger): messenger.sendMessage(PanoConstants.EVENT_ITEMS_SCROLL_NEXT) def _scrollPreviousCallback(self, messenger): messenger.sendMessage(PanoConstants.EVENT_ITEMS_SCROLL_PREV)
def makePickableQuests(self, questList): self.doCameraNPCInteraction(True) quests = [] for questId in questList: quest = Quest(questId, base.localAvatar.questManager) quest.setupCurrentObjectiveFromData(-1, 0, None) quests.append(quest) positions = [(0, 0, 0.65), (0, 0, 0.1), (0, 0, -0.45)] self.questFrame = DirectFrame(relief=None, pos=(-0.8, 0, 0), geom=DGG.getDefaultDialogGeom(), geom_color=Vec4(0.8, 0.6, 0.4, 1), geom_scale=(1.85, 1, 0.9), geom_hpr=(0, 0, -90)) self.cancelBtn = DirectButton(text="Cancel", geom=CIGlobals.getDefaultBtnGeom(), geom_scale=(0.6, 0.75, 0.75), relief=None, parent=self.questFrame, pos=(0.2, 0, -0.8), text_scale=0.045, text_pos=(0, -0.015), scale=1.1, command=self.__cancelQuestPicker, extraArgs=[False]) self.timer = Timer() self.timer.load() self.timer.setScale(0.3) self.timer.reparentTo(self.questFrame) self.timer.setPos(-0.1, 0, -0.8) self.timer.setInitialTime(20) self.timer.setZeroCommand(self.__cancelQuestPicker) self.timer.startTiming() self.questPosters = [] self.questBtns = [] for i in xrange(len(quests)): poster = None quest = quests[i] poster = QuestGlobals.generatePoster(quest, parent=aspect2d) poster.setScale(0.85) poster.setPos(0, 0, 0) poster.progressBar.hide() self.questPosters.append(poster) # Let's setup the choose button. btn = DirectButton(geom=CIGlobals.getDefaultBtnGeom(), parent=poster, pos=(0.35, 0, 0.215), text='Choose', text_scale=0.08, text_pos=(0, -0.025), relief=None, command=self.d_pickedQuest, extraArgs=[quests[i]]) btn.setScale(0.4) btn.setBin('gui-popup', 60) btn.initialiseoptions(DirectButton) poster.reparentTo(self.questFrame.stateNodePath[0], 20) poster.setPos(positions[i]) poster.show() self.questBtns.append(btn)
class LocalToon(DistributedPlayerToon, BaseLocalAvatar): neverDisable = 1 GTAControls = ConfigVariableBool('want-gta-controls', False) def __init__(self, cr): try: self.LocalToon_initialized return except: self.LocalToon_initialized = 1 DistributedPlayerToon.__init__(self, cr) BaseLocalAvatar.__init__(self) self.chatInputState = False self.avatarChoice = cr.localAvChoice self.chatInput = ChatInput() self.positionExaminer = PositionExaminer() self.friendRequestManager = FriendRequestManager() self.friendsList = FriendsList() self.questManager = QuestManager(self) self.questUpdateGUI = QuestUpdateGUI() self.panel = ToonPanel() self.firstTimeGenerating = True friendsgui = loader.loadModel( 'phase_3.5/models/gui/friendslist_gui.bam') self.friendButton = DirectButton( geom=(friendsgui.find('**/FriendsBox_Closed'), friendsgui.find('**/FriendsBox_Rollover'), friendsgui.find('**/FriendsBox_Rollover')), text=("", "Friends", "Friends", ""), text_fg=(1, 1, 1, 1), text_shadow=(0, 0, 0, 1), text_scale=0.09, text_pos=(0, -0.18), relief=None, parent=base.a2dTopRight, pos=(-0.141, 0, -0.125), command=self.friendsButtonClicked, scale=0.8) friendsgui.removeNode() del friendsgui self.hideFriendButton() self.runSfx = base.loadSfx( "phase_3.5/audio/sfx/AV_footstep_runloop.ogg") self.runSfx.setLoop(True) self.walkSfx = base.loadSfx( "phase_3.5/audio/sfx/AV_footstep_walkloop.ogg") self.walkSfx.setLoop(True) self.offset = 3.2375 self.firstPersonCamPos = None self.movementKeymap = { "forward": 0, "backward": 0, "left": 0, "right": 0, "jump": 0 } self.avatarMovementEnabled = False self.isMoving_forward = False self.isMoving_side = False self.isMoving_back = False self.isMoving_jump = False self.gagThrowBtn = None self.pickerTrav = None self.pickerRay = None self.pickerRayNode = None self.pickerHandler = None self.rolledOverTag = None self.clickToonCallback = None self.inTutorial = False self.hasDoneJump = False self.lastState = None self.lastAction = None self.jumpHardLandIval = None # This is used by CutsceneGUI self.allowA2dToggle = True # This is used by the animation traverser. self.__traverseGUI = None def primaryFirePress(self): if not self.canUseGag(): return DistributedPlayerToon.primaryFirePress(self) def primaryFireRelease(self): if not self.canUseGag(): return DistributedPlayerToon.primaryFireRelease(self) def secondaryFirePress(self): if not self.canUseGag(): return DistributedPlayerToon.secondaryFirePress(self) def secondaryFireRelease(self): if not self.canUseGag(): return DistributedPlayerToon.secondaryFireRelease(self) def stopPlay(self): if not self.playState: self.notify.warning("Redundant call to stopPlay()") return self.hideBookButton() self.hideFriendButton() BaseLocalAvatar.stopPlay(self) self.stopTrackAnimToSpeed() def startPlay(self, gags=False, book=False, friends=False, laff=False, chat=False, wantMouse=1): if self.playState: self.notify.warning("Redundant call to startPlay()") return if book: self.showBookButton() if friends: self.showFriendButton() if chat: self.createChatInput() self.startTrackAnimToSpeed() BaseLocalAvatar.startPlay(self, gags, laff, wantMouse) def handleSuitAttack(self, attack): if self.isFirstPerson(): self.getFPSCam().handleSuitAttack(attack) def areGagsAllowed(self): return (BaseLocalAvatar.areGagsAllowed(self) and (self.chatInput is not None and self.chatInput.fsm.getCurrentState().getName() == 'idle')) def setEquippedAttack(self, gagId): DistributedPlayerToon.setEquippedAttack(self, gagId) BaseLocalAvatar.setEquippedAttack(self, gagId) def updateAttackAmmo(self, attackId, ammo, maxAmmo, ammo2, maxAmmo2, clip, maxClip): DistributedPlayerToon.updateAttackAmmo(self, attackId, ammo, maxAmmo, ammo2, maxAmmo2, clip, maxClip) BaseLocalAvatar.updateAttackAmmo(self, attackId, ammo, maxAmmo, ammo2, maxAmmo2, clip, maxClip) def setupAttacks(self): DistributedPlayerToon.setupAttacks(self) BaseLocalAvatar.setupAttacks(self) def _handleWentInTunnel(self, requestStatus): self.cr.playGame.getPlace().doneStatus = requestStatus messenger.send(self.cr.playGame.getPlace().doneEvent) def _handleCameOutTunnel(self): self.wrtReparentTo(render) self.cr.playGame.getPlace().fsm.request( self.cr.playGame.getPlace().nextState) def handleClickedWhisper(self, senderName, fromId, isPlayer, openPanel=False): place = self.cr.playGame.getPlace() if place is None or not hasattr(place, 'fsm') or place.fsm is None: return if openPanel and place.fsm.getCurrentState().getName() in [ 'walk', 'shtickerBook' ]: self.panel.makePanel(fromId) self.chatInput.disableKeyboardShortcuts() self.chatInput.fsm.request('input', ["", fromId]) def handleClickedSentWhisper(self, senderName, fromId, isPlayer): self.handleClickedWhisper(senderName, fromId, isPlayer, True) def hasDiscoveredHood(self, zoneId): return zoneId in self.hoodsDiscovered def hasTeleportAccess(self, zoneId): return zoneId in self.teleportAccess def tutorialCreated(self, zoneId): self.cr.tutorialCreated(zoneId) def friendsButtonClicked(self): self.hideFriendButton() self.friendsList.fsm.request('onlineFriendsList') def destroyFriendButton(self): if CIGlobals.isNodePathOk(self.friendButton): self.friendButton.destroy() self.friendButton = None def hideFriendButton(self): self.friendButton.hide() def showFriendButton(self): self.friendButton.show() def gotoNode(self, node, eyeHeight=3): possiblePoints = (Point3(0, 0, 0), Point3(3, 6, 0), Point3(-3, 6, 0), Point3(6, 6, 0), Point3(-6, 6, 0), Point3(3, 9, 0), Point3(-3, 9, 0), Point3(6, 9, 0), Point3(-6, 9, 0), Point3(9, 9, 0), Point3(-9, 9, 0), Point3(6, 0, 0), Point3(-6, 0, 0), Point3(6, 3, 0), Point3(-6, 3, 0), Point3(9, 9, 0), Point3(-9, 9, 0), Point3(0, 12, 0), Point3(3, 12, 0), Point3(-3, 12, 0), Point3(6, 12, 0), Point3(-6, 12, 0), Point3(9, 12, 0), Point3(-9, 12, 0), Point3(0, -6, 0), Point3(-3, -6, 0), Point3(0, -9, 0), Point3(-6, -9, 0)) for point in possiblePoints: pos = self.positionExaminer.consider(node, point, eyeHeight) if pos: self.setPos(node, pos) self.lookAt(node) self.setHpr(self.getH() + random.choice((-10, 10)), 0, 0) return self.setPos(node, 0, 0, 0) def setFriendsList(self, friends): DistributedPlayerToon.setFriendsList(self, friends) self.cr.friendsManager.d_requestFriendsList() self.panel.maybeUpdateFriendButton() def d_requestAddFriend(self, avId): self.sendUpdate('requestAddFriend', [avId]) def enablePicking(self): self.accept('toonClicked', self.toonClicked) def disablePicking(self): self.ignore('toonClicked') def toonClicked(self, avId): if not self.clickToonCallback: self.panel.makePanel(avId) else: self.clickToonCallback(avId) self.clickToonCallback = None def prepareToSwitchControlType(self): # Hack fix for getting stuck moving in one direction without pressing the movement keys. inputs = [ "run", "forward", "reverse", "turnLeft", "turnRight", "slideLeft", "slideRight", "jump" ] for inputName in inputs: try: inputState.releaseInputs(inputName) except: pass def getBackpack(self): return DistributedPlayerToon.getBackpack(self) def enterReadBook(self, ts=0, callback=None, extraArgs=[]): self.stopLookAround() self.b_lookAtObject(0, -45, 0) DistributedPlayerToon.enterReadBook(self, ts, callback, extraArgs) def exitReadBook(self): DistributedPlayerToon.exitReadBook(self) self.startLookAround() def getAirborneHeight(self): return self.offset + 0.025000000000000001 def setupControls(self): self.walkControls = CILocalControls() self.walkControls.setupControls() self.walkControls.setMode( CIGlobals.getSettingsMgr().getSetting("bpov").getValue()) def setWalkSpeedNormal(self): self.walkControls.setWalkSpeed(CIGlobals.ToonForwardSpeed, CIGlobals.ToonJumpForce, CIGlobals.ToonReverseSpeed, CIGlobals.ToonRotateSpeed) def setWalkSpeedNormalNoJump(self): self.walkControls.setWalkSpeed(CIGlobals.ToonForwardSpeed, 0.0, CIGlobals.ToonForwardSpeed, CIGlobals.ToonRotateSpeed) def setWalkSpeedSlow(self): self.walkControls.setWalkSpeed(CIGlobals.ToonForwardSlowSpeed, CIGlobals.ToonJumpSlowForce, CIGlobals.ToonReverseSlowSpeed, CIGlobals.ToonRotateSlowSpeed) def setDNAStrand(self, dnaStrand): DistributedPlayerToon.setDNAStrand(self, dnaStrand) if self.firstTimeGenerating: self.setupCamera() self.firstTimeGenerating = False def setMoney(self, money): DistributedPlayerToon.setMoney(self, money) def setupNameTag(self, tempName=None): DistributedPlayerToon.setupNameTag(self, tempName) self.nametag.setNametagColor( NametagGlobals.NametagColors[NametagGlobals.CCLocal]) self.nametag.unmanage(base.marginManager) self.nametag.setActive(0) self.nametag.updateAll() def b_setAnimState(self, anim, callback=None, extraArgs=[]): if self.anim != anim: self.d_setAnimState(anim) DistributedPlayerToon.setAnimState(self, anim, callback=callback, extraArgs=extraArgs) camTransitionStates = ['teleportIn', 'teleportOut', 'died'] if anim in camTransitionStates and not NO_TRANSITION in extraArgs: self.doFirstPersonCameraTransition() def enableAvatarControls(self, wantMouse=0): BaseLocalAvatar.enableAvatarControls(self, wantMouse) self.accept('jumpStart', self.__jump) def handleJumpLand(self): if self.jumpHardLandIval: self.jumpHardLandIval.finish() self.jumpHardLandIval = None if self.getHealth() > 0: self.b_setAnimState('Happy') def handleJumpHardLand(self): if self.jumpHardLandIval: self.jumpHardLandIval.finish() self.jumpHardLandIval = None self.jumpHardLandIval = ActorInterval(self, 'zend') self.jumpHardLandIval.setDoneEvent('LT::zend-done') self.acceptOnce('LT::zend-done', self.handleJumpLand) self.jumpHardLandIval.start() def disableAvatarControls(self, chat=False): BaseLocalAvatar.disableAvatarControls(self, chat) self.ignore('jumpStart') for k, _ in self.movementKeymap.items(): self.updateMovementKeymap(k, 0) self.resetTorsoRotation() self.resetHeadHpr() def updateMovementKeymap(self, key, value): self.movementKeymap[key] = value def getMovementKeyValue(self, key): return self.movementKeymap[key] def playMovementSfx(self, movement): """ This previously was the main method of playing movement sfxs, but now this is only used for tunnels """ if movement == 'run': self.walkSfx.stop() self.runSfx.play() elif movement == 'walk': self.runSfx.stop() self.walkSfx.play() else: self.runSfx.stop() self.walkSfx.stop() def __forward(self): self.resetHeadHpr() self.stopLookAround() if self.getHealth() < 1: self.setPlayRate(1.2, 'dwalk') self.setAnimState('deadWalk') else: self.setAnimState('run') self.isMoving_side = False self.isMoving_back = False self.isMoving_forward = True self.isMoving_jump = False def __turn(self): self.resetHeadHpr() self.stopLookAround() if self.getHealth() < 1: self.setPlayRate(1.2, 'dwalk') self.setAnimState('deadWalk') else: self.setPlayRate(1.0, "walk") self.setAnimState("walk") self.isMoving_forward = False self.isMoving_back = False self.isMoving_side = True self.isMoving_jump = False def __reverse(self): self.resetHeadHpr() self.stopLookAround() if self.getHealth() < 1: self.setPlayRate(-1.0, 'dwalk') self.setAnimState('deadWalk') else: self.setAnimState("walkBack") self.isMoving_side = False self.isMoving_forward = False self.isMoving_back = True self.isMoving_jump = False def __jump(self): if self.getHealth() > 0: if self.playingAnim in ['run', 'walk']: self.b_setAnimState("leap") else: self.b_setAnimState("jump") self.isMoving_side = False self.isMoving_forward = False self.isMoving_back = False self.isMoving_jump = True def __neutral(self): self.resetHeadHpr() self.startLookAround() if self.getHealth() > 0: self.setAnimState("neutral") else: self.setPlayRate(1.0, 'dneutral') self.setAnimState("deadNeutral") self.isMoving_side = False self.isMoving_forward = False self.isMoving_back = False self.isMoving_jump = False def movementTask(self, task): if self.getMovementKeyValue("jump") == 1: if not self.walkControls.isAirborne: if self.walkControls.mayJump: self.__jump() self.hasDoneJump = True else: if self.hasDoneJump: if self.getHealth() > 0: self.b_setAnimState('Happy') self.hasDoneJump = False else: if not self.walkControls.isAirborne: if self.hasDoneJump: if self.getHealth() > 0: self.b_setAnimState('Happy') self.hasDoneJump = False return task.cont def startTrackAnimToSpeed(self): if not base.taskMgr.hasTaskNamed(self.uniqueName('trackAnimToSpeed')): base.taskMgr.add(self.trackAnimToSpeed, self.uniqueName('trackAnimToSpeed')) def stopTrackAnimToSpeed(self): base.taskMgr.remove(self.uniqueName('trackAnimToSpeed')) def trackAnimToSpeed(self, task): slideSpeed, speed, rotSpeed = self.walkControls.getSpeeds() state = None if self.isSwimming: state = 'swim' else: if self.getHealth() > 0: state = 'Happy' else: state = 'Sad' if state != self.lastState: self.lastState = state self.b_setAnimState(state) if base.minigame is None and not self.battleControls: if state == 'Sad' and not self.isSwimming: self.setWalkSpeedSlow() else: self.setWalkSpeedNormal() action = self.setSpeed(speed, rotSpeed, slideSpeed) if action != self.lastAction: self.lastAction = action if action == CIGlobals.WALK_INDEX: self.resetHeadHpr() self.stopLookAround() elif action == CIGlobals.RUN_INDEX or action in [ CIGlobals.STRAFE_LEFT_INDEX, CIGlobals.STRAFE_RIGHT_INDEX ] or action == CIGlobals.REVERSE_INDEX: self.resetHeadHpr() self.stopLookAround() else: self.resetHeadHpr() self.stopLookAround() if self.walkControls.mode == self.walkControls.MThirdPerson: if state == 'Happy': self.startLookAround() return task.cont def setLoadout(self, gagIds): DistributedPlayerToon.setLoadout(self, gagIds) place = base.cr.playGame.getPlace() if place and place.fsm.getCurrentState().getName() == 'shtickerBook': if hasattr(place, 'shtickerBookStateData'): stateData = place.shtickerBookStateData if stateData.getCurrentPage() is not None: if stateData.getCurrentPage().title == 'Gags': stateData.getCurrentPage().gui.fsm.request('idle') def resetHeadHpr(self, override=False): if self.lookMode == self.LMOff or not self.walkControls.controlsEnabled or override: self.b_lookAtObject(0, 0, 0, blink=0) def checkSuitHealth(self, suit): pass def handleLookSpot(self, hpr): h, p, r = hpr self.d_lookAtObject(h, p, r, blink=1) def showBookButton(self, inBook=0): self.book_gui = loader.loadModel( "phase_3.5/models/gui/stickerbook_gui.bam") self.book_btn = DirectButton( image=(self.book_gui.find('**/BookIcon_CLSD'), self.book_gui.find('**/BookIcon_OPEN'), self.book_gui.find('**/BookIcon_RLVR')), relief=None, pos=(-0.158, 0, 0.17), command=self.bookButtonClicked, scale=0.305, parent=base.a2dBottomRight) self.book_btn.setBin('gui-popup', 60) if inBook: self.book_btn["image"] = (self.book_gui.find('**/BookIcon_OPEN'), self.book_gui.find('**/BookIcon_CLSD'), self.book_gui.find('**/BookIcon_RLVR2')) self.book_btn["command"] = self.bookButtonClicked self.book_btn["extraArgs"] = [0] def hideBookButton(self): if hasattr(self, 'book_gui'): self.book_gui.removeNode() del self.book_gui if hasattr(self, 'book_btn'): self.book_btn.destroy() del self.book_btn def bookButtonClicked(self, openIt=1): if openIt: base.cr.playGame.getPlace().fsm.request('shtickerBook') else: base.cr.playGame.getPlace().shtickerBookStateData.finishedResume() def handleHealthChange(self, hp, oldHp): if hp > 0 and oldHp < 1: if self.cr.playGame and self.cr.playGame.getPlace(): if self.cr.playGame.getPlace().fsm.getCurrentState().getName( ) == 'walk': if self.cr.playGame.getPlace( ).walkStateData.fsm.getCurrentState().getName( ) == 'deadWalking': self.cr.playGame.getPlace().walkStateData.fsm.request( 'walking') if self.animFSM.getCurrentState().getName() == 'deadNeutral': self.b_setAnimState("neutral") elif self.animFSM.getCurrentState().getName() == 'deadWalk': self.b_setAnimState("run") BaseLocalAvatar.handleHealthChange(self, hp, oldHp) DistributedPlayerToon.handleHealthChange(self, hp, oldHp) def setSessionHealth(self, hp): currHp = self.getSessionHealth() self.handleHealthChange(hp, currHp) DistributedPlayerToon.setSessionHealth(self, hp) def reparentTo(self, parent): self.notify.debug("Local toon reparent to {0}".format( parent.node().getName())) DistributedPlayerToon.reparentTo(self, parent) def wrtReparentTo(self, parent): self.notify.debug("Local toon wrtReparent to {0}".format( parent.node().getName())) DistributedPlayerToon.wrtReparentTo(self, parent) def loadAvatar(self): DistributedPlayerToon.loadAvatar(self) base.avatars.remove(self) def diedStateDone(self, requestStatus): hood = self.cr.playGame.hood.id if hood == ZoneUtil.BattleTTC: hood = ZoneUtil.ToontownCentral toZone = ZoneUtil.getZoneId(hood) if self.zoneId != toZone: requestStatus = { 'zoneId': toZone, 'hoodId': hood, 'where': ZoneUtil.getWhereName(toZone), 'avId': self.doId, 'loader': ZoneUtil.getLoaderName(toZone), 'shardId': None, 'wantLaffMeter': 1, 'how': 'teleportIn' } self.cr.playGame.getPlace().doneStatus = requestStatus messenger.send(self.cr.playGame.getPlace().doneEvent) else: return def teleportToCT(self): toZone = ZoneUtil.CogTropolisId hood = ZoneUtil.CogTropolis requestStatus = { 'zoneId': toZone, 'hoodId': hood, 'where': ZoneUtil.getWhereName(toZone), 'avId': self.doId, 'loader': ZoneUtil.getLoaderName(toZone), 'shardId': None, 'wantLaffMeter': 1, 'how': 'teleportIn' } self.cr.playGame.getPlace().fsm.request('teleportOut', [requestStatus]) def setQuests(self, dataStr): oldDataStr = self.quests DistributedPlayerToon.setQuests(self, dataStr) self.questManager.makeQuestsFromData() # Let's send our quest data update event. messenger.send(QUEST_DATA_UPDATE_EVENT, [oldDataStr, dataStr]) def createChatInput(self): if not self.chatInputState: self.chatInput.load() self.chatInput.enter() self.chatInputState = True def disableChatInput(self): if self.chatInputState: self.chatInput.exit() self.chatInput.unload() self.chatInputState = False def toggleAspect2d(self): if self.allowA2dToggle: if base.aspect2d.isHidden(): base.aspect2d.show() else: base.aspect2d.hide() def startTraverseAnimationControls(self, animName): if not self.__traverseGUI: if not self.getNumFrames(animName) is None: frame = self.getCurrentFrame(animName) if frame is None: frame = 0 self.pose(animName, 0) self.accept('h', self.__traverseAnimation, extraArgs=[animName, -1]) self.accept('j', self.__traverseAnimation, extraArgs=[animName, 1]) self.__traverseGUI = OnscreenText( text= 'Current Frame: {0}\n\'H\' Decrease Frame, \'J\' Increase Frame' .format(str(frame)), pos=(0, -0.75), font=CIGlobals.getToonFont(), fg=(1, 1, 1, 1), shadow=(0, 0, 0, 1)) else: self.notify.info( 'Tried to traverse unknown animation: {0}'.format( animName)) def __traverseAnimation(self, animName, delta): frame = self.getCurrentFrame(animName) if frame is None: frame = 0 if (frame + delta) < 0: frame = self.getNumFrames(animName) - 1 elif (frame + delta) > (self.getNumFrames(animName) - 1): frame = self.getNumFrames(animName) - 1 else: frame += delta self.pose(animName, frame) self.__traverseGUI.setText( 'Current Frame: {0}\n\'H\' Decrease Frame, \'J\' Increase Frame'. format(str(frame))) def endTraverseAnimationControls(self): self.ignore('h') self.ignore('j') if self.__traverseGUI: self.__traverseGUI.destroy() self.__traverseGUI = None def generate(self): DistributedPlayerToon.generate(self) def delete(self): DistributedPlayerToon.delete(self) self.deleteLaffMeter() return def disable(self): DistributedPlayerToon.disable(self) self.stopTrackAnimToSpeed() base.camLens.setMinFov(CIGlobals.OriginalCameraFov / (4. / 3.)) if self.jumpHardLandIval: self.ignore('LT::zend-done') self.jumpHardLandIval.finish() self.jumpHardLandIval = None if self.friendsList: self.friendsList.destroy() self.friendsList = None if self.panel: self.panel.cleanup() self.panel = None if self.positionExaminer: self.positionExaminer.delete() self.positionExaminer = None self.disablePicking() self.destroyFriendButton() self.stopLookAround() self.disableAvatarControls() self.destroyControls() if self.smartCamera: self.smartCamera.stopUpdateSmartCamera() self.smartCamera.deleteSmartCameraCollisions() self.smartCamera = None if self.questManager: self.questManager.cleanup() self.questManager = None if self.questUpdateGUI: self.questUpdateGUI.cleanup() self.questUpdateGUI = None if self.friendRequestManager: self.friendRequestManager.cleanup() self.friendRequestManager = None self.destroyInvGui() if self.crosshair: self.crosshair.destroy() self.crosshair = None self.disableLaffMeter() self.disableGags() self.disableChatInput() self.hideBookButton() self.weaponType = None self.runSfx = None self.walkSfx = None self.offset = None self.movementKeymap = None self.minigame = None self.inTutorial = None self.avatarChoice = None self.chatInputState = None self.playState = None self.endTraverseAnimationControls() self.ignore("gotLookSpot") self.ignore("clickedWhisper") self.ignore('/') self.ignore(base.inputStore.ToggleAspect2D) return def delete(self): DistributedPlayerToon.delete(self) del base.localAvatar del __builtins__['localAvatar'] print "Local avatar finally deleted" def sewerHeadOff(self, zoneId): # TEMPORARY requestStatus = { 'zoneId': zoneId, 'hoodId': 0, 'where': 'sewer', 'avId': self.doId, 'loader': 'sewer', 'shardId': None, 'wantLaffMeter': 1 } self.cr.playGame.getPlace().fsm.request('teleportOut', [requestStatus]) def announceGenerate(self): DistributedPlayerToon.announceGenerate(self) self.setupControls() self.startLookAround() self.friendRequestManager.watch() self.accept("gotLookSpot", self.handleLookSpot) self.accept("clickedWhisper", self.handleClickedSentWhisper) self.accept(base.inputStore.ToggleAspect2D, self.toggleAspect2d) if not metadata.IS_PRODUCTION: self.acceptOnce('m', self.sendUpdate, ['reqMakeSewer']) self.accept('l', render.ls) self.accept('/', self.printPos) self.accept('\\', self.printPos_cam) #self.accept('c', self.walkControls.setCollisionsActive, [0]) self.createInvGui() # Unused developer methods. #self.accept('p', self.enterPictureMode) #self.accept('c', self.teleportToCT) #posBtn = DirectButton(text = "Get Pos", scale = 0.08, pos = (0.3, 0, 0), parent = base.a2dLeftCenter, command = self.printAvPos) def enterHiddenToonMode(self): self.laffMeter.stop() self.laffMeter.disable() self.laffMeter.destroy() self.getGeomNode().hide() self.deleteNameTag() self.invGui.disable() self.hideFriendButton() self.hideBookButton() self.removeAdminToken()