class CalendarGuiDay(DirectFrame): notify = directNotify.newCategory('CalendarGuiDay') ScrollListTextSize = 0.03 def __init__(self, parent, myDate, startDate, dayClickCallback=None, onlyFutureDaysClickable=False): self.origParent = parent self.startDate = startDate self.myDate = myDate self.dayClickCallback = dayClickCallback self.onlyFutureDaysClickable = onlyFutureDaysClickable DirectFrame.__init__(self, parent=parent) self.timedEvents = [] self.partiesInvitedToToday = [] self.hostedPartiesToday = [] self.yearlyHolidaysToday = [] self.showMarkers = base.config.GetBool('show-calendar-markers', 0) self.filter = ToontownGlobals.CalendarFilterShowAll self.load() self.createGuiObjects() self.update() def createDummyLocators(self): self.dayButtonLocator = self.attachNewNode('dayButtonLocator') self.dayButtonLocator.setX(0.1) self.dayButtonLocator.setZ(-0.05) self.numberLocator = self.attachNewNode('numberLocator') self.numberLocator.setX(0.09) self.scrollLocator = self.attachNewNode('scrollLocator') self.selectedLocator = self.attachNewNode('selectedLocator') self.selectedLocator.setX(0.11) self.selectedLocator.setZ(-0.06) def load(self): dayAsset = loader.loadModel( 'phase_4/models/parties/tt_m_gui_sbk_calendar_box') dayAsset.reparentTo(self) self.dayButtonLocator = self.find('**/loc_origin') self.numberLocator = self.find('**/loc_number') self.scrollLocator = self.find('**/loc_topLeftList') self.selectedLocator = self.find('**/loc_origin') self.todayBox = self.find('**/boxToday') self.todayBox.hide() self.selectedFrame = self.find('**/boxHover') self.selectedFrame.hide() self.defaultBox = self.find('**/boxBlank') self.scrollBottomRightLocator = self.find('**/loc_bottomRightList') self.scrollDownLocator = self.find('**/loc_scrollDown') self.attachMarker(self.scrollDownLocator) self.scrollUpLocator = self.find('**/loc_scrollUp') self.attachMarker(self.scrollUpLocator) def attachMarker(self, parent, scale=0.005, color=(1, 0, 0)): if self.showMarkers: marker = loader.loadModel('phase_3/models/misc/sphere') marker.reparentTo(parent) marker.setScale(scale) marker.setColor(*color) def createGuiObjects(self): self.dayButton = DirectButton(parent=self.dayButtonLocator, image=self.selectedFrame, relief=None, command=self.__clickedOnDay, pressEffect=1, rolloverSound=None, clickSound=None) self.numberWidget = DirectLabel( parent=self.numberLocator, relief=None, text=str(self.myDate.day), text_scale=0.04, text_align=TextNode.ACenter, text_font=ToontownGlobals.getInterfaceFont(), text_fg=Vec4(110 / 255.0, 126 / 255.0, 255 / 255.0, 1)) self.attachMarker(self.numberLocator) self.listXorigin = 0 self.listFrameSizeX = self.scrollBottomRightLocator.getX( ) - self.scrollLocator.getX() self.scrollHeight = self.scrollLocator.getZ( ) - self.scrollBottomRightLocator.getZ() self.listZorigin = self.scrollBottomRightLocator.getZ() self.listFrameSizeZ = self.scrollLocator.getZ( ) - self.scrollBottomRightLocator.getZ() self.arrowButtonXScale = 1 self.arrowButtonZScale = 1 self.itemFrameXorigin = 0 self.itemFrameZorigin = 0 self.buttonXstart = self.itemFrameXorigin + 0.21 self.gui = loader.loadModel('phase_3.5/models/gui/friendslist_gui') buttonOffSet = -0.01 incButtonPos = (0.0, 0, 0) decButtonPos = (0.0, 0, 0) itemFrameMinZ = self.listZorigin itemFrameMaxZ = self.listZorigin + self.listFrameSizeZ arrowUp = self.find('**/downScroll_up') arrowDown = self.find('**/downScroll_down') arrowHover = self.find('**/downScroll_hover') self.scrollList = DirectScrolledList( parent=self.scrollLocator, relief=None, pos=(0, 0, 0), incButton_image=(arrowUp, arrowDown, arrowHover, arrowUp), incButton_relief=None, incButton_scale=(self.arrowButtonXScale, 1, self.arrowButtonZScale), incButton_pos=incButtonPos, incButton_image3_color=Vec4(1, 1, 1, 0.2), decButton_image=(arrowUp, arrowDown, arrowHover, arrowUp), decButton_relief=None, decButton_scale=(self.arrowButtonXScale, 1, -self.arrowButtonZScale), decButton_pos=decButtonPos, decButton_image3_color=Vec4(1, 1, 1, 0.2), itemFrame_pos=(self.itemFrameXorigin, 0, -0.03), numItemsVisible=4, incButtonCallback=self.scrollButtonPressed, decButtonCallback=self.scrollButtonPressed) itemFrameParent = self.scrollList.itemFrame.getParent() self.scrollList.incButton.reparentTo(self.scrollDownLocator) self.scrollList.decButton.reparentTo(self.scrollUpLocator) arrowUp.removeNode() arrowDown.removeNode() arrowHover.removeNode() clipper = PlaneNode('clipper') clipper.setPlane(Plane(Vec3(-1, 0, 0), Point3(0.23, 0, 0))) clipNP = self.scrollList.component('itemFrame').attachNewNode(clipper) self.scrollList.component('itemFrame').setClipPlane(clipNP) return def scrollButtonPressed(self): self.__clickedOnDay() def adjustForMonth(self): curServerDate = base.cr.toontownTimeManager.getCurServerDateTime() if self.onlyFutureDaysClickable: if self.myDate.year < curServerDate.year or self.myDate.year == curServerDate.year and self.myDate.month < curServerDate.month or self.myDate.year == curServerDate.year and self.myDate.month == curServerDate.month and self.myDate.day < curServerDate.day: self.numberWidget.setColorScale(0.5, 0.5, 0.5, 0.5) self.numberWidget['state'] = DirectGuiGlobals.DISABLED else: self.numberWidget.setColorScale(1, 1, 1, 1) if self.myDate.month != self.startDate.month: self.setColorScale(0.75, 0.75, 0.75, 1.0) if self.dayClickCallback is not None: self.numberWidget['state'] = DirectGuiGlobals.DISABLED else: self.setColorScale(1, 1, 1, 1) if self.myDate.date() == curServerDate.date(): self.defaultBox.hide() self.todayBox.show() else: self.defaultBox.show() self.todayBox.hide() return def destroy(self): if self.dayClickCallback is not None: self.numberWidget.destroy() self.dayClickCallback = None self.notify.debug('desroying %s' % self.myDate) try: for item in self.scrollList['items']: if hasattr(item, 'description') and item.description and hasattr( item.description, 'destroy'): self.notify.debug('desroying description of item %s' % item) item.unbind(DGG.ENTER) item.unbind(DGG.EXIT) item.description.destroy() except e: self.notify.debug('pass %s' % self.myDate) self.scrollList.removeAndDestroyAllItems() self.scrollList.destroy() self.dayButton.destroy() DirectFrame.destroy(self) return def addWeeklyHolidays(self): if not self.filter == ToontownGlobals.CalendarFilterShowAll and not self.filter == ToontownGlobals.CalendarFilterShowOnlyHolidays: return if base.cr.newsManager: holidays = base.cr.newsManager.getHolidaysForWeekday( self.myDate.weekday()) holidayName = '' holidayDesc = '' for holidayId in holidays: if holidayId in TTLocalizer.HolidayNamesInCalendar: holidayName = TTLocalizer.HolidayNamesInCalendar[ holidayId][0] holidayDesc = TTLocalizer.HolidayNamesInCalendar[ holidayId][1] else: holidayName = TTLocalizer.UnknownHoliday % holidayId self.addTitleAndDescToScrollList(holidayName, holidayDesc) self.scrollList.refresh() if base.config.GetBool('calendar-test-items', 0): if self.myDate.date() + datetime.timedelta( days=-1 ) == base.cr.toontownTimeManager.getCurServerDateTime().date(): testItems = ('1:00 AM Party', '2:00 AM CEO', '11:15 AM Party', '5:30 PM CJ', '11:00 PM Party', 'Really Really Long String') for text in testItems: newItem = DirectLabel(relief=None, text=text, text_scale=self.ScrollListTextSize, text_align=TextNode.ALeft) self.scrollList.addItem(newItem) if self.myDate.date() + datetime.timedelta( days=-2 ) == base.cr.toontownTimeManager.getCurServerDateTime().date(): testItems = ('1:00 AM Party', '3:00 AM CFO', '11:00 AM Party') textSize = self.ScrollListTextSize for text in testItems: newItem = DirectLabel(relief=None, text=text, text_scale=textSize, text_align=TextNode.ALeft) self.scrollList.addItem(newItem) def updateArrowButtons(self): numItems = 0 try: numItems = len(self.scrollList['items']) except e: numItems = 0 if numItems <= self.scrollList.numItemsVisible: self.scrollList.incButton.hide() self.scrollList.decButton.hide() else: self.scrollList.incButton.show() self.scrollList.decButton.show() def collectTimedEvents(self): self.timedEvents = [] if self.filter == ToontownGlobals.CalendarFilterShowAll or self.filter == ToontownGlobals.CalendarFilterShowOnlyParties: for party in localAvatar.partiesInvitedTo: if party.startTime.date() == self.myDate.date(): self.partiesInvitedToToday.append(party) self.timedEvents.append((party.startTime.time(), party)) for party in localAvatar.hostedParties: if party.startTime.date() == self.myDate.date(): self.hostedPartiesToday.append(party) self.timedEvents.append((party.startTime.time(), party)) if base.cr.newsManager and ( self.filter == ToontownGlobals.CalendarFilterShowAll or self.filter == ToontownGlobals.CalendarFilterShowOnlyHolidays): yearlyHolidays = base.cr.newsManager.getYearlyHolidaysForDate( self.myDate) for holiday in yearlyHolidays: holidayId = holiday[1] holidayStart = holiday[2] holidayEnd = holiday[3] holidayType = holiday[0] if holidayStart[0] == self.myDate.month and holidayStart[ 1] == self.myDate.day: myTime = datetime.time(holidayStart[2], holidayStart[3]) elif holidayEnd[0] == self.myDate.month and holidayEnd[ 1] == self.myDate.day: myTime = datetime.time(holidayEnd[2], holidayEnd[3]) else: self.notify.error('holiday is not today %s' % holiday) self.timedEvents.append((myTime, holiday)) oncelyHolidays = base.cr.newsManager.getOncelyHolidaysForDate( self.myDate) for holiday in oncelyHolidays: holidayId = holiday[1] holidayStart = holiday[2] holidayEnd = holiday[3] holidayType = holiday[0] if holidayStart[0] == self.myDate.year and holidayStart[ 1] == self.myDate.month and holidayStart[ 2] == self.myDate.day: myTime = datetime.time(holidayStart[3], holidayStart[4]) elif holidayEnd[0] == self.myDate.year and holidayEnd[ 1] == self.myDate.month and holidayEnd[ 2] == self.myDate.day: myTime = datetime.time(holidayEnd[3], holidayEnd[4]) else: self.notify.error('holiday is not today %s' % holiday) self.timedEvents.append((myTime, holiday)) multipleStartHolidays = base.cr.newsManager.getMultipleStartHolidaysForDate( self.myDate) for holiday in multipleStartHolidays: holidayId = holiday[1] holidayStart = holiday[2] holidayEnd = holiday[3] holidayType = holiday[0] if holidayStart[0] == self.myDate.year and holidayStart[ 1] == self.myDate.month and holidayStart[ 2] == self.myDate.day: myTime = datetime.time(holidayStart[3], holidayStart[4]) elif holidayEnd[0] == self.myDate.year and holidayEnd[ 1] == self.myDate.month and holidayEnd[ 2] == self.myDate.day: myTime = datetime.time(holidayEnd[3], holidayEnd[4]) else: self.notify.error('holiday is not today %s' % holiday) self.timedEvents.append((myTime, holiday)) relativelyHolidays = base.cr.newsManager.getRelativelyHolidaysForDate( self.myDate) for holiday in relativelyHolidays: holidayId = holiday[1] holidayStart = holiday[2] holidayEnd = holiday[3] holidayType = holiday[0] if holidayStart[0] == self.myDate.month and holidayStart[ 1] == self.myDate.day: myTime = datetime.time(holidayStart[2], holidayStart[3]) elif holidayEnd[0] == self.myDate.month and holidayEnd[ 1] == self.myDate.day: myTime = datetime.time(holidayEnd[2], holidayEnd[3]) else: self.notify.error('holiday is not today %s' % holiday) self.timedEvents.append((myTime, holiday)) def timedEventCompare(te1, te2): if te1[0] < te2[0]: return -1 elif te1[0] == te2[0]: return 0 else: return 1 self.timedEvents.sort(cmp=timedEventCompare) for timedEvent in self.timedEvents: if isinstance(timedEvent[1], PartyInfo): self.addPartyToScrollList(timedEvent[1]) elif isinstance( timedEvent[1], tuple ) and timedEvent[1][0] == NewsManager.YearlyHolidayType: self.addYearlyHolidayToScrollList(timedEvent[1]) elif isinstance( timedEvent[1], tuple ) and timedEvent[1][0] == NewsManager.OncelyHolidayType: self.addOncelyHolidayToScrollList(timedEvent[1]) elif isinstance(timedEvent[1], tuple) and timedEvent[1][ 0] == NewsManager.OncelyMultipleStartHolidayType: self.addOncelyMultipleStartHolidayToScrollList(timedEvent[1]) elif isinstance( timedEvent[1], tuple ) and timedEvent[1][0] == NewsManager.RelativelyHolidayType: self.addRelativelyHolidayToScrollList(timedEvent[1]) def addYearlyHolidayToScrollList(self, holiday): holidayId = holiday[1] holidayStart = holiday[2] holidayEnd = holiday[3] holidayType = holiday[0] holidayText = '' startTime = datetime.time(holidayStart[2], holidayStart[3]) endTime = datetime.time(holidayEnd[2], holidayEnd[3]) startDate = datetime.date(self.myDate.year, holidayStart[0], holidayStart[1]) endDate = datetime.date(self.myDate.year, holidayEnd[0], holidayEnd[1]) if endDate < startDate: endDate = datetime.date(endDate.year + 1, endDate.month, endDate.day) if holidayId in TTLocalizer.HolidayNamesInCalendar: holidayName = TTLocalizer.HolidayNamesInCalendar[holidayId][0] holidayDesc = TTLocalizer.HolidayNamesInCalendar[holidayId][1] else: holidayName = TTLocalizer.UnknownHoliday % holidayId holidayDesc = TTLocalizer.UnknownHoliday % holidayId if holidayStart[0] == holidayEnd[0] and holidayStart[1] == holidayEnd[ 1]: holidayText = myStrftime(startTime) holidayText += ' ' + holidayName holidayDesc += ' ' + TTLocalizer.CalendarEndsAt + myStrftime( endTime) elif self.myDate.month == holidayStart[ 0] and self.myDate.day == holidayStart[1]: holidayText = myStrftime(startTime) holidayText += ' ' + holidayName holidayDesc = holidayName + '. ' + holidayDesc holidayDesc += ' ' + TTLocalizer.CalendarEndsAt + endDate.strftime( TTLocalizer.HolidayFormat) + myStrftime(endTime) elif self.myDate.month == holidayEnd[ 0] and self.myDate.day == holidayEnd[1]: holidayText = myStrftime(endTime) holidayText += ' ' + TTLocalizer.CalendarEndDash + holidayName holidayDesc = TTLocalizer.CalendarEndOf + holidayName holidayDesc += '. ' + TTLocalizer.CalendarStartedOn + startDate.strftime( TTLocalizer.HolidayFormat) + myStrftime(startTime) else: self.notify.error('unhandled case') self.addTitleAndDescToScrollList(holidayText, holidayDesc) def addOncelyHolidayToScrollList(self, holiday): holidayId = holiday[1] holidayStart = holiday[2] holidayEnd = holiday[3] holidayType = holiday[0] holidayText = '' startTime = datetime.time(holidayStart[3], holidayStart[4]) endTime = datetime.time(holidayEnd[3], holidayEnd[4]) startDate = datetime.date(holidayStart[0], holidayStart[1], holidayStart[2]) endDate = datetime.date(holidayStart[0], holidayEnd[1], holidayEnd[2]) if endDate < startDate: endDate = datetime.date(endDate.year + 1, endDate.month, endDate.day) if holidayId in TTLocalizer.HolidayNamesInCalendar: holidayName = TTLocalizer.HolidayNamesInCalendar[holidayId][0] holidayDesc = TTLocalizer.HolidayNamesInCalendar[holidayId][1] else: holidayName = TTLocalizer.UnknownHoliday % holidayId holidayDesc = '' if holidayStart[1] == holidayEnd[1] and holidayStart[2] == holidayEnd[ 2]: holidayText = myStrftime(startTime) holidayText += ' ' + holidayName holidayDesc = holidayName + '. ' + holidayDesc holidayDesc += ' ' + TTLocalizer.CalendarEndsAt + myStrftime( endTime) elif self.myDate.year == holidayStart[ 0] and self.myDate.month == holidayStart[ 1] and self.myDate.day == holidayStart[2]: holidayText = myStrftime(startTime) holidayText += ' ' + holidayName holidayDesc = holidayName + '. ' + holidayDesc holidayDesc += ' ' + TTLocalizer.CalendarEndsAt + endDate.strftime( TTLocalizer.HolidayFormat) + myStrftime(endTime) elif self.myDate.year == holidayEnd[ 0] and self.myDate.month == holidayEnd[ 1] and self.myDate.day == holidayEnd[2]: holidayText = myStrftime(endTime) holidayText += ' ' + TTLocalizer.CalendarEndDash + holidayName holidayDesc = TTLocalizer.CalendarEndOf + holidayName holidayDesc += '. ' + TTLocalizer.CalendarStartedOn + startDate.strftime( TTLocalizer.HolidayFormat) + myStrftime(startTime) else: self.notify.error('unhandled case') self.addTitleAndDescToScrollList(holidayText, holidayDesc) def addOncelyMultipleStartHolidayToScrollList(self, holiday): self.addOncelyHolidayToScrollList(holiday) def addRelativelyHolidayToScrollList(self, holiday): holidayId = holiday[1] holidayStart = holiday[2] holidayEnd = holiday[3] holidayType = holiday[0] holidayText = '' startTime = datetime.time(holidayStart[2], holidayStart[3]) endTime = datetime.time(holidayEnd[2], holidayEnd[3]) startDate = datetime.date(self.myDate.year, holidayStart[0], holidayStart[1]) endDate = datetime.date(self.myDate.year, holidayEnd[0], holidayEnd[1]) if endDate < startDate: endDate.year += 1 if holidayId in TTLocalizer.HolidayNamesInCalendar: holidayName = TTLocalizer.HolidayNamesInCalendar[holidayId][0] holidayDesc = TTLocalizer.HolidayNamesInCalendar[holidayId][1] else: holidayName = TTLocalizer.UnknownHoliday % holidayId holidayDesc = '' if holidayStart[0] == holidayEnd[0] and holidayStart[1] == holidayEnd[ 1]: holidayText = myStrftime(startTime) holidayText += ' ' + holidayName holidayDesc += ' ' + TTLocalizer.CalendarEndsAt + myStrftime( endTime) elif self.myDate.month == holidayStart[ 0] and self.myDate.day == holidayStart[1]: holidayText = myStrftime(startTime) holidayText += ' ' + holidayName holidayDesc = holidayName + '. ' + holidayDesc holidayDesc += ' ' + TTLocalizer.CalendarEndsAt + endDate.strftime( TTLocalizer.HolidayFormat) + myStrftime(endTime) elif self.myDate.month == holidayEnd[ 0] and self.myDate.day == holidayEnd[1]: holidayText = myStrftime(endTime) holidayText += ' ' + TTLocalizer.CalendarEndDash + holidayName holidayDesc = TTLocalizer.CalendarEndOf + holidayName holidayDesc += '. ' + TTLocalizer.CalendarStartedOn + startDate.strftime( TTLocalizer.HolidayFormat) + myStrftime(startTime) else: self.notify.error('unhandled case') self.addTitleAndDescToScrollList(holidayText, holidayDesc) 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 exitedTextItem(self, newItem, mousepos): newItem.description.hide() def enteredTextItem(self, newItem, descText, descUnderItemZAdjust, mousePos): if not newItem.description.checkedHeight: newItem.description.checkedHeight = True newItem.description['text'] = descText bounds = newItem.description.getBounds() descHeight = newItem.description.getHeight() scrollItemHeight = newItem.getHeight() descOverItemZAdjust = descHeight - scrollItemHeight / 2.0 descZPos = self.getPos( aspect2d)[2] + descUnderItemZAdjust - descHeight if descZPos < -1.0: newItem.description.setZ(descOverItemZAdjust) descWidth = newItem.description.getWidth() brightFrame = loader.loadModel( 'phase_4/models/parties/tt_m_gui_sbk_calendar_popUp_bg') newItem.description['geom'] = brightFrame newItem.description['geom_scale'] = (descWidth, 1, descHeight) descGeomZ = (bounds[2] - bounds[3]) / 2.0 descGeomZ += bounds[3] newItem.description['geom_pos'] = (0, 0, descGeomZ) newItem.description.show() 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 __clickedOnScrollItem(self): self.__clickedOnDay() def __clickedOnDay(self): acceptClick = True if self.onlyFutureDaysClickable: curServerDate = base.cr.toontownTimeManager.getCurServerDateTime() if self.myDate.date() < curServerDate.date(): acceptClick = False if not acceptClick: return if self.dayClickCallback: self.dayClickCallback(self) self.notify.debug('we got clicked on %s' % self.myDate.date()) messenger.send('clickedOnDay', [self.myDate.date()]) def updateSelected(self, selected): multiplier = 1.1 if selected: self.selectedFrame.show() self.setScale(multiplier) self.setPos(-0.01, 0, 0.01) grandParent = self.origParent.getParent() self.origParent.reparentTo(grandParent) else: self.selectedFrame.hide() self.setScale(1.0) self.setPos(0, 0, 0) def changeDate(self, startDate, myDate): self.startDate = startDate self.myDate = myDate self.scrollList.removeAndDestroyAllItems() self.update() def update(self): self.numberWidget['text'] = str(self.myDate.day) self.adjustForMonth() self.addWeeklyHolidays() self.collectTimedEvents() self.updateArrowButtons() def changeFilter(self, filter): oldFilter = self.filter self.filter = filter if self.filter != oldFilter: self.scrollList.removeAndDestroyAllItems() self.update()
class lobbyGUI(): def __init__(self, _client): self.client = _client self.playerList = [] # Visuals self.lstLobby = DirectScrolledList( decButton_pos= (1.1, 0, -0.45), decButton_text = "up", decButton_text_scale = 0.06, decButton_borderWidth = (0.005, 0.005), incButton_pos= (1.1, 0, -0.55), incButton_text = "down", incButton_text_scale = 0.06, incButton_borderWidth = (0.005, 0.005), frameSize = (-1.05, 1.20, -1.16, 0.16), frameColor = (1,0,0,0.5), pos = (-0.075, 0, 0.5), numItemsVisible = 10, forceHeight = 0.11, itemFrame_frameSize = (-1, 1, -1.11, 0.11), itemFrame_pos = (0, 0, 0), ) # create a start button self.btnStart = DirectButton( # Scale and position scale = 0.15, pos = (1,0,-0.90), # Text text = "Start", # Frame # Functionality command = self.start) # create a back button self.btnBack = DirectButton( # Scale and position scale = 0.15, pos = (-1,0,-0.90), # Text text = "back", # Frame # Functionality command = self.back) self.hide() def show(self): self.lstLobby.show() self.btnStart.show() self.btnBack.show() def hide(self): self.lstLobby.hide() self.btnStart.hide() self.btnBack.hide() def start(self): #TODO: Send event or whatever to let the other parts know we can # start the game pass def back(self): #TODO: Send event or whatever to let the other parts know we # want to move to the previous menu pass def updateList(self, newList): for item in newList: l = DirectLabel(text = item, text_scale=0.1) self.lstLobby.addItem(l)
class GroupTrackerPage(ShtikerPage.ShtikerPage): notify = directNotify.newCategory('GroupTrackerPage') def __init__(self): ShtikerPage.ShtikerPage.__init__(self) self.groupWidgets = [] self.playerWidgets = [] self.images = [] # image nodes: Possible images to apply on groups self.scrollList = None # DirectScrolledList: Holds the GroupTrackerGroup widgets self.scrollTitle = None # DirectLabel: Title of the list that holds the groups self.playerList = None # DirectScrolledList: Holds players when showing a specific group details self.playerListTitle = None # DirectLabel: Title of the playerList self.groupInfoTitle = None # DirectLabel: holds the group detail title to show on the right self.groupInfoDistrict = None # DirectLabel: shows group detail district on the right self.statusMessage = None # DirectLabel: Shows important messages like Loading... or "No boarding groups available" self.groupIcon = None # DirectButton: Icon to associate with the group ex. sellbot icon or cashbot icon depending on group info self.wantGroupToggle = None # DirectButton: Allows the toon to toggle his listing def load(self): self.listXorigin = -0.02 self.listFrameSizeX = 0.67 self.listZorigin = -0.96 self.listFrameSizeZ = 1.04 self.arrowButtonScale = 1.3 self.itemFrameXorigin = -0.237 self.itemFrameZorigin = 0.365 self.buttonXstart = self.itemFrameXorigin + 0.293 self.gui = loader.loadModel('phase_3.5/models/gui/friendslist_gui') guiButton = loader.loadModel('phase_3/models/gui/quit_button') self.scrollList = DirectScrolledList( parent=self, relief=None, pos=(-0.5, 0, 0), incButton_image=(self.gui.find('**/FndsLst_ScrollUp'), self.gui.find('**/FndsLst_ScrollDN'), self.gui.find('**/FndsLst_ScrollUp_Rllvr'), self.gui.find('**/FndsLst_ScrollUp')), incButton_relief=None, incButton_scale=(self.arrowButtonScale, self.arrowButtonScale, -self.arrowButtonScale), incButton_pos=(self.buttonXstart, 0, self.itemFrameZorigin - 0.999), incButton_image3_color=Vec4(1, 1, 1, 0.2), decButton_image=(self.gui.find('**/FndsLst_ScrollUp'), self.gui.find('**/FndsLst_ScrollDN'), self.gui.find('**/FndsLst_ScrollUp_Rllvr'), self.gui.find('**/FndsLst_ScrollUp')), decButton_relief=None, decButton_scale=(self.arrowButtonScale, self.arrowButtonScale, self.arrowButtonScale), decButton_pos=(self.buttonXstart, 0, self.itemFrameZorigin + 0.227), decButton_image3_color=Vec4(1, 1, 1, 0.2), itemFrame_pos=(self.itemFrameXorigin, 0, self.itemFrameZorigin), itemFrame_scale=1.0, itemFrame_relief=DGG.SUNKEN, itemFrame_frameSize=(self.listXorigin, self.listXorigin + self.listFrameSizeX, self.listZorigin, self.listZorigin + self.listFrameSizeZ), itemFrame_frameColor=(0.85, 0.95, 1, 1), itemFrame_borderWidth=(0.01, 0.01), numItemsVisible=15, forceHeight=0.065, items=self.groupWidgets) self.scrollTitle = DirectFrame(parent=self.scrollList, text=TTLocalizer.GroupTrackerListTitle, text_scale=0.06, text_align=TextNode.ACenter, relief=None, pos=(self.buttonXstart, 0, self.itemFrameZorigin + 0.127)) self.playerList = DirectScrolledList( parent=self, relief=None, pos=(0.45, 0, 0.1), incButton_image=(self.gui.find('**/FndsLst_ScrollUp'), self.gui.find('**/FndsLst_ScrollDN'), self.gui.find('**/FndsLst_ScrollUp_Rllvr'), self.gui.find('**/FndsLst_ScrollUp')), incButton_relief=None, incButton_scale=(1.0, 1.0, -1.0), incButton_pos=(0, 0, -0.28), incButton_image3_color=Vec4(1, 1, 1, 0.05), decButton_image=(self.gui.find('**/FndsLst_ScrollUp'), self.gui.find('**/FndsLst_ScrollDN'), self.gui.find('**/FndsLst_ScrollUp_Rllvr'), self.gui.find('**/FndsLst_ScrollUp')), decButton_relief=None, decButton_scale=(1.0, 1.0, 1.0), decButton_pos=(0.0, 0, 0.04), decButton_image3_color=Vec4(1, 1, 1, 0.25), itemFrame_pos=(0, 0, -0.05), itemFrame_scale=1.0, itemFrame_relief=DGG.SUNKEN, itemFrame_frameSize=( -0.3, 0.3, #x -0.2, 0.06), #z itemFrame_frameColor=(0.85, 0.95, 1, 1), itemFrame_borderWidth=(0.01, 0.01), numItemsVisible=4, forceHeight=0.05, items=self.playerWidgets) self.playerListTitle = DirectFrame(parent=self.playerList, text='', text_scale=0.05, text_align=TextNode.ACenter, relief=None, pos=(0, 0, 0.08)) self.groupInfoTitle = DirectLabel(parent=self, text='', text_scale=0.080, text_align=TextNode.ACenter, text_wordwrap=15, relief=None, pos=(0.45, 0, 0.5)) self.groupInfoDistrict = DirectLabel(parent=self, text='', text_scale=0.050, text_align=TextNode.ACenter, text_wordwrap=15, relief=None, pos=(0.45, 0, 0.4)) self.statusMessage = DirectLabel(parent=self, text='', text_scale=0.060, text_align=TextNode.ACenter, text_wordwrap=5, relief=None, pos=(0.45, 0, 0.1)) # Group Image: self.groupIcon = DirectButton(parent=self, relief=None, state=DGG.DISABLED, image=None, image_scale=(0.35, 1, 0.35), image_color=Vec4(1.0, 1.0, 1.0, 0.75), pos=(0.45, 10, -0.45), command=self.doNothing) # Group Toggle: self.wantGroupToggle = DirectButton( parent=self, relief=None, image=(guiButton.find('**/QuitBtn_UP'), guiButton.find('**/QuitBtn_DN'), guiButton.find('**/QuitBtn_RLVR')), image_scale=(0.7, 1, 1), text='', text_scale=0.052, text_pos=(0, -0.02), pos=(0.2, 0, -0.65), command=self.toggleWantGroup) self.updateWantGroupButton() # Loading possible group icons suitIcons = loader.loadModel('phase_3/models/gui/cog_icons') bossbotIcon = suitIcons.find('**/CorpIcon') bossbotIcon.setColor(SUIT_ICON_COLORS[0]) self.images.append(bossbotIcon) lawbotIcon = suitIcons.find('**/LegalIcon') lawbotIcon.setColor(SUIT_ICON_COLORS[1]) self.images.append(lawbotIcon) cashbotIcon = suitIcons.find('**/MoneyIcon') cashbotIcon.setColor(SUIT_ICON_COLORS[2]) self.images.append(cashbotIcon) sellbotIcon = suitIcons.find('**/SalesIcon') sellbotIcon.setColor(SUIT_ICON_COLORS[3]) self.images.append(sellbotIcon) # Clean up self.clearGroupInfo() self.statusMessage.hide() suitIcons.removeNode() self.gui.removeNode() guiButton.removeNode() self.accept('GroupTrackerResponse', self.updatePage) def unload(self): self.scrollList.destroy() self.groupInfoDistrict.destroy() self.playerList.destroy() self.groupInfoTitle.destroy() self.groupIcon.destroy() self.wantGroupToggle.destroy() for widget in self.playerWidgets: widget.destroy() for widget in self.groupWidgets: widget.destroy() self.playerWidgets = [] del self.scrollList del self.groupInfoDistrict del self.playerList del self.groupInfoTitle del self.groupIcon del self.wantGroupToggle ShtikerPage.ShtikerPage.unload(self) def enter(self): ShtikerPage.ShtikerPage.enter(self) self.setGroups([]) # CLEAR IT ALL self.setPlayers() # CLEAR IT ALL if (self.scrollList['items'] == []): self.statusMessage['text'] = TTLocalizer.GroupTrackerLoading self.statusMessage.show() base.cr.globalGroupTracker.requestGroups() taskMgr.doMethodLater(3, self.displayNoGroupsTaskHandler, self.uniqueName('timeout')) def displayNoGroups(self): self.statusMessage['text'] = TTLocalizer.GroupTrackerEmpty self.statusMessage.show() self.clearGroupInfo() def displayNoGroupsTaskHandler(self, task): self.displayNoGroups() return task.done def updatePage(self): taskMgr.remove(self.uniqueName('timeout')) groups = base.cr.globalGroupTracker.getGroupInfo() self.setGroups(groups) def exit(self): self.clearGroupInfo() ShtikerPage.ShtikerPage.exit(self) base.cr.globalGroupTracker.doneRequesting() def updateGroupInfoEventHandle(self, groupWidget, mouseEvent): self.updateGroupInfo(groupWidget) def updateGroupInfo(self, groupWidget): ''' Updates the Right Page of the Group Tracker Page with new Info ''' self.statusMessage.hide() # Update the Player List self.setPlayers(groupWidget) self.playerList.show() # Update the Player List Title self.playerListTitle['text'] = ('Players ' + str(groupWidget.getCurrentPlayers()) + '/' + str(groupWidget.getMaxPlayers()) + ':') self.playerListTitle.show() # Update the District self.groupInfoDistrict[ 'text'] = TTLocalizer.BoardingGroupDistrictInformation % { 'district': groupWidget.getDistrict() } self.groupInfoDistrict.show() # Update the Title self.groupInfoTitle['text'] = groupWidget.getTitle() self.groupInfoTitle.show() # Update the Image self.groupIcon['image'] = self.images[ GroupTrackerGlobals.CATEGORY_TO_IMAGE_ID[ groupWidget.getCategory()]] self.groupIcon['image_scale'] = (0.35, 1, 0.35) self.groupIcon.show() def clearGroupInfo(self): self.playerList.hide() self.playerListTitle.hide() self.groupInfoDistrict.hide() self.groupInfoTitle.hide() self.groupIcon.hide() def setPlayers(self, groupWidget=None): ''' Calls updatePlayerList ''' # Clear the Widgets that were held in the listings for playerWidget in self.playerWidgets: playerWidget.destroy() self.playerWidgets = [] # Make a player widget for each player # TODO: Edit this stuff when avIds come from players if groupWidget: leaderId = groupWidget.getLeaderId() playerNames = groupWidget.getMemberNames() playerIds = groupWidget.getMemberIds() for playerName in playerNames: playerId = playerIds[playerNames.index(playerName)] isLeader = playerId == leaderId self.playerWidgets.append( GroupTrackerPlayer(parent=self, avId=playerId, name=playerName, isLeader=isLeader)) self.updatePlayerList() def reconsiderGroupInfo(self, groupWidget): ''' If someone is viewing this info and it was updated, we also want to update the info being viewed ''' if self.playerWidgets is None or self.playerList['items'] == []: return # No Info is being viewed at the moment since you cant have an empty group # We have to update if this group's leader is the leader in the playerlist being viewed right now leaderId = groupWidget.getLeaderId() # Check all the players in the playerList being viewed for the same leader for playerWidget in self.playerWidgets: if playerWidget.getLeader(): if leaderId == playerWidget.getId(): self.updateGroupInfo(groupWidget) return False return True def setGroups(self, groups): ''' Calls updateGroupList ''' # Clear our Group Widgets for group in self.groupWidgets: group.destroy() self.groupWidgets = [] wantReconsiderInfo = True # Create a new group widget for each group for group in groups: if not group[GroupTrackerGlobals.SHOW] or len( group[GroupTrackerGlobals.MEMBER_IDS]) == 0: continue # We are using this to see if this group is dead or if someone doesnt want it up leaderId = 0 for i, g in base.cr.globalGroupTracker.leader2Group.items(): if g == group: leaderId = i if not leaderId: continue leaderName = group[GroupTrackerGlobals.LEADER_NAME] shardName = group[GroupTrackerGlobals.SHARD_NAME] category = group[GroupTrackerGlobals.CATEGORY] memberIds = group[GroupTrackerGlobals.MEMBER_IDS] memberNames = group[GroupTrackerGlobals.MEMBER_NAMES] groupWidget = GroupTrackerGroup(parent=self, leaderId=leaderId, leaderName=leaderName, shardName=shardName, category=category, memberIds=memberIds, memberNames=memberNames) groupWidget.bind(DGG.WITHIN, self.updateGroupInfoEventHandle, extraArgs=[groupWidget]) self.groupWidgets.append(groupWidget) if wantReconsiderInfo: wantReconsiderInfo = self.reconsiderGroupInfo(groupWidget) # Edge case where a group that was removed, info might remain on the screen if it didn't exist any more if wantReconsiderInfo: self.clearGroupInfo() # There are no groups, hide the information if len(self.groupWidgets) == 0: self.displayNoGroups() self.updateGroupList() def updateGroupList(self): self.statusMessage.hide() if self.scrollList is None: return # Clear the Group Listing for item in self.scrollList['items']: if item: self.scrollList.removeItem(item, refresh=True) self.scrollList['items'] = [] # Re-populate the Group Listing for groupWidget in self.groupWidgets: self.scrollList.addItem(groupWidget, refresh=True) if len(self.groupWidgets) == 0: self.displayNoGroups() def updatePlayerList(self): if self.playerList is None: return # Clear the Player Listing for item in self.playerList['items']: if item: self.playerList.removeItem(item) self.playerList['items'] = [] # Re-Populate the List for playerWidget in self.playerWidgets: self.playerList.addItem(playerWidget) def toggleWantGroup(self): if settings.get('grouptracker', False): settings['grouptracker'] = False base.cr.globalGroupTracker.showMe(False) else: settings['grouptracker'] = True base.cr.globalGroupTracker.showMe(True) base.localAvatar.wantGroupTracker() base.localAvatar.wantGroupTracker( ) # Updates the ai toon so the boarding group AI could know what he wants self.updateWantGroupButton() def updateWantGroupButton(self): if settings.get('grouptracker', False): self.wantGroupToggle['text'] = 'Hide Me' else: self.wantGroupToggle['text'] = 'Show Me' def doNothing(self): pass
class Highscore(): def __init__(self): home = os.path.expanduser("~") quickJNRDir = os.path.join(home, ".quickShooter") if not os.path.exists(quickJNRDir): os.makedirs(quickJNRDir) self.highscorefile = os.path.join(quickJNRDir, "highscore.txt") self.highscore = [] if not os.path.exists(self.highscorefile): with open(self.highscorefile, "w") as f: f.write("""Foxy;4000 Wolf;3500 Coon;3000 Kitty;2020 Ferret;2000 Lynx;1700 Lion;1280 Tiger;800 Birdy;450 Fishy;250""") with open(self.highscorefile, "r+") as f: data = f.readlines() for line in data: name = line.split(";")[0] pts = line.split(";")[1] self.highscore.append([name, pts]) self.lstHighscore = DirectScrolledList( frameSize = (-1, 1, -0.6, 0.6), frameColor = (0,0,0,0.5), pos = (0, 0, 0), numItemsVisible = 10, itemMakeFunction = self.__makeListItem, itemFrame_frameSize = (-0.9, 0.9, 0.0, -1), itemFrame_color = (1, 1, 1, 0), itemFrame_pos = (0, 0, 0.5)) self.btnBack = DirectButton( # size of the button scale = (0.15, 0.15, 0.15), text = "Back", # set no relief relief = None, frameColor = (0,0,0,0), # No sink in when press pressEffect = False, # position on the window pos = (0.2, 0, 0.1), # the event which is thrown on clickSound command = self.btnBack_Click, # sounds that should be played rolloverSound = None, clickSound = None) self.btnBack.setTransparency(1) self.btnBack.reparentTo(base.a2dBottomLeft) self.refreshList() self.hide() def show(self): self.lstHighscore.show() self.btnBack.show() def hide(self): self.lstHighscore.hide() self.btnBack.hide() def writeHighscore(self): self.__sortHigscore() with open(self.highscorefile, "w") as f: for entry in self.highscore: f.write("{0};{1}".format(entry[0], entry[1])) def refreshList(self): self.__sortHigscore() self.lstHighscore.removeAllItems() for entry in self.highscore: self.lstHighscore.addItem("{0};{1}".format(entry[0], entry[1])) def __makeListItem(self, highscoreItem, stuff, morestuff): name = highscoreItem.split(";")[0] pts = highscoreItem.split(";")[1] # left l = -0.9 # right r = 0.9 itemFrame = DirectFrame( frameColor=(1, 1, 1, 0.5), frameSize=(l, r, -0.1, 0), relief=DGG.SUNKEN, borderWidth=(0.01, 0.01), pos=(0, 0, 0)) lblName = DirectLabel( pos=(l + 0.01, 0, -0.07), text=name, text_align=TextNode.ALeft, scale=0.07, frameColor=(0, 0, 0, 0)) lblPts = DirectLabel( pos=(r - 0.01, 0, -0.07), text=pts, text_align=TextNode.ARight, scale=0.07, frameColor=(0, 0, 0, 0)) lblName.reparentTo(itemFrame) lblPts.reparentTo(itemFrame) return itemFrame def __sortHigscore(self): self.highscore = sorted( self.highscore, key=lambda score: int(score[1]), reverse=True)[:10] def setPoints(self, name, points): self.highscore.append([name, str(points) + "\n"]) self.refreshList() self.writeHighscore() def btnBack_Click(self): self.hide() base.messenger.send("Highscore_back")
class CalendarGuiDay(DirectFrame): notify = directNotify.newCategory('CalendarGuiDay') ScrollListTextSize = 0.03 def __init__(self, parent, myDate, startDate, dayClickCallback = None, onlyFutureDaysClickable = False): self.origParent = parent self.startDate = startDate self.myDate = myDate self.dayClickCallback = dayClickCallback self.onlyFutureDaysClickable = onlyFutureDaysClickable DirectFrame.__init__(self, parent=parent) self.timedEvents = [] self.partiesInvitedToToday = [] self.hostedPartiesToday = [] self.yearlyHolidaysToday = [] self.showMarkers = base.config.GetBool('show-calendar-markers', 0) self.filter = ToontownGlobals.CalendarFilterShowAll self.load() self.createGuiObjects() self.update() def createDummyLocators(self): self.dayButtonLocator = self.attachNewNode('dayButtonLocator') self.dayButtonLocator.setX(0.1) self.dayButtonLocator.setZ(-0.05) self.numberLocator = self.attachNewNode('numberLocator') self.numberLocator.setX(0.09) self.scrollLocator = self.attachNewNode('scrollLocator') self.selectedLocator = self.attachNewNode('selectedLocator') self.selectedLocator.setX(0.11) self.selectedLocator.setZ(-0.06) def load(self): dayAsset = loader.loadModel('phase_4/models/parties/tt_m_gui_sbk_calendar_box') dayAsset.reparentTo(self) self.dayButtonLocator = self.find('**/loc_origin') self.numberLocator = self.find('**/loc_number') self.scrollLocator = self.find('**/loc_topLeftList') self.selectedLocator = self.find('**/loc_origin') self.todayBox = self.find('**/boxToday') self.todayBox.hide() self.selectedFrame = self.find('**/boxHover') self.selectedFrame.hide() self.defaultBox = self.find('**/boxBlank') self.scrollBottomRightLocator = self.find('**/loc_bottomRightList') self.scrollDownLocator = self.find('**/loc_scrollDown') self.attachMarker(self.scrollDownLocator) self.scrollUpLocator = self.find('**/loc_scrollUp') self.attachMarker(self.scrollUpLocator) def attachMarker(self, parent, scale = 0.005, color = (1, 0, 0)): if self.showMarkers: marker = loader.loadModel('phase_3/models/misc/sphere') marker.reparentTo(parent) marker.setScale(scale) marker.setColor(*color) def createGuiObjects(self): self.dayButton = DirectButton(parent=self.dayButtonLocator, image=self.selectedFrame, relief=None, command=self.__clickedOnDay, pressEffect=1, rolloverSound=None, clickSound=None) self.numberWidget = DirectLabel(parent=self.numberLocator, relief=None, text=str(self.myDate.day), text_scale=0.04, text_align=TextNode.ACenter, text_font=ToontownGlobals.getInterfaceFont(), text_fg=Vec4(110 / 255.0, 126 / 255.0, 255 / 255.0, 1)) self.attachMarker(self.numberLocator) self.listXorigin = 0 self.listFrameSizeX = self.scrollBottomRightLocator.getX() - self.scrollLocator.getX() self.scrollHeight = self.scrollLocator.getZ() - self.scrollBottomRightLocator.getZ() self.listZorigin = self.scrollBottomRightLocator.getZ() self.listFrameSizeZ = self.scrollLocator.getZ() - self.scrollBottomRightLocator.getZ() self.arrowButtonXScale = 1 self.arrowButtonZScale = 1 self.itemFrameXorigin = 0 self.itemFrameZorigin = 0 self.buttonXstart = self.itemFrameXorigin + 0.21 self.gui = loader.loadModel('phase_3.5/models/gui/friendslist_gui') buttonOffSet = -0.01 incButtonPos = (0.0, 0, 0) decButtonPos = (0.0, 0, 0) itemFrameMinZ = self.listZorigin itemFrameMaxZ = self.listZorigin + self.listFrameSizeZ arrowUp = self.find('**/downScroll_up') arrowDown = self.find('**/downScroll_down') arrowHover = self.find('**/downScroll_hover') self.scrollList = DirectScrolledList(parent=self.scrollLocator, relief=None, pos=(0, 0, 0), incButton_image=(arrowUp, arrowDown, arrowHover, arrowUp), incButton_relief=None, incButton_scale=(self.arrowButtonXScale, 1, self.arrowButtonZScale), incButton_pos=incButtonPos, incButton_image3_color=(1, 1, 1, 0.2), decButton_image=(arrowUp, arrowDown, arrowHover, arrowUp), decButton_relief=None, decButton_scale=(self.arrowButtonXScale, 1, -self.arrowButtonZScale), decButton_pos=decButtonPos, decButton_image3_color=(1, 1, 1, 0.2), itemFrame_pos=(self.itemFrameXorigin, 0, -0.03), numItemsVisible=4, incButtonCallback=self.scrollButtonPressed, decButtonCallback=self.scrollButtonPressed) itemFrameParent = self.scrollList.itemFrame.getParent() self.scrollList.incButton.reparentTo(self.scrollDownLocator) self.scrollList.decButton.reparentTo(self.scrollUpLocator) arrowUp.removeNode() arrowDown.removeNode() arrowHover.removeNode() clipper = PlaneNode('clipper') clipper.setPlane(Plane((-1, 0, 0), (0.23, 0, 0))) clipNP = self.scrollList.component('itemFrame').attachNewNode(clipper) self.scrollList.component('itemFrame').setClipPlane(clipNP) return def scrollButtonPressed(self): self.__clickedOnDay() def adjustForMonth(self): curServerDate = base.cr.toontownTimeManager.getCurServerDateTime() if self.onlyFutureDaysClickable: if self.myDate.year < curServerDate.year or self.myDate.year == curServerDate.year and self.myDate.month < curServerDate.month or self.myDate.year == curServerDate.year and self.myDate.month == curServerDate.month and self.myDate.day < curServerDate.day: self.numberWidget.setColorScale(0.5, 0.5, 0.5, 0.5) self.numberWidget['state'] = DirectGuiGlobals.DISABLED else: self.numberWidget.setColorScale(1, 1, 1, 1) if self.myDate.month != self.startDate.month: self.setColorScale(0.75, 0.75, 0.75, 1.0) if self.dayClickCallback is not None: self.numberWidget['state'] = DirectGuiGlobals.DISABLED else: self.setColorScale(1, 1, 1, 1) if self.myDate.date() == curServerDate.date(): self.defaultBox.hide() self.todayBox.show() else: self.defaultBox.show() self.todayBox.hide() return def destroy(self): if self.dayClickCallback is not None: self.numberWidget.destroy() self.dayClickCallback = None self.notify.debug('desroying %s' % self.myDate) try: for item in self.scrollList['items']: if hasattr(item, 'description') and item.description and hasattr(item.description, 'destroy'): self.notify.debug('desroying description of item %s' % item) item.unbind(DGG.ENTER) item.unbind(DGG.EXIT) item.description.destroy() except e: self.notify.debug('pass %s' % self.myDate) self.scrollList.removeAndDestroyAllItems() self.scrollList.destroy() self.dayButton.destroy() DirectFrame.destroy(self) def updateArrowButtons(self): numItems = 0 try: numItems = len(self.scrollList['items']) except e: numItems = 0 if numItems <= self.scrollList.numItemsVisible: self.scrollList.incButton.hide() self.scrollList.decButton.hide() else: self.scrollList.incButton.show() self.scrollList.decButton.show() def collectTimedEvents(self): if self.filter == ToontownGlobals.CalendarFilterShowAll or self.filter == ToontownGlobals.CalendarFilterShowOnlyParties: for party in localAvatar.partiesInvitedTo: if party.startTime.date() == self.myDate.date(): self.addPartyToScrollList(party) for party in localAvatar.hostedParties: if party.startTime.date() == self.myDate.date(): self.addPartyToScrollList(party) if self.filter == ToontownGlobals.CalendarFilterShowAll or self.filter == ToontownGlobals.CalendarFilterShowOnlyHolidays: for id, holiday in HolidayGlobals.Holidays.iteritems(): title, description = TTLocalizer.HolidayNamesInCalendar[id] if 'weekDay' in holiday: if self.myDate.weekday() == holiday['weekDay']: self.addTitleAndDescToScrollList(title, description) elif 'startMonth' in holiday or 'startDay' in holiday: startDate = HolidayGlobals.getStartDate(holiday, self.myDate) endDate = HolidayGlobals.getEndDate(holiday, self.myDate) if self.isDateMatch(self.myDate, startDate): if self.isDateMatch(startDate, endDate): description = '%s. %s' % (title, description) else: description = '%s. %s %s %s' % (title, description, TTLocalizer.CalendarEndsAt, endDate.strftime('%b %d')) self.addTitleAndDescToScrollList(title, description) elif self.isDateMatch(self.myDate, endDate): title = '%s %s' % (TTLocalizer.CalendarEndOf, title) description = '%s. %s %s' % (title, TTLocalizer.CalendarStartedOn, startDate.strftime('%b %d')) self.addTitleAndDescToScrollList(title, description) def isDateMatch(self, date1, date2): return date1.day == date2.day and date1.month == date2.month 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 exitedTextItem(self, newItem, mousepos): newItem.description.hide() def enteredTextItem(self, newItem, descText, descUnderItemZAdjust, mousePos): if not newItem.description.checkedHeight: newItem.description.checkedHeight = True newItem.description['text'] = descText bounds = newItem.description.getBounds() descHeight = newItem.description.getHeight() scrollItemHeight = newItem.getHeight() descOverItemZAdjust = descHeight - scrollItemHeight / 2.0 descZPos = self.getPos(aspect2d)[2] + descUnderItemZAdjust - descHeight if descZPos < -1.0: newItem.description.setZ(descOverItemZAdjust) descWidth = newItem.description.getWidth() brightFrame = loader.loadModel('phase_4/models/parties/tt_m_gui_sbk_calendar_popUp_bg') newItem.description['geom'] = brightFrame newItem.description['geom_scale'] = (descWidth, 1, descHeight) descGeomZ = (bounds[2] - bounds[3]) / 2.0 descGeomZ += bounds[3] newItem.description['geom_pos'] = (0, 0, descGeomZ) newItem.description.show() 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 __clickedOnScrollItem(self): self.__clickedOnDay() def __clickedOnDay(self): acceptClick = True if self.onlyFutureDaysClickable: curServerDate = base.cr.toontownTimeManager.getCurServerDateTime() if self.myDate.date() < curServerDate.date(): acceptClick = False if not acceptClick: return if self.dayClickCallback: self.dayClickCallback(self) self.notify.debug('we got clicked on %s' % self.myDate.date()) messenger.send('clickedOnDay', [self.myDate.date()]) def updateSelected(self, selected): multiplier = 1.1 if selected: self.selectedFrame.show() self.setScale(multiplier) self.setPos(-0.01, 0, 0.01) grandParent = self.origParent.getParent() self.origParent.reparentTo(grandParent) else: self.selectedFrame.hide() self.setScale(1.0) self.setPos(0, 0, 0) def changeDate(self, startDate, myDate): self.startDate = startDate self.myDate = myDate self.scrollList.removeAndDestroyAllItems() self.update() def update(self): self.numberWidget['text'] = str(self.myDate.day) self.adjustForMonth() self.collectTimedEvents() self.updateArrowButtons() def changeFilter(self, filter): oldFilter = self.filter self.filter = filter if self.filter != oldFilter: self.scrollList.removeAndDestroyAllItems() self.update()
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 CalendarGuiDay(DirectFrame): notify = directNotify.newCategory('CalendarGuiDay') ScrollListTextSize = 0.03 LargeTextSize = 0.0232 def __init__(self, parent, myDate, startDate, dayClickCallback = None, onlyFutureDaysClickable = False): self.origParent = parent self.startDate = startDate self.myDate = myDate self.dayClickCallback = dayClickCallback self.onlyFutureDaysClickable = onlyFutureDaysClickable DirectFrame.__init__(self, parent=parent) self.timedEvents = [] self.partiesInvitedToToday = [] self.hostedPartiesToday = [] self.yearlyHolidaysToday = [] self.showMarkers = config.GetBool('show-calendar-markers', 0) self.filter = ToontownGlobals.CalendarFilterShowAll self.load() self.createGuiObjects() self.update() def createDummyLocators(self): self.dayButtonLocator = self.attachNewNode('dayButtonLocator') self.dayButtonLocator.setX(0.1) self.dayButtonLocator.setZ(-0.05) self.numberLocator = self.attachNewNode('numberLocator') self.numberLocator.setX(0.09) self.scrollLocator = self.attachNewNode('scrollLocator') self.selectedLocator = self.attachNewNode('selectedLocator') self.selectedLocator.setX(0.11) self.selectedLocator.setZ(-0.06) def load(self): dayAsset = loader.loadModel('phase_4/models/parties/tt_m_gui_sbk_calendar_box') dayAsset.reparentTo(self) self.dayButtonLocator = self.find('**/loc_origin') self.numberLocator = self.find('**/loc_number') self.scrollLocator = self.find('**/loc_topLeftList') self.selectedLocator = self.find('**/loc_origin') self.todayBox = self.find('**/boxToday') self.todayBox.hide() self.selectedFrame = self.find('**/boxHover') self.selectedFrame.hide() self.defaultBox = self.find('**/boxBlank') self.scrollBottomRightLocator = self.find('**/loc_bottomRightList') self.scrollDownLocator = self.find('**/loc_scrollDown') self.attachMarker(self.scrollDownLocator) self.scrollUpLocator = self.find('**/loc_scrollUp') self.attachMarker(self.scrollUpLocator) def attachMarker(self, parent, scale = 0.005, color = (1, 0, 0)): if self.showMarkers: marker = loader.loadModel('phase_3/models/misc/sphere') marker.reparentTo(parent) marker.setScale(scale) marker.setColor(*color) def createGuiObjects(self): self.dayButton = DirectButton(parent=self.dayButtonLocator, image=self.selectedFrame, relief=None, command=self.__clickedOnDay, pressEffect=1, rolloverSound=None, clickSound=None) self.numberWidget = DirectLabel(parent=self.numberLocator, relief=None, text=str(self.myDate.day), text_scale=0.04, text_align=TextNode.ACenter, text_font=ToontownGlobals.getInterfaceFont(), text_fg=Vec4(110 / 255.0, 126 / 255.0, 255 / 255.0, 1)) self.attachMarker(self.numberLocator) self.listXorigin = 0 self.listFrameSizeX = self.scrollBottomRightLocator.getX() - self.scrollLocator.getX() self.scrollHeight = self.scrollLocator.getZ() - self.scrollBottomRightLocator.getZ() self.listZorigin = self.scrollBottomRightLocator.getZ() self.listFrameSizeZ = self.scrollLocator.getZ() - self.scrollBottomRightLocator.getZ() self.arrowButtonXScale = 1 self.arrowButtonZScale = 1 self.itemFrameXorigin = 0 self.itemFrameZorigin = 0 self.buttonXstart = self.itemFrameXorigin + 0.21 self.gui = loader.loadModel('phase_3.5/models/gui/friendslist_gui') buttonOffSet = -0.01 incButtonPos = (0.0, 0, 0) decButtonPos = (0.0, 0, 0) itemFrameMinZ = self.listZorigin itemFrameMaxZ = self.listZorigin + self.listFrameSizeZ arrowUp = self.find('**/downScroll_up') arrowDown = self.find('**/downScroll_down') arrowHover = self.find('**/downScroll_hover') self.scrollList = DirectScrolledList(parent=self.scrollLocator, relief=None, pos=(0, 0, 0), incButton_image=(arrowUp, arrowDown, arrowHover, arrowUp), incButton_relief=None, incButton_scale=(self.arrowButtonXScale, 1, self.arrowButtonZScale), incButton_pos=incButtonPos, incButton_image3_color=Vec4(1, 1, 1, 0.2), decButton_image=(arrowUp, arrowDown, arrowHover, arrowUp), decButton_relief=None, decButton_scale=(self.arrowButtonXScale, 1, -self.arrowButtonZScale), decButton_pos=decButtonPos, decButton_image3_color=Vec4(1, 1, 1, 0.2), itemFrame_pos=(self.itemFrameXorigin, 0, -0.03), numItemsVisible=4, incButtonCallback=self.scrollButtonPressed, decButtonCallback=self.scrollButtonPressed) itemFrameParent = self.scrollList.itemFrame.getParent() self.scrollList.incButton.reparentTo(self.scrollDownLocator) self.scrollList.decButton.reparentTo(self.scrollUpLocator) arrowUp.removeNode() arrowDown.removeNode() arrowHover.removeNode() clipper = PlaneNode('clipper') clipper.setPlane(Plane(Vec3(-1, 0, 0), Point3(0.23, 0, 0))) clipNP = self.scrollList.component('itemFrame').attachNewNode(clipper) self.scrollList.component('itemFrame').setClipPlane(clipNP) def scrollButtonPressed(self): self.__clickedOnDay() def adjustForMonth(self): curServerDate = base.cr.toontownTimeManager.getCurServerDateTime() if self.onlyFutureDaysClickable: if self.myDate.year < curServerDate.year or self.myDate.year == curServerDate.year and self.myDate.month < curServerDate.month or self.myDate.year == curServerDate.year and self.myDate.month == curServerDate.month and self.myDate.day < curServerDate.day: self.numberWidget.setColorScale(0.5, 0.5, 0.5, 0.5) self.numberWidget['state'] = DirectGuiGlobals.DISABLED else: self.numberWidget.setColorScale(1, 1, 1, 1) if self.myDate.month != self.startDate.month: self.setColorScale(0.75, 0.75, 0.75, 1.0) if self.dayClickCallback is not None: self.numberWidget['state'] = DirectGuiGlobals.DISABLED else: self.setColorScale(1, 1, 1, 1) if self.myDate.date() == curServerDate.date(): self.defaultBox.hide() self.todayBox.show() else: self.defaultBox.show() self.todayBox.hide() def destroy(self): if self.dayClickCallback is not None: self.numberWidget.destroy() self.dayClickCallback = None self.notify.debug('desroying %s' % self.myDate) try: for item in self.scrollList['items']: if hasattr(item, 'description') and item.description and hasattr(item.description, 'destroy'): self.notify.debug('desroying description of item %s' % item) item.unbind(DGG.ENTER) item.unbind(DGG.EXIT) item.description.destroy() except e: self.notify.debug('pass %s' % self.myDate) self.scrollList.removeAndDestroyAllItems() self.scrollList.destroy() self.dayButton.destroy() DirectFrame.destroy(self) def addWeeklyHolidays(self): if not self.filter == ToontownGlobals.CalendarFilterShowAll and not self.filter == ToontownGlobals.CalendarFilterShowOnlyHolidays: return if base.cr.newsManager: holidays = base.cr.newsManager.getHolidaysForWeekday(self.myDate.weekday()) holidayName = '' holidayDesc = '' for holidayId in holidays: if holidayId in TTLocalizer.HolidayNamesInCalendar: holidayName = TTLocalizer.HolidayNamesInCalendar[holidayId][0] holidayDesc = TTLocalizer.HolidayNamesInCalendar[holidayId][1] else: holidayName = TTLocalizer.UnknownHoliday % holidayId self.addTitleAndDescToScrollList(holidayName, holidayDesc) self.scrollList.refresh() if config.GetBool('calendar-test-items', 0): if self.myDate.date() + datetime.timedelta(days=-1) == base.cr.toontownTimeManager.getCurServerDateTime().date(): testItems = ('1:00 AM Party', '2:00 AM CEO', '11:15 AM Party', '5:30 PM CJ', '11:00 PM Party', 'Really Really Long String') for text in testItems: newItem = DirectLabel(relief=None, text=text, text_scale=self.ScrollListTextSize, text_align=TextNode.ALeft) self.scrollList.addItem(newItem) if self.myDate.date() + datetime.timedelta(days=-2) == base.cr.toontownTimeManager.getCurServerDateTime().date(): testItems = ('1:00 AM Party', '3:00 AM CFO', '11:00 AM Party') textSize = self.ScrollListTextSize for text in testItems: newItem = DirectLabel(relief=None, text=text, text_scale=textSize, text_align=TextNode.ALeft) self.scrollList.addItem(newItem) def updateArrowButtons(self): numItems = 0 try: numItems = len(self.scrollList['items']) except e: numItems = 0 if numItems <= self.scrollList.numItemsVisible: self.scrollList.incButton.hide() self.scrollList.decButton.hide() else: self.scrollList.incButton.show() self.scrollList.decButton.show() def collectTimedEvents(self): self.timedEvents = [] if self.filter == ToontownGlobals.CalendarFilterShowAll or self.filter == ToontownGlobals.CalendarFilterShowOnlyParties: for party in localAvatar.partiesInvitedTo: if party.startTime.date() == self.myDate.date(): self.partiesInvitedToToday.append(party) self.timedEvents.append((party.startTime.time(), party)) for party in localAvatar.hostedParties: if party.startTime.date() == self.myDate.date(): self.hostedPartiesToday.append(party) self.timedEvents.append((party.startTime.time(), party)) if base.cr.newsManager and (self.filter == ToontownGlobals.CalendarFilterShowAll or self.filter == ToontownGlobals.CalendarFilterShowOnlyHolidays): # December 14th - Winter if self.myDate.month == 12 and self.myDate.day == 14: holidayName = 'Winter Holiday' holidayDesc = 'Celebrate the Winter Holiday with Toontastic decorations,Cattlelog items and more!' self.addTitleAndDescToScrollList(holidayName, holidayDesc) if self.myDate.weekday() == 4 or self.myDate.weekday() == 5: holidayName = 'Fish Bingo!' holidayDesc = 'Celebrate the weekend with bingo!' # Janurary 4th - end of Winter if self.myDate.month == 1 and self.myDate.day == 4: holidayName = 'Winter Holiday End' holidayDesc = 'The end of the Winter Holiday!' self.addTitleAndDescToScrollList(holidayName, holidayDesc) # December 30th - New year's fireworks if self.myDate.month == 12 and self.myDate.day == 30: holidayName = "New Year's Fireworks" holidayDesc = "Let us light the skys with Toontastic fireworks!" self.addTitleAndDescToScrollList(holidayName, holidayDesc) # December 31st - New year's fireworks if self.myDate.month == 12 and self.myDate.day == 31: holidayName = "New Year's Fireworks" holidayDesc = "Let us light the skys with Toontastic fireworks!" self.addTitleAndDescToScrollList(holidayName, holidayDesc) # October 21st - Halloween if self.myDate.month == 10 and self.myDate.day == 21: holidayName = "Halloween Holiday" holidayDesc = "Celebrate Halloween as spooky trees and streetlights transform Toontown!" self.addTitleAndDescToScrollList(holidayName, holidayDesc) # November 1st - end of halloween if self.myDate.month == 11 and self.myDate.day == 1: holidayName = " End of Halloween Holiday" holidayDesc = "The end of the Halloween Holiday!" self.addTitleAndDescToScrollList(holidayName, holidayDesc) # March 14th - Ides of March if self.myDate.month == 3 and self.myDate.day == 14: holidayName = "Ides of March Invasion" holidayDesc = "Beware the Ides of March! Stop the Backstabber Cogs from invading Toontown!" self.addTitleAndDescToScrollList(holidayName, holidayDesc) # March 15th - Ides of March if self.myDate.month == 3 and self.myDate.day == 15: holidayName = "Ides of March Invasion" holidayDesc = "Beware the Ides of March! Stop the Backstabber Cogs from invading Toontown!" self.addTitleAndDescToScrollList(holidayName, holidayDesc) # July 29th - XP week if self.myDate.month == 7 and self.myDate.day == 29: holidayName = "Triple XP Week" holidayDesc = "Celebrate Toontown with extra XP on ALL wacky gags!" self.addTitleAndDescToScrollList(holidayName, holidayDesc) # August 5th - end of XP week if self.myDate.month == 8 and self.myDate.day == 5: holidayName = "End of Triple XP Week" holidayDesc = "The end of the triple XP on gags" self.addTitleAndDescToScrollList(holidayName, holidayDesc) if self.myDate.month == 6 and self.myDate.day == 29: holidayName = "Summer Fireworks" holidayDesc = "Celebrate Summer with a fireworks show every hour in each playground!" self.addTitleAndDescToScrollList(holidayName, holidayDesc) # March 29th - April Toons' Week if self.myDate.month == 3 and self.myDate.day == 29: holidayName = "April Toons' Week" holidayDesc = "Celebrate April Toons' Week - a holiday built by Toons for Toons!!" self.addTitleAndDescToScrollList(holidayName, holidayDesc) # April 11th - April Toons end if self.myDate.month == 4 and self.myDate.day == 11: holidayName = "April Toons End" holidayDesc = "Here lies then end of all the April Toons' Sillyness!" self.addTitleAndDescToScrollList(holidayName, holidayDesc) if self.myDate.month == 7 and self.myDate.day == 15: holidayName = "End of Summer Fireworks" holidayDesc = "Here lies the end of the Toontastic Summer Fireworks!" self.addTitleAndDescToScrollList(holidayName, holidayDesc) # 15th of April if self.myDate.month == 4 and self.myDate.day == 15: holidayName = "Tax Day Invasion" holidayDesc = "Number Crunchers are invading us. Apperntly we owe taxes! What are taxes?" self.addTitleAndDescToScrollList(holidayName, holidayDesc) # # if self.myDate.day == 15 and not self.myDate.month == 4: # holidayName = "V2.0 Mover & Shakers" # holidayDesc = "V2.0 Mover & Shakers Cogs are invading Toontown in masses! Stop them!" # self.addTitleAndDescToScrollList(holidayName, holidayDesc) # # if self.myDate.day == 31 and self.myDate.month == 1: # holidayName = "Skelecog Legal Eagle" # holidayDesc = "Skelecog Legal Eagles are invading Toontown in masses! Stop them!" # self.addTitleAndDescToScrollList(holidayName, holidayDesc) # # if self.myDate.day == 31 and self.myDate.month == 3: # holidayName = "Skelecog Legal Eagles" # holidayDesc = "Skelecog Legal Eagles are invading Toontown in masses! Stop them!" # self.addTitleAndDescToScrollList(holidayName, holidayDesc) # # if self.myDate.day == 31 and self.myDate.month == 5: # holidayName = "Skelecog Legal Eagles" # holidayDesc = "Skelecog Legal Eagles are invading Toontown in masses! Stop them!" # self.addTitleAndDescToScrollList(holidayName, holidayDesc) # # if self.myDate.day == 31 and self.myDate.month == 7: # holidayName = "Skelecog Legal Eagles" # holidayDesc = "Skelecog Legal Eagles are invading Toontown in masses! Stop them!" # self.addTitleAndDescToScrollList(holidayName, holidayDesc) # # if self.myDate.day == 31 and self.myDate.month == 8: # holidayName = "Skelecog Legal Eagles" # holidayDesc = "Skelecog Legal Eagles are invading Toontown in masses! Stop them!" # self.addTitleAndDescToScrollList(holidayName, holidayDesc) # # if self.myDate.day == 31 and self.myDate.month == 10 : # holidayName = "Skelecog Legal Eagles" # holidayDesc = "Skelecog Legal Eagles are invading Toontown in masses! Stop them!" # self.addTitleAndDescToScrollList(holidayName, holidayDesc) # # if self.myDate.day == 31 and self.myDate.month == 12: # holidayName = "Skelecog Legal Eagles" # holidayDesc = "Skelecog Legal Eagles are invading Toontown in masses! Stop them!" # self.addTitleAndDescToScrollList(holidayName, holidayDesc) # # if self.myDate.day == 30 and self.myDate.month == 4: # holidayName = "Skelecog Legal Eagles" # holidayDesc = "Skelecog Legal Eagles are invading Toontown in masses! Stop them!" # self.addTitleAndDescToScrollList(holidayName, holidayDesc) # # if self.myDate.day == 30 and self.myDate.month == 6: # holidayName = "Skelecog Legal Eagles" # holidayDesc = "Skelecog Legal Eagles are invading Toontown in masses! Stop them!" # self.addTitleAndDescToScrollList(holidayName, holidayDesc) # # if self.myDate.day == 30 and self.myDate.month == 9: # holidayName = "Skelecog Legal Eagles" # holidayDesc = "Skelecog Legal Eagles are invading Toontown in masses! Stop them!" # self.addTitleAndDescToScrollList(holidayName, holidayDesc) # # if self.myDate.day == 30 and self.myDate.month == 11: # holidayName = "Skelecog Legal Eagles" # holidayDesc = "Skelecog Legal Eagles are invading Toontown in masses! Stop them!" # self.addTitleAndDescToScrollList(holidayName, holidayDesc) # # if self.myDate.day == 29 and self.myDate.month == 2: # holidayName = "Skelecog Legal Eagles" # holidayDesc = "Skelecog Legal Eagles are invading Toontown in masses! Stop them!" # self.addTitleAndDescToScrollList(holidayName, holidayDesc) oncelyHolidays = base.cr.newsManager.getOncelyHolidaysForDate(self.myDate) for holiday in oncelyHolidays: holidayId = holiday[1] holidayStart = holiday[2] holidayEnd = holiday[3] holidayType = holiday[0] if holidayStart[0] == self.myDate.year and holidayStart[1] == self.myDate.month and holidayStart[2] == self.myDate.day: myTime = datetime.time(holidayStart[3], holidayStart[4]) elif holidayEnd[0] == self.myDate.year and holidayEnd[1] == self.myDate.month and holidayEnd[2] == self.myDate.day: myTime = datetime.time(holidayEnd[3], holidayEnd[4]) else: self.notify.error('holiday is not today %s' % holiday) self.timedEvents.append((myTime, holiday)) multipleStartHolidays = base.cr.newsManager.getMultipleStartHolidaysForDate(self.myDate) for holiday in multipleStartHolidays: holidayId = holiday[1] holidayStart = holiday[2] holidayEnd = holiday[3] holidayType = holiday[0] if holidayStart[0] == self.myDate.year and holidayStart[1] == self.myDate.month and holidayStart[2] == self.myDate.day: myTime = datetime.time(holidayStart[3], holidayStart[4]) elif holidayEnd[0] == self.myDate.year and holidayEnd[1] == self.myDate.month and holidayEnd[2] == self.myDate.day: myTime = datetime.time(holidayEnd[3], holidayEnd[4]) else: self.notify.error('holiday is not today %s' % holiday) self.timedEvents.append((myTime, holiday)) relativelyHolidays = base.cr.newsManager.getRelativelyHolidaysForDate(self.myDate) for holiday in relativelyHolidays: holidayId = holiday[1] holidayStart = holiday[2] holidayEnd = holiday[3] holidayType = holiday[0] if holidayStart[0] == self.myDate.month and holidayStart[1] == self.myDate.day: myTime = datetime.time(holidayStart[2], holidayStart[3]) elif holidayEnd[0] == self.myDate.month and holidayEnd[1] == self.myDate.day: myTime = datetime.time(holidayEnd[2], holidayEnd[3]) else: self.notify.error('holiday is not today %s' % holiday) self.timedEvents.append((myTime, holiday)) def timedEventCompare(te1, te2): if te1[0] < te2[0]: return -1 elif te1[0] == te2[0]: return 0 else: return 1 self.timedEvents.sort(cmp=timedEventCompare) for timedEvent in self.timedEvents: if isinstance(timedEvent[1], PartyInfo): self.addPartyToScrollList(timedEvent[1]) elif isinstance(timedEvent[1], tuple) and timedEvent[1][0] == NewsManager.YearlyHolidayType: self.addYearlyHolidayToScrollList(timedEvent[1]) elif isinstance(timedEvent[1], tuple) and timedEvent[1][0] == NewsManager.OncelyHolidayType: self.addOncelyHolidayToScrollList(timedEvent[1]) elif isinstance(timedEvent[1], tuple) and timedEvent[1][0] == NewsManager.OncelyMultipleStartHolidayType: self.addOncelyMultipleStartHolidayToScrollList(timedEvent[1]) elif isinstance(timedEvent[1], tuple) and timedEvent[1][0] == NewsManager.RelativelyHolidayType: self.addRelativelyHolidayToScrollList(timedEvent[1]) def addYearlyHolidayToScrollList(self, holiday): holidayId = holiday[1] holidayStart = holiday[2] holidayEnd = holiday[3] holidayType = holiday[0] holidayText = '' startTime = datetime.time(holidayStart[2], holidayStart[3]) endTime = datetime.time(holidayEnd[2], holidayEnd[3]) startDate = datetime.date(self.myDate.year, holidayStart[0], holidayStart[1]) endDate = datetime.date(self.myDate.year, holidayEnd[0], holidayEnd[1]) if endDate < startDate: endDate = datetime.date(endDate.year + 1, endDate.month, endDate.day) if holidayId in TTLocalizer.HolidayNamesInCalendar: holidayName = TTLocalizer.HolidayNamesInCalendar[holidayId][0] holidayDesc = TTLocalizer.HolidayNamesInCalendar[holidayId][1] else: holidayName = TTLocalizer.UnknownHoliday % holidayId holidayDesc = TTLocalizer.UnknownHoliday % holidayId if holidayStart[0] == holidayEnd[0] and holidayStart[1] == holidayEnd[1]: holidayText = myStrftime(startTime) holidayText += ' ' + holidayName holidayDesc += ' ' + TTLocalizer.CalendarEndsAt + myStrftime(endTime) elif self.myDate.month == holidayStart[0] and self.myDate.day == holidayStart[1]: holidayText = myStrftime(startTime) holidayText += ' ' + holidayName holidayDesc = holidayName + '. ' + holidayDesc holidayDesc += ' ' + TTLocalizer.CalendarEndsAt + endDate.strftime(TTLocalizer.HolidayFormat) + myStrftime(endTime) elif self.myDate.month == holidayEnd[0] and self.myDate.day == holidayEnd[1]: holidayText = myStrftime(endTime) holidayText += ' ' + TTLocalizer.CalendarEndDash + holidayName holidayDesc = TTLocalizer.CalendarEndOf + holidayName holidayDesc += '. ' + TTLocalizer.CalendarStartedOn + startDate.strftime(TTLocalizer.HolidayFormat) + myStrftime(startTime) else: self.notify.error('unhandled case') self.addTitleAndDescToScrollList(holidayText, holidayDesc) def addOncelyHolidayToScrollList(self, holiday): holidayId = holiday[1] holidayStart = holiday[2] holidayEnd = holiday[3] holidayType = holiday[0] holidayText = '' startTime = datetime.time(holidayStart[3], holidayStart[4]) endTime = datetime.time(holidayEnd[3], holidayEnd[4]) startDate = datetime.date(holidayStart[0], holidayStart[1], holidayStart[2]) endDate = datetime.date(holidayStart[0], holidayEnd[1], holidayEnd[2]) if endDate < startDate: endDate = datetime.date(endDate.year + 1, endDate.month, endDate.day) if holidayId in TTLocalizer.HolidayNamesInCalendar: holidayName = TTLocalizer.HolidayNamesInCalendar[holidayId][0] holidayDesc = TTLocalizer.HolidayNamesInCalendar[holidayId][1] else: holidayName = TTLocalizer.UnknownHoliday % holidayId holidayDesc = '' if holidayStart[1] == holidayEnd[1] and holidayStart[2] == holidayEnd[2]: holidayText = myStrftime(startTime) holidayText += ' ' + holidayName holidayDesc = holidayName + '. ' + holidayDesc holidayDesc += ' ' + TTLocalizer.CalendarEndsAt + myStrftime(endTime) elif self.myDate.year == holidayStart[0] and self.myDate.month == holidayStart[1] and self.myDate.day == holidayStart[2]: holidayText = myStrftime(startTime) holidayText += ' ' + holidayName holidayDesc = holidayName + '. ' + holidayDesc holidayDesc += ' ' + TTLocalizer.CalendarEndsAt + endDate.strftime(TTLocalizer.HolidayFormat) + myStrftime(endTime) elif self.myDate.year == holidayEnd[0] and self.myDate.month == holidayEnd[1] and self.myDate.day == holidayEnd[2]: holidayText = myStrftime(endTime) holidayText += ' ' + TTLocalizer.CalendarEndDash + holidayName holidayDesc = TTLocalizer.CalendarEndOf + holidayName holidayDesc += '. ' + TTLocalizer.CalendarStartedOn + startDate.strftime(TTLocalizer.HolidayFormat) + myStrftime(startTime) else: self.notify.error('unhandled case') self.addTitleAndDescToScrollList(holidayText, holidayDesc) def addOncelyMultipleStartHolidayToScrollList(self, holiday): self.addOncelyHolidayToScrollList(holiday) def addRelativelyHolidayToScrollList(self, holiday): holidayId = holiday[1] holidayStart = holiday[2] holidayEnd = holiday[3] holidayType = holiday[0] holidayText = '' startTime = datetime.time(holidayStart[2], holidayStart[3]) endTime = datetime.time(holidayEnd[2], holidayEnd[3]) startDate = datetime.date(self.myDate.year, holidayStart[0], holidayStart[1]) endDate = datetime.date(self.myDate.year, holidayEnd[0], holidayEnd[1]) if endDate < startDate: endDate.year += 1 if holidayId in TTLocalizer.HolidayNamesInCalendar: holidayName = TTLocalizer.HolidayNamesInCalendar[holidayId][0] holidayDesc = TTLocalizer.HolidayNamesInCalendar[holidayId][1] else: holidayName = TTLocalizer.UnknownHoliday % holidayId holidayDesc = '' if holidayStart[0] == holidayEnd[0] and holidayStart[1] == holidayEnd[1]: holidayText = myStrftime(startTime) holidayText += ' ' + holidayName holidayDesc += ' ' + TTLocalizer.CalendarEndsAt + myStrftime(endTime) elif self.myDate.month == holidayStart[0] and self.myDate.day == holidayStart[1]: holidayText = myStrftime(startTime) holidayText += ' ' + holidayName holidayDesc = holidayName + '. ' + holidayDesc holidayDesc += ' ' + TTLocalizer.CalendarEndsAt + endDate.strftime(TTLocalizer.HolidayFormat) + myStrftime(endTime) elif self.myDate.month == holidayEnd[0] and self.myDate.day == holidayEnd[1]: holidayText = myStrftime(endTime) holidayText += ' ' + TTLocalizer.CalendarEndDash + holidayName holidayDesc = TTLocalizer.CalendarEndOf + holidayName holidayDesc += '. ' + TTLocalizer.CalendarStartedOn + startDate.strftime(TTLocalizer.HolidayFormat) + myStrftime(startTime) else: self.notify.error('unhandled case') self.addTitleAndDescToScrollList(holidayText, holidayDesc) 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 exitedTextItem(self, newItem, mousepos): newItem.description.hide() def enteredTextItem(self, newItem, descText, descUnderItemZAdjust, mousePos): if not newItem.description.checkedHeight: newItem.description.checkedHeight = True newItem.description['text'] = descText bounds = newItem.description.getBounds() descHeight = newItem.description.getHeight() scrollItemHeight = newItem.getHeight() descOverItemZAdjust = descHeight - scrollItemHeight / 2.0 descZPos = self.getPos(aspect2d)[2] + descUnderItemZAdjust - descHeight if descZPos < -1.0: newItem.description.setZ(descOverItemZAdjust) descWidth = newItem.description.getWidth() brightFrame = loader.loadModel('phase_4/models/parties/tt_m_gui_sbk_calendar_popUp_bg') newItem.description['geom'] = brightFrame newItem.description['geom_scale'] = (descWidth, 1, descHeight) descGeomZ = (bounds[2] - bounds[3]) / 2.0 descGeomZ += bounds[3] newItem.description['geom_pos'] = (0, 0, descGeomZ) newItem.description.show() 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 __clickedOnScrollItem(self): self.__clickedOnDay() def __clickedOnDay(self): acceptClick = True if self.onlyFutureDaysClickable: curServerDate = base.cr.toontownTimeManager.getCurServerDateTime() if self.myDate.date() < curServerDate.date(): acceptClick = False if not acceptClick: return if self.dayClickCallback: self.dayClickCallback(self) self.notify.debug('we got clicked on %s' % self.myDate.date()) messenger.send('clickedOnDay', [self.myDate.date()]) def updateSelected(self, selected): multiplier = 1.1 if selected: self.selectedFrame.show() self.setScale(multiplier) self.setPos(-0.01, 0, 0.01) grandParent = self.origParent.getParent() self.origParent.reparentTo(grandParent) else: self.selectedFrame.hide() self.setScale(1.0) self.setPos(0, 0, 0) def changeDate(self, startDate, myDate): self.startDate = startDate self.myDate = myDate self.scrollList.removeAndDestroyAllItems() self.update() def update(self): self.numberWidget['text'] = str(self.myDate.day) self.adjustForMonth() self.addWeeklyHolidays() self.collectTimedEvents() self.updateArrowButtons() def changeFilter(self, filter): oldFilter = self.filter self.filter = filter if self.filter != oldFilter: self.scrollList.removeAndDestroyAllItems() self.update()
class FriendsList(DirectFrame): notify = DirectNotifyGlobal.directNotify.newCategory('FriendsList') def __init__(self): DirectFrame.__init__(self, parent=base.a2dTopRight, pos=(-0.25, 0.0, -0.46)) gui = loader.loadModel('phase_3.5/models/gui/friendslist_gui.bam') self['image'] = gui.find('**/FriendsBox_Open') self.headingText = OnscreenText(text='', parent=self, pos=(0.01, 0.2), fg=(0.1, 0.1, 0.4, 1.0), scale=0.04) self.frameForNames = DirectScrolledList(frameSize=(0.0, 0.35, 0, 0.35), incButton_geom=(gui.find('**/FndsLst_ScrollUp'), gui.find('**/FndsLst_ScrollDN'), gui.find('**/FndsLst_ScrollUp_Rllvr'), gui.find('**/FndsLst_ScrollUp')), incButton_relief=None, incButton_hpr=(0, 0, 180), incButton_pos=(0.17, 0, -0.04), decButton_geom=(gui.find('**/FndsLst_ScrollUp'), gui.find('**/FndsLst_ScrollDN'), gui.find('**/FndsLst_ScrollUp_Rllvr'), gui.find('**/FndsLst_ScrollUp')), decButton_relief=None, decButton_pos=(0.17, 0, 0.395), pos=(-0.1625, 0.0, -0.27), parent=self, numItemsVisible=9, forceHeight=0.04, itemFrame_frameSize=(-0.15, 0.15, 0, -0.35), itemFrame_pos=(0, 0, 0.3275), itemFrame_relief=None, relief=None) self.fwdBtn = DirectButton(geom=(gui.find('**/Horiz_Arrow_UP'), gui.find('**/Horiz_Arrow_DN'), gui.find('**/Horiz_Arrow_Rllvr'), gui.find('**/Horiz_Arrow_UP')), relief=None, parent=self, pos=(0.17, 0.0, -0.38), command=self.doState) self.backBtn = DirectButton(geom=(gui.find('**/Horiz_Arrow_UP'), gui.find('**/Horiz_Arrow_DN'), gui.find('**/Horiz_Arrow_Rllvr'), gui.find('**/Horiz_Arrow_UP')), relief=None, parent=self, pos=(-0.15, 0.0, -0.38), hpr=(180, 0, 0), command=self.doState) self.closeBtn = DirectButton(geom=CIGlobals.getCancelBtnGeom(), relief=None, parent=self, command=self.exitClicked) self.closeBtn.setPos(0.015, 0.0, -0.375) gui.removeNode() del gui self.hide() self.friends = {} self.onlineFriends = {} self.fsm = ClassicFSM.ClassicFSM('FriendsList', [State.State('off', self.enterOff, self.exitOff), State.State('onlineFriendsList', self.enterOnlineFriendsList, self.exitOnlineFriendsList), State.State('allFriendsList', self.enterAllFriendsList, self.exitAllFriendsList)], 'off', 'off') self.fsm.enterInitialState() self.accept('gotFriendsList', self.handleFriendsList) return def destroy(self): self.ignore('gotFriendsList') self.fsm.requestFinalState() del self.fsm self.headingText.destroy() del self.headingText self.frameForNames.destroy() del self.frameForNames self.fwdBtn.destroy() del self.fwdBtn self.backBtn.destroy() del self.backBtn self.closeBtn.destroy() del self.closeBtn del self.friends del self.onlineFriends DirectFrame.destroy(self) def doState(self, state): self.fsm.request(state) def exitClicked(self): self.fsm.request('off') base.localAvatar.showFriendButton() def setButtons(self, fwd = None, back = None): if fwd: self.fwdBtn['extraArgs'] = [fwd] self.fwdBtn['state'] = DGG.NORMAL else: self.fwdBtn['extraArgs'] = [] self.fwdBtn['state'] = DGG.DISABLED if back: self.backBtn['extraArgs'] = [back] self.backBtn['state'] = DGG.NORMAL else: self.backBtn['extraArgs'] = [] self.backBtn['state'] = DGG.DISABLED def handleFriendsList(self, friendIdArray, nameArray, flags): self.friends = {} self.onlineFriends = {} for i in xrange(len(friendIdArray)): avatarId = friendIdArray[i] name = nameArray[i] self.friends[avatarId] = name if flags[i] == 1: self.onlineFriends[avatarId] = name def enterOff(self): self.hide() def exitOff(self): self.show() def addFriend(self, name, avatarId): self.frameForNames.addItem(DirectButton(text=name, extraArgs=[avatarId], command=self.friendClicked, scale=0.035, relief=None, text1_bg=textDownColor, text2_bg=textRolloverColor, text_align=TextNode.ALeft)) return def friendClicked(self, avatarId): self.fsm.request('off') base.localAvatar.panel.makePanel(avatarId) def resetAll(self): self.headingText.setText('') self.frameForNames.removeAndDestroyAllItems() self.setButtons(None, None) return def sortListItems(self): self.frameForNames['items'].sort(key=lambda x: x['text']) self.frameForNames.refresh() def enterAllFriendsList(self): self.headingText.setText('All\nFriends') for friendId, name in self.friends.items(): self.addFriend(name, friendId) self.sortListItems() self.setButtons(None, 'onlineFriendsList') return def exitAllFriendsList(self): self.resetAll() def enterOnlineFriendsList(self): self.headingText.setText('Online\nFriends') for friendId, name in self.onlineFriends.items(): self.addFriend(name, friendId) self.sortListItems() self.setButtons('allFriendsList', None) return def exitOnlineFriendsList(self): self.resetAll()
class CalendarGuiDay(DirectFrame): """A class to represent the gui for one day in the month. Do not put references to the shtiker page or book, so this class may be extended later.""" notify = directNotify.newCategory("CalendarGuiDay") ScrollListTextSize = 0.03 def __init__(self, parent, myDate, startDate, dayClickCallback=None, onlyFutureDaysClickable=False): """Construct ourself.""" self.origParent = parent self.startDate = startDate self.myDate = myDate self.dayClickCallback = dayClickCallback # If true, only allow clicks on days in the future self.onlyFutureDaysClickable = onlyFutureDaysClickable DirectFrame.__init__(self, parent=parent) self.timedEvents = [] self.partiesInvitedToToday = [] self.hostedPartiesToday = [] self.yearlyHolidaysToday = [] # either ending or starting today self.showMarkers = base.config.GetBool('show-calendar-markers', 0) self.filter = ToontownGlobals.CalendarFilterShowAll self.load() # self.createDummyLocators() self.createGuiObjects() self.update() def createDummyLocators(self): """Put some programming locators until we get the real art assets.""" self.dayButtonLocator = self.attachNewNode('dayButtonLocator') self.dayButtonLocator.setX(0.1) self.dayButtonLocator.setZ(-0.05) self.numberLocator = self.attachNewNode('numberLocator') self.numberLocator.setX(0.09) self.scrollLocator = self.attachNewNode('scrollLocator') self.selectedLocator = self.attachNewNode('selectedLocator') self.selectedLocator.setX(0.11) self.selectedLocator.setZ(-0.06) def load(self): """Load the assets, and make sure locators are there.""" dayAsset = loader.loadModel( 'phase_4/models/parties/tt_m_gui_sbk_calendar_box') dayAsset.reparentTo(self) self.dayButtonLocator = self.find('**/loc_origin') self.numberLocator = self.find('**/loc_number') self.scrollLocator = self.find('**/loc_topLeftList') self.selectedLocator = self.find('**/loc_origin') self.todayBox = self.find('**/boxToday') self.todayBox.hide() self.selectedFrame = self.find('**/boxHover') self.selectedFrame.hide() self.defaultBox = self.find('**/boxBlank') self.scrollBottomRightLocator = self.find('**/loc_bottomRightList') self.scrollDownLocator = self.find('**/loc_scrollDown') self.attachMarker(self.scrollDownLocator) self.scrollUpLocator = self.find('**/loc_scrollUp') self.attachMarker(self.scrollUpLocator) def attachMarker(self, parent, scale=0.005, color=(1, 0, 0)): """Attach a marker to the parent to aid in visual debugging.""" if self.showMarkers: marker = loader.loadModel("phase_3/models/misc/sphere") marker.reparentTo(parent) marker.setScale(scale) marker.setColor(*color) def createGuiObjects(self): """Create the other gui objects in the month, assumes we have proper locators.""" # we create an invisible button so the day can be clicked on self.dayButton = DirectButton( parent=self.dayButtonLocator, image=self.selectedFrame, relief=None, command=self.__clickedOnDay, # next three settings are for debug pressEffect=1, rolloverSound=None, clickSound=None) self.numberWidget = DirectLabel( parent=self.numberLocator, relief=None, text=str(self.myDate.day), text_scale=0.04, text_align=TextNode.ACenter, text_font=ToontownGlobals.getInterfaceFont(), text_fg=Vec4(110 / 255.0, 126 / 255.0, 255 / 255.0, 1), ) self.attachMarker(self.numberLocator) self.listXorigin = 0 self.listFrameSizeX = self.scrollBottomRightLocator.getX( ) - self.scrollLocator.getX() self.scrollHeight = self.scrollLocator.getZ( ) - self.scrollBottomRightLocator.getZ() self.listZorigin = self.scrollBottomRightLocator.getZ() self.listFrameSizeZ = self.scrollLocator.getZ( ) - self.scrollBottomRightLocator.getZ() self.arrowButtonXScale = 1 self.arrowButtonZScale = 1 self.itemFrameXorigin = 0 self.itemFrameZorigin = 0 self.buttonXstart = self.itemFrameXorigin + 0.21 self.gui = loader.loadModel("phase_3.5/models/gui/friendslist_gui") buttonOffSet = -0.01 # these settings put the arrow buttons on the top incButtonPos = (0.0, 0, 0) decButtonPos = (0.0, 0, 0) # these settings put the arrow buttons on the right side # incButtonPos = (self.buttonXstart,0,self.listZorigin - buttonOffSet) # decButtonPos = (self.buttonXstart, 0, self.listZorigin + self.listFrameSizeZ + buttonOffSet) itemFrameMinZ = self.listZorigin itemFrameMaxZ = self.listZorigin + self.listFrameSizeZ arrowUp = self.find("**/downScroll_up") arrowDown = self.find("**/downScroll_down") arrowHover = self.find("**/downScroll_hover") self.scrollList = DirectScrolledList( parent=self.scrollLocator, relief=None, pos=(0, 0, 0), # inc and dec are DirectButtons # incButton is on the bottom of page, decButton is on the top! incButton_image=( arrowUp, arrowDown, arrowHover, arrowUp, ), incButton_relief=None, incButton_scale=(self.arrowButtonXScale, 1, self.arrowButtonZScale), incButton_pos=incButtonPos, # Make the disabled button fade out incButton_image3_color=Vec4(1, 1, 1, 0.2), decButton_image=( arrowUp, arrowDown, arrowHover, arrowUp, ), decButton_relief=None, decButton_scale=(self.arrowButtonXScale, 1, -self.arrowButtonZScale), decButton_pos=decButtonPos, # Make the disabled button fade out decButton_image3_color=Vec4(1, 1, 1, 0.2), # itemFrame is a DirectFrame, shift it down a bit to match top left scroll itemFrame_pos=(self.itemFrameXorigin, 0, -0.03), # each item is a button with text on it numItemsVisible=4, # so we select the day when we click on a scroll button incButtonCallback=self.scrollButtonPressed, decButtonCallback=self.scrollButtonPressed, ) # make sure the arrow buttons appear over item frame itemFrameParent = self.scrollList.itemFrame.getParent() self.scrollList.incButton.reparentTo(self.scrollDownLocator) self.scrollList.decButton.reparentTo(self.scrollUpLocator) arrowUp.removeNode() arrowDown.removeNode() arrowHover.removeNode() # Set up a clipping plane to truncate names that would extend # off the right end of the scrolled list. clipper = PlaneNode('clipper') clipper.setPlane(Plane(Vec3(-1, 0, 0), Point3(0.23, 0, 0))) clipNP = self.scrollList.component('itemFrame').attachNewNode(clipper) self.scrollList.component('itemFrame').setClipPlane(clipNP) def scrollButtonPressed(self): """Select the current day when the scroll button is pressed.""" self.__clickedOnDay() def adjustForMonth(self): """Darken us if we are not in the same month as startDate.""" # make us glow if are equal to the serverDate curServerDate = base.cr.toontownTimeManager.getCurServerDateTime() if self.onlyFutureDaysClickable: if self.myDate.year < curServerDate.year or \ ( self.myDate.year == curServerDate.year and self.myDate.month < curServerDate.month ) or \ ( self.myDate.year == curServerDate.year and self.myDate.month == curServerDate.month and self.myDate.day < curServerDate.day ): self.numberWidget.setColorScale(0.5, 0.5, 0.5, 0.5) self.numberWidget['state'] = DirectGuiGlobals.DISABLED else: self.numberWidget.setColorScale(1, 1, 1, 1) if self.myDate.month != self.startDate.month: self.setColorScale(0.75, 0.75, 0.75, 1.0) if self.dayClickCallback is not None: self.numberWidget['state'] = DirectGuiGlobals.DISABLED else: self.setColorScale(1, 1, 1, 1) if self.myDate.date() == curServerDate.date(): self.defaultBox.hide() self.todayBox.show() else: self.defaultBox.show() self.todayBox.hide() def destroy(self): if self.dayClickCallback is not None: self.numberWidget.destroy() self.dayClickCallback = None self.notify.debug('desroying %s' % self.myDate) try: for item in self.scrollList['items']: if hasattr(item, "description") and item.description and hasattr( item.description, 'destroy'): self.notify.debug('desroying description of item %s' % item) item.unbind(DGG.ENTER) item.unbind(DGG.EXIT) item.description.destroy() except e: self.notify.debug('pass %s' % self.myDate) # an empty scroll list will come to this point pass self.scrollList.removeAndDestroyAllItems() self.scrollList.destroy() self.dayButton.destroy() DirectFrame.destroy(self) def addWeeklyHolidays(self): """Add weekly holidays to our scroll list.""" if not (self.filter == ToontownGlobals.CalendarFilterShowAll or \ self.filter == ToontownGlobals.CalendarFilterShowOnlyHolidays): return if base.cr.newsManager: holidays = base.cr.newsManager.getHolidaysForWeekday( self.myDate.weekday()) holidayName = "" holidayDesc = "" for holidayId in holidays: if holidayId in TTLocalizer.HolidayNamesInCalendar: holidayName = TTLocalizer.HolidayNamesInCalendar[ holidayId][0] holidayDesc = TTLocalizer.HolidayNamesInCalendar[ holidayId][1] else: holidayName = TTLocalizer.UnknownHoliday % holidayId self.addTitleAndDescToScrollList(holidayName, holidayDesc) self.scrollList.refresh() if base.config.GetBool('calendar-test-items', 0): # add test items just so we see scroll list arrows if self.myDate.date() + datetime.timedelta( days=-1 ) == base.cr.toontownTimeManager.getCurServerDateTime().date(): testItems = ("1:00 AM Party", "2:00 AM CEO", "11:15 AM Party", "5:30 PM CJ", "11:00 PM Party", "Really Really Long String") for text in testItems: newItem = DirectLabel( relief=None, text=text, text_scale=self.ScrollListTextSize, text_align=TextNode.ALeft, ) self.scrollList.addItem(newItem) if self.myDate.date() + datetime.timedelta( days=-2 ) == base.cr.toontownTimeManager.getCurServerDateTime().date(): testItems = ( "1:00 AM Party", "3:00 AM CFO", "11:00 AM Party", ) textSize = self.ScrollListTextSize for text in testItems: newItem = DirectLabel( relief=None, text=text, text_scale=textSize, text_align=TextNode.ALeft, ) self.scrollList.addItem(newItem) def updateArrowButtons(self): """If we don't have anything in out scroll list, hide the arrow buttons.""" numItems = 0 try: numItems = len(self.scrollList['items']) except e: numItems = 0 if numItems <= self.scrollList.numItemsVisible: self.scrollList.incButton.hide() self.scrollList.decButton.hide() else: self.scrollList.incButton.show() self.scrollList.decButton.show() def collectTimedEvents(self): """Sort by time the events in my day.""" # possible events would be yearly holidays, # oncely holidays and relatively holidays # parties # and in the future planned boss battle raids self.timedEvents = [] if (self.filter == ToontownGlobals.CalendarFilterShowAll or \ self.filter == ToontownGlobals.CalendarFilterShowOnlyParties): for party in localAvatar.partiesInvitedTo: #if self.myDate.month == 9 and self.myDate.day == 1: # import pdb; pdb.set_trace() if party.startTime.date() == self.myDate.date(): self.partiesInvitedToToday.append(party) self.timedEvents.append((party.startTime.time(), party)) for party in localAvatar.hostedParties: if party.startTime.date() == self.myDate.date(): self.hostedPartiesToday.append(party) self.timedEvents.append((party.startTime.time(), party)) if base.cr.newsManager and (self.filter == ToontownGlobals.CalendarFilterShowAll or \ self.filter == ToontownGlobals.CalendarFilterShowOnlyHolidays): yearlyHolidays = base.cr.newsManager.getYearlyHolidaysForDate( self.myDate) for holiday in yearlyHolidays: holidayId = holiday[1] holidayStart = holiday[2] holidayEnd = holiday[3] holidayType = holiday[0] if holidayStart[0] == self.myDate.month and \ holidayStart[1] == self.myDate.day: myTime = datetime.time(holidayStart[2], holidayStart[3]) elif holidayEnd[0] == self.myDate.month and \ holidayEnd[1] == self.myDate.day: myTime = datetime.time(holidayEnd[2], holidayEnd[3]) else: self.notify.error('holiday is not today %s' % holiday) self.timedEvents.append((myTime, holiday)) oncelyHolidays = base.cr.newsManager.getOncelyHolidaysForDate( self.myDate) for holiday in oncelyHolidays: holidayId = holiday[1] holidayStart = holiday[2] holidayEnd = holiday[3] holidayType = holiday[0] if holidayStart[0] == self.myDate.year and \ holidayStart[1] == self.myDate.month and \ holidayStart[2] == self.myDate.day: myTime = datetime.time(holidayStart[3], holidayStart[4]) elif holidayEnd[0] == self.myDate.year and \ holidayEnd[1] == self.myDate.month and \ holidayEnd[2] == self.myDate.day: myTime = datetime.time(holidayEnd[3], holidayEnd[4]) else: self.notify.error('holiday is not today %s' % holiday) self.timedEvents.append((myTime, holiday)) multipleStartHolidays = base.cr.newsManager.getMultipleStartHolidaysForDate( self.myDate) for holiday in multipleStartHolidays: holidayId = holiday[1] holidayStart = holiday[2] holidayEnd = holiday[3] holidayType = holiday[0] if holidayStart[0] == self.myDate.year and \ holidayStart[1] == self.myDate.month and \ holidayStart[2] == self.myDate.day: myTime = datetime.time(holidayStart[3], holidayStart[4]) elif holidayEnd[0] == self.myDate.year and \ holidayEnd[1] == self.myDate.month and \ holidayEnd[2] == self.myDate.day: myTime = datetime.time(holidayEnd[3], holidayEnd[4]) else: self.notify.error('holiday is not today %s' % holiday) self.timedEvents.append((myTime, holiday)) relativelyHolidays = base.cr.newsManager.getRelativelyHolidaysForDate( self.myDate) for holiday in relativelyHolidays: holidayId = holiday[1] holidayStart = holiday[2] holidayEnd = holiday[3] holidayType = holiday[0] if holidayStart[0] == self.myDate.month and \ holidayStart[1] == self.myDate.day: myTime = datetime.time(holidayStart[2], holidayStart[3]) elif holidayEnd[0] == self.myDate.month and \ holidayEnd[1] == self.myDate.day: myTime = datetime.time(holidayEnd[2], holidayEnd[3]) else: self.notify.error('holiday is not today %s' % holiday) self.timedEvents.append((myTime, holiday)) # sort timedEvents def timedEventCompare(te1, te2): if te1[0] < te2[0]: return -1 elif te1[0] == te2[0]: return 0 else: return 1 self.timedEvents.sort(cmp=timedEventCompare) # now add them to the scroll list for timedEvent in self.timedEvents: if isinstance(timedEvent[1], PartyInfo): self.addPartyToScrollList(timedEvent[1]) elif isinstance( timedEvent[1], tuple ) and timedEvent[1][0] == NewsManager.YearlyHolidayType: self.addYearlyHolidayToScrollList(timedEvent[1]) elif isinstance( timedEvent[1], tuple ) and timedEvent[1][0] == NewsManager.OncelyHolidayType: self.addOncelyHolidayToScrollList(timedEvent[1]) elif isinstance(timedEvent[1], tuple) and timedEvent[1][ 0] == NewsManager.OncelyMultipleStartHolidayType: self.addOncelyMultipleStartHolidayToScrollList(timedEvent[1]) elif isinstance( timedEvent[1], tuple ) and timedEvent[1][0] == NewsManager.RelativelyHolidayType: self.addRelativelyHolidayToScrollList(timedEvent[1]) def addYearlyHolidayToScrollList(self, holiday): """Add a yearly holiday to the scroll list. Could be start date or end date""" # first figure out if it ends on the same day holidayId = holiday[1] holidayStart = holiday[2] holidayEnd = holiday[3] holidayType = holiday[0] holidayText = "" startTime = datetime.time(holidayStart[2], holidayStart[3]) endTime = datetime.time(holidayEnd[2], holidayEnd[3]) startDate = datetime.date(self.myDate.year, holidayStart[0], holidayStart[1]) endDate = datetime.date(self.myDate.year, holidayEnd[0], holidayEnd[1]) if endDate < startDate: endDate = datetime.date(endDate.year + 1, endDate.month, endDate.day) if holidayId in TTLocalizer.HolidayNamesInCalendar: holidayName = TTLocalizer.HolidayNamesInCalendar[holidayId][0] holidayDesc = TTLocalizer.HolidayNamesInCalendar[holidayId][1] else: holidayName = TTLocalizer.UnknownHoliday % holidayId holidayDesc = TTLocalizer.UnknownHoliday % holidayId if holidayStart[0] == holidayEnd[0] and \ holidayStart[1] == holidayEnd[1]: # end of holiday is on the same day holidayText = myStrftime(startTime) holidayText += " " + holidayName holidayDesc += " " + TTLocalizer.CalendarEndsAt + myStrftime( endTime) elif self.myDate.month == holidayStart[0] and \ self.myDate.day == holidayStart[1]: holidayText = myStrftime(startTime) holidayText += " " + holidayName holidayDesc = holidayName + ". " + holidayDesc holidayDesc += " " + TTLocalizer.CalendarEndsAt + endDate.strftime( TTLocalizer.HolidayFormat) + myStrftime(endTime) elif self.myDate.month == holidayEnd[0] and \ self.myDate.day == holidayEnd[1]: holidayText = myStrftime(endTime) holidayText += " " + TTLocalizer.CalendarEndDash + holidayName holidayDesc = TTLocalizer.CalendarEndOf + holidayName holidayDesc += ". " + TTLocalizer.CalendarStartedOn + startDate.strftime( TTLocalizer.HolidayFormat) + myStrftime(startTime) else: self.notify.error('unhandled case') self.addTitleAndDescToScrollList(holidayText, holidayDesc) def addOncelyHolidayToScrollList(self, holiday): """Add a oncely holiday to the scroll list. Could be start date or end date""" # first figure out if it ends on the same day holidayId = holiday[1] holidayStart = holiday[2] holidayEnd = holiday[3] holidayType = holiday[0] holidayText = "" startTime = datetime.time(holidayStart[3], holidayStart[4]) endTime = datetime.time(holidayEnd[3], holidayEnd[4]) startDate = datetime.date(holidayStart[0], holidayStart[1], holidayStart[2]) endDate = datetime.date(holidayStart[0], holidayEnd[1], holidayEnd[2]) if endDate < startDate: endDate = datetime.date(endDate.year + 1, endDate.month, endDate.day) if holidayId in TTLocalizer.HolidayNamesInCalendar: holidayName = TTLocalizer.HolidayNamesInCalendar[holidayId][0] holidayDesc = TTLocalizer.HolidayNamesInCalendar[holidayId][1] else: holidayName = TTLocalizer.UnknownHoliday % holidayId holidayDesc = "" if holidayStart[1] == holidayEnd[1] and \ holidayStart[2] == holidayEnd[2]: # end of holiday is on the same day holidayText = myStrftime(startTime) holidayText += " " + holidayName holidayDesc = holidayName + ". " + holidayDesc holidayDesc += " " + TTLocalizer.CalendarEndsAt + myStrftime( endTime) elif self.myDate.year == holidayStart[0] and \ self.myDate.month == holidayStart[1] and \ self.myDate.day == holidayStart[2]: holidayText = myStrftime(startTime) holidayText += " " + holidayName holidayDesc = holidayName + ". " + holidayDesc holidayDesc += " " + TTLocalizer.CalendarEndsAt + endDate.strftime( TTLocalizer.HolidayFormat) + myStrftime(endTime) elif self.myDate.year == holidayEnd[0] and \ self.myDate.month == holidayEnd[1] and \ self.myDate.day == holidayEnd[2]: holidayText = myStrftime(endTime) holidayText += " " + TTLocalizer.CalendarEndDash + holidayName holidayDesc = TTLocalizer.CalendarEndOf + holidayName holidayDesc += ". " + TTLocalizer.CalendarStartedOn + startDate.strftime( TTLocalizer.HolidayFormat) + myStrftime(startTime) else: self.notify.error('unhandled case') self.addTitleAndDescToScrollList(holidayText, holidayDesc) def addOncelyMultipleStartHolidayToScrollList(self, holiday): """Add a multiple start holiday to the scroll list. Could be start date or end date""" # I can't think of anything different we'd do from addOncely, so just call that self.addOncelyHolidayToScrollList(holiday) def addRelativelyHolidayToScrollList(self, holiday): """Add a relatively holiday to the scroll list. Could be start date or end date""" # first figure out if it ends on the same day holidayId = holiday[1] holidayStart = holiday[2] holidayEnd = holiday[3] holidayType = holiday[0] holidayText = "" startTime = datetime.time(holidayStart[2], holidayStart[3]) endTime = datetime.time(holidayEnd[2], holidayEnd[3]) startDate = datetime.date(self.myDate.year, holidayStart[0], holidayStart[1]) endDate = datetime.date(self.myDate.year, holidayEnd[0], holidayEnd[1]) if endDate < startDate: endDate.year += 1 if holidayId in TTLocalizer.HolidayNamesInCalendar: holidayName = TTLocalizer.HolidayNamesInCalendar[holidayId][0] holidayDesc = TTLocalizer.HolidayNamesInCalendar[holidayId][1] else: holidayName = TTLocalizer.UnknownHoliday % holidayId holidayDesc = "" if holidayStart[0] == holidayEnd[0] and \ holidayStart[1] == holidayEnd[1]: # end of holiday is on the same day holidayText = myStrftime(startTime) holidayText += " " + holidayName holidayDesc += " " + TTLocalizer.CalendarEndsAt + myStrftime( endTime) elif self.myDate.month == holidayStart[0] and \ self.myDate.day == holidayStart[1]: holidayText = myStrftime(startTime) holidayText += " " + holidayName holidayDesc = holidayName + ". " + holidayDesc holidayDesc += " " + TTLocalizer.CalendarEndsAt + endDate.strftime( TTLocalizer.HolidayFormat) + myStrftime(endTime) elif self.myDate.month == holidayEnd[0] and \ self.myDate.day == holidayEnd[1]: holidayText = myStrftime(endTime) holidayText += " " + TTLocalizer.CalendarEndDash + holidayName holidayDesc = TTLocalizer.CalendarEndOf + holidayName holidayDesc += ". " + TTLocalizer.CalendarStartedOn + startDate.strftime( TTLocalizer.HolidayFormat) + myStrftime(startTime) else: self.notify.error('unhandled case') self.addTitleAndDescToScrollList(holidayText, holidayDesc) 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 exitedTextItem(self, newItem, mousepos): newItem.description.hide() def enteredTextItem(self, newItem, descText, descUnderItemZAdjust, mousePos): # compute if we go over edge, then adjust if needed if not newItem.description.checkedHeight: newItem.description.checkedHeight = True newItem.description['text'] = descText bounds = newItem.description.getBounds() descHeight = newItem.description.getHeight() # lets see if we go down too far scrollItemHeight = newItem.getHeight() descOverItemZAdjust = descHeight - (scrollItemHeight / 2.0) descZPos = self.getPos( aspect2d)[2] + descUnderItemZAdjust - descHeight if descZPos < -1.0: newItem.description.setZ(descOverItemZAdjust) descWidth = newItem.description.getWidth() brightFrame = loader.loadModel( 'phase_4/models/parties/tt_m_gui_sbk_calendar_popUp_bg') newItem.description['geom'] = brightFrame newItem.description['geom_scale'] = (descWidth, 1, descHeight) descGeomZ = (bounds[2] - bounds[3]) / 2.0 descGeomZ += bounds[3] # self.notify.debug('descGeomZ=%s' % descGeomZ) newItem.description['geom_pos'] = (0, 0, descGeomZ) # self.notify.debug('descWidth=%s descHeight=%s' % (descWidth, descHeight)) newItem.description.show() 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]) def __clickedOnScrollItem(self): """Handle the user clicking on a scroll item.""" self.__clickedOnDay() def __clickedOnDay(self): """Handle user clicking on us a day square.""" acceptClick = True if self.onlyFutureDaysClickable: curServerDate = base.cr.toontownTimeManager.getCurServerDateTime() if self.myDate.date() < curServerDate.date(): acceptClick = False if not acceptClick: return if self.dayClickCallback: self.dayClickCallback(self) self.notify.debug('we got clicked on %s' % self.myDate.date()) # tell the calendarGuiMonth messenger.send('clickedOnDay', [self.myDate.date()]) def updateSelected(self, selected): # note set multiplier to 1.0 if we don't want to pop selected days multiplier = 1.1 if selected: self.selectedFrame.show() self.setScale(multiplier) self.setPos(-0.01, 0, 0.01) grandParent = self.origParent.getParent() self.origParent.reparentTo(grandParent) else: self.selectedFrame.hide() self.setScale(1.0) self.setPos(0, 0, 0) def changeDate(self, startDate, myDate): """Change the date that we are displaying.""" self.startDate = startDate self.myDate = myDate self.scrollList.removeAndDestroyAllItems() self.update() def update(self): """Fill in the day with the proper contents.""" self.numberWidget['text'] = str(self.myDate.day) self.adjustForMonth() self.addWeeklyHolidays() self.collectTimedEvents() self.updateArrowButtons() def changeFilter(self, filter): """Change our fliter, update scroll items if needed.""" oldFilter = self.filter self.filter = filter if self.filter != oldFilter: self.scrollList.removeAndDestroyAllItems() self.update()
class CalendarGuiDay(DirectFrame): notify = directNotify.newCategory('CalendarGuiDay') ScrollListTextSize = 0.03 def __init__(self, parent, myDate, startDate, dayClickCallback=None, onlyFutureDaysClickable=False): self.origParent = parent self.startDate = startDate self.myDate = myDate self.dayClickCallback = dayClickCallback self.onlyFutureDaysClickable = onlyFutureDaysClickable DirectFrame.__init__(self, parent=parent) self.timedEvents = [] self.partiesInvitedToToday = [] self.hostedPartiesToday = [] self.yearlyHolidaysToday = [] self.showMarkers = base.config.GetBool('show-calendar-markers', 0) self.filter = ToontownGlobals.CalendarFilterShowAll self.load() self.createGuiObjects() self.update() def createDummyLocators(self): self.dayButtonLocator = self.attachNewNode('dayButtonLocator') self.dayButtonLocator.setX(0.1) self.dayButtonLocator.setZ(-0.05) self.numberLocator = self.attachNewNode('numberLocator') self.numberLocator.setX(0.09) self.scrollLocator = self.attachNewNode('scrollLocator') self.selectedLocator = self.attachNewNode('selectedLocator') self.selectedLocator.setX(0.11) self.selectedLocator.setZ(-0.06) def load(self): dayAsset = loader.loadModel( 'phase_4/models/parties/tt_m_gui_sbk_calendar_box') dayAsset.reparentTo(self) self.dayButtonLocator = self.find('**/loc_origin') self.numberLocator = self.find('**/loc_number') self.scrollLocator = self.find('**/loc_topLeftList') self.selectedLocator = self.find('**/loc_origin') self.todayBox = self.find('**/boxToday') self.todayBox.hide() self.selectedFrame = self.find('**/boxHover') self.selectedFrame.hide() self.defaultBox = self.find('**/boxBlank') self.scrollBottomRightLocator = self.find('**/loc_bottomRightList') self.scrollDownLocator = self.find('**/loc_scrollDown') self.attachMarker(self.scrollDownLocator) self.scrollUpLocator = self.find('**/loc_scrollUp') self.attachMarker(self.scrollUpLocator) def attachMarker(self, parent, scale=0.005, color=(1, 0, 0)): if self.showMarkers: marker = loader.loadModel('phase_3/models/misc/sphere') marker.reparentTo(parent) marker.setScale(scale) marker.setColor(*color) def createGuiObjects(self): self.dayButton = DirectButton(parent=self.dayButtonLocator, image=self.selectedFrame, relief=None, command=self.__clickedOnDay, pressEffect=1, rolloverSound=None, clickSound=None) self.numberWidget = DirectLabel( parent=self.numberLocator, relief=None, text=str(self.myDate.day), text_scale=0.04, text_align=TextNode.ACenter, text_font=ToontownGlobals.getInterfaceFont(), text_fg=Vec4(110 / 255.0, 126 / 255.0, 255 / 255.0, 1)) self.attachMarker(self.numberLocator) self.listXorigin = 0 self.listFrameSizeX = self.scrollBottomRightLocator.getX( ) - self.scrollLocator.getX() self.scrollHeight = self.scrollLocator.getZ( ) - self.scrollBottomRightLocator.getZ() self.listZorigin = self.scrollBottomRightLocator.getZ() self.listFrameSizeZ = self.scrollLocator.getZ( ) - self.scrollBottomRightLocator.getZ() self.arrowButtonXScale = 1 self.arrowButtonZScale = 1 self.itemFrameXorigin = 0 self.itemFrameZorigin = 0 self.buttonXstart = self.itemFrameXorigin + 0.21 self.gui = loader.loadModel('phase_3.5/models/gui/friendslist_gui') buttonOffSet = -0.01 incButtonPos = (0.0, 0, 0) decButtonPos = (0.0, 0, 0) itemFrameMinZ = self.listZorigin itemFrameMaxZ = self.listZorigin + self.listFrameSizeZ arrowUp = self.find('**/downScroll_up') arrowDown = self.find('**/downScroll_down') arrowHover = self.find('**/downScroll_hover') self.scrollList = DirectScrolledList( parent=self.scrollLocator, relief=None, pos=(0, 0, 0), incButton_image=(arrowUp, arrowDown, arrowHover, arrowUp), incButton_relief=None, incButton_scale=(self.arrowButtonXScale, 1, self.arrowButtonZScale), incButton_pos=incButtonPos, incButton_image3_color=(1, 1, 1, 0.2), decButton_image=(arrowUp, arrowDown, arrowHover, arrowUp), decButton_relief=None, decButton_scale=(self.arrowButtonXScale, 1, -self.arrowButtonZScale), decButton_pos=decButtonPos, decButton_image3_color=(1, 1, 1, 0.2), itemFrame_pos=(self.itemFrameXorigin, 0, -0.03), numItemsVisible=4, incButtonCallback=self.scrollButtonPressed, decButtonCallback=self.scrollButtonPressed) itemFrameParent = self.scrollList.itemFrame.getParent() self.scrollList.incButton.reparentTo(self.scrollDownLocator) self.scrollList.decButton.reparentTo(self.scrollUpLocator) arrowUp.removeNode() arrowDown.removeNode() arrowHover.removeNode() clipper = PlaneNode('clipper') clipper.setPlane(Plane((-1, 0, 0), (0.23, 0, 0))) clipNP = self.scrollList.component('itemFrame').attachNewNode(clipper) self.scrollList.component('itemFrame').setClipPlane(clipNP) return def scrollButtonPressed(self): self.__clickedOnDay() def adjustForMonth(self): curServerDate = base.cr.toontownTimeManager.getCurServerDateTime() if self.onlyFutureDaysClickable: if self.myDate.year < curServerDate.year or self.myDate.year == curServerDate.year and self.myDate.month < curServerDate.month or self.myDate.year == curServerDate.year and self.myDate.month == curServerDate.month and self.myDate.day < curServerDate.day: self.numberWidget.setColorScale(0.5, 0.5, 0.5, 0.5) self.numberWidget['state'] = DirectGuiGlobals.DISABLED else: self.numberWidget.setColorScale(1, 1, 1, 1) if self.myDate.month != self.startDate.month: self.setColorScale(0.75, 0.75, 0.75, 1.0) if self.dayClickCallback is not None: self.numberWidget['state'] = DirectGuiGlobals.DISABLED else: self.setColorScale(1, 1, 1, 1) if self.myDate.date() == curServerDate.date(): self.defaultBox.hide() self.todayBox.show() else: self.defaultBox.show() self.todayBox.hide() return def destroy(self): if self.dayClickCallback is not None: self.numberWidget.destroy() self.dayClickCallback = None self.notify.debug('desroying %s' % self.myDate) try: for item in self.scrollList['items']: if hasattr(item, 'description') and item.description and hasattr( item.description, 'destroy'): self.notify.debug('desroying description of item %s' % item) item.unbind(DGG.ENTER) item.unbind(DGG.EXIT) item.description.destroy() except e: self.notify.debug('pass %s' % self.myDate) self.scrollList.removeAndDestroyAllItems() self.scrollList.destroy() self.dayButton.destroy() DirectFrame.destroy(self) def updateArrowButtons(self): numItems = 0 try: numItems = len(self.scrollList['items']) except e: numItems = 0 if numItems <= self.scrollList.numItemsVisible: self.scrollList.incButton.hide() self.scrollList.decButton.hide() else: self.scrollList.incButton.show() self.scrollList.decButton.show() def collectTimedEvents(self): if self.filter == ToontownGlobals.CalendarFilterShowAll or self.filter == ToontownGlobals.CalendarFilterShowOnlyParties: for party in localAvatar.partiesInvitedTo: if party.startTime.date() == self.myDate.date(): self.addPartyToScrollList(party) for party in localAvatar.hostedParties: if party.startTime.date() == self.myDate.date(): self.addPartyToScrollList(party) if self.filter == ToontownGlobals.CalendarFilterShowAll or self.filter == ToontownGlobals.CalendarFilterShowOnlyHolidays: for id, holiday in HolidayGlobals.Holidays.iteritems(): title, description = TTLocalizer.HolidayNamesInCalendar[id] if 'weekDay' in holiday: if self.myDate.weekday() == holiday['weekDay']: self.addTitleAndDescToScrollList(title, description) elif 'startMonth' in holiday or 'startDay' in holiday: startDate = HolidayGlobals.getStartDate( holiday, self.myDate) endDate = HolidayGlobals.getEndDate(holiday, self.myDate) if self.isDateMatch(self.myDate, startDate): if self.isDateMatch(startDate, endDate): description = '%s. %s' % (title, description) else: description = '%s. %s %s %s' % ( title, description, TTLocalizer.CalendarEndsAt, endDate.strftime('%b %d')) self.addTitleAndDescToScrollList(title, description) elif self.isDateMatch(self.myDate, endDate): title = '%s %s' % (TTLocalizer.CalendarEndOf, title) description = '%s. %s %s' % ( title, TTLocalizer.CalendarStartedOn, startDate.strftime('%b %d')) self.addTitleAndDescToScrollList(title, description) def isDateMatch(self, date1, date2): return date1.day == date2.day and date1.month == date2.month 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 exitedTextItem(self, newItem, mousepos): newItem.description.hide() def enteredTextItem(self, newItem, descText, descUnderItemZAdjust, mousePos): if not newItem.description.checkedHeight: newItem.description.checkedHeight = True newItem.description['text'] = descText bounds = newItem.description.getBounds() descHeight = newItem.description.getHeight() scrollItemHeight = newItem.getHeight() descOverItemZAdjust = descHeight - scrollItemHeight / 2.0 descZPos = self.getPos( aspect2d)[2] + descUnderItemZAdjust - descHeight if descZPos < -1.0: newItem.description.setZ(descOverItemZAdjust) descWidth = newItem.description.getWidth() brightFrame = loader.loadModel( 'phase_4/models/parties/tt_m_gui_sbk_calendar_popUp_bg') newItem.description['geom'] = brightFrame newItem.description['geom_scale'] = (descWidth, 1, descHeight) descGeomZ = (bounds[2] - bounds[3]) / 2.0 descGeomZ += bounds[3] newItem.description['geom_pos'] = (0, 0, descGeomZ) newItem.description.show() 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 __clickedOnScrollItem(self): self.__clickedOnDay() def __clickedOnDay(self): acceptClick = True if self.onlyFutureDaysClickable: curServerDate = base.cr.toontownTimeManager.getCurServerDateTime() if self.myDate.date() < curServerDate.date(): acceptClick = False if not acceptClick: return if self.dayClickCallback: self.dayClickCallback(self) self.notify.debug('we got clicked on %s' % self.myDate.date()) messenger.send('clickedOnDay', [self.myDate.date()]) def updateSelected(self, selected): multiplier = 1.1 if selected: self.selectedFrame.show() self.setScale(multiplier) self.setPos(-0.01, 0, 0.01) grandParent = self.origParent.getParent() self.origParent.reparentTo(grandParent) else: self.selectedFrame.hide() self.setScale(1.0) self.setPos(0, 0, 0) def changeDate(self, startDate, myDate): self.startDate = startDate self.myDate = myDate self.scrollList.removeAndDestroyAllItems() self.update() def update(self): self.numberWidget['text'] = str(self.myDate.day) self.adjustForMonth() self.collectTimedEvents() self.updateArrowButtons() def changeFilter(self, filter): oldFilter = self.filter self.filter = filter if self.filter != oldFilter: self.scrollList.removeAndDestroyAllItems() self.update()
class MenuOptions(Menu): def __init__(self, _engine): """ This function will initialise the main screen of the options and prepare the tabs with the various settings """ Menu.__init__(self) # Engine self.engine = _engine self.initGeneralTab() self.initControlTab() self.currentTab = [0] self.tabGroup = [ DirectRadioButton( text = _("General"), variable = self.currentTab, value = [0], scale = 0.05, pos = (-0.6, 0, 0.65), command = self.showGeneralTab), DirectRadioButton( text = _("Controls"), variable = self.currentTab, value = [1], scale = 0.05, pos = (0.6, 0, 0.65), command = self.showControlTab) ] for tab in self.tabGroup: tab.reparentTo(self.frameMain) tab.setOthers(self.tabGroup) # set the text of all GUI elements self.setText() self.hideBase() def initGeneralTab(self): """ This function will set up the content of the general tab """ self.frameGeneral = DirectFrame( # size of the frame frameSize = (base.a2dLeft, base.a2dRight, -0.6, 0.6), # position of the frame pos = (0, 0, 0), # tramsparent bg color frameColor = (0, 0, 0, 0.5)) yPos = 0.45 shiftY = 0.25 self.lblLanguage = DirectLabel( text = _("Language"), scale = 0.15, pos = (base.a2dLeft + 0.25, 0, yPos), frameColor = (0,0,0,0), text_fg = (1,1,1,1), #text_font = self.defaultFont, text_align = TextNode.ALeft) self.cmbLanguage = DirectOptionMenu( text = "languages", scale = 0.15, pos = (base.a2dRight - 1.5, 0, 0.45), items = ["Deutsch","English","русский", "français"], initialitem = 0, highlightColor = (0.65,0.65,0.65,1), #text_font = self.defaultFontRegular, #item_text_font = self.defaultFontRegular, command = self.cmbLanguage_SelectionChanged) yPos -= shiftY self.lblResolution = DirectLabel( text = _("Screen resolution"), scale = 0.15, pos = (base.a2dLeft + 0.25, 0, yPos), frameColor = (0,0,0,0), text_fg = (1,1,1,1), #text_font = self.defaultFont, text_align = TextNode.ALeft) # get the display resolutions di = base.pipe.getDisplayInformation() sizes = [] for index in range(di.getTotalDisplayModes()): tmptext = "{0}x{1}".format( di.getDisplayModeWidth(index), di.getDisplayModeHeight(index)) if not tmptext in sizes: sizes.append(tmptext) self.cmbResolution = DirectOptionMenu( text = "resolutions", scale = 0.15, pos = (base.a2dRight - 1.5, 0, yPos), items = sizes, initialitem = 0, highlightColor = (0.65, 0.65, 0.65, 1), #text_font = self.defaultFontRegular, #item_text_font = self.defaultFontRegular, command = self.cmbResolution_SelectionChanged) yPos -= shiftY self.lblGraphicQuality = DirectLabel( text = _("Graphic quality"), scale = 0.15, pos = (base.a2dLeft + 0.25, 0, yPos), frameColor = (0,0,0,0), text_fg = (1,1,1,1), #text_font = self.defaultFont, text_align = TextNode.ALeft) self.graphicqualityTextMap = { 0:_("Low"), 1:_("Medium"), 2:_("High")} self.sliderGraphicQuality = DirectSlider( scale = 0.5, pos = (base.a2dRight - 1, 0, yPos + 0.05), range = (0,2), scrollSize = 1, text = self.graphicqualityTextMap[self.engine.settings.graphicquality], text_scale = 0.25, text_align = TextNode.ALeft, text_pos = (1.1, -0.1), text_fg = (1,1,1,1), #text_font = self.defaultFont, value = self.engine.settings.graphicquality, command = self.sliderGraphicQuality_ValueChanged) yPos -= shiftY self.lblVolume = DirectLabel( text = _("Volume"), scale = 0.15, pos = (base.a2dLeft + 0.25, 0, yPos), frameColor = (0,0,0,0), text_fg = (1,1,1,1), #text_font = self.defaultFont, text_align = TextNode.ALeft) self.sliderVolume = DirectSlider( scale = 0.5, pos = (base.a2dRight - 1, 0, yPos + 0.05), range = (0,1), scrollSize = 0.01, text = str(int(self.engine.settings.volume * 100)) + "%", text_scale = 0.25, text_align = TextNode.ALeft, text_pos = (1.1, -0.1), text_fg = (1,1,1,1), #text_font = self.defaultFont, value = self.engine.settings.volume, command = self.sliderVolume_ValueChanged) yPos -= shiftY self.lblVolumeMute = DirectLabel( text = _("Mute"), scale = 0.15, pos = (base.a2dLeft + 0.25, 0, yPos), frameColor = (0,0,0,0), text_fg = (1,1,1,1), #text_font = self.defaultFont, text_align = TextNode.ALeft) self.cbVolumeMute = DirectCheckBox( text = "X", pos = (base.a2dRight - 1, 0, yPos), scale = (0.25, 0.25, 0.25), command = self.cbVolumeMute_CheckedChanged, rolloverSound = None, clickSound = None, relief = 0, pressEffect = False, #frameColor = (0,0,0,0), checkedImage = "gui/buttons/options/SoundSwitch_off.png", uncheckedImage = "gui/buttons/options/SoundSwitch_on.png" ) self.cbVolumeMute.setTransparency(1) self.cbVolumeMute.setImage() self.cbVolumeMute["image_scale"] = 0.25 self.cbVolumeMute["text"] = "" self.createBackButton(self.btnBack_Click) self.lblLanguage.reparentTo(self.frameGeneral) self.cmbLanguage.reparentTo(self.frameGeneral) self.lblResolution.reparentTo(self.frameGeneral) self.cmbResolution.reparentTo(self.frameGeneral) self.lblGraphicQuality.reparentTo(self.frameGeneral) self.sliderGraphicQuality.reparentTo(self.frameGeneral) self.lblVolume.reparentTo(self.frameGeneral) self.sliderVolume.reparentTo(self.frameGeneral) self.lblVolumeMute.reparentTo(self.frameGeneral) self.cbVolumeMute.reparentTo(self.frameGeneral) self.frameGeneral.reparentTo(self.frameMain) self.accept("LanguageChanged", self.setText) def initControlTab(self): """ This function will set up the content of the control tab """ self.frameControl = DirectFrame( # size of the frame frameSize = (base.a2dLeft, base.a2dRight, -0.6, 0.6), # position of the frame pos = (0, 0, 0), # tramsparent bg color frameColor = (0, 0, 0, 0.5)) numItemsVisible = 9 itemHeight = 0.10 # the list field for the keyboard maping to the actions self.controlsList = DirectScrolledList( decButton_pos= (0, 0, -0.05), decButton_text = _("up"), decButton_text_scale = 0.04, decButton_borderWidth = (0.005, 0.005), incButton_pos= (0, 0, -1.05), incButton_text = _("down"), incButton_text_scale = 0.04, incButton_borderWidth = (0.005, 0.005), frameSize = (-1, 1, -1.1, 0.0), frameColor = (0,0,0,0.5), pos = (0, 0, 0.6), numItemsVisible = numItemsVisible, forceHeight = itemHeight, itemFrame_frameSize = (-0.9, 0.9, -0.9, 0), itemFrame_pos = (0, 0, -0.1), ) self.fillControlsList() self.controlsList.reparentTo(self.frameControl) self.frameControl.reparentTo(self.frameMain) def fillControlsList(self): for key, value in sorted(self.engine.settings.playerKeys.items()): # the base frame of any item in the list itemFrame = DirectFrame( frameSize = (-0.9, 0.9, -0.09, 0), frameColor = (0, 1, 0, 0)) def changeKey(key, value): # all possible keyboard keys to set for a specific action keyboard = [ "escape", "f1", "f2", "f3", "f4", "f5", "f6", "f7", "f8", "f9", "f10", "f11", "f12", "print_screen", "scroll_lock", "pause", "num_lock", "insert", "delete", "home", "end", "page_up", "page_down", "tab", "caps_lock", "shift", "rcontrol", "lcontrol", "ralt", "lalt", "space", "backspace", "enter", "arrow_left", "arrow_up", "arrow_down", "arrow_right", "a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z", "ä", "ö", "ü", ",", ";", ".", ":", "_", "-", "#", "'", "+", "*", "~", "'", "`", "!", "\"", "§", "$", "%", "&", "/", "(", ")", "=", "?", "{", "}", "[", "]", "\\", "^", "°" ] def setKey(arg): """ This function will set the chosen key for the given action """ # ignore all keyboard inputs again for keyboardKey in keyboard: self.ignore(keyboardKey) if arg == 1: # if the dialog was closed with OK # set the settings to the new value self.engine.settings.playerKeys[key][0] = self.selectedKey if len(self.engine.settings.playerKeys[key]) > 1: # just set the run key value if it is possible newKey = self.engine.settings.playerKeys["run"][0] + "-" + self.selectedKey self.engine.settings.playerKeys[key][1] = newKey # refresh the controls list self.controlsList.removeAllItems() self.fillControlsList() # finaly close the dialog self.keySelectDialog.hide() self.keySelectDialog = None # this variable will store the selected key for the given action self.selectedKey = value[0] def setSelectedKey(selkey): """ set the pressed key as the selected one and actualise the text on the dialog """ self.selectedKey = selkey self.keySelectDialog["text"] = "{0}: {1}".format(key, self.selectedKey) # accept all keyboard keys for keyboardKey in keyboard: self.accept( keyboardKey, setSelectedKey, [keyboardKey]) # set up a dialog wich will ask for the new key for the chosen action self.keySelectDialog = OkCancelDialog( dialogName = "OkCancelDialog", text = "{0}: {1}".format(key, value[0]), fadeScreen = 1, command = setKey ) # show the dialog self.keySelectDialog.show() # add the change button to change the key of the action itemBtnChange = DirectButton( text = _("change"), scale = 0.05, pos = (0.5, 0, -0.05), command = changeKey, extraArgs = [key, value] ) itemBtnChange.reparentTo(itemFrame) # add the label wich will show the name and key of the action itemText = DirectLabel( text = "{0} - {1}".format(key, value[0]), text_scale = 0.06, text_align = TextNode.ALeft, pos = (-0.88, 0, -0.06)) itemText.reparentTo(itemFrame) # finaly add the item to the list self.controlsList.addItem(itemFrame) def show(self): self.setText() self.showBase() def showGeneralTab(self): # set the selected language in the textbox if self.engine.settings.selectedLanguage == "de-DE": self.cmbLanguage.set(0, False) elif self.engine.settings.selectedLanguage == "ru-RU": self.cmbLanguage.set(2, False) elif self.engine.settings.selectedLanguage == "fr-FR": self.cmbLanguage.set(3, False) else: self.cmbLanguage.set(1, False) res = str(self.engine.settings.windowSize[0]) + "x" + str(self.engine.settings.windowSize[1]) i = 0 for item in self.cmbResolution["items"]: if item == res: self.cmbResolution.set(i, False) i += 1 self.sliderGraphicQuality["value"] = self.engine.settings.graphicquality self.sliderVolume["value"] = self.engine.settings.volume #self.cbVolumeMute["indicatorValue"] = settings.muted self.cbVolumeMute["isChecked"] = not self.engine.settings.muted self.cbVolumeMute.commandFunc(None) #self.cbVolumeMute.setIndicatorValue() self.frameGeneral.show() self.hideControlTab() def showControlTab(self): self.frameControl.show() self.hideGeneralTab() def hide(self): self.hideBase() def hideGeneralTab(self): self.frameGeneral.hide() def hideControlTab(self): self.frameControl.hide() def setText(self): self.title["text"] = _("Options") self.btnBack["text"] = _("Back") self.lblLanguage["text"] = _("Language") self.lblResolution["text"] = _("Screen resolution") self.lblGraphicQuality["text"] = _("Graphic quality") self.graphicqualityTextMap = { 0:_("Low"), 1:_("Medium"), 2:_("High")} self.sliderGraphicQuality["text"] = self.graphicqualityTextMap[ self.engine.settings.graphicquality] self.lblVolume["text"] = _("Volume") self.lblVolumeMute["text"] = _("Mute") def cmbLanguage_SelectionChanged(self, arg): # TODO: get available languages and maping from language class! if arg == "Deutsch": self.engine.lng.changeLanguage("de-DE") self.engine.settings.selectedLanguage = "de-DE" elif arg == "русский": self.engine.lng.changeLanguage("ru-RU") self.engine.settings.selectedLanguage = "ru-RU" elif arg == "français": self.engine.lng.changeLanguage("fr-FR") self.engine.settings.selectedLanguage = "fr-FR" else: self.engine.lng.changeLanguage("en-US") self.engine.settings.selectedLanguage = "en-US" def cmbResolution_SelectionChanged(self, arg): resx = int(arg.split("x")[0]) resy = int(arg.split("x")[1]) self.engine.settings.windowSize = [resx, resy] self.engine.graphicMgr.setResolution(resx, resy) def sliderGraphicQuality_ValueChanged(self): val = int(round(self.sliderGraphicQuality["value"], 0)) self.sliderGraphicQuality["text"] = self.graphicqualityTextMap[val] if val != self.engine.settings.graphicquality: self.engine.settings.graphicquality = val self.engine.graphicMgr.setGraphicQuality(self.engine.settings.graphicquality) def sliderVolume_ValueChanged(self): val = round(self.sliderVolume["value"], 2) self.sliderVolume["text"] = str(int(val * 100)) + "%" self.engine.settings.volume = val self.engine.audioMgr.setVolume(self.engine.settings.volume) def cbVolumeMute_CheckedChanged(self, checked): self.cbVolumeMute["image_scale"] = 0.35 self.cbVolumeMute["image_pos"] = (0.05,0,0.25) self.engine.settings.muted = bool(checked) self.engine.audioMgr.mute(self.engine.settings.muted) def btnBack_Click(self): base.messenger.send("OptMenu_back")
class MainMenu(): def __init__(self, showbase): self.showbase = showbase self.status = OnscreenText(text = "", pos = Vec3(0, -0.35, 0), scale = 0.05, fg = (1, 0, 0, 1), align = TextNode.ACenter, mayChange = True) self.background = DirectFrame( frameSize = (-1, 1, -1, 1), frameTexture = 'media/gui/mainmenu/menu.png', parent = self.showbase.render2d, ) self.title = OnscreenText( text = 'Main Menu', fg = (1, 1, 1, 1), parent = self.background, pos = (-0.6, 0.1), scale = 0.06 ) self.ip = '127.0.0.1' # Should make this write to file... so that the user can save ip's... # yep thats a good idea, there will be a few things i guess that need to be done like this # like settings and keys and whatnot # Buttons self.buttons = [] serverButtons = Vec3(-0.60, 0, -0.79) # Host self.params = ['3', '8'] p = serverButtons + Vec3(-0.25, 0, 0) self.hostButton = DirectButton(text = 'Host', pos = p, scale = 0.048, relief = DGG.GROOVE, command = self.showbase.hostGame, extraArgs = [self.params]) self.buttons.append(self.hostButton) # Join p = serverButtons + Vec3(0.0, 0.0, 0.0) self.joinButton = DirectButton(text = 'Join', pos = p, scale = 0.048, relief = DGG.GROOVE, command = self.joinServer) self.buttons.append(self.joinButton) # Refresh if self.showbase.online: p = serverButtons + Vec3(0.25, 0, 0) self.refreshButton = DirectButton(text = "Refresh", pos = p, scale = 0.048, relief = DGG.GROOVE, command = self.refreshStart) self.buttons.append(self.refreshButton) self.refreshStart() chatFrameCenter = (0.0, 0.325) chatFrameSize = (2.5, 1.2) self.chat = DirectFrame( frameColor = (0, 0, 0, 1), frameSize = (chatFrameSize[0] / 2, -chatFrameSize[0] / 2, chatFrameSize[1] / 2, -chatFrameSize[1] / 2), pos = (chatFrameCenter[0], 0, chatFrameCenter[1]) ) channelFrameSize = (chatFrameSize[0] / 4, chatFrameSize[1]) channelFrameCenter = (- chatFrameSize[0] / 2 + channelFrameSize[0] / 2, 0) numItemsVisible = 8 itemHeight = channelFrameSize[1] / (numItemsVisible + 1) self.channels = DirectScrolledList( parent = self.chat, pos = (channelFrameCenter[0], 0, channelFrameCenter[1]), frameSize = (-channelFrameSize[0] / 2, channelFrameSize[0] / 2, channelFrameSize[1] / 2, -channelFrameSize[1] / 2), frameColor = (1, 0, 0, 0.5), numItemsVisible = numItemsVisible, forceHeight = itemHeight, #itemFrame_frameSize = (-channelFrameSize[0] / 2.1, channelFrameSize[0] / 2.1, itemHeight, -channelFrameSize[1] + itemHeight), itemFrame_pos = (0, 0, channelFrameSize[1] / 2 - itemHeight), decButton_pos = (-0.2, 0, channelFrameCenter[1] - channelFrameSize[1] / 2 + itemHeight / 4), decButton_text = 'Prev', decButton_text_scale = 0.05, decButton_borderWidth = (0.005, 0.005), incButton_pos = (0.2, 0, channelFrameCenter[1] - channelFrameSize[1] / 2 + itemHeight / 4), incButton_text = 'Next', incButton_text_scale = 0.05, incButton_borderWidth = (0.005, 0.005), ) b1 = DirectButton(text = ("Button1", "click!", "roll", "disabled"), text_scale = 0.1, borderWidth = (0.01, 0.01), relief = 2) b2 = DirectButton(text = ("Button2", "click!", "roll", "disabled"), text_scale = 0.1, borderWidth = (0.01, 0.01), relief = 2) l1 = DirectLabel(text = "Test1", text_scale = 0.1) l2 = DirectLabel(text = "Test2", text_scale = 0.1) l3 = DirectLabel(text = "Test3", text_scale = 0.1) self.channels.addItem(b1) self.channels.addItem(b2) self.channels.addItem(l1) self.channels.addItem(l2) self.channels.addItem(l3) for fruit in ['apple', 'pear', 'banana', 'orange', 'cake', 'chocolate']: l = DirectLabel(text = fruit, text_scale = 0.1) self.channels.addItem(l) # need to add the chat stuff # i guess have like a chat manager which will hold an array of 'chat_instances' # and the chat manager can sort out which is displayed and which channel the text is sent from/received to # a bit more thinking needs to be done i guess # can discuss sometime (not really that important now :P) # also i guess the layout and shit will need to be sorted (for whoever is doing the designing) # current games list (need to implement this) # it should send a query to the master server to get the current list (just ip's atmo i guess) # options shit aswell needs to be sorted # maybe just an overlay or something # functionality for the host button (popup an overlay that will be able to set options and then 'start_game' button # then should auto connect and go to lobby (will be same as for all clients, except have a couple of different buttons i guess) # close game instead of disconnect, start game instead of ready (greyed until all others are ready), kick button i suppose # once the options are set the 'server_inst' should be started on the local computer (which will broadcast to master server, once host can successfully connect) # then game client will move to pregame state (connect to the server, and wait for others and ready) else: self.entry = DirectEntry( focusInCommand = self.clearText, frameSize = (-3, 3, -.5, 1), initialText = self.ip, parent = self.buttons[0], pos = (0, -0.6, -1.5), text_align = TextNode.ACenter, ) self.hide() def refreshStart(self): self.refreshButton["state"] = DGG.DISABLED if self.showbase.authCon.getConnected(): self.servers = [] self.showbase.authCon.sendData('serverQuery') self.showbase.taskMgr.doMethodLater(0.25, self.queryServers, 'Server Query') def queryServers(self, task): finished = False temp = self.showbase.authCon.getData() for package in temp: if len(package) == 2: # Handle Server Query if package[0] == 'server': self.servers.append(package[1]) print package[1] elif package[0] == 'final': self.refreshButton["state"] = DGG.NORMAL finished = True else: self.showbase.authCon.passData(package) if finished: return task.done return task.cont def joinChat(self): pass # Let the client mini auth with the lobby server(lobby_loop) by "Logging into the chat" # Since everything will be in the main menu? like a main chat window.. something similar to HoN i guess? # When the player opens the Join game by button, a list will be send from the lobby server telling it what games are active. # Then the player picks one and it connects via the host name/ip or whatever. # While this is busy happening the client stays connected to the lobby server. def joinServer(self): if self.showbase.online: self.ip = '127.0.0.1' else: self.ip = self.entry.get() self.status.setText('Attempting to join server @ ' + self.ip + '...') # attempt to connect to the game server self.showbase.client = Client(self.showbase, self.ip, 9099, compress = True) if self.showbase.client.getConnected(): print 'Connected to server, Awaiting authentication...' self.showbase.client.sendData(('username', self.showbase.username)) self.showbase.taskMgr.add(self.authorizationListener, 'Authorization Listener') else: self.status.setText('Could not Connect...') def authorizationListener(self, task): temp = self.showbase.client.getData() auth = False if temp != []: for package in temp: if len(package) == 2: if package[0] == 'auth': print 'Authentication Successful' auth = True elif package[0] == 'fail': self.status.setText('Authentication failed on server...') return task.done else: self.showbase.client.passData(package) if auth: self.showbase.startPregame() return task.done return task.again def clearText(self): self.entry.enterText('') def hide(self): self.showbase.taskMgr.remove('Server Query Timeout') self.background.hide() for b in self.buttons: b.hide() self.status.hide() if self.showbase.online: self.chat.hide() self.channels.hide() else: self.entry.hide() def show(self): self.background.show() for b in self.buttons: b.show() self.status.show() if self.showbase.online: self.chat.show() self.channels.show() else: self.entry.show()
class MainMenu(): def __init__(self, showbase): self.showbase = showbase self.status = OnscreenText(text="", pos=Vec3(0, -0.35, 0), scale=0.05, fg=(1, 0, 0, 1), align=TextNode.ACenter, mayChange=True) self.background = DirectFrame( frameSize=(-1, 1, -1, 1), frameTexture='media/gui/mainmenu/menu.png', parent=self.showbase.render2d, ) self.title = OnscreenText(text='Main Menu', fg=(1, 1, 1, 1), parent=self.background, pos=(-0.6, 0.1), scale=0.06) self.ip = '127.0.0.1' # Should make this write to file... so that the user can save ip's... # yep thats a good idea, there will be a few things i guess that need to be done like this # like settings and keys and whatnot # Buttons self.buttons = [] serverButtons = Vec3(-0.60, 0, -0.79) # Host self.params = ['3', '8'] p = serverButtons + Vec3(-0.25, 0, 0) self.hostButton = DirectButton(text='Host', pos=p, scale=0.048, relief=DGG.GROOVE, command=self.showbase.hostGame, extraArgs=[self.params]) self.buttons.append(self.hostButton) # Join p = serverButtons + Vec3(0.0, 0.0, 0.0) self.joinButton = DirectButton(text='Join', pos=p, scale=0.048, relief=DGG.GROOVE, command=self.joinServer) self.buttons.append(self.joinButton) # Refresh if self.showbase.online: p = serverButtons + Vec3(0.25, 0, 0) self.refreshButton = DirectButton(text="Refresh", pos=p, scale=0.048, relief=DGG.GROOVE, command=self.refreshStart) self.buttons.append(self.refreshButton) self.refreshStart() chatFrameCenter = (0.0, 0.325) chatFrameSize = (2.5, 1.2) self.chat = DirectFrame( frameColor=(0, 0, 0, 1), frameSize=(chatFrameSize[0] / 2, -chatFrameSize[0] / 2, chatFrameSize[1] / 2, -chatFrameSize[1] / 2), pos=(chatFrameCenter[0], 0, chatFrameCenter[1])) channelFrameSize = (chatFrameSize[0] / 4, chatFrameSize[1]) channelFrameCenter = (-chatFrameSize[0] / 2 + channelFrameSize[0] / 2, 0) numItemsVisible = 8 itemHeight = channelFrameSize[1] / (numItemsVisible + 1) self.channels = DirectScrolledList( parent=self.chat, pos=(channelFrameCenter[0], 0, channelFrameCenter[1]), frameSize=(-channelFrameSize[0] / 2, channelFrameSize[0] / 2, channelFrameSize[1] / 2, -channelFrameSize[1] / 2), frameColor=(1, 0, 0, 0.5), numItemsVisible=numItemsVisible, forceHeight=itemHeight, #itemFrame_frameSize = (-channelFrameSize[0] / 2.1, channelFrameSize[0] / 2.1, itemHeight, -channelFrameSize[1] + itemHeight), itemFrame_pos=(0, 0, channelFrameSize[1] / 2 - itemHeight), decButton_pos=(-0.2, 0, channelFrameCenter[1] - channelFrameSize[1] / 2 + itemHeight / 4), decButton_text='Prev', decButton_text_scale=0.05, decButton_borderWidth=(0.005, 0.005), incButton_pos=(0.2, 0, channelFrameCenter[1] - channelFrameSize[1] / 2 + itemHeight / 4), incButton_text='Next', incButton_text_scale=0.05, incButton_borderWidth=(0.005, 0.005), ) b1 = DirectButton(text=("Button1", "click!", "roll", "disabled"), text_scale=0.1, borderWidth=(0.01, 0.01), relief=2) b2 = DirectButton(text=("Button2", "click!", "roll", "disabled"), text_scale=0.1, borderWidth=(0.01, 0.01), relief=2) l1 = DirectLabel(text="Test1", text_scale=0.1) l2 = DirectLabel(text="Test2", text_scale=0.1) l3 = DirectLabel(text="Test3", text_scale=0.1) self.channels.addItem(b1) self.channels.addItem(b2) self.channels.addItem(l1) self.channels.addItem(l2) self.channels.addItem(l3) for fruit in [ 'apple', 'pear', 'banana', 'orange', 'cake', 'chocolate' ]: l = DirectLabel(text=fruit, text_scale=0.1) self.channels.addItem(l) # need to add the chat stuff # i guess have like a chat manager which will hold an array of 'chat_instances' # and the chat manager can sort out which is displayed and which channel the text is sent from/received to # a bit more thinking needs to be done i guess # can discuss sometime (not really that important now :P) # also i guess the layout and shit will need to be sorted (for whoever is doing the designing) # current games list (need to implement this) # it should send a query to the master server to get the current list (just ip's atmo i guess) # options shit aswell needs to be sorted # maybe just an overlay or something # functionality for the host button (popup an overlay that will be able to set options and then 'start_game' button # then should auto connect and go to lobby (will be same as for all clients, except have a couple of different buttons i guess) # close game instead of disconnect, start game instead of ready (greyed until all others are ready), kick button i suppose # once the options are set the 'server_inst' should be started on the local computer (which will broadcast to master server, once host can successfully connect) # then game client will move to pregame state (connect to the server, and wait for others and ready) else: self.entry = DirectEntry( focusInCommand=self.clearText, frameSize=(-3, 3, -.5, 1), initialText=self.ip, parent=self.buttons[0], pos=(0, -0.6, -1.5), text_align=TextNode.ACenter, ) self.hide() def refreshStart(self): self.refreshButton["state"] = DGG.DISABLED if self.showbase.authCon.getConnected(): self.servers = [] self.showbase.authCon.sendData('serverQuery') self.showbase.taskMgr.doMethodLater(0.25, self.queryServers, 'Server Query') def queryServers(self, task): finished = False temp = self.showbase.authCon.getData() for package in temp: if len(package) == 2: # Handle Server Query if package[0] == 'server': self.servers.append(package[1]) print package[1] elif package[0] == 'final': self.refreshButton["state"] = DGG.NORMAL finished = True else: self.showbase.authCon.passData(package) if finished: return task.done return task.cont def joinChat(self): pass # Let the client mini auth with the lobby server(lobby_loop) by "Logging into the chat" # Since everything will be in the main menu? like a main chat window.. something similar to HoN i guess? # When the player opens the Join game by button, a list will be send from the lobby server telling it what games are active. # Then the player picks one and it connects via the host name/ip or whatever. # While this is busy happening the client stays connected to the lobby server. def joinServer(self): if self.showbase.online: self.ip = '127.0.0.1' else: self.ip = self.entry.get() self.status.setText('Attempting to join server @ ' + self.ip + '...') # attempt to connect to the game server self.showbase.client = Client(self.showbase, self.ip, 9099, compress=True) if self.showbase.client.getConnected(): print 'Connected to server, Awaiting authentication...' self.showbase.client.sendData(('username', self.showbase.username)) self.showbase.taskMgr.add(self.authorizationListener, 'Authorization Listener') else: self.status.setText('Could not Connect...') def authorizationListener(self, task): temp = self.showbase.client.getData() auth = False if temp != []: for package in temp: if len(package) == 2: if package[0] == 'auth': print 'Authentication Successful' auth = True elif package[0] == 'fail': self.status.setText( 'Authentication failed on server...') return task.done else: self.showbase.client.passData(package) if auth: self.showbase.startPregame() return task.done return task.again def clearText(self): self.entry.enterText('') def hide(self): self.showbase.taskMgr.remove('Server Query Timeout') self.background.hide() for b in self.buttons: b.hide() self.status.hide() if self.showbase.online: self.chat.hide() self.channels.hide() else: self.entry.hide() def show(self): self.background.show() for b in self.buttons: b.show() self.status.show() if self.showbase.online: self.chat.show() self.channels.show() else: self.entry.show()
class FriendsList(DirectFrame): notify = DirectNotifyGlobal.directNotify.newCategory('FriendsList') def __init__(self): DirectFrame.__init__(self, parent=base.a2dTopRight, pos=(-0.25, 0.0, -0.46)) gui = loader.loadModel('phase_3.5/models/gui/friendslist_gui.bam') self['image'] = gui.find('**/FriendsBox_Open') self.headingText = OnscreenText(text='', parent=self, pos=(0.01, 0.2), fg=(0.1, 0.1, 0.4, 1.0), scale=0.04) self.frameForNames = DirectScrolledList( frameSize=(0.0, 0.35, 0, 0.35), incButton_geom=(gui.find('**/FndsLst_ScrollUp'), gui.find('**/FndsLst_ScrollDN'), gui.find('**/FndsLst_ScrollUp_Rllvr'), gui.find('**/FndsLst_ScrollUp')), incButton_relief=None, incButton_hpr=(0, 0, 180), incButton_pos=(0.17, 0, -0.04), decButton_geom=(gui.find('**/FndsLst_ScrollUp'), gui.find('**/FndsLst_ScrollDN'), gui.find('**/FndsLst_ScrollUp_Rllvr'), gui.find('**/FndsLst_ScrollUp')), decButton_relief=None, decButton_pos=(0.17, 0, 0.395), pos=(-0.1625, 0.0, -0.27), parent=self, numItemsVisible=9, forceHeight=0.04, itemFrame_frameSize=(-0.15, 0.15, 0, -0.35), itemFrame_pos=(0, 0, 0.3275), itemFrame_relief=None, relief=None) self.fwdBtn = DirectButton(geom=(gui.find('**/Horiz_Arrow_UP'), gui.find('**/Horiz_Arrow_DN'), gui.find('**/Horiz_Arrow_Rllvr'), gui.find('**/Horiz_Arrow_UP')), relief=None, parent=self, pos=(0.17, 0.0, -0.38), command=self.doState) self.backBtn = DirectButton(geom=(gui.find('**/Horiz_Arrow_UP'), gui.find('**/Horiz_Arrow_DN'), gui.find('**/Horiz_Arrow_Rllvr'), gui.find('**/Horiz_Arrow_UP')), relief=None, parent=self, pos=(-0.15, 0.0, -0.38), hpr=(180, 0, 0), command=self.doState) self.closeBtn = DirectButton(geom=CIGlobals.getCancelBtnGeom(), relief=None, parent=self, command=self.exitClicked) self.closeBtn.setPos(0.015, 0.0, -0.375) gui.removeNode() del gui self.hide() self.friends = {} self.onlineFriends = {} self.fsm = ClassicFSM.ClassicFSM('FriendsList', [ State.State('off', self.enterOff, self.exitOff), State.State('onlineFriendsList', self.enterOnlineFriendsList, self.exitOnlineFriendsList), State.State('allFriendsList', self.enterAllFriendsList, self.exitAllFriendsList) ], 'off', 'off') self.fsm.enterInitialState() self.accept('gotFriendsList', self.handleFriendsList) return def destroy(self): self.ignore('gotFriendsList') self.fsm.requestFinalState() del self.fsm self.headingText.destroy() del self.headingText self.frameForNames.destroy() del self.frameForNames self.fwdBtn.destroy() del self.fwdBtn self.backBtn.destroy() del self.backBtn self.closeBtn.destroy() del self.closeBtn del self.friends del self.onlineFriends DirectFrame.destroy(self) def doState(self, state): self.fsm.request(state) def exitClicked(self): self.fsm.request('off') base.localAvatar.showFriendButton() def setButtons(self, fwd=None, back=None): if fwd: self.fwdBtn['extraArgs'] = [fwd] self.fwdBtn['state'] = DGG.NORMAL else: self.fwdBtn['extraArgs'] = [] self.fwdBtn['state'] = DGG.DISABLED if back: self.backBtn['extraArgs'] = [back] self.backBtn['state'] = DGG.NORMAL else: self.backBtn['extraArgs'] = [] self.backBtn['state'] = DGG.DISABLED def handleFriendsList(self, friendIdArray, nameArray, flags, adminTokens): self.friends = {} self.onlineFriends = {} for i in xrange(len(friendIdArray)): avatarId = friendIdArray[i] name = nameArray[i] adminToken = adminTokens[i] self.friends[avatarId] = [name, adminToken] if flags[i] == 1: self.onlineFriends[avatarId] = [name, adminToken] def enterOff(self): self.hide() def exitOff(self): self.show() def addFriend(self, name, avatarId, adminToken): text_fg = CIGlobals.TextColorByAdminToken[adminToken] self.frameForNames.addItem( DirectButton(text=name, extraArgs=[avatarId], command=self.friendClicked, scale=0.035, relief=None, text_fg=text_fg, text1_bg=textDownColor, text2_bg=textRolloverColor, text_align=TextNode.ALeft)) return def friendClicked(self, avatarId): self.fsm.request('off') base.localAvatar.panel.makePanel(avatarId) def resetAll(self): self.headingText.setText('') self.frameForNames.removeAndDestroyAllItems() self.setButtons(None, None) return def sortListItems(self): self.frameForNames['items'].sort(key=lambda x: x['text']) self.frameForNames.refresh() def enterAllFriendsList(self): self.headingText.setText('All\nFriends') for friendId, data in self.friends.items(): name = data[0] adminToken = data[1] self.addFriend(name, friendId, adminToken) self.sortListItems() self.setButtons(None, 'onlineFriendsList') return def exitAllFriendsList(self): self.resetAll() def enterOnlineFriendsList(self): self.headingText.setText('Online\nFriends') for friendId, data in self.onlineFriends.items(): name = data[0] adminToken = data[1] self.addFriend(name, friendId, adminToken) self.sortListItems() self.setButtons('allFriendsList', None) return def exitOnlineFriendsList(self): self.resetAll()
class CalendarGuiDay(DirectFrame): notify = directNotify.newCategory('CalendarGuiDay') ScrollListTextSize = 0.03 def __init__(self, parent, myDate, startDate, dayClickCallback = None, onlyFutureDaysClickable = False): self.origParent = parent self.startDate = startDate self.myDate = myDate self.dayClickCallback = dayClickCallback self.onlyFutureDaysClickable = onlyFutureDaysClickable DirectFrame.__init__(self, parent=parent) self.timedEvents = [] self.partiesInvitedToToday = [] self.hostedPartiesToday = [] self.yearlyHolidaysToday = [] self.showMarkers = base.config.GetBool('show-calendar-markers', 0) self.filter = ToontownGlobals.CalendarFilterShowAll self.load() self.createGuiObjects() self.update() def createDummyLocators(self): self.dayButtonLocator = self.attachNewNode('dayButtonLocator') self.dayButtonLocator.setX(0.1) self.dayButtonLocator.setZ(-0.05) self.numberLocator = self.attachNewNode('numberLocator') self.numberLocator.setX(0.09) self.scrollLocator = self.attachNewNode('scrollLocator') self.selectedLocator = self.attachNewNode('selectedLocator') self.selectedLocator.setX(0.11) self.selectedLocator.setZ(-0.06) def load(self): dayAsset = loader.loadModel('phase_4/models/parties/tt_m_gui_sbk_calendar_box') dayAsset.reparentTo(self) self.dayButtonLocator = self.find('**/loc_origin') self.numberLocator = self.find('**/loc_number') self.scrollLocator = self.find('**/loc_topLeftList') self.selectedLocator = self.find('**/loc_origin') self.todayBox = self.find('**/boxToday') self.todayBox.hide() self.selectedFrame = self.find('**/boxHover') self.selectedFrame.hide() self.defaultBox = self.find('**/boxBlank') self.scrollBottomRightLocator = self.find('**/loc_bottomRightList') self.scrollDownLocator = self.find('**/loc_scrollDown') self.attachMarker(self.scrollDownLocator) self.scrollUpLocator = self.find('**/loc_scrollUp') self.attachMarker(self.scrollUpLocator) def attachMarker(self, parent, scale = 0.005, color = (1, 0, 0)): if self.showMarkers: marker = loader.loadModel('phase_3/models/misc/sphere') marker.reparentTo(parent) marker.setScale(scale) marker.setColor(*color) def createGuiObjects(self): self.dayButton = DirectButton(parent=self.dayButtonLocator, image=self.selectedFrame, relief=None, command=self.__clickedOnDay, pressEffect=1, rolloverSound=None, clickSound=None) self.numberWidget = DirectLabel(parent=self.numberLocator, relief=None, text=str(self.myDate.day), text_scale=0.04, text_align=TextNode.ACenter, text_font=ToontownGlobals.getInterfaceFont(), text_fg=Vec4(110 / 255.0, 126 / 255.0, 255 / 255.0, 1)) self.attachMarker(self.numberLocator) self.listXorigin = 0 self.listFrameSizeX = self.scrollBottomRightLocator.getX() - self.scrollLocator.getX() self.scrollHeight = self.scrollLocator.getZ() - self.scrollBottomRightLocator.getZ() self.listZorigin = self.scrollBottomRightLocator.getZ() self.listFrameSizeZ = self.scrollLocator.getZ() - self.scrollBottomRightLocator.getZ() self.arrowButtonXScale = 1 self.arrowButtonZScale = 1 self.itemFrameXorigin = 0 self.itemFrameZorigin = 0 self.buttonXstart = self.itemFrameXorigin + 0.21 self.gui = loader.loadModel('phase_3.5/models/gui/friendslist_gui') buttonOffSet = -0.01 incButtonPos = (0.0, 0, 0) decButtonPos = (0.0, 0, 0) itemFrameMinZ = self.listZorigin itemFrameMaxZ = self.listZorigin + self.listFrameSizeZ arrowUp = self.find('**/downScroll_up') arrowDown = self.find('**/downScroll_down') arrowHover = self.find('**/downScroll_hover') self.scrollList = DirectScrolledList(parent=self.scrollLocator, relief=None, pos=(0, 0, 0), incButton_image=(arrowUp, arrowDown, arrowHover, arrowUp), incButton_relief=None, incButton_scale=(self.arrowButtonXScale, 1, self.arrowButtonZScale), incButton_pos=incButtonPos, incButton_image3_color=Vec4(1, 1, 1, 0.2), decButton_image=(arrowUp, arrowDown, arrowHover, arrowUp), decButton_relief=None, decButton_scale=(self.arrowButtonXScale, 1, -self.arrowButtonZScale), decButton_pos=decButtonPos, decButton_image3_color=Vec4(1, 1, 1, 0.2), itemFrame_pos=(self.itemFrameXorigin, 0, -0.03), numItemsVisible=4, incButtonCallback=self.scrollButtonPressed, decButtonCallback=self.scrollButtonPressed) itemFrameParent = self.scrollList.itemFrame.getParent() self.scrollList.incButton.reparentTo(self.scrollDownLocator) self.scrollList.decButton.reparentTo(self.scrollUpLocator) arrowUp.removeNode() arrowDown.removeNode() arrowHover.removeNode() clipper = PlaneNode('clipper') clipper.setPlane(Plane(Vec3(-1, 0, 0), Point3(0.23, 0, 0))) clipNP = self.scrollList.component('itemFrame').attachNewNode(clipper) self.scrollList.component('itemFrame').setClipPlane(clipNP) return def scrollButtonPressed(self): self.__clickedOnDay() def adjustForMonth(self): curServerDate = base.cr.toontownTimeManager.getCurServerDateTime() if self.onlyFutureDaysClickable: if self.myDate.year < curServerDate.year or self.myDate.year == curServerDate.year and self.myDate.month < curServerDate.month or self.myDate.year == curServerDate.year and self.myDate.month == curServerDate.month and self.myDate.day < curServerDate.day: self.numberWidget.setColorScale(0.5, 0.5, 0.5, 0.5) self.numberWidget['state'] = DirectGuiGlobals.DISABLED else: self.numberWidget.setColorScale(1, 1, 1, 1) if self.myDate.month != self.startDate.month: self.setColorScale(0.75, 0.75, 0.75, 1.0) if self.dayClickCallback is not None: self.numberWidget['state'] = DirectGuiGlobals.DISABLED else: self.setColorScale(1, 1, 1, 1) if self.myDate.date() == curServerDate.date(): self.defaultBox.hide() self.todayBox.show() else: self.defaultBox.show() self.todayBox.hide() return def destroy(self): if self.dayClickCallback is not None: self.numberWidget.destroy() self.dayClickCallback = None self.notify.debug('desroying %s' % self.myDate) try: for item in self.scrollList['items']: if hasattr(item, 'description') and item.description and hasattr(item.description, 'destroy'): self.notify.debug('desroying description of item %s' % item) item.unbind(DGG.ENTER) item.unbind(DGG.EXIT) item.description.destroy() except e: self.notify.debug('pass %s' % self.myDate) self.scrollList.removeAndDestroyAllItems() self.scrollList.destroy() self.dayButton.destroy() DirectFrame.destroy(self) return def addWeeklyHolidays(self): if not self.filter == ToontownGlobals.CalendarFilterShowAll and not self.filter == ToontownGlobals.CalendarFilterShowOnlyHolidays: return if base.cr.newsManager: holidays = base.cr.newsManager.getHolidaysForWeekday(self.myDate.weekday()) holidayName = '' holidayDesc = '' for holidayId in holidays: if holidayId in TTLocalizer.HolidayNamesInCalendar: holidayName = TTLocalizer.HolidayNamesInCalendar[holidayId][0] holidayDesc = TTLocalizer.HolidayNamesInCalendar[holidayId][1] else: holidayName = TTLocalizer.UnknownHoliday % holidayId self.addTitleAndDescToScrollList(holidayName, holidayDesc) self.scrollList.refresh() if base.config.GetBool('calendar-test-items', 0): if self.myDate.date() + datetime.timedelta(days=-1) == base.cr.toontownTimeManager.getCurServerDateTime().date(): testItems = ('1:00 AM Party', '2:00 AM CEO', '11:15 AM Party', '5:30 PM CJ', '11:00 PM Party', 'Really Really Long String') for text in testItems: newItem = DirectLabel(relief=None, text=text, text_scale=self.ScrollListTextSize, text_align=TextNode.ALeft) self.scrollList.addItem(newItem) if self.myDate.date() + datetime.timedelta(days=-2) == base.cr.toontownTimeManager.getCurServerDateTime().date(): testItems = ('1:00 AM Party', '3:00 AM CFO', '11:00 AM Party') textSize = self.ScrollListTextSize for text in testItems: newItem = DirectLabel(relief=None, text=text, text_scale=textSize, text_align=TextNode.ALeft) self.scrollList.addItem(newItem) def updateArrowButtons(self): numItems = 0 try: numItems = len(self.scrollList['items']) except e: numItems = 0 if numItems <= self.scrollList.numItemsVisible: self.scrollList.incButton.hide() self.scrollList.decButton.hide() else: self.scrollList.incButton.show() self.scrollList.decButton.show() def collectTimedEvents(self): self.timedEvents = [] if self.filter == ToontownGlobals.CalendarFilterShowAll or self.filter == ToontownGlobals.CalendarFilterShowOnlyParties: for party in localAvatar.partiesInvitedTo: if party.startTime.date() == self.myDate.date(): self.partiesInvitedToToday.append(party) self.timedEvents.append((party.startTime.time(), party)) for party in localAvatar.hostedParties: if party.startTime.date() == self.myDate.date(): self.hostedPartiesToday.append(party) self.timedEvents.append((party.startTime.time(), party)) if base.cr.newsManager and (self.filter == ToontownGlobals.CalendarFilterShowAll or self.filter == ToontownGlobals.CalendarFilterShowOnlyHolidays): yearlyHolidays = base.cr.newsManager.getYearlyHolidaysForDate(self.myDate) for holiday in yearlyHolidays: holidayId = holiday[1] holidayStart = holiday[2] holidayEnd = holiday[3] holidayType = holiday[0] if holidayStart[0] == self.myDate.month and holidayStart[1] == self.myDate.day: myTime = datetime.time(holidayStart[2], holidayStart[3]) elif holidayEnd[0] == self.myDate.month and holidayEnd[1] == self.myDate.day: myTime = datetime.time(holidayEnd[2], holidayEnd[3]) else: self.notify.error('holiday is not today %s' % holiday) self.timedEvents.append((myTime, holiday)) oncelyHolidays = base.cr.newsManager.getOncelyHolidaysForDate(self.myDate) for holiday in oncelyHolidays: holidayId = holiday[1] holidayStart = holiday[2] holidayEnd = holiday[3] holidayType = holiday[0] if holidayStart[0] == self.myDate.year and holidayStart[1] == self.myDate.month and holidayStart[2] == self.myDate.day: myTime = datetime.time(holidayStart[3], holidayStart[4]) elif holidayEnd[0] == self.myDate.year and holidayEnd[1] == self.myDate.month and holidayEnd[2] == self.myDate.day: myTime = datetime.time(holidayEnd[3], holidayEnd[4]) else: self.notify.error('holiday is not today %s' % holiday) self.timedEvents.append((myTime, holiday)) multipleStartHolidays = base.cr.newsManager.getMultipleStartHolidaysForDate(self.myDate) for holiday in multipleStartHolidays: holidayId = holiday[1] holidayStart = holiday[2] holidayEnd = holiday[3] holidayType = holiday[0] if holidayStart[0] == self.myDate.year and holidayStart[1] == self.myDate.month and holidayStart[2] == self.myDate.day: myTime = datetime.time(holidayStart[3], holidayStart[4]) elif holidayEnd[0] == self.myDate.year and holidayEnd[1] == self.myDate.month and holidayEnd[2] == self.myDate.day: myTime = datetime.time(holidayEnd[3], holidayEnd[4]) else: self.notify.error('holiday is not today %s' % holiday) self.timedEvents.append((myTime, holiday)) relativelyHolidays = base.cr.newsManager.getRelativelyHolidaysForDate(self.myDate) for holiday in relativelyHolidays: holidayId = holiday[1] holidayStart = holiday[2] holidayEnd = holiday[3] holidayType = holiday[0] if holidayStart[0] == self.myDate.month and holidayStart[1] == self.myDate.day: myTime = datetime.time(holidayStart[2], holidayStart[3]) elif holidayEnd[0] == self.myDate.month and holidayEnd[1] == self.myDate.day: myTime = datetime.time(holidayEnd[2], holidayEnd[3]) else: self.notify.error('holiday is not today %s' % holiday) self.timedEvents.append((myTime, holiday)) def timedEventCompare(te1, te2): if te1[0] < te2[0]: return -1 elif te1[0] == te2[0]: return 0 else: return 1 self.timedEvents.sort(cmp=timedEventCompare) for timedEvent in self.timedEvents: if isinstance(timedEvent[1], PartyInfo): self.addPartyToScrollList(timedEvent[1]) elif isinstance(timedEvent[1], tuple) and timedEvent[1][0] == NewsManager.YearlyHolidayType: self.addYearlyHolidayToScrollList(timedEvent[1]) elif isinstance(timedEvent[1], tuple) and timedEvent[1][0] == NewsManager.OncelyHolidayType: self.addOncelyHolidayToScrollList(timedEvent[1]) elif isinstance(timedEvent[1], tuple) and timedEvent[1][0] == NewsManager.OncelyMultipleStartHolidayType: self.addOncelyMultipleStartHolidayToScrollList(timedEvent[1]) elif isinstance(timedEvent[1], tuple) and timedEvent[1][0] == NewsManager.RelativelyHolidayType: self.addRelativelyHolidayToScrollList(timedEvent[1]) def addYearlyHolidayToScrollList(self, holiday): holidayId = holiday[1] holidayStart = holiday[2] holidayEnd = holiday[3] holidayType = holiday[0] holidayText = '' startTime = datetime.time(holidayStart[2], holidayStart[3]) endTime = datetime.time(holidayEnd[2], holidayEnd[3]) startDate = datetime.date(self.myDate.year, holidayStart[0], holidayStart[1]) endDate = datetime.date(self.myDate.year, holidayEnd[0], holidayEnd[1]) if endDate < startDate: endDate = datetime.date(endDate.year + 1, endDate.month, endDate.day) if holidayId in TTLocalizer.HolidayNamesInCalendar: holidayName = TTLocalizer.HolidayNamesInCalendar[holidayId][0] holidayDesc = TTLocalizer.HolidayNamesInCalendar[holidayId][1] else: holidayName = TTLocalizer.UnknownHoliday % holidayId holidayDesc = TTLocalizer.UnknownHoliday % holidayId if holidayStart[0] == holidayEnd[0] and holidayStart[1] == holidayEnd[1]: holidayText = myStrftime(startTime) holidayText += ' ' + holidayName holidayDesc += ' ' + TTLocalizer.CalendarEndsAt + myStrftime(endTime) elif self.myDate.month == holidayStart[0] and self.myDate.day == holidayStart[1]: holidayText = myStrftime(startTime) holidayText += ' ' + holidayName holidayDesc = holidayName + '. ' + holidayDesc holidayDesc += ' ' + TTLocalizer.CalendarEndsAt + endDate.strftime(TTLocalizer.HolidayFormat) + myStrftime(endTime) elif self.myDate.month == holidayEnd[0] and self.myDate.day == holidayEnd[1]: holidayText = myStrftime(endTime) holidayText += ' ' + TTLocalizer.CalendarEndDash + holidayName holidayDesc = TTLocalizer.CalendarEndOf + holidayName holidayDesc += '. ' + TTLocalizer.CalendarStartedOn + startDate.strftime(TTLocalizer.HolidayFormat) + myStrftime(startTime) else: self.notify.error('unhandled case') self.addTitleAndDescToScrollList(holidayText, holidayDesc) def addOncelyHolidayToScrollList(self, holiday): holidayId = holiday[1] holidayStart = holiday[2] holidayEnd = holiday[3] holidayType = holiday[0] holidayText = '' startTime = datetime.time(holidayStart[3], holidayStart[4]) endTime = datetime.time(holidayEnd[3], holidayEnd[4]) startDate = datetime.date(holidayStart[0], holidayStart[1], holidayStart[2]) endDate = datetime.date(holidayStart[0], holidayEnd[1], holidayEnd[2]) if endDate < startDate: endDate = datetime.date(endDate.year + 1, endDate.month, endDate.day) if holidayId in TTLocalizer.HolidayNamesInCalendar: holidayName = TTLocalizer.HolidayNamesInCalendar[holidayId][0] holidayDesc = TTLocalizer.HolidayNamesInCalendar[holidayId][1] else: holidayName = TTLocalizer.UnknownHoliday % holidayId holidayDesc = '' if holidayStart[1] == holidayEnd[1] and holidayStart[2] == holidayEnd[2]: holidayText = myStrftime(startTime) holidayText += ' ' + holidayName holidayDesc = holidayName + '. ' + holidayDesc holidayDesc += ' ' + TTLocalizer.CalendarEndsAt + myStrftime(endTime) elif self.myDate.year == holidayStart[0] and self.myDate.month == holidayStart[1] and self.myDate.day == holidayStart[2]: holidayText = myStrftime(startTime) holidayText += ' ' + holidayName holidayDesc = holidayName + '. ' + holidayDesc holidayDesc += ' ' + TTLocalizer.CalendarEndsAt + endDate.strftime(TTLocalizer.HolidayFormat) + myStrftime(endTime) elif self.myDate.year == holidayEnd[0] and self.myDate.month == holidayEnd[1] and self.myDate.day == holidayEnd[2]: holidayText = myStrftime(endTime) holidayText += ' ' + TTLocalizer.CalendarEndDash + holidayName holidayDesc = TTLocalizer.CalendarEndOf + holidayName holidayDesc += '. ' + TTLocalizer.CalendarStartedOn + startDate.strftime(TTLocalizer.HolidayFormat) + myStrftime(startTime) else: self.notify.error('unhandled case') self.addTitleAndDescToScrollList(holidayText, holidayDesc) def addOncelyMultipleStartHolidayToScrollList(self, holiday): self.addOncelyHolidayToScrollList(holiday) def addRelativelyHolidayToScrollList(self, holiday): holidayId = holiday[1] holidayStart = holiday[2] holidayEnd = holiday[3] holidayType = holiday[0] holidayText = '' startTime = datetime.time(holidayStart[2], holidayStart[3]) endTime = datetime.time(holidayEnd[2], holidayEnd[3]) startDate = datetime.date(self.myDate.year, holidayStart[0], holidayStart[1]) endDate = datetime.date(self.myDate.year, holidayEnd[0], holidayEnd[1]) if endDate < startDate: endDate.year += 1 if holidayId in TTLocalizer.HolidayNamesInCalendar: holidayName = TTLocalizer.HolidayNamesInCalendar[holidayId][0] holidayDesc = TTLocalizer.HolidayNamesInCalendar[holidayId][1] else: holidayName = TTLocalizer.UnknownHoliday % holidayId holidayDesc = '' if holidayStart[0] == holidayEnd[0] and holidayStart[1] == holidayEnd[1]: holidayText = myStrftime(startTime) holidayText += ' ' + holidayName holidayDesc += ' ' + TTLocalizer.CalendarEndsAt + myStrftime(endTime) elif self.myDate.month == holidayStart[0] and self.myDate.day == holidayStart[1]: holidayText = myStrftime(startTime) holidayText += ' ' + holidayName holidayDesc = holidayName + '. ' + holidayDesc holidayDesc += ' ' + TTLocalizer.CalendarEndsAt + endDate.strftime(TTLocalizer.HolidayFormat) + myStrftime(endTime) elif self.myDate.month == holidayEnd[0] and self.myDate.day == holidayEnd[1]: holidayText = myStrftime(endTime) holidayText += ' ' + TTLocalizer.CalendarEndDash + holidayName holidayDesc = TTLocalizer.CalendarEndOf + holidayName holidayDesc += '. ' + TTLocalizer.CalendarStartedOn + startDate.strftime(TTLocalizer.HolidayFormat) + myStrftime(startTime) else: self.notify.error('unhandled case') self.addTitleAndDescToScrollList(holidayText, holidayDesc) 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 exitedTextItem(self, newItem, mousepos): newItem.description.hide() def enteredTextItem(self, newItem, descText, descUnderItemZAdjust, mousePos): if not newItem.description.checkedHeight: newItem.description.checkedHeight = True newItem.description['text'] = descText bounds = newItem.description.getBounds() descHeight = newItem.description.getHeight() scrollItemHeight = newItem.getHeight() descOverItemZAdjust = descHeight - scrollItemHeight / 2.0 descZPos = self.getPos(aspect2d)[2] + descUnderItemZAdjust - descHeight if descZPos < -1.0: newItem.description.setZ(descOverItemZAdjust) descWidth = newItem.description.getWidth() brightFrame = loader.loadModel('phase_4/models/parties/tt_m_gui_sbk_calendar_popUp_bg') newItem.description['geom'] = brightFrame newItem.description['geom_scale'] = (descWidth, 1, descHeight) descGeomZ = (bounds[2] - bounds[3]) / 2.0 descGeomZ += bounds[3] newItem.description['geom_pos'] = (0, 0, descGeomZ) newItem.description.show() 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 __clickedOnScrollItem(self): self.__clickedOnDay() def __clickedOnDay(self): acceptClick = True if self.onlyFutureDaysClickable: curServerDate = base.cr.toontownTimeManager.getCurServerDateTime() if self.myDate.date() < curServerDate.date(): acceptClick = False if not acceptClick: return if self.dayClickCallback: self.dayClickCallback(self) self.notify.debug('we got clicked on %s' % self.myDate.date()) messenger.send('clickedOnDay', [self.myDate.date()]) def updateSelected(self, selected): multiplier = 1.1 if selected: self.selectedFrame.show() self.setScale(multiplier) self.setPos(-0.01, 0, 0.01) grandParent = self.origParent.getParent() self.origParent.reparentTo(grandParent) else: self.selectedFrame.hide() self.setScale(1.0) self.setPos(0, 0, 0) def changeDate(self, startDate, myDate): self.startDate = startDate self.myDate = myDate self.scrollList.removeAndDestroyAllItems() self.update() def update(self): self.numberWidget['text'] = str(self.myDate.day) self.adjustForMonth() self.addWeeklyHolidays() self.collectTimedEvents() self.updateArrowButtons() def changeFilter(self, filter): oldFilter = self.filter self.filter = filter if self.filter != oldFilter: self.scrollList.removeAndDestroyAllItems() self.update()
class JoinScreenHelper(object): def __init__(self, app, scene): self.app = app self.scene = scene self.joinLogBox = None self.playConnector = None def stop(self): self.playConnector.cancel() def show(self, servers=None): promptToHost = (servers is None) while len(self.joinLogBox['items']): self.joinLogBox.removeItem(self.joinLogBox['items'][0]) if servers is None: servers = [const.JOIN_LOCAL_GAME] if self.app.connectionSettings.lanGames == 'beforeinet': servers.append(const.JOIN_LAN_GAME) servers += list(self.app.connectionSettings.servers) if self.app.connectionSettings.lanGames == 'afterinet': servers.append(const.JOIN_LAN_GAME) if self.app.connectionSettings.createGames: servers.append(const.CREATE_GAME) self.playConnector.begin(tuple(servers), promptToHost) def setup(self, joinNode): self.playConnector = PlayConnector( self.app, onSucceed=self.scene.showMainMenu, onFail=self.joinFailed, onLogLine=self.addJoinLogEntry, passwordGetFunction=self.getUserDetails, hostGameQueryFunction=self.askToHostGame, ) colours = self.app.theme.colours self.joinLogBox = DirectScrolledList( decButton_text='', decButton_borderWidth=(0, 0), incButton_text='', incButton_borderWidth=(0, 0), pos=(-0.85, 0, 0.4), color=colours.joinScreenBackground, itemFrame_frameSize=(-0.05, 1.75, -0.888, 0.088), parent=joinNode, numItemsVisible=MAX_LOG_ITEMS, ) self.joinLogBox.setTransparency(TransparencyAttrib.MAlpha) self.scene.button( 'cancel', self.scene.showMainMenu, right=0.87, z=-0.67, parent=joinNode, ) @defer.inlineCallbacks def joinFailed(self): yield self.scene.showOkDialog('Could not join any games') self.scene.showMainMenu() def getUserDetails(self, host, errorText=''): return ServerLoginDialogMaker(self.app).run(host, errorText) def askToHostGame(self): d = defer.Deferred() def gotResponse(result): dialog.cleanup() d.callback(result) dialog = YesNoDialog( dialogName='hostGameQuery', text='No games found. Host a game?', command=gotResponse, fadeScreen=0.3, button_pad=(0.1, 0.03), buttonPadSF=1.3, ) dialog.show() return d def addJoinLogEntry(self, text): colours = self.app.theme.colours font = self.app.screenManager.fonts.consoleFont label = DirectLabel( text=text, text_scale=font.getPandaScale(), text_fg=colours.mainMenuColour, text_font=font.getPandaFont(self.app), text_align=TextNode.ALeft, relief=None, ) while len(self.joinLogBox['items']) >= MAX_LOG_ITEMS: self.joinLogBox.removeItem(self.joinLogBox['items'][0]) self.joinLogBox.addItem(label)
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 FriendsList(DirectFrame): notify = DirectNotifyGlobal.directNotify.newCategory("FriendsList") GRAYED_OUT_COLOR = (128.0 / 255.0, 128.0 / 255.0, 128.0 / 255.0, 1.0) NORMAL_COLOR = (1.0, 1.0, 1.0, 1.0) def __init__(self): DirectFrame.__init__(self, parent=base.a2dTopRight, pos=(-0.2235, 0.0, -0.457)) gui = loader.loadModel('phase_3.5/models/gui/friendslist_gui.bam') self['image'] = gui.find('**/FriendsBox_Open') self.headingText = OnscreenText(text="", parent=self, pos=(0.01, 0.2), fg=(0.1, 0.1, 0.4, 1.0), scale=0.04) self.frameForNames = DirectScrolledList( frameSize=(0.0, 0.35, 0, 0.35), incButton_geom=(gui.find('**/FndsLst_ScrollUp'), gui.find('**/FndsLst_ScrollDN'), gui.find('**/FndsLst_ScrollUp_Rllvr'), gui.find('**/FndsLst_ScrollUp')), incButton_relief=None, incButton_hpr=(0, 0, 180), incButton_pos=(0.17, 0, -0.04), decButton_geom=(gui.find('**/FndsLst_ScrollUp'), gui.find('**/FndsLst_ScrollDN'), gui.find('**/FndsLst_ScrollUp_Rllvr'), gui.find('**/FndsLst_ScrollUp')), decButton_relief=None, decButton_pos=(0.17, 0, 0.395), pos=(-0.1625, 0.0, -0.27), parent=self, numItemsVisible=9, forceHeight=0.04, itemFrame_frameSize=(-0.15, 0.15, 0, -0.35), itemFrame_pos=(0, 0, 0.3275), itemFrame_relief=None, relief=None) self.fwdBtn = CIGlobals.makeDirectionalBtn(1, self, (0.17, 0.0, -0.38), command=self.doState) self.backBtn = CIGlobals.makeDirectionalBtn(0, self, (-0.15, 0.0, -0.38), command=self.doState) self.closeBtn = DirectButton(geom=CIGlobals.getCancelBtnGeom(), relief=None, parent=self, command=self.exitClicked) self.closeBtn.setPos(0.015, 0.0, -0.375) gui.removeNode() del gui self.hide() self.friends = {} self.onlineFriends = {} self.fsm = ClassicFSM.ClassicFSM('FriendsList', [ State.State('off', self.enterOff, self.exitOff), State.State('onlineFriendsList', self.enterOnlineFriendsList, self.exitOnlineFriendsList), State.State('allFriendsList', self.enterAllFriendsList, self.exitAllFriendsList) ], 'off', 'off') self.fsm.enterInitialState() self.accept('gotFriendsList', self.handleFriendsList) def destroy(self): self.ignore('gotFriendsList') self.fsm.requestFinalState() del self.fsm self.headingText.destroy() del self.headingText self.frameForNames.destroy() del self.frameForNames self.fwdBtn.destroy() del self.fwdBtn self.backBtn.destroy() del self.backBtn self.closeBtn.destroy() del self.closeBtn del self.friends del self.onlineFriends DirectFrame.destroy(self) def doState(self, state): self.fsm.request(state) def exitClicked(self): self.fsm.request('off') base.localAvatar.showFriendButton() def setButtons(self, fwd=None, back=None): if fwd: self.fwdBtn['extraArgs'] = [fwd] self.fwdBtn['state'] = DGG.NORMAL self.fwdBtn.setColorScale(self.NORMAL_COLOR) else: self.fwdBtn['extraArgs'] = [] self.fwdBtn['state'] = DGG.DISABLED self.fwdBtn.setColorScale(self.GRAYED_OUT_COLOR) if back: self.backBtn['extraArgs'] = [back] self.backBtn['state'] = DGG.NORMAL self.backBtn.setColorScale(self.NORMAL_COLOR) else: self.backBtn['extraArgs'] = [] self.backBtn['state'] = DGG.DISABLED self.backBtn.setColorScale(self.GRAYED_OUT_COLOR) if self.frameForNames.incButton['state'] == DGG.DISABLED: self.frameForNames.incButton.setColorScale(self.GRAYED_OUT_COLOR) else: self.frameForNames.incButton.setColorScale(self.NORMAL_COLOR) if self.frameForNames.decButton['state'] == DGG.DISABLED: self.frameForNames.decButton.setColorScale(self.GRAYED_OUT_COLOR) else: self.frameForNames.decButton.setColorScale(self.NORMAL_COLOR) def handleFriendsList(self, friendIdArray, nameArray, flags, accessLevels): self.friends = {} self.onlineFriends = {} for i in xrange(len(friendIdArray)): avatarId = friendIdArray[i] name = nameArray[i] accessLevel = accessLevels[i] self.friends[avatarId] = [name, accessLevel] if flags[i] == 1: # This friend is online self.onlineFriends[avatarId] = [name, accessLevel] def enterOff(self): self.hide() def exitOff(self): self.show() def addFriend(self, name, avatarId, accessLevel): text_fg = AdminCommands.Roles.get( accessLevel ).token.color if accessLevel > AdminCommands.NoAccess else (0, 0, 0, 1) self.frameForNames.addItem( DirectButton(text=name, extraArgs=[avatarId], command=self.friendClicked, scale=0.035, relief=None, text_fg=text_fg, text1_bg=textDownColor, text2_bg=textRolloverColor, text_align=TextNode.ALeft)) def friendClicked(self, avatarId): base.localAvatar.panel.makePanel(avatarId) def maybeShowList(self): if self.isHidden() and self.fsm.getCurrentState().getName() != 'off': base.localAvatar.hideFriendButton() self.show() def resetAll(self): self.headingText.setText("") self.frameForNames.removeAndDestroyAllItems() self.setButtons(None, None) def sortListItems(self): self.frameForNames['items'].sort(key=lambda x: x['text']) self.frameForNames.refresh() def enterAllFriendsList(self): self.headingText.setText("ALL\nFRIENDS") for friendId, data in self.friends.items(): name = data[0] accessLevel = data[1] self.addFriend(name, friendId, accessLevel) self.sortListItems() self.setButtons(None, 'onlineFriendsList') def exitAllFriendsList(self): self.resetAll() def enterOnlineFriendsList(self): self.headingText.setText("ONLINE\nFRIENDS") for friendId, data in self.onlineFriends.items(): name = data[0] accessLevel = data[1] self.addFriend(name, friendId, accessLevel) self.sortListItems() self.setButtons('allFriendsList', None) def exitOnlineFriendsList(self): self.resetAll()
class UnoGameCardDeck(DirectFrame): def __init__(self, ug): DirectFrame.__init__(self, relief=None, sortOrder=50, parent=base.a2dBottomCenter) self.initialiseoptions(UnoGameCardDeck) self.container = DirectFrame(parent=self, relief=None) self.title = None self.cards = [] self.cardBtns = [] self.numCards = 0 self.unoGame = ug self.deck = None self.cardToFollowGui = None self.holiday = base.cr.holidayManager.getHoliday() self.gui = None self.loadCards() return def loadCards(self): self.gui = loader.loadModel( "phase_4/models/minigames/mg_uno_game_cards.egg") if self.holiday == HolidayType.CHRISTMAS: cards = self.gui.find( '**/mg_uno_numcards_green_7').getParent().getChildren() for child in cards: child.setTexture( loader.loadTexture('winter/maps/uno/%s.png' % (child.getName())), 1) def updateCardToFollowGui(self): self.deleteCardToFollowGui() if self.unoGame.cardToFollow[-2:] == str(UGG.CARD_BLUE): self.cardToFollowGui = OnscreenImage( image=self.getCard('mg_uno_numcards_blue_blank'), parent=base.a2dRightCenter) elif self.unoGame.cardToFollow[-2:] == str(UGG.CARD_RED): self.cardToFollowGui = OnscreenImage( image=self.getCard('mg_uno_numcards_red_blank'), parent=base.a2dRightCenter) elif self.unoGame.cardToFollow[-2:] == str(UGG.CARD_GREEN): self.cardToFollowGui = OnscreenImage( image=self.getCard('mg_uno_numcards_green_blank'), parent=base.a2dRightCenter) elif self.unoGame.cardToFollow[-2:] == str(UGG.CARD_YELLOW): self.cardToFollowGui = OnscreenImage( image=self.getCard('mg_uno_numcards_yellow_blank'), parent=base.a2dRightCenter) if self.cardToFollowGui: self.cardToFollowGui.setScale(0.25, 0.3, 0.3) self.cardToFollowGui.setPos(-0.175, 0, -0.75) def deleteCardToFollowGui(self): if self.cardToFollowGui: self.cardToFollowGui.destroy() self.cardToFollowGui = None def getCard(self, cardType): cards = loader.loadModel( "phase_4/models/minigames/mg_uno_game_cards.egg") card = cards.find('**/' + cardType) if self.holiday == HolidayType.CHRISTMAS: holidayTexture = loader.loadTexture('winter/maps/uno/%s.png' % (card.getName())) card.setTexture(holidayTexture, 1) return card def generate(self): self.container["image"] = "phase_4/maps/mg_uno_card_deck.png" self.container.setTransparency(True) self.container.setZ(-0.456) self.container.setSx(2) self.container.setSz(1) gui = loader.loadModel("phase_3.5/models/gui/friendslist_gui.bam") numItemsVisible = 5 itemHeight = -0.25 self.deck = DirectScrolledList( itemFrame_relief=DGG.SUNKEN, decButton_pos=(0.35, 0, -0.02), decButton_geom=(gui.find('**/Horiz_Arrow_UP'), gui.find('**/Horiz_Arrow_DN'), gui.find('**/Horiz_Arrow_Rllvr'), gui.find('**/Horiz_Arrow_UP')), decButton_relief=None, decButton_hpr=(0, 0, 90), incButton_pos=(0.35, 0, 1.95), incButton_geom=(gui.find('**/Horiz_Arrow_UP'), gui.find('**/Horiz_Arrow_DN'), gui.find('**/Horiz_Arrow_Rllvr'), gui.find('**/Horiz_Arrow_UP')), incButton_hpr=(0, 0, -90), incButton_relief=None, pos=(-0.936, 0, -0.41), hpr=(0, 0, 90), scale=0.97, numItemsVisible=numItemsVisible, forceHeight=itemHeight, itemFrame_frameSize=(-0.2, 0.2, -0.37, 1.5), itemFrame_pos=(0.35, 0, 0.4), itemFrame_borderWidth=(0.02, 0.02), ) def disable(self): if self.deck: self.deck.destroy() self.deck = None for btn in self.cardBtns: btn.destroy() del btn self.deleteCardToFollowGui() return def delete(self): DirectFrame.destroy(self) self.disable() self.gui.removeNode() self.gui = None self.cards = None self.title = None self.container = None self.cardBtns = None self.numCards = None self.unoGame = None self.deck = None return def drawCard(self, id): card = self.getCard(UGG.cardId2cardTex[id]) card.setScale(0.225, 0.3, 0.3) card.setR(-90) cardBtn = DirectButton(geom=card, relief=None, scale=(0.3, 0.3, 0.23), command=self.placeCard) cardBtn.setPythonTag('id', id) cardBtn['extraArgs'] = [id, cardBtn] cardBtn['state'] = DGG.DISABLED if not self.deck: self.generate() self.deck.addItem(cardBtn) self.cardBtns.append(cardBtn) self.enableAll(self.unoGame.cardToFollow) # Scroll to the card we just added to the deck. self.deck.scrollTo(len(self.cardBtns)) card.removeNode() del card def enableAll(self, cardToFollow=None): for btn in self.cardBtns: if cardToFollow != None: if (cardToFollow == btn.getPythonTag('id') or cardToFollow[:2] == btn.getPythonTag('id')[:2] or cardToFollow[-2:] == btn.getPythonTag('id')[-2:] or btn.getPythonTag('id') == str(UGG.CARD_WILD) or btn.getPythonTag('id') == str( UGG.CARD_WILD_DRAW_FOUR)): btn['state'] = DGG.NORMAL else: btn['state'] = DGG.DISABLED else: btn['state'] = DGG.NORMAL def disableAll(self): for btn in self.cardBtns: btn['state'] = DGG.DISABLED def placeCard(self, id, btn): self.deck.removeItem(btn) self.cardBtns.remove(btn) self.disableAll() self.unoGame.d_requestPlaceCard(id)
class GroupTrackerPage(ShtikerPage.ShtikerPage): notify = directNotify.newCategory('GroupTrackerPage') def __init__(self): ShtikerPage.ShtikerPage.__init__(self) self.groupWidgets = [] self.playerWidgets = [] self.images = [] # image nodes: Possible images to apply on groups self.scrollList = None # DirectScrolledList: Holds the GroupTrackerGroup widgets self.scrollTitle = None # DirectLabel: Title of the list that holds the groups self.playerList = None # DirectScrolledList: Holds players when showing a specific group details self.playerListTitle = None # DirectLabel: Title of the playerList self.groupInfoTitle = None # DirectLabel: holds the group detail title to show on the right self.groupInfoDistrict = None # DirectLabel: shows group detail district on the right self.statusMessage = None # DirectLabel: Shows important messages like Loading... or "No boarding groups available" self.groupIcon = None # DirectButton: Icon to associate with the group ex. sellbot icon or cashbot icon depending on group info self.wantGroupToggle = None # DirectButton: Allows the toon to toggle his listing def load(self): self.listXorigin = -0.02 self.listFrameSizeX = 0.67 self.listZorigin = -0.96 self.listFrameSizeZ = 1.04 self.arrowButtonScale = 1.3 self.itemFrameXorigin = -0.237 self.itemFrameZorigin = 0.365 self.buttonXstart = self.itemFrameXorigin + 0.293 self.gui = loader.loadModel('phase_3.5/models/gui/friendslist_gui') guiButton = loader.loadModel('phase_3/models/gui/quit_button') self.scrollList = DirectScrolledList(parent=self, relief=None, pos=(-0.5, 0, 0), incButton_image=(self.gui.find('**/FndsLst_ScrollUp'), self.gui.find('**/FndsLst_ScrollDN'), self.gui.find('**/FndsLst_ScrollUp_Rllvr'), self.gui.find('**/FndsLst_ScrollUp') ), incButton_relief=None, incButton_scale=(self.arrowButtonScale, self.arrowButtonScale, -self.arrowButtonScale), incButton_pos=(self.buttonXstart, 0, self.itemFrameZorigin - 0.999), incButton_image3_color=Vec4(1, 1, 1, 0.2), decButton_image=(self.gui.find('**/FndsLst_ScrollUp'), self.gui.find('**/FndsLst_ScrollDN'), self.gui.find('**/FndsLst_ScrollUp_Rllvr'), self.gui.find('**/FndsLst_ScrollUp') ), decButton_relief=None, decButton_scale=(self.arrowButtonScale, self.arrowButtonScale, self.arrowButtonScale), decButton_pos=(self.buttonXstart, 0, self.itemFrameZorigin + 0.227), decButton_image3_color=Vec4(1, 1, 1, 0.2), itemFrame_pos=(self.itemFrameXorigin, 0, self.itemFrameZorigin), itemFrame_scale=1.0, itemFrame_relief=DGG.SUNKEN, itemFrame_frameSize=(self.listXorigin, self.listXorigin + self.listFrameSizeX, self.listZorigin, self.listZorigin + self.listFrameSizeZ ), itemFrame_frameColor=(0.85, 0.95, 1, 1), itemFrame_borderWidth=(0.01, 0.01), numItemsVisible=15, forceHeight=0.065, items=self.groupWidgets ) self.scrollTitle = DirectFrame(parent=self.scrollList, text=TTLocalizer.GroupTrackerListTitle, text_scale=0.06, text_align=TextNode.ACenter, relief=None, pos=(self.buttonXstart, 0, self.itemFrameZorigin + 0.127) ) self.playerList = DirectScrolledList(parent=self, relief=None, pos=(0.45, 0, 0.1), incButton_image=(self.gui.find('**/FndsLst_ScrollUp'), self.gui.find('**/FndsLst_ScrollDN'), self.gui.find('**/FndsLst_ScrollUp_Rllvr'), self.gui.find('**/FndsLst_ScrollUp') ), incButton_relief=None, incButton_scale=(1.0, 1.0, -1.0), incButton_pos=(0, 0, -0.28), incButton_image3_color=Vec4(1, 1, 1, 0.05), decButton_image=(self.gui.find('**/FndsLst_ScrollUp'), self.gui.find('**/FndsLst_ScrollDN'), self.gui.find('**/FndsLst_ScrollUp_Rllvr'), self.gui.find('**/FndsLst_ScrollUp') ), decButton_relief=None, decButton_scale=(1.0, 1.0, 1.0), decButton_pos=(0.0, 0, 0.04), decButton_image3_color=Vec4(1, 1, 1, 0.25), itemFrame_pos=(0, 0, -0.05), itemFrame_scale=1.0, itemFrame_relief=DGG.SUNKEN, itemFrame_frameSize=(-0.3, 0.3, #x -0.2, 0.06), #z itemFrame_frameColor=(0.85, 0.95, 1, 1), itemFrame_borderWidth=(0.01, 0.01), numItemsVisible=4, forceHeight=0.05, items=self.playerWidgets ) self.playerListTitle = DirectFrame(parent=self.playerList, text='', text_scale=0.05, text_align=TextNode.ACenter, relief=None, pos=(0, 0, 0.08) ) self.groupInfoTitle = DirectLabel(parent=self, text='', text_scale=0.080, text_align=TextNode.ACenter, text_wordwrap=15, relief=None, pos=(0.45, 0, 0.5)) self.groupInfoDistrict = DirectLabel(parent=self, text='', text_scale=0.050, text_align=TextNode.ACenter, text_wordwrap=15, relief=None, pos=(0.45, 0, 0.4) ) self.statusMessage = DirectLabel(parent=self, text='', text_scale=0.060, text_align=TextNode.ACenter, text_wordwrap=5, relief=None, pos=(0.45,0,0.1)) # Group Image: self.groupIcon = DirectButton(parent=self, relief=None, state=DGG.DISABLED, image=None, image_scale=(0.35, 1, 0.35), image_color=Vec4(1.0, 1.0, 1.0, 0.75), pos=(0.45, 10, -0.45), command=self.doNothing) # Group Toggle: self.wantGroupToggle = DirectButton(parent=self, relief=None, image=(guiButton.find('**/QuitBtn_UP'), guiButton.find('**/QuitBtn_DN'), guiButton.find('**/QuitBtn_RLVR')), image_scale=(0.7, 1, 1), text='', text_scale=0.052, text_pos=(0, -0.02), pos=(0.2, 0, -0.65), command=self.toggleWantGroup) self.updateWantGroupButton() # Loading possible group icons suitIcons = loader.loadModel('phase_3/models/gui/cog_icons') bossbotIcon = suitIcons.find('**/CorpIcon') bossbotIcon.setColor(SUIT_ICON_COLORS[0]) self.images.append(bossbotIcon) lawbotIcon = suitIcons.find('**/LegalIcon') lawbotIcon.setColor(SUIT_ICON_COLORS[1]) self.images.append(lawbotIcon) cashbotIcon = suitIcons.find('**/MoneyIcon') cashbotIcon.setColor(SUIT_ICON_COLORS[2]) self.images.append(cashbotIcon) sellbotIcon = suitIcons.find('**/SalesIcon') sellbotIcon.setColor(SUIT_ICON_COLORS[3]) self.images.append(sellbotIcon) # Clean up self.clearGroupInfo() self.statusMessage.hide() suitIcons.removeNode() self.gui.removeNode() guiButton.removeNode() self.accept('GroupTrackerResponse', self.updatePage) def unload(self): self.scrollList.destroy() self.groupInfoDistrict.destroy() self.playerList.destroy() self.groupInfoTitle.destroy() self.groupIcon.destroy() self.wantGroupToggle.destroy() for widget in self.playerWidgets: widget.destroy() for widget in self.groupWidgets: widget.destroy() self.playerWidgets = [] del self.scrollList del self.groupInfoDistrict del self.playerList del self.groupInfoTitle del self.groupIcon del self.wantGroupToggle ShtikerPage.ShtikerPage.unload(self) def enter(self): ShtikerPage.ShtikerPage.enter(self) self.setGroups([]) # CLEAR IT ALL self.setPlayers() # CLEAR IT ALL if(self.scrollList['items'] == []): self.statusMessage['text'] = TTLocalizer.GroupTrackerLoading self.statusMessage.show() base.cr.globalGroupTracker.requestGroups() taskMgr.doMethodLater(3, self.displayNoGroupsTaskHandler, self.uniqueName('timeout')) def displayNoGroups(self): self.statusMessage['text'] = TTLocalizer.GroupTrackerEmpty self.statusMessage.show() self.clearGroupInfo() def displayNoGroupsTaskHandler(self, task): self.displayNoGroups() return task.done def updatePage(self): taskMgr.remove(self.uniqueName('timeout')) groups = base.cr.globalGroupTracker.getGroupInfo() self.setGroups(groups) def exit(self): self.clearGroupInfo() ShtikerPage.ShtikerPage.exit(self) base.cr.globalGroupTracker.doneRequesting() def updateGroupInfoEventHandle(self, groupWidget, mouseEvent): self.updateGroupInfo(groupWidget) def updateGroupInfo(self, groupWidget): ''' Updates the Right Page of the Group Tracker Page with new Info ''' self.statusMessage.hide() # Update the Player List self.setPlayers(groupWidget) self.playerList.show() # Update the Player List Title self.playerListTitle['text'] = ('Players ' + str(groupWidget.getCurrentPlayers()) + '/' + str(groupWidget.getMaxPlayers()) + ':') self.playerListTitle.show() # Update the District self.groupInfoDistrict['text'] = TTLocalizer.BoardingGroupDistrictInformation % { 'district' : groupWidget.getDistrict() } self.groupInfoDistrict.show() # Update the Title self.groupInfoTitle['text'] = groupWidget.getTitle() self.groupInfoTitle.show() # Update the Image self.groupIcon['image'] = self.images[GroupTrackerGlobals.CATEGORY_TO_IMAGE_ID[groupWidget.getCategory()]] self.groupIcon['image_scale'] = (0.35, 1, 0.35) self.groupIcon.show() def clearGroupInfo(self): self.playerList.hide() self.playerListTitle.hide() self.groupInfoDistrict.hide() self.groupInfoTitle.hide() self.groupIcon.hide() def setPlayers(self, groupWidget=None): ''' Calls updatePlayerList ''' # Clear the Widgets that were held in the listings for playerWidget in self.playerWidgets: playerWidget.destroy() self.playerWidgets = [] # Make a player widget for each player # TODO: Edit this stuff when avIds come from players if groupWidget: leaderId = groupWidget.getLeaderId() playerNames = groupWidget.getMemberNames() playerIds = groupWidget.getMemberIds() for playerName in playerNames: playerId = playerIds[playerNames.index(playerName)] isLeader = playerId == leaderId self.playerWidgets.append(GroupTrackerPlayer(parent=self, avId=playerId, name=playerName, isLeader=isLeader)) self.updatePlayerList() def reconsiderGroupInfo(self, groupWidget): ''' If someone is viewing this info and it was updated, we also want to update the info being viewed ''' if self.playerWidgets is None or self.playerList['items'] == []: return # No Info is being viewed at the moment since you cant have an empty group # We have to update if this group's leader is the leader in the playerlist being viewed right now leaderId = groupWidget.getLeaderId() # Check all the players in the playerList being viewed for the same leader for playerWidget in self.playerWidgets: if playerWidget.getLeader(): if leaderId == playerWidget.getId(): self.updateGroupInfo(groupWidget) return False return True def setGroups(self, groups): ''' Calls updateGroupList ''' # Clear our Group Widgets for group in self.groupWidgets: group.destroy() self.groupWidgets = [] wantReconsiderInfo = True # Create a new group widget for each group for group in groups: if not group[GroupTrackerGlobals.SHOW] or len(group[GroupTrackerGlobals.MEMBER_IDS]) == 0: continue # We are using this to see if this group is dead or if someone doesnt want it up leaderId = 0 for i, g in base.cr.globalGroupTracker.leader2Group.items(): if g == group: leaderId = i if not leaderId: continue leaderName = group[GroupTrackerGlobals.LEADER_NAME] shardName = group[GroupTrackerGlobals.SHARD_NAME] category = group[GroupTrackerGlobals.CATEGORY] memberIds = group[GroupTrackerGlobals.MEMBER_IDS] memberNames = group[GroupTrackerGlobals.MEMBER_NAMES] groupWidget = GroupTrackerGroup(parent=self, leaderId=leaderId, leaderName=leaderName, shardName=shardName, category=category, memberIds=memberIds, memberNames=memberNames) groupWidget.bind(DGG.WITHIN, self.updateGroupInfoEventHandle, extraArgs=[groupWidget]) self.groupWidgets.append(groupWidget) if wantReconsiderInfo: wantReconsiderInfo = self.reconsiderGroupInfo(groupWidget) # Edge case where a group that was removed, info might remain on the screen if it didn't exist any more if wantReconsiderInfo: self.clearGroupInfo() # There are no groups, hide the information if len(self.groupWidgets) == 0: self.displayNoGroups() self.updateGroupList() def updateGroupList(self): self.statusMessage.hide() if self.scrollList is None: return # Clear the Group Listing for item in self.scrollList['items']: if item: self.scrollList.removeItem(item, refresh=True) self.scrollList['items'] = [] # Re-populate the Group Listing for groupWidget in self.groupWidgets: self.scrollList.addItem(groupWidget, refresh=True) if len(self.groupWidgets) == 0: self.displayNoGroups() def updatePlayerList(self): if self.playerList is None: return # Clear the Player Listing for item in self.playerList['items']: if item: self.playerList.removeItem(item) self.playerList['items'] = [] # Re-Populate the List for playerWidget in self.playerWidgets: self.playerList.addItem(playerWidget) def toggleWantGroup(self): if settings.get('grouptracker', False): settings['grouptracker'] = False base.cr.globalGroupTracker.showMe(False) else: settings['grouptracker'] = True base.cr.globalGroupTracker.showMe(True) base.localAvatar.wantGroupTracker() base.localAvatar.wantGroupTracker() # Updates the ai toon so the boarding group AI could know what he wants self.updateWantGroupButton() def updateWantGroupButton(self): if settings.get('grouptracker', False): self.wantGroupToggle['text'] = 'Hide Me' else: self.wantGroupToggle['text'] = 'Show Me' def doNothing(self): pass