def addPartyToScrollList(self, party): textSize = self.ScrollListTextSize descTextSize = 0.05 partyTitle = myStrftime(party.startTime) partyTitle = partyTitle + ' ' + TTLocalizer.EventsPageCalendarTabParty textSize = self.ScrollListTextSize descTextSize = 0.05 newItem = DirectButton(relief=None, text=partyTitle, text_scale=textSize, text_align=TextNode.ALeft, rolloverSound=None, clickSound=None, pressEffect=0, command=self.__clickedOnScrollItem) scrollItemHeight = newItem.getHeight() descUnderItemZAdjust = scrollItemHeight * descTextSize / textSize descUnderItemZAdjust = max(0.0534, descUnderItemZAdjust) descUnderItemZAdjust = -descUnderItemZAdjust descZAdjust = descUnderItemZAdjust self.scrollList.addItem(newItem) newItem.description = MiniInviteVisual(newItem, party) newItem.description.setBin('gui-popup', 0) newItem.description.hide() newItem.bind( DGG.ENTER, self.enteredTextItem, extraArgs=[newItem, newItem.description, descUnderItemZAdjust]) newItem.bind(DGG.EXIT, self.exitedTextItem, extraArgs=[newItem]) return
def addTitleAndDescToScrollList(self, title, desc): textSize = self.ScrollListTextSize descTextSize = 0.05 newItem = DirectButton( relief=None, text=title, text_scale=textSize, text_align=TextNode.ALeft, rolloverSound=None, clickSound=None, pressEffect=0, command=self.__clickedOnScrollItem, ) scrollItemHeight = newItem.getHeight() descUnderItemZAdjust = scrollItemHeight * descTextSize / textSize descUnderItemZAdjust = max(0.0534, descUnderItemZAdjust) descUnderItemZAdjust = -descUnderItemZAdjust descZAdjust = descUnderItemZAdjust newItem.description = DirectLabel( parent=newItem, pos=(0.115, 0, descZAdjust), text="", text_wordwrap=15, pad=(0.02, 0.02), text_scale=descTextSize, text_align=TextNode.ACenter, textMayChange=0, ) newItem.description.checkedHeight = False newItem.description.setBin("gui-popup", 0) newItem.description.hide() newItem.bind(DGG.ENTER, self.enteredTextItem, extraArgs=[newItem, desc, descUnderItemZAdjust]) newItem.bind(DGG.EXIT, self.exitedTextItem, extraArgs=[newItem]) self.scrollList.addItem(newItem)
def addTitleAndDescToScrollList(self, title, desc): textSize = self.ScrollListTextSize descTextSize = 0.05 newItem = DirectButton(relief=None, text=title, text_scale=textSize, text_align=TextNode.ALeft, rolloverSound=None, clickSound=None, pressEffect=0, command=self.__clickedOnScrollItem) scrollItemHeight = newItem.getHeight() descUnderItemZAdjust = scrollItemHeight * descTextSize / textSize descUnderItemZAdjust = max(0.0534, descUnderItemZAdjust) descUnderItemZAdjust = -descUnderItemZAdjust descZAdjust = descUnderItemZAdjust newItem.description = DirectLabel(parent=newItem, pos=(0.115, 0, descZAdjust), text='', text_wordwrap=15, pad=(0.02, 0.02), text_scale=descTextSize, text_align=TextNode.ACenter, textMayChange=0) newItem.description.checkedHeight = False newItem.description.setBin('gui-popup', 0) newItem.description.hide() newItem.bind(DGG.ENTER, self.enteredTextItem, extraArgs=[newItem, desc, descUnderItemZAdjust]) newItem.bind(DGG.EXIT, self.exitedTextItem, extraArgs=[newItem]) self.scrollList.addItem(newItem) return
def addPartyToScrollList(self, party): textSize = self.ScrollListTextSize descTextSize = 0.05 partyTitle = myStrftime(party.startTime) partyTitle = partyTitle + " " + TTLocalizer.EventsPageCalendarTabParty textSize = self.ScrollListTextSize descTextSize = 0.05 newItem = DirectButton( relief=None, text=partyTitle, text_scale=textSize, text_align=TextNode.ALeft, rolloverSound=None, clickSound=None, pressEffect=0, command=self.__clickedOnScrollItem, ) scrollItemHeight = newItem.getHeight() descUnderItemZAdjust = scrollItemHeight * descTextSize / textSize descUnderItemZAdjust = max(0.0534, descUnderItemZAdjust) descUnderItemZAdjust = -descUnderItemZAdjust descZAdjust = descUnderItemZAdjust self.scrollList.addItem(newItem) newItem.description = MiniInviteVisual(newItem, party) newItem.description.setBin("gui-popup", 0) newItem.description.hide() newItem.bind(DGG.ENTER, self.enteredTextItem, extraArgs=[newItem, newItem.description, descUnderItemZAdjust]) newItem.bind(DGG.EXIT, self.exitedTextItem, extraArgs=[newItem])
def addTitleAndDescToScrollList(self, title, desc): """Add a text title and popup description to the scrollList.""" textSize = self.ScrollListTextSize descTextSize = 0.05 newItem = DirectButton( relief=None, text=title, text_scale=textSize, text_align=TextNode.ALeft, rolloverSound=None, clickSound=None, pressEffect=0, command=self.__clickedOnScrollItem, ) # lower tool tip a little scrollItemHeight = newItem.getHeight() descUnderItemZAdjust = (scrollItemHeight * descTextSize / textSize) descUnderItemZAdjust = max( 0.0534, descUnderItemZAdjust) # ensure minimum height descUnderItemZAdjust = -descUnderItemZAdjust # self.notify.debug('scrollItemHeight of %s = %f' % (title, scrollItemHeight)) descZAdjust = descUnderItemZAdjust # self.notify.debug('descUnderItemZAdjust of %s = %f' % (title, descUnderItemZAdjust)) newItem.description = DirectLabel( parent=newItem, pos=(0.115, 0, descZAdjust), text='', text_wordwrap=15, pad=(0.02, 0.02), text_scale=descTextSize, text_align=TextNode.ACenter, textMayChange=0, ) # if we set text here, it really slows down changing the month # do it when we first enter the scroll item instead newItem.description.checkedHeight = False # # workaround to stop getting clipped by plane node newItem.description.setBin('gui-popup', 0) newItem.description.hide() newItem.bind(DGG.ENTER, self.enteredTextItem, extraArgs=[newItem, desc, descUnderItemZAdjust]) newItem.bind(DGG.EXIT, self.exitedTextItem, extraArgs=[newItem]) self.scrollList.addItem(newItem)
def addPartyToScrollList(self, party): """Add a party to the scroll list.""" textSize = self.ScrollListTextSize descTextSize = 0.05 partyTitle = myStrftime(party.startTime) partyTitle = partyTitle + " " + TTLocalizer.EventsPageCalendarTabParty textSize = self.ScrollListTextSize descTextSize = 0.05 newItem = DirectButton( relief=None, text=partyTitle, text_scale=textSize, text_align=TextNode.ALeft, rolloverSound=None, clickSound=None, pressEffect=0, command=self.__clickedOnScrollItem, ) # lower tool tip a little scrollItemHeight = newItem.getHeight() descUnderItemZAdjust = (scrollItemHeight * descTextSize / textSize) descUnderItemZAdjust = max( 0.0534, descUnderItemZAdjust) # ensure minimum height descUnderItemZAdjust = -descUnderItemZAdjust # self.notify.debug('scrollItemHeight of %s = %f' % (title, scrollItemHeight)) descZAdjust = descUnderItemZAdjust # self.notify.debug('descUnderItemZAdjust of %s = %f' % (title, descUnderItemZAdjust)) self.scrollList.addItem(newItem) newItem.description = MiniInviteVisual(newItem, party) # # workaround to stop getting clipped by plane node newItem.description.setBin('gui-popup', 0) newItem.description.hide() newItem.bind( DGG.ENTER, self.enteredTextItem, extraArgs=[newItem, newItem.description, descUnderItemZAdjust]) newItem.bind(DGG.EXIT, self.exitedTextItem, extraArgs=[newItem])
class ModPanelButton: def __init__(self, menu, name, command, register): self.menu = menu self.name = name self.command = command if type(command) == types.StringType: command = self.call_word self.button = DirectButton(frameSize=None, text=name, image=(ModPanelGlobals.Button.find('**/QuitBtn_UP'), ModPanelGlobals.Button.find('**/QuitBtn_DN'), ModPanelGlobals.Button.find('**/QuitBtn_RLVR')), relief=None, command=command, text_pos=(0, -0.015), geom=None, pad=(0.01, 0.01), suppressKeys=0, pos=(0, 0, 0), text_scale=0.059, borderWidth=(0.015, 0.01), scale=.7 ) self.button.reparent_to(menu) if register: self.button.bind(DirectGuiGlobals.B2PRESS, self.delete_button) self.button.bind(DirectGuiGlobals.B3PRESS, self.button.editStart) self.button.bind(DirectGuiGlobals.B3RELEASE, self.edit_stop) self.menu.buttons.append(self) messenger.send('save-file') def call_word(self): messenger.send('magicWord', [self.command]) def hide(self): self.button.hide() def show(self): self.button.show() def place(self): self.button.place() def set_pos(self, x, y, z): self.button.set_pos(x, y, z) def destroy(self): self.button.destroy() def edit_stop(self, dispatch): self.button.editStop(dispatch) messenger.send('save-file') def delete_button(self, dispatch): self.button.destroy() if self in self.menu.buttons: self.menu.buttons.remove(self) messenger.send('save-file') def get_data(self): return (self.name, self.command, self.button.get_pos())
class PartyPlanner(DirectFrame, FSM): notify = DirectNotifyGlobal.directNotify.newCategory('PartyPlanner') def __init__(self, doneEvent = None): FSM.__init__(self, 'PartyPlannerFSM') DirectFrame.__init__(self) self.doneEvent = doneEvent self.stateArray = ['Off', 'Welcome', 'PartyEditor', 'Guests', 'Date', 'Time', 'Invitation', 'Farewell'] self.partyTime = base.cr.toontownTimeManager.getCurServerDateTime() self.partyNowTime = base.cr.toontownTimeManager.getCurServerDateTime() minutesToNextFifteen = 15 - self.partyTime.minute % 15 self.cleanPartyTime = self.partyTime + timedelta(minutes=minutesToNextFifteen, seconds=-self.partyTime.second) self.partyTime = self.cleanPartyTime self.guests = [] self.isPrivate = False self.selectedCalendarGuiDay = None self.gui = loader.loadModel('phase_4/models/parties/partyPlannerGUI') self.partyDuration = timedelta(hours=PartyGlobals.DefaultPartyDuration) self.timeTypeToMaxValue = {'hour': 23, 'minute': 59} self.timeTypeToChangeAmount = {'hour': (1, -1), 'minute': (15, -15), 'ampm': (1, -1)} self.partyInfo = None self.asapMinuteRounding = base.config.GetInt('party-asap-minute-rounding', PartyGlobals.PartyPlannerAsapMinuteRounding) self.load() self.request('Welcome') return def enterWelcome(self, *args): self.prevButton['state'] = DirectGuiGlobals.DISABLED self.prevButton.hide() self.nextButton['state'] = DirectGuiGlobals.NORMAL self.welcomePage.show() self.partyPlannerHead.reparentTo(self.welcomePage) self.partyPlannerHead.startBlink() self.partyPlannerHead.startLookAround() self.nametagNP.reparentTo(self.welcomePage) self.chatNP.reparentTo(self.welcomePage) def exitWelcome(self): self.welcomePage.hide() self.prevButton.show() self.partyPlannerHead.stopBlink() self.partyPlannerHead.stopLookAround() def enterPartyEditor(self, *args): self.prevButton['state'] = DirectGuiGlobals.NORMAL self.nextButton['state'] = DirectGuiGlobals.DISABLED self.nextButton.hide() self.partyEditorPage.show() self.okWithGroundsGui.doneStatus = '' self.partyEditor.request('Idle') def exitPartyEditor(self): self.partyEditor.request('Hidden') self.partyEditorPage.hide() def enterGuests(self, *args): self.prevButton['state'] = DirectGuiGlobals.NORMAL self.nextButton['state'] = DirectGuiGlobals.NORMAL self.nextButton.show() self.guestPage.show() def exitGuests(self): self.guests = [] for friendCheckBox in self.friendList['items']: if friendCheckBox['indicatorValue']: self.guests.append(friendCheckBox.getPythonTag('id')) self.guestPage.hide() def enterDate(self, *args): self.prevButton.show() self.prevButton['state'] = DirectGuiGlobals.NORMAL if self.selectedCalendarGuiDay is None: self.nextButton['state'] = DirectGuiGlobals.DISABLED self.nextButton.hide() self.makePartyNowButton.show() self.datePage.show() return def exitDate(self): self.datePage.hide() self.nextButton.show() if self.selectedCalendarGuiDay is not None: self.partyTime = self.cleanPartyTime self.alterPartyTime(year=self.selectedCalendarGuiDay.myDate.year, month=self.selectedCalendarGuiDay.myDate.month, day=self.selectedCalendarGuiDay.myDate.day) else: self.partyNowTime = self.calcAsapTime() self.partyTime = self.partyNowTime return def calcAsapTime(self): curServerTime = base.cr.toontownTimeManager.getCurServerDateTime() baseTime = curServerTime baseTime = baseTime.replace(baseTime.year, baseTime.month, baseTime.day, baseTime.hour, baseTime.minute, second=0, microsecond=0) minute = curServerTime.minute remainder = minute % self.asapMinuteRounding if remainder: baseTime += timedelta(minutes=self.asapMinuteRounding - remainder) else: baseTime += timedelta(minutes=self.asapMinuteRounding) return baseTime def enterTime(self, *args): self.prevButton.show() self.prevButton['state'] = DirectGuiGlobals.NORMAL self.nextButton.show() self.timePage.show() self.timePageRecapToontownTimeLabel2['text'] = '%s' % PartyUtils.formatDateTime(self.partyTime) self.timePageRecapLocalTimeLabel['text'] = '%s%s' % (TTLocalizer.PartyPlannerTimeLocalTime, PartyUtils.formatDateTime(self.partyTime, inLocalTime=True)) def exitTime(self): self.timePage.hide() self.nextButton.show() def enterInvitation(self, *args): self.prevButton['state'] = DirectGuiGlobals.NORMAL self.nextButton.hide() defaultInviteTheme = PartyGlobals.InviteTheme.GenericMale if hasattr(base.cr, 'newsManager') and base.cr.newsManager: if ToontownGlobals.VICTORY_PARTY_HOLIDAY in base.cr.newsManager.getHolidayIdList(): defaultInviteTheme = PartyGlobals.InviteTheme.VictoryParty elif ToontownGlobals.KARTING_TICKETS_HOLIDAY in base.cr.newsManager.getHolidayIdList() or ToontownGlobals.CIRCUIT_RACING_EVENT in base.cr.newsManager.getHolidayIdList(): defaultInviteTheme = PartyGlobals.InviteTheme.Racing elif ToontownGlobals.VALENTINES_DAY in base.cr.newsManager.getHolidayIdList(): defaultInviteTheme = PartyGlobals.InviteTheme.Valentoons if self.partyInfo is not None: del self.partyInfo activityList = self.partyEditor.partyEditorGrid.getActivitiesOnGrid() decorationList = self.partyEditor.partyEditorGrid.getDecorationsOnGrid() endTime = self.partyTime + self.partyDuration self.partyInfo = PartyInfo(0, 0, self.partyTime.year, self.partyTime.month, self.partyTime.day, self.partyTime.hour, self.partyTime.minute, endTime.year, endTime.month, endTime.day, endTime.hour, endTime.minute, self.isPrivate, defaultInviteTheme, activityList, decorationList, 0) if self.noFriends or len(self.getInvitees()) == 0: self.inviteVisual.setNoFriends(True) self.invitationTitleLabel['text'] = TTLocalizer.PartyPlannerConfirmTitleNoFriends self.inviteButton['text'] = TTLocalizer.PartyPlannerInviteButtonNoFriends self.selectedInviteThemeLabel.stash() self.nextThemeButton.stash() self.prevThemeButton.stash() self.setInviteTheme(defaultInviteTheme) else: self.inviteVisual.setNoFriends(False) self.invitationTitleLabel['text'] = TTLocalizer.PartyPlannerConfirmTitle self.inviteButton['text'] = TTLocalizer.PartyPlannerInviteButton self.selectedInviteThemeLabel.unstash() self.nextThemeButton.unstash() self.prevThemeButton.unstash() self.setInviteTheme(defaultInviteTheme) self.inviteVisual.updateInvitation(base.localAvatar.getName(), self.partyInfo) self.invitationPage.show() return def __prevTheme(self): self.nextThemeButton.show() prevTheme = self.currentInvitationTheme - 1 while prevTheme not in self.inviteThemes: prevTheme -= 1 if prevTheme == self.currentInvitationTheme: self.notify.warning('No previous invite theme found.') break elif prevTheme < 0: prevTheme = len(self.inviteVisual.inviteThemesIdToInfo) - 1 self.setInviteTheme(prevTheme) def __nextTheme(self): self.prevThemeButton.show() nextTheme = self.currentInvitationTheme + 1 while nextTheme not in self.inviteThemes: nextTheme += 1 if nextTheme == self.currentInvitationTheme: self.notify.warning('No next invite theme found.') break elif nextTheme >= len(self.inviteVisual.inviteThemesIdToInfo): nextTheme = 0 self.setInviteTheme(nextTheme) def setInviteTheme(self, themeNumber): self.currentInvitationTheme = themeNumber self.selectedInviteThemeLabel['text'] = '%s %s (%d/%d)' % (self.inviteVisual.inviteThemesIdToInfo[self.currentInvitationTheme][1], TTLocalizer.PartyPlannerInvitationTheme, self.inviteThemes.index(self.currentInvitationTheme) + 1, len(self.inviteThemes)) self.partyInfo.inviteTheme = self.currentInvitationTheme self.inviteVisual.updateInvitation(base.localAvatar.getName(), self.partyInfo) def exitInvitation(self): self.invitationPage.hide() self.nextButton.show() def enterFarewell(self, goingBackAllowed): self.farewellPage.show() if goingBackAllowed: self.prevButton.show() else: self.prevButton.hide() self.nextButton.hide() self.partyPlannerHead.reparentTo(self.farewellPage) self.partyPlannerHead.startBlink() self.partyPlannerHead.startLookAround() self.nametagNP.reparentTo(self.farewellPage) self.chatNP.reparentTo(self.farewellPage) def exitFarewell(self): self.farewellPage.hide() self.nextButton.show() self.prevButton.show() self.partyPlannerHead.stopBlink() self.partyPlannerHead.stopLookAround() def load(self): self.frame = DirectFrame(parent=aspect2d, geom=self.gui.find('**/background'), relief=None, scale=0.85, pos=(0.05, 0.0, 0.1)) self.titleScale = TTLocalizer.PPtitleScale self._createNavButtons() self.welcomePage = self._createWelcomePage() self.welcomePage.hide() self.datePage = self._createDatePage() self.datePage.hide() self.timePage = self._createTimePage() self.timePage.hide() self.guestPage = self._createGuestPage() self.guestPage.hide() self.partyEditorPage = self._createPartyEditorPage() self.partyEditorPage.hide() self.invitationPage = self._createInvitationPage() self.invitationPage.hide() self.farewellPage = self._createFarewellPage() self.farewellPage.hide() return def _createNavButtons(self): self.quitButton = DirectButton(parent=self.frame, relief=None, geom=(self.gui.find('**/cancelButton_up'), self.gui.find('**/cancelButton_down'), self.gui.find('**/cancelButton_rollover')), command=self.__acceptExit) self.nextButton = DirectButton(parent=self.frame, relief=None, geom=(self.gui.find('**/bottomNext_button/nextButton_up'), self.gui.find('**/bottomNext_button/nextButton_down'), self.gui.find('**/bottomNext_button/nextButton_rollover')), command=self.__nextItem, state=DirectGuiGlobals.DISABLED) self.prevButton = DirectButton(parent=self.frame, relief=None, geom=(self.gui.find('**/bottomPrevious_button/previousButton_up'), self.gui.find('**/bottomPrevious_button/previousButton_down'), self.gui.find('**/bottomPrevious_button/previousButton_rollover')), command=self.__prevItem, state=DirectGuiGlobals.DISABLED) self.currentItem = None return def __createNametag(self, parent): if self.nametagGroup == None: self.nametagGroup = NametagGroup() self.nametagGroup.setFont(OTPGlobals.getInterfaceFont()) self.nametagGroup.setActive(0) self.nametagGroup.setAvatar(self.partyPlannerHead) self.nametagGroup.manage(base.marginManager) self.nametagGroup.setColorCode(self.nametagGroup.CCNonPlayer) self.nametagGroup.getNametag2d().setContents(0) self.nametagNode = NametagFloat2d() self.nametagNode.setContents(Nametag.CName) self.nametagGroup.addNametag(self.nametagNode) self.nametagGroup.setName(base.cr.partyManager.getPartyPlannerName()) self.nametagNP = parent.attachNewNode(self.nametagNode.upcastToPandaNode()) nametagPos = self.gui.find('**/step_01_partymanPeteNametag_locator').getPos() self.nametagNP.setPosHprScale(nametagPos[0], 0, nametagPos[2], 0, 0, 0, 0.1, 1, 0.1) self.chatNode = NametagFloat2d() self.chatNode.setContents(Nametag.CSpeech | Nametag.CThought) self.nametagGroup.addNametag(self.chatNode) self.nametagGroup.setChat(TTLocalizer.PartyPlannerInstructions, CFSpeech) self.chatNP = parent.attachNewNode(self.chatNode.upcastToPandaNode()) chatPos = self.gui.find('**/step_01_partymanPeteText_locator').getPos() self.chatNP.setPosHprScale(chatPos[0], 0, chatPos[2], 0, 0, 0, 0.08, 1, 0.08) return def clearNametag(self): if self.nametagGroup != None: self.nametagGroup.unmanage(base.marginManager) self.nametagGroup.removeNametag(self.nametagNode) self.nametagGroup.removeNametag(self.chatNode) self.nametagNP.removeNode() self.chatNP.removeNode() del self.nametagNP del self.chatNP del self.nametagNode del self.chatNode self.nametagGroup.setAvatar(NodePath()) self.nametagGroup = None return def _createWelcomePage(self): self.nametagGroup = None page = DirectFrame(self.frame) page.setName('PartyPlannerWelcomePage') self.welcomeTitleLabel = DirectLabel(parent=page, relief=None, text=TTLocalizer.PartyPlannerWelcomeTitle, pos=self.gui.find('**/title_locator').getPos(), scale=self.titleScale) self.partyPlannerHead = ToonHead.ToonHead() partyPlannerStyle = base.cr.partyManager.getPartyPlannerStyle() self.partyPlannerHead.setupHead(partyPlannerStyle, forGui=True) self.partyPlannerHead.setPos(self.gui.find('**/step_01_partymanPete_locator').getPos()) animal = partyPlannerStyle.getAnimal() if animal == 'cat' or animal == 'pig': headScale = 0.4 elif animal == 'dog' or animal == 'bear': headScale = 0.45 elif animal == 'rabbit': headScale = 0.35 else: headScale = 0.3 self.partyPlannerHead.setScale(headScale) self.partyPlannerHead.setH(180.0) self.partyPlannerHead.reparentTo(page) self.__createNametag(page) return page def _createDatePage(self): page = DirectFrame(self.frame) page.setName('PartyPlannerDatePage') self.createDateTitleLabel = DirectLabel(parent=page, relief=None, text=TTLocalizer.PartyPlannerDateTitle, pos=self.gui.find('**/title_locator').getPos(), scale=self.titleScale) pos = self.gui.find('**/step_06_sendInvitation_locator').getPos() self.makePartyNowButton = DirectButton(parent=page, relief=None, geom=(self.gui.find('**/send_up'), self.gui.find('**/send_down'), self.gui.find('**/send_rollover')), text=TTLocalizer.PartyPlannerPartyNow, text_pos=(pos[0], pos[2]), text_scale=0.05, command=self.__doMakePartyNow) curServerDate = base.cr.toontownTimeManager.getCurServerDateTime() self.calendarGuiMonth = CalendarGuiMonth(page, curServerDate, scale=0.95, pos=(-0.05, 0.0, -0.33), dayClickCallback=self._dayClickCallback, onlyFutureDaysClickable=True) return page def __doMakePartyNow(self): self.request('Invitation') def _dayClickCallback(self, calendarGuiDay): self.selectedCalendarGuiDay = calendarGuiDay self.nextButton['state'] = DirectGuiGlobals.NORMAL self.makePartyNowButton.hide() self.nextButton.show() def alterPartyTime(self, year = None, month = None, day = None, hour = None, minute = None): self.partyTime = datetime(year=self.positiveTime('year', year), month=self.positiveTime('month', month), day=self.positiveTime('day', day), hour=self.positiveTime('hour', hour), minute=self.positiveTime('minute', minute), tzinfo=self.partyTime.tzinfo) def positiveTime(self, type, amount): if amount is None: return getattr(self.partyTime, type) if type == 'hour' or type == 'minute': if amount < 0: return self.timeTypeToMaxValue[type] + 1 + self.timeTypeToChangeAmount[type][1] elif amount > self.timeTypeToMaxValue[type]: return 0 return amount def _createTimePage(self): page = DirectFrame(self.frame) page.setName('PartyPlannerTimePage') self.createTimeTitleLabel = DirectLabel(parent=page, relief=None, text=TTLocalizer.PartyPlannerTimeTitle, pos=self.gui.find('**/title_locator').getPos(), scale=self.titleScale) self.clockImage = DirectFrame(parent=page, relief=None, geom=self.gui.find('**/toontownTime_background')) self.timePageToontownLabel = DirectLabel(parent=page, relief=None, text=TTLocalizer.PartyPlannerTimeToontown, pos=self.gui.find('**/step_03_toontown_locator').getPos(), scale=0.15, text_fg=(1.0, 0.0, 0.0, 1.0), text_font=ToontownGlobals.getSignFont()) self.timePageTimeLabel = DirectLabel(parent=page, relief=None, text=TTLocalizer.PartyPlannerTimeTime, pos=self.gui.find('**/step_03_time_locator').getPos(), scale=0.15, text_fg=(1.0, 0.0, 0.0, 1.0), text_font=ToontownGlobals.getSignFont()) self.timePageRecapLabel = DirectLabel(parent=page, relief=None, text=TTLocalizer.PartyPlannerTimeRecap, pos=self.gui.find('**/step_03_partyDateAndTime_locator').getPos(), scale=0.09) self.timePageRecapToontownTimeLabel1 = DirectLabel(parent=page, relief=None, text=TTLocalizer.PartyPlannerTimeToontownTime, pos=self.gui.find('**/step_03_toontownTime_locator').getPos(), scale=0.06) self.timePageRecapToontownTimeLabel2 = DirectLabel(parent=page, relief=None, text='%s' % PartyUtils.formatDateTime(self.partyTime), pos=self.gui.find('**/step_03_toontownDateAndTime_loactor').getPos(), textMayChange=True, scale=0.06) self.timePageRecapLocalTimeLabel = DirectLabel(parent=page, relief=None, text='%s%s' % (TTLocalizer.PartyPlannerTimeLocalTime, PartyUtils.formatDateTime(self.partyTime, inLocalTime=True)), pos=self.gui.find('**/step_03_localDateAndTime_loactor').getPos(), textMayChange=True, scale=0.06, text_fg=(1.0, 0.0, 0.0, 1.0)) self.timeInputHourLabel, self.timeInputHourUpButton, self.timeInputHourDownButton = self.getTimeWidgets(page, 'hour') self.timeInputMinuteLabel, self.timeInputMinuteUpButton, self.timeInputMinuteDownButton = self.getTimeWidgets(page, 'minute') self.timeInputAmPmLabel, self.timeInputAmPmUpButton, self.timeInputAmPmDownButton = self.getTimeWidgets(page, 'ampm') self.timePagecolonLabel = DirectLabel(parent=page, relief=None, text=':', pos=self.gui.find('**/step_03_colon_locator').getPos(), scale=0.15) return page def getTimeWidgets(self, page, type): if type == 'ampm': data = self.getCurrentAmPm() else: data = getattr(self.partyTime, type) if data == 0 and type == 'minute': data = '00' else: if type == 'hour': data = data % 12 if data == 0: data = 12 data = '%d' % data label = DirectLabel(parent=page, relief=None, text='%s' % data, textMayChange=True, pos=self.gui.find('**/step_03_%s_locator' % type).getPos(), scale=0.12) def changeValue(self, amount): if type == 'ampm': self.alterPartyTime(hour=(self.partyTime.hour + 12) % 24) newAmount = self.getCurrentAmPm() label['text'] = newAmount else: if type == 'hour': newAmount = getattr(self.partyTime, type) + amount newAmount = newAmount % 12 if self.timeInputAmPmLabel['text'] == TTLocalizer.PartyTimeFormatMeridiemPM: newAmount = newAmount % 12 + 12 self.alterPartyTime(hour=newAmount) elif type == 'minute': newAmount = getattr(self.partyTime, type) + amount self.alterPartyTime(minute=newAmount) else: PartyPlanner.notify.error('Invalid type for changeValue in PartyPlanner: %s' % type) newAmount = getattr(self.partyTime, type) if newAmount < 10 and type == 'minute': label['text'] = '0%d' % newAmount else: if type == 'hour': newAmount = newAmount % 12 if newAmount == 0: newAmount = 12 label['text'] = '%d' % newAmount self.timePageRecapToontownTimeLabel2['text'] = '%s' % PartyUtils.formatDateTime(self.partyTime) self.timePageRecapLocalTimeLabel['text'] = '%s%s' % (TTLocalizer.PartyPlannerTimeLocalTime, PartyUtils.formatDateTime(self.partyTime, inLocalTime=True)) upButton = DirectButton(parent=page, relief=None, geom=(self.gui.find('**/%sButtonUp_up' % type), self.gui.find('**/%sButtonUp_down' % type), self.gui.find('**/%sButtonUp_rollover' % type)), command=changeValue, extraArgs=[self, self.timeTypeToChangeAmount[type][0]]) downButton = DirectButton(parent=page, relief=None, geom=(self.gui.find('**/%sButtonDown_up' % type), self.gui.find('**/%sButtonDown_down' % type), self.gui.find('**/%sButtonDown_rollover' % type)), command=changeValue, extraArgs=[self, self.timeTypeToChangeAmount[type][1]]) return (label, upButton, downButton) def getCurrentAmPm(self): if self.partyTime.hour < 12: return TTLocalizer.PartyTimeFormatMeridiemAM else: return TTLocalizer.PartyTimeFormatMeridiemPM def _createGuestPage(self): page = DirectFrame(self.frame) page.setName('PartyPlannerGuestPage') self.guestTitleLabel = DirectLabel(parent=page, relief=None, text=TTLocalizer.PartyPlannerGuestTitle, pos=self.gui.find('**/title_locator').getPos(), scale=self.titleScale) self.guestBackgroundLabel = DirectLabel(parent=page, relief=None, image=self.gui.find('**/guestListBackground_flat'), scale=(1.2, 1.0, 1.0)) self.friendList = ScrolledFriendList(page, self.gui, makeItemsCheckBoxes=True) if len(base.localAvatar.friendsList) == 0: self.noFriends = True else: self.noFriends = False for friendPair in base.localAvatar.friendsList: self.friendList.addFriend(determineFriendName(friendPair), friendPair[0]) self.friendList.scrollTo(0) pos = self.gui.find('**/step_04_partyWillBe_locator').getPos() self.publicPrivateLabel = DirectLabel(parent=page, relief=None, text=TTLocalizer.PartyPlannerPublicPrivateLabel, text_align=TextNode.ACenter, text_scale=0.065, pos=pos) self.publicDescriptionLabel = DirectLabel(parent=page, relief=None, text=TTLocalizer.PartyPlannerPublicDescription, text_align=TextNode.ACenter, text_scale=TTLocalizer.PPpbulicDescriptionLabel, pos=(pos[0] - 0.52, pos[1], pos[2])) self.publicDescriptionLabel.stash() self.privateDescriptionLabel = DirectLabel(parent=page, relief=None, text=TTLocalizer.PartyPlannerPrivateDescription, text_align=TextNode.ACenter, text_scale=TTLocalizer.PPprivateDescriptionLabel, pos=(pos[0] + 0.55, pos[1], pos[2])) self.privateDescriptionLabel.stash() pos = self.gui.find('**/step_04_public_locator').getPos() self.publicButton = DirectButton(parent=page, relief=None, geom=(self.gui.find('**/publicButton_up'), self.gui.find('**/publicButton_down'), self.gui.find('**/publicButton_rollover'), self.gui.find('**/publicButton_inactive')), text=TTLocalizer.PartyPlannerPublic, text_pos=(pos[0], pos[2]), text_scale=TTLocalizer.PPpublicButton, command=self.__doTogglePublicPrivate) self.publicButton['state'] = DirectGuiGlobals.DISABLED self.publicButton.bind(DirectGuiGlobals.ENTER, self.__enterPublic) self.publicButton.bind(DirectGuiGlobals.EXIT, self.__exitPublic) pos = self.gui.find('**/step_04_private_locator').getPos() self.privateButton = DirectButton(parent=page, relief=None, geom=(self.gui.find('**/privateButton_up'), self.gui.find('**/privateButton_down'), self.gui.find('**/privateButton_rollover'), self.gui.find('**/privateButton_inactive')), text=TTLocalizer.PartyPlannerPrivate, text_pos=(pos[0], pos[2]), text_scale=TTLocalizer.PPprivateButton, command=self.__doTogglePublicPrivate) self.privateButton.bind(DirectGuiGlobals.ENTER, self.__enterPrivate) self.privateButton.bind(DirectGuiGlobals.EXIT, self.__exitPrivate) self.checkAllButton = DirectButton(parent=page, relief=None, geom=(self.gui.find('**/checkAllButton_up'), self.gui.find('**/checkAllButton_down'), self.gui.find('**/checkAllButton_rollover')), command=self.__doCheckAll) self.uncheckAllButton = DirectButton(parent=page, relief=None, geom=(self.gui.find('**/uncheckAllButton_up'), self.gui.find('**/uncheckAllButton_down'), self.gui.find('**/uncheckAllButton_rollover')), command=self.__doUncheckAll) return page def __doCheckAll(self): for friendBox in self.friendList['items']: friendBox['indicatorValue'] = True def __doUncheckAll(self): for friendBox in self.friendList['items']: friendBox['indicatorValue'] = False def __enterPrivate(self, mouseEvent): self.privateDescriptionLabel.unstash() def __exitPrivate(self, mouseEvent): self.privateDescriptionLabel.stash() def __enterPublic(self, mouseEvent): self.publicDescriptionLabel.unstash() def __exitPublic(self, mouseEvent): self.publicDescriptionLabel.stash() def __doTogglePublicPrivate(self): if self.isPrivate: self.isPrivate = False self.privateButton['state'] = DirectGuiGlobals.NORMAL self.publicButton['state'] = DirectGuiGlobals.DISABLED else: self.isPrivate = True self.privateButton['state'] = DirectGuiGlobals.DISABLED self.publicButton['state'] = DirectGuiGlobals.NORMAL def _createPartyEditorPage(self): page = DirectFrame(self.frame) page.setName('PartyPlannerEditorPage') self.LayoutTitleLabel = DirectLabel(parent=page, relief=None, text=TTLocalizer.PartyPlannerEditorTitle, pos=self.gui.find('**/title_locator').getPos() + Point3(0.0, 0.0, 0.075), scale=self.titleScale) self.costLabel = DirectLabel(parent=page, pos=(-0.74, 0.0, 0.17), relief=None, text=TTLocalizer.PartyPlannerTotalCost % 0, text_align=TextNode.ACenter, scale=TTLocalizer.PPcostLabel, textMayChange=True) self.partyGridBackground = DirectFrame(parent=page, relief=None, geom=self.gui.find('**/partyGrid_flat')) self.partyGroundsLabel = DirectLabel(parent=page, relief=None, text=TTLocalizer.PartyPlannerPartyGrounds, text_font=ToontownGlobals.getSignFont(), text_fg=VBase4(1.0, 0.0, 0.0, 1.0), text_scale=TTLocalizer.PPpartyGroundsLabel, pos=self.gui.find('**/step_05_partyGrounds_text_locator').getPos(), scale=0.1) self.activityBackground = DirectFrame(parent=page, relief=None, geom=self.gui.find('**/activitiesDecorations_flat1'), pos=(0.0, 0.0, 0.04)) pos = self.gui.find('**/step_05_instructions_locator').getPos() self.instructionLabel = DirectLabel(parent=page, relief=None, text=' ', text_pos=(pos[0], pos[2]), text_scale=TTLocalizer.PPinstructionLabel, textMayChange=True, geom=self.gui.find('**/instructions_flat')) self.elementTitleLabel = DirectLabel(parent=page, relief=None, text=' ', pos=self.gui.find('**/step_05_activitiesName_text_locator').getPos() + Point3(0.0, 0.0, 0.04), text_scale=TTLocalizer.PPelementTitleLabel, textMayChange=True) self.elementPriceNode = TextNode('ElementPrice') self.elementPriceNode.setAlign(TextNode.ALeft) self.elementPriceNode.setTextColor(0.0, 0.0, 0.0, 1.0) self.elementPriceNode.setFont(ToontownGlobals.getToonFont()) self.elementPrice = page.attachNewNode(self.elementPriceNode) self.elementPrice.setScale(TTLocalizer.PPelementPriceNode) self.elementPrice.setPos(self.gui.find('**/step_05_activityPrice_text_locator').getPos() + Point3(-0.02, 0.0, 0.04)) self.elementDescriptionNode = TextNode('ElementDescription') self.elementDescriptionNode.setAlign(TextNode.ACenter) self.elementDescriptionNode.setWordwrap(8) self.elementDescriptionNode.setFont(ToontownGlobals.getToonFont()) self.elementDescriptionNode.setTextColor(0.0, 0.0, 0.0, 1.0) self.elementDescription = page.attachNewNode(self.elementDescriptionNode) self.elementDescription.setScale(TTLocalizer.PPelementDescription) self.elementDescription.setPos(self.gui.find('**/step_05_activityDescription_text_locator').getPos() + Point3(0.0, 0.0, 0.04)) self.totalMoney = base.localAvatar.getTotalMoney() catalogGui = loader.loadModel('phase_5.5/models/gui/catalog_gui') self.beanBank = DirectLabel(parent=page, relief=None, text=str(self.totalMoney), text_align=TextNode.ARight, text_scale=0.075, text_fg=(0.95, 0.95, 0, 1), text_shadow=(0, 0, 0, 1), text_pos=(0.495, -0.53), text_font=ToontownGlobals.getSignFont(), textMayChange=True, image=catalogGui.find('**/bean_bank'), image_scale=(0.65, 0.65, 0.65), scale=0.9, pos=(-0.75, 0.0, 0.6)) catalogGui.removeNode() del catalogGui self.accept(localAvatar.uniqueName('moneyChange'), self.__moneyChange) self.accept(localAvatar.uniqueName('bankMoneyChange'), self.__moneyChange) self.partyEditor = PartyEditor(self, page) self.partyEditor.request('Hidden') pos = self.gui.find('**/step_05_add_text_locator').getPos() self.elementBuyButton = DirectButton(parent=page, relief=None, text=TTLocalizer.PartyPlannerBuy, text_pos=(pos[0], pos[2]), text_scale=TTLocalizer.PPelementBuyButton, geom=(self.gui.find('**/add_up'), self.gui.find('**/add_down'), self.gui.find('**/add_rollover')), geom3_color=VBase4(0.5, 0.5, 0.5, 1.0), textMayChange=True, pos=(0.0, 0.0, 0.04), command=self.partyEditor.buyCurrentElement) self.okWithPartyGroundsLayoutEvent = 'okWithPartyGroundsLayoutEvent' self.accept(self.okWithPartyGroundsLayoutEvent, self.okWithPartyGroundsLayout) self.okWithGroundsGui = TTDialog.TTGlobalDialog(dialogName=self.uniqueName('PartyEditorOkGui'), doneEvent=self.okWithPartyGroundsLayoutEvent, message=TTLocalizer.PartyPlannerOkWithGroundsLayout, style=TTDialog.YesNo, okButtonText=OTPLocalizer.DialogYes, cancelButtonText=OTPLocalizer.DialogNo) self.okWithGroundsGui.doneStatus = '' self.okWithGroundsGui.hide() return page def okWithPartyGroundsLayout(self): self.okWithGroundsGui.hide() if self.okWithGroundsGui.doneStatus == 'ok': self.__nextItem() def setNextButtonState(self, enabled): if enabled: self.nextButton['state'] = DirectGuiGlobals.NORMAL self.nextButton.show() else: self.nextButton['state'] = DirectGuiGlobals.DISABLED self.nextButton.hide() def _createInvitationPage(self): self.__handleHolidays() page = DirectFrame(self.frame) page.setName('PartyPlannerInvitationPage') self.invitationTitleLabel = DirectLabel(parent=page, relief=None, text=TTLocalizer.PartyPlannerConfirmTitle, textMayChange=True, pos=self.gui.find('**/title_locator').getPos(), scale=self.titleScale) self.invitationBackground = DirectFrame(parent=page, relief=None, geom=self.gui.find('**/invitationBackground')) self.inviteVisual = InviteVisual(page) self.selectedInviteThemeLabel = DirectLabel(parent=page, relief=None, pos=self.gui.find('**/step_06_theme_locator').getPos(), text='', text_scale=0.06, textMayChange=True) self.nextThemeButton = DirectButton(parent=page, relief=None, geom=(self.gui.find('**/topNext_button/nextButton_up'), self.gui.find('**/topNext_button/nextButton_down'), self.gui.find('**/topNext_button/nextButton_rollover')), command=self.__nextTheme) self.prevThemeButton = DirectButton(parent=page, relief=None, geom=(self.gui.find('**/topPrevious_button/previousButton_up'), self.gui.find('**/topPrevious_button/previousButton_down'), self.gui.find('**/topPrevious_button/previousButton_rollover')), command=self.__prevTheme) pos = self.gui.find('**/step_06_sendInvitation_locator').getPos() self.inviteButton = DirectButton(parent=page, relief=None, geom=(self.gui.find('**/send_up'), self.gui.find('**/send_down'), self.gui.find('**/send_rollover')), text=TTLocalizer.PartyPlannerInviteButton, textMayChange=True, text_scale=0.05, text_pos=(pos[0], pos[2]), command=self.__handleComplete) return page def __handleHolidays(self): self.inviteThemes = range(len(PartyGlobals.InviteTheme)) if hasattr(base.cr, 'newsManager') and base.cr.newsManager: holidayIds = base.cr.newsManager.getHolidayIdList() if ToontownGlobals.VALENTINES_DAY not in holidayIds: self.inviteThemes.remove(PartyGlobals.InviteTheme.Valentoons) if ToontownGlobals.VICTORY_PARTY_HOLIDAY not in holidayIds: self.inviteThemes.remove(PartyGlobals.InviteTheme.VictoryParty) if ToontownGlobals.WINTER_DECORATIONS not in holidayIds and ToontownGlobals.WACKY_WINTER_DECORATIONS not in holidayIds: self.inviteThemes.remove(PartyGlobals.InviteTheme.Winter) def _createFarewellPage(self): page = DirectFrame(self.frame) page.setName('PartyPlannerFarewellPage') self.confirmTitleLabel = DirectLabel(parent=page, relief=None, text=TTLocalizer.PartyPlannerConfirmationAllOkTitle, textMayChange=True, pos=self.gui.find('**/title_locator').getPos(), scale=self.titleScale) pos = self.gui.find('**/step_07_close_text_locator').getPos() self.closePlannerButton = DirectButton(parent=page, relief=None, geom=(self.gui.find('**/close_up'), self.gui.find('**/close_down'), self.gui.find('**/close_rollover')), text=TTLocalizer.PartyPlannerClosePlanner, text_scale=0.055, text_pos=(pos[0], pos[2]), command=self.__acceptExit) return page def close(self): self.ignore('addPartyResponseReceived') self.ignore(localAvatar.uniqueName('moneyChange')) self.ignore(localAvatar.uniqueName('bankMoneyChange')) self.timeInputHourUpButton.destroy() self.timeInputHourDownButton.destroy() self.timeInputMinuteUpButton.destroy() self.timeInputMinuteDownButton.destroy() self.timeInputAmPmUpButton.destroy() self.timeInputAmPmDownButton.destroy() self.privateButton.destroy() self.publicButton.destroy() self.makePartyNowButton.destroy() self.checkAllButton.destroy() self.uncheckAllButton.destroy() self.elementBuyButton.destroy() self.nextThemeButton.destroy() self.prevThemeButton.destroy() self.inviteButton.destroy() self.closePlannerButton.destroy() self.ignore(self.okWithPartyGroundsLayoutEvent) if hasattr(self, 'okWithGroundsGui'): self.okWithGroundsGui.cleanup() del self.okWithGroundsGui if hasattr(self, 'frame') and not self.frame.isEmpty(): messenger.send(self.doneEvent) self.hide() self.cleanup() self.friendList.removeAndDestroyAllItems() self.friendList.destroy() self.calendarGuiMonth.destroy() self.frame.destroy() self.partyPlannerHead.delete() self.partyPlannerHead.removeNode() self.clearNametag() self.partyEditor.request('Cleanup') self.partyEditor = None self.destroy() del self return def __handleComplete(self): self.inviteButton['state'] = DirectGuiGlobals.DISABLED self.prevButton['state'] = DirectGuiGlobals.DISABLED endTime = self.partyTime + self.partyDuration hostId = base.localAvatar.doId self.partyActivities = self.partyEditor.partyEditorGrid.getActivitiesOnGrid() decorations = self.partyEditor.partyEditorGrid.getDecorationsOnGrid() invitees = self.getInvitees() self.accept('addPartyResponseReceived', self.processAddPartyResponse) base.cr.partyManager.sendAddParty(hostId, self.partyTime.strftime('%Y-%m-%d %H:%M:%S'), endTime.strftime('%Y-%m-%d %H:%M:%S'), self.isPrivate, self.currentInvitationTheme, self.partyActivities, decorations, invitees) def getInvitees(self): invitees = [] for friendBox in self.friendList['items']: if friendBox['indicatorValue']: invitees.append(friendBox.getPythonTag('id')) return invitees def processAddPartyResponse(self, hostId, errorCode): PartyPlanner.notify.debug('processAddPartyResponse : hostId=%d errorCode=%s' % (hostId, PartyGlobals.AddPartyErrorCode.getString(errorCode))) goingBackAllowed = False if errorCode == PartyGlobals.AddPartyErrorCode.AllOk: goingBackAllowed = False self.confirmTitleLabel['text'] = TTLocalizer.PartyPlannerConfirmationAllOkTitle if self.noFriends or len(self.getInvitees()) == 0: confirmRecapText = TTLocalizer.PartyPlannerConfirmationAllOkTextNoFriends else: confirmRecapText = TTLocalizer.PartyPlannerConfirmationAllOkText elif errorCode == PartyGlobals.AddPartyErrorCode.ValidationError: self.confirmTitleLabel['text'] = TTLocalizer.PartyPlannerConfirmationErrorTitle confirmRecapText = TTLocalizer.PartyPlannerConfirmationValidationErrorText elif errorCode == PartyGlobals.AddPartyErrorCode.DatabaseError: self.confirmTitleLabel['text'] = TTLocalizer.PartyPlannerConfirmationErrorTitle confirmRecapText = TTLocalizer.PartyPlannerConfirmationDatabaseErrorText elif errorCode == PartyGlobals.AddPartyErrorCode.TooManyHostedParties: goingBackAllowed = False self.confirmTitleLabel['text'] = TTLocalizer.PartyPlannerConfirmationErrorTitle confirmRecapText = TTLocalizer.PartyPlannerConfirmationTooManyText self.nametagGroup.setChat(confirmRecapText, CFSpeech) self.request('Farewell', goingBackAllowed) def __acceptExit(self): PartyPlanner.notify.debug('__acceptExit') if hasattr(self, 'frame'): self.hide() messenger.send(self.doneEvent) def __nextItem(self): messenger.send('wakeup') if self.state == 'PartyEditor' and self.okWithGroundsGui.doneStatus != 'ok': self.okWithGroundsGui.show() return if self.state == 'PartyEditor' and self.noFriends: self.request('Date') self.selectedCalendarGuiDay = None self.calendarGuiMonth.clearSelectedDay() return if self.state == 'Guests': self.selectedCalendarGuiDay = None self.calendarGuiMonth.clearSelectedDay() if self.state == 'Time': if self.partyTime < base.cr.toontownTimeManager.getCurServerDateTime(): self.okChooseFutureTimeEvent = 'okChooseFutureTimeEvent' self.acceptOnce(self.okChooseFutureTimeEvent, self.okChooseFutureTime) self.chooseFutureTimeDialog = TTDialog.TTGlobalDialog(dialogName=self.uniqueName('chooseFutureTimeDialog'), doneEvent=self.okChooseFutureTimeEvent, message=TTLocalizer.PartyPlannerChooseFutureTime, style=TTDialog.Acknowledge) self.chooseFutureTimeDialog.show() return self.requestNext() return def okChooseFutureTime(self): if hasattr(self, 'chooseFutureTimeDialog'): self.chooseFutureTimeDialog.cleanup() del self.chooseFutureTimeDialog if hasattr(self, 'okChooseFutureTimeEvent'): self.ignore(self.okChooseFutureTimeEvent) def __prevItem(self): messenger.send('wakeup') if self.state == 'Date' and self.noFriends: self.request('PartyEditor') return if self.state == 'Invitation' and self.selectedCalendarGuiDay is None: self.request('Guests') return self.requestPrev() return def __moneyChange(self, newMoney): if hasattr(self, 'totalMoney'): self.totalMoney = base.localAvatar.getTotalMoney() if hasattr(self, 'beanBank'): self.beanBank['text'] = str(int(self.totalMoney))
class PlacerTool3D(DirectFrame): ORIGINAL_SCALE = (1.0, 1.0, 1.0) MINIMIZED_SCALE = (0.85, 1.0, 0.15) ORIG_DRAG_BUTTON_POS = (0.37, 0.0, 0.37) MINI_DRAG_BUTTON_POS = (0.37, 0.0, 0.03) ORIG_MINI_BUTTON_POS = (0.29, 0.0, 0.37) MINI_MINI_BUTTON_POS = (0.29, 0.0, 0.03) ORIG_NAME_POS = (-0.39, 0.0, 0.27) MINI_NAME_POS = (-0.39, 0.0, 0.0) def __init__(self, target, increment=0.01, hprIncrement=1.0, parent=aspect2d, pos=(0.0, 0.0, 0.0)): DirectFrame.__init__(self, parent) self.target = target self.increment = increment self.minimized = False self.mainFrame = DirectFrame( parent=self, relief=None, geom=DGG.getDefaultDialogGeom(), geom_color=(1, 1, 0.75, 1), geom_scale=self.ORIGINAL_SCALE, pos=pos, ) # Arrow gui (preload) gui = loader.loadModel('phase_3/models/gui/tt_m_gui_mat_mainGui.bam') # Set Bins self.mainFrame.setBin('gui-popup', 0) # Name name = self.target.getName() self.nameLabel = TTLabel(self.mainFrame, text='Target: %s' % name, pos=self.ORIG_NAME_POS, text_align=TextNode.ALeft, text_wordwrap=13) # Pos pos = self.target.getPos() self.posLabel = TTLabel(self.mainFrame, text='Position: ', pos=(-0.39, 0.0, 0.055), text_align=TextNode.ALeft) self.xPosSpinner = PlacerToolSpinner(self.mainFrame, value=pos[0], pos=(-0.085, 0.0, 0.06), increment=increment, callback=self.handleXChange) self.yPosSpinner = PlacerToolSpinner(self.mainFrame, value=pos[1], pos=(0.1, 0.0, 0.06), increment=increment, callback=self.handleYChange) self.zPosSpinner = PlacerToolSpinner(self.mainFrame, value=pos[2], pos=(0.28, 0.0, 0.06), increment=increment, callback=self.handleZChange) # hpr hpr = self.target.getHpr() self.hprLabel = TTLabel(self.mainFrame, text='HPR: ', pos=(-0.39, 0.0, -0.19), text_align=TextNode.ALeft) self.hSpinner = PlacerToolSpinner(self.mainFrame, value=hpr[0], pos=(-0.085, 0.0, -0.195), increment=hprIncrement, callback=self.handleHChange) self.pSpinner = PlacerToolSpinner(self.mainFrame, value=hpr[1], pos=(0.1, 0.0, -0.195), increment=hprIncrement, callback=self.handlePChange) self.rSpinner = PlacerToolSpinner(self.mainFrame, value=hpr[2], pos=(0.28, 0.0, -0.195), increment=hprIncrement, callback=self.handleRChange) # scale scale = [round(s, 3) for s in self.target.getScale()] self.scaleLabel = TTLabel(self.mainFrame, text='Scale: ', pos=(-0.39, 0.0, -0.4), text_align=TextNode.ALeft) self.sxSpinner = PlacerToolSpinner(self.mainFrame, value=hpr[0], pos=(-0.085, 0.0, -0.4), increment=increment, callback=self.handleSxChange) self.sySpinner = PlacerToolSpinner(self.mainFrame, value=hpr[1], pos=(0.1, 0.0, -0.4), increment=increment, callback=self.handleSyChange) self.szSpinner = PlacerToolSpinner(self.mainFrame, value=hpr[2], pos=(0.28, 0.0, -0.4), increment=increment, callback=self.handleSzChange) gui.removeNode() gui = loader.loadModel('phase_3/models/gui/tt_m_gui_mat_nameShop') thumb = gui.find('**/tt_t_gui_mat_namePanelCircle') self.dragButton = DirectButton(self.mainFrame, relief=None, image=thumb, image_scale=(0.5, 0.5, 0.5), pos=self.ORIG_DRAG_BUTTON_POS) self.minimizeButton = DirectButton(self.mainFrame, relief=None, image=thumb, image_scale=(0.5, 0.5, 0.5), image_color=(0.0, 0.0, 0.65, 1.0), pos=self.ORIG_MINI_BUTTON_POS, command=self.toggleMinimize, extraArgs=[]) self.dragButton.bind(DGG.B1PRESS, self.onPress) if target is not None: self.setTarget(target) def destroy(self): self.target = None messenger.send('placer-destroyed', [self]) DirectFrame.destroy(self) def setTarget(self, target): self.target = target name = self.target.getName() scale = [round(s, 3) for s in self.target.getScale()] x, y, z = self.target.getPos() h, p, r = self.target.getHpr() sx, sy, sz = self.target.getScale() self.nameLabel['text'] = 'Target: %s' % name self.xPosSpinner.setValue(x) self.yPosSpinner.setValue(y) self.zPosSpinner.setValue(z) self.hSpinner.setValue(h) self.pSpinner.setValue(p) self.rSpinner.setValue(r) self.sxSpinner.setValue(sx) self.sySpinner.setValue(sy) self.szSpinner.setValue(sz) def handleXChange(self, value): self.changeTargetPos(0, value) def handleYChange(self, value): self.changeTargetPos(1, value) def handleZChange(self, value): self.changeTargetPos(2, value) def handleHChange(self, value): self.changeTargetHpr(0, value) def handlePChange(self, value): self.changeTargetHpr(1, value) def handleRChange(self, value): self.changeTargetHpr(2, value) def handleSxChange(self, value): self.changeTargetScale(0, value) def handleSyChange(self, value): self.changeTargetScale(1, value) def handleSzChange(self, value): self.changeTargetScale(2, value) def changeTargetPos(self, index, value): pos = self.target.getPos() pos[index] = float(value) self.target.setPos(pos) def changeTargetHpr(self, index, value): hpr = self.target.getHpr() hpr[index] = float(value) self.target.setHpr(hpr) def changeTargetScale(self, index, value): pos = self.target.getScale() pos[index] = float(value) self.target.setScale(pos) def toggleMinimize(self): if self.minimized: self.maximize() else: self.minimize() def minimize(self): self.minimized = True self.mainFrame['geom_scale'] = self.MINIMIZED_SCALE self.nameLabel.setPos(self.MINI_NAME_POS) self.dragButton.setPos(self.MINI_DRAG_BUTTON_POS) self.minimizeButton.setPos(self.MINI_MINI_BUTTON_POS) self.posLabel.hide() self.xPosSpinner.hide() self.yPosSpinner.hide() self.zPosSpinner.hide() self.hprLabel.hide() self.hSpinner.hide() self.pSpinner.hide() self.rSpinner.hide() self.scaleLabel.hide() self.setPos(0, 0, 0) def maximize(self): self.minimized = False self.mainFrame['geom_scale'] = self.ORIGINAL_SCALE self.nameLabel.setPos(self.ORIG_NAME_POS) self.dragButton.setPos(self.ORIG_DRAG_BUTTON_POS) self.minimizeButton.setPos(self.ORIG_MINI_BUTTON_POS) self.posLabel.show() self.xPosSpinner.show() self.yPosSpinner.show() self.zPosSpinner.show() self.hprLabel.show() self.hSpinner.show() self.pSpinner.show() self.rSpinner.show() self.scaleLabel.show() self.setPos(0, 0, 0) def onPress(self, e=None): self.accept('mouse1-up', self.onRelease) taskMgr.add(self.mouseMoverTask, '%s-mouseMoverTask' % self.id) def onRelease(self, e=None): self.ignore('mouse1-up') taskMgr.remove('%s-mouseMoverTask' % self.id) def mouseMoverTask(self, task): if base.mouseWatcherNode.hasMouse(): mpos = base.mouseWatcherNode.getMouse() buttonPos = self.dragButton.getPos() newPos = (mpos[0] - buttonPos[0] / 2 - 0.02, 0, mpos[1] - buttonPos[2]) self.setPos(render2d, newPos) return task.cont
def _show_char_desc(self): """Show detailed character description. Includes description of every character's trait and their current status. """ if self._char_desc_shown: self._fr["frameSize"] = (-0.31, 0.31, -0.1, 0.115) clear_wids(self._char_desc_wids) self._status_lab = None else: shift = 0.7 self._fr["frameSize"] = (-0.31, 0.31, -0.1, shift) shift -= 0.06 self._char_desc_wids.append( DirectLabel( parent=self._fr, # Traits text=base.labels.CHARACTERS[5], # noqa: F821, text_font=base.main_font, # noqa: F821, frameSize=(0.1, 0.1, 0.1, 0.1), text_scale=0.03, text_fg=RUST_COL, pos=(-0.225, 0, shift), ) ) if self.char.id in base.team.chars.keys(): # noqa: F821 traits_but = DirectButton( parent=self._fr, text="", frameSize=(-0.025, 0.025, -0.025, 0.025), frameTexture=GUI_PIC + "like.png", relief="flat", pos=(0.265, 0, shift + 0.013), command=base.traits_gui.show, # noqa: F821 ) traits_but.bind( DGG.ENTER, self._highlight_traits_but, extraArgs=[traits_but] ) traits_but.bind( DGG.EXIT, self._dehighlight_traits_but, extraArgs=[traits_but] ) self._char_desc_wids.append(traits_but) shift = self._fill_traits(shift) self._status_lab = DirectLabel( # Status parent=self._fr, # Status text=base.labels.CHARACTERS[4], # noqa: F821 text_font=base.main_font, # noqa: F821 frameSize=(0.1, 0.1, 0.1, 0.1), text_scale=0.03, text_fg=RUST_COL, pos=(-0.221, 0, shift), ) self._char_desc_wids.append(self._status_lab) self._fill_status(shift) self._char_desc_shown = not self._char_desc_shown
class DirectWindow(DirectFrame): def __init__( self, pos=(-.5, .5), title='Title', curSize=(1, 1), maxSize=(1, 1), minSize=(.5, .5), backgroundColor=(1, 1, 1, 1), borderColor=(1, 1, 1, 1), titleColor=(1, 1, 1, 1), borderSize=0.04, titleSize=0.06, closeButton=False, windowParent=aspect2d, preserve=True, preserveWhole=True, ): self.preserve = preserve self.preserveWhole = preserveWhole self.windowParent = windowParent self.windowPos = pos DirectFrame.__init__( self, parent=windowParent, pos=(self.windowPos[0], 0, self.windowPos[1]), frameColor=(0, 0, 0, 0), frameTexture=loader.loadTexture(DIRECTORY + 'transparent.png')) self.setTransparency(True) # the title part of the window, drag around to move the window self.headerHeight = titleSize h = -self.headerHeight self.windowHeaderLeft = DirectButton( parent=self, frameTexture=DEFAULT_TITLE_GEOM_LEFT, frameSize=(-.5, .5, -.5, .5), borderWidth=(0, 0), relief=DGG.FLAT, frameColor=titleColor, ) self.windowHeaderCenter = DirectButton( parent=self, frameTexture=DEFAULT_TITLE_GEOM_CENTER, frameSize=(-.5, .5, -.5, .5), borderWidth=(0, 0), relief=DGG.FLAT, frameColor=titleColor, ) if closeButton: rightTitleGeom = DEFAULT_TITLE_GEOM_RIGHT_CLOSE command = self.destroy else: rightTitleGeom = DEFAULT_TITLE_GEOM_RIGHT command = None self.windowHeaderRight = DirectButton(parent=self, frameTexture=rightTitleGeom, frameSize=(-.5, .5, -.5, .5), borderWidth=(0, 0), relief=DGG.FLAT, frameColor=titleColor, command=command) self.windowHeaderLeft.setTransparency(True) self.windowHeaderCenter.setTransparency(True) self.windowHeaderRight.setTransparency(True) self.windowHeaderLeft.bind(DGG.B1PRESS, self.startWindowDrag) self.windowHeaderCenter.bind(DGG.B1PRESS, self.startWindowDrag) self.windowHeaderRight.bind(DGG.B1PRESS, self.startWindowDrag) # this is not handled correctly, if a window is dragged which has been # created before another it will not be released # check the bugfixed startWindowDrag function #self.windowHeader.bind(DGG.B1RELEASE,self.stopWindowDrag) text = TextNode('WindowTitleTextNode') text.setText(title) text.setAlign(TextNode.ACenter) text.setTextColor(0, 0, 0, 1) text.setShadow(0.05, 0.05) text.setShadowColor(1, 1, 1, 1) self.textNodePath = self.attachNewNode(text) self.textNodePath.setScale(self.headerHeight * 0.8) # the content part of the window, put stuff beneath # contentWindow.getCanvas() to put it into it self.maxVirtualSize = maxSize self.minVirtualSize = minSize self.resizeSize = borderSize self.contentWindow = DirectScrolledFrame( parent=self, pos=(0, 0, -self.headerHeight), canvasSize=(0, self.maxVirtualSize[0], 0, self.maxVirtualSize[1]), frameColor=( 0, 0, 0, 0), # defines the background color of the resize-button relief=DGG.FLAT, borderWidth=(0, 0), verticalScroll_frameSize=[0, self.resizeSize, 0, 1], horizontalScroll_frameSize=[0, 1, 0, self.resizeSize], # resize the scrollbar according to window size verticalScroll_resizeThumb=False, horizontalScroll_resizeThumb=False, # define the textures for the scrollbars verticalScroll_frameTexture=VERTICALSCROLL_FRAMETEXTURE, verticalScroll_incButton_frameTexture= VERTICALSCROLL_INCBUTTON_FRAMETEXTURE, verticalScroll_decButton_frameTexture= VERTICALSCROLL_DECBUTTON_FRAMETEXTURE, verticalScroll_thumb_frameTexture=VERTICALSCROLL_TUMB_FRAMETEXTURE, horizontalScroll_frameTexture=HORIZONTALSCROLL_FRAMETEXTURE, horizontalScroll_incButton_frameTexture= HORIZONTALSCROLL_INCBUTTON_FRAMETEXTURE, horizontalScroll_decButton_frameTexture= HORIZONTALSCROLL_DECBUTTON_FRAMETEXTURE, horizontalScroll_thumb_frameTexture= HORIZONTALSCROLL_TUMB_FRAMETEXTURE, # make all flat, so the texture is as we want it verticalScroll_relief=DGG.FLAT, verticalScroll_thumb_relief=DGG.FLAT, verticalScroll_decButton_relief=DGG.FLAT, verticalScroll_incButton_relief=DGG.FLAT, horizontalScroll_relief=DGG.FLAT, horizontalScroll_thumb_relief=DGG.FLAT, horizontalScroll_decButton_relief=DGG.FLAT, horizontalScroll_incButton_relief=DGG.FLAT, # colors verticalScroll_frameColor=borderColor, verticalScroll_incButton_frameColor=borderColor, verticalScroll_decButton_frameColor=borderColor, verticalScroll_thumb_frameColor=borderColor, horizontalScroll_frameColor=borderColor, horizontalScroll_incButton_frameColor=borderColor, horizontalScroll_decButton_frameColor=borderColor, horizontalScroll_thumb_frameColor=borderColor, ) self.contentWindow.setTransparency(True) # background color self.backgroundColor = DirectFrame( parent=self.contentWindow.getCanvas(), frameSize=(0, self.maxVirtualSize[0], 0, self.maxVirtualSize[1]), frameColor=backgroundColor, relief=DGG.FLAT, borderWidth=(.01, .01), ) self.backgroundColor.setTransparency(True) # Add a box self.box = boxes.VBox(parent=self.getCanvas()) # is needed for some nicer visuals of the resize button (background) self.windowResizeBackground = DirectButton( parent=self, frameSize=(-.5, .5, -.5, .5), borderWidth=(0, 0), scale=(self.resizeSize, 1, self.resizeSize), relief=DGG.FLAT, frameColor=backgroundColor, ) # the resize button of the window self.windowResize = DirectButton( parent=self, frameSize=(-.5, .5, -.5, .5), borderWidth=(0, 0), scale=(self.resizeSize, 1, self.resizeSize), relief=DGG.FLAT, frameTexture=DEFAULT_RESIZE_GEOM, frameColor=borderColor, ) self.windowResize.setTransparency(True) self.windowResize.bind(DGG.B1PRESS, self.startResizeDrag) self.windowResize.bind(DGG.B1RELEASE, self.stopResizeDrag) # offset then clicking on the resize button from the mouse to the resizebutton # position, required to calculate the position / scaling self.offset = None self.taskName = "resizeTask-%s" % str(hash(self)) # do sizing of the window (minimum) #self.resize( Vec3(0,0,0), Vec3(0,0,0) ) # maximum #self.resize( Vec3(100,0,-100), Vec3(0,0,0) ) self.resize(Vec3(curSize[0], 0, -curSize[1]), Vec3(0, 0, 0)) def getCanvas(self): return self.contentWindow.getCanvas() # dragging functions def startWindowDrag(self, param): self.wrtReparentTo(aspect2dMouseNode) self.ignoreAll() self.accept('mouse1-up', self.stopWindowDrag) def stopWindowDrag(self, param=None): # this is called 2 times (bug), so make sure it's not already parented to aspect2d if self.getParent() != self.windowParent: self.wrtReparentTo(self.windowParent) if self.preserve: if self.preserveWhole: if self.getZ() > 1: self.setZ(1) elif self.getZ() < -1 - self.getHeight(): self.setZ(-1 - self.getHeight()) if self.getX() > base.a2dRight - self.getWidth(): self.setX(base.a2dRight - self.getWidth()) elif self.getX() < base.a2dLeft: self.setX(base.a2dLeft) else: if self.getZ() > 1: self.setZ(1) elif self.getZ() < -1 + self.headerHeight: self.setZ(-1 + self.headerHeight) if self.getX() > base.a2dRight - self.headerHeight: self.setX(base.a2dRight - self.headerHeight) elif self.getX( ) < base.a2dLeft + self.headerHeight - self.getWidth(): self.setX(base.a2dLeft + self.headerHeight - self.getWidth()) #else: #Window moved beyond reach. Destroy window? # resize functions def resize(self, mPos, offset): mXPos = max(min(mPos.getX(), self.maxVirtualSize[0]), self.minVirtualSize[0]) mZPos = max(min(mPos.getZ(), -self.minVirtualSize[1]), -self.maxVirtualSize[1] - self.headerHeight) self.windowResize.setPos(mXPos - self.resizeSize / 2., 0, mZPos + self.resizeSize / 2.) self.windowResizeBackground.setPos(mXPos - self.resizeSize / 2., 0, mZPos + self.resizeSize / 2.) self['frameSize'] = (0, mXPos, 0, mZPos) self.windowHeaderLeft.setPos(self.headerHeight / 2., 0, -self.headerHeight / 2.) self.windowHeaderLeft.setScale(self.headerHeight, 1, self.headerHeight) self.windowHeaderCenter.setPos(mXPos / 2., 0, -self.headerHeight / 2.) self.windowHeaderCenter.setScale(mXPos - self.headerHeight * 2., 1, self.headerHeight) self.windowHeaderRight.setPos(mXPos - self.headerHeight / 2., 0, -self.headerHeight / 2.) self.windowHeaderRight.setScale(self.headerHeight, 1, self.headerHeight) self.contentWindow['frameSize'] = (0, mXPos, mZPos + self.headerHeight, 0) self.textNodePath.setPos(mXPos / 2., 0, -self.headerHeight / 3. * 2.) # show and hide that small background for the window sizer if mXPos == self.maxVirtualSize[0] and \ mZPos == -self.maxVirtualSize[1]-self.headerHeight: self.windowResizeBackground.hide() else: self.windowResizeBackground.show() def resizeTask(self, task=None): mPos = aspect2dMouseNode.getPos(self) + self.offset self.resize(mPos, self.offset) return task.cont def startResizeDrag(self, param): self.offset = self.windowResize.getPos(aspect2dMouseNode) taskMgr.remove(self.taskName) taskMgr.add(self.resizeTask, self.taskName) def stopResizeDrag(self, param): taskMgr.remove(self.taskName) # get the window to the front self.wrtReparentTo(self.windowParent) def addHorizontal(self, widgets): """ Accepts a list of directgui objects which are added to a horizontal box, which is then added to the vertical stack. """ hbox = boxes.HBox() for widget in widgets: hbox.pack(widget) self.box.pack(hbox) self.updateMaxSize() def addVertical(self, widgets): """ Accepts a list of directgui objects which are added to a vertical box, which is then added to the vertical stack. May cause funky layout results. """ #vbox = boxes.VBox() for widget in widgets: self.box.pack(widget) self.updateMaxSize() def add(self, widgets): """Shortcut function for addVertical""" self.addVertical(widgets) def updateMaxSize(self): """Updates the max canvas size to include all items packed. Window is resized to show all contents.""" bottomLeft, topRight = self.box.getTightBounds() self.maxVirtualSize = (topRight[0], -bottomLeft[2]) self.contentWindow['canvasSize'] = (0, self.maxVirtualSize[0], -self.maxVirtualSize[1], 0) self.backgroundColor['frameSize'] = (0, self.maxVirtualSize[0], -self.maxVirtualSize[1], 0) #perhaps this should be optional -- automatically resize for new elements self.reset() def reset(self): """Poorly named function that resizes window to fit all contents""" self.resize( Vec3(self.maxVirtualSize[0], 0, -self.maxVirtualSize[1] - self.headerHeight), Vec3(0, 0, 0))
class GloveShopGui: def __init__(self): self.index = 0 self.id = time.time() self.lastGlove = base.localAvatar.style.gloveColor self.timer = ToontownTimer.ToontownTimer() self.timer.reparentTo(aspect2d) self.timer.posInTopRightCorner() self.timer.countdown(GloveNPCGlobals.TIMER_SECONDS, self.__exit, [GloveNPCGlobals.TIMER_END]) self.setupButtons() self.bindButtons() self.__updateIndex(0) def setupButtons(self): gui = loader.loadModel('phase_3/models/gui/tt_m_gui_mat_mainGui') arrowImage = (gui.find('**/tt_t_gui_mat_shuffleArrowUp'), gui.find('**/tt_t_gui_mat_shuffleArrowDown')) buttonImage = (gui.find('**/tt_t_gui_mat_shuffleUp'), gui.find('**/tt_t_gui_mat_shuffleDown')) self.title = DirectLabel(aspect2d, relief=None, text=TTLocalizer.GloveGuiTitle, text_fg=(0, 1, 0, 1), text_scale=0.15, text_font=ToontownGlobals.getSignFont(), pos=(0, 0, -0.30), text_shadow=(1, 1, 1, 1)) self.notice = DirectLabel(aspect2d, relief=None, text='', text_fg=(1, 0, 0, 1), text_scale=0.11, text_font=ToontownGlobals.getSignFont(), pos=(0, 0, -0.45), text_shadow=(1, 1, 1, 1)) self.color = DirectLabel(aspect2d, relief=None, text='', text_scale=0.11, text_font=ToontownGlobals.getSignFont(), pos=(0, 0, -0.70), text_shadow=(1, 1, 1, 1)) self.buyButton = DirectButton( aspect2d, relief=None, image=buttonImage, text=TTLocalizer.GloveGuiBuy, text_font=ToontownGlobals.getInterfaceFont(), text_scale=0.11, text_pos=(0, -0.02), pos=(-0.60, 0, -0.90), text_fg=(1, 1, 1, 1), text_shadow=(0, 0, 0, 1), command=self.__exit, extraArgs=[GloveNPCGlobals.CHANGE]) self.cancelButton = DirectButton( aspect2d, relief=None, image=buttonImage, text=TTLocalizer.lCancel, text_font=ToontownGlobals.getInterfaceFont(), text_scale=0.11, text_pos=(0, -0.02), pos=(0.60, 0, -0.90), text_fg=(1, 1, 1, 1), text_shadow=(0, 0, 0, 1), command=self.__exit, extraArgs=[GloveNPCGlobals.USER_CANCEL]) self.downArrow = DirectButton(aspect2d, relief=None, image=arrowImage, pos=(-0.60, 0, -0.66)) self.upArrow = DirectButton(aspect2d, relief=None, image=arrowImage, pos=(0.60, 0, -0.66), scale=-1) gui.removeNode() def bindButtons(self): self.downArrow.bind(DGG.B1PRESS, self.__taskUpdate, extraArgs=[-1]) self.downArrow.bind(DGG.B1RELEASE, self.__taskDone) self.upArrow.bind(DGG.B1PRESS, self.__taskUpdate, extraArgs=[1]) self.upArrow.bind(DGG.B1RELEASE, self.__taskDone) def destroy(self): if self.timer: self.timer.destroy() if not hasattr(self, 'title'): return # TODO: DirectDialog-ify self.title.destroy() self.notice.destroy() self.color.destroy() self.buyButton.destroy() self.cancelButton.destroy() self.downArrow.destroy() self.upArrow.destroy() del self.title del self.notice del self.color del self.buyButton del self.cancelButton del self.downArrow del self.upArrow taskMgr.remove('runGloveCounter-%s' % self.id) def setClientGlove(self, color): dna = base.localAvatar.style dna.gloveColor = color base.localAvatar.setDNA(dna) def __exit(self, state): self.destroy() self.setClientGlove(self.lastGlove) messenger.send( 'gloveShopDone', [state, self.index if state == GloveNPCGlobals.CHANGE else 0]) def __updateIndex(self, offset): self.index += offset hitLimit = 0 if self.index <= 0: self.downArrow['state'] = DGG.DISABLED hitLimit = 1 else: self.downArrow['state'] = DGG.NORMAL if (self.index + 1) >= len(TTLocalizer.NumToColor): self.upArrow['state'] = DGG.DISABLED hitLimit = 1 else: self.upArrow['state'] = DGG.NORMAL if self.lastGlove == self.index: self.buyButton['state'] = DGG.DISABLED self.notice['text'] = TTLocalizer.GloveGuiSameColor else: self.buyButton['state'] = DGG.NORMAL self.notice[ 'text'] = TTLocalizer.GloveGuiNotice % ToontownGlobals.GloveCost self.color['text'] = TTLocalizer.NumToColor[self.index] self.color['text_fg'] = ToonDNA.allColorsList[self.index] self.setClientGlove(self.index) return hitLimit def __runTask(self, task): if task.time - task.prevTime < task.delayTime: return Task.cont else: task.delayTime = max(0.05, task.delayTime * 0.75) task.prevTime = task.time hitLimit = self.__updateIndex(task.delta) return Task.done if hitLimit else Task.cont def __taskDone(self, event): messenger.send('wakeup') taskMgr.remove('runGloveCounter-%s' % self.id) def __taskUpdate(self, delta, event): messenger.send('wakeup') task = Task(self.__runTask) task.delayTime = 0.4 task.prevTime = 0.0 task.delta = delta hitLimit = self.__updateIndex(delta) if not hitLimit: taskMgr.add(task, 'runGloveCounter-%s' % self.id)
def __init__(self): self._coh_desc_wids = [] self._coh_desc_shown = False self._res_desc_wids = [] self._res_desc_shown = False self._resources = {} self._blink_step = 0 self._reload_ico = None self._reload_min = None self._err_snd = loader.loadSfx("sounds/GUI/error.ogg") # noqa: F821 self._res_frame = DirectFrame( parent=base.a2dTopLeft, # noqa: F821 frameSize=(-0.37, 0.37, -0.03, 0.028), pos=(0.37, 0, -0.028), frameTexture=GUI_PIC + "metal1.png", ) self._res_frame.setTransparency(TransparencyAttrib.MAlpha) DirectFrame( parent=self._res_frame, # noqa: F821 frameSize=(-0.023, 0.023, -0.023, 0.023), pos=(-0.34, 0, 0), frameTexture=GUI_PIC + "dollar.png", ) self._resources["dollars"] = DirectLabel( parent=self._res_frame, text="", frameSize=(0.1, 0.1, 0.1, 0.1), text_scale=0.035, text_fg=RUST_COL, pos=(-0.27, 0, -0.008), ) DirectFrame( parent=self._res_frame, # noqa: F821 frameSize=(-0.018, 0.018, -0.018, 0.018), pos=(-0.18, 0, 0), frameTexture=GUI_PIC + "chars.png", ) self._resources["chars"] = DirectLabel( parent=self._res_frame, text="{}/{}".format(len(base.team.chars), base.train.cells), # noqa: F821 frameSize=(0.1, 0.1, 0.1, 0.1), text_scale=0.035, text_fg=RUST_COL, pos=(-0.12, 0, -0.008), ) but = DirectButton( parent=self._res_frame, frameSize=(-0.023, 0.023, -0.023, 0.023), relief="flat", pos=(-0.06, 0, 0), frameTexture=GUI_PIC + "medicine.png", command=base.team.use_medicine, # noqa: F821 ) but.bind(DGG.ENTER, self._highlight_res_but, extraArgs=[but, "medicine_boxes"]) but.bind(DGG.EXIT, self._dehighlight_but, extraArgs=[but]) self._resources["medicine_boxes"] = DirectLabel( parent=self._res_frame, text="0", frameSize=(0.1, 0.1, 0.1, 0.1), text_scale=0.035, text_fg=RUST_COL, pos=(-0.02, 0, -0.008), ) but = DirectButton( parent=self._res_frame, frameSize=(-0.023, 0.023, -0.023, 0.023), relief="flat", pos=(0.035, 0, 0), frameTexture=GUI_PIC + "smoke_filter.png", command=base.train.use_smoke_filter, # noqa: F821 ) but.bind(DGG.ENTER, self._highlight_res_but, extraArgs=[but, "smoke_filters"]) but.bind(DGG.EXIT, self._dehighlight_but, extraArgs=[but]) self._resources["smoke_filters"] = DirectLabel( parent=self._res_frame, text="0", frameSize=(0.1, 0.1, 0.1, 0.1), text_scale=0.035, text_fg=RUST_COL, pos=(0.075, 0, -0.008), ) but = DirectButton( parent=self._res_frame, frameSize=(-0.014, 0.014, -0.021, 0.021), relief="flat", pos=(0.12, 0, 0), frameTexture=GUI_PIC + "stimulator.png", command=base.team.use_stimulator, # noqa: F821 ) but.bind(DGG.ENTER, self._highlight_res_but, extraArgs=[but, "stimulators"]) but.bind(DGG.EXIT, self._dehighlight_but, extraArgs=[but]) self._resources["stimulators"] = DirectLabel( parent=self._res_frame, text="0", frameSize=(0.1, 0.1, 0.1, 0.1), text_scale=0.035, text_fg=RUST_COL, pos=(0.16, 0, -0.008), ) DirectButton( parent=self._res_frame, frameSize=(-0.014, 0.014, -0.021, 0.021), relief="flat", pos=(0.2, 0, 0), frameTexture=GUI_PIC + "places_of_interest.png", ) self._resources["places_of_interest"] = DirectLabel( parent=self._res_frame, text="0/10", frameSize=(0.1, 0.1, 0.1, 0.1), text_scale=0.035, text_fg=RUST_COL, pos=(0.27, 0, -0.008), ) DirectButton( parent=self._res_frame, pos=(0.34, 0, -0.013), command=self._show_expendable_resources, clickSound=base.main_menu.click_snd, # noqa: F821 **ABOUT_BUT_PARAMS, ).setTransparency(TransparencyAttrib.MAlpha) self._coh_frame = DirectFrame( parent=base.a2dBottomRight, # noqa: F821 frameSize=(-0.55, 0.55, -0.05, 0.05), pos=(-0.6, 0, 1.95), frameTexture=GUI_PIC + "metal1.png", state=DGG.NORMAL, ) self._coh_frame.setTransparency(TransparencyAttrib.MAlpha) self._cohesion = DirectWaitBar( parent=self._coh_frame, frameSize=(-0.45, 0.45, -0.002, 0.002), frameColor=(0.35, 0.35, 0.35, 1), value=0, barColor=SILVER_COL, pos=(0, 0, 0.02), ) recall_ico = DirectButton( parent=self._coh_frame, frameSize=(-0.023, 0.023, -0.023, 0.023), frameTexture=GUI_PIC + "ny_recall.png", pos=(-0.27, 0, -0.02), relief="flat", command=base.team.cohesion_recall, # noqa: F821 ) recall_ico.setTransparency(TransparencyAttrib.MAlpha) recall_ico.bind(DGG.ENTER, self._highlight_coh_but, extraArgs=[recall_ico]) recall_ico.bind(DGG.EXIT, self._dehighlight_but, extraArgs=[recall_ico]) cover_ico = DirectButton( parent=self._coh_frame, frameSize=(-0.035, 0.035, -0.035, 0.035), frameTexture=GUI_PIC + "ny_cover.png", pos=(-0.09, 0, -0.01), relief="flat", command=base.team.cohesion_cover_fire, # noqa: F821 ) cover_ico.setTransparency(TransparencyAttrib.MAlpha) cover_ico.bind(DGG.ENTER, self._highlight_coh_but, extraArgs=[cover_ico]) cover_ico.bind(DGG.EXIT, self._dehighlight_but, extraArgs=[cover_ico]) heal_ico = DirectButton( parent=self._coh_frame, frameSize=(-0.023, 0.023, -0.023, 0.023), frameTexture=GUI_PIC + "ny_heal.png", pos=(0.09, 0, -0.015), relief="flat", command=base.team.cohesion_heal_wounded, # noqa: F821 ) heal_ico.setTransparency(TransparencyAttrib.MAlpha) heal_ico.bind(DGG.ENTER, self._highlight_coh_but, extraArgs=[heal_ico]) heal_ico.bind(DGG.EXIT, self._dehighlight_but, extraArgs=[heal_ico]) rage_ico = DirectButton( parent=self._coh_frame, frameSize=(-0.035, 0.035, -0.035, 0.035), frameTexture=GUI_PIC + "ny_rage.png", pos=(0.27, 0, -0.015), relief="flat", command=base.team.cohesion_rage, # noqa: F821 ) rage_ico.setTransparency(TransparencyAttrib.MAlpha) rage_ico.bind(DGG.ENTER, self._highlight_coh_but, extraArgs=[rage_ico]) rage_ico.bind(DGG.EXIT, self._dehighlight_but, extraArgs=[rage_ico]) heart_ico = DirectButton( parent=self._coh_frame, frameSize=(-0.035, 0.035, -0.035, 0.035), frameTexture=GUI_PIC + "ny_heart.png", pos=(0.445, 0, -0.015), relief="flat", command=base.team.cohesion_hold_together, # noqa: F821 ) heart_ico.setTransparency(TransparencyAttrib.MAlpha) heart_ico.bind(DGG.ENTER, self._highlight_coh_but, extraArgs=[heart_ico]) heart_ico.bind(DGG.EXIT, self._dehighlight_but, extraArgs=[heart_ico]) self._coh_icons = ( {"wid": recall_ico, "file": "recall.png", "value": 20}, {"wid": cover_ico, "file": "cover.png", "value": 40}, {"wid": heal_ico, "file": "heal.png", "value": 60}, {"wid": rage_ico, "file": "rage.png", "value": 80}, {"wid": heart_ico, "file": "heart.png", "value": 100}, ) DirectButton( parent=self._coh_frame, pos=(-0.5, 0, -0.028), command=self._show_cohesion_abilities, clickSound=base.main_menu.click_snd, # noqa: F821 **ABOUT_BUT_PARAMS, ).setTransparency(TransparencyAttrib.MAlpha)
def render(self): ''' traverse the tree and update the visuals according to it ''' for treeItem in self.treeStructure.getRec(): # create nodes that have no visual elements if not treeItem in self.treeStructureNodes: treeNode = self.childrenCanvas.attachNewNode('') hor = self.horizontalTreeLine.instanceUnderNode(treeNode, '') vert = self.verticalTreeLine.instanceUnderNode(treeNode, '') vert.setZ(0.007) hor.setPos(-1.5 * self.itemIndent, 0, self.itemScale * .25) vert.setX(-.5 * self.itemIndent) nodeButton = DirectButton( parent=treeNode, scale=self.itemScale, relief=DGG.FLAT, text_scale=self.itemTextScale, text_align=TextNode.ALeft, text=treeItem.name, rolloverSound=None, #clickSound=None, ) nodeButton.bind(DGG.B1PRESS, treeItem.button1press) nodeButton.bind(DGG.B2PRESS, treeItem.button2press) nodeButton.bind(DGG.B3PRESS, treeItem.button3press) #treeButton = None #if len(treeItem.childrens) > 0: treeButton = DirectButton( parent=nodeButton, frameColor=(1, 1, 1, 1), frameSize=(-.4, .4, -.4, .4), pos=(-.5 * self.itemIndent / self.itemScale, 0, .25), text='', text_pos=(-.1, -.22), text_scale=(1.6, 1), text_fg=(0, 0, 0, 1), enableEdit=0, command=treeItem.setOpen, sortOrder=1000, rolloverSound=None, #clickSound=None, ) self.treeStructureNodes[treeItem] = [ treeNode, nodeButton, treeButton, hor, vert ] # destroy nodes no more used for treeItem in self.treeStructureNodes.keys()[:]: #treeItem = self.treeStructureNodes[treeName] if treeItem not in self.treeStructure.getRec(): treeNode, nodeButton, treeButton, hor, vert = self.treeStructureNodes[ treeItem] #nodeButton['text']='' nodeButton.unbind(DGG.B1PRESS) nodeButton.unbind(DGG.B2PRESS) nodeButton.unbind(DGG.B3PRESS) #nodeButton.detachNode() #nodeButton.removeNode() nodeButton.destroy() if treeButton: #treeButton['text']='' #treeButton['command']=None treeButton.detachNode() treeButton.removeNode() hor.detachNode() hor.removeNode() vert.detachNode() vert.removeNode() treeItem.destroy() #treeNode.detachNode() treeNode.removeNode() #treeNode.destroy() del self.treeStructureNodes[treeItem] frameHeight = len(self.treeStructureNodes) * self.verticalSpacing self.childrenFrame['canvasSize'] = (0, self.frameWidth - self.itemScale * 2, 0, frameHeight) self.childrenCanvas.setZ(frameHeight - 1)
def addItem(self,text,extraArgs=None,atIndex=None,textColorName=None): """ add item to the list text : text for the button extraArgs : the object which will be passed to user command(s) (both command and contextMenu) when the button get clicked atIndex : where to add the item <None> : put item at the end of list <integer> : put item at index <integer> <button> : put item at <button>'s index textColorName : the color name eg. 'yellow' """ textColor = self.buttonTextColor if textColorName != None: textColor = globals.colors[textColorName] button = DirectButton(parent=self.canvas, scale=self.itemScale, relief=DGG.FLAT, frameColor=(0,0,0,0),text_scale=self.itemTextScale, text=text, text_pos=(0,self.itemTextZ),text_fg=textColor, text_font=self.font, text_align=TextNode.ALeft, command=self.__setFocusButton, enableEdit=0, suppressMouse=0, rolloverSound=None,clickSound=None) #button.setMyMode(self.mode) l,r,b,t=button.getBounds() # top & bottom are blindly set without knowing where exactly the baseline is, # but this ratio fits most fonts baseline=-self.fontHeight*.25 #button['saved_color'] = textColor button['frameSize']=(l-self.xtraSideSpace,r+self.xtraSideSpace,baseline,baseline+self.fontHeight) # Zc=NodePath(button).getBounds().getCenter()[1]-self.fontHeight*.5+.25 # # Zc=button.getCenter()[1]-self.fontHeight*.5+.25 # button['frameSize']=(l-self.xtraSideSpace,r+self.xtraSideSpace,Zc,Zc+self.fontHeight) button['extraArgs']=[button,extraArgs] button._DirectGuiBase__componentInfo['text2'][0].setColorScale(self.rolloverColor) button.bind(DGG.B3PRESS,self.__rightPressed,[button]) if isinstance(atIndex,DirectButton): if atIndex.isEmpty(): atIndex=None else: index=self.buttonsList.index(atIndex) self.buttonsList.insert(index,button) if atIndex==None: self.buttonsList.append(button) index=self.numItems elif type(atIndex)==IntType: index=atIndex self.buttonsList.insert(index,button) Zpos=(-.7-index)*self.itemVertSpacing button.setPos(.02,0,Zpos) if index!=self.numItems: for i in range(index+1,self.numItems+1): self.buttonsList[i].setZ(self.buttonsList[i],-self.fontHeight) self.numItems+=1 self.__adjustCanvasLength(self.numItems) if self.autoFocus: self.focusViewOnItem(index) if self.colorChange: Sequence( button.colorScaleInterval(self.colorChangeDuration,self.newItemColor,globals.colors['guiblue3']), button.colorScaleInterval(self.colorChangeDuration,Vec4(1,1,1,1),self.newItemColor) ).start()
class OptionPage(StateData): def __init__(self, book, parentFSM): self.book = book self.parentFSM = parentFSM StateData.__init__(self, 'optionPageDone') self.fsm = ClassicFSM('OptionPage', [ State('off', self.enterOff, self.exitOff), State('basePage', self.enterBasePage, self.exitBasePage), State('displayPage', self.enterDisplayPage, self.exitDisplayPage) ], 'off', 'off') self.fsm.enterInitialState() self.parentFSM.getStateNamed('optionPage').addChild(self.fsm) def enterOff(self): pass def exitOff(self): pass def load(self): StateData.load(self) def unload(self): StateData.unload(self) def enter(self): StateData.enter(self) self.fsm.request('basePage') def exit(self): self.fsm.request('off') StateData.exit(self) def openDisplayPage(self): self.fsm.request('displayPage') def enterDisplayPage(self): self.book.createPageButtons(False, False) self.book.setTitle('Display Options') dialog_gui = loader.loadModel( 'phase_3/models/gui/dialog_box_buttons_gui.bam') width, height, fs, music, sfx, tex_detail, model_detail, aa, af = SettingsManager( ).getSettings('settings.json') self.width = width self.height = height self.windowType = [fs] self.buttons = [ DirectRadioButton(text='Windowed', variable=self.windowType, value=[False], scale=0.1, pos=(-0.45, 0.15, 0.15)), DirectRadioButton(text='Fullscreen', variable=self.windowType, value=[True], scale=0.1, pos=(-0.45, -0.15, -0.15)) ] for button in self.buttons: button.setOthers(self.buttons) self.resoLbl = DirectLabel(text='%sx%s' % (width, height), scale=0.08, relief=None, pos=(0.25, 0, 0)) self.resSlider = DirectSlider(range=(0, 200), pageSize=50, command=self.setResoText, scale=0.3, orientation=DGG.VERTICAL, pos=(0.6, 0, 0)) self.okBtn = DirectButton(text='OK', geom=CIGlobals.getOkayBtnGeom(), relief=None, pos=(-0.5, -0.5, -0.5), text_scale=0.05, text_pos=(0, -0.11), command=self.applyDisplaySettings) self.cancelBtn = DirectButton(text='Cancel', geom=CIGlobals.getCancelBtnGeom(), relief=None, pos=(-0.3, -0.5, -0.5), text_scale=0.05, text_pos=(0, -0.11), command=self.cancelDisplaySettings) if self.resoLbl['text'] == '640x480': self.resSlider['value'] = 0 else: if self.resoLbl['text'] == '800x600': self.resSlider['value'] = 50 else: if self.resoLbl['text'] == '1024x768': self.resSlider['value'] = 100 else: if self.resoLbl['text'] == '1280x1024': self.resSlider['value'] = 150 else: if self.resoLbl['text'] == '1600x1200': self.resSlider['value'] = 200 return def exitDisplayPage(self): for button in self.buttons: button.destroy() del button self.resoLbl.destroy() del self.resoLbl self.resSlider.destroy() del self.resSlider self.okBtn.destroy() del self.okBtn self.cancelBtn.destroy() del self.cancelBtn del self.width del self.height del self.windowType del self.buttons self.book.clearTitle() def changeSetting(self, setting, value): if setting == 'music': if value: value = False else: if not value: value = True base.enableMusic(value) self.music_btn['extraArgs'] = ['music', value] if value: valueTxt = 'On' else: valueTxt = 'Off' self.music_lbl['text'] = str(valueTxt).capitalize() else: if setting == 'sfx': if value: value = False else: if not value: value = True base.enableSoundEffects(value) self.sfx_btn['extraArgs'] = ['sfx', value] if value: valueTxt = 'On' else: valueTxt = 'Off' self.sfx_lbl['text'] = str(valueTxt).capitalize() else: if setting == 'model-detail': if value == 'high': value = 'low' else: if value == 'medium': value = 'high' else: if value == 'low': value = 'medium' self.moddet_lbl['text'] = value.capitalize() self.moddet_btn['extraArgs'] = ['model-detail', value] else: if setting == 'texture-detail': if value == 'normal': value = 'low' loadPrcFileData('', 'compressed-textures 1') else: if value == 'low': value = 'normal' loadPrcFileData('', 'compressed-textures 0') self.texdet_lbl['text'] = value.capitalize() self.texdet_btn['extraArgs'] = [ 'texture-detail', value ] else: if setting == 'aa': if value == 'on': value = 'off' render.clear_antialias() else: if value == 'off': value = 'on' render.set_antialias(AntialiasAttrib.MAuto) self.aa_lbl['text'] = value.capitalize() self.aa_btn['extraArgs'] = ['aa', value] else: if setting == 'af': if value == 'on': value = 'off' else: if value == 'off': value = 'on' self.af_lbl['text'] = value.capitalize() self.af_btn['extraArgs'] = ['af', value] SettingsManager().writeSettingToFile(setting, value, 'settings.json') def setResoText(self): if self.resSlider['value'] == 200: self.width = 1600 self.height = 1200 else: if 150 <= self.resSlider['value'] <= 199: self.width = 1280 self.height = 1024 else: if 100 <= self.resSlider['value'] <= 149: self.width = 1024 self.height = 768 else: if 50 <= self.resSlider['value'] <= 99: self.width = 800 self.height = 600 else: if self.resSlider['value'] == 0: self.width = 640 self.height = 480 self.resoLbl['text'] = str(self.width) + 'x' + str(self.height) def applyDisplaySettings(self): SettingsManager().writeSettingToFile('resolution', (self.width, self.height), 'settings.json', apply=1) SettingsManager().writeSettingToFile('fullscreen', self.windowType, 'settings.json', apply=1) self.fsm.request('basePage') def cancelDisplaySettings(self): self.fsm.request('basePage') def enterBasePage(self): self.book.createPageButtons(None, 'districtPage') self.book.setTitle('Options') width, height, fs, music, sfx, tex_detail, model_detail, aa, af = SettingsManager( ).getSettings('settings.json') if music: musicTxt = 'On' else: musicTxt = 'Off' if sfx: sfxTxt = 'On' else: sfxTxt = 'Off' if fs: fsTxt = 'On' else: fsTxt = 'Off' self.music_btn = DirectButton(geom=(qt_btn.find('**/QuitBtn_UP'), qt_btn.find('**/QuitBtn_DN'), qt_btn.find('**/QuitBtn_RLVR')), relief=None, text='Music', scale=1, text_scale=0.055, command=self.changeSetting, extraArgs=['music', music], pos=(-0.45, 0.55, 0.55), text_pos=(0, -0.01)) self.music_lbl = DirectLabel(relief=None, scale=0.09, pos=(0.45, 0.55, 0.52), text_align=TextNode.ACenter) self.music_lbl['text'] = str(musicTxt).capitalize() self.sfx_btn = DirectButton(geom=(qt_btn.find('**/QuitBtn_UP'), qt_btn.find('**/QuitBtn_DN'), qt_btn.find('**/QuitBtn_RLVR')), relief=None, text='SFX', scale=1, text_scale=0.055, command=self.changeSetting, extraArgs=['sfx', sfx], pos=(-0.45, 0.45, 0.45), text_pos=(0, -0.01)) self.sfx_lbl = DirectLabel(relief=None, scale=0.09, pos=(0.45, 0.45, 0.42), text_align=TextNode.ACenter) self.sfx_lbl['text'] = str(sfxTxt).capitalize() self.moddet_btn = DirectButton( geom=(qt_btn.find('**/QuitBtn_UP'), qt_btn.find('**/QuitBtn_DN'), qt_btn.find('**/QuitBtn_RLVR')), relief=None, text='Model Detail', scale=1, text_scale=0.055, command=self.changeSetting, extraArgs=['model-detail', model_detail], pos=(-0.45, 0.35, 0.35), text_pos=(0, -0.01)) self.moddet_lbl = DirectLabel(relief=None, scale=0.09, pos=(0.45, 0.35, 0.32), text_align=TextNode.ACenter) self.moddet_lbl['text'] = model_detail.capitalize() self.moddet_btn.bind(DGG.ENTER, self.createMustRestartGui) self.moddet_btn.bind(DGG.EXIT, self.removeMustRestartGui) self.texdet_btn = DirectButton( geom=(qt_btn.find('**/QuitBtn_UP'), qt_btn.find('**/QuitBtn_DN'), qt_btn.find('**/QuitBtn_RLVR')), relief=None, text='Texture Detail', scale=1, text_scale=0.0535, command=self.changeSetting, extraArgs=['texture-detail', tex_detail], pos=(-0.45, 0.25, 0.25), text_pos=(0, -0.01)) self.texdet_lbl = DirectLabel(relief=None, scale=0.09, pos=(0.45, 0.25, 0.22), text_align=TextNode.ACenter) self.texdet_lbl['text'] = tex_detail.capitalize() self.texdet_btn.bind(DGG.ENTER, self.createMustRestartGui) self.texdet_btn.bind(DGG.EXIT, self.removeMustRestartGui) self.display_btn = DirectButton(geom=(qt_btn.find('**/QuitBtn_UP'), qt_btn.find('**/QuitBtn_DN'), qt_btn.find('**/QuitBtn_RLVR')), relief=None, text='Display', command=self.openDisplayPage, scale=1, text_scale=0.0535, pos=(-0.45, -0.25, 0.02), text_pos=(0, -0.01)) self.display_lbl = DirectLabel(relief=None, scale=0.06, pos=(0.45, -0.25, 0.02), text_align=TextNode.ACenter) self.display_lbl['text'] = 'Fullscreen: %s\nResolution: %s' % ( str(fsTxt).capitalize(), (width, height)) self.aa_btn = DirectButton(geom=(qt_btn.find('**/QuitBtn_UP'), qt_btn.find('**/QuitBtn_DN'), qt_btn.find('**/QuitBtn_RLVR')), relief=None, text='Anti-Aliasing', command=self.changeSetting, extraArgs=['aa', aa], scale=1, text_scale=0.0535, pos=(-0.45, -0.35, -0.18), text_pos=(0, -0.01)) self.aa_lbl = DirectLabel(relief=None, scale=0.09, pos=(0.45, -0.35, -0.21), text_align=TextNode.ACenter) self.aa_lbl['text'] = aa.capitalize() self.af_btn = DirectButton(geom=(qt_btn.find('**/QuitBtn_UP'), qt_btn.find('**/QuitBtn_DN'), qt_btn.find('**/QuitBtn_RLVR')), relief=None, text='Anisotropic Filtering', command=self.changeSetting, extraArgs=['af', af], scale=1, text_scale=0.0435, pos=(-0.45, -0.35, -0.28), text_pos=(0, -0.01)) self.af_lbl = DirectLabel(relief=None, scale=0.09, pos=(0.45, -0.35, -0.31), text_align=TextNode.ACenter) self.af_lbl['text'] = af.capitalize() self.af_btn.bind(DGG.ENTER, self.createMustRestartGui) self.af_btn.bind(DGG.EXIT, self.removeMustRestartGui) self.exit_btn = DirectButton(geom=(qt_btn.find('**/QuitBtn_UP'), qt_btn.find('**/QuitBtn_DN'), qt_btn.find('**/QuitBtn_RLVR')), relief=None, text='Exit Toontown', scale=1.2, text_scale=0.0535, command=self.book.finished, extraArgs=['exit'], pos=(-0.45, -0.65, -0.6), text_pos=(0, -0.01)) return def createMustRestartGui(self, foo): self.mustRestartLbl = DirectLabel( text='Changing this setting requires a game restart.', text_fg=(0.9, 0, 0, 1), text_shadow=(0, 0, 0, 1), text_scale=0.06, text_align=TextNode.ACenter, pos=(0, 0, -0.435), relief=None) return def removeMustRestartGui(self, foo): if hasattr(self, 'mustRestartLbl'): self.mustRestartLbl.destroy() del self.mustRestartLbl def exitBasePage(self): self.music_btn.destroy() del self.music_btn self.sfx_btn.destroy() del self.sfx_btn self.moddet_btn.destroy() del self.moddet_btn self.texdet_btn.destroy() del self.texdet_btn self.display_btn.destroy() del self.display_btn self.aa_btn.destroy() del self.aa_btn self.exit_btn.destroy() del self.exit_btn self.music_lbl.destroy() del self.music_lbl self.sfx_lbl.destroy() del self.sfx_lbl self.moddet_lbl.destroy() del self.moddet_lbl self.texdet_lbl.destroy() del self.texdet_lbl self.display_lbl.destroy() del self.display_lbl self.aa_lbl.destroy() del self.aa_lbl self.af_btn.destroy() del self.af_btn self.af_lbl.destroy() del self.af_lbl self.book.deletePageButtons(False, True) self.book.clearTitle()
def render(self): ''' traverse the tree and update the visuals according to it ''' for treeItem in self.treeStructure.getRec(): # create nodes that have no visual elements if not treeItem in self.treeStructureNodes: treeNode = self.childrenCanvas.attachNewNode('') hor=self.horizontalTreeLine.instanceUnderNode(treeNode,'') vert=self.verticalTreeLine.instanceUnderNode(treeNode,'') vert.setZ(0.007) hor.setPos(-1.5*self.itemIndent,0,self.itemScale*.25) vert.setX(-.5*self.itemIndent) nodeButton = DirectButton( parent=treeNode, scale=self.itemScale, relief=DGG.FLAT, text_scale=self.itemTextScale, text_align=TextNode.ALeft, text=treeItem.name, rolloverSound=None, #clickSound=None, ) nodeButton.bind(DGG.B1PRESS,treeItem.button1press) nodeButton.bind(DGG.B2PRESS,treeItem.button2press) nodeButton.bind(DGG.B3PRESS,treeItem.button3press) #treeButton = None #if len(treeItem.childrens) > 0: treeButton = DirectButton( parent=nodeButton, frameColor=(1,1,1,1), frameSize=(-.4,.4,-.4,.4), pos=(-.5*self.itemIndent/self.itemScale,0,.25), text='', text_pos=(-.1,-.22), text_scale=(1.6,1), text_fg=(0,0,0,1), enableEdit=0, command=treeItem.setOpen, sortOrder=1000, rolloverSound=None, #clickSound=None, ) self.treeStructureNodes[treeItem] = [treeNode, nodeButton, treeButton, hor, vert] # destroy nodes no more used for treeItem in self.treeStructureNodes.keys()[:]: #treeItem = self.treeStructureNodes[treeName] if treeItem not in self.treeStructure.getRec(): treeNode, nodeButton, treeButton, hor, vert = self.treeStructureNodes[treeItem] #nodeButton['text']='' nodeButton.unbind(DGG.B1PRESS) nodeButton.unbind(DGG.B2PRESS) nodeButton.unbind(DGG.B3PRESS) #nodeButton.detachNode() #nodeButton.removeNode() nodeButton.destroy() if treeButton: #treeButton['text']='' #treeButton['command']=None treeButton.detachNode() treeButton.removeNode() hor.detachNode() hor.removeNode() vert.detachNode() vert.removeNode() treeItem.destroy() #treeNode.detachNode() treeNode.removeNode() #treeNode.destroy() del self.treeStructureNodes[treeItem] frameHeight = len(self.treeStructureNodes) * self.verticalSpacing self.childrenFrame['canvasSize'] = (0, self.frameWidth-self.itemScale*2, 0, frameHeight) self.childrenCanvas.setZ(frameHeight-1)
class ModPanelButton: def __init__(self, menu, name, command, register): self.menu = menu self.name = name self.command = command if type(command) == types.StringType: command = self.call_word self.button = DirectButton( frameSize=None, text=name, image=(ModPanelGlobals.Button.find('**/QuitBtn_UP'), ModPanelGlobals.Button.find('**/QuitBtn_DN'), ModPanelGlobals.Button.find('**/QuitBtn_RLVR')), relief=None, command=command, text_pos=(0, -0.015), geom=None, pad=(0.01, 0.01), suppressKeys=0, pos=(0, 0, 0), text_scale=0.059, borderWidth=(0.015, 0.01), scale=.7) self.button.reparent_to(menu) if register: self.button.bind(DirectGuiGlobals.B2PRESS, self.delete_button) self.button.bind(DirectGuiGlobals.B3PRESS, self.button.editStart) self.button.bind(DirectGuiGlobals.B3RELEASE, self.edit_stop) self.menu.buttons.append(self) messenger.send('save-file') def call_word(self): messenger.send('magicWord', [self.command]) def hide(self): self.button.hide() def show(self): self.button.show() def place(self): self.button.place() def set_pos(self, x, y, z): self.button.set_pos(x, y, z) def destroy(self): self.button.destroy() def edit_stop(self, dispatch): self.button.editStop(dispatch) messenger.send('save-file') def delete_button(self, dispatch): self.button.destroy() if self in self.menu.buttons: self.menu.buttons.remove(self) messenger.send('save-file') def get_data(self): return self.name, self.command, self.button.get_pos()
class DirectWindow( DirectFrame ): def __init__( self, pos = ( -.5, .5), title = 'Title', curSize = ( 1, 1), maxSize = ( 1, 1 ), minSize = ( .5, .5 ), backgroundColor = ( 1, 1, 1, 1 ), borderColor = ( 1, 1, 1, 1 ), titleColor = ( 1, 1, 1, 1 ), borderSize = 0.04, titleSize = 0.06, closeButton = False, windowParent = aspect2d, preserve = True, preserveWhole = True, ): self.preserve = preserve self.preserveWhole = preserveWhole self.windowParent = windowParent self.windowPos = pos DirectFrame.__init__( self, parent = windowParent, pos = ( self.windowPos[0], 0, self.windowPos[1] ), frameColor = ( 0, 0, 0, 0 ), frameTexture = loader.loadTexture( DIRECTORY+'transparent.png' ) ) self.setTransparency(True) # the title part of the window, drag around to move the window self.headerHeight = titleSize h = -self.headerHeight self.windowHeaderLeft = DirectButton( parent = self, frameTexture = DEFAULT_TITLE_GEOM_LEFT, frameSize = ( -.5, .5, -.5, .5 ), borderWidth = ( 0, 0 ), relief = DGG.FLAT, frameColor = titleColor, ) self.windowHeaderCenter = DirectButton( parent = self, frameTexture = DEFAULT_TITLE_GEOM_CENTER, frameSize = ( -.5, .5, -.5, .5 ), borderWidth = ( 0, 0 ), relief = DGG.FLAT, frameColor = titleColor, ) if closeButton: rightTitleGeom = DEFAULT_TITLE_GEOM_RIGHT_CLOSE command = self.destroy else: rightTitleGeom = DEFAULT_TITLE_GEOM_RIGHT command = None self.windowHeaderRight = DirectButton( parent = self, frameTexture = rightTitleGeom, frameSize = ( -.5, .5, -.5, .5 ), borderWidth = ( 0, 0 ), relief = DGG.FLAT, frameColor = titleColor, command = command ) self.windowHeaderLeft.setTransparency(True) self.windowHeaderCenter.setTransparency(True) self.windowHeaderRight.setTransparency(True) self.windowHeaderLeft.bind( DGG.B1PRESS, self.startWindowDrag ) self.windowHeaderCenter.bind( DGG.B1PRESS, self.startWindowDrag ) self.windowHeaderRight.bind( DGG.B1PRESS, self.startWindowDrag ) # this is not handled correctly, if a window is dragged which has been # created before another it will not be released # check the bugfixed startWindowDrag function #self.windowHeader.bind(DGG.B1RELEASE,self.stopWindowDrag) text = TextNode('WindowTitleTextNode') text.setText(title) text.setAlign(TextNode.ACenter) text.setTextColor( 0, 0, 0, 1 ) text.setShadow(0.05, 0.05) text.setShadowColor( 1, 1, 1, 1 ) self.textNodePath = self.attachNewNode(text) self.textNodePath.setScale(self.headerHeight*0.8) # the content part of the window, put stuff beneath # contentWindow.getCanvas() to put it into it self.maxVirtualSize = maxSize self.minVirtualSize = minSize self.resizeSize = borderSize self.contentWindow = DirectScrolledFrame( parent = self, pos = ( 0, 0, -self.headerHeight ), canvasSize = ( 0, self.maxVirtualSize[0], 0, self.maxVirtualSize[1] ), frameColor = ( 0, 0, 0, 0), # defines the background color of the resize-button relief = DGG.FLAT, borderWidth = (0, 0), verticalScroll_frameSize = [0, self.resizeSize, 0, 1], horizontalScroll_frameSize = [0, 1, 0, self.resizeSize], # resize the scrollbar according to window size verticalScroll_resizeThumb = False, horizontalScroll_resizeThumb = False, # define the textures for the scrollbars verticalScroll_frameTexture = VERTICALSCROLL_FRAMETEXTURE, verticalScroll_incButton_frameTexture = VERTICALSCROLL_INCBUTTON_FRAMETEXTURE, verticalScroll_decButton_frameTexture = VERTICALSCROLL_DECBUTTON_FRAMETEXTURE, verticalScroll_thumb_frameTexture = VERTICALSCROLL_TUMB_FRAMETEXTURE, horizontalScroll_frameTexture = HORIZONTALSCROLL_FRAMETEXTURE, horizontalScroll_incButton_frameTexture = HORIZONTALSCROLL_INCBUTTON_FRAMETEXTURE, horizontalScroll_decButton_frameTexture = HORIZONTALSCROLL_DECBUTTON_FRAMETEXTURE, horizontalScroll_thumb_frameTexture = HORIZONTALSCROLL_TUMB_FRAMETEXTURE, # make all flat, so the texture is as we want it verticalScroll_relief = DGG.FLAT, verticalScroll_thumb_relief = DGG.FLAT, verticalScroll_decButton_relief = DGG.FLAT, verticalScroll_incButton_relief = DGG.FLAT, horizontalScroll_relief = DGG.FLAT, horizontalScroll_thumb_relief = DGG.FLAT, horizontalScroll_decButton_relief = DGG.FLAT, horizontalScroll_incButton_relief = DGG.FLAT, # colors verticalScroll_frameColor = borderColor, verticalScroll_incButton_frameColor = borderColor, verticalScroll_decButton_frameColor = borderColor, verticalScroll_thumb_frameColor = borderColor, horizontalScroll_frameColor = borderColor, horizontalScroll_incButton_frameColor = borderColor, horizontalScroll_decButton_frameColor = borderColor, horizontalScroll_thumb_frameColor = borderColor, ) self.contentWindow.setTransparency(True) # background color self.backgroundColor = DirectFrame( parent = self.contentWindow.getCanvas(), frameSize = ( 0, self.maxVirtualSize[0], 0, self.maxVirtualSize[1] ), frameColor = backgroundColor, relief = DGG.FLAT, borderWidth = ( .01, .01), ) self.backgroundColor.setTransparency(True) # Add a box self.box = boxes.VBox(parent = self.getCanvas()) # is needed for some nicer visuals of the resize button (background) self.windowResizeBackground = DirectButton( parent = self, frameSize = ( -.5, .5, -.5, .5 ), borderWidth = ( 0, 0 ), scale = ( self.resizeSize, 1, self.resizeSize ), relief = DGG.FLAT, frameColor = backgroundColor, ) # the resize button of the window self.windowResize = DirectButton( parent = self, frameSize = ( -.5, .5, -.5, .5 ), borderWidth = ( 0, 0 ), scale = ( self.resizeSize, 1, self.resizeSize ), relief = DGG.FLAT, frameTexture = DEFAULT_RESIZE_GEOM, frameColor = borderColor, ) self.windowResize.setTransparency(True) self.windowResize.bind(DGG.B1PRESS,self.startResizeDrag) self.windowResize.bind(DGG.B1RELEASE,self.stopResizeDrag) # offset then clicking on the resize button from the mouse to the resizebutton # position, required to calculate the position / scaling self.offset = None self.taskName = "resizeTask-%s" % str(hash(self)) # do sizing of the window (minimum) #self.resize( Vec3(0,0,0), Vec3(0,0,0) ) # maximum #self.resize( Vec3(100,0,-100), Vec3(0,0,0) ) self.resize( Vec3(curSize[0], 0, -curSize[1]), Vec3(0,0,0)) def getCanvas(self): return self.contentWindow.getCanvas() # dragging functions def startWindowDrag( self, param ): self.wrtReparentTo( aspect2dMouseNode ) self.ignoreAll() self.accept( 'mouse1-up', self.stopWindowDrag ) def stopWindowDrag( self, param=None ): # this is called 2 times (bug), so make sure it's not already parented to aspect2d if self.getParent() != self.windowParent: self.wrtReparentTo( self.windowParent ) if self.preserve: if self.preserveWhole: if self.getZ() > 1: self.setZ(1) elif self.getZ() < -1 - self.getHeight(): self.setZ(-1 - self.getHeight()) if self.getX() > base.a2dRight - self.getWidth(): self.setX(base.a2dRight - self.getWidth()) elif self.getX() < base.a2dLeft: self.setX(base.a2dLeft) else: if self.getZ() > 1: self.setZ(1) elif self.getZ() < -1 + self.headerHeight: self.setZ(-1 + self.headerHeight) if self.getX() > base.a2dRight - self.headerHeight: self.setX(base.a2dRight - self.headerHeight) elif self.getX() < base.a2dLeft + self.headerHeight - self.getWidth(): self.setX(base.a2dLeft + self.headerHeight - self.getWidth()) #else: #Window moved beyond reach. Destroy window? # resize functions def resize( self, mPos, offset ): mXPos = max( min( mPos.getX(), self.maxVirtualSize[0] ), self.minVirtualSize[0]) mZPos = max( min( mPos.getZ(), -self.minVirtualSize[1] ), -self.maxVirtualSize[1]-self.headerHeight) self.windowResize.setPos( mXPos-self.resizeSize/2., 0, mZPos+self.resizeSize/2. ) self.windowResizeBackground.setPos( mXPos-self.resizeSize/2., 0, mZPos+self.resizeSize/2. ) self['frameSize'] = (0, mXPos, 0, mZPos) self.windowHeaderLeft.setPos( self.headerHeight/2., 0, -self.headerHeight/2. ) self.windowHeaderLeft.setScale( self.headerHeight, 1, self.headerHeight ) self.windowHeaderCenter.setPos( mXPos/2., 0, -self.headerHeight/2. ) self.windowHeaderCenter.setScale( mXPos - self.headerHeight*2., 1, self.headerHeight ) self.windowHeaderRight.setPos( mXPos-self.headerHeight/2., 0, -self.headerHeight/2. ) self.windowHeaderRight.setScale( self.headerHeight, 1, self.headerHeight ) self.contentWindow['frameSize'] = ( 0, mXPos, mZPos+self.headerHeight, 0) self.textNodePath.setPos( mXPos/2., 0, -self.headerHeight/3.*2. ) # show and hide that small background for the window sizer if mXPos == self.maxVirtualSize[0] and \ mZPos == -self.maxVirtualSize[1]-self.headerHeight: self.windowResizeBackground.hide() else: self.windowResizeBackground.show() def resizeTask( self, task=None ): mPos = aspect2dMouseNode.getPos( self )+self.offset self.resize( mPos, self.offset ) return task.cont def startResizeDrag( self, param ): self.offset = self.windowResize.getPos( aspect2dMouseNode ) taskMgr.remove( self.taskName ) taskMgr.add( self.resizeTask, self.taskName ) def stopResizeDrag( self, param ): taskMgr.remove( self.taskName ) # get the window to the front self.wrtReparentTo( self.windowParent ) def addHorizontal(self, widgets): """ Accepts a list of directgui objects which are added to a horizontal box, which is then added to the vertical stack. """ hbox = boxes.HBox() for widget in widgets: hbox.pack(widget) self.box.pack(hbox) self.updateMaxSize() def addVertical(self, widgets): """ Accepts a list of directgui objects which are added to a vertical box, which is then added to the vertical stack. May cause funky layout results. """ #vbox = boxes.VBox() for widget in widgets: self.box.pack(widget) self.updateMaxSize() def add(self, widgets): """Shortcut function for addVertical""" self.addVertical(widgets) def updateMaxSize(self): """Updates the max canvas size to include all items packed. Window is resized to show all contents.""" bottomLeft, topRight = self.box.getTightBounds() self.maxVirtualSize = (topRight[0], -bottomLeft[2]) self.contentWindow['canvasSize'] = ( 0, self.maxVirtualSize[0], -self.maxVirtualSize[1], 0) self.backgroundColor['frameSize'] = ( 0, self.maxVirtualSize[0], -self.maxVirtualSize[1], 0 ) #perhaps this should be optional -- automatically resize for new elements self.reset() def reset(self): """Poorly named function that resizes window to fit all contents""" self.resize( Vec3(self.maxVirtualSize[0], 0, -self.maxVirtualSize[1]-self.headerHeight), Vec3(0,0,0))
class OptionPage(StateData): def __init__(self, book, parentFSM): self.book = book self.parentFSM = parentFSM StateData.__init__(self, 'optionPageDone') self.fsm = ClassicFSM('OptionPage', [ State('off', self.enterOff, self.exitOff), State('basePage', self.enterBasePage, self.exitBasePage), State('displayPage', self.enterDisplayPage, self.exitDisplayPage) ], 'off', 'off') self.fsm.enterInitialState() self.parentFSM.getStateNamed('optionPage').addChild(self.fsm) def enterOff(self): pass def exitOff(self): pass def load(self): StateData.load(self) def unload(self): StateData.unload(self) def enter(self): StateData.enter(self) self.fsm.request('basePage') def exit(self): self.fsm.request('off') StateData.exit(self) def openDisplayPage(self): self.fsm.request('displayPage') def enterDisplayPage(self): self.book.createPageButtons(False, False) self.book.setTitle("Display Options") dialog_gui = loader.loadModel( "phase_3/models/gui/dialog_box_buttons_gui.bam") width, height, fs, music, sfx, tex_detail, model_detail, aa, af = SettingsManager( ).getSettings("settings.json") self.width = width self.height = height self.windowType = [fs] self.buttons = [ DirectRadioButton(text="Windowed", variable=self.windowType, value=[False], scale=0.1, pos=(-0.45, 0.15, 0.15)), DirectRadioButton(text="Fullscreen", variable=self.windowType, value=[True], scale=0.1, pos=(-0.45, -0.15, -0.15)) ] for button in self.buttons: button.setOthers(self.buttons) self.resoLbl = DirectLabel(text="%sx%s" % (width, height), scale=0.08, relief=None, pos=(0.25, 0, 0)) self.resSlider = DirectSlider(range=(0, 200), pageSize=50, command=self.setResoText, scale=0.3, orientation=DGG.VERTICAL, pos=(0.6, 0, 0)) self.okBtn = DirectButton(text="OK", geom=CIGlobals.getOkayBtnGeom(), relief=None, pos=(-0.5, -0.5, -0.5), text_scale=0.05, text_pos=(0, -0.11), command=self.applyDisplaySettings) self.cancelBtn = DirectButton(text="Cancel", geom=CIGlobals.getCancelBtnGeom(), relief=None, pos=(-0.3, -0.5, -0.5), text_scale=0.05, text_pos=(0, -0.11), command=self.cancelDisplaySettings) if self.resoLbl['text'] == "640x480": self.resSlider['value'] = 0 elif self.resoLbl['text'] == "800x600": self.resSlider['value'] = 50 elif self.resoLbl['text'] == "1024x768": self.resSlider['value'] = 100 elif self.resoLbl['text'] == "1280x1024": self.resSlider['value'] = 150 elif self.resoLbl['text'] == "1600x1200": self.resSlider['value'] = 200 def exitDisplayPage(self): for button in self.buttons: button.destroy() del button self.resoLbl.destroy() del self.resoLbl self.resSlider.destroy() del self.resSlider self.okBtn.destroy() del self.okBtn self.cancelBtn.destroy() del self.cancelBtn del self.width del self.height del self.windowType del self.buttons self.book.clearTitle() def changeSetting(self, setting, value): if setting == "music": if value: value = False elif not value: value = True base.enableMusic(value) self.music_btn['extraArgs'] = ["music", value] if value: valueTxt = "On" else: valueTxt = "Off" self.music_lbl['text'] = str(valueTxt).capitalize() elif setting == "sfx": if value: value = False elif not value: value = True base.enableSoundEffects(value) self.sfx_btn['extraArgs'] = ["sfx", value] if value: valueTxt = "On" else: valueTxt = "Off" self.sfx_lbl['text'] = str(valueTxt).capitalize() elif setting == "model-detail": if value == "high": value = "low" elif value == "medium": value = "high" elif value == "low": value = "medium" self.moddet_lbl['text'] = value.capitalize() self.moddet_btn['extraArgs'] = ["model-detail", value] elif setting == "texture-detail": if value == "normal": value = "low" loadPrcFileData("", "compressed-textures 1") elif value == "low": value = "normal" loadPrcFileData("", "compressed-textures 0") self.texdet_lbl['text'] = value.capitalize() self.texdet_btn['extraArgs'] = ["texture-detail", value] elif setting == "aa": if value == "on": value = "off" render.clear_antialias() elif value == "off": value = "on" render.set_antialias(AntialiasAttrib.MAuto) self.aa_lbl['text'] = value.capitalize() self.aa_btn['extraArgs'] = ["aa", value] elif setting == "af": if value == "on": value = "off" elif value == "off": value = "on" self.af_lbl['text'] = value.capitalize() self.af_btn['extraArgs'] = ["af", value] SettingsManager().writeSettingToFile(setting, value, "settings.json") def setResoText(self): if self.resSlider['value'] == 200: self.width = 1600 self.height = 1200 elif 150 <= self.resSlider['value'] <= 199: self.width = 1280 self.height = 1024 elif 100 <= self.resSlider['value'] <= 149: self.width = 1024 self.height = 768 elif 50 <= self.resSlider['value'] <= 99: self.width = 800 self.height = 600 elif self.resSlider['value'] == 0: self.width = 640 self.height = 480 self.resoLbl['text'] = str(self.width) + "x" + str(self.height) def applyDisplaySettings(self): SettingsManager().writeSettingToFile("resolution", (self.width, self.height), "settings.json", apply=1) SettingsManager().writeSettingToFile("fullscreen", self.windowType, "settings.json", apply=1) self.fsm.request('basePage') def cancelDisplaySettings(self): self.fsm.request('basePage') def enterBasePage(self): self.book.createPageButtons(None, 'districtPage') self.book.setTitle("Options") width, height, fs, music, sfx, tex_detail, model_detail, aa, af = SettingsManager( ).getSettings("settings.json") if music: musicTxt = "On" else: musicTxt = "Off" if sfx: sfxTxt = "On" else: sfxTxt = "Off" if fs: fsTxt = "On" else: fsTxt = "Off" self.music_btn = DirectButton(geom=(qt_btn.find('**/QuitBtn_UP'), qt_btn.find('**/QuitBtn_DN'), qt_btn.find('**/QuitBtn_RLVR')), relief=None, text="Music", scale=1, text_scale=0.055, command=self.changeSetting, extraArgs=["music", music], pos=(-0.45, 0.55, 0.55), text_pos=(0, -0.01)) self.music_lbl = DirectLabel(relief=None, scale=0.09, pos=(0.45, 0.55, 0.52), text_align=TextNode.ACenter) self.music_lbl['text'] = str(musicTxt).capitalize() self.sfx_btn = DirectButton(geom=(qt_btn.find('**/QuitBtn_UP'), qt_btn.find('**/QuitBtn_DN'), qt_btn.find('**/QuitBtn_RLVR')), relief=None, text="SFX", scale=1, text_scale=0.055, command=self.changeSetting, extraArgs=["sfx", sfx], pos=(-0.45, 0.45, 0.45), text_pos=(0, -0.01)) self.sfx_lbl = DirectLabel(relief=None, scale=0.09, pos=(0.45, 0.45, 0.42), text_align=TextNode.ACenter) self.sfx_lbl['text'] = str(sfxTxt).capitalize() self.moddet_btn = DirectButton( geom=(qt_btn.find('**/QuitBtn_UP'), qt_btn.find('**/QuitBtn_DN'), qt_btn.find('**/QuitBtn_RLVR')), relief=None, text="Model Detail", scale=1, text_scale=0.055, command=self.changeSetting, extraArgs=["model-detail", model_detail], pos=(-0.45, 0.35, 0.35), text_pos=(0, -0.01)) self.moddet_lbl = DirectLabel(relief=None, scale=0.09, pos=(0.45, 0.35, 0.32), text_align=TextNode.ACenter) self.moddet_lbl['text'] = model_detail.capitalize() self.moddet_btn.bind(DGG.ENTER, self.createMustRestartGui) self.moddet_btn.bind(DGG.EXIT, self.removeMustRestartGui) self.texdet_btn = DirectButton( geom=(qt_btn.find('**/QuitBtn_UP'), qt_btn.find('**/QuitBtn_DN'), qt_btn.find('**/QuitBtn_RLVR')), relief=None, text="Texture Detail", scale=1, text_scale=0.0535, command=self.changeSetting, extraArgs=["texture-detail", tex_detail], pos=(-0.45, 0.25, 0.25), text_pos=(0, -0.01)) self.texdet_lbl = DirectLabel(relief=None, scale=0.09, pos=(0.45, 0.25, 0.22), text_align=TextNode.ACenter) self.texdet_lbl['text'] = tex_detail.capitalize() self.texdet_btn.bind(DGG.ENTER, self.createMustRestartGui) self.texdet_btn.bind(DGG.EXIT, self.removeMustRestartGui) self.display_btn = DirectButton(geom=(qt_btn.find('**/QuitBtn_UP'), qt_btn.find('**/QuitBtn_DN'), qt_btn.find('**/QuitBtn_RLVR')), relief=None, text="Display", command=self.openDisplayPage, scale=1, text_scale=0.0535, pos=(-0.45, -0.25, 0.02), text_pos=(0, -0.01)) self.display_lbl = DirectLabel(relief=None, scale=0.06, pos=(0.45, -0.25, 0.02), text_align=TextNode.ACenter) self.display_lbl['text'] = "Fullscreen: %s\nResolution: %s" % ( str(fsTxt).capitalize(), (width, height)) self.aa_btn = DirectButton(geom=(qt_btn.find('**/QuitBtn_UP'), qt_btn.find('**/QuitBtn_DN'), qt_btn.find('**/QuitBtn_RLVR')), relief=None, text="Anti-Aliasing", command=self.changeSetting, extraArgs=["aa", aa], scale=1, text_scale=0.0535, pos=(-0.45, -0.35, -0.18), text_pos=(0, -0.01)) self.aa_lbl = DirectLabel(relief=None, scale=0.09, pos=(0.45, -0.35, -0.21), text_align=TextNode.ACenter) self.aa_lbl['text'] = aa.capitalize() self.af_btn = DirectButton(geom=(qt_btn.find('**/QuitBtn_UP'), qt_btn.find('**/QuitBtn_DN'), qt_btn.find('**/QuitBtn_RLVR')), relief=None, text="Anisotropic Filtering", command=self.changeSetting, extraArgs=["af", af], scale=1, text_scale=0.0435, pos=(-0.45, -0.35, -0.28), text_pos=(0, -0.01)) self.af_lbl = DirectLabel(relief=None, scale=0.09, pos=(0.45, -0.35, -0.31), text_align=TextNode.ACenter) self.af_lbl['text'] = af.capitalize() self.af_btn.bind(DGG.ENTER, self.createMustRestartGui) self.af_btn.bind(DGG.EXIT, self.removeMustRestartGui) self.exit_btn = DirectButton(geom=(qt_btn.find('**/QuitBtn_UP'), qt_btn.find('**/QuitBtn_DN'), qt_btn.find('**/QuitBtn_RLVR')), relief=None, text="Exit Toontown", scale=1.2, text_scale=0.0535, command=self.book.finished, extraArgs=["exit"], pos=(-0.45, -0.65, -0.60), text_pos=(0, -0.01)) def createMustRestartGui(self, foo): self.mustRestartLbl = DirectLabel( text="Changing this setting requires a game restart.", text_fg=(0.9, 0, 0, 1), text_shadow=(0, 0, 0, 1), text_scale=0.06, text_align=TextNode.ACenter, pos=(0, 0, -0.435), relief=None) def removeMustRestartGui(self, foo): if hasattr(self, 'mustRestartLbl'): self.mustRestartLbl.destroy() del self.mustRestartLbl def exitBasePage(self): self.music_btn.destroy() del self.music_btn self.sfx_btn.destroy() del self.sfx_btn self.moddet_btn.destroy() del self.moddet_btn self.texdet_btn.destroy() del self.texdet_btn self.display_btn.destroy() del self.display_btn self.aa_btn.destroy() del self.aa_btn self.exit_btn.destroy() del self.exit_btn self.music_lbl.destroy() del self.music_lbl self.sfx_lbl.destroy() del self.sfx_lbl self.moddet_lbl.destroy() del self.moddet_lbl self.texdet_lbl.destroy() del self.texdet_lbl self.display_lbl.destroy() del self.display_lbl self.aa_lbl.destroy() del self.aa_lbl self.af_btn.destroy() del self.af_btn self.af_lbl.destroy() del self.af_lbl self.book.deletePageButtons(False, True) self.book.clearTitle()
def __init__(self): self._weapon_buts = {} self._turn_snd = loader.loadSfx( # noqa: F821 "sounds/train/railroad_switch.ogg" ) frame = DirectFrame( parent=base.a2dBottomRight, # noqa: F821 frameSize=(-0.09, 0.09, -0.28, 0.28), pos=(-0.09, 0, 0.28), frameTexture=GUI_PIC + "metal1.png", ) frame.setTransparency(TransparencyAttrib.MAlpha) DirectFrame( # an icon for the locomotive durability parent=frame, frameSize=(-0.023, 0.023, -0.023, 0.023), pos=(0.05, 0, 0.24), frameTexture=GUI_PIC + "train.png", ).setTransparency(TransparencyAttrib.MAlpha) DirectFrame( # an icon for the locomotive speed parent=frame, frameSize=(-0.028, 0.028, -0.023, 0.023), pos=(-0.012, 0, 0.24), frameTexture=GUI_PIC + "speed.png", ).setTransparency(TransparencyAttrib.MAlpha) self._durability = DirectWaitBar( parent=frame, frameSize=(-0.225, 0.225, -0.002, 0.002), frameColor=(0.35, 0.35, 0.35, 1), range=1000, value=1000, barColor=(0.42, 0.42, 0.8, 1), pos=(0.05, 0, -0.025), ) self._durability.setR(-90) self._speed = DirectWaitBar( parent=frame, frameSize=(-0.225, 0.225, -0.002, 0.002), frameColor=(0.35, 0.35, 0.35, 1), range=1, value=1, barColor=(1, 0.63, 0, 0.6), pos=(-0.012, 0, -0.025), ) self._speed.setR(-90) DirectLabel( # speed gauge scale parent=frame, pos=(-0.05, 0, 0.19), frameSize=(-0.25, 0.25, -0.01, 0.01), frameColor=(0, 0, 0, 0), text="40-\n\n-\n\n-\n\n-\n\n20-\n\n-\n\n-\n\n-\n\n0-", text_scale=0.028, text_fg=SILVER_COL, ) frame_miles = DirectFrame( frameSize=(-0.115, 0.115, -0.06, 0.05), pos=(0, 0, -0.95), frameTexture=GUI_PIC + "metal1.png", sortOrder=-1, ) frame_miles.set_transparency(TransparencyAttrib.MAlpha) but = DirectButton( parent=frame_miles, frameSize=(-0.015, 0.015, -0.025, 0.025), frameTexture=GUI_PIC + "grenade.png", pos=(-0.075, 0, 0.015), relief="flat", ) but.setTransparency(TransparencyAttrib.MAlpha) but.bind(DGG.ENTER, self._highlight_weapon_but, extraArgs=[but]) but.bind(DGG.EXIT, self._dehighlight_weapon_but, extraArgs=[but]) self._weapon_buts["Grenade Launcher"] = { "but": but, "reload_step": 0, "dis_command": None, "reloading_len": 13, "frame": DirectFrame( parent=frame_miles, frameColor=(0, 0, 0, 0.25), pos=(-0.075, 0, -0.01), frameSize=(-0.013, 0.013, 0, 0.05), ), } but = DirectButton( parent=frame_miles, frameSize=(-0.015, 0.015, -0.025, 0.025), frameTexture=GUI_PIC + "machine_gun.png", pos=(0, 0, 0.015), relief="flat", ) but.setTransparency(TransparencyAttrib.MAlpha) but.bind(DGG.ENTER, self._highlight_weapon_but, extraArgs=[but]) but.bind(DGG.EXIT, self._dehighlight_weapon_but, extraArgs=[but]) self._weapon_buts["Machine Gun"] = { "but": but, "reload_step": 0, "dis_command": None, "reloading_len": 22, "frame": DirectFrame( parent=frame_miles, frameColor=(0, 0, 0, 0.25), pos=(0, 0, -0.01), frameSize=(-0.013, 0.013, 0, 0.05), ), } but = DirectButton( parent=frame_miles, frameSize=(-0.015, 0.015, -0.025, 0.025), frameTexture=GUI_PIC + "cluster_rocket.png", pos=(0.075, 0, 0.015), relief="flat", ) but.setTransparency(TransparencyAttrib.MAlpha) but.bind(DGG.ENTER, self._highlight_weapon_but, extraArgs=[but]) but.bind(DGG.EXIT, self._dehighlight_weapon_but, extraArgs=[but]) self._weapon_buts["Cluster Howitzer"] = { "but": but, "reload_step": 0, "dis_command": None, "reloading_len": 45, "frame": DirectFrame( parent=frame_miles, frameColor=(0, 0, 0, 0.25), pos=(0.075, 0, -0.01), frameSize=(-0.013, 0.013, 0, 0.05), ), } self._miles_meter = DirectLabel( parent=frame_miles, text="0000000", text_font=base.main_font, # noqa: F821 frameSize=(0.1, 0.1, 0.15, 0.15), text_scale=(0.033, 0.031), text_fg=RUST_COL, pos=(0, 0, -0.04), ) taskMgr.doMethodLater( # noqa: F821 0.25, self._update_speed, "update_speed_indicator" ) self._fork_lab = None
class LaffShopGui(DirectFrame): def __init__(self): DirectFrame.__init__(self, parent=aspect2d, relief=None, geom=DGG.getDefaultDialogGeom(), geom_color=ToontownGlobals.GlobalDialogColor, geom_scale=(1.33, 1, 1.3), pos=(0, 0, 0), text='', text_scale=0.07, text_pos=(0, 0.475)) self.initialiseoptions(LaffShopGui) self.additionalLaff = 0 self.timer = ToontownTimer.ToontownTimer() self.timer.reparentTo(aspect2d) self.timer.posInTopRightCorner() self.timer.countdown(LaffRestockGlobals.TIMER_SECONDS, self.__cancel, [LaffRestockGlobals.TIMER_END]) self.setupButtons() self.bindButtons() self.laffMeter = LaffMeter.LaffMeter(base.localAvatar.style, base.localAvatar.getHp(), base.localAvatar.getMaxHp()) self.laffMeter.reparentTo(self) self.laffMeter.setPos(0, 0, 0.065) self.laffMeter.setScale(0.13) self.__updateLaffMeter(1) def setupButtons(self): buttons = loader.loadModel('phase_3/models/gui/dialog_box_buttons_gui') arrowGui = loader.loadModel('phase_3/models/gui/create_a_toon_gui') arrowImageList = (arrowGui.find('**/CrtATn_R_Arrow_UP'), arrowGui.find('**/CrtATn_R_Arrow_DN'), arrowGui.find('**/CrtATn_R_Arrow_RLVR'), arrowGui.find('**/CrtATn_R_Arrow_UP')) self.cancelButton = DirectButton( parent=self, relief=None, image=(buttons.find('**/CloseBtn_UP'), buttons.find('**/CloseBtn_DN'), buttons.find('**/CloseBtn_Rllvr')), pos=(-0.2, 0, -0.5), text=OTPLocalizer.lCancel, text_scale=0.06, text_pos=(0, -0.1), command=self.__cancel, extraArgs=[LaffRestockGlobals.USER_CANCEL]) self.okButton = DirectButton( parent=self, relief=None, image=(buttons.find('**/ChtBx_OKBtn_UP'), buttons.find('**/ChtBx_OKBtn_DN'), buttons.find('**/ChtBx_OKBtn_Rllvr')), pos=(0.2, 0, -0.5), text=OTPLocalizer.lOK, text_scale=0.06, text_pos=(0, -0.1), command=self.__restock) self.upArrow = DirectButton(parent=self, relief=None, image=arrowImageList, image_scale=(1, 1, 1), image3_color=Vec4(0.6, 0.6, 0.6, 0.25), pos=(0.2, 0, -0.265)) self.downArrow = DirectButton(parent=self, relief=None, image=arrowImageList, image_scale=(-1, 1, 1), image3_color=Vec4(0.6, 0.6, 0.6, 0.25), pos=(-0.2, 0, -0.265)) buttons.removeNode() arrowGui.removeNode() def bindButtons(self): self.downArrow.bind(DGG.B1PRESS, self.__taskUpdate, extraArgs=[-1]) self.downArrow.bind(DGG.B1RELEASE, self.__taskDone) self.upArrow.bind(DGG.B1PRESS, self.__taskUpdate, extraArgs=[1]) self.upArrow.bind(DGG.B1RELEASE, self.__taskDone) def destroy(self): self.ignoreAll() if self.timer: self.timer.destroy() taskMgr.remove(self.taskName('runLaffCounter')) DirectFrame.destroy(self) def __cancel(self, state): self.destroy() messenger.send('laffShopDone', [state, 0]) def __restock(self): self.destroy() messenger.send('laffShopDone', [LaffRestockGlobals.RESTOCK, self.additionalLaff]) def __updateLaffMeter(self, amount): self.additionalLaff += amount hitLimit = 0 newLaff = base.localAvatar.getHp() + self.additionalLaff if (newLaff - 1) <= base.localAvatar.getHp(): self.downArrow['state'] = DGG.DISABLED hitLimit = 1 else: self.downArrow['state'] = DGG.NORMAL if newLaff >= base.localAvatar.getMaxHp(): self.upArrow['state'] = DGG.DISABLED hitLimit = 1 else: self.upArrow['state'] = DGG.NORMAL cost = self.additionalLaff * ToontownGlobals.CostPerLaffRestock self['text'] = TTLocalizer.RestockAskMessage % (self.additionalLaff, cost) if cost > base.localAvatar.getTotalMoney(): self.okButton['state'] = DGG.DISABLED self['text'] += TTLocalizer.RestockNoMoneyGuiMessage else: self.okButton['state'] = DGG.NORMAL self.laffMeter.hp = newLaff self.laffMeter.start() return hitLimit def __runTask(self, task): if task.time - task.prevTime < task.delayTime: return Task.cont else: task.delayTime = max(0.05, task.delayTime * 0.75) task.prevTime = task.time hitLimit = self.__updateLaffMeter(task.delta) return Task.done if hitLimit else Task.cont def __taskDone(self, event): messenger.send('wakeup') taskMgr.remove(self.taskName('runLaffCounter')) def __taskUpdate(self, delta, event): messenger.send('wakeup') task = Task(self.__runTask) task.delayTime = 0.4 task.prevTime = 0.0 task.delta = delta hitLimit = self.__updateLaffMeter(delta) if not hitLimit: taskMgr.add(task, self.taskName('runLaffCounter'))
class PartyEditor(DirectObject, FSM): notify = directNotify.newCategory('PartyEditor') def __init__(self, partyPlanner, parent): FSM.__init__(self, self.__class__.__name__) self.partyPlanner = partyPlanner self.parent = parent self.partyEditorGrid = PartyEditorGrid(self) self.currentElement = None self.defaultTransitions = {'Hidden': ['Idle', 'Cleanup'], 'Idle': ['DraggingElement', 'Hidden', 'Cleanup'], 'DraggingElement': ['Idle', 'DraggingElement', 'Hidden', 'Cleanup'], 'Cleanup': []} self.initElementList() self.initPartyClock() self.initTrashCan() return def initElementList(self): self.activityIconsModel = loader.loadModel('phase_4/models/parties/eventSignIcons') self.decorationModels = loader.loadModel('phase_4/models/parties/partyDecorations') pos = self.partyPlanner.gui.find('**/step_05_activitiesIcon_locator').getPos() self.elementList = DirectScrolledList(parent=self.parent, relief=None, decButton_image=(self.partyPlanner.gui.find('**/activitiesButtonUp_up'), self.partyPlanner.gui.find('**/activitiesButtonUp_down'), self.partyPlanner.gui.find('**/activitiesButtonUp_rollover'), self.partyPlanner.gui.find('**/activitiesButtonUp_inactive')), decButton_relief=None, decButton_pos=(-0.05, 0.0, -0.38), incButton_image=(self.partyPlanner.gui.find('**/activitiesButtonDown_up'), self.partyPlanner.gui.find('**/activitiesButtonDown_down'), self.partyPlanner.gui.find('**/activitiesButtonDown_rollover'), self.partyPlanner.gui.find('**/activitiesButtonDown_inactive')), incButton_relief=None, incButton_pos=(-0.05, 0.0, -0.94), itemFrame_pos=(pos[0], pos[1], pos[2] + 0.04), itemFrame_relief=None, numItemsVisible=1, items=[]) holidayIds = base.cr.newsManager.getHolidayIdList() isWinter = ToontownGlobals.WINTER_DECORATIONS in holidayIds or ToontownGlobals.WACKY_WINTER_DECORATIONS in holidayIds isVictory = ToontownGlobals.VICTORY_PARTY_HOLIDAY in holidayIds isValentine = ToontownGlobals.VALENTINES_DAY in holidayIds for activityId in PartyGlobals.PartyEditorActivityOrder: if not isVictory and activityId in PartyGlobals.VictoryPartyActivityIds or not isWinter and activityId in PartyGlobals.WinterPartyActivityIds or not isValentine and activityId in PartyGlobals.ValentinePartyActivityIds: pass elif isVictory and activityId in PartyGlobals.VictoryPartyReplacementActivityIds or isWinter and activityId in PartyGlobals.WinterPartyReplacementActivityIds or isValentine and activityId in PartyGlobals.ValentinePartyReplacementActivityIds: pass else: pele = PartyEditorListElement(self, activityId) self.elementList.addItem(pele) if activityId == PartyGlobals.ActivityIds.PartyClock: self.partyClockElement = pele for decorationId in PartyGlobals.DecorationIds: if not isVictory and decorationId in PartyGlobals.VictoryPartyDecorationIds or not isWinter and decorationId in PartyGlobals.WinterPartyDecorationIds or not isValentine and decorationId in PartyGlobals.ValentinePartyDecorationIds: pass elif isVictory and decorationId in PartyGlobals.VictoryPartyReplacementDecorationIds or isValentine and decorationId in PartyGlobals.ValentinePartyReplacementDecorationIds: pass elif decorationId in PartyGlobals.TTIUnreleasedDecor: pass else: pele = PartyEditorListElement(self, decorationId, isDecoration=True) self.elementList.addItem(pele) self.elementList.refresh() self.elementList['command'] = self.scrollItemChanged return def initPartyClock(self): self.partyClockElement.buyButtonClicked((8, 7)) def initTrashCan(self): trashcanGui = loader.loadModel('phase_3/models/gui/trashcan_gui') self.trashCanButton = DirectButton(parent=self.parent, relief=None, pos=Point3(*PartyGlobals.TrashCanPosition), scale=PartyGlobals.TrashCanScale, geom=(trashcanGui.find('**/TrashCan_CLSD'), trashcanGui.find('**/TrashCan_OPEN'), trashcanGui.find('**/TrashCan_RLVR'), trashcanGui.find('**/TrashCan_RLVR')), command=self.trashCanClicked) self.trashCanButton.bind(DirectGuiGlobals.ENTER, self.mouseEnterTrash) self.trashCanButton.bind(DirectGuiGlobals.EXIT, self.mouseExitTrash) self.mouseOverTrash = False self.oldInstructionText = '' self.trashCanLastClickedTime = 0 return def scrollItemChanged(self): if not self.elementList['items']: return self.currentElement = self.elementList['items'][self.elementList.getSelectedIndex()] self.elementList['items'][self.elementList.getSelectedIndex()].elementSelectedFromList() if self.elementList['items'][self.elementList.getSelectedIndex()].isDecoration: self.partyPlanner.instructionLabel['text'] = TTLocalizer.PartyPlannerEditorInstructionsClickedElementDecoration else: self.partyPlanner.instructionLabel['text'] = TTLocalizer.PartyPlannerEditorInstructionsClickedElementActivity def listElementClicked(self): self.request('DraggingElement') def listElementReleased(self): self.request('Idle', True) def trashCanClicked(self): currentTime = time.time() if currentTime - self.trashCanLastClickedTime < 0.2: self.clearPartyGrounds() self.trashCanLastClickedTime = time.time() def clearPartyGrounds(self): for item in self.elementList['items']: item.clearPartyGrounds() self.initPartyClock() if self.currentElement: self.currentElement.checkSoldOutAndPaidStatusAndAffordability() def buyCurrentElement(self): if self.currentElement: purchaseSuccessful = self.currentElement.buyButtonClicked() if purchaseSuccessful: self.handleMutuallyExclusiveActivities() else: self.partyPlanner.instructionLabel['text'] = TTLocalizer.PartyPlannerEditorInstructionsNoRoom def mouseEnterTrash(self, mouseEvent): self.mouseOverTrash = True self.oldInstructionText = self.partyPlanner.instructionLabel['text'] self.partyPlanner.instructionLabel['text'] = TTLocalizer.PartyPlannerEditorInstructionsTrash def mouseExitTrash(self, mouseEvent): self.mouseOverTrash = False self.partyPlanner.instructionLabel['text'] = self.oldInstructionText def enterHidden(self): PartyEditor.notify.debug('Enter Hidden') def exitHidden(self): PartyEditor.notify.debug('Exit Hidden') def enterIdle(self, fromDragging = False): PartyEditor.notify.debug('Enter Idle') if not fromDragging: self.elementList.scrollTo(0) self.elementList['items'][0].elementSelectedFromList() self.currentElement = self.elementList['items'][self.elementList.getSelectedIndex()] self.currentElement.checkSoldOutAndPaidStatusAndAffordability() self.partyPlanner.instructionLabel['text'] = TTLocalizer.PartyPlannerEditorInstructionsIdle self.updateCostsAndBank() self.handleMutuallyExclusiveActivities() def handleMutuallyExclusiveActivities(self): mutSet = self.getMutuallyExclusiveActivities() if not mutSet: return currentActivities = self.partyEditorGrid.getActivitiesElementsOnGrid() lastActivity = self.partyEditorGrid.lastActivityIdPlaced for act in currentActivities: if act.id in mutSet and not lastActivity == act.id: act.removeFromGrid() removedName = TTLocalizer.PartyActivityNameDict[act.id]['editor'] addedName = TTLocalizer.PartyActivityNameDict[lastActivity]['editor'] instr = TTLocalizer.PartyPlannerEditorInstructionsRemoved % {'removed': removedName, 'added': addedName} self.partyPlanner.instructionLabel['text'] = instr self.updateCostsAndBank() def getMutuallyExclusiveActivities(self): currentActivities = self.partyEditorGrid.getActivitiesOnGrid() actSet = Set([]) for act in currentActivities: actSet.add(act[0]) result = None for mutuallyExclusiveTuples in PartyGlobals.MutuallyExclusiveActivities: mutSet = Set(mutuallyExclusiveTuples) inter = mutSet.intersection(actSet) if len(inter) > 1: result = inter break return result def updateCostsAndBank(self): currentActivities = self.partyEditorGrid.getActivitiesOnGrid() currentDecorations = self.partyEditorGrid.getDecorationsOnGrid() newCost = 0 for elementTuple in currentActivities: newCost += PartyGlobals.ActivityInformationDict[elementTuple[0]]['cost'] for elementTuple in currentDecorations: newCost += PartyGlobals.DecorationInformationDict[elementTuple[0]]['cost'] self.partyPlanner.costLabel['text'] = TTLocalizer.PartyPlannerTotalCost % newCost if len(currentActivities) > 0 or len(currentDecorations) > 0: self.partyPlanner.setNextButtonState(enabled=True) else: self.partyPlanner.setNextButtonState(enabled=False) self.partyPlanner.totalCost = newCost self.partyPlanner.beanBank['text'] = str(int(self.partyPlanner.totalMoney - self.partyPlanner.totalCost)) def exitIdle(self): PartyEditor.notify.debug('Exit Idle') def enterDraggingElement(self): PartyEditor.notify.debug('Enter DraggingElement') if self.currentElement.isDecoration: self.partyPlanner.instructionLabel['text'] = TTLocalizer.PartyPlannerEditorInstructionsDraggingDecoration else: self.partyPlanner.instructionLabel['text'] = TTLocalizer.PartyPlannerEditorInstructionsDraggingActivity def exitDraggingElement(self): PartyEditor.notify.debug('Exit DraggingElement') def enterCleanup(self): PartyEditor.notify.debug('Enter Cleanup') self.partyEditorGrid.destroy() self.elementList.removeAndDestroyAllItems() self.elementList.destroy() self.trashCanButton.unbind(DirectGuiGlobals.ENTER) self.trashCanButton.unbind(DirectGuiGlobals.EXIT) self.trashCanButton.destroy() def exitCleanup(self): PartyEditor.notify.debug('Exit Cleanup')
class PartyPlanner(DirectFrame, FSM): notify = DirectNotifyGlobal.directNotify.newCategory('PartyPlanner') def __init__(self, doneEvent = None): FSM.__init__(self, 'PartyPlannerFSM') DirectFrame.__init__(self) self.doneEvent = doneEvent self.stateArray = ['Off', 'Welcome', 'PartyEditor', 'Guests', 'Date', 'Time', 'Invitation', 'Farewell'] self.partyTime = base.cr.toontownTimeManager.getCurServerDateTime() self.partyNowTime = base.cr.toontownTimeManager.getCurServerDateTime() minutesToNextFifteen = 15 - self.partyTime.minute % 15 self.cleanPartyTime = self.partyTime + timedelta(minutes=minutesToNextFifteen, seconds=-self.partyTime.second) self.partyTime = self.cleanPartyTime self.guests = [] self.isPrivate = False self.selectedCalendarGuiDay = None self.gui = loader.loadModel('phase_4/models/parties/partyPlannerGUI') self.partyDuration = timedelta(hours=PartyGlobals.DefaultPartyDuration) self.timeTypeToMaxValue = {'hour': 23, 'minute': 59} self.timeTypeToChangeAmount = {'hour': (1, -1), 'minute': (15, -15), 'ampm': (1, -1)} self.partyInfo = None self.asapMinuteRounding = base.config.GetInt('party-asap-minute-rounding', PartyGlobals.PartyPlannerAsapMinuteRounding) self.load() self.request('Welcome') return def enterWelcome(self, *args): self.prevButton['state'] = DirectGuiGlobals.DISABLED self.prevButton.hide() self.nextButton['state'] = DirectGuiGlobals.NORMAL self.welcomePage.show() self.partyPlannerHead.reparentTo(self.welcomePage) self.partyPlannerHead.startBlink() self.partyPlannerHead.startLookAround() self.nametagNP.reparentTo(self.welcomePage) self.chatNP.reparentTo(self.welcomePage) def exitWelcome(self): self.welcomePage.hide() self.prevButton.show() self.partyPlannerHead.stopBlink() self.partyPlannerHead.stopLookAround() def enterPartyEditor(self, *args): self.prevButton['state'] = DirectGuiGlobals.NORMAL self.nextButton['state'] = DirectGuiGlobals.DISABLED self.nextButton.hide() self.partyEditorPage.show() self.okWithGroundsGui.doneStatus = '' self.partyEditor.request('Idle') def exitPartyEditor(self): self.partyEditor.request('Hidden') self.partyEditorPage.hide() def enterGuests(self, *args): self.prevButton['state'] = DirectGuiGlobals.NORMAL self.nextButton['state'] = DirectGuiGlobals.NORMAL self.nextButton.show() self.guestPage.show() def exitGuests(self): self.guests = [] for friendCheckBox in self.friendList['items']: if friendCheckBox['indicatorValue']: self.guests.append(friendCheckBox.getPythonTag('id')) self.guestPage.hide() def enterDate(self, *args): self.prevButton.show() self.prevButton['state'] = DirectGuiGlobals.NORMAL if self.selectedCalendarGuiDay is None: self.nextButton['state'] = DirectGuiGlobals.DISABLED self.nextButton.hide() self.makePartyNowButton.show() self.datePage.show() return def exitDate(self): self.datePage.hide() self.nextButton.show() if self.selectedCalendarGuiDay is not None: self.partyTime = self.cleanPartyTime self.alterPartyTime(year=self.selectedCalendarGuiDay.myDate.year, month=self.selectedCalendarGuiDay.myDate.month, day=self.selectedCalendarGuiDay.myDate.day) else: self.partyNowTime = self.calcAsapTime() self.partyTime = self.partyNowTime return def calcAsapTime(self): curServerTime = base.cr.toontownTimeManager.getCurServerDateTime() baseTime = curServerTime baseTime = baseTime.replace(baseTime.year, baseTime.month, baseTime.day, baseTime.hour, baseTime.minute, second=0, microsecond=0) minute = curServerTime.minute remainder = minute % self.asapMinuteRounding if remainder: baseTime += timedelta(minutes=self.asapMinuteRounding - remainder) else: baseTime += timedelta(minutes=self.asapMinuteRounding) return baseTime def enterTime(self, *args): self.prevButton.show() self.prevButton['state'] = DirectGuiGlobals.NORMAL self.nextButton.show() self.timePage.show() self.timePageRecapToontownTimeLabel2['text'] = '%s' % PartyUtils.formatDateTime(self.partyTime) self.timePageRecapLocalTimeLabel['text'] = '%s%s' % (TTLocalizer.PartyPlannerTimeLocalTime, PartyUtils.formatDateTime(self.partyTime, inLocalTime=True)) def exitTime(self): self.timePage.hide() self.nextButton.show() def enterInvitation(self, *args): self.prevButton['state'] = DirectGuiGlobals.NORMAL self.nextButton.hide() defaultInviteTheme = PartyGlobals.InviteTheme.GenericMale if hasattr(base.cr, 'newsManager') and base.cr.newsManager: if ToontownGlobals.VICTORY_PARTY_HOLIDAY in base.cr.newsManager.getHolidayIdList(): defaultInviteTheme = PartyGlobals.InviteTheme.VictoryParty elif ToontownGlobals.KARTING_TICKETS_HOLIDAY in base.cr.newsManager.getHolidayIdList() or ToontownGlobals.CIRCUIT_RACING_EVENT in base.cr.newsManager.getHolidayIdList(): defaultInviteTheme = PartyGlobals.InviteTheme.Racing elif ToontownGlobals.VALENTINES_DAY in base.cr.newsManager.getHolidayIdList(): defaultInviteTheme = PartyGlobals.InviteTheme.Valentoons if self.partyInfo is not None: del self.partyInfo activityList = self.partyEditor.partyEditorGrid.getActivitiesOnGrid() decorationList = self.partyEditor.partyEditorGrid.getDecorationsOnGrid() endTime = self.partyTime + self.partyDuration self.partyInfo = PartyInfo(0, 0, self.partyTime.year, self.partyTime.month, self.partyTime.day, self.partyTime.hour, self.partyTime.minute, endTime.year, endTime.month, endTime.day, endTime.hour, endTime.minute, self.isPrivate, defaultInviteTheme, activityList, decorationList, 0) if self.noFriends or len(self.getInvitees()) == 0: self.inviteVisual.setNoFriends(True) self.invitationTitleLabel['text'] = TTLocalizer.PartyPlannerConfirmTitleNoFriends self.inviteButton['text'] = TTLocalizer.PartyPlannerInviteButtonNoFriends self.selectedInviteThemeLabel.stash() self.nextThemeButton.stash() self.prevThemeButton.stash() self.setInviteTheme(defaultInviteTheme) else: self.inviteVisual.setNoFriends(False) self.invitationTitleLabel['text'] = TTLocalizer.PartyPlannerConfirmTitle self.inviteButton['text'] = TTLocalizer.PartyPlannerInviteButton self.selectedInviteThemeLabel.unstash() self.nextThemeButton.unstash() self.prevThemeButton.unstash() self.setInviteTheme(defaultInviteTheme) self.inviteVisual.updateInvitation(base.localAvatar.getName(), self.partyInfo) self.invitationPage.show() return def __prevTheme(self): self.nextThemeButton.show() prevTheme = self.currentInvitationTheme - 1 while prevTheme not in self.inviteThemes: prevTheme -= 1 if prevTheme == self.currentInvitationTheme: self.notify.warning('No previous invite theme found.') break elif prevTheme < 0: prevTheme = len(self.inviteVisual.inviteThemesIdToInfo) - 1 self.setInviteTheme(prevTheme) def __nextTheme(self): self.prevThemeButton.show() nextTheme = self.currentInvitationTheme + 1 while nextTheme not in self.inviteThemes: nextTheme += 1 if nextTheme == self.currentInvitationTheme: self.notify.warning('No next invite theme found.') break elif nextTheme >= len(self.inviteVisual.inviteThemesIdToInfo): nextTheme = 0 self.setInviteTheme(nextTheme) def setInviteTheme(self, themeNumber): self.currentInvitationTheme = themeNumber self.selectedInviteThemeLabel['text'] = '%s %s (%d/%d)' % (self.inviteVisual.inviteThemesIdToInfo[self.currentInvitationTheme][1], TTLocalizer.PartyPlannerInvitationTheme, self.inviteThemes.index(self.currentInvitationTheme) + 1, len(self.inviteThemes)) self.partyInfo.inviteTheme = self.currentInvitationTheme self.inviteVisual.updateInvitation(base.localAvatar.getName(), self.partyInfo) def exitInvitation(self): self.invitationPage.hide() self.nextButton.show() def enterFarewell(self, goingBackAllowed): self.farewellPage.show() if goingBackAllowed: self.prevButton.show() else: self.prevButton.hide() self.nextButton.hide() self.partyPlannerHead.reparentTo(self.farewellPage) self.partyPlannerHead.startBlink() self.partyPlannerHead.startLookAround() self.nametagNP.reparentTo(self.farewellPage) self.chatNP.reparentTo(self.farewellPage) def exitFarewell(self): self.farewellPage.hide() self.nextButton.show() self.prevButton.show() self.partyPlannerHead.stopBlink() self.partyPlannerHead.stopLookAround() def load(self): self.frame = DirectFrame(parent=aspect2d, geom=self.gui.find('**/background'), relief=None, scale=0.85, pos=(0.05, 0.0, 0.1)) self.titleScale = TTLocalizer.PPtitleScale self._createNavButtons() self.welcomePage = self._createWelcomePage() self.welcomePage.hide() self.datePage = self._createDatePage() self.datePage.hide() self.timePage = self._createTimePage() self.timePage.hide() self.guestPage = self._createGuestPage() self.guestPage.hide() self.partyEditorPage = self._createPartyEditorPage() self.partyEditorPage.hide() self.invitationPage = self._createInvitationPage() self.invitationPage.hide() self.farewellPage = self._createFarewellPage() self.farewellPage.hide() return def _createNavButtons(self): self.quitButton = DirectButton(parent=self.frame, relief=None, geom=(self.gui.find('**/cancelButton_up'), self.gui.find('**/cancelButton_down'), self.gui.find('**/cancelButton_rollover')), command=self.__acceptExit) self.nextButton = DirectButton(parent=self.frame, relief=None, geom=(self.gui.find('**/bottomNext_button/nextButton_up'), self.gui.find('**/bottomNext_button/nextButton_down'), self.gui.find('**/bottomNext_button/nextButton_rollover')), command=self.__nextItem, state=DirectGuiGlobals.DISABLED) self.prevButton = DirectButton(parent=self.frame, relief=None, geom=(self.gui.find('**/bottomPrevious_button/previousButton_up'), self.gui.find('**/bottomPrevious_button/previousButton_down'), self.gui.find('**/bottomPrevious_button/previousButton_rollover')), command=self.__prevItem, state=DirectGuiGlobals.DISABLED) self.currentItem = None return def __createNametag(self, parent): if self.nametagGroup == None: self.nametagGroup = NametagGroup() self.nametagGroup.setFont(OTPGlobals.getInterfaceFont()) self.nametagGroup.setActive(0) self.nametagGroup.setAvatar(self.partyPlannerHead) self.nametagGroup.manage(base.marginManager) self.nametagGroup.setColorCode(self.nametagGroup.CCNonPlayer) self.nametagGroup.getNametag2d().setContents(0) self.nametagNode = NametagFloat2d() self.nametagNode.setContents(Nametag.CName) self.nametagGroup.addNametag(self.nametagNode) self.nametagGroup.setName(base.cr.partyManager.getPartyPlannerName()) self.nametagNP = parent.attachNewNode(self.nametagNode.upcastToPandaNode()) nametagPos = self.gui.find('**/step_01_partymanPeteNametag_locator').getPos() self.nametagNP.setPosHprScale(nametagPos[0], 0, nametagPos[2], 0, 0, 0, 0.1, 1, 0.1) self.chatNode = NametagFloat2d() self.chatNode.setContents(Nametag.CSpeech | Nametag.CThought) self.nametagGroup.addNametag(self.chatNode) self.nametagGroup.setChat(TTLocalizer.PartyPlannerInstructions, CFSpeech) self.chatNP = parent.attachNewNode(self.chatNode.upcastToPandaNode()) chatPos = self.gui.find('**/step_01_partymanPeteText_locator').getPos() self.chatNP.setPosHprScale(chatPos[0], 0, chatPos[2], 0, 0, 0, 0.08, 1, 0.08) return def clearNametag(self): if self.nametagGroup != None: self.nametagGroup.unmanage(base.marginManager) self.nametagGroup.removeNametag(self.nametagNode) self.nametagGroup.removeNametag(self.chatNode) self.nametagNP.removeNode() self.chatNP.removeNode() del self.nametagNP del self.chatNP del self.nametagNode del self.chatNode self.nametagGroup.setAvatar(NodePath()) self.nametagGroup = None return def _createWelcomePage(self): self.nametagGroup = None page = DirectFrame(self.frame) page.setName('PartyPlannerWelcomePage') self.welcomeTitleLabel = DirectLabel(parent=page, relief=None, text=TTLocalizer.PartyPlannerWelcomeTitle, pos=self.gui.find('**/title_locator').getPos(), scale=self.titleScale) self.partyPlannerHead = ToonHead.ToonHead() partyPlannerStyle = base.cr.partyManager.getPartyPlannerStyle() self.partyPlannerHead.setupHead(partyPlannerStyle, forGui=True) self.partyPlannerHead.setPos(self.gui.find('**/step_01_partymanPete_locator').getPos()) animal = partyPlannerStyle.getAnimal() if animal == 'cat' or animal == 'pig': headScale = 0.4 elif animal == 'dog' or animal == 'bear': headScale = 0.45 elif animal == 'rabbit': headScale = 0.35 else: headScale = 0.3 self.partyPlannerHead.setScale(headScale) self.partyPlannerHead.setH(180.0) self.partyPlannerHead.reparentTo(page) self.__createNametag(page) return page def _createDatePage(self): page = DirectFrame(self.frame) page.setName('PartyPlannerDatePage') self.createDateTitleLabel = DirectLabel(parent=page, relief=None, text=TTLocalizer.PartyPlannerDateTitle, pos=self.gui.find('**/title_locator').getPos(), scale=self.titleScale) pos = self.gui.find('**/step_06_sendInvitation_locator').getPos() self.makePartyNowButton = DirectButton(parent=page, relief=None, geom=(self.gui.find('**/send_up'), self.gui.find('**/send_down'), self.gui.find('**/send_rollover')), text=TTLocalizer.PartyPlannerPartyNow, text_pos=(pos[0], pos[2]), text_scale=0.05, command=self.__doMakePartyNow) curServerDate = base.cr.toontownTimeManager.getCurServerDateTime() self.calendarGuiMonth = CalendarGuiMonth(page, curServerDate, scale=0.95, pos=(-0.05, 0.0, -0.33), dayClickCallback=self._dayClickCallback, onlyFutureDaysClickable=True) return page def __doMakePartyNow(self): self.request('Invitation') def _dayClickCallback(self, calendarGuiDay): self.selectedCalendarGuiDay = calendarGuiDay self.nextButton['state'] = DirectGuiGlobals.NORMAL self.makePartyNowButton.hide() self.nextButton.show() def alterPartyTime(self, year = None, month = None, day = None, hour = None, minute = None): self.partyTime = datetime(year=self.positiveTime('year', year), month=self.positiveTime('month', month), day=self.positiveTime('day', day), hour=self.positiveTime('hour', hour), minute=self.positiveTime('minute', minute), tzinfo=self.partyTime.tzinfo) def positiveTime(self, type, amount): if amount is None: return getattr(self.partyTime, type) if type == 'hour' or type == 'minute': if amount < 0: return self.timeTypeToMaxValue[type] + 1 + self.timeTypeToChangeAmount[type][1] elif amount > self.timeTypeToMaxValue[type]: return 0 return amount def _createTimePage(self): page = DirectFrame(self.frame) page.setName('PartyPlannerTimePage') self.createTimeTitleLabel = DirectLabel(parent=page, relief=None, text=TTLocalizer.PartyPlannerTimeTitle, pos=self.gui.find('**/title_locator').getPos(), scale=self.titleScale) self.clockImage = DirectFrame(parent=page, relief=None, geom=self.gui.find('**/toontownTime_background')) self.timePageToontownLabel = DirectLabel(parent=page, relief=None, text=TTLocalizer.PartyPlannerTimeToontown, pos=self.gui.find('**/step_03_toontown_locator').getPos(), scale=0.15, text_fg=(1.0, 0.0, 0.0, 1.0), text_font=ToontownGlobals.getSignFont()) self.timePageTimeLabel = DirectLabel(parent=page, relief=None, text=TTLocalizer.PartyPlannerTimeTime, pos=self.gui.find('**/step_03_time_locator').getPos(), scale=0.15, text_fg=(1.0, 0.0, 0.0, 1.0), text_font=ToontownGlobals.getSignFont()) self.timePageRecapLabel = DirectLabel(parent=page, relief=None, text=TTLocalizer.PartyPlannerTimeRecap, pos=self.gui.find('**/step_03_partyDateAndTime_locator').getPos(), scale=0.09) self.timePageRecapToontownTimeLabel1 = DirectLabel(parent=page, relief=None, text=TTLocalizer.PartyPlannerTimeToontownTime, pos=self.gui.find('**/step_03_toontownTime_locator').getPos(), scale=0.06) self.timePageRecapToontownTimeLabel2 = DirectLabel(parent=page, relief=None, text='%s' % PartyUtils.formatDateTime(self.partyTime), pos=self.gui.find('**/step_03_toontownDateAndTime_loactor').getPos(), textMayChange=True, scale=0.06) self.timePageRecapLocalTimeLabel = DirectLabel(parent=page, relief=None, text='%s%s' % (TTLocalizer.PartyPlannerTimeLocalTime, PartyUtils.formatDateTime(self.partyTime, inLocalTime=True)), pos=self.gui.find('**/step_03_localDateAndTime_loactor').getPos(), textMayChange=True, scale=0.06, text_fg=(1.0, 0.0, 0.0, 1.0)) self.timeInputHourLabel, self.timeInputHourUpButton, self.timeInputHourDownButton = self.getTimeWidgets(page, 'hour') self.timeInputMinuteLabel, self.timeInputMinuteUpButton, self.timeInputMinuteDownButton = self.getTimeWidgets(page, 'minute') self.timeInputAmPmLabel, self.timeInputAmPmUpButton, self.timeInputAmPmDownButton = self.getTimeWidgets(page, 'ampm') self.timePagecolonLabel = DirectLabel(parent=page, relief=None, text=':', pos=self.gui.find('**/step_03_colon_locator').getPos(), scale=0.15) return page def getTimeWidgets(self, page, type): if type == 'ampm': data = self.getCurrentAmPm() else: data = getattr(self.partyTime, type) if data == 0 and type == 'minute': data = '00' else: if type == 'hour': data = data % 12 if data == 0: data = 12 data = '%d' % data label = DirectLabel(parent=page, relief=None, text='%s' % data, textMayChange=True, pos=self.gui.find('**/step_03_%s_locator' % type).getPos(), scale=0.12) def changeValue(self, amount): if type == 'ampm': self.alterPartyTime(hour=(self.partyTime.hour + 12) % 24) newAmount = self.getCurrentAmPm() label['text'] = newAmount else: if type == 'hour': newAmount = getattr(self.partyTime, type) + amount newAmount = newAmount % 12 if self.timeInputAmPmLabel['text'] == TTLocalizer.PartyTimeFormatMeridiemPM: newAmount = newAmount % 12 + 12 self.alterPartyTime(hour=newAmount) elif type == 'minute': newAmount = getattr(self.partyTime, type) + amount self.alterPartyTime(minute=newAmount) else: PartyPlanner.notify.error('Invalid type for changeValue in PartyPlanner: %s' % type) newAmount = getattr(self.partyTime, type) if newAmount < 10 and type == 'minute': label['text'] = '0%d' % newAmount else: if type == 'hour': newAmount = newAmount % 12 if newAmount == 0: newAmount = 12 label['text'] = '%d' % newAmount self.timePageRecapToontownTimeLabel2['text'] = '%s' % PartyUtils.formatDateTime(self.partyTime) self.timePageRecapLocalTimeLabel['text'] = '%s%s' % (TTLocalizer.PartyPlannerTimeLocalTime, PartyUtils.formatDateTime(self.partyTime, inLocalTime=True)) upButton = DirectButton(parent=page, relief=None, geom=(self.gui.find('**/%sButtonUp_up' % type), self.gui.find('**/%sButtonUp_down' % type), self.gui.find('**/%sButtonUp_rollover' % type)), command=changeValue, extraArgs=[self, self.timeTypeToChangeAmount[type][0]]) downButton = DirectButton(parent=page, relief=None, geom=(self.gui.find('**/%sButtonDown_up' % type), self.gui.find('**/%sButtonDown_down' % type), self.gui.find('**/%sButtonDown_rollover' % type)), command=changeValue, extraArgs=[self, self.timeTypeToChangeAmount[type][1]]) return (label, upButton, downButton) def getCurrentAmPm(self): if self.partyTime.hour < 12: return TTLocalizer.PartyTimeFormatMeridiemAM else: return TTLocalizer.PartyTimeFormatMeridiemPM def _createGuestPage(self): page = DirectFrame(self.frame) page.setName('PartyPlannerGuestPage') self.guestTitleLabel = DirectLabel(parent=page, relief=None, text=TTLocalizer.PartyPlannerGuestTitle, pos=self.gui.find('**/title_locator').getPos(), scale=self.titleScale) self.guestBackgroundLabel = DirectLabel(parent=page, relief=None, image=self.gui.find('**/guestListBackground_flat'), scale=(1.2, 1.0, 1.0)) self.friendList = ScrolledFriendList(page, self.gui, makeItemsCheckBoxes=True) if len(base.localAvatar.friendsList) == 0: self.noFriends = True else: self.noFriends = False for friendPair in base.localAvatar.friendsList: self.friendList.addFriend(determineFriendName(friendPair), friendPair[0]) self.friendList.scrollTo(0) pos = self.gui.find('**/step_04_partyWillBe_locator').getPos() self.publicPrivateLabel = DirectLabel(parent=page, relief=None, text=TTLocalizer.PartyPlannerPublicPrivateLabel, text_align=TextNode.ACenter, text_scale=0.065, pos=pos) self.publicDescriptionLabel = DirectLabel(parent=page, relief=None, text=TTLocalizer.PartyPlannerPublicDescription, text_align=TextNode.ACenter, text_scale=TTLocalizer.PPpbulicDescriptionLabel, pos=(pos[0] - 0.52, pos[1], pos[2])) self.publicDescriptionLabel.stash() self.privateDescriptionLabel = DirectLabel(parent=page, relief=None, text=TTLocalizer.PartyPlannerPrivateDescription, text_align=TextNode.ACenter, text_scale=TTLocalizer.PPprivateDescriptionLabel, pos=(pos[0] + 0.55, pos[1], pos[2])) self.privateDescriptionLabel.stash() pos = self.gui.find('**/step_04_public_locator').getPos() self.publicButton = DirectButton(parent=page, relief=None, geom=(self.gui.find('**/publicButton_up'), self.gui.find('**/publicButton_down'), self.gui.find('**/publicButton_rollover'), self.gui.find('**/publicButton_inactive')), text=TTLocalizer.PartyPlannerPublic, text_pos=(pos[0], pos[2]), text_scale=TTLocalizer.PPpublicButton, command=self.__doTogglePublicPrivate) self.publicButton['state'] = DirectGuiGlobals.DISABLED self.publicButton.bind(DirectGuiGlobals.ENTER, self.__enterPublic) self.publicButton.bind(DirectGuiGlobals.EXIT, self.__exitPublic) pos = self.gui.find('**/step_04_private_locator').getPos() self.privateButton = DirectButton(parent=page, relief=None, geom=(self.gui.find('**/privateButton_up'), self.gui.find('**/privateButton_down'), self.gui.find('**/privateButton_rollover'), self.gui.find('**/privateButton_inactive')), text=TTLocalizer.PartyPlannerPrivate, text_pos=(pos[0], pos[2]), text_scale=TTLocalizer.PPprivateButton, command=self.__doTogglePublicPrivate) self.privateButton.bind(DirectGuiGlobals.ENTER, self.__enterPrivate) self.privateButton.bind(DirectGuiGlobals.EXIT, self.__exitPrivate) self.checkAllButton = DirectButton(parent=page, relief=None, geom=(self.gui.find('**/checkAllButton_up'), self.gui.find('**/checkAllButton_down'), self.gui.find('**/checkAllButton_rollover')), command=self.__doCheckAll) self.uncheckAllButton = DirectButton(parent=page, relief=None, geom=(self.gui.find('**/uncheckAllButton_up'), self.gui.find('**/uncheckAllButton_down'), self.gui.find('**/uncheckAllButton_rollover')), command=self.__doUncheckAll) return page def __doCheckAll(self): for friendBox in self.friendList['items']: friendBox['indicatorValue'] = True def __doUncheckAll(self): for friendBox in self.friendList['items']: friendBox['indicatorValue'] = False def __enterPrivate(self, mouseEvent): self.privateDescriptionLabel.unstash() def __exitPrivate(self, mouseEvent): self.privateDescriptionLabel.stash() def __enterPublic(self, mouseEvent): self.publicDescriptionLabel.unstash() def __exitPublic(self, mouseEvent): self.publicDescriptionLabel.stash() def __doTogglePublicPrivate(self): if self.isPrivate: self.isPrivate = False self.privateButton['state'] = DirectGuiGlobals.NORMAL self.publicButton['state'] = DirectGuiGlobals.DISABLED else: self.isPrivate = True self.privateButton['state'] = DirectGuiGlobals.DISABLED self.publicButton['state'] = DirectGuiGlobals.NORMAL def _createPartyEditorPage(self): page = DirectFrame(self.frame) page.setName('PartyPlannerEditorPage') self.LayoutTitleLabel = DirectLabel(parent=page, relief=None, text=TTLocalizer.PartyPlannerEditorTitle, pos=self.gui.find('**/title_locator').getPos() + Point3(0.0, 0.0, 0.075), scale=self.titleScale) self.costLabel = DirectLabel(parent=page, pos=(-0.74, 0.0, 0.17), relief=None, text=TTLocalizer.PartyPlannerTotalCost % 0, text_align=TextNode.ACenter, scale=TTLocalizer.PPcostLabel, textMayChange=True) self.partyGridBackground = DirectFrame(parent=page, relief=None, geom=self.gui.find('**/partyGrid_flat')) self.partyGroundsLabel = DirectLabel(parent=page, relief=None, text=TTLocalizer.PartyPlannerPartyGrounds, text_font=ToontownGlobals.getSignFont(), text_fg=VBase4(1.0, 0.0, 0.0, 1.0), text_scale=TTLocalizer.PPpartyGroundsLabel, pos=self.gui.find('**/step_05_partyGrounds_text_locator').getPos(), scale=0.1) self.activityBackground = DirectFrame(parent=page, relief=None, geom=self.gui.find('**/activitiesDecorations_flat1'), pos=(0.0, 0.0, 0.04)) pos = self.gui.find('**/step_05_instructions_locator').getPos() self.instructionLabel = DirectLabel(parent=page, relief=None, text=' ', text_pos=(pos[0], pos[2]), text_scale=TTLocalizer.PPinstructionLabel, textMayChange=True, geom=self.gui.find('**/instructions_flat')) self.elementTitleLabel = DirectLabel(parent=page, relief=None, text=' ', pos=self.gui.find('**/step_05_activitiesName_text_locator').getPos() + Point3(0.0, 0.0, 0.04), text_scale=TTLocalizer.PPelementTitleLabel, textMayChange=True) self.elementPriceNode = TextNode('ElementPrice') self.elementPriceNode.setAlign(TextNode.ALeft) self.elementPriceNode.setTextColor(0.0, 0.0, 0.0, 1.0) self.elementPriceNode.setFont(ToontownGlobals.getToonFont()) self.elementPrice = page.attachNewNode(self.elementPriceNode) self.elementPrice.setScale(TTLocalizer.PPelementPriceNode) self.elementPrice.setPos(self.gui.find('**/step_05_activityPrice_text_locator').getPos() + Point3(-0.02, 0.0, 0.04)) self.elementDescriptionNode = TextNode('ElementDescription') self.elementDescriptionNode.setAlign(TextNode.ACenter) self.elementDescriptionNode.setWordwrap(8) self.elementDescriptionNode.setFont(ToontownGlobals.getToonFont()) self.elementDescriptionNode.setTextColor(0.0, 0.0, 0.0, 1.0) self.elementDescription = page.attachNewNode(self.elementDescriptionNode) self.elementDescription.setScale(TTLocalizer.PPelementDescription) self.elementDescription.setPos(self.gui.find('**/step_05_activityDescription_text_locator').getPos() + Point3(0.0, 0.0, 0.04)) self.totalMoney = base.localAvatar.getTotalMoney() catalogGui = loader.loadModel('phase_5.5/models/gui/catalog_gui') self.beanBank = DirectLabel(parent=page, relief=None, text=str(self.totalMoney), text_align=TextNode.ARight, text_scale=0.075, text_fg=(0.95, 0.95, 0, 1), text_shadow=(0, 0, 0, 1), text_pos=(0.495, -0.53), text_font=ToontownGlobals.getSignFont(), textMayChange=True, image=catalogGui.find('**/bean_bank'), image_scale=(0.65, 0.65, 0.65), scale=0.9, pos=(-0.75, 0.0, 0.6)) catalogGui.removeNode() del catalogGui self.accept(localAvatar.uniqueName('moneyChange'), self.__moneyChange) self.accept(localAvatar.uniqueName('bankMoneyChange'), self.__moneyChange) self.partyEditor = PartyEditor(self, page) self.partyEditor.request('Hidden') pos = self.gui.find('**/step_05_add_text_locator').getPos() self.elementBuyButton = DirectButton(parent=page, relief=None, text=TTLocalizer.PartyPlannerBuy, text_pos=(pos[0], pos[2]), text_scale=TTLocalizer.PPelementBuyButton, geom=(self.gui.find('**/add_up'), self.gui.find('**/add_down'), self.gui.find('**/add_rollover')), geom3_color=VBase4(0.5, 0.5, 0.5, 1.0), textMayChange=True, pos=(0.0, 0.0, 0.04), command=self.partyEditor.buyCurrentElement) self.okWithPartyGroundsLayoutEvent = 'okWithPartyGroundsLayoutEvent' self.accept(self.okWithPartyGroundsLayoutEvent, self.okWithPartyGroundsLayout) self.okWithGroundsGui = TTDialog.TTGlobalDialog(dialogName=self.uniqueName('PartyEditorOkGui'), doneEvent=self.okWithPartyGroundsLayoutEvent, message=TTLocalizer.PartyPlannerOkWithGroundsLayout, style=TTDialog.YesNo, okButtonText=OTPLocalizer.DialogYes, cancelButtonText=OTPLocalizer.DialogNo) self.okWithGroundsGui.doneStatus = '' self.okWithGroundsGui.hide() return page def okWithPartyGroundsLayout(self): self.okWithGroundsGui.hide() if self.okWithGroundsGui.doneStatus == 'ok': self.__nextItem() def setNextButtonState(self, enabled): if enabled: self.nextButton['state'] = DirectGuiGlobals.NORMAL self.nextButton.show() else: self.nextButton['state'] = DirectGuiGlobals.DISABLED self.nextButton.hide() def _createInvitationPage(self): self.__handleHolidays() page = DirectFrame(self.frame) page.setName('PartyPlannerInvitationPage') self.invitationTitleLabel = DirectLabel(parent=page, relief=None, text=TTLocalizer.PartyPlannerConfirmTitle, textMayChange=True, pos=self.gui.find('**/title_locator').getPos(), scale=self.titleScale) self.invitationBackground = DirectFrame(parent=page, relief=None, geom=self.gui.find('**/invitationBackground')) self.inviteVisual = InviteVisual(page) self.selectedInviteThemeLabel = DirectLabel(parent=page, relief=None, pos=self.gui.find('**/step_06_theme_locator').getPos(), text='', text_scale=0.06, textMayChange=True) self.nextThemeButton = DirectButton(parent=page, relief=None, geom=(self.gui.find('**/topNext_button/nextButton_up'), self.gui.find('**/topNext_button/nextButton_down'), self.gui.find('**/topNext_button/nextButton_rollover')), command=self.__nextTheme) self.prevThemeButton = DirectButton(parent=page, relief=None, geom=(self.gui.find('**/topPrevious_button/previousButton_up'), self.gui.find('**/topPrevious_button/previousButton_down'), self.gui.find('**/topPrevious_button/previousButton_rollover')), command=self.__prevTheme) pos = self.gui.find('**/step_06_sendInvitation_locator').getPos() self.inviteButton = DirectButton(parent=page, relief=None, geom=(self.gui.find('**/send_up'), self.gui.find('**/send_down'), self.gui.find('**/send_rollover')), text=TTLocalizer.PartyPlannerInviteButton, textMayChange=True, text_scale=0.05, text_pos=(pos[0], pos[2]), command=self.__handleComplete) return page def __handleHolidays(self): self.inviteThemes = list(range(len(PartyGlobals.InviteTheme))) if hasattr(base.cr, 'newsManager') and base.cr.newsManager: holidayIds = base.cr.newsManager.getHolidayIdList() if ToontownGlobals.VALENTINES_DAY not in holidayIds: self.inviteThemes.remove(PartyGlobals.InviteTheme.Valentoons) if ToontownGlobals.VICTORY_PARTY_HOLIDAY not in holidayIds: self.inviteThemes.remove(PartyGlobals.InviteTheme.VictoryParty) if ToontownGlobals.WINTER_DECORATIONS not in holidayIds and ToontownGlobals.WACKY_WINTER_DECORATIONS not in holidayIds: self.inviteThemes.remove(PartyGlobals.InviteTheme.Winter) def _createFarewellPage(self): page = DirectFrame(self.frame) page.setName('PartyPlannerFarewellPage') self.confirmTitleLabel = DirectLabel(parent=page, relief=None, text=TTLocalizer.PartyPlannerConfirmationAllOkTitle, textMayChange=True, pos=self.gui.find('**/title_locator').getPos(), scale=self.titleScale) pos = self.gui.find('**/step_07_close_text_locator').getPos() self.closePlannerButton = DirectButton(parent=page, relief=None, geom=(self.gui.find('**/close_up'), self.gui.find('**/close_down'), self.gui.find('**/close_rollover')), text=TTLocalizer.PartyPlannerClosePlanner, text_scale=0.055, text_pos=(pos[0], pos[2]), command=self.__acceptExit) return page def close(self): self.ignore('addPartyResponseReceived') self.ignore(localAvatar.uniqueName('moneyChange')) self.ignore(localAvatar.uniqueName('bankMoneyChange')) self.timeInputHourUpButton.destroy() self.timeInputHourDownButton.destroy() self.timeInputMinuteUpButton.destroy() self.timeInputMinuteDownButton.destroy() self.timeInputAmPmUpButton.destroy() self.timeInputAmPmDownButton.destroy() self.privateButton.destroy() self.publicButton.destroy() self.makePartyNowButton.destroy() self.checkAllButton.destroy() self.uncheckAllButton.destroy() self.elementBuyButton.destroy() self.nextThemeButton.destroy() self.prevThemeButton.destroy() self.inviteButton.destroy() self.closePlannerButton.destroy() self.ignore(self.okWithPartyGroundsLayoutEvent) if hasattr(self, 'okWithGroundsGui'): self.okWithGroundsGui.cleanup() del self.okWithGroundsGui if hasattr(self, 'frame') and not self.frame.isEmpty(): messenger.send(self.doneEvent) self.hide() self.cleanup() self.friendList.removeAndDestroyAllItems() self.friendList.destroy() self.calendarGuiMonth.destroy() self.frame.destroy() self.partyPlannerHead.delete() self.partyPlannerHead.removeNode() self.clearNametag() self.partyEditor.request('Cleanup') self.partyEditor = None self.destroy() del self return def __handleComplete(self): self.inviteButton['state'] = DirectGuiGlobals.DISABLED self.prevButton['state'] = DirectGuiGlobals.DISABLED endTime = self.partyTime + self.partyDuration hostId = base.localAvatar.doId self.partyActivities = self.partyEditor.partyEditorGrid.getActivitiesOnGrid() decorations = self.partyEditor.partyEditorGrid.getDecorationsOnGrid() invitees = self.getInvitees() self.accept('addPartyResponseReceived', self.processAddPartyResponse) base.cr.partyManager.sendAddParty(hostId, self.partyTime.strftime('%Y-%m-%d %H:%M:%S'), endTime.strftime('%Y-%m-%d %H:%M:%S'), self.isPrivate, self.currentInvitationTheme, self.partyActivities, decorations, invitees) def getInvitees(self): invitees = [] for friendBox in self.friendList['items']: if friendBox['indicatorValue']: invitees.append(friendBox.getPythonTag('id')) return invitees def processAddPartyResponse(self, hostId, errorCode): PartyPlanner.notify.debug('processAddPartyResponse : hostId=%d errorCode=%s' % (hostId, PartyGlobals.AddPartyErrorCode.getString(errorCode))) goingBackAllowed = False if errorCode == PartyGlobals.AddPartyErrorCode.AllOk: goingBackAllowed = False self.confirmTitleLabel['text'] = TTLocalizer.PartyPlannerConfirmationAllOkTitle if self.noFriends or len(self.getInvitees()) == 0: confirmRecapText = TTLocalizer.PartyPlannerConfirmationAllOkTextNoFriends else: confirmRecapText = TTLocalizer.PartyPlannerConfirmationAllOkText elif errorCode == PartyGlobals.AddPartyErrorCode.ValidationError: self.confirmTitleLabel['text'] = TTLocalizer.PartyPlannerConfirmationErrorTitle confirmRecapText = TTLocalizer.PartyPlannerConfirmationValidationErrorText elif errorCode == PartyGlobals.AddPartyErrorCode.DatabaseError: self.confirmTitleLabel['text'] = TTLocalizer.PartyPlannerConfirmationErrorTitle confirmRecapText = TTLocalizer.PartyPlannerConfirmationDatabaseErrorText elif errorCode == PartyGlobals.AddPartyErrorCode.TooManyHostedParties: goingBackAllowed = False self.confirmTitleLabel['text'] = TTLocalizer.PartyPlannerConfirmationErrorTitle confirmRecapText = TTLocalizer.PartyPlannerConfirmationTooManyText self.nametagGroup.setChat(confirmRecapText, CFSpeech) self.request('Farewell', goingBackAllowed) def __acceptExit(self): PartyPlanner.notify.debug('__acceptExit') if hasattr(self, 'frame'): self.hide() messenger.send(self.doneEvent) def __nextItem(self): messenger.send('wakeup') if self.state == 'PartyEditor' and self.okWithGroundsGui.doneStatus != 'ok': self.okWithGroundsGui.show() return if self.state == 'PartyEditor' and self.noFriends: self.request('Date') self.selectedCalendarGuiDay = None self.calendarGuiMonth.clearSelectedDay() return if self.state == 'Guests': self.selectedCalendarGuiDay = None self.calendarGuiMonth.clearSelectedDay() if self.state == 'Time': if self.partyTime < base.cr.toontownTimeManager.getCurServerDateTime(): self.okChooseFutureTimeEvent = 'okChooseFutureTimeEvent' self.acceptOnce(self.okChooseFutureTimeEvent, self.okChooseFutureTime) self.chooseFutureTimeDialog = TTDialog.TTGlobalDialog(dialogName=self.uniqueName('chooseFutureTimeDialog'), doneEvent=self.okChooseFutureTimeEvent, message=TTLocalizer.PartyPlannerChooseFutureTime, style=TTDialog.Acknowledge) self.chooseFutureTimeDialog.show() return self.requestNext() return def okChooseFutureTime(self): if hasattr(self, 'chooseFutureTimeDialog'): self.chooseFutureTimeDialog.cleanup() del self.chooseFutureTimeDialog if hasattr(self, 'okChooseFutureTimeEvent'): self.ignore(self.okChooseFutureTimeEvent) def __prevItem(self): messenger.send('wakeup') if self.state == 'Date' and self.noFriends: self.request('PartyEditor') return if self.state == 'Invitation' and self.selectedCalendarGuiDay is None: self.request('Guests') return self.requestPrev() return def __moneyChange(self, newMoney): if hasattr(self, 'totalMoney'): self.totalMoney = base.localAvatar.getTotalMoney() if hasattr(self, 'beanBank'): self.beanBank['text'] = str(int(self.totalMoney))
class ScrolledButtonsList(DirectObject): """ A class to display a list of selectable buttons. It is displayed using scrollable window (DirectScrolledFrame). """ def __init__(self, parent=None, frameSize=(.8,1.2), buttonTextColor=(1,1,1,1), font=None, itemScale=.045, itemTextScale=0.85, itemTextZ=0, command=None, contextMenu=None, autoFocus=0, colorChange=1, colorChangeDuration=1, newItemColor=globals.colors['guiblue1'], rolloverColor=globals.colors['guiyellow'], suppressMouseWheel=1, modifier='control'): self.mode = None self.focusButton=None self.command=command self.contextMenu=contextMenu self.autoFocus=autoFocus self.colorChange=colorChange self.colorChangeDuration=colorChangeDuration*.5 self.newItemColor=newItemColor self.rolloverColor=rolloverColor self.rightClickTextColors=(Vec4(0,1,0,1),Vec4(0,35,100,1)) self.font=font if font: self.fontHeight=font.getLineHeight() else: self.fontHeight=TextNode.getDefaultFont().getLineHeight() self.fontHeight*=1.2 # let's enlarge font height a little self.xtraSideSpace=.2*self.fontHeight self.itemTextScale=itemTextScale self.itemTextZ=itemTextZ self.buttonTextColor=buttonTextColor self.suppressMouseWheel=suppressMouseWheel self.modifier=modifier self.buttonsList=[] self.numItems=0 self.__eventReceivers={} # DirectScrolledFrame to hold items self.itemScale=itemScale self.itemVertSpacing=self.fontHeight*self.itemScale self.frameWidth,self.frameHeight=frameSize # I set canvas' Z size smaller than the frame to avoid the auto-generated vertical slider bar self.childrenFrame = DirectScrolledFrame( parent=parent,pos=(-self.frameWidth*.5,0,.5*self.frameHeight), relief=DGG.GROOVE, state=DGG.NORMAL, # to create a mouse watcher region frameSize=(0, self.frameWidth, -self.frameHeight, 0), frameColor=(0,0,0,.7), canvasSize=(0, 0, -self.frameHeight*.5, 0), borderWidth=(0.01,0.01), manageScrollBars=0, enableEdit=0, suppressMouse=0, sortOrder=1000 ) # the real canvas is "self.childrenFrame.getCanvas()", # but if the frame is hidden since the beginning, # no matter how I set the canvas Z pos, the transform would be resistant, # so just create a new node under the canvas to be my canvas self.canvas=self.childrenFrame.getCanvas().attachNewNode('myCanvas') # slider background SliderBG=DirectFrame( parent=self.childrenFrame,frameSize=(-.025,.025,-self.frameHeight,0), frameColor=(0,0,0,.7), pos=(-.03,0,0),enableEdit=0, suppressMouse=0) # slider thumb track sliderTrack = DirectFrame( parent=SliderBG, relief=DGG.FLAT, #state=DGG.NORMAL, frameColor=(1,1,1,.2), frameSize=(-.015,.015,-self.frameHeight+.01,-.01), enableEdit=0, suppressMouse=0) # page up self.pageUpRegion=DirectFrame( parent=SliderBG, relief=DGG.FLAT, state=DGG.NORMAL, frameColor=(1,.8,.2,.1), frameSize=(-.015,.015,0,0), enableEdit=0, suppressMouse=0) self.pageUpRegion.setAlphaScale(0) self.pageUpRegion.bind(DGG.B1PRESS,self.__startScrollPage,[-1]) self.pageUpRegion.bind(DGG.WITHIN,self.__continueScrollUp) self.pageUpRegion.bind(DGG.WITHOUT,self.__suspendScrollUp) # page down self.pageDnRegion=DirectFrame( parent=SliderBG, relief=DGG.FLAT, state=DGG.NORMAL, frameColor=(1,.8,.2,.1), frameSize=(-.015,.015,0,0), enableEdit=0, suppressMouse=0) self.pageDnRegion.setAlphaScale(0) self.pageDnRegion.bind(DGG.B1PRESS,self.__startScrollPage,[1]) self.pageDnRegion.bind(DGG.WITHIN,self.__continueScrollDn) self.pageDnRegion.bind(DGG.WITHOUT,self.__suspendScrollDn) self.pageUpDnSuspended=[0,0] # slider thumb self.vertSliderThumb=DirectButton(parent=SliderBG, relief=DGG.FLAT, frameColor=(1,1,1,.6), frameSize=(-.015,.015,0,0), enableEdit=0, suppressMouse=0, rolloverSound=None, clickSound=None) self.vertSliderThumb.bind(DGG.B1PRESS,self.__startdragSliderThumb) self.vertSliderThumb.bind(DGG.WITHIN,self.__enteringThumb) self.vertSliderThumb.bind(DGG.WITHOUT,self.__exitingThumb) self.oldPrefix=base.buttonThrowers[0].node().getPrefix() self.sliderThumbDragPrefix='draggingSliderThumb-' # GOD & I DAMN IT !!! # These things below don't work well if the canvas has a lot of buttons. # So I end up checking the mouse region every frame by myself using a continuous task. # self.accept(DGG.WITHIN+self.childrenFrame.guiId,self.__enteringFrame) # self.accept(DGG.WITHOUT+self.childrenFrame.guiId,self.__exitingFrame) self.isMouseInRegion=False self.mouseOutInRegionCommand=(self.__exitingFrame,self.__enteringFrame) taskMgr.doMethodLater(.2,self.__getFrameRegion,'getFrameRegion') def __getFrameRegion(self,t): for g in range(base.mouseWatcherNode.getNumGroups()): region=base.mouseWatcherNode.getGroup(g).findRegion(self.childrenFrame.guiId) if region!=None: self.frameRegion=region taskMgr.add(self.__mouseInRegionCheck,'mouseInRegionCheck') break def __mouseInRegionCheck(self,t): """ check if the mouse is within or without the scrollable frame, and upon within or without, run the provided command """ if not base.mouseWatcherNode.hasMouse(): return Task.cont m=base.mouseWatcherNode.getMouse() bounds=self.frameRegion.getFrame() inRegion=bounds[0]<m[0]<bounds[1] and bounds[2]<m[1]<bounds[3] if self.isMouseInRegion==inRegion: return Task.cont self.isMouseInRegion=inRegion self.mouseOutInRegionCommand[inRegion]() return Task.cont def __startdragSliderThumb(self,m=None): if self.mode != None: if hasattr(self.mode, 'enableMouseCamControl') == 1: if self.mode.enableMouseCamControl == 1: self.mode.game.app.disableMouseCamControl() mpos=base.mouseWatcherNode.getMouse() parentZ=self.vertSliderThumb.getParent().getZ(render2d) sliderDragTask=taskMgr.add(self.__dragSliderThumb,'dragSliderThumb') sliderDragTask.ZposNoffset=mpos[1]-self.vertSliderThumb.getZ(render2d)+parentZ # sliderDragTask.mouseX=base.winList[0].getPointer(0).getX() self.oldPrefix=base.buttonThrowers[0].node().getPrefix() base.buttonThrowers[0].node().setPrefix(self.sliderThumbDragPrefix) self.acceptOnce(self.sliderThumbDragPrefix+'mouse1-up',self.__stopdragSliderThumb) def __dragSliderThumb(self,t): if not base.mouseWatcherNode.hasMouse(): return mpos=base.mouseWatcherNode.getMouse() # newY=base.winList[0].getPointer(0).getY() self.__updateCanvasZpos((t.ZposNoffset-mpos[1])/self.canvasRatio) # base.winList[0].movePointer(0, t.mouseX, newY) return Task.cont def __stopdragSliderThumb(self,m=None): if self.mode != None: if hasattr(self.mode, 'enableMouseCamControl') == 1: if self.mode.enableMouseCamControl == 1: self.mode.game.app.enableMouseCamControl() taskMgr.remove('dragSliderThumb') self.__stopScrollPage() base.buttonThrowers[0].node().setPrefix(self.oldPrefix) if self.isMouseInRegion: self.mouseOutInRegionCommand[self.isMouseInRegion]() def __startScrollPage(self,dir,m): self.oldPrefix=base.buttonThrowers[0].node().getPrefix() base.buttonThrowers[0].node().setPrefix(self.sliderThumbDragPrefix) self.acceptOnce(self.sliderThumbDragPrefix+'mouse1-up',self.__stopdragSliderThumb) t=taskMgr.add(self.__scrollPage,'scrollPage',extraArgs=[int((dir+1)*.5),dir*.01/self.canvasRatio]) self.pageUpDnSuspended=[0,0] def __scrollPage(self,dir,scroll): if not self.pageUpDnSuspended[dir]: self.__scrollCanvas(scroll) return Task.cont def __stopScrollPage(self,m=None): taskMgr.remove('scrollPage') def __suspendScrollUp(self,m=None): self.pageUpRegion.setAlphaScale(0) self.pageUpDnSuspended[0]=1 def __continueScrollUp(self,m=None): if taskMgr.hasTaskNamed('dragSliderThumb'): return self.pageUpRegion.setAlphaScale(1) self.pageUpDnSuspended[0]=0 def __suspendScrollDn(self,m=None): self.pageDnRegion.setAlphaScale(0) self.pageUpDnSuspended[1]=1 def __continueScrollDn(self,m=None): if taskMgr.hasTaskNamed('dragSliderThumb'): return self.pageDnRegion.setAlphaScale(1) self.pageUpDnSuspended[1]=0 def __suspendScrollPage(self,m=None): self.__suspendScrollUp() self.__suspendScrollDn() def __enteringThumb(self,m=None): self.vertSliderThumb['frameColor']=(1,1,1,1) self.__suspendScrollPage() def __exitingThumb(self,m=None): self.vertSliderThumb['frameColor']=(1,1,1,.6) def __scrollCanvas(self,scroll): if self.vertSliderThumb.isHidden() or self.buttonsList == []: return self.__updateCanvasZpos(self.canvas.getZ()+scroll) def __updateCanvasZpos(self,Zpos): newZ=clampScalar(Zpos, .0, self.canvasLen-self.frameHeight+.015) self.canvas.setZ(newZ) thumbZ=-newZ*self.canvasRatio self.vertSliderThumb.setZ(thumbZ) self.pageUpRegion['frameSize']=(-.015,.015,thumbZ-.01,-.01) self.pageDnRegion['frameSize']=(-.015,.015,-self.frameHeight+.01,thumbZ+self.vertSliderThumb['frameSize'][2]) def __adjustCanvasLength(self,numItem): self.canvasLen=float(numItem)*self.itemVertSpacing self.canvasRatio=(self.frameHeight-.015)/(self.canvasLen+.01) if self.canvasLen<=self.frameHeight-.015: canvasZ=.0 self.vertSliderThumb.hide() self.pageUpRegion.hide() self.pageDnRegion.hide() self.canvasLen=self.frameHeight-.015 else: canvasZ=self.canvas.getZ() self.vertSliderThumb.show() self.pageUpRegion.show() self.pageDnRegion.show() self.__updateCanvasZpos(canvasZ) self.vertSliderThumb['frameSize']=(-.015,.015,-self.frameHeight*self.canvasRatio,-.01) thumbZ=self.vertSliderThumb.getZ() self.pageUpRegion['frameSize']=(-.015,.015,thumbZ-.01,-.01) self.pageDnRegion['frameSize']=(-.015,.015,-self.frameHeight+.01,thumbZ+self.vertSliderThumb['frameSize'][2]) def __acceptAndIgnoreWorldEvent(self,event,command,extraArgs=[]): receivers=messenger.whoAccepts(event) if receivers is None: self.__eventReceivers[event]={} else: self.__eventReceivers[event]=receivers.copy() for r in self.__eventReceivers[event].keys(): if type(r) != types.TupleType: r.ignore(event) self.accept(event,command,extraArgs) def __ignoreAndReAcceptWorldEvent(self,events): for event in events: self.ignore(event) if self.__eventReceivers.has_key(event): for r, method_xtraArgs_persist in self.__eventReceivers[event].items(): if type(r) != types.TupleType: messenger.accept(event,r,*method_xtraArgs_persist) self.__eventReceivers[event]={} def __enteringFrame(self,m=None): # sometimes the WITHOUT event for page down region doesn't fired, # so directly suspend the page scrolling here self.__suspendScrollPage() BTprefix=base.buttonThrowers[0].node().getPrefix() if BTprefix==self.sliderThumbDragPrefix: return self.inOutBTprefix=BTprefix if self.suppressMouseWheel: self.__acceptAndIgnoreWorldEvent(self.inOutBTprefix+'wheel_up', command=self.__scrollCanvas, extraArgs=[-.07]) self.__acceptAndIgnoreWorldEvent(self.inOutBTprefix+'wheel_down', command=self.__scrollCanvas, extraArgs=[.07]) else: self.accept(self.inOutBTprefix+self.modifier+'-wheel_up',self.__scrollCanvas, [-.07]) self.accept(self.inOutBTprefix+self.modifier+'-wheel_down',self.__scrollCanvas, [.07]) def __exitingFrame(self,m=None): if not hasattr(self,'inOutBTprefix'): return if self.suppressMouseWheel: self.__ignoreAndReAcceptWorldEvent( ( self.inOutBTprefix+'wheel_up', self.inOutBTprefix+'wheel_down', ) ) else: self.ignore(self.inOutBTprefix+self.modifier+'-wheel_up') self.ignore(self.inOutBTprefix+self.modifier+'-wheel_down') def __setFocusButton(self,button,item): if self.focusButton: self.restoreNodeButton2Normal() self.focusButton=button self.highlightNodeButton() if callable(self.command) and button in self.buttonsList: # run user command and pass the selected item, it's index, and the button self.command(item,self.buttonsList.index(button),button) def __rightPressed(self,button,m): self.__isRightIn=True # text0 : normal # text1 : pressed # text2 : rollover # text3 : disabled button._DirectGuiBase__componentInfo['text2'][0].setColorScale(self.rightClickTextColors[self.focusButton==button]) button.bind(DGG.B3RELEASE,self.__rightReleased,[button]) button.bind(DGG.WITHIN,self.__rightIn,[button]) button.bind(DGG.WITHOUT,self.__rightOut,[button]) def __rightIn(self,button,m): self.__isRightIn=True button._DirectGuiBase__componentInfo['text2'][0].setColorScale(self.rightClickTextColors[self.focusButton==button]) def __rightOut(self,button,m): self.__isRightIn=False button._DirectGuiBase__componentInfo['text2'][0].setColorScale(Vec4(1,1,1,1)) def __rightReleased(self,button,m): button.unbind(DGG.B3RELEASE) button.unbind(DGG.WITHIN) button.unbind(DGG.WITHOUT) button._DirectGuiBase__componentInfo['text2'][0].setColorScale(self.rolloverColor) if not self.__isRightIn: return if callable(self.contextMenu): # run user command and pass the selected item, it's index, and the button self.contextMenu(button['extraArgs'][1],self.buttonsList.index(button),button) def scrollToBottom(self): ##for i in range(0,self.numItems): self.__scrollCanvas(1) def selectButton(self, button, item): self.__setFocusButton(button, item) def restoreNodeButton2Normal(self): """ stop highlighting item """ if self.focusButton != None: #self.focusButton['text_fg']=(1,1,1,1) self.focusButton['frameColor']=(0,0,0,0) def highlightNodeButton(self,idx=None): """ highlight the item """ if idx is not None: self.focusButton=self.buttonsList[idx] #self.focusButton['text_fg']=(.01,.01,.01,1) # nice dark blue. don't mess with the text fg color though! we want it custom self.focusButton['frameColor']=(0,.3,.8,1) def clear(self): """ clear the list """ for c in self.buttonsList: c.remove() self.buttonsList=[] self.focusButton=None self.numItems=0 def addItem(self,text,extraArgs=None,atIndex=None,textColorName=None): """ add item to the list text : text for the button extraArgs : the object which will be passed to user command(s) (both command and contextMenu) when the button get clicked atIndex : where to add the item <None> : put item at the end of list <integer> : put item at index <integer> <button> : put item at <button>'s index textColorName : the color name eg. 'yellow' """ textColor = self.buttonTextColor if textColorName != None: textColor = globals.colors[textColorName] button = DirectButton(parent=self.canvas, scale=self.itemScale, relief=DGG.FLAT, frameColor=(0,0,0,0),text_scale=self.itemTextScale, text=text, text_pos=(0,self.itemTextZ),text_fg=textColor, text_font=self.font, text_align=TextNode.ALeft, command=self.__setFocusButton, enableEdit=0, suppressMouse=0, rolloverSound=None,clickSound=None) #button.setMyMode(self.mode) l,r,b,t=button.getBounds() # top & bottom are blindly set without knowing where exactly the baseline is, # but this ratio fits most fonts baseline=-self.fontHeight*.25 #button['saved_color'] = textColor button['frameSize']=(l-self.xtraSideSpace,r+self.xtraSideSpace,baseline,baseline+self.fontHeight) # Zc=NodePath(button).getBounds().getCenter()[1]-self.fontHeight*.5+.25 # # Zc=button.getCenter()[1]-self.fontHeight*.5+.25 # button['frameSize']=(l-self.xtraSideSpace,r+self.xtraSideSpace,Zc,Zc+self.fontHeight) button['extraArgs']=[button,extraArgs] button._DirectGuiBase__componentInfo['text2'][0].setColorScale(self.rolloverColor) button.bind(DGG.B3PRESS,self.__rightPressed,[button]) if isinstance(atIndex,DirectButton): if atIndex.isEmpty(): atIndex=None else: index=self.buttonsList.index(atIndex) self.buttonsList.insert(index,button) if atIndex==None: self.buttonsList.append(button) index=self.numItems elif type(atIndex)==IntType: index=atIndex self.buttonsList.insert(index,button) Zpos=(-.7-index)*self.itemVertSpacing button.setPos(.02,0,Zpos) if index!=self.numItems: for i in range(index+1,self.numItems+1): self.buttonsList[i].setZ(self.buttonsList[i],-self.fontHeight) self.numItems+=1 self.__adjustCanvasLength(self.numItems) if self.autoFocus: self.focusViewOnItem(index) if self.colorChange: Sequence( button.colorScaleInterval(self.colorChangeDuration,self.newItemColor,globals.colors['guiblue3']), button.colorScaleInterval(self.colorChangeDuration,Vec4(1,1,1,1),self.newItemColor) ).start() def focusViewOnItem(self,idx): """ Scroll the window so the newly added item will be displayed in the middle of the window, if possible. """ Zpos=(idx+.7)*self.itemVertSpacing-self.frameHeight*.5 self.__updateCanvasZpos(Zpos) def setAutoFocus(self,b): """ set auto-view-focus state of newly added item """ self.autoFocus=b def index(self,button): """ get the index of button """ if not button in self.buttonsList: return None return self.buttonsList.index(button) def getNumItems(self): """ get the current number of items on the list """ return self.numItems def disableItem(self,i): if not 0<=i<self.numItems: print 'DISABLING : invalid index (%s)' %i return self.buttonsList[i]['state']=DGG.DISABLED self.buttonsList[i].setColorScale(.3,.3,.3,1) def enableItem(self,i): if not 0<=i<self.numItems: print 'ENABLING : invalid index (%s)' %i return self.buttonsList[i]['state']=DGG.NORMAL self.buttonsList[i].setColorScale(1,1,1,1) def removeItem(self,index): if not 0<=index<self.numItems: print 'REMOVAL : invalid index (%s)' %index return if self.numItems==0: return if self.focusButton==self.buttonsList[index]: self.focusButton=None self.buttonsList[index].removeNode() del self.buttonsList[index] self.numItems-=1 for i in range(index,self.numItems): self.buttonsList[i].setZ(self.buttonsList[i],self.fontHeight) self.__adjustCanvasLength(self.numItems) def destroy(self): self.clear() self.__exitingFrame() self.ignoreAll() self.childrenFrame.removeNode() taskMgr.remove('mouseInRegionCheck') def hide(self): self.childrenFrame.hide() self.isMouseInRegion=False self.__exitingFrame() taskMgr.remove('mouseInRegionCheck') def show(self): self.childrenFrame.show() if not hasattr(self,'frameRegion'): taskMgr.doMethodLater(.2,self.__getFrameRegion,'getFrameRegion') elif not taskMgr.hasTaskNamed('mouseInRegionCheck'): taskMgr.add(self.__mouseInRegionCheck,'mouseInRegionCheck') def toggleVisibility(self): if self.childrenFrame.isHidden(): self.show() else: self.hide() def setMyMode(self, myMode): self.mode = myMode
class PartyEditor(DirectObject, FSM): """ This class creates the grid and scrolled list needed for players to drag and drop activities and decorations onto their party grounds. """ notify = directNotify.newCategory("PartyEditor") def __init__(self, partyPlanner, parent): FSM.__init__(self, self.__class__.__name__) self.partyPlanner = partyPlanner self.parent = parent self.partyEditorGrid = PartyEditorGrid(self) self.currentElement = None self.defaultTransitions = { "Hidden": ["Idle", "Cleanup"], "Idle": ["DraggingElement", "Hidden", "Cleanup"], "DraggingElement": ["Idle", "DraggingElement", "Hidden", "Cleanup"], "Cleanup": [], } self.initElementList() self.initPartyClock() self.initTrashCan() def initElementList(self): self.activityIconsModel = loader.loadModel( "phase_4/models/parties/eventSignIcons") self.decorationModels = loader.loadModel( "phase_4/models/parties/partyDecorations") pos = self.partyPlanner.gui.find( "**/step_05_activitiesIcon_locator").getPos() self.elementList = DirectScrolledList( parent=self.parent, relief=None, # inc and dec are DirectButtons decButton_image=( self.partyPlanner.gui.find("**/activitiesButtonUp_up"), self.partyPlanner.gui.find("**/activitiesButtonUp_down"), self.partyPlanner.gui.find("**/activitiesButtonUp_rollover"), self.partyPlanner.gui.find("**/activitiesButtonUp_inactive"), ), decButton_relief=None, decButton_pos=(-0.05, 0.0, -0.38), incButton_image=( self.partyPlanner.gui.find("**/activitiesButtonDown_up"), self.partyPlanner.gui.find("**/activitiesButtonDown_down"), self.partyPlanner.gui.find("**/activitiesButtonDown_rollover"), self.partyPlanner.gui.find("**/activitiesButtonDown_inactive"), ), incButton_relief=None, incButton_pos=(-0.05, 0.0, -0.94), # itemFrame is a DirectFrame itemFrame_pos=(pos[0], pos[1], pos[2] + 0.04), itemFrame_relief=None, # each item is a button with text on it numItemsVisible=1, items=[], ) for activityId in PartyGlobals.PartyEditorActivityOrder: if activityId in PartyGlobals.VictoryPartyActivityIds: holidayIds = base.cr.newsManager.getHolidayIdList() if ToontownGlobals.VICTORY_PARTY_HOLIDAY in holidayIds: pele = PartyEditorListElement(self, activityId) self.elementList.addItem(pele) elif activityId in PartyGlobals.VictoryPartyReplacementActivityIds: holidayIds = base.cr.newsManager.getHolidayIdList() if not ToontownGlobals.VICTORY_PARTY_HOLIDAY in holidayIds: pele = PartyEditorListElement(self, activityId) self.elementList.addItem(pele) else: pele = PartyEditorListElement(self, activityId) self.elementList.addItem(pele) if activityId == PartyGlobals.ActivityIds.PartyClock: self.partyClockElement = pele for decorationId in PartyGlobals.DecorationIds: decorName = PartyGlobals.DecorationIds.getString(decorationId) if (decorName == "HeartTarget") \ or (decorName == "HeartBanner") \ or (decorName == "FlyingHeart"): holidayIds = base.cr.newsManager.getHolidayIdList() if ToontownGlobals.VALENTINES_DAY in holidayIds: pele = PartyEditorListElement(self, decorationId, isDecoration=True) self.elementList.addItem(pele) elif decorationId in PartyGlobals.VictoryPartyDecorationIds: holidayIds = base.cr.newsManager.getHolidayIdList() if ToontownGlobals.VICTORY_PARTY_HOLIDAY in holidayIds: pele = PartyEditorListElement(self, decorationId, isDecoration=True) self.elementList.addItem(pele) elif decorationId in PartyGlobals.VictoryPartyReplacementDecorationIds: holidayIds = base.cr.newsManager.getHolidayIdList() if not ToontownGlobals.VICTORY_PARTY_HOLIDAY in holidayIds: pele = PartyEditorListElement(self, decorationId, isDecoration=True) self.elementList.addItem(pele) else: pele = PartyEditorListElement(self, decorationId, isDecoration=True) self.elementList.addItem(pele) self.elementList.refresh() self.elementList['command'] = self.scrollItemChanged def initPartyClock(self): self.partyClockElement.buyButtonClicked((8, 7)) def initTrashCan(self): trashcanGui = loader.loadModel("phase_3/models/gui/trashcan_gui") self.trashCanButton = DirectButton( parent=self.parent, relief=None, pos=Point3(*PartyGlobals.TrashCanPosition), scale=PartyGlobals.TrashCanScale, geom=( trashcanGui.find("**/TrashCan_CLSD"), trashcanGui.find("**/TrashCan_OPEN"), trashcanGui.find("**/TrashCan_RLVR"), trashcanGui.find("**/TrashCan_RLVR"), ), command=self.trashCanClicked, ) self.trashCanButton.bind(DirectGuiGlobals.ENTER, self.mouseEnterTrash) self.trashCanButton.bind(DirectGuiGlobals.EXIT, self.mouseExitTrash) self.mouseOverTrash = False self.oldInstructionText = "" self.trashCanLastClickedTime = 0 def scrollItemChanged(self): if not self.elementList["items"]: # we are probably closing the gui, do nothing return self.currentElement = self.elementList["items"][ self.elementList.getSelectedIndex()] self.elementList["items"][ self.elementList.getSelectedIndex()].elementSelectedFromList() if self.elementList["items"][ self.elementList.getSelectedIndex()].isDecoration: self.partyPlanner.instructionLabel[ "text"] = TTLocalizer.PartyPlannerEditorInstructionsClickedElementDecoration else: self.partyPlanner.instructionLabel[ "text"] = TTLocalizer.PartyPlannerEditorInstructionsClickedElementActivity def listElementClicked(self): self.request("DraggingElement") def listElementReleased(self): self.request("Idle", True) def trashCanClicked(self): currentTime = time.time() # Check for double click, if so, clear the party grounds if currentTime - self.trashCanLastClickedTime < 0.2: self.clearPartyGrounds() self.trashCanLastClickedTime = time.time() def clearPartyGrounds(self): for item in self.elementList["items"]: item.clearPartyGrounds() self.initPartyClock() if self.currentElement: self.currentElement.checkSoldOutAndPaidStatusAndAffordability() def buyCurrentElement(self): if self.currentElement: purchaseSuccessful = self.currentElement.buyButtonClicked() if purchaseSuccessful: # The buying and placement of the item was successful self.handleMutuallyExclusiveActivities() pass else: # The buying and placement of the item was not successful self.partyPlanner.instructionLabel[ "text"] = TTLocalizer.PartyPlannerEditorInstructionsNoRoom def mouseEnterTrash(self, mouseEvent): self.mouseOverTrash = True self.oldInstructionText = self.partyPlanner.instructionLabel["text"] self.partyPlanner.instructionLabel[ "text"] = TTLocalizer.PartyPlannerEditorInstructionsTrash def mouseExitTrash(self, mouseEvent): self.mouseOverTrash = False self.partyPlanner.instructionLabel["text"] = self.oldInstructionText ### FSM Methods ### def enterHidden(self): PartyEditor.notify.debug("Enter Hidden") def exitHidden(self): PartyEditor.notify.debug("Exit Hidden") def enterIdle(self, fromDragging=False): PartyEditor.notify.debug("Enter Idle") if not fromDragging: self.elementList.scrollTo(0) self.elementList["items"][0].elementSelectedFromList() self.currentElement = self.elementList["items"][ self.elementList.getSelectedIndex()] self.currentElement.checkSoldOutAndPaidStatusAndAffordability() self.partyPlanner.instructionLabel[ "text"] = TTLocalizer.PartyPlannerEditorInstructionsIdle self.updateCostsAndBank() self.handleMutuallyExclusiveActivities() def handleMutuallyExclusiveActivities(self): """Smartly removed the older activity and inform the user.""" mutSet = self.getMutuallyExclusiveActivities() if not mutSet: return # our mutset doesn't tell us which one is older currentActivities = self.partyEditorGrid.getActivitiesElementsOnGrid() lastActivity = self.partyEditorGrid.lastActivityIdPlaced for act in currentActivities: if (act.id in mutSet) and not (lastActivity == act.id): act.removeFromGrid() removedName = TTLocalizer.PartyActivityNameDict[ act.id]["editor"] addedName = TTLocalizer.PartyActivityNameDict[lastActivity][ "editor"] instr = TTLocalizer.PartyPlannerEditorInstructionsRemoved % \ {"removed" : removedName, "added" : addedName} self.partyPlanner.instructionLabel["text"] = instr self.updateCostsAndBank() # deliberately no break here, in case they manage to # get 3 jukeboxes into the editor somehow def getMutuallyExclusiveActivities(self): """Return the set of activities on the grid that are mutually exclusive, None otherwise.""" # create a set of activity Ids currentActivities = self.partyEditorGrid.getActivitiesOnGrid() actSet = Set([]) for act in currentActivities: actSet.add(act[0]) result = None for mutuallyExclusiveTuples in PartyGlobals.MutuallyExclusiveActivities: mutSet = Set(mutuallyExclusiveTuples) inter = mutSet.intersection(actSet) if len(inter) > 1: result = inter break return result def updateCostsAndBank(self): """ We need to update the total cost of the party and what they will have left in their bank. """ currentActivities = self.partyEditorGrid.getActivitiesOnGrid() currentDecorations = self.partyEditorGrid.getDecorationsOnGrid() newCost = 0 for elementTuple in currentActivities: newCost += PartyGlobals.ActivityInformationDict[ elementTuple[0]]["cost"] for elementTuple in currentDecorations: newCost += PartyGlobals.DecorationInformationDict[ elementTuple[0]]["cost"] self.partyPlanner.costLabel[ "text"] = TTLocalizer.PartyPlannerTotalCost % newCost if len(currentActivities) > 0 or len(currentDecorations) > 0: self.partyPlanner.setNextButtonState(enabled=True) else: self.partyPlanner.setNextButtonState(enabled=False) self.partyPlanner.totalCost = newCost self.partyPlanner.beanBank["text"] = str( int(self.partyPlanner.totalMoney - self.partyPlanner.totalCost)) def exitIdle(self): PartyEditor.notify.debug("Exit Idle") def enterDraggingElement(self): PartyEditor.notify.debug("Enter DraggingElement") if self.currentElement.isDecoration: self.partyPlanner.instructionLabel[ "text"] = TTLocalizer.PartyPlannerEditorInstructionsDraggingDecoration else: self.partyPlanner.instructionLabel[ "text"] = TTLocalizer.PartyPlannerEditorInstructionsDraggingActivity def exitDraggingElement(self): PartyEditor.notify.debug("Exit DraggingElement") def enterCleanup(self): PartyEditor.notify.debug("Enter Cleanup") self.partyEditorGrid.destroy() self.elementList.removeAndDestroyAllItems() self.elementList.destroy() self.trashCanButton.unbind(DirectGuiGlobals.ENTER) self.trashCanButton.unbind(DirectGuiGlobals.EXIT) self.trashCanButton.destroy() def exitCleanup(self): PartyEditor.notify.debug("Exit Cleanup")
class LaffShopGui(DirectFrame): def __init__(self): DirectFrame.__init__(self, parent=aspect2d, relief=None, geom=DGG.getDefaultDialogGeom(), geom_color=ToontownGlobals.GlobalDialogColor, geom_scale=(1.33, 1, 1.3), pos=(0, 0, 0), text='', text_scale=0.07, text_pos=(0, 0.475)) self.initialiseoptions(LaffShopGui) self.additionalLaff = 0 self.timer = ToontownTimer.ToontownTimer() self.timer.reparentTo(aspect2d) self.timer.posInTopRightCorner() self.timer.countdown(LaffRestockGlobals.TIMER_SECONDS, self.__cancel, [LaffRestockGlobals.TIMER_END]) self.setupButtons() self.bindButtons() self.laffMeter = LaffMeter.LaffMeter(base.localAvatar.style, base.localAvatar.getHp(), base.localAvatar.getMaxHp()) self.laffMeter.reparentTo(self) self.laffMeter.setPos(0, 0, 0.065) self.laffMeter.setScale(0.13) self.__updateLaffMeter(1) def setupButtons(self): buttons = loader.loadModel('phase_3/models/gui/dialog_box_buttons_gui') arrowGui = loader.loadModel('phase_3/models/gui/create_a_toon_gui') arrowImageList = (arrowGui.find('**/CrtATn_R_Arrow_UP'), arrowGui.find('**/CrtATn_R_Arrow_DN'), arrowGui.find('**/CrtATn_R_Arrow_RLVR'), arrowGui.find('**/CrtATn_R_Arrow_UP')) self.cancelButton = DirectButton(parent=self, relief=None, image=(buttons.find('**/CloseBtn_UP'), buttons.find('**/CloseBtn_DN'), buttons.find('**/CloseBtn_Rllvr')), pos=(-0.2, 0, -0.5), text=OTPLocalizer.lCancel, text_scale=0.06, text_pos=(0, -0.1), command=self.__cancel, extraArgs=[LaffRestockGlobals.USER_CANCEL]) self.okButton = DirectButton(parent=self, relief=None, image=(buttons.find('**/ChtBx_OKBtn_UP'), buttons.find('**/ChtBx_OKBtn_DN'), buttons.find('**/ChtBx_OKBtn_Rllvr')), pos=(0.2, 0, -0.5), text=OTPLocalizer.lOK, text_scale=0.06, text_pos=(0, -0.1), command=self.__restock) self.upArrow = DirectButton(parent=self, relief=None, image=arrowImageList, image_scale=(1, 1, 1), image3_color=Vec4(0.6, 0.6, 0.6, 0.25), pos=(0.2, 0, -0.265)) self.downArrow = DirectButton(parent=self, relief=None, image=arrowImageList, image_scale=(-1, 1, 1), image3_color=Vec4(0.6, 0.6, 0.6, 0.25), pos=(-0.2, 0, -0.265)) buttons.removeNode() arrowGui.removeNode() def bindButtons(self): self.downArrow.bind(DGG.B1PRESS, self.__taskUpdate, extraArgs=[-1]) self.downArrow.bind(DGG.B1RELEASE, self.__taskDone) self.upArrow.bind(DGG.B1PRESS, self.__taskUpdate, extraArgs=[1]) self.upArrow.bind(DGG.B1RELEASE, self.__taskDone) def destroy(self): self.ignoreAll() if self.timer: self.timer.destroy() taskMgr.remove(self.taskName('runLaffCounter')) DirectFrame.destroy(self) def __cancel(self, state): self.destroy() messenger.send('laffShopDone', [state, 0]) def __restock(self): self.destroy() messenger.send('laffShopDone', [LaffRestockGlobals.RESTOCK, self.additionalLaff]) def __updateLaffMeter(self, amount): self.additionalLaff += amount hitLimit = 0 newLaff = base.localAvatar.getHp() + self.additionalLaff if (newLaff - 1) <= base.localAvatar.getHp(): self.downArrow['state'] = DGG.DISABLED hitLimit = 1 else: self.downArrow['state'] = DGG.NORMAL if newLaff >= base.localAvatar.getMaxHp(): self.upArrow['state'] = DGG.DISABLED hitLimit = 1 else: self.upArrow['state'] = DGG.NORMAL cost = self.additionalLaff * ToontownGlobals.CostPerLaffRestock self['text'] = TTLocalizer.RestockAskMessage % (self.additionalLaff, cost) if cost > base.localAvatar.getTotalMoney(): self.okButton['state'] = DGG.DISABLED self['text'] += TTLocalizer.RestockNoMoneyGuiMessage else: self.okButton['state'] = DGG.NORMAL self.laffMeter.hp = newLaff self.laffMeter.start() return hitLimit def __runTask(self, task): if task.time - task.prevTime < task.delayTime: return Task.cont else: task.delayTime = max(0.05, task.delayTime * 0.75) task.prevTime = task.time hitLimit = self.__updateLaffMeter(task.delta) return Task.done if hitLimit else Task.cont def __taskDone(self, event): messenger.send('wakeup') taskMgr.remove(self.taskName('runLaffCounter')) def __taskUpdate(self, delta, event): messenger.send('wakeup') task = Task(self.__runTask) task.delayTime = 0.4 task.prevTime = 0.0 task.delta = delta hitLimit = self.__updateLaffMeter(delta) if not hitLimit: taskMgr.add(task, self.taskName('runLaffCounter'))
class GloveShopGui: def __init__(self): self.index = 0 self.id = time.time() self.lastGlove = base.localAvatar.style.gloveColor self.timer = ToontownTimer.ToontownTimer() self.timer.reparentTo(aspect2d) self.timer.posInTopRightCorner() self.timer.countdown(GloveNPCGlobals.TIMER_SECONDS, self.__exit, [GloveNPCGlobals.TIMER_END]) self.setupButtons() self.bindButtons() self.__updateIndex(0) def setupButtons(self): gui = loader.loadModel('phase_3/models/gui/tt_m_gui_mat_mainGui') arrowImage = (gui.find('**/tt_t_gui_mat_shuffleArrowUp'), gui.find('**/tt_t_gui_mat_shuffleArrowDown')) buttonImage = (gui.find('**/tt_t_gui_mat_shuffleUp'), gui.find('**/tt_t_gui_mat_shuffleDown')) self.title = DirectLabel(aspect2d, relief=None, text=TTLocalizer.GloveGuiTitle, text_fg=(0, 1, 0, 1), text_scale=0.15, text_font=ToontownGlobals.getSignFont(), pos=(0, 0, -0.30), text_shadow=(1, 1, 1, 1)) self.notice = DirectLabel(aspect2d, relief=None, text='', text_fg=(1, 0, 0, 1), text_scale=0.11, text_font=ToontownGlobals.getSignFont(), pos=(0, 0, -0.45), text_shadow=(1, 1, 1, 1)) self.color = DirectLabel(aspect2d, relief=None, text='', text_scale=0.11, text_font=ToontownGlobals.getSignFont(), pos=(0, 0, -0.70), text_shadow=(1, 1, 1, 1)) self.buyButton = DirectButton(aspect2d, relief=None, image=buttonImage, text=TTLocalizer.GloveGuiBuy, text_font=ToontownGlobals.getInterfaceFont(), text_scale=0.11, text_pos=(0, -0.02), pos=(-0.60, 0, -0.90), text_fg=(1, 1, 1, 1), text_shadow=(0, 0, 0, 1), command=self.__exit, extraArgs=[GloveNPCGlobals.CHANGE]) self.cancelButton = DirectButton(aspect2d, relief=None, image=buttonImage, text=TTLocalizer.lCancel, text_font=ToontownGlobals.getInterfaceFont(), text_scale=0.11, text_pos=(0, -0.02), pos=(0.60, 0, -0.90), text_fg=(1, 1, 1, 1), text_shadow=(0, 0, 0, 1), command=self.__exit, extraArgs=[GloveNPCGlobals.USER_CANCEL]) self.downArrow = DirectButton(aspect2d, relief=None, image=arrowImage, pos=(-0.60, 0, -0.66)) self.upArrow = DirectButton(aspect2d, relief=None, image=arrowImage, pos=(0.60, 0, -0.66), scale=-1) gui.removeNode() def bindButtons(self): self.downArrow.bind(DGG.B1PRESS, self.__taskUpdate, extraArgs=[-1]) self.downArrow.bind(DGG.B1RELEASE, self.__taskDone) self.upArrow.bind(DGG.B1PRESS, self.__taskUpdate, extraArgs=[1]) self.upArrow.bind(DGG.B1RELEASE, self.__taskDone) def destroy(self): if self.timer: self.timer.destroy() if not hasattr(self, 'title'): return # TODO: DirectDialog-ify self.title.destroy() self.notice.destroy() self.color.destroy() self.buyButton.destroy() self.cancelButton.destroy() self.downArrow.destroy() self.upArrow.destroy() del self.title del self.notice del self.color del self.buyButton del self.cancelButton del self.downArrow del self.upArrow taskMgr.remove('runGloveCounter-%s' % self.id) def setClientGlove(self, color): dna = base.localAvatar.style dna.gloveColor = color base.localAvatar.setDNA(dna) def __exit(self, state): self.destroy() self.setClientGlove(self.lastGlove) messenger.send('gloveShopDone', [state, self.index if state == GloveNPCGlobals.CHANGE else 0]) def __updateIndex(self, offset): self.index += offset hitLimit = 0 if self.index <= 0: self.downArrow['state'] = DGG.DISABLED hitLimit = 1 else: self.downArrow['state'] = DGG.NORMAL if (self.index + 1) >= len(TTLocalizer.NumToColor): self.upArrow['state'] = DGG.DISABLED hitLimit = 1 else: self.upArrow['state'] = DGG.NORMAL if self.lastGlove == self.index: self.buyButton['state'] = DGG.DISABLED self.notice['text'] = TTLocalizer.GloveGuiSameColor else: self.buyButton['state'] = DGG.NORMAL self.notice['text'] = TTLocalizer.GloveGuiNotice % ToontownGlobals.GloveCost self.color['text'] = TTLocalizer.NumToColor[self.index] self.color['text_fg'] = ToonDNA.allColorsList[self.index] self.setClientGlove(self.index) return hitLimit def __runTask(self, task): if task.time - task.prevTime < task.delayTime: return Task.cont else: task.delayTime = max(0.05, task.delayTime * 0.75) task.prevTime = task.time hitLimit = self.__updateIndex(task.delta) return Task.done if hitLimit else Task.cont def __taskDone(self, event): messenger.send('wakeup') taskMgr.remove('runGloveCounter-%s' % self.id) def __taskUpdate(self, delta, event): messenger.send('wakeup') task = Task(self.__runTask) task.delayTime = 0.4 task.prevTime = 0.0 task.delta = delta hitLimit = self.__updateIndex(delta) if not hitLimit: taskMgr.add(task, 'runGloveCounter-%s' % self.id)
class DirectWindow( DirectFrame ): def __init__( self , pos = ( -.5, .5) , title = 'Title' , bgColor = (.5,.5,.5,1) , buttonColor = (1,1,1,1) #( .6, .6, .6, 1 ) #, minSize = ( .5, .5 ) #, maxSize = ( 1, 1 ) , minWindowSize = (0,0) , maxWindowSize = (10000,10000) , virtualSize = (1,1) , windowBorderTextureFiles = [ DEFAULT_TITLE_TEXTURE_LEFT , DEFAULT_TITLE_TEXTURE_CENTER , DEFAULT_TITLE_TEXTURE_RIGHT , DEFAULT_RESIZE_GEOM ] , windowBorderGeomFiles = [ DEFAULT_TITLE_GEOM_RIGHT ] , windowColors = [ ( 1, 1, 1, 1 ) , ( 1, 1, 1, 1 ) , ( 1, 1, 1, 1 ) , ( 1, 1, 1, 1 ) ] , borderSize = 0.01 , dragbarSize = 0.05 , parent=None): self.windowPos = pos self.minWindowSize = minWindowSize self.maxWindowSize = maxWindowSize self.virtualSize = virtualSize self.borderSize = borderSize self.dragbarSize = dragbarSize if parent is None: parent=aspect2d self.parent=parent self.previousSize = (10,10) self.collapsed = False # maybe we should check if aspect2d doesnt already contain the aspect2dMouseNode self.mouseNode = self.parent.attachNewNode( 'aspect2dMouseNode', sort = 999999 ) taskMgr.add( self.mouseNodeTask, 'mouseNodeTask' ) windowBorderTextures = list() for windowBorder in windowBorderTextureFiles: if windowBorder is not None: mdlFile = loader.loadTexture(windowBorder) windowBorderTextures.append(mdlFile) else: windowBorderTextures.append(None) windowBorderGeoms = list() for windowGeom in windowBorderGeomFiles: if windowGeom is not None: mdlFile = loader.loadModel(windowGeom) mdls = ( mdlFile.find('**/**-default'), mdlFile.find('**/**-click'), mdlFile.find('**/**-rollover'), mdlFile.find('**/**-disabled') ) windowBorderGeoms.append(mdls) else: windowBorderGeoms.append((None,None,None,None,),) # the main window we want to move around self.parentWindow = DirectFrame( parent=self.parent, pos=(self.windowPos[0], 0, self.windowPos[1]), #frameSize=# is defined in resize scale=(1, 1, -1), frameColor=bgColor, borderWidth=(0, 0), relief=DGG.FLAT, sortOrder=1, ) # header of the window (drag&drop with it) # the title part of the window, drag around to move the window self.headerParent = DirectButton( parent=self.parentWindow, pos=(0, 0, 0), #frameSize=# is defined in resize scale=(1, 1, self.dragbarSize), frameColor=(1, 1, 1, 1), borderWidth=(0, 0), relief=DGG.FLAT, ) self.headerParent.bind(DGG.B1PRESS,self.startWindowDrag) # images in the headerParent self.headerCenter = DirectFrame( parent=self.headerParent, pos=(0, 0, 1), #frameSize=# is defined in resize scale=(1,1,-1), frameColor=windowColors[1], frameTexture=windowBorderTextures[1], borderWidth=(0, 0), relief=DGG.FLAT, ) self.headerLeft = DirectFrame( parent=self.headerParent, pos=(0, 0, 1), frameSize=(0, self.dragbarSize, 0, 1), scale=(1,1,-1), frameColor=windowColors[0], frameTexture=windowBorderTextures[0], borderWidth=(0, 0), relief=DGG.FLAT, ) # collapse button self.headerRight = DirectButton( parent=self.headerParent, #pos=# is defined in resize frameSize=(0, self.dragbarSize, 0, 1), scale=(1,1,-1), frameColor=windowColors[2], #frameTexture=windowBorderTextures[2], borderWidth=(0, 0), relief=DGG.FLAT, command=self.toggleCollapsed, geom=windowBorderGeoms[0], geom_scale=(self.dragbarSize,1,1) ) # the resize button of the window self.resizeButton = DirectButton( parent=self.parentWindow, pos=(1-self.dragbarSize, 0, 1), frameSize=(0, 1, 0, 1), scale=(self.dragbarSize,1,-self.dragbarSize), frameColor=windowColors[3], frameTexture=windowBorderTextures[3], borderWidth=(0, 0), relief=DGG.FLAT, sortOrder=1, ) self.resizeButton.bind(DGG.B1PRESS,self.startResizeDrag) # text in the center of the window 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.headerCenter.attachNewNode(text) self.textNodePath.setPos(.5,0,.3) self.textNodePath.setScale(0.8*self.dragbarSize,1,0.8) if Y_INVERTED: scale = (1,1,-1) else: scale = (1,1,1) # the content part of the window, put stuff beneath # contentWindow.getCanvas() to put it into it self.contentWindow = DirectScrolledFrame( parent = self.parentWindow, #pos = # is defined in resize scale = scale, canvasSize = (0,self.virtualSize[0],0,self.virtualSize[1]), frameColor = buttonColor, relief = DGG.RAISED, borderWidth = (0,0), verticalScroll_frameSize = [0,self.dragbarSize,0,1], verticalScroll_frameTexture = loader.loadTexture( 'rightBorder.png' ), verticalScroll_incButton_frameTexture = loader.loadTexture( 'scrollDown.png' ), verticalScroll_decButton_frameTexture = loader.loadTexture( 'scrollDown.png' ), verticalScroll_thumb_frameTexture = loader.loadTexture( 'scrollBar.png' ), horizontalScroll_frameSize = [0,1,0,self.dragbarSize], horizontalScroll_frameTexture = loader.loadTexture( 'bottomBorder.png' ), horizontalScroll_incButton_frameTexture = loader.loadTexture( 'scrollDown.png' ), horizontalScroll_decButton_frameTexture = loader.loadTexture( 'scrollDown.png' ), horizontalScroll_thumb_frameTexture = loader.loadTexture( 'scrollBar.png' ), ) # child we attach should be inside the window DirectFrame.__init__( self, parent = self.contentWindow.getCanvas(), pos = (0,0,self.virtualSize[1]), scale = (1,1,1), frameSize = ( 0, self.virtualSize[0]+2*self.borderSize, 0, self.virtualSize[1] ), #frameColor = (0,0,0,1), relief = DGG.RIDGE, borderWidth = (0,0), ) self.initialiseoptions(DirectWindow) # offset then clicking on the resize button from the mouse to the resizebutton # position, required to calculate the position / scaling self.offset = None self.resizeButtonTaskName = "resizeTask-%s" % str(hash(self)) # do sizing of the window to virtualSize #self.resize( self.virtualSize[0]+2*self.borderSize # , self.virtualSize[1]+self.dragbarSize+2*self.borderSize ) self.resize(10,10) # a task that keeps a node at the position of the mouse-cursor def mouseNodeTask(self, task): if WindowManager.hasMouse(): x=WindowManager.getMouseX() y=WindowManager.getMouseY() # the mouse position is read relative to render2d, so set it accordingly self.mouseNode.setPos( render2d, x, 0, y ) return task.cont # dragging functions def startWindowDrag( self, param ): self.parentWindow.wrtReparentTo( self.mouseNode ) self.ignoreAll() self.accept( 'mouse1-up', self.stopWindowDrag ) def stopWindowDrag( self, param=None ): # this could be called even after the window has been destroyed #if self: # this is called 2 times (bug), so make sure it's not already parented to aspect2d if self.parentWindow.getParent() != self.parent: self.parentWindow.wrtReparentTo(self.parent) self.ignoreAll() # resize functions def startResizeDrag(self, param): self.offset = self.resizeButton.getPos(aspect2d) - self.mouseNode.getPos(aspect2d) taskMgr.remove( self.resizeButtonTaskName ) taskMgr.add( self.resizeButtonTask, self.resizeButtonTaskName ) self.accept( 'mouse1-up', self.stopResizeDrag,['x'] ) def resize(self,windowX,windowY): # limit max/min size of the window maxX = min(self.maxWindowSize[0], self.virtualSize[0]+2*self.borderSize) minX = max( self.dragbarSize*3, self.minWindowSize[0]) windowWidth = min( maxX, max( minX, windowX ) ) maxY = min( self.maxWindowSize[1], self.virtualSize[1]+self.dragbarSize+2*self.borderSize ) minY = max( self.dragbarSize*4, self.minWindowSize[1]) windowHeight = min( maxY, max( minY, windowY ) ) if self.collapsed: windowHeight = 2*self.dragbarSize+2*self.borderSize windowWidth = windowWidth self.contentWindow.hide() # store changed window width only self.previousSize = windowWidth, self.previousSize[1] else: self.contentWindow.show() self.previousSize = windowWidth, windowHeight # set the window size self.headerParent['frameSize'] = (0, windowWidth, 0, 1) self.headerCenter['frameSize'] = (0, windowWidth, 0, 1) self.parentWindow['frameSize'] = (0, windowWidth, 0, windowHeight) self.contentWindow['frameSize'] = (0, windowWidth-self.borderSize*2, 0, windowHeight-self.dragbarSize-2*self.borderSize) self.contentWindow.setPos(self.borderSize,0,windowHeight-self.borderSize) self.headerRight.setPos(windowWidth-self.dragbarSize, 0, 1) self.textNodePath.setPos(windowWidth/2.,0,.3) self.resizeButton.setPos(windowWidth-self.dragbarSize, 0, windowHeight) def resizeButtonTask(self, task=None): mPos = self.mouseNode.getPos(self.parentWindow) # max height, the smaller of (given maxWindowSize and real size of content and borders windowX = mPos.getX() + self.offset.getX() + self.dragbarSize windowY = mPos.getZ() - self.offset.getZ() self.resize(windowX,windowY) return task.cont def stopResizeDrag(self, param): taskMgr.remove( self.resizeButtonTaskName ) self.ignoreAll() # a bugfix for a wrong implementation def detachNode( self ): self.parentWindow.detachNode() #self. = None #DirectFrame.detachNode( self ) def removeNode( self ): self.parentWindow.removeNode() #DirectFrame.removeNode( self ) def toggleCollapsed(self,state=None): if state is None: state=not self.collapsed if state: self.collapse() else: self.uncollapse() def collapse(self): self.collapsed = True self.resize(*self.previousSize) def uncollapse(self): self.collapsed = False self.resize(*self.previousSize)