Ejemplo n.º 1
0
 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
Ejemplo n.º 2
0
 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)
Ejemplo n.º 3
0
 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
Ejemplo n.º 4
0
 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])
Ejemplo n.º 5
0
    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)
Ejemplo n.º 6
0
    def addPartyToScrollList(self, party):
        """Add a party to the scroll list."""
        textSize = self.ScrollListTextSize
        descTextSize = 0.05
        partyTitle = myStrftime(party.startTime)
        partyTitle = partyTitle + " " + TTLocalizer.EventsPageCalendarTabParty

        textSize = self.ScrollListTextSize
        descTextSize = 0.05
        newItem = DirectButton(
            relief=None,
            text=partyTitle,
            text_scale=textSize,
            text_align=TextNode.ALeft,
            rolloverSound=None,
            clickSound=None,
            pressEffect=0,
            command=self.__clickedOnScrollItem,
        )

        # lower tool tip a little
        scrollItemHeight = newItem.getHeight()

        descUnderItemZAdjust = (scrollItemHeight * descTextSize / textSize)
        descUnderItemZAdjust = max(
            0.0534, descUnderItemZAdjust)  # ensure minimum height
        descUnderItemZAdjust = -descUnderItemZAdjust
        # self.notify.debug('scrollItemHeight of %s = %f' % (title, scrollItemHeight))
        descZAdjust = descUnderItemZAdjust
        # self.notify.debug('descUnderItemZAdjust of %s = %f' % (title, descUnderItemZAdjust))
        self.scrollList.addItem(newItem)

        newItem.description = MiniInviteVisual(newItem, party)
        # # workaround to stop getting clipped by plane node
        newItem.description.setBin('gui-popup', 0)
        newItem.description.hide()

        newItem.bind(
            DGG.ENTER,
            self.enteredTextItem,
            extraArgs=[newItem, newItem.description, descUnderItemZAdjust])
        newItem.bind(DGG.EXIT, self.exitedTextItem, extraArgs=[newItem])
class ModPanelButton:
    def __init__(self, menu, name, command, register):
        self.menu = menu
        self.name = name
        
        self.command = command
        if type(command) == types.StringType:
            command = self.call_word

        self.button = DirectButton(frameSize=None, text=name, 
            image=(ModPanelGlobals.Button.find('**/QuitBtn_UP'),
            ModPanelGlobals.Button.find('**/QuitBtn_DN'),
            ModPanelGlobals.Button.find('**/QuitBtn_RLVR')),
            relief=None, command=command, text_pos=(0, -0.015),
            geom=None, pad=(0.01, 0.01), suppressKeys=0, pos=(0, 0, 0), 
            text_scale=0.059, borderWidth=(0.015, 0.01), scale=.7
        )
        
        self.button.reparent_to(menu)
        
        if register:
            self.button.bind(DirectGuiGlobals.B2PRESS, self.delete_button)
            self.button.bind(DirectGuiGlobals.B3PRESS, self.button.editStart)
            self.button.bind(DirectGuiGlobals.B3RELEASE, self.edit_stop)
            self.menu.buttons.append(self)
            messenger.send('save-file')
        
    def call_word(self):
        messenger.send('magicWord', [self.command])
        
    def hide(self):
        self.button.hide()
        
    def show(self):
        self.button.show()
        
    def place(self):
        self.button.place()
        
    def set_pos(self, x, y, z):
        self.button.set_pos(x, y, z)
        
    def destroy(self):
        self.button.destroy()
        
    def edit_stop(self, dispatch):
        self.button.editStop(dispatch)
        
        messenger.send('save-file')

    def delete_button(self, dispatch):
        self.button.destroy()
        if self in self.menu.buttons:
            self.menu.buttons.remove(self)
            
        messenger.send('save-file')
        
    def get_data(self):
        return (self.name, self.command, self.button.get_pos())
class PartyPlanner(DirectFrame, FSM):
    notify = DirectNotifyGlobal.directNotify.newCategory('PartyPlanner')

    def __init__(self, doneEvent = None):
        FSM.__init__(self, 'PartyPlannerFSM')
        DirectFrame.__init__(self)
        self.doneEvent = doneEvent
        self.stateArray = ['Off',
         'Welcome',
         'PartyEditor',
         'Guests',
         'Date',
         'Time',
         'Invitation',
         'Farewell']
        self.partyTime = base.cr.toontownTimeManager.getCurServerDateTime()
        self.partyNowTime = base.cr.toontownTimeManager.getCurServerDateTime()
        minutesToNextFifteen = 15 - self.partyTime.minute % 15
        self.cleanPartyTime = self.partyTime + timedelta(minutes=minutesToNextFifteen, seconds=-self.partyTime.second)
        self.partyTime = self.cleanPartyTime
        self.guests = []
        self.isPrivate = False
        self.selectedCalendarGuiDay = None
        self.gui = loader.loadModel('phase_4/models/parties/partyPlannerGUI')
        self.partyDuration = timedelta(hours=PartyGlobals.DefaultPartyDuration)
        self.timeTypeToMaxValue = {'hour': 23,
         'minute': 59}
        self.timeTypeToChangeAmount = {'hour': (1, -1),
         'minute': (15, -15),
         'ampm': (1, -1)}
        self.partyInfo = None
        self.asapMinuteRounding = base.config.GetInt('party-asap-minute-rounding', PartyGlobals.PartyPlannerAsapMinuteRounding)
        self.load()
        self.request('Welcome')
        return

    def enterWelcome(self, *args):
        self.prevButton['state'] = DirectGuiGlobals.DISABLED
        self.prevButton.hide()
        self.nextButton['state'] = DirectGuiGlobals.NORMAL
        self.welcomePage.show()
        self.partyPlannerHead.reparentTo(self.welcomePage)
        self.partyPlannerHead.startBlink()
        self.partyPlannerHead.startLookAround()
        self.nametagNP.reparentTo(self.welcomePage)
        self.chatNP.reparentTo(self.welcomePage)

    def exitWelcome(self):
        self.welcomePage.hide()
        self.prevButton.show()
        self.partyPlannerHead.stopBlink()
        self.partyPlannerHead.stopLookAround()

    def enterPartyEditor(self, *args):
        self.prevButton['state'] = DirectGuiGlobals.NORMAL
        self.nextButton['state'] = DirectGuiGlobals.DISABLED
        self.nextButton.hide()
        self.partyEditorPage.show()
        self.okWithGroundsGui.doneStatus = ''
        self.partyEditor.request('Idle')

    def exitPartyEditor(self):
        self.partyEditor.request('Hidden')
        self.partyEditorPage.hide()

    def enterGuests(self, *args):
        self.prevButton['state'] = DirectGuiGlobals.NORMAL
        self.nextButton['state'] = DirectGuiGlobals.NORMAL
        self.nextButton.show()
        self.guestPage.show()

    def exitGuests(self):
        self.guests = []
        for friendCheckBox in self.friendList['items']:
            if friendCheckBox['indicatorValue']:
                self.guests.append(friendCheckBox.getPythonTag('id'))

        self.guestPage.hide()

    def enterDate(self, *args):
        self.prevButton.show()
        self.prevButton['state'] = DirectGuiGlobals.NORMAL
        if self.selectedCalendarGuiDay is None:
            self.nextButton['state'] = DirectGuiGlobals.DISABLED
            self.nextButton.hide()
            self.makePartyNowButton.show()
        self.datePage.show()
        return

    def exitDate(self):
        self.datePage.hide()
        self.nextButton.show()
        if self.selectedCalendarGuiDay is not None:
            self.partyTime = self.cleanPartyTime
            self.alterPartyTime(year=self.selectedCalendarGuiDay.myDate.year, month=self.selectedCalendarGuiDay.myDate.month, day=self.selectedCalendarGuiDay.myDate.day)
        else:
            self.partyNowTime = self.calcAsapTime()
            self.partyTime = self.partyNowTime
        return

    def calcAsapTime(self):
        curServerTime = base.cr.toontownTimeManager.getCurServerDateTime()
        baseTime = curServerTime
        baseTime = baseTime.replace(baseTime.year, baseTime.month, baseTime.day, baseTime.hour, baseTime.minute, second=0, microsecond=0)
        minute = curServerTime.minute
        remainder = minute % self.asapMinuteRounding
        if remainder:
            baseTime += timedelta(minutes=self.asapMinuteRounding - remainder)
        else:
            baseTime += timedelta(minutes=self.asapMinuteRounding)
        return baseTime

    def enterTime(self, *args):
        self.prevButton.show()
        self.prevButton['state'] = DirectGuiGlobals.NORMAL
        self.nextButton.show()
        self.timePage.show()
        self.timePageRecapToontownTimeLabel2['text'] = '%s' % PartyUtils.formatDateTime(self.partyTime)
        self.timePageRecapLocalTimeLabel['text'] = '%s%s' % (TTLocalizer.PartyPlannerTimeLocalTime, PartyUtils.formatDateTime(self.partyTime, inLocalTime=True))

    def exitTime(self):
        self.timePage.hide()
        self.nextButton.show()

    def enterInvitation(self, *args):
        self.prevButton['state'] = DirectGuiGlobals.NORMAL
        self.nextButton.hide()
        defaultInviteTheme = PartyGlobals.InviteTheme.GenericMale
        if hasattr(base.cr, 'newsManager') and base.cr.newsManager:
            if ToontownGlobals.VICTORY_PARTY_HOLIDAY in base.cr.newsManager.getHolidayIdList():
                defaultInviteTheme = PartyGlobals.InviteTheme.VictoryParty
            elif ToontownGlobals.KARTING_TICKETS_HOLIDAY in base.cr.newsManager.getHolidayIdList() or ToontownGlobals.CIRCUIT_RACING_EVENT in base.cr.newsManager.getHolidayIdList():
                defaultInviteTheme = PartyGlobals.InviteTheme.Racing
            elif ToontownGlobals.VALENTINES_DAY in base.cr.newsManager.getHolidayIdList():
                defaultInviteTheme = PartyGlobals.InviteTheme.Valentoons
        if self.partyInfo is not None:
            del self.partyInfo
        activityList = self.partyEditor.partyEditorGrid.getActivitiesOnGrid()
        decorationList = self.partyEditor.partyEditorGrid.getDecorationsOnGrid()
        endTime = self.partyTime + self.partyDuration
        self.partyInfo = PartyInfo(0, 0, self.partyTime.year, self.partyTime.month, self.partyTime.day, self.partyTime.hour, self.partyTime.minute, endTime.year, endTime.month, endTime.day, endTime.hour, endTime.minute, self.isPrivate, defaultInviteTheme, activityList, decorationList, 0)
        if self.noFriends or len(self.getInvitees()) == 0:
            self.inviteVisual.setNoFriends(True)
            self.invitationTitleLabel['text'] = TTLocalizer.PartyPlannerConfirmTitleNoFriends
            self.inviteButton['text'] = TTLocalizer.PartyPlannerInviteButtonNoFriends
            self.selectedInviteThemeLabel.stash()
            self.nextThemeButton.stash()
            self.prevThemeButton.stash()
            self.setInviteTheme(defaultInviteTheme)
        else:
            self.inviteVisual.setNoFriends(False)
            self.invitationTitleLabel['text'] = TTLocalizer.PartyPlannerConfirmTitle
            self.inviteButton['text'] = TTLocalizer.PartyPlannerInviteButton
            self.selectedInviteThemeLabel.unstash()
            self.nextThemeButton.unstash()
            self.prevThemeButton.unstash()
            self.setInviteTheme(defaultInviteTheme)
        self.inviteVisual.updateInvitation(base.localAvatar.getName(), self.partyInfo)
        self.invitationPage.show()
        return

    def __prevTheme(self):
        self.nextThemeButton.show()
        prevTheme = self.currentInvitationTheme - 1
        while prevTheme not in self.inviteThemes:
            prevTheme -= 1
            if prevTheme == self.currentInvitationTheme:
                self.notify.warning('No previous invite theme found.')
                break
            elif prevTheme < 0:
                prevTheme = len(self.inviteVisual.inviteThemesIdToInfo) - 1

        self.setInviteTheme(prevTheme)

    def __nextTheme(self):
        self.prevThemeButton.show()
        nextTheme = self.currentInvitationTheme + 1
        while nextTheme not in self.inviteThemes:
            nextTheme += 1
            if nextTheme == self.currentInvitationTheme:
                self.notify.warning('No next invite theme found.')
                break
            elif nextTheme >= len(self.inviteVisual.inviteThemesIdToInfo):
                nextTheme = 0

        self.setInviteTheme(nextTheme)

    def setInviteTheme(self, themeNumber):
        self.currentInvitationTheme = themeNumber
        self.selectedInviteThemeLabel['text'] = '%s %s (%d/%d)' % (self.inviteVisual.inviteThemesIdToInfo[self.currentInvitationTheme][1],
         TTLocalizer.PartyPlannerInvitationTheme,
         self.inviteThemes.index(self.currentInvitationTheme) + 1,
         len(self.inviteThemes))
        self.partyInfo.inviteTheme = self.currentInvitationTheme
        self.inviteVisual.updateInvitation(base.localAvatar.getName(), self.partyInfo)

    def exitInvitation(self):
        self.invitationPage.hide()
        self.nextButton.show()

    def enterFarewell(self, goingBackAllowed):
        self.farewellPage.show()
        if goingBackAllowed:
            self.prevButton.show()
        else:
            self.prevButton.hide()
        self.nextButton.hide()
        self.partyPlannerHead.reparentTo(self.farewellPage)
        self.partyPlannerHead.startBlink()
        self.partyPlannerHead.startLookAround()
        self.nametagNP.reparentTo(self.farewellPage)
        self.chatNP.reparentTo(self.farewellPage)

    def exitFarewell(self):
        self.farewellPage.hide()
        self.nextButton.show()
        self.prevButton.show()
        self.partyPlannerHead.stopBlink()
        self.partyPlannerHead.stopLookAround()

    def load(self):
        self.frame = DirectFrame(parent=aspect2d, geom=self.gui.find('**/background'), relief=None, scale=0.85, pos=(0.05, 0.0, 0.1))
        self.titleScale = TTLocalizer.PPtitleScale
        self._createNavButtons()
        self.welcomePage = self._createWelcomePage()
        self.welcomePage.hide()
        self.datePage = self._createDatePage()
        self.datePage.hide()
        self.timePage = self._createTimePage()
        self.timePage.hide()
        self.guestPage = self._createGuestPage()
        self.guestPage.hide()
        self.partyEditorPage = self._createPartyEditorPage()
        self.partyEditorPage.hide()
        self.invitationPage = self._createInvitationPage()
        self.invitationPage.hide()
        self.farewellPage = self._createFarewellPage()
        self.farewellPage.hide()
        return

    def _createNavButtons(self):
        self.quitButton = DirectButton(parent=self.frame, relief=None, geom=(self.gui.find('**/cancelButton_up'), self.gui.find('**/cancelButton_down'), self.gui.find('**/cancelButton_rollover')), command=self.__acceptExit)
        self.nextButton = DirectButton(parent=self.frame, relief=None, geom=(self.gui.find('**/bottomNext_button/nextButton_up'), self.gui.find('**/bottomNext_button/nextButton_down'), self.gui.find('**/bottomNext_button/nextButton_rollover')), command=self.__nextItem, state=DirectGuiGlobals.DISABLED)
        self.prevButton = DirectButton(parent=self.frame, relief=None, geom=(self.gui.find('**/bottomPrevious_button/previousButton_up'), self.gui.find('**/bottomPrevious_button/previousButton_down'), self.gui.find('**/bottomPrevious_button/previousButton_rollover')), command=self.__prevItem, state=DirectGuiGlobals.DISABLED)
        self.currentItem = None
        return

    def __createNametag(self, parent):
        if self.nametagGroup == None:
            self.nametagGroup = NametagGroup()
            self.nametagGroup.setFont(OTPGlobals.getInterfaceFont())
            self.nametagGroup.setActive(0)
            self.nametagGroup.setAvatar(self.partyPlannerHead)
            self.nametagGroup.manage(base.marginManager)
            self.nametagGroup.setColorCode(self.nametagGroup.CCNonPlayer)
            self.nametagGroup.getNametag2d().setContents(0)
            self.nametagNode = NametagFloat2d()
            self.nametagNode.setContents(Nametag.CName)
            self.nametagGroup.addNametag(self.nametagNode)
            self.nametagGroup.setName(base.cr.partyManager.getPartyPlannerName())
            self.nametagNP = parent.attachNewNode(self.nametagNode.upcastToPandaNode())
            nametagPos = self.gui.find('**/step_01_partymanPeteNametag_locator').getPos()
            self.nametagNP.setPosHprScale(nametagPos[0], 0, nametagPos[2], 0, 0, 0, 0.1, 1, 0.1)
            self.chatNode = NametagFloat2d()
            self.chatNode.setContents(Nametag.CSpeech | Nametag.CThought)
            self.nametagGroup.addNametag(self.chatNode)
            self.nametagGroup.setChat(TTLocalizer.PartyPlannerInstructions, CFSpeech)
            self.chatNP = parent.attachNewNode(self.chatNode.upcastToPandaNode())
            chatPos = self.gui.find('**/step_01_partymanPeteText_locator').getPos()
            self.chatNP.setPosHprScale(chatPos[0], 0, chatPos[2], 0, 0, 0, 0.08, 1, 0.08)
        return

    def clearNametag(self):
        if self.nametagGroup != None:
            self.nametagGroup.unmanage(base.marginManager)
            self.nametagGroup.removeNametag(self.nametagNode)
            self.nametagGroup.removeNametag(self.chatNode)
            self.nametagNP.removeNode()
            self.chatNP.removeNode()
            del self.nametagNP
            del self.chatNP
            del self.nametagNode
            del self.chatNode
            self.nametagGroup.setAvatar(NodePath())
            self.nametagGroup = None
        return

    def _createWelcomePage(self):
        self.nametagGroup = None
        page = DirectFrame(self.frame)
        page.setName('PartyPlannerWelcomePage')
        self.welcomeTitleLabel = DirectLabel(parent=page, relief=None, text=TTLocalizer.PartyPlannerWelcomeTitle, pos=self.gui.find('**/title_locator').getPos(), scale=self.titleScale)
        self.partyPlannerHead = ToonHead.ToonHead()
        partyPlannerStyle = base.cr.partyManager.getPartyPlannerStyle()
        self.partyPlannerHead.setupHead(partyPlannerStyle, forGui=True)
        self.partyPlannerHead.setPos(self.gui.find('**/step_01_partymanPete_locator').getPos())
        animal = partyPlannerStyle.getAnimal()
        if animal == 'cat' or animal == 'pig':
            headScale = 0.4
        elif animal == 'dog' or animal == 'bear':
            headScale = 0.45
        elif animal == 'rabbit':
            headScale = 0.35
        else:
            headScale = 0.3
        self.partyPlannerHead.setScale(headScale)
        self.partyPlannerHead.setH(180.0)
        self.partyPlannerHead.reparentTo(page)
        self.__createNametag(page)
        return page

    def _createDatePage(self):
        page = DirectFrame(self.frame)
        page.setName('PartyPlannerDatePage')
        self.createDateTitleLabel = DirectLabel(parent=page, relief=None, text=TTLocalizer.PartyPlannerDateTitle, pos=self.gui.find('**/title_locator').getPos(), scale=self.titleScale)
        pos = self.gui.find('**/step_06_sendInvitation_locator').getPos()
        self.makePartyNowButton = DirectButton(parent=page, relief=None, geom=(self.gui.find('**/send_up'), self.gui.find('**/send_down'), self.gui.find('**/send_rollover')), text=TTLocalizer.PartyPlannerPartyNow, text_pos=(pos[0], pos[2]), text_scale=0.05, command=self.__doMakePartyNow)
        curServerDate = base.cr.toontownTimeManager.getCurServerDateTime()
        self.calendarGuiMonth = CalendarGuiMonth(page, curServerDate, scale=0.95, pos=(-0.05, 0.0, -0.33), dayClickCallback=self._dayClickCallback, onlyFutureDaysClickable=True)
        return page

    def __doMakePartyNow(self):
        self.request('Invitation')

    def _dayClickCallback(self, calendarGuiDay):
        self.selectedCalendarGuiDay = calendarGuiDay
        self.nextButton['state'] = DirectGuiGlobals.NORMAL
        self.makePartyNowButton.hide()
        self.nextButton.show()

    def alterPartyTime(self, year = None, month = None, day = None, hour = None, minute = None):
        self.partyTime = datetime(year=self.positiveTime('year', year), month=self.positiveTime('month', month), day=self.positiveTime('day', day), hour=self.positiveTime('hour', hour), minute=self.positiveTime('minute', minute), tzinfo=self.partyTime.tzinfo)

    def positiveTime(self, type, amount):
        if amount is None:
            return getattr(self.partyTime, type)
        if type == 'hour' or type == 'minute':
            if amount < 0:
                return self.timeTypeToMaxValue[type] + 1 + self.timeTypeToChangeAmount[type][1]
            elif amount > self.timeTypeToMaxValue[type]:
                return 0
        return amount

    def _createTimePage(self):
        page = DirectFrame(self.frame)
        page.setName('PartyPlannerTimePage')
        self.createTimeTitleLabel = DirectLabel(parent=page, relief=None, text=TTLocalizer.PartyPlannerTimeTitle, pos=self.gui.find('**/title_locator').getPos(), scale=self.titleScale)
        self.clockImage = DirectFrame(parent=page, relief=None, geom=self.gui.find('**/toontownTime_background'))
        self.timePageToontownLabel = DirectLabel(parent=page, relief=None, text=TTLocalizer.PartyPlannerTimeToontown, pos=self.gui.find('**/step_03_toontown_locator').getPos(), scale=0.15, text_fg=(1.0, 0.0, 0.0, 1.0), text_font=ToontownGlobals.getSignFont())
        self.timePageTimeLabel = DirectLabel(parent=page, relief=None, text=TTLocalizer.PartyPlannerTimeTime, pos=self.gui.find('**/step_03_time_locator').getPos(), scale=0.15, text_fg=(1.0, 0.0, 0.0, 1.0), text_font=ToontownGlobals.getSignFont())
        self.timePageRecapLabel = DirectLabel(parent=page, relief=None, text=TTLocalizer.PartyPlannerTimeRecap, pos=self.gui.find('**/step_03_partyDateAndTime_locator').getPos(), scale=0.09)
        self.timePageRecapToontownTimeLabel1 = DirectLabel(parent=page, relief=None, text=TTLocalizer.PartyPlannerTimeToontownTime, pos=self.gui.find('**/step_03_toontownTime_locator').getPos(), scale=0.06)
        self.timePageRecapToontownTimeLabel2 = DirectLabel(parent=page, relief=None, text='%s' % PartyUtils.formatDateTime(self.partyTime), pos=self.gui.find('**/step_03_toontownDateAndTime_loactor').getPos(), textMayChange=True, scale=0.06)
        self.timePageRecapLocalTimeLabel = DirectLabel(parent=page, relief=None, text='%s%s' % (TTLocalizer.PartyPlannerTimeLocalTime, PartyUtils.formatDateTime(self.partyTime, inLocalTime=True)), pos=self.gui.find('**/step_03_localDateAndTime_loactor').getPos(), textMayChange=True, scale=0.06, text_fg=(1.0, 0.0, 0.0, 1.0))
        self.timeInputHourLabel, self.timeInputHourUpButton, self.timeInputHourDownButton = self.getTimeWidgets(page, 'hour')
        self.timeInputMinuteLabel, self.timeInputMinuteUpButton, self.timeInputMinuteDownButton = self.getTimeWidgets(page, 'minute')
        self.timeInputAmPmLabel, self.timeInputAmPmUpButton, self.timeInputAmPmDownButton = self.getTimeWidgets(page, 'ampm')
        self.timePagecolonLabel = DirectLabel(parent=page, relief=None, text=':', pos=self.gui.find('**/step_03_colon_locator').getPos(), scale=0.15)
        return page

    def getTimeWidgets(self, page, type):
        if type == 'ampm':
            data = self.getCurrentAmPm()
        else:
            data = getattr(self.partyTime, type)
            if data == 0 and type == 'minute':
                data = '00'
            else:
                if type == 'hour':
                    data = data % 12
                    if data == 0:
                        data = 12
                data = '%d' % data
        label = DirectLabel(parent=page, relief=None, text='%s' % data, textMayChange=True, pos=self.gui.find('**/step_03_%s_locator' % type).getPos(), scale=0.12)

        def changeValue(self, amount):
            if type == 'ampm':
                self.alterPartyTime(hour=(self.partyTime.hour + 12) % 24)
                newAmount = self.getCurrentAmPm()
                label['text'] = newAmount
            else:
                if type == 'hour':
                    newAmount = getattr(self.partyTime, type) + amount
                    newAmount = newAmount % 12
                    if self.timeInputAmPmLabel['text'] == TTLocalizer.PartyTimeFormatMeridiemPM:
                        newAmount = newAmount % 12 + 12
                    self.alterPartyTime(hour=newAmount)
                elif type == 'minute':
                    newAmount = getattr(self.partyTime, type) + amount
                    self.alterPartyTime(minute=newAmount)
                else:
                    PartyPlanner.notify.error('Invalid type for changeValue in PartyPlanner: %s' % type)
                newAmount = getattr(self.partyTime, type)
                if newAmount < 10 and type == 'minute':
                    label['text'] = '0%d' % newAmount
                else:
                    if type == 'hour':
                        newAmount = newAmount % 12
                        if newAmount == 0:
                            newAmount = 12
                    label['text'] = '%d' % newAmount
            self.timePageRecapToontownTimeLabel2['text'] = '%s' % PartyUtils.formatDateTime(self.partyTime)
            self.timePageRecapLocalTimeLabel['text'] = '%s%s' % (TTLocalizer.PartyPlannerTimeLocalTime, PartyUtils.formatDateTime(self.partyTime, inLocalTime=True))

        upButton = DirectButton(parent=page, relief=None, geom=(self.gui.find('**/%sButtonUp_up' % type), self.gui.find('**/%sButtonUp_down' % type), self.gui.find('**/%sButtonUp_rollover' % type)), command=changeValue, extraArgs=[self, self.timeTypeToChangeAmount[type][0]])
        downButton = DirectButton(parent=page, relief=None, geom=(self.gui.find('**/%sButtonDown_up' % type), self.gui.find('**/%sButtonDown_down' % type), self.gui.find('**/%sButtonDown_rollover' % type)), command=changeValue, extraArgs=[self, self.timeTypeToChangeAmount[type][1]])
        return (label, upButton, downButton)

    def getCurrentAmPm(self):
        if self.partyTime.hour < 12:
            return TTLocalizer.PartyTimeFormatMeridiemAM
        else:
            return TTLocalizer.PartyTimeFormatMeridiemPM

    def _createGuestPage(self):
        page = DirectFrame(self.frame)
        page.setName('PartyPlannerGuestPage')
        self.guestTitleLabel = DirectLabel(parent=page, relief=None, text=TTLocalizer.PartyPlannerGuestTitle, pos=self.gui.find('**/title_locator').getPos(), scale=self.titleScale)
        self.guestBackgroundLabel = DirectLabel(parent=page, relief=None, image=self.gui.find('**/guestListBackground_flat'), scale=(1.2, 1.0, 1.0))
        self.friendList = ScrolledFriendList(page, self.gui, makeItemsCheckBoxes=True)
        if len(base.localAvatar.friendsList) == 0:
            self.noFriends = True
        else:
            self.noFriends = False
            for friendPair in base.localAvatar.friendsList:
                self.friendList.addFriend(determineFriendName(friendPair), friendPair[0])

            self.friendList.scrollTo(0)
        pos = self.gui.find('**/step_04_partyWillBe_locator').getPos()
        self.publicPrivateLabel = DirectLabel(parent=page, relief=None, text=TTLocalizer.PartyPlannerPublicPrivateLabel, text_align=TextNode.ACenter, text_scale=0.065, pos=pos)
        self.publicDescriptionLabel = DirectLabel(parent=page, relief=None, text=TTLocalizer.PartyPlannerPublicDescription, text_align=TextNode.ACenter, text_scale=TTLocalizer.PPpbulicDescriptionLabel, pos=(pos[0] - 0.52, pos[1], pos[2]))
        self.publicDescriptionLabel.stash()
        self.privateDescriptionLabel = DirectLabel(parent=page, relief=None, text=TTLocalizer.PartyPlannerPrivateDescription, text_align=TextNode.ACenter, text_scale=TTLocalizer.PPprivateDescriptionLabel, pos=(pos[0] + 0.55, pos[1], pos[2]))
        self.privateDescriptionLabel.stash()
        pos = self.gui.find('**/step_04_public_locator').getPos()
        self.publicButton = DirectButton(parent=page, relief=None, geom=(self.gui.find('**/publicButton_up'),
         self.gui.find('**/publicButton_down'),
         self.gui.find('**/publicButton_rollover'),
         self.gui.find('**/publicButton_inactive')), text=TTLocalizer.PartyPlannerPublic, text_pos=(pos[0], pos[2]), text_scale=TTLocalizer.PPpublicButton, command=self.__doTogglePublicPrivate)
        self.publicButton['state'] = DirectGuiGlobals.DISABLED
        self.publicButton.bind(DirectGuiGlobals.ENTER, self.__enterPublic)
        self.publicButton.bind(DirectGuiGlobals.EXIT, self.__exitPublic)
        pos = self.gui.find('**/step_04_private_locator').getPos()
        self.privateButton = DirectButton(parent=page, relief=None, geom=(self.gui.find('**/privateButton_up'),
         self.gui.find('**/privateButton_down'),
         self.gui.find('**/privateButton_rollover'),
         self.gui.find('**/privateButton_inactive')), text=TTLocalizer.PartyPlannerPrivate, text_pos=(pos[0], pos[2]), text_scale=TTLocalizer.PPprivateButton, command=self.__doTogglePublicPrivate)
        self.privateButton.bind(DirectGuiGlobals.ENTER, self.__enterPrivate)
        self.privateButton.bind(DirectGuiGlobals.EXIT, self.__exitPrivate)
        self.checkAllButton = DirectButton(parent=page, relief=None, geom=(self.gui.find('**/checkAllButton_up'), self.gui.find('**/checkAllButton_down'), self.gui.find('**/checkAllButton_rollover')), command=self.__doCheckAll)
        self.uncheckAllButton = DirectButton(parent=page, relief=None, geom=(self.gui.find('**/uncheckAllButton_up'), self.gui.find('**/uncheckAllButton_down'), self.gui.find('**/uncheckAllButton_rollover')), command=self.__doUncheckAll)
        return page

    def __doCheckAll(self):
        for friendBox in self.friendList['items']:
            friendBox['indicatorValue'] = True

    def __doUncheckAll(self):
        for friendBox in self.friendList['items']:
            friendBox['indicatorValue'] = False

    def __enterPrivate(self, mouseEvent):
        self.privateDescriptionLabel.unstash()

    def __exitPrivate(self, mouseEvent):
        self.privateDescriptionLabel.stash()

    def __enterPublic(self, mouseEvent):
        self.publicDescriptionLabel.unstash()

    def __exitPublic(self, mouseEvent):
        self.publicDescriptionLabel.stash()

    def __doTogglePublicPrivate(self):
        if self.isPrivate:
            self.isPrivate = False
            self.privateButton['state'] = DirectGuiGlobals.NORMAL
            self.publicButton['state'] = DirectGuiGlobals.DISABLED
        else:
            self.isPrivate = True
            self.privateButton['state'] = DirectGuiGlobals.DISABLED
            self.publicButton['state'] = DirectGuiGlobals.NORMAL

    def _createPartyEditorPage(self):
        page = DirectFrame(self.frame)
        page.setName('PartyPlannerEditorPage')
        self.LayoutTitleLabel = DirectLabel(parent=page, relief=None, text=TTLocalizer.PartyPlannerEditorTitle, pos=self.gui.find('**/title_locator').getPos() + Point3(0.0, 0.0, 0.075), scale=self.titleScale)
        self.costLabel = DirectLabel(parent=page, pos=(-0.74, 0.0, 0.17), relief=None, text=TTLocalizer.PartyPlannerTotalCost % 0, text_align=TextNode.ACenter, scale=TTLocalizer.PPcostLabel, textMayChange=True)
        self.partyGridBackground = DirectFrame(parent=page, relief=None, geom=self.gui.find('**/partyGrid_flat'))
        self.partyGroundsLabel = DirectLabel(parent=page, relief=None, text=TTLocalizer.PartyPlannerPartyGrounds, text_font=ToontownGlobals.getSignFont(), text_fg=VBase4(1.0, 0.0, 0.0, 1.0), text_scale=TTLocalizer.PPpartyGroundsLabel, pos=self.gui.find('**/step_05_partyGrounds_text_locator').getPos(), scale=0.1)
        self.activityBackground = DirectFrame(parent=page, relief=None, geom=self.gui.find('**/activitiesDecorations_flat1'), pos=(0.0, 0.0, 0.04))
        pos = self.gui.find('**/step_05_instructions_locator').getPos()
        self.instructionLabel = DirectLabel(parent=page, relief=None, text=' ', text_pos=(pos[0], pos[2]), text_scale=TTLocalizer.PPinstructionLabel, textMayChange=True, geom=self.gui.find('**/instructions_flat'))
        self.elementTitleLabel = DirectLabel(parent=page, relief=None, text=' ', pos=self.gui.find('**/step_05_activitiesName_text_locator').getPos() + Point3(0.0, 0.0, 0.04), text_scale=TTLocalizer.PPelementTitleLabel, textMayChange=True)
        self.elementPriceNode = TextNode('ElementPrice')
        self.elementPriceNode.setAlign(TextNode.ALeft)
        self.elementPriceNode.setTextColor(0.0, 0.0, 0.0, 1.0)
        self.elementPriceNode.setFont(ToontownGlobals.getToonFont())
        self.elementPrice = page.attachNewNode(self.elementPriceNode)
        self.elementPrice.setScale(TTLocalizer.PPelementPriceNode)
        self.elementPrice.setPos(self.gui.find('**/step_05_activityPrice_text_locator').getPos() + Point3(-0.02, 0.0, 0.04))
        self.elementDescriptionNode = TextNode('ElementDescription')
        self.elementDescriptionNode.setAlign(TextNode.ACenter)
        self.elementDescriptionNode.setWordwrap(8)
        self.elementDescriptionNode.setFont(ToontownGlobals.getToonFont())
        self.elementDescriptionNode.setTextColor(0.0, 0.0, 0.0, 1.0)
        self.elementDescription = page.attachNewNode(self.elementDescriptionNode)
        self.elementDescription.setScale(TTLocalizer.PPelementDescription)
        self.elementDescription.setPos(self.gui.find('**/step_05_activityDescription_text_locator').getPos() + Point3(0.0, 0.0, 0.04))
        self.totalMoney = base.localAvatar.getTotalMoney()
        catalogGui = loader.loadModel('phase_5.5/models/gui/catalog_gui')
        self.beanBank = DirectLabel(parent=page, relief=None, text=str(self.totalMoney), text_align=TextNode.ARight, text_scale=0.075, text_fg=(0.95, 0.95, 0, 1), text_shadow=(0, 0, 0, 1), text_pos=(0.495, -0.53), text_font=ToontownGlobals.getSignFont(), textMayChange=True, image=catalogGui.find('**/bean_bank'), image_scale=(0.65, 0.65, 0.65), scale=0.9, pos=(-0.75, 0.0, 0.6))
        catalogGui.removeNode()
        del catalogGui
        self.accept(localAvatar.uniqueName('moneyChange'), self.__moneyChange)
        self.accept(localAvatar.uniqueName('bankMoneyChange'), self.__moneyChange)
        self.partyEditor = PartyEditor(self, page)
        self.partyEditor.request('Hidden')
        pos = self.gui.find('**/step_05_add_text_locator').getPos()
        self.elementBuyButton = DirectButton(parent=page, relief=None, text=TTLocalizer.PartyPlannerBuy, text_pos=(pos[0], pos[2]), text_scale=TTLocalizer.PPelementBuyButton, geom=(self.gui.find('**/add_up'), self.gui.find('**/add_down'), self.gui.find('**/add_rollover')), geom3_color=VBase4(0.5, 0.5, 0.5, 1.0), textMayChange=True, pos=(0.0, 0.0, 0.04), command=self.partyEditor.buyCurrentElement)
        self.okWithPartyGroundsLayoutEvent = 'okWithPartyGroundsLayoutEvent'
        self.accept(self.okWithPartyGroundsLayoutEvent, self.okWithPartyGroundsLayout)
        self.okWithGroundsGui = TTDialog.TTGlobalDialog(dialogName=self.uniqueName('PartyEditorOkGui'), doneEvent=self.okWithPartyGroundsLayoutEvent, message=TTLocalizer.PartyPlannerOkWithGroundsLayout, style=TTDialog.YesNo, okButtonText=OTPLocalizer.DialogYes, cancelButtonText=OTPLocalizer.DialogNo)
        self.okWithGroundsGui.doneStatus = ''
        self.okWithGroundsGui.hide()
        return page

    def okWithPartyGroundsLayout(self):
        self.okWithGroundsGui.hide()
        if self.okWithGroundsGui.doneStatus == 'ok':
            self.__nextItem()

    def setNextButtonState(self, enabled):
        if enabled:
            self.nextButton['state'] = DirectGuiGlobals.NORMAL
            self.nextButton.show()
        else:
            self.nextButton['state'] = DirectGuiGlobals.DISABLED
            self.nextButton.hide()

    def _createInvitationPage(self):
        self.__handleHolidays()
        page = DirectFrame(self.frame)
        page.setName('PartyPlannerInvitationPage')
        self.invitationTitleLabel = DirectLabel(parent=page, relief=None, text=TTLocalizer.PartyPlannerConfirmTitle, textMayChange=True, pos=self.gui.find('**/title_locator').getPos(), scale=self.titleScale)
        self.invitationBackground = DirectFrame(parent=page, relief=None, geom=self.gui.find('**/invitationBackground'))
        self.inviteVisual = InviteVisual(page)
        self.selectedInviteThemeLabel = DirectLabel(parent=page, relief=None, pos=self.gui.find('**/step_06_theme_locator').getPos(), text='', text_scale=0.06, textMayChange=True)
        self.nextThemeButton = DirectButton(parent=page, relief=None, geom=(self.gui.find('**/topNext_button/nextButton_up'), self.gui.find('**/topNext_button/nextButton_down'), self.gui.find('**/topNext_button/nextButton_rollover')), command=self.__nextTheme)
        self.prevThemeButton = DirectButton(parent=page, relief=None, geom=(self.gui.find('**/topPrevious_button/previousButton_up'), self.gui.find('**/topPrevious_button/previousButton_down'), self.gui.find('**/topPrevious_button/previousButton_rollover')), command=self.__prevTheme)
        pos = self.gui.find('**/step_06_sendInvitation_locator').getPos()
        self.inviteButton = DirectButton(parent=page, relief=None, geom=(self.gui.find('**/send_up'), self.gui.find('**/send_down'), self.gui.find('**/send_rollover')), text=TTLocalizer.PartyPlannerInviteButton, textMayChange=True, text_scale=0.05, text_pos=(pos[0], pos[2]), command=self.__handleComplete)
        return page

    def __handleHolidays(self):
        self.inviteThemes = range(len(PartyGlobals.InviteTheme))
        if hasattr(base.cr, 'newsManager') and base.cr.newsManager:
            holidayIds = base.cr.newsManager.getHolidayIdList()
            if ToontownGlobals.VALENTINES_DAY not in holidayIds:
                self.inviteThemes.remove(PartyGlobals.InviteTheme.Valentoons)
            if ToontownGlobals.VICTORY_PARTY_HOLIDAY not in holidayIds:
                self.inviteThemes.remove(PartyGlobals.InviteTheme.VictoryParty)
            if ToontownGlobals.WINTER_DECORATIONS not in holidayIds and ToontownGlobals.WACKY_WINTER_DECORATIONS not in holidayIds:
                self.inviteThemes.remove(PartyGlobals.InviteTheme.Winter)

    def _createFarewellPage(self):
        page = DirectFrame(self.frame)
        page.setName('PartyPlannerFarewellPage')
        self.confirmTitleLabel = DirectLabel(parent=page, relief=None, text=TTLocalizer.PartyPlannerConfirmationAllOkTitle, textMayChange=True, pos=self.gui.find('**/title_locator').getPos(), scale=self.titleScale)
        pos = self.gui.find('**/step_07_close_text_locator').getPos()
        self.closePlannerButton = DirectButton(parent=page, relief=None, geom=(self.gui.find('**/close_up'), self.gui.find('**/close_down'), self.gui.find('**/close_rollover')), text=TTLocalizer.PartyPlannerClosePlanner, text_scale=0.055, text_pos=(pos[0], pos[2]), command=self.__acceptExit)
        return page

    def close(self):
        self.ignore('addPartyResponseReceived')
        self.ignore(localAvatar.uniqueName('moneyChange'))
        self.ignore(localAvatar.uniqueName('bankMoneyChange'))
        self.timeInputHourUpButton.destroy()
        self.timeInputHourDownButton.destroy()
        self.timeInputMinuteUpButton.destroy()
        self.timeInputMinuteDownButton.destroy()
        self.timeInputAmPmUpButton.destroy()
        self.timeInputAmPmDownButton.destroy()
        self.privateButton.destroy()
        self.publicButton.destroy()
        self.makePartyNowButton.destroy()
        self.checkAllButton.destroy()
        self.uncheckAllButton.destroy()
        self.elementBuyButton.destroy()
        self.nextThemeButton.destroy()
        self.prevThemeButton.destroy()
        self.inviteButton.destroy()
        self.closePlannerButton.destroy()
        self.ignore(self.okWithPartyGroundsLayoutEvent)
        if hasattr(self, 'okWithGroundsGui'):
            self.okWithGroundsGui.cleanup()
            del self.okWithGroundsGui
        if hasattr(self, 'frame') and not self.frame.isEmpty():
            messenger.send(self.doneEvent)
            self.hide()
            self.cleanup()
            self.friendList.removeAndDestroyAllItems()
            self.friendList.destroy()
            self.calendarGuiMonth.destroy()
            self.frame.destroy()
        self.partyPlannerHead.delete()
        self.partyPlannerHead.removeNode()
        self.clearNametag()
        self.partyEditor.request('Cleanup')
        self.partyEditor = None
        self.destroy()
        del self
        return

    def __handleComplete(self):
        self.inviteButton['state'] = DirectGuiGlobals.DISABLED
        self.prevButton['state'] = DirectGuiGlobals.DISABLED
        endTime = self.partyTime + self.partyDuration
        hostId = base.localAvatar.doId
        self.partyActivities = self.partyEditor.partyEditorGrid.getActivitiesOnGrid()
        decorations = self.partyEditor.partyEditorGrid.getDecorationsOnGrid()
        invitees = self.getInvitees()
        self.accept('addPartyResponseReceived', self.processAddPartyResponse)
        base.cr.partyManager.sendAddParty(hostId, self.partyTime.strftime('%Y-%m-%d %H:%M:%S'), endTime.strftime('%Y-%m-%d %H:%M:%S'), self.isPrivate, self.currentInvitationTheme, self.partyActivities, decorations, invitees)

    def getInvitees(self):
        invitees = []
        for friendBox in self.friendList['items']:
            if friendBox['indicatorValue']:
                invitees.append(friendBox.getPythonTag('id'))

        return invitees

    def processAddPartyResponse(self, hostId, errorCode):
        PartyPlanner.notify.debug('processAddPartyResponse : hostId=%d errorCode=%s' % (hostId, PartyGlobals.AddPartyErrorCode.getString(errorCode)))
        goingBackAllowed = False
        if errorCode == PartyGlobals.AddPartyErrorCode.AllOk:
            goingBackAllowed = False
            self.confirmTitleLabel['text'] = TTLocalizer.PartyPlannerConfirmationAllOkTitle
            if self.noFriends or len(self.getInvitees()) == 0:
                confirmRecapText = TTLocalizer.PartyPlannerConfirmationAllOkTextNoFriends
            else:
                confirmRecapText = TTLocalizer.PartyPlannerConfirmationAllOkText
        elif errorCode == PartyGlobals.AddPartyErrorCode.ValidationError:
            self.confirmTitleLabel['text'] = TTLocalizer.PartyPlannerConfirmationErrorTitle
            confirmRecapText = TTLocalizer.PartyPlannerConfirmationValidationErrorText
        elif errorCode == PartyGlobals.AddPartyErrorCode.DatabaseError:
            self.confirmTitleLabel['text'] = TTLocalizer.PartyPlannerConfirmationErrorTitle
            confirmRecapText = TTLocalizer.PartyPlannerConfirmationDatabaseErrorText
        elif errorCode == PartyGlobals.AddPartyErrorCode.TooManyHostedParties:
            goingBackAllowed = False
            self.confirmTitleLabel['text'] = TTLocalizer.PartyPlannerConfirmationErrorTitle
            confirmRecapText = TTLocalizer.PartyPlannerConfirmationTooManyText
        self.nametagGroup.setChat(confirmRecapText, CFSpeech)
        self.request('Farewell', goingBackAllowed)

    def __acceptExit(self):
        PartyPlanner.notify.debug('__acceptExit')
        if hasattr(self, 'frame'):
            self.hide()
            messenger.send(self.doneEvent)

    def __nextItem(self):
        messenger.send('wakeup')
        if self.state == 'PartyEditor' and self.okWithGroundsGui.doneStatus != 'ok':
            self.okWithGroundsGui.show()
            return
        if self.state == 'PartyEditor' and self.noFriends:
            self.request('Date')
            self.selectedCalendarGuiDay = None
            self.calendarGuiMonth.clearSelectedDay()
            return
        if self.state == 'Guests':
            self.selectedCalendarGuiDay = None
            self.calendarGuiMonth.clearSelectedDay()
        if self.state == 'Time':
            if self.partyTime < base.cr.toontownTimeManager.getCurServerDateTime():
                self.okChooseFutureTimeEvent = 'okChooseFutureTimeEvent'
                self.acceptOnce(self.okChooseFutureTimeEvent, self.okChooseFutureTime)
                self.chooseFutureTimeDialog = TTDialog.TTGlobalDialog(dialogName=self.uniqueName('chooseFutureTimeDialog'), doneEvent=self.okChooseFutureTimeEvent, message=TTLocalizer.PartyPlannerChooseFutureTime, style=TTDialog.Acknowledge)
                self.chooseFutureTimeDialog.show()
                return
        self.requestNext()
        return

    def okChooseFutureTime(self):
        if hasattr(self, 'chooseFutureTimeDialog'):
            self.chooseFutureTimeDialog.cleanup()
            del self.chooseFutureTimeDialog
        if hasattr(self, 'okChooseFutureTimeEvent'):
            self.ignore(self.okChooseFutureTimeEvent)

    def __prevItem(self):
        messenger.send('wakeup')
        if self.state == 'Date' and self.noFriends:
            self.request('PartyEditor')
            return
        if self.state == 'Invitation' and self.selectedCalendarGuiDay is None:
            self.request('Guests')
            return
        self.requestPrev()
        return

    def __moneyChange(self, newMoney):
        if hasattr(self, 'totalMoney'):
            self.totalMoney = base.localAvatar.getTotalMoney()
        if hasattr(self, 'beanBank'):
            self.beanBank['text'] = str(int(self.totalMoney))
Ejemplo n.º 9
0
class PlacerTool3D(DirectFrame):
    ORIGINAL_SCALE = (1.0, 1.0, 1.0)
    MINIMIZED_SCALE = (0.85, 1.0, 0.15)
    ORIG_DRAG_BUTTON_POS = (0.37, 0.0, 0.37)
    MINI_DRAG_BUTTON_POS = (0.37, 0.0, 0.03)
    ORIG_MINI_BUTTON_POS = (0.29, 0.0, 0.37)
    MINI_MINI_BUTTON_POS = (0.29, 0.0, 0.03)
    ORIG_NAME_POS = (-0.39, 0.0, 0.27)
    MINI_NAME_POS = (-0.39, 0.0, 0.0)

    def __init__(self,
                 target,
                 increment=0.01,
                 hprIncrement=1.0,
                 parent=aspect2d,
                 pos=(0.0, 0.0, 0.0)):
        DirectFrame.__init__(self, parent)
        self.target = target
        self.increment = increment
        self.minimized = False
        self.mainFrame = DirectFrame(
            parent=self,
            relief=None,
            geom=DGG.getDefaultDialogGeom(),
            geom_color=(1, 1, 0.75, 1),
            geom_scale=self.ORIGINAL_SCALE,
            pos=pos,
        )
        # Arrow gui (preload)
        gui = loader.loadModel('phase_3/models/gui/tt_m_gui_mat_mainGui.bam')
        # Set Bins
        self.mainFrame.setBin('gui-popup', 0)
        # Name
        name = self.target.getName()
        self.nameLabel = TTLabel(self.mainFrame,
                                 text='Target: %s' % name,
                                 pos=self.ORIG_NAME_POS,
                                 text_align=TextNode.ALeft,
                                 text_wordwrap=13)
        # Pos
        pos = self.target.getPos()
        self.posLabel = TTLabel(self.mainFrame,
                                text='Position: ',
                                pos=(-0.39, 0.0, 0.055),
                                text_align=TextNode.ALeft)
        self.xPosSpinner = PlacerToolSpinner(self.mainFrame,
                                             value=pos[0],
                                             pos=(-0.085, 0.0, 0.06),
                                             increment=increment,
                                             callback=self.handleXChange)
        self.yPosSpinner = PlacerToolSpinner(self.mainFrame,
                                             value=pos[1],
                                             pos=(0.1, 0.0, 0.06),
                                             increment=increment,
                                             callback=self.handleYChange)
        self.zPosSpinner = PlacerToolSpinner(self.mainFrame,
                                             value=pos[2],
                                             pos=(0.28, 0.0, 0.06),
                                             increment=increment,
                                             callback=self.handleZChange)
        # hpr
        hpr = self.target.getHpr()
        self.hprLabel = TTLabel(self.mainFrame,
                                text='HPR: ',
                                pos=(-0.39, 0.0, -0.19),
                                text_align=TextNode.ALeft)
        self.hSpinner = PlacerToolSpinner(self.mainFrame,
                                          value=hpr[0],
                                          pos=(-0.085, 0.0, -0.195),
                                          increment=hprIncrement,
                                          callback=self.handleHChange)
        self.pSpinner = PlacerToolSpinner(self.mainFrame,
                                          value=hpr[1],
                                          pos=(0.1, 0.0, -0.195),
                                          increment=hprIncrement,
                                          callback=self.handlePChange)
        self.rSpinner = PlacerToolSpinner(self.mainFrame,
                                          value=hpr[2],
                                          pos=(0.28, 0.0, -0.195),
                                          increment=hprIncrement,
                                          callback=self.handleRChange)
        # scale
        scale = [round(s, 3) for s in self.target.getScale()]
        self.scaleLabel = TTLabel(self.mainFrame,
                                  text='Scale: ',
                                  pos=(-0.39, 0.0, -0.4),
                                  text_align=TextNode.ALeft)

        self.sxSpinner = PlacerToolSpinner(self.mainFrame,
                                           value=hpr[0],
                                           pos=(-0.085, 0.0, -0.4),
                                           increment=increment,
                                           callback=self.handleSxChange)
        self.sySpinner = PlacerToolSpinner(self.mainFrame,
                                           value=hpr[1],
                                           pos=(0.1, 0.0, -0.4),
                                           increment=increment,
                                           callback=self.handleSyChange)
        self.szSpinner = PlacerToolSpinner(self.mainFrame,
                                           value=hpr[2],
                                           pos=(0.28, 0.0, -0.4),
                                           increment=increment,
                                           callback=self.handleSzChange)

        gui.removeNode()
        gui = loader.loadModel('phase_3/models/gui/tt_m_gui_mat_nameShop')
        thumb = gui.find('**/tt_t_gui_mat_namePanelCircle')
        self.dragButton = DirectButton(self.mainFrame,
                                       relief=None,
                                       image=thumb,
                                       image_scale=(0.5, 0.5, 0.5),
                                       pos=self.ORIG_DRAG_BUTTON_POS)
        self.minimizeButton = DirectButton(self.mainFrame,
                                           relief=None,
                                           image=thumb,
                                           image_scale=(0.5, 0.5, 0.5),
                                           image_color=(0.0, 0.0, 0.65, 1.0),
                                           pos=self.ORIG_MINI_BUTTON_POS,
                                           command=self.toggleMinimize,
                                           extraArgs=[])
        self.dragButton.bind(DGG.B1PRESS, self.onPress)
        if target is not None:
            self.setTarget(target)

    def destroy(self):
        self.target = None
        messenger.send('placer-destroyed', [self])
        DirectFrame.destroy(self)

    def setTarget(self, target):
        self.target = target
        name = self.target.getName()
        scale = [round(s, 3) for s in self.target.getScale()]
        x, y, z = self.target.getPos()
        h, p, r = self.target.getHpr()
        sx, sy, sz = self.target.getScale()
        self.nameLabel['text'] = 'Target: %s' % name
        self.xPosSpinner.setValue(x)
        self.yPosSpinner.setValue(y)
        self.zPosSpinner.setValue(z)
        self.hSpinner.setValue(h)
        self.pSpinner.setValue(p)
        self.rSpinner.setValue(r)
        self.sxSpinner.setValue(sx)
        self.sySpinner.setValue(sy)
        self.szSpinner.setValue(sz)

    def handleXChange(self, value):
        self.changeTargetPos(0, value)

    def handleYChange(self, value):
        self.changeTargetPos(1, value)

    def handleZChange(self, value):
        self.changeTargetPos(2, value)

    def handleHChange(self, value):
        self.changeTargetHpr(0, value)

    def handlePChange(self, value):
        self.changeTargetHpr(1, value)

    def handleRChange(self, value):
        self.changeTargetHpr(2, value)

    def handleSxChange(self, value):
        self.changeTargetScale(0, value)

    def handleSyChange(self, value):
        self.changeTargetScale(1, value)

    def handleSzChange(self, value):
        self.changeTargetScale(2, value)

    def changeTargetPos(self, index, value):
        pos = self.target.getPos()
        pos[index] = float(value)
        self.target.setPos(pos)

    def changeTargetHpr(self, index, value):
        hpr = self.target.getHpr()
        hpr[index] = float(value)
        self.target.setHpr(hpr)

    def changeTargetScale(self, index, value):
        pos = self.target.getScale()
        pos[index] = float(value)
        self.target.setScale(pos)

    def toggleMinimize(self):
        if self.minimized:
            self.maximize()
        else:
            self.minimize()

    def minimize(self):
        self.minimized = True
        self.mainFrame['geom_scale'] = self.MINIMIZED_SCALE
        self.nameLabel.setPos(self.MINI_NAME_POS)
        self.dragButton.setPos(self.MINI_DRAG_BUTTON_POS)
        self.minimizeButton.setPos(self.MINI_MINI_BUTTON_POS)
        self.posLabel.hide()
        self.xPosSpinner.hide()
        self.yPosSpinner.hide()
        self.zPosSpinner.hide()
        self.hprLabel.hide()
        self.hSpinner.hide()
        self.pSpinner.hide()
        self.rSpinner.hide()
        self.scaleLabel.hide()
        self.setPos(0, 0, 0)

    def maximize(self):
        self.minimized = False
        self.mainFrame['geom_scale'] = self.ORIGINAL_SCALE
        self.nameLabel.setPos(self.ORIG_NAME_POS)
        self.dragButton.setPos(self.ORIG_DRAG_BUTTON_POS)
        self.minimizeButton.setPos(self.ORIG_MINI_BUTTON_POS)
        self.posLabel.show()
        self.xPosSpinner.show()
        self.yPosSpinner.show()
        self.zPosSpinner.show()
        self.hprLabel.show()
        self.hSpinner.show()
        self.pSpinner.show()
        self.rSpinner.show()
        self.scaleLabel.show()
        self.setPos(0, 0, 0)

    def onPress(self, e=None):
        self.accept('mouse1-up', self.onRelease)
        taskMgr.add(self.mouseMoverTask, '%s-mouseMoverTask' % self.id)

    def onRelease(self, e=None):
        self.ignore('mouse1-up')
        taskMgr.remove('%s-mouseMoverTask' % self.id)

    def mouseMoverTask(self, task):
        if base.mouseWatcherNode.hasMouse():
            mpos = base.mouseWatcherNode.getMouse()
            buttonPos = self.dragButton.getPos()
            newPos = (mpos[0] - buttonPos[0] / 2 - 0.02, 0,
                      mpos[1] - buttonPos[2])
            self.setPos(render2d, newPos)
        return task.cont
Ejemplo n.º 10
0
    def _show_char_desc(self):
        """Show detailed character description.

        Includes description of every character's
        trait and their current status.
        """
        if self._char_desc_shown:
            self._fr["frameSize"] = (-0.31, 0.31, -0.1, 0.115)
            clear_wids(self._char_desc_wids)
            self._status_lab = None
        else:
            shift = 0.7
            self._fr["frameSize"] = (-0.31, 0.31, -0.1, shift)
            shift -= 0.06
            self._char_desc_wids.append(
                DirectLabel(
                    parent=self._fr,
                    # Traits
                    text=base.labels.CHARACTERS[5],  # noqa: F821,
                    text_font=base.main_font,  # noqa: F821,
                    frameSize=(0.1, 0.1, 0.1, 0.1),
                    text_scale=0.03,
                    text_fg=RUST_COL,
                    pos=(-0.225, 0, shift),
                )
            )
            if self.char.id in base.team.chars.keys():  # noqa: F821
                traits_but = DirectButton(
                    parent=self._fr,
                    text="",
                    frameSize=(-0.025, 0.025, -0.025, 0.025),
                    frameTexture=GUI_PIC + "like.png",
                    relief="flat",
                    pos=(0.265, 0, shift + 0.013),
                    command=base.traits_gui.show,  # noqa: F821
                )
                traits_but.bind(
                    DGG.ENTER, self._highlight_traits_but, extraArgs=[traits_but]
                )
                traits_but.bind(
                    DGG.EXIT, self._dehighlight_traits_but, extraArgs=[traits_but]
                )

                self._char_desc_wids.append(traits_but)

            shift = self._fill_traits(shift)

            self._status_lab = DirectLabel(  # Status
                parent=self._fr,
                # Status
                text=base.labels.CHARACTERS[4],  # noqa: F821
                text_font=base.main_font,  # noqa: F821
                frameSize=(0.1, 0.1, 0.1, 0.1),
                text_scale=0.03,
                text_fg=RUST_COL,
                pos=(-0.221, 0, shift),
            )
            self._char_desc_wids.append(self._status_lab)
            self._fill_status(shift)

        self._char_desc_shown = not self._char_desc_shown
Ejemplo n.º 11
0
class DirectWindow(DirectFrame):
    def __init__(
        self,
        pos=(-.5, .5),
        title='Title',
        curSize=(1, 1),
        maxSize=(1, 1),
        minSize=(.5, .5),
        backgroundColor=(1, 1, 1, 1),
        borderColor=(1, 1, 1, 1),
        titleColor=(1, 1, 1, 1),
        borderSize=0.04,
        titleSize=0.06,
        closeButton=False,
        windowParent=aspect2d,
        preserve=True,
        preserveWhole=True,
    ):
        self.preserve = preserve
        self.preserveWhole = preserveWhole
        self.windowParent = windowParent
        self.windowPos = pos
        DirectFrame.__init__(
            self,
            parent=windowParent,
            pos=(self.windowPos[0], 0, self.windowPos[1]),
            frameColor=(0, 0, 0, 0),
            frameTexture=loader.loadTexture(DIRECTORY + 'transparent.png'))
        self.setTransparency(True)

        # the title part of the window, drag around to move the window
        self.headerHeight = titleSize
        h = -self.headerHeight
        self.windowHeaderLeft = DirectButton(
            parent=self,
            frameTexture=DEFAULT_TITLE_GEOM_LEFT,
            frameSize=(-.5, .5, -.5, .5),
            borderWidth=(0, 0),
            relief=DGG.FLAT,
            frameColor=titleColor,
        )
        self.windowHeaderCenter = DirectButton(
            parent=self,
            frameTexture=DEFAULT_TITLE_GEOM_CENTER,
            frameSize=(-.5, .5, -.5, .5),
            borderWidth=(0, 0),
            relief=DGG.FLAT,
            frameColor=titleColor,
        )
        if closeButton:
            rightTitleGeom = DEFAULT_TITLE_GEOM_RIGHT_CLOSE
            command = self.destroy
        else:
            rightTitleGeom = DEFAULT_TITLE_GEOM_RIGHT
            command = None
        self.windowHeaderRight = DirectButton(parent=self,
                                              frameTexture=rightTitleGeom,
                                              frameSize=(-.5, .5, -.5, .5),
                                              borderWidth=(0, 0),
                                              relief=DGG.FLAT,
                                              frameColor=titleColor,
                                              command=command)

        self.windowHeaderLeft.setTransparency(True)
        self.windowHeaderCenter.setTransparency(True)
        self.windowHeaderRight.setTransparency(True)

        self.windowHeaderLeft.bind(DGG.B1PRESS, self.startWindowDrag)
        self.windowHeaderCenter.bind(DGG.B1PRESS, self.startWindowDrag)
        self.windowHeaderRight.bind(DGG.B1PRESS, self.startWindowDrag)

        # this is not handled correctly, if a window is dragged which has been
        # created before another it will not be released
        # check the bugfixed startWindowDrag function
        #self.windowHeader.bind(DGG.B1RELEASE,self.stopWindowDrag)

        text = TextNode('WindowTitleTextNode')
        text.setText(title)
        text.setAlign(TextNode.ACenter)
        text.setTextColor(0, 0, 0, 1)
        text.setShadow(0.05, 0.05)
        text.setShadowColor(1, 1, 1, 1)
        self.textNodePath = self.attachNewNode(text)
        self.textNodePath.setScale(self.headerHeight * 0.8)

        # the content part of the window, put stuff beneath
        # contentWindow.getCanvas() to put it into it
        self.maxVirtualSize = maxSize
        self.minVirtualSize = minSize
        self.resizeSize = borderSize
        self.contentWindow = DirectScrolledFrame(
            parent=self,
            pos=(0, 0, -self.headerHeight),
            canvasSize=(0, self.maxVirtualSize[0], 0, self.maxVirtualSize[1]),
            frameColor=(
                0, 0, 0,
                0),  # defines the background color of the resize-button
            relief=DGG.FLAT,
            borderWidth=(0, 0),
            verticalScroll_frameSize=[0, self.resizeSize, 0, 1],
            horizontalScroll_frameSize=[0, 1, 0, self.resizeSize],

            # resize the scrollbar according to window size
            verticalScroll_resizeThumb=False,
            horizontalScroll_resizeThumb=False,
            # define the textures for the scrollbars
            verticalScroll_frameTexture=VERTICALSCROLL_FRAMETEXTURE,
            verticalScroll_incButton_frameTexture=
            VERTICALSCROLL_INCBUTTON_FRAMETEXTURE,
            verticalScroll_decButton_frameTexture=
            VERTICALSCROLL_DECBUTTON_FRAMETEXTURE,
            verticalScroll_thumb_frameTexture=VERTICALSCROLL_TUMB_FRAMETEXTURE,
            horizontalScroll_frameTexture=HORIZONTALSCROLL_FRAMETEXTURE,
            horizontalScroll_incButton_frameTexture=
            HORIZONTALSCROLL_INCBUTTON_FRAMETEXTURE,
            horizontalScroll_decButton_frameTexture=
            HORIZONTALSCROLL_DECBUTTON_FRAMETEXTURE,
            horizontalScroll_thumb_frameTexture=
            HORIZONTALSCROLL_TUMB_FRAMETEXTURE,
            # make all flat, so the texture is as we want it
            verticalScroll_relief=DGG.FLAT,
            verticalScroll_thumb_relief=DGG.FLAT,
            verticalScroll_decButton_relief=DGG.FLAT,
            verticalScroll_incButton_relief=DGG.FLAT,
            horizontalScroll_relief=DGG.FLAT,
            horizontalScroll_thumb_relief=DGG.FLAT,
            horizontalScroll_decButton_relief=DGG.FLAT,
            horizontalScroll_incButton_relief=DGG.FLAT,
            # colors
            verticalScroll_frameColor=borderColor,
            verticalScroll_incButton_frameColor=borderColor,
            verticalScroll_decButton_frameColor=borderColor,
            verticalScroll_thumb_frameColor=borderColor,
            horizontalScroll_frameColor=borderColor,
            horizontalScroll_incButton_frameColor=borderColor,
            horizontalScroll_decButton_frameColor=borderColor,
            horizontalScroll_thumb_frameColor=borderColor,
        )
        self.contentWindow.setTransparency(True)

        # background color
        self.backgroundColor = DirectFrame(
            parent=self.contentWindow.getCanvas(),
            frameSize=(0, self.maxVirtualSize[0], 0, self.maxVirtualSize[1]),
            frameColor=backgroundColor,
            relief=DGG.FLAT,
            borderWidth=(.01, .01),
        )
        self.backgroundColor.setTransparency(True)

        # Add a box
        self.box = boxes.VBox(parent=self.getCanvas())

        # is needed for some nicer visuals of the resize button (background)
        self.windowResizeBackground = DirectButton(
            parent=self,
            frameSize=(-.5, .5, -.5, .5),
            borderWidth=(0, 0),
            scale=(self.resizeSize, 1, self.resizeSize),
            relief=DGG.FLAT,
            frameColor=backgroundColor,
        )

        # the resize button of the window
        self.windowResize = DirectButton(
            parent=self,
            frameSize=(-.5, .5, -.5, .5),
            borderWidth=(0, 0),
            scale=(self.resizeSize, 1, self.resizeSize),
            relief=DGG.FLAT,
            frameTexture=DEFAULT_RESIZE_GEOM,
            frameColor=borderColor,
        )
        self.windowResize.setTransparency(True)
        self.windowResize.bind(DGG.B1PRESS, self.startResizeDrag)
        self.windowResize.bind(DGG.B1RELEASE, self.stopResizeDrag)

        # offset then clicking on the resize button from the mouse to the resizebutton
        # position, required to calculate the position / scaling
        self.offset = None
        self.taskName = "resizeTask-%s" % str(hash(self))

        # do sizing of the window (minimum)
        #self.resize( Vec3(0,0,0), Vec3(0,0,0) )
        # maximum
        #self.resize( Vec3(100,0,-100), Vec3(0,0,0) )
        self.resize(Vec3(curSize[0], 0, -curSize[1]), Vec3(0, 0, 0))

    def getCanvas(self):
        return self.contentWindow.getCanvas()

    # dragging functions
    def startWindowDrag(self, param):
        self.wrtReparentTo(aspect2dMouseNode)
        self.ignoreAll()
        self.accept('mouse1-up', self.stopWindowDrag)

    def stopWindowDrag(self, param=None):
        # this is called 2 times (bug), so make sure it's not already parented to aspect2d
        if self.getParent() != self.windowParent:
            self.wrtReparentTo(self.windowParent)
        if self.preserve:
            if self.preserveWhole:
                if self.getZ() > 1:
                    self.setZ(1)
                elif self.getZ() < -1 - self.getHeight():
                    self.setZ(-1 - self.getHeight())
                if self.getX() > base.a2dRight - self.getWidth():
                    self.setX(base.a2dRight - self.getWidth())
                elif self.getX() < base.a2dLeft:
                    self.setX(base.a2dLeft)
            else:
                if self.getZ() > 1:
                    self.setZ(1)
                elif self.getZ() < -1 + self.headerHeight:
                    self.setZ(-1 + self.headerHeight)
                if self.getX() > base.a2dRight - self.headerHeight:
                    self.setX(base.a2dRight - self.headerHeight)
                elif self.getX(
                ) < base.a2dLeft + self.headerHeight - self.getWidth():
                    self.setX(base.a2dLeft + self.headerHeight -
                              self.getWidth())
        #else: #Window moved beyond reach. Destroy window?

    # resize functions
    def resize(self, mPos, offset):
        mXPos = max(min(mPos.getX(), self.maxVirtualSize[0]),
                    self.minVirtualSize[0])
        mZPos = max(min(mPos.getZ(), -self.minVirtualSize[1]),
                    -self.maxVirtualSize[1] - self.headerHeight)
        self.windowResize.setPos(mXPos - self.resizeSize / 2., 0,
                                 mZPos + self.resizeSize / 2.)
        self.windowResizeBackground.setPos(mXPos - self.resizeSize / 2., 0,
                                           mZPos + self.resizeSize / 2.)
        self['frameSize'] = (0, mXPos, 0, mZPos)
        self.windowHeaderLeft.setPos(self.headerHeight / 2., 0,
                                     -self.headerHeight / 2.)
        self.windowHeaderLeft.setScale(self.headerHeight, 1, self.headerHeight)
        self.windowHeaderCenter.setPos(mXPos / 2., 0, -self.headerHeight / 2.)
        self.windowHeaderCenter.setScale(mXPos - self.headerHeight * 2., 1,
                                         self.headerHeight)
        self.windowHeaderRight.setPos(mXPos - self.headerHeight / 2., 0,
                                      -self.headerHeight / 2.)
        self.windowHeaderRight.setScale(self.headerHeight, 1,
                                        self.headerHeight)
        self.contentWindow['frameSize'] = (0, mXPos, mZPos + self.headerHeight,
                                           0)
        self.textNodePath.setPos(mXPos / 2., 0, -self.headerHeight / 3. * 2.)
        # show and hide that small background for the window sizer
        if mXPos == self.maxVirtualSize[0] and \
           mZPos == -self.maxVirtualSize[1]-self.headerHeight:
            self.windowResizeBackground.hide()
        else:
            self.windowResizeBackground.show()

    def resizeTask(self, task=None):
        mPos = aspect2dMouseNode.getPos(self) + self.offset
        self.resize(mPos, self.offset)
        return task.cont

    def startResizeDrag(self, param):
        self.offset = self.windowResize.getPos(aspect2dMouseNode)
        taskMgr.remove(self.taskName)
        taskMgr.add(self.resizeTask, self.taskName)

    def stopResizeDrag(self, param):
        taskMgr.remove(self.taskName)
        # get the window to the front
        self.wrtReparentTo(self.windowParent)

    def addHorizontal(self, widgets):
        """
      Accepts a list of directgui objects which are added to a horizontal box, which is then added to the vertical stack.
      """
        hbox = boxes.HBox()
        for widget in widgets:
            hbox.pack(widget)
        self.box.pack(hbox)
        self.updateMaxSize()

    def addVertical(self, widgets):
        """
      Accepts a list of directgui objects which are added to a vertical box, which is then added to the vertical stack.
      May cause funky layout results.
      """
        #vbox = boxes.VBox()
        for widget in widgets:
            self.box.pack(widget)
        self.updateMaxSize()

    def add(self, widgets):
        """Shortcut function for addVertical"""
        self.addVertical(widgets)

    def updateMaxSize(self):
        """Updates the max canvas size to include all items packed.
      Window is resized to show all contents."""
        bottomLeft, topRight = self.box.getTightBounds()
        self.maxVirtualSize = (topRight[0], -bottomLeft[2])
        self.contentWindow['canvasSize'] = (0, self.maxVirtualSize[0],
                                            -self.maxVirtualSize[1], 0)
        self.backgroundColor['frameSize'] = (0, self.maxVirtualSize[0],
                                             -self.maxVirtualSize[1], 0)

        #perhaps this should be optional -- automatically resize for new elements
        self.reset()

    def reset(self):
        """Poorly named function that resizes window to fit all contents"""
        self.resize(
            Vec3(self.maxVirtualSize[0], 0,
                 -self.maxVirtualSize[1] - self.headerHeight), Vec3(0, 0, 0))
Ejemplo n.º 12
0
class GloveShopGui:
    def __init__(self):
        self.index = 0
        self.id = time.time()
        self.lastGlove = base.localAvatar.style.gloveColor
        self.timer = ToontownTimer.ToontownTimer()
        self.timer.reparentTo(aspect2d)
        self.timer.posInTopRightCorner()
        self.timer.countdown(GloveNPCGlobals.TIMER_SECONDS, self.__exit,
                             [GloveNPCGlobals.TIMER_END])
        self.setupButtons()
        self.bindButtons()
        self.__updateIndex(0)

    def setupButtons(self):
        gui = loader.loadModel('phase_3/models/gui/tt_m_gui_mat_mainGui')
        arrowImage = (gui.find('**/tt_t_gui_mat_shuffleArrowUp'),
                      gui.find('**/tt_t_gui_mat_shuffleArrowDown'))
        buttonImage = (gui.find('**/tt_t_gui_mat_shuffleUp'),
                       gui.find('**/tt_t_gui_mat_shuffleDown'))

        self.title = DirectLabel(aspect2d,
                                 relief=None,
                                 text=TTLocalizer.GloveGuiTitle,
                                 text_fg=(0, 1, 0, 1),
                                 text_scale=0.15,
                                 text_font=ToontownGlobals.getSignFont(),
                                 pos=(0, 0, -0.30),
                                 text_shadow=(1, 1, 1, 1))

        self.notice = DirectLabel(aspect2d,
                                  relief=None,
                                  text='',
                                  text_fg=(1, 0, 0, 1),
                                  text_scale=0.11,
                                  text_font=ToontownGlobals.getSignFont(),
                                  pos=(0, 0, -0.45),
                                  text_shadow=(1, 1, 1, 1))

        self.color = DirectLabel(aspect2d,
                                 relief=None,
                                 text='',
                                 text_scale=0.11,
                                 text_font=ToontownGlobals.getSignFont(),
                                 pos=(0, 0, -0.70),
                                 text_shadow=(1, 1, 1, 1))

        self.buyButton = DirectButton(
            aspect2d,
            relief=None,
            image=buttonImage,
            text=TTLocalizer.GloveGuiBuy,
            text_font=ToontownGlobals.getInterfaceFont(),
            text_scale=0.11,
            text_pos=(0, -0.02),
            pos=(-0.60, 0, -0.90),
            text_fg=(1, 1, 1, 1),
            text_shadow=(0, 0, 0, 1),
            command=self.__exit,
            extraArgs=[GloveNPCGlobals.CHANGE])

        self.cancelButton = DirectButton(
            aspect2d,
            relief=None,
            image=buttonImage,
            text=TTLocalizer.lCancel,
            text_font=ToontownGlobals.getInterfaceFont(),
            text_scale=0.11,
            text_pos=(0, -0.02),
            pos=(0.60, 0, -0.90),
            text_fg=(1, 1, 1, 1),
            text_shadow=(0, 0, 0, 1),
            command=self.__exit,
            extraArgs=[GloveNPCGlobals.USER_CANCEL])

        self.downArrow = DirectButton(aspect2d,
                                      relief=None,
                                      image=arrowImage,
                                      pos=(-0.60, 0, -0.66))
        self.upArrow = DirectButton(aspect2d,
                                    relief=None,
                                    image=arrowImage,
                                    pos=(0.60, 0, -0.66),
                                    scale=-1)

        gui.removeNode()

    def bindButtons(self):
        self.downArrow.bind(DGG.B1PRESS, self.__taskUpdate, extraArgs=[-1])
        self.downArrow.bind(DGG.B1RELEASE, self.__taskDone)
        self.upArrow.bind(DGG.B1PRESS, self.__taskUpdate, extraArgs=[1])
        self.upArrow.bind(DGG.B1RELEASE, self.__taskDone)

    def destroy(self):
        if self.timer:
            self.timer.destroy()

        if not hasattr(self, 'title'):
            return

        # TODO: DirectDialog-ify
        self.title.destroy()
        self.notice.destroy()
        self.color.destroy()
        self.buyButton.destroy()
        self.cancelButton.destroy()
        self.downArrow.destroy()
        self.upArrow.destroy()
        del self.title
        del self.notice
        del self.color
        del self.buyButton
        del self.cancelButton
        del self.downArrow
        del self.upArrow

        taskMgr.remove('runGloveCounter-%s' % self.id)

    def setClientGlove(self, color):
        dna = base.localAvatar.style

        dna.gloveColor = color
        base.localAvatar.setDNA(dna)

    def __exit(self, state):
        self.destroy()
        self.setClientGlove(self.lastGlove)
        messenger.send(
            'gloveShopDone',
            [state, self.index if state == GloveNPCGlobals.CHANGE else 0])

    def __updateIndex(self, offset):
        self.index += offset
        hitLimit = 0

        if self.index <= 0:
            self.downArrow['state'] = DGG.DISABLED
            hitLimit = 1
        else:
            self.downArrow['state'] = DGG.NORMAL

        if (self.index + 1) >= len(TTLocalizer.NumToColor):
            self.upArrow['state'] = DGG.DISABLED
            hitLimit = 1
        else:
            self.upArrow['state'] = DGG.NORMAL

        if self.lastGlove == self.index:
            self.buyButton['state'] = DGG.DISABLED
            self.notice['text'] = TTLocalizer.GloveGuiSameColor
        else:
            self.buyButton['state'] = DGG.NORMAL
            self.notice[
                'text'] = TTLocalizer.GloveGuiNotice % ToontownGlobals.GloveCost

        self.color['text'] = TTLocalizer.NumToColor[self.index]
        self.color['text_fg'] = ToonDNA.allColorsList[self.index]
        self.setClientGlove(self.index)
        return hitLimit

    def __runTask(self, task):
        if task.time - task.prevTime < task.delayTime:
            return Task.cont
        else:
            task.delayTime = max(0.05, task.delayTime * 0.75)
            task.prevTime = task.time
            hitLimit = self.__updateIndex(task.delta)

            return Task.done if hitLimit else Task.cont

    def __taskDone(self, event):
        messenger.send('wakeup')
        taskMgr.remove('runGloveCounter-%s' % self.id)

    def __taskUpdate(self, delta, event):
        messenger.send('wakeup')

        task = Task(self.__runTask)
        task.delayTime = 0.4
        task.prevTime = 0.0
        task.delta = delta
        hitLimit = self.__updateIndex(delta)

        if not hitLimit:
            taskMgr.add(task, 'runGloveCounter-%s' % self.id)
Ejemplo n.º 13
0
    def __init__(self):
        self._coh_desc_wids = []
        self._coh_desc_shown = False
        self._res_desc_wids = []
        self._res_desc_shown = False
        self._resources = {}
        self._blink_step = 0
        self._reload_ico = None
        self._reload_min = None

        self._err_snd = loader.loadSfx("sounds/GUI/error.ogg")  # noqa: F821

        self._res_frame = DirectFrame(
            parent=base.a2dTopLeft,  # noqa: F821
            frameSize=(-0.37, 0.37, -0.03, 0.028),
            pos=(0.37, 0, -0.028),
            frameTexture=GUI_PIC + "metal1.png",
        )
        self._res_frame.setTransparency(TransparencyAttrib.MAlpha)

        DirectFrame(
            parent=self._res_frame,  # noqa: F821
            frameSize=(-0.023, 0.023, -0.023, 0.023),
            pos=(-0.34, 0, 0),
            frameTexture=GUI_PIC + "dollar.png",
        )
        self._resources["dollars"] = DirectLabel(
            parent=self._res_frame,
            text="",
            frameSize=(0.1, 0.1, 0.1, 0.1),
            text_scale=0.035,
            text_fg=RUST_COL,
            pos=(-0.27, 0, -0.008),
        )
        DirectFrame(
            parent=self._res_frame,  # noqa: F821
            frameSize=(-0.018, 0.018, -0.018, 0.018),
            pos=(-0.18, 0, 0),
            frameTexture=GUI_PIC + "chars.png",
        )
        self._resources["chars"] = DirectLabel(
            parent=self._res_frame,
            text="{}/{}".format(len(base.team.chars), base.train.cells),  # noqa: F821
            frameSize=(0.1, 0.1, 0.1, 0.1),
            text_scale=0.035,
            text_fg=RUST_COL,
            pos=(-0.12, 0, -0.008),
        )
        but = DirectButton(
            parent=self._res_frame,
            frameSize=(-0.023, 0.023, -0.023, 0.023),
            relief="flat",
            pos=(-0.06, 0, 0),
            frameTexture=GUI_PIC + "medicine.png",
            command=base.team.use_medicine,  # noqa: F821
        )
        but.bind(DGG.ENTER, self._highlight_res_but, extraArgs=[but, "medicine_boxes"])
        but.bind(DGG.EXIT, self._dehighlight_but, extraArgs=[but])

        self._resources["medicine_boxes"] = DirectLabel(
            parent=self._res_frame,
            text="0",
            frameSize=(0.1, 0.1, 0.1, 0.1),
            text_scale=0.035,
            text_fg=RUST_COL,
            pos=(-0.02, 0, -0.008),
        )
        but = DirectButton(
            parent=self._res_frame,
            frameSize=(-0.023, 0.023, -0.023, 0.023),
            relief="flat",
            pos=(0.035, 0, 0),
            frameTexture=GUI_PIC + "smoke_filter.png",
            command=base.train.use_smoke_filter,  # noqa: F821
        )
        but.bind(DGG.ENTER, self._highlight_res_but, extraArgs=[but, "smoke_filters"])
        but.bind(DGG.EXIT, self._dehighlight_but, extraArgs=[but])

        self._resources["smoke_filters"] = DirectLabel(
            parent=self._res_frame,
            text="0",
            frameSize=(0.1, 0.1, 0.1, 0.1),
            text_scale=0.035,
            text_fg=RUST_COL,
            pos=(0.075, 0, -0.008),
        )
        but = DirectButton(
            parent=self._res_frame,
            frameSize=(-0.014, 0.014, -0.021, 0.021),
            relief="flat",
            pos=(0.12, 0, 0),
            frameTexture=GUI_PIC + "stimulator.png",
            command=base.team.use_stimulator,  # noqa: F821
        )
        but.bind(DGG.ENTER, self._highlight_res_but, extraArgs=[but, "stimulators"])
        but.bind(DGG.EXIT, self._dehighlight_but, extraArgs=[but])

        self._resources["stimulators"] = DirectLabel(
            parent=self._res_frame,
            text="0",
            frameSize=(0.1, 0.1, 0.1, 0.1),
            text_scale=0.035,
            text_fg=RUST_COL,
            pos=(0.16, 0, -0.008),
        )
        DirectButton(
            parent=self._res_frame,
            frameSize=(-0.014, 0.014, -0.021, 0.021),
            relief="flat",
            pos=(0.2, 0, 0),
            frameTexture=GUI_PIC + "places_of_interest.png",
        )
        self._resources["places_of_interest"] = DirectLabel(
            parent=self._res_frame,
            text="0/10",
            frameSize=(0.1, 0.1, 0.1, 0.1),
            text_scale=0.035,
            text_fg=RUST_COL,
            pos=(0.27, 0, -0.008),
        )
        DirectButton(
            parent=self._res_frame,
            pos=(0.34, 0, -0.013),
            command=self._show_expendable_resources,
            clickSound=base.main_menu.click_snd,  # noqa: F821
            **ABOUT_BUT_PARAMS,
        ).setTransparency(TransparencyAttrib.MAlpha)

        self._coh_frame = DirectFrame(
            parent=base.a2dBottomRight,  # noqa: F821
            frameSize=(-0.55, 0.55, -0.05, 0.05),
            pos=(-0.6, 0, 1.95),
            frameTexture=GUI_PIC + "metal1.png",
            state=DGG.NORMAL,
        )
        self._coh_frame.setTransparency(TransparencyAttrib.MAlpha)

        self._cohesion = DirectWaitBar(
            parent=self._coh_frame,
            frameSize=(-0.45, 0.45, -0.002, 0.002),
            frameColor=(0.35, 0.35, 0.35, 1),
            value=0,
            barColor=SILVER_COL,
            pos=(0, 0, 0.02),
        )
        recall_ico = DirectButton(
            parent=self._coh_frame,
            frameSize=(-0.023, 0.023, -0.023, 0.023),
            frameTexture=GUI_PIC + "ny_recall.png",
            pos=(-0.27, 0, -0.02),
            relief="flat",
            command=base.team.cohesion_recall,  # noqa: F821
        )
        recall_ico.setTransparency(TransparencyAttrib.MAlpha)
        recall_ico.bind(DGG.ENTER, self._highlight_coh_but, extraArgs=[recall_ico])
        recall_ico.bind(DGG.EXIT, self._dehighlight_but, extraArgs=[recall_ico])

        cover_ico = DirectButton(
            parent=self._coh_frame,
            frameSize=(-0.035, 0.035, -0.035, 0.035),
            frameTexture=GUI_PIC + "ny_cover.png",
            pos=(-0.09, 0, -0.01),
            relief="flat",
            command=base.team.cohesion_cover_fire,  # noqa: F821
        )
        cover_ico.setTransparency(TransparencyAttrib.MAlpha)
        cover_ico.bind(DGG.ENTER, self._highlight_coh_but, extraArgs=[cover_ico])
        cover_ico.bind(DGG.EXIT, self._dehighlight_but, extraArgs=[cover_ico])

        heal_ico = DirectButton(
            parent=self._coh_frame,
            frameSize=(-0.023, 0.023, -0.023, 0.023),
            frameTexture=GUI_PIC + "ny_heal.png",
            pos=(0.09, 0, -0.015),
            relief="flat",
            command=base.team.cohesion_heal_wounded,  # noqa: F821
        )
        heal_ico.setTransparency(TransparencyAttrib.MAlpha)
        heal_ico.bind(DGG.ENTER, self._highlight_coh_but, extraArgs=[heal_ico])
        heal_ico.bind(DGG.EXIT, self._dehighlight_but, extraArgs=[heal_ico])

        rage_ico = DirectButton(
            parent=self._coh_frame,
            frameSize=(-0.035, 0.035, -0.035, 0.035),
            frameTexture=GUI_PIC + "ny_rage.png",
            pos=(0.27, 0, -0.015),
            relief="flat",
            command=base.team.cohesion_rage,  # noqa: F821
        )
        rage_ico.setTransparency(TransparencyAttrib.MAlpha)
        rage_ico.bind(DGG.ENTER, self._highlight_coh_but, extraArgs=[rage_ico])
        rage_ico.bind(DGG.EXIT, self._dehighlight_but, extraArgs=[rage_ico])

        heart_ico = DirectButton(
            parent=self._coh_frame,
            frameSize=(-0.035, 0.035, -0.035, 0.035),
            frameTexture=GUI_PIC + "ny_heart.png",
            pos=(0.445, 0, -0.015),
            relief="flat",
            command=base.team.cohesion_hold_together,  # noqa: F821
        )
        heart_ico.setTransparency(TransparencyAttrib.MAlpha)
        heart_ico.bind(DGG.ENTER, self._highlight_coh_but, extraArgs=[heart_ico])
        heart_ico.bind(DGG.EXIT, self._dehighlight_but, extraArgs=[heart_ico])

        self._coh_icons = (
            {"wid": recall_ico, "file": "recall.png", "value": 20},
            {"wid": cover_ico, "file": "cover.png", "value": 40},
            {"wid": heal_ico, "file": "heal.png", "value": 60},
            {"wid": rage_ico, "file": "rage.png", "value": 80},
            {"wid": heart_ico, "file": "heart.png", "value": 100},
        )
        DirectButton(
            parent=self._coh_frame,
            pos=(-0.5, 0, -0.028),
            command=self._show_cohesion_abilities,
            clickSound=base.main_menu.click_snd,  # noqa: F821
            **ABOUT_BUT_PARAMS,
        ).setTransparency(TransparencyAttrib.MAlpha)
Ejemplo n.º 14
0
    def render(self):
        ''' traverse the tree and update the visuals according to it
    '''
        for treeItem in self.treeStructure.getRec():
            # create nodes that have no visual elements
            if not treeItem in self.treeStructureNodes:
                treeNode = self.childrenCanvas.attachNewNode('')

                hor = self.horizontalTreeLine.instanceUnderNode(treeNode, '')
                vert = self.verticalTreeLine.instanceUnderNode(treeNode, '')
                vert.setZ(0.007)
                hor.setPos(-1.5 * self.itemIndent, 0, self.itemScale * .25)
                vert.setX(-.5 * self.itemIndent)

                nodeButton = DirectButton(
                    parent=treeNode,
                    scale=self.itemScale,
                    relief=DGG.FLAT,
                    text_scale=self.itemTextScale,
                    text_align=TextNode.ALeft,
                    text=treeItem.name,
                    rolloverSound=None,
                    #clickSound=None,
                )
                nodeButton.bind(DGG.B1PRESS, treeItem.button1press)
                nodeButton.bind(DGG.B2PRESS, treeItem.button2press)
                nodeButton.bind(DGG.B3PRESS, treeItem.button3press)

                #treeButton = None
                #if len(treeItem.childrens) > 0:
                treeButton = DirectButton(
                    parent=nodeButton,
                    frameColor=(1, 1, 1, 1),
                    frameSize=(-.4, .4, -.4, .4),
                    pos=(-.5 * self.itemIndent / self.itemScale, 0, .25),
                    text='',
                    text_pos=(-.1, -.22),
                    text_scale=(1.6, 1),
                    text_fg=(0, 0, 0, 1),
                    enableEdit=0,
                    command=treeItem.setOpen,
                    sortOrder=1000,
                    rolloverSound=None,
                    #clickSound=None,
                )

                self.treeStructureNodes[treeItem] = [
                    treeNode, nodeButton, treeButton, hor, vert
                ]

        # destroy nodes no more used
        for treeItem in self.treeStructureNodes.keys()[:]:
            #treeItem = self.treeStructureNodes[treeName]
            if treeItem not in self.treeStructure.getRec():
                treeNode, nodeButton, treeButton, hor, vert = self.treeStructureNodes[
                    treeItem]
                #nodeButton['text']=''
                nodeButton.unbind(DGG.B1PRESS)
                nodeButton.unbind(DGG.B2PRESS)
                nodeButton.unbind(DGG.B3PRESS)
                #nodeButton.detachNode()
                #nodeButton.removeNode()
                nodeButton.destroy()
                if treeButton:
                    #treeButton['text']=''
                    #treeButton['command']=None
                    treeButton.detachNode()
                    treeButton.removeNode()
                hor.detachNode()
                hor.removeNode()
                vert.detachNode()
                vert.removeNode()
                treeItem.destroy()
                #treeNode.detachNode()
                treeNode.removeNode()
                #treeNode.destroy()
                del self.treeStructureNodes[treeItem]

        frameHeight = len(self.treeStructureNodes) * self.verticalSpacing
        self.childrenFrame['canvasSize'] = (0, self.frameWidth -
                                            self.itemScale * 2, 0, frameHeight)
        self.childrenCanvas.setZ(frameHeight - 1)
Ejemplo n.º 15
0
   def addItem(self,text,extraArgs=None,atIndex=None,textColorName=None):
       """
          add item to the list
          text : text for the button
          extraArgs : the object which will be passed to user command(s)
                      (both command and contextMenu) when the button get clicked
          atIndex : where to add the item
                    <None> : put item at the end of list
                    <integer> : put item at index <integer>
                    <button> : put item at <button>'s index
           textColorName : the color name eg. 'yellow'
       """
       textColor = self.buttonTextColor
       if textColorName != None:
           textColor = globals.colors[textColorName]
           
       button = DirectButton(parent=self.canvas,
           scale=self.itemScale,
           relief=DGG.FLAT,
           frameColor=(0,0,0,0),text_scale=self.itemTextScale,
           text=text, text_pos=(0,self.itemTextZ),text_fg=textColor,
           text_font=self.font, text_align=TextNode.ALeft,
           command=self.__setFocusButton,
           enableEdit=0, suppressMouse=0, rolloverSound=None,clickSound=None)
       #button.setMyMode(self.mode)
       l,r,b,t=button.getBounds()
       # top & bottom are blindly set without knowing where exactly the baseline is,
       # but this ratio fits most fonts
       baseline=-self.fontHeight*.25
       #button['saved_color'] = textColor
       button['frameSize']=(l-self.xtraSideSpace,r+self.xtraSideSpace,baseline,baseline+self.fontHeight)
 
 #          Zc=NodePath(button).getBounds().getCenter()[1]-self.fontHeight*.5+.25
 # #          Zc=button.getCenter()[1]-self.fontHeight*.5+.25
 #          button['frameSize']=(l-self.xtraSideSpace,r+self.xtraSideSpace,Zc,Zc+self.fontHeight)
      
       button['extraArgs']=[button,extraArgs]
       button._DirectGuiBase__componentInfo['text2'][0].setColorScale(self.rolloverColor)
       button.bind(DGG.B3PRESS,self.__rightPressed,[button])
       if isinstance(atIndex,DirectButton):
          if atIndex.isEmpty():
             atIndex=None
          else:
             index=self.buttonsList.index(atIndex)
             self.buttonsList.insert(index,button)
       if atIndex==None:
          self.buttonsList.append(button)
          index=self.numItems
       elif type(atIndex)==IntType:
          index=atIndex
          self.buttonsList.insert(index,button)
       Zpos=(-.7-index)*self.itemVertSpacing
       button.setPos(.02,0,Zpos)
       if index!=self.numItems:
          for i in range(index+1,self.numItems+1):
              self.buttonsList[i].setZ(self.buttonsList[i],-self.fontHeight)
       self.numItems+=1
       self.__adjustCanvasLength(self.numItems)
       if self.autoFocus:
          self.focusViewOnItem(index)
       if self.colorChange:
          Sequence(
             button.colorScaleInterval(self.colorChangeDuration,self.newItemColor,globals.colors['guiblue3']),
             button.colorScaleInterval(self.colorChangeDuration,Vec4(1,1,1,1),self.newItemColor)
             ).start()
Ejemplo n.º 16
0
class OptionPage(StateData):
    def __init__(self, book, parentFSM):
        self.book = book
        self.parentFSM = parentFSM
        StateData.__init__(self, 'optionPageDone')
        self.fsm = ClassicFSM('OptionPage', [
            State('off', self.enterOff, self.exitOff),
            State('basePage', self.enterBasePage, self.exitBasePage),
            State('displayPage', self.enterDisplayPage, self.exitDisplayPage)
        ], 'off', 'off')
        self.fsm.enterInitialState()
        self.parentFSM.getStateNamed('optionPage').addChild(self.fsm)

    def enterOff(self):
        pass

    def exitOff(self):
        pass

    def load(self):
        StateData.load(self)

    def unload(self):
        StateData.unload(self)

    def enter(self):
        StateData.enter(self)
        self.fsm.request('basePage')

    def exit(self):
        self.fsm.request('off')
        StateData.exit(self)

    def openDisplayPage(self):
        self.fsm.request('displayPage')

    def enterDisplayPage(self):
        self.book.createPageButtons(False, False)
        self.book.setTitle('Display Options')
        dialog_gui = loader.loadModel(
            'phase_3/models/gui/dialog_box_buttons_gui.bam')
        width, height, fs, music, sfx, tex_detail, model_detail, aa, af = SettingsManager(
        ).getSettings('settings.json')
        self.width = width
        self.height = height
        self.windowType = [fs]
        self.buttons = [
            DirectRadioButton(text='Windowed',
                              variable=self.windowType,
                              value=[False],
                              scale=0.1,
                              pos=(-0.45, 0.15, 0.15)),
            DirectRadioButton(text='Fullscreen',
                              variable=self.windowType,
                              value=[True],
                              scale=0.1,
                              pos=(-0.45, -0.15, -0.15))
        ]
        for button in self.buttons:
            button.setOthers(self.buttons)

        self.resoLbl = DirectLabel(text='%sx%s' % (width, height),
                                   scale=0.08,
                                   relief=None,
                                   pos=(0.25, 0, 0))
        self.resSlider = DirectSlider(range=(0, 200),
                                      pageSize=50,
                                      command=self.setResoText,
                                      scale=0.3,
                                      orientation=DGG.VERTICAL,
                                      pos=(0.6, 0, 0))
        self.okBtn = DirectButton(text='OK',
                                  geom=CIGlobals.getOkayBtnGeom(),
                                  relief=None,
                                  pos=(-0.5, -0.5, -0.5),
                                  text_scale=0.05,
                                  text_pos=(0, -0.11),
                                  command=self.applyDisplaySettings)
        self.cancelBtn = DirectButton(text='Cancel',
                                      geom=CIGlobals.getCancelBtnGeom(),
                                      relief=None,
                                      pos=(-0.3, -0.5, -0.5),
                                      text_scale=0.05,
                                      text_pos=(0, -0.11),
                                      command=self.cancelDisplaySettings)
        if self.resoLbl['text'] == '640x480':
            self.resSlider['value'] = 0
        else:
            if self.resoLbl['text'] == '800x600':
                self.resSlider['value'] = 50
            else:
                if self.resoLbl['text'] == '1024x768':
                    self.resSlider['value'] = 100
                else:
                    if self.resoLbl['text'] == '1280x1024':
                        self.resSlider['value'] = 150
                    else:
                        if self.resoLbl['text'] == '1600x1200':
                            self.resSlider['value'] = 200
        return

    def exitDisplayPage(self):
        for button in self.buttons:
            button.destroy()
            del button

        self.resoLbl.destroy()
        del self.resoLbl
        self.resSlider.destroy()
        del self.resSlider
        self.okBtn.destroy()
        del self.okBtn
        self.cancelBtn.destroy()
        del self.cancelBtn
        del self.width
        del self.height
        del self.windowType
        del self.buttons
        self.book.clearTitle()

    def changeSetting(self, setting, value):
        if setting == 'music':
            if value:
                value = False
            else:
                if not value:
                    value = True
            base.enableMusic(value)
            self.music_btn['extraArgs'] = ['music', value]
            if value:
                valueTxt = 'On'
            else:
                valueTxt = 'Off'
            self.music_lbl['text'] = str(valueTxt).capitalize()
        else:
            if setting == 'sfx':
                if value:
                    value = False
                else:
                    if not value:
                        value = True
                base.enableSoundEffects(value)
                self.sfx_btn['extraArgs'] = ['sfx', value]
                if value:
                    valueTxt = 'On'
                else:
                    valueTxt = 'Off'
                self.sfx_lbl['text'] = str(valueTxt).capitalize()
            else:
                if setting == 'model-detail':
                    if value == 'high':
                        value = 'low'
                    else:
                        if value == 'medium':
                            value = 'high'
                        else:
                            if value == 'low':
                                value = 'medium'
                    self.moddet_lbl['text'] = value.capitalize()
                    self.moddet_btn['extraArgs'] = ['model-detail', value]
                else:
                    if setting == 'texture-detail':
                        if value == 'normal':
                            value = 'low'
                            loadPrcFileData('', 'compressed-textures 1')
                        else:
                            if value == 'low':
                                value = 'normal'
                                loadPrcFileData('', 'compressed-textures 0')
                        self.texdet_lbl['text'] = value.capitalize()
                        self.texdet_btn['extraArgs'] = [
                            'texture-detail', value
                        ]
                    else:
                        if setting == 'aa':
                            if value == 'on':
                                value = 'off'
                                render.clear_antialias()
                            else:
                                if value == 'off':
                                    value = 'on'
                                    render.set_antialias(AntialiasAttrib.MAuto)
                            self.aa_lbl['text'] = value.capitalize()
                            self.aa_btn['extraArgs'] = ['aa', value]
                        else:
                            if setting == 'af':
                                if value == 'on':
                                    value = 'off'
                                else:
                                    if value == 'off':
                                        value = 'on'
                                self.af_lbl['text'] = value.capitalize()
                                self.af_btn['extraArgs'] = ['af', value]
        SettingsManager().writeSettingToFile(setting, value, 'settings.json')

    def setResoText(self):
        if self.resSlider['value'] == 200:
            self.width = 1600
            self.height = 1200
        else:
            if 150 <= self.resSlider['value'] <= 199:
                self.width = 1280
                self.height = 1024
            else:
                if 100 <= self.resSlider['value'] <= 149:
                    self.width = 1024
                    self.height = 768
                else:
                    if 50 <= self.resSlider['value'] <= 99:
                        self.width = 800
                        self.height = 600
                    else:
                        if self.resSlider['value'] == 0:
                            self.width = 640
                            self.height = 480
        self.resoLbl['text'] = str(self.width) + 'x' + str(self.height)

    def applyDisplaySettings(self):
        SettingsManager().writeSettingToFile('resolution',
                                             (self.width, self.height),
                                             'settings.json',
                                             apply=1)
        SettingsManager().writeSettingToFile('fullscreen',
                                             self.windowType,
                                             'settings.json',
                                             apply=1)
        self.fsm.request('basePage')

    def cancelDisplaySettings(self):
        self.fsm.request('basePage')

    def enterBasePage(self):
        self.book.createPageButtons(None, 'districtPage')
        self.book.setTitle('Options')
        width, height, fs, music, sfx, tex_detail, model_detail, aa, af = SettingsManager(
        ).getSettings('settings.json')
        if music:
            musicTxt = 'On'
        else:
            musicTxt = 'Off'
        if sfx:
            sfxTxt = 'On'
        else:
            sfxTxt = 'Off'
        if fs:
            fsTxt = 'On'
        else:
            fsTxt = 'Off'
        self.music_btn = DirectButton(geom=(qt_btn.find('**/QuitBtn_UP'),
                                            qt_btn.find('**/QuitBtn_DN'),
                                            qt_btn.find('**/QuitBtn_RLVR')),
                                      relief=None,
                                      text='Music',
                                      scale=1,
                                      text_scale=0.055,
                                      command=self.changeSetting,
                                      extraArgs=['music', music],
                                      pos=(-0.45, 0.55, 0.55),
                                      text_pos=(0, -0.01))
        self.music_lbl = DirectLabel(relief=None,
                                     scale=0.09,
                                     pos=(0.45, 0.55, 0.52),
                                     text_align=TextNode.ACenter)
        self.music_lbl['text'] = str(musicTxt).capitalize()
        self.sfx_btn = DirectButton(geom=(qt_btn.find('**/QuitBtn_UP'),
                                          qt_btn.find('**/QuitBtn_DN'),
                                          qt_btn.find('**/QuitBtn_RLVR')),
                                    relief=None,
                                    text='SFX',
                                    scale=1,
                                    text_scale=0.055,
                                    command=self.changeSetting,
                                    extraArgs=['sfx', sfx],
                                    pos=(-0.45, 0.45, 0.45),
                                    text_pos=(0, -0.01))
        self.sfx_lbl = DirectLabel(relief=None,
                                   scale=0.09,
                                   pos=(0.45, 0.45, 0.42),
                                   text_align=TextNode.ACenter)
        self.sfx_lbl['text'] = str(sfxTxt).capitalize()
        self.moddet_btn = DirectButton(
            geom=(qt_btn.find('**/QuitBtn_UP'), qt_btn.find('**/QuitBtn_DN'),
                  qt_btn.find('**/QuitBtn_RLVR')),
            relief=None,
            text='Model Detail',
            scale=1,
            text_scale=0.055,
            command=self.changeSetting,
            extraArgs=['model-detail', model_detail],
            pos=(-0.45, 0.35, 0.35),
            text_pos=(0, -0.01))
        self.moddet_lbl = DirectLabel(relief=None,
                                      scale=0.09,
                                      pos=(0.45, 0.35, 0.32),
                                      text_align=TextNode.ACenter)
        self.moddet_lbl['text'] = model_detail.capitalize()
        self.moddet_btn.bind(DGG.ENTER, self.createMustRestartGui)
        self.moddet_btn.bind(DGG.EXIT, self.removeMustRestartGui)
        self.texdet_btn = DirectButton(
            geom=(qt_btn.find('**/QuitBtn_UP'), qt_btn.find('**/QuitBtn_DN'),
                  qt_btn.find('**/QuitBtn_RLVR')),
            relief=None,
            text='Texture Detail',
            scale=1,
            text_scale=0.0535,
            command=self.changeSetting,
            extraArgs=['texture-detail', tex_detail],
            pos=(-0.45, 0.25, 0.25),
            text_pos=(0, -0.01))
        self.texdet_lbl = DirectLabel(relief=None,
                                      scale=0.09,
                                      pos=(0.45, 0.25, 0.22),
                                      text_align=TextNode.ACenter)
        self.texdet_lbl['text'] = tex_detail.capitalize()
        self.texdet_btn.bind(DGG.ENTER, self.createMustRestartGui)
        self.texdet_btn.bind(DGG.EXIT, self.removeMustRestartGui)
        self.display_btn = DirectButton(geom=(qt_btn.find('**/QuitBtn_UP'),
                                              qt_btn.find('**/QuitBtn_DN'),
                                              qt_btn.find('**/QuitBtn_RLVR')),
                                        relief=None,
                                        text='Display',
                                        command=self.openDisplayPage,
                                        scale=1,
                                        text_scale=0.0535,
                                        pos=(-0.45, -0.25, 0.02),
                                        text_pos=(0, -0.01))
        self.display_lbl = DirectLabel(relief=None,
                                       scale=0.06,
                                       pos=(0.45, -0.25, 0.02),
                                       text_align=TextNode.ACenter)
        self.display_lbl['text'] = 'Fullscreen: %s\nResolution: %s' % (
            str(fsTxt).capitalize(), (width, height))
        self.aa_btn = DirectButton(geom=(qt_btn.find('**/QuitBtn_UP'),
                                         qt_btn.find('**/QuitBtn_DN'),
                                         qt_btn.find('**/QuitBtn_RLVR')),
                                   relief=None,
                                   text='Anti-Aliasing',
                                   command=self.changeSetting,
                                   extraArgs=['aa', aa],
                                   scale=1,
                                   text_scale=0.0535,
                                   pos=(-0.45, -0.35, -0.18),
                                   text_pos=(0, -0.01))
        self.aa_lbl = DirectLabel(relief=None,
                                  scale=0.09,
                                  pos=(0.45, -0.35, -0.21),
                                  text_align=TextNode.ACenter)
        self.aa_lbl['text'] = aa.capitalize()
        self.af_btn = DirectButton(geom=(qt_btn.find('**/QuitBtn_UP'),
                                         qt_btn.find('**/QuitBtn_DN'),
                                         qt_btn.find('**/QuitBtn_RLVR')),
                                   relief=None,
                                   text='Anisotropic Filtering',
                                   command=self.changeSetting,
                                   extraArgs=['af', af],
                                   scale=1,
                                   text_scale=0.0435,
                                   pos=(-0.45, -0.35, -0.28),
                                   text_pos=(0, -0.01))
        self.af_lbl = DirectLabel(relief=None,
                                  scale=0.09,
                                  pos=(0.45, -0.35, -0.31),
                                  text_align=TextNode.ACenter)
        self.af_lbl['text'] = af.capitalize()
        self.af_btn.bind(DGG.ENTER, self.createMustRestartGui)
        self.af_btn.bind(DGG.EXIT, self.removeMustRestartGui)
        self.exit_btn = DirectButton(geom=(qt_btn.find('**/QuitBtn_UP'),
                                           qt_btn.find('**/QuitBtn_DN'),
                                           qt_btn.find('**/QuitBtn_RLVR')),
                                     relief=None,
                                     text='Exit Toontown',
                                     scale=1.2,
                                     text_scale=0.0535,
                                     command=self.book.finished,
                                     extraArgs=['exit'],
                                     pos=(-0.45, -0.65, -0.6),
                                     text_pos=(0, -0.01))
        return

    def createMustRestartGui(self, foo):
        self.mustRestartLbl = DirectLabel(
            text='Changing this setting requires a game restart.',
            text_fg=(0.9, 0, 0, 1),
            text_shadow=(0, 0, 0, 1),
            text_scale=0.06,
            text_align=TextNode.ACenter,
            pos=(0, 0, -0.435),
            relief=None)
        return

    def removeMustRestartGui(self, foo):
        if hasattr(self, 'mustRestartLbl'):
            self.mustRestartLbl.destroy()
            del self.mustRestartLbl

    def exitBasePage(self):
        self.music_btn.destroy()
        del self.music_btn
        self.sfx_btn.destroy()
        del self.sfx_btn
        self.moddet_btn.destroy()
        del self.moddet_btn
        self.texdet_btn.destroy()
        del self.texdet_btn
        self.display_btn.destroy()
        del self.display_btn
        self.aa_btn.destroy()
        del self.aa_btn
        self.exit_btn.destroy()
        del self.exit_btn
        self.music_lbl.destroy()
        del self.music_lbl
        self.sfx_lbl.destroy()
        del self.sfx_lbl
        self.moddet_lbl.destroy()
        del self.moddet_lbl
        self.texdet_lbl.destroy()
        del self.texdet_lbl
        self.display_lbl.destroy()
        del self.display_lbl
        self.aa_lbl.destroy()
        del self.aa_lbl
        self.af_btn.destroy()
        del self.af_btn
        self.af_lbl.destroy()
        del self.af_lbl
        self.book.deletePageButtons(False, True)
        self.book.clearTitle()
Ejemplo n.º 17
0
  def render(self):
    ''' traverse the tree and update the visuals according to it
    '''
    for treeItem in self.treeStructure.getRec():
      # create nodes that have no visual elements
      if not treeItem in self.treeStructureNodes:
        treeNode = self.childrenCanvas.attachNewNode('')
        
        hor=self.horizontalTreeLine.instanceUnderNode(treeNode,'')
        vert=self.verticalTreeLine.instanceUnderNode(treeNode,'')
        vert.setZ(0.007)
        hor.setPos(-1.5*self.itemIndent,0,self.itemScale*.25)
        vert.setX(-.5*self.itemIndent)
        
        nodeButton = DirectButton(
            parent=treeNode,
            scale=self.itemScale,
            relief=DGG.FLAT,
            text_scale=self.itemTextScale,
            text_align=TextNode.ALeft,
            text=treeItem.name,
            rolloverSound=None,
            #clickSound=None,
          )
        nodeButton.bind(DGG.B1PRESS,treeItem.button1press)
        nodeButton.bind(DGG.B2PRESS,treeItem.button2press)
        nodeButton.bind(DGG.B3PRESS,treeItem.button3press)
        
        #treeButton = None
        #if len(treeItem.childrens) > 0:
        treeButton = DirectButton(
            parent=nodeButton,
            frameColor=(1,1,1,1),
            frameSize=(-.4,.4,-.4,.4),
            pos=(-.5*self.itemIndent/self.itemScale,0,.25),
            text='',
            text_pos=(-.1,-.22),
            text_scale=(1.6,1),
            text_fg=(0,0,0,1),
            enableEdit=0,
            command=treeItem.setOpen,
            sortOrder=1000,
            rolloverSound=None,
            #clickSound=None,
          )
        

        self.treeStructureNodes[treeItem] = [treeNode, nodeButton, treeButton, hor, vert]
    
    # destroy nodes no more used
    for treeItem in self.treeStructureNodes.keys()[:]:
      #treeItem = self.treeStructureNodes[treeName]
      if treeItem not in self.treeStructure.getRec():
        treeNode, nodeButton, treeButton, hor, vert = self.treeStructureNodes[treeItem]
        #nodeButton['text']=''
        nodeButton.unbind(DGG.B1PRESS)
        nodeButton.unbind(DGG.B2PRESS)
        nodeButton.unbind(DGG.B3PRESS)
        #nodeButton.detachNode()
        #nodeButton.removeNode()
        nodeButton.destroy()
        if treeButton:
          #treeButton['text']=''
          #treeButton['command']=None
          treeButton.detachNode()
          treeButton.removeNode()
        hor.detachNode()
        hor.removeNode()
        vert.detachNode()
        vert.removeNode()
        treeItem.destroy()
        #treeNode.detachNode()
        treeNode.removeNode()
        #treeNode.destroy()
        del self.treeStructureNodes[treeItem]
    
    frameHeight = len(self.treeStructureNodes) * self.verticalSpacing
    self.childrenFrame['canvasSize'] = (0, self.frameWidth-self.itemScale*2, 0, frameHeight)
    self.childrenCanvas.setZ(frameHeight-1)
class ModPanelButton:
    def __init__(self, menu, name, command, register):
        self.menu = menu
        self.name = name

        self.command = command
        if type(command) == types.StringType:
            command = self.call_word

        self.button = DirectButton(
            frameSize=None,
            text=name,
            image=(ModPanelGlobals.Button.find('**/QuitBtn_UP'),
                   ModPanelGlobals.Button.find('**/QuitBtn_DN'),
                   ModPanelGlobals.Button.find('**/QuitBtn_RLVR')),
            relief=None,
            command=command,
            text_pos=(0, -0.015),
            geom=None,
            pad=(0.01, 0.01),
            suppressKeys=0,
            pos=(0, 0, 0),
            text_scale=0.059,
            borderWidth=(0.015, 0.01),
            scale=.7)

        self.button.reparent_to(menu)

        if register:
            self.button.bind(DirectGuiGlobals.B2PRESS, self.delete_button)
            self.button.bind(DirectGuiGlobals.B3PRESS, self.button.editStart)
            self.button.bind(DirectGuiGlobals.B3RELEASE, self.edit_stop)
            self.menu.buttons.append(self)
            messenger.send('save-file')

    def call_word(self):
        messenger.send('magicWord', [self.command])

    def hide(self):
        self.button.hide()

    def show(self):
        self.button.show()

    def place(self):
        self.button.place()

    def set_pos(self, x, y, z):
        self.button.set_pos(x, y, z)

    def destroy(self):
        self.button.destroy()

    def edit_stop(self, dispatch):
        self.button.editStop(dispatch)

        messenger.send('save-file')

    def delete_button(self, dispatch):
        self.button.destroy()
        if self in self.menu.buttons:
            self.menu.buttons.remove(self)

        messenger.send('save-file')

    def get_data(self):
        return self.name, self.command, self.button.get_pos()
Ejemplo n.º 19
0
class DirectWindow( DirectFrame ):
  def __init__( self,
                pos              = ( -.5, .5),
                title            = 'Title',
                curSize          = ( 1, 1),
                maxSize          = ( 1, 1 ),
                minSize          = ( .5, .5 ),
                backgroundColor  = ( 1, 1, 1, 1 ),
                borderColor      = ( 1, 1, 1, 1 ),
                titleColor       = ( 1, 1, 1, 1 ),
                borderSize       = 0.04,
                titleSize        = 0.06,
                closeButton      = False,
                windowParent     = aspect2d,
                preserve         = True,
                preserveWhole      = True,
              ):
    self.preserve = preserve
    self.preserveWhole = preserveWhole
    self.windowParent = windowParent
    self.windowPos = pos
    DirectFrame.__init__( self,
        parent       = windowParent,
        pos          = ( self.windowPos[0], 0, self.windowPos[1] ),
        frameColor  = ( 0, 0, 0, 0 ),
        frameTexture = loader.loadTexture( DIRECTORY+'transparent.png' )
      )
    self.setTransparency(True)
   
    # the title part of the window, drag around to move the window
    self.headerHeight = titleSize
    h = -self.headerHeight
    self.windowHeaderLeft = DirectButton(
        parent       = self,
        frameTexture = DEFAULT_TITLE_GEOM_LEFT,
        frameSize    = ( -.5, .5, -.5, .5 ),
        borderWidth  = ( 0, 0 ),
        relief       = DGG.FLAT,
        frameColor   = titleColor,
      )
    self.windowHeaderCenter = DirectButton(
        parent       = self,
        frameTexture = DEFAULT_TITLE_GEOM_CENTER,
        frameSize    = ( -.5, .5, -.5, .5 ),
        borderWidth  = ( 0, 0 ),
        relief       = DGG.FLAT,
        frameColor   = titleColor,
      )
    if closeButton:
      rightTitleGeom = DEFAULT_TITLE_GEOM_RIGHT_CLOSE
      command = self.destroy
    else:
      rightTitleGeom = DEFAULT_TITLE_GEOM_RIGHT
      command = None
    self.windowHeaderRight = DirectButton(
        parent       = self,
        frameTexture = rightTitleGeom,
        frameSize    = ( -.5, .5, -.5, .5 ),
        borderWidth  = ( 0, 0 ),
        relief       = DGG.FLAT,
        frameColor   = titleColor,
        command      = command
      )
   
    self.windowHeaderLeft.setTransparency(True)
    self.windowHeaderCenter.setTransparency(True)
    self.windowHeaderRight.setTransparency(True)
   
    self.windowHeaderLeft.bind( DGG.B1PRESS, self.startWindowDrag )
    self.windowHeaderCenter.bind( DGG.B1PRESS, self.startWindowDrag )
    self.windowHeaderRight.bind( DGG.B1PRESS, self.startWindowDrag )
   
    # this is not handled correctly, if a window is dragged which has been
    # created before another it will not be released
    # check the bugfixed startWindowDrag function
    #self.windowHeader.bind(DGG.B1RELEASE,self.stopWindowDrag)
   
    text = TextNode('WindowTitleTextNode')
    text.setText(title)
    text.setAlign(TextNode.ACenter)
    text.setTextColor( 0, 0, 0, 1 )
    text.setShadow(0.05, 0.05)
    text.setShadowColor( 1, 1, 1, 1 )
    self.textNodePath = self.attachNewNode(text)
    self.textNodePath.setScale(self.headerHeight*0.8)
   
    # the content part of the window, put stuff beneath
    # contentWindow.getCanvas() to put it into it
    self.maxVirtualSize = maxSize
    self.minVirtualSize = minSize
    self.resizeSize     = borderSize
    self.contentWindow = DirectScrolledFrame(
        parent                                  = self,
        pos                                     = ( 0, 0, -self.headerHeight ),
        canvasSize                              = ( 0, self.maxVirtualSize[0], 0, self.maxVirtualSize[1] ),
        frameColor                              = ( 0, 0, 0, 0), # defines the background color of the resize-button
        relief                                  = DGG.FLAT,
        borderWidth                             = (0, 0),
        verticalScroll_frameSize                = [0, self.resizeSize, 0, 1],
        horizontalScroll_frameSize              = [0, 1, 0, self.resizeSize],
       
        # resize the scrollbar according to window size
        verticalScroll_resizeThumb              = False,
        horizontalScroll_resizeThumb            = False,
        # define the textures for the scrollbars
        verticalScroll_frameTexture             = VERTICALSCROLL_FRAMETEXTURE,
        verticalScroll_incButton_frameTexture   = VERTICALSCROLL_INCBUTTON_FRAMETEXTURE,
        verticalScroll_decButton_frameTexture   = VERTICALSCROLL_DECBUTTON_FRAMETEXTURE,
        verticalScroll_thumb_frameTexture       = VERTICALSCROLL_TUMB_FRAMETEXTURE,
        horizontalScroll_frameTexture           = HORIZONTALSCROLL_FRAMETEXTURE,
        horizontalScroll_incButton_frameTexture = HORIZONTALSCROLL_INCBUTTON_FRAMETEXTURE,
        horizontalScroll_decButton_frameTexture = HORIZONTALSCROLL_DECBUTTON_FRAMETEXTURE,
        horizontalScroll_thumb_frameTexture     = HORIZONTALSCROLL_TUMB_FRAMETEXTURE,
        # make all flat, so the texture is as we want it
        verticalScroll_relief                   = DGG.FLAT,
        verticalScroll_thumb_relief             = DGG.FLAT,
        verticalScroll_decButton_relief         = DGG.FLAT,
        verticalScroll_incButton_relief         = DGG.FLAT,
        horizontalScroll_relief                 = DGG.FLAT,
        horizontalScroll_thumb_relief           = DGG.FLAT,
        horizontalScroll_decButton_relief       = DGG.FLAT,
        horizontalScroll_incButton_relief       = DGG.FLAT,
        # colors
        verticalScroll_frameColor               = borderColor,
        verticalScroll_incButton_frameColor     = borderColor,
        verticalScroll_decButton_frameColor     = borderColor,
        verticalScroll_thumb_frameColor         = borderColor,
        horizontalScroll_frameColor             = borderColor,
        horizontalScroll_incButton_frameColor   = borderColor,
        horizontalScroll_decButton_frameColor   = borderColor,
        horizontalScroll_thumb_frameColor       = borderColor,
      )
    self.contentWindow.setTransparency(True)


    # background color
    self.backgroundColor = DirectFrame(
        parent       = self.contentWindow.getCanvas(),
        frameSize    = ( 0, self.maxVirtualSize[0], 0, self.maxVirtualSize[1] ),
        frameColor   = backgroundColor,
        relief       = DGG.FLAT,
        borderWidth  = ( .01, .01),
      )
    self.backgroundColor.setTransparency(True)

    # Add a box
    self.box = boxes.VBox(parent = self.getCanvas())

   
    # is needed for some nicer visuals of the resize button (background)
    self.windowResizeBackground = DirectButton(
        parent       = self,
        frameSize    = ( -.5, .5, -.5, .5 ),
        borderWidth  = ( 0, 0 ),
        scale        = ( self.resizeSize, 1, self.resizeSize ),
        relief       = DGG.FLAT,
        frameColor   = backgroundColor,
      )

    # the resize button of the window
    self.windowResize = DirectButton(
        parent       = self,
        frameSize    = ( -.5, .5, -.5, .5 ),
        borderWidth  = ( 0, 0 ),
        scale        = ( self.resizeSize, 1, self.resizeSize ),
        relief       = DGG.FLAT,
        frameTexture = DEFAULT_RESIZE_GEOM,
        frameColor   = borderColor,
      )
    self.windowResize.setTransparency(True)
    self.windowResize.bind(DGG.B1PRESS,self.startResizeDrag)
    self.windowResize.bind(DGG.B1RELEASE,self.stopResizeDrag)
   
    # offset then clicking on the resize button from the mouse to the resizebutton
    # position, required to calculate the position / scaling
    self.offset = None
    self.taskName = "resizeTask-%s" % str(hash(self))
   
    # do sizing of the window (minimum)
    #self.resize( Vec3(0,0,0), Vec3(0,0,0) )
    # maximum
    #self.resize( Vec3(100,0,-100), Vec3(0,0,0) )
    self.resize( Vec3(curSize[0], 0, -curSize[1]), Vec3(0,0,0))
 
  def getCanvas(self):
    return self.contentWindow.getCanvas()
 
  # dragging functions
  def startWindowDrag( self, param ):
    self.wrtReparentTo( aspect2dMouseNode )
    self.ignoreAll()
    self.accept( 'mouse1-up', self.stopWindowDrag )
  def stopWindowDrag( self, param=None ):
    # this is called 2 times (bug), so make sure it's not already parented to aspect2d
    if self.getParent() != self.windowParent:
      self.wrtReparentTo( self.windowParent )
    if self.preserve:
        if self.preserveWhole:
            if self.getZ() > 1:
                self.setZ(1)
            elif self.getZ() < -1 - self.getHeight():
                self.setZ(-1 - self.getHeight())
            if self.getX() > base.a2dRight - self.getWidth():
                self.setX(base.a2dRight - self.getWidth())
            elif self.getX() < base.a2dLeft:
                self.setX(base.a2dLeft)
        else:
            if self.getZ() > 1:
                self.setZ(1)
            elif self.getZ() < -1 + self.headerHeight:
                self.setZ(-1 + self.headerHeight)
            if self.getX() > base.a2dRight - self.headerHeight:
                self.setX(base.a2dRight - self.headerHeight)
            elif self.getX() < base.a2dLeft + self.headerHeight - self.getWidth():
                self.setX(base.a2dLeft + self.headerHeight - self.getWidth())
    #else: #Window moved beyond reach. Destroy window?
  # resize functions
  def resize( self, mPos, offset ):
    mXPos = max( min( mPos.getX(), self.maxVirtualSize[0] ), self.minVirtualSize[0])
    mZPos = max( min( mPos.getZ(), -self.minVirtualSize[1] ), -self.maxVirtualSize[1]-self.headerHeight)
    self.windowResize.setPos( mXPos-self.resizeSize/2., 0, mZPos+self.resizeSize/2. )
    self.windowResizeBackground.setPos( mXPos-self.resizeSize/2., 0, mZPos+self.resizeSize/2. )
    self['frameSize'] = (0, mXPos, 0, mZPos)
    self.windowHeaderLeft.setPos( self.headerHeight/2., 0, -self.headerHeight/2. )
    self.windowHeaderLeft.setScale( self.headerHeight, 1, self.headerHeight )
    self.windowHeaderCenter.setPos( mXPos/2., 0, -self.headerHeight/2. )
    self.windowHeaderCenter.setScale( mXPos - self.headerHeight*2., 1, self.headerHeight )
    self.windowHeaderRight.setPos( mXPos-self.headerHeight/2., 0, -self.headerHeight/2. )
    self.windowHeaderRight.setScale( self.headerHeight, 1, self.headerHeight )
    self.contentWindow['frameSize'] = ( 0, mXPos, mZPos+self.headerHeight, 0)
    self.textNodePath.setPos( mXPos/2., 0, -self.headerHeight/3.*2. )
    # show and hide that small background for the window sizer
    if mXPos == self.maxVirtualSize[0] and \
       mZPos == -self.maxVirtualSize[1]-self.headerHeight:
      self.windowResizeBackground.hide()
    else:
      self.windowResizeBackground.show()
 
  def resizeTask( self, task=None ):
    mPos = aspect2dMouseNode.getPos( self )+self.offset
    self.resize( mPos, self.offset )
    return task.cont
  def startResizeDrag( self, param ):
    self.offset  = self.windowResize.getPos( aspect2dMouseNode )
    taskMgr.remove( self.taskName )
    taskMgr.add( self.resizeTask, self.taskName )
  def stopResizeDrag( self, param ):
    taskMgr.remove( self.taskName )
    # get the window to the front
    self.wrtReparentTo( self.windowParent )
  def addHorizontal(self, widgets):
      """
      Accepts a list of directgui objects which are added to a horizontal box, which is then added to the vertical stack.
      """
      hbox = boxes.HBox()
      for widget in widgets:
          hbox.pack(widget)
      self.box.pack(hbox)
      self.updateMaxSize()
 
  def addVertical(self, widgets):
      """
      Accepts a list of directgui objects which are added to a vertical box, which is then added to the vertical stack.
      May cause funky layout results.
      """
      #vbox = boxes.VBox()
      for widget in widgets:
          self.box.pack(widget)
      self.updateMaxSize()
 
  def add(self, widgets):
      """Shortcut function for addVertical"""
      self.addVertical(widgets)
 
  def updateMaxSize(self):
      """Updates the max canvas size to include all items packed.
      Window is resized to show all contents."""
      bottomLeft, topRight = self.box.getTightBounds()
      self.maxVirtualSize = (topRight[0], -bottomLeft[2])
      self.contentWindow['canvasSize'] = ( 0, self.maxVirtualSize[0], -self.maxVirtualSize[1],  0)
      self.backgroundColor['frameSize'] = ( 0, self.maxVirtualSize[0], -self.maxVirtualSize[1], 0 )

      #perhaps this should be optional -- automatically resize for new elements
      self.reset()
 
  def reset(self):
    """Poorly named function that resizes window to fit all contents"""
    self.resize( Vec3(self.maxVirtualSize[0], 0, -self.maxVirtualSize[1]-self.headerHeight), Vec3(0,0,0))
Ejemplo n.º 20
0
class OptionPage(StateData):
    def __init__(self, book, parentFSM):
        self.book = book
        self.parentFSM = parentFSM
        StateData.__init__(self, 'optionPageDone')
        self.fsm = ClassicFSM('OptionPage', [
            State('off', self.enterOff, self.exitOff),
            State('basePage', self.enterBasePage, self.exitBasePage),
            State('displayPage', self.enterDisplayPage, self.exitDisplayPage)
        ], 'off', 'off')
        self.fsm.enterInitialState()
        self.parentFSM.getStateNamed('optionPage').addChild(self.fsm)

    def enterOff(self):
        pass

    def exitOff(self):
        pass

    def load(self):
        StateData.load(self)

    def unload(self):
        StateData.unload(self)

    def enter(self):
        StateData.enter(self)
        self.fsm.request('basePage')

    def exit(self):
        self.fsm.request('off')
        StateData.exit(self)

    def openDisplayPage(self):
        self.fsm.request('displayPage')

    def enterDisplayPage(self):
        self.book.createPageButtons(False, False)
        self.book.setTitle("Display Options")
        dialog_gui = loader.loadModel(
            "phase_3/models/gui/dialog_box_buttons_gui.bam")
        width, height, fs, music, sfx, tex_detail, model_detail, aa, af = SettingsManager(
        ).getSettings("settings.json")
        self.width = width
        self.height = height
        self.windowType = [fs]
        self.buttons = [
            DirectRadioButton(text="Windowed",
                              variable=self.windowType,
                              value=[False],
                              scale=0.1,
                              pos=(-0.45, 0.15, 0.15)),
            DirectRadioButton(text="Fullscreen",
                              variable=self.windowType,
                              value=[True],
                              scale=0.1,
                              pos=(-0.45, -0.15, -0.15))
        ]

        for button in self.buttons:
            button.setOthers(self.buttons)

        self.resoLbl = DirectLabel(text="%sx%s" % (width, height),
                                   scale=0.08,
                                   relief=None,
                                   pos=(0.25, 0, 0))
        self.resSlider = DirectSlider(range=(0, 200),
                                      pageSize=50,
                                      command=self.setResoText,
                                      scale=0.3,
                                      orientation=DGG.VERTICAL,
                                      pos=(0.6, 0, 0))
        self.okBtn = DirectButton(text="OK",
                                  geom=CIGlobals.getOkayBtnGeom(),
                                  relief=None,
                                  pos=(-0.5, -0.5, -0.5),
                                  text_scale=0.05,
                                  text_pos=(0, -0.11),
                                  command=self.applyDisplaySettings)
        self.cancelBtn = DirectButton(text="Cancel",
                                      geom=CIGlobals.getCancelBtnGeom(),
                                      relief=None,
                                      pos=(-0.3, -0.5, -0.5),
                                      text_scale=0.05,
                                      text_pos=(0, -0.11),
                                      command=self.cancelDisplaySettings)
        if self.resoLbl['text'] == "640x480":
            self.resSlider['value'] = 0
        elif self.resoLbl['text'] == "800x600":
            self.resSlider['value'] = 50
        elif self.resoLbl['text'] == "1024x768":
            self.resSlider['value'] = 100
        elif self.resoLbl['text'] == "1280x1024":
            self.resSlider['value'] = 150
        elif self.resoLbl['text'] == "1600x1200":
            self.resSlider['value'] = 200

    def exitDisplayPage(self):
        for button in self.buttons:
            button.destroy()
            del button
        self.resoLbl.destroy()
        del self.resoLbl
        self.resSlider.destroy()
        del self.resSlider
        self.okBtn.destroy()
        del self.okBtn
        self.cancelBtn.destroy()
        del self.cancelBtn
        del self.width
        del self.height
        del self.windowType
        del self.buttons
        self.book.clearTitle()

    def changeSetting(self, setting, value):
        if setting == "music":
            if value:
                value = False
            elif not value:
                value = True
            base.enableMusic(value)
            self.music_btn['extraArgs'] = ["music", value]
            if value:
                valueTxt = "On"
            else:
                valueTxt = "Off"
            self.music_lbl['text'] = str(valueTxt).capitalize()
        elif setting == "sfx":
            if value:
                value = False
            elif not value:
                value = True
            base.enableSoundEffects(value)
            self.sfx_btn['extraArgs'] = ["sfx", value]
            if value:
                valueTxt = "On"
            else:
                valueTxt = "Off"
            self.sfx_lbl['text'] = str(valueTxt).capitalize()
        elif setting == "model-detail":
            if value == "high":
                value = "low"
            elif value == "medium":
                value = "high"
            elif value == "low":
                value = "medium"
            self.moddet_lbl['text'] = value.capitalize()
            self.moddet_btn['extraArgs'] = ["model-detail", value]
        elif setting == "texture-detail":
            if value == "normal":
                value = "low"
                loadPrcFileData("", "compressed-textures 1")
            elif value == "low":
                value = "normal"
                loadPrcFileData("", "compressed-textures 0")
            self.texdet_lbl['text'] = value.capitalize()
            self.texdet_btn['extraArgs'] = ["texture-detail", value]
        elif setting == "aa":
            if value == "on":
                value = "off"
                render.clear_antialias()
            elif value == "off":
                value = "on"
                render.set_antialias(AntialiasAttrib.MAuto)
            self.aa_lbl['text'] = value.capitalize()
            self.aa_btn['extraArgs'] = ["aa", value]
        elif setting == "af":
            if value == "on":
                value = "off"
            elif value == "off":
                value = "on"
            self.af_lbl['text'] = value.capitalize()
            self.af_btn['extraArgs'] = ["af", value]

        SettingsManager().writeSettingToFile(setting, value, "settings.json")

    def setResoText(self):
        if self.resSlider['value'] == 200:
            self.width = 1600
            self.height = 1200
        elif 150 <= self.resSlider['value'] <= 199:
            self.width = 1280
            self.height = 1024
        elif 100 <= self.resSlider['value'] <= 149:
            self.width = 1024
            self.height = 768
        elif 50 <= self.resSlider['value'] <= 99:
            self.width = 800
            self.height = 600
        elif self.resSlider['value'] == 0:
            self.width = 640
            self.height = 480
        self.resoLbl['text'] = str(self.width) + "x" + str(self.height)

    def applyDisplaySettings(self):
        SettingsManager().writeSettingToFile("resolution",
                                             (self.width, self.height),
                                             "settings.json",
                                             apply=1)
        SettingsManager().writeSettingToFile("fullscreen",
                                             self.windowType,
                                             "settings.json",
                                             apply=1)
        self.fsm.request('basePage')

    def cancelDisplaySettings(self):
        self.fsm.request('basePage')

    def enterBasePage(self):
        self.book.createPageButtons(None, 'districtPage')
        self.book.setTitle("Options")
        width, height, fs, music, sfx, tex_detail, model_detail, aa, af = SettingsManager(
        ).getSettings("settings.json")
        if music:
            musicTxt = "On"
        else:
            musicTxt = "Off"
        if sfx:
            sfxTxt = "On"
        else:
            sfxTxt = "Off"
        if fs:
            fsTxt = "On"
        else:
            fsTxt = "Off"
        self.music_btn = DirectButton(geom=(qt_btn.find('**/QuitBtn_UP'),
                                            qt_btn.find('**/QuitBtn_DN'),
                                            qt_btn.find('**/QuitBtn_RLVR')),
                                      relief=None,
                                      text="Music",
                                      scale=1,
                                      text_scale=0.055,
                                      command=self.changeSetting,
                                      extraArgs=["music", music],
                                      pos=(-0.45, 0.55, 0.55),
                                      text_pos=(0, -0.01))
        self.music_lbl = DirectLabel(relief=None,
                                     scale=0.09,
                                     pos=(0.45, 0.55, 0.52),
                                     text_align=TextNode.ACenter)
        self.music_lbl['text'] = str(musicTxt).capitalize()

        self.sfx_btn = DirectButton(geom=(qt_btn.find('**/QuitBtn_UP'),
                                          qt_btn.find('**/QuitBtn_DN'),
                                          qt_btn.find('**/QuitBtn_RLVR')),
                                    relief=None,
                                    text="SFX",
                                    scale=1,
                                    text_scale=0.055,
                                    command=self.changeSetting,
                                    extraArgs=["sfx", sfx],
                                    pos=(-0.45, 0.45, 0.45),
                                    text_pos=(0, -0.01))
        self.sfx_lbl = DirectLabel(relief=None,
                                   scale=0.09,
                                   pos=(0.45, 0.45, 0.42),
                                   text_align=TextNode.ACenter)
        self.sfx_lbl['text'] = str(sfxTxt).capitalize()

        self.moddet_btn = DirectButton(
            geom=(qt_btn.find('**/QuitBtn_UP'), qt_btn.find('**/QuitBtn_DN'),
                  qt_btn.find('**/QuitBtn_RLVR')),
            relief=None,
            text="Model Detail",
            scale=1,
            text_scale=0.055,
            command=self.changeSetting,
            extraArgs=["model-detail", model_detail],
            pos=(-0.45, 0.35, 0.35),
            text_pos=(0, -0.01))
        self.moddet_lbl = DirectLabel(relief=None,
                                      scale=0.09,
                                      pos=(0.45, 0.35, 0.32),
                                      text_align=TextNode.ACenter)
        self.moddet_lbl['text'] = model_detail.capitalize()
        self.moddet_btn.bind(DGG.ENTER, self.createMustRestartGui)
        self.moddet_btn.bind(DGG.EXIT, self.removeMustRestartGui)

        self.texdet_btn = DirectButton(
            geom=(qt_btn.find('**/QuitBtn_UP'), qt_btn.find('**/QuitBtn_DN'),
                  qt_btn.find('**/QuitBtn_RLVR')),
            relief=None,
            text="Texture Detail",
            scale=1,
            text_scale=0.0535,
            command=self.changeSetting,
            extraArgs=["texture-detail", tex_detail],
            pos=(-0.45, 0.25, 0.25),
            text_pos=(0, -0.01))
        self.texdet_lbl = DirectLabel(relief=None,
                                      scale=0.09,
                                      pos=(0.45, 0.25, 0.22),
                                      text_align=TextNode.ACenter)
        self.texdet_lbl['text'] = tex_detail.capitalize()
        self.texdet_btn.bind(DGG.ENTER, self.createMustRestartGui)
        self.texdet_btn.bind(DGG.EXIT, self.removeMustRestartGui)

        self.display_btn = DirectButton(geom=(qt_btn.find('**/QuitBtn_UP'),
                                              qt_btn.find('**/QuitBtn_DN'),
                                              qt_btn.find('**/QuitBtn_RLVR')),
                                        relief=None,
                                        text="Display",
                                        command=self.openDisplayPage,
                                        scale=1,
                                        text_scale=0.0535,
                                        pos=(-0.45, -0.25, 0.02),
                                        text_pos=(0, -0.01))
        self.display_lbl = DirectLabel(relief=None,
                                       scale=0.06,
                                       pos=(0.45, -0.25, 0.02),
                                       text_align=TextNode.ACenter)
        self.display_lbl['text'] = "Fullscreen: %s\nResolution: %s" % (
            str(fsTxt).capitalize(), (width, height))

        self.aa_btn = DirectButton(geom=(qt_btn.find('**/QuitBtn_UP'),
                                         qt_btn.find('**/QuitBtn_DN'),
                                         qt_btn.find('**/QuitBtn_RLVR')),
                                   relief=None,
                                   text="Anti-Aliasing",
                                   command=self.changeSetting,
                                   extraArgs=["aa", aa],
                                   scale=1,
                                   text_scale=0.0535,
                                   pos=(-0.45, -0.35, -0.18),
                                   text_pos=(0, -0.01))
        self.aa_lbl = DirectLabel(relief=None,
                                  scale=0.09,
                                  pos=(0.45, -0.35, -0.21),
                                  text_align=TextNode.ACenter)
        self.aa_lbl['text'] = aa.capitalize()

        self.af_btn = DirectButton(geom=(qt_btn.find('**/QuitBtn_UP'),
                                         qt_btn.find('**/QuitBtn_DN'),
                                         qt_btn.find('**/QuitBtn_RLVR')),
                                   relief=None,
                                   text="Anisotropic Filtering",
                                   command=self.changeSetting,
                                   extraArgs=["af", af],
                                   scale=1,
                                   text_scale=0.0435,
                                   pos=(-0.45, -0.35, -0.28),
                                   text_pos=(0, -0.01))
        self.af_lbl = DirectLabel(relief=None,
                                  scale=0.09,
                                  pos=(0.45, -0.35, -0.31),
                                  text_align=TextNode.ACenter)
        self.af_lbl['text'] = af.capitalize()
        self.af_btn.bind(DGG.ENTER, self.createMustRestartGui)
        self.af_btn.bind(DGG.EXIT, self.removeMustRestartGui)

        self.exit_btn = DirectButton(geom=(qt_btn.find('**/QuitBtn_UP'),
                                           qt_btn.find('**/QuitBtn_DN'),
                                           qt_btn.find('**/QuitBtn_RLVR')),
                                     relief=None,
                                     text="Exit Toontown",
                                     scale=1.2,
                                     text_scale=0.0535,
                                     command=self.book.finished,
                                     extraArgs=["exit"],
                                     pos=(-0.45, -0.65, -0.60),
                                     text_pos=(0, -0.01))

    def createMustRestartGui(self, foo):
        self.mustRestartLbl = DirectLabel(
            text="Changing this setting requires a game restart.",
            text_fg=(0.9, 0, 0, 1),
            text_shadow=(0, 0, 0, 1),
            text_scale=0.06,
            text_align=TextNode.ACenter,
            pos=(0, 0, -0.435),
            relief=None)

    def removeMustRestartGui(self, foo):
        if hasattr(self, 'mustRestartLbl'):
            self.mustRestartLbl.destroy()
            del self.mustRestartLbl

    def exitBasePage(self):
        self.music_btn.destroy()
        del self.music_btn
        self.sfx_btn.destroy()
        del self.sfx_btn
        self.moddet_btn.destroy()
        del self.moddet_btn
        self.texdet_btn.destroy()
        del self.texdet_btn
        self.display_btn.destroy()
        del self.display_btn
        self.aa_btn.destroy()
        del self.aa_btn
        self.exit_btn.destroy()
        del self.exit_btn
        self.music_lbl.destroy()
        del self.music_lbl
        self.sfx_lbl.destroy()
        del self.sfx_lbl
        self.moddet_lbl.destroy()
        del self.moddet_lbl
        self.texdet_lbl.destroy()
        del self.texdet_lbl
        self.display_lbl.destroy()
        del self.display_lbl
        self.aa_lbl.destroy()
        del self.aa_lbl
        self.af_btn.destroy()
        del self.af_btn
        self.af_lbl.destroy()
        del self.af_lbl
        self.book.deletePageButtons(False, True)
        self.book.clearTitle()
Ejemplo n.º 21
0
    def __init__(self):
        self._weapon_buts = {}
        self._turn_snd = loader.loadSfx(  # noqa: F821
            "sounds/train/railroad_switch.ogg"
        )

        frame = DirectFrame(
            parent=base.a2dBottomRight,  # noqa: F821
            frameSize=(-0.09, 0.09, -0.28, 0.28),
            pos=(-0.09, 0, 0.28),
            frameTexture=GUI_PIC + "metal1.png",
        )
        frame.setTransparency(TransparencyAttrib.MAlpha)
        DirectFrame(  # an icon for the locomotive durability
            parent=frame,
            frameSize=(-0.023, 0.023, -0.023, 0.023),
            pos=(0.05, 0, 0.24),
            frameTexture=GUI_PIC + "train.png",
        ).setTransparency(TransparencyAttrib.MAlpha)

        DirectFrame(  # an icon for the locomotive speed
            parent=frame,
            frameSize=(-0.028, 0.028, -0.023, 0.023),
            pos=(-0.012, 0, 0.24),
            frameTexture=GUI_PIC + "speed.png",
        ).setTransparency(TransparencyAttrib.MAlpha)

        self._durability = DirectWaitBar(
            parent=frame,
            frameSize=(-0.225, 0.225, -0.002, 0.002),
            frameColor=(0.35, 0.35, 0.35, 1),
            range=1000,
            value=1000,
            barColor=(0.42, 0.42, 0.8, 1),
            pos=(0.05, 0, -0.025),
        )
        self._durability.setR(-90)
        self._speed = DirectWaitBar(
            parent=frame,
            frameSize=(-0.225, 0.225, -0.002, 0.002),
            frameColor=(0.35, 0.35, 0.35, 1),
            range=1,
            value=1,
            barColor=(1, 0.63, 0, 0.6),
            pos=(-0.012, 0, -0.025),
        )
        self._speed.setR(-90)

        DirectLabel(  # speed gauge scale
            parent=frame,
            pos=(-0.05, 0, 0.19),
            frameSize=(-0.25, 0.25, -0.01, 0.01),
            frameColor=(0, 0, 0, 0),
            text="40-\n\n-\n\n-\n\n-\n\n20-\n\n-\n\n-\n\n-\n\n0-",
            text_scale=0.028,
            text_fg=SILVER_COL,
        )
        frame_miles = DirectFrame(
            frameSize=(-0.115, 0.115, -0.06, 0.05),
            pos=(0, 0, -0.95),
            frameTexture=GUI_PIC + "metal1.png",
            sortOrder=-1,
        )
        frame_miles.set_transparency(TransparencyAttrib.MAlpha)

        but = DirectButton(
            parent=frame_miles,
            frameSize=(-0.015, 0.015, -0.025, 0.025),
            frameTexture=GUI_PIC + "grenade.png",
            pos=(-0.075, 0, 0.015),
            relief="flat",
        )
        but.setTransparency(TransparencyAttrib.MAlpha)
        but.bind(DGG.ENTER, self._highlight_weapon_but, extraArgs=[but])
        but.bind(DGG.EXIT, self._dehighlight_weapon_but, extraArgs=[but])

        self._weapon_buts["Grenade Launcher"] = {
            "but": but,
            "reload_step": 0,
            "dis_command": None,
            "reloading_len": 13,
            "frame": DirectFrame(
                parent=frame_miles,
                frameColor=(0, 0, 0, 0.25),
                pos=(-0.075, 0, -0.01),
                frameSize=(-0.013, 0.013, 0, 0.05),
            ),
        }

        but = DirectButton(
            parent=frame_miles,
            frameSize=(-0.015, 0.015, -0.025, 0.025),
            frameTexture=GUI_PIC + "machine_gun.png",
            pos=(0, 0, 0.015),
            relief="flat",
        )
        but.setTransparency(TransparencyAttrib.MAlpha)
        but.bind(DGG.ENTER, self._highlight_weapon_but, extraArgs=[but])
        but.bind(DGG.EXIT, self._dehighlight_weapon_but, extraArgs=[but])

        self._weapon_buts["Machine Gun"] = {
            "but": but,
            "reload_step": 0,
            "dis_command": None,
            "reloading_len": 22,
            "frame": DirectFrame(
                parent=frame_miles,
                frameColor=(0, 0, 0, 0.25),
                pos=(0, 0, -0.01),
                frameSize=(-0.013, 0.013, 0, 0.05),
            ),
        }

        but = DirectButton(
            parent=frame_miles,
            frameSize=(-0.015, 0.015, -0.025, 0.025),
            frameTexture=GUI_PIC + "cluster_rocket.png",
            pos=(0.075, 0, 0.015),
            relief="flat",
        )
        but.setTransparency(TransparencyAttrib.MAlpha)
        but.bind(DGG.ENTER, self._highlight_weapon_but, extraArgs=[but])
        but.bind(DGG.EXIT, self._dehighlight_weapon_but, extraArgs=[but])

        self._weapon_buts["Cluster Howitzer"] = {
            "but": but,
            "reload_step": 0,
            "dis_command": None,
            "reloading_len": 45,
            "frame": DirectFrame(
                parent=frame_miles,
                frameColor=(0, 0, 0, 0.25),
                pos=(0.075, 0, -0.01),
                frameSize=(-0.013, 0.013, 0, 0.05),
            ),
        }

        self._miles_meter = DirectLabel(
            parent=frame_miles,
            text="0000000",
            text_font=base.main_font,  # noqa: F821
            frameSize=(0.1, 0.1, 0.15, 0.15),
            text_scale=(0.033, 0.031),
            text_fg=RUST_COL,
            pos=(0, 0, -0.04),
        )
        taskMgr.doMethodLater(  # noqa: F821
            0.25, self._update_speed, "update_speed_indicator"
        )
        self._fork_lab = None
Ejemplo n.º 22
0
class LaffShopGui(DirectFrame):
    def __init__(self):
        DirectFrame.__init__(self,
                             parent=aspect2d,
                             relief=None,
                             geom=DGG.getDefaultDialogGeom(),
                             geom_color=ToontownGlobals.GlobalDialogColor,
                             geom_scale=(1.33, 1, 1.3),
                             pos=(0, 0, 0),
                             text='',
                             text_scale=0.07,
                             text_pos=(0, 0.475))
        self.initialiseoptions(LaffShopGui)

        self.additionalLaff = 0
        self.timer = ToontownTimer.ToontownTimer()
        self.timer.reparentTo(aspect2d)
        self.timer.posInTopRightCorner()
        self.timer.countdown(LaffRestockGlobals.TIMER_SECONDS, self.__cancel,
                             [LaffRestockGlobals.TIMER_END])
        self.setupButtons()
        self.bindButtons()
        self.laffMeter = LaffMeter.LaffMeter(base.localAvatar.style,
                                             base.localAvatar.getHp(),
                                             base.localAvatar.getMaxHp())
        self.laffMeter.reparentTo(self)
        self.laffMeter.setPos(0, 0, 0.065)
        self.laffMeter.setScale(0.13)
        self.__updateLaffMeter(1)

    def setupButtons(self):
        buttons = loader.loadModel('phase_3/models/gui/dialog_box_buttons_gui')
        arrowGui = loader.loadModel('phase_3/models/gui/create_a_toon_gui')
        arrowImageList = (arrowGui.find('**/CrtATn_R_Arrow_UP'),
                          arrowGui.find('**/CrtATn_R_Arrow_DN'),
                          arrowGui.find('**/CrtATn_R_Arrow_RLVR'),
                          arrowGui.find('**/CrtATn_R_Arrow_UP'))

        self.cancelButton = DirectButton(
            parent=self,
            relief=None,
            image=(buttons.find('**/CloseBtn_UP'),
                   buttons.find('**/CloseBtn_DN'),
                   buttons.find('**/CloseBtn_Rllvr')),
            pos=(-0.2, 0, -0.5),
            text=OTPLocalizer.lCancel,
            text_scale=0.06,
            text_pos=(0, -0.1),
            command=self.__cancel,
            extraArgs=[LaffRestockGlobals.USER_CANCEL])
        self.okButton = DirectButton(
            parent=self,
            relief=None,
            image=(buttons.find('**/ChtBx_OKBtn_UP'),
                   buttons.find('**/ChtBx_OKBtn_DN'),
                   buttons.find('**/ChtBx_OKBtn_Rllvr')),
            pos=(0.2, 0, -0.5),
            text=OTPLocalizer.lOK,
            text_scale=0.06,
            text_pos=(0, -0.1),
            command=self.__restock)
        self.upArrow = DirectButton(parent=self,
                                    relief=None,
                                    image=arrowImageList,
                                    image_scale=(1, 1, 1),
                                    image3_color=Vec4(0.6, 0.6, 0.6, 0.25),
                                    pos=(0.2, 0, -0.265))
        self.downArrow = DirectButton(parent=self,
                                      relief=None,
                                      image=arrowImageList,
                                      image_scale=(-1, 1, 1),
                                      image3_color=Vec4(0.6, 0.6, 0.6, 0.25),
                                      pos=(-0.2, 0, -0.265))

        buttons.removeNode()
        arrowGui.removeNode()

    def bindButtons(self):
        self.downArrow.bind(DGG.B1PRESS, self.__taskUpdate, extraArgs=[-1])
        self.downArrow.bind(DGG.B1RELEASE, self.__taskDone)
        self.upArrow.bind(DGG.B1PRESS, self.__taskUpdate, extraArgs=[1])
        self.upArrow.bind(DGG.B1RELEASE, self.__taskDone)

    def destroy(self):
        self.ignoreAll()

        if self.timer:
            self.timer.destroy()

        taskMgr.remove(self.taskName('runLaffCounter'))
        DirectFrame.destroy(self)

    def __cancel(self, state):
        self.destroy()
        messenger.send('laffShopDone', [state, 0])

    def __restock(self):
        self.destroy()
        messenger.send('laffShopDone',
                       [LaffRestockGlobals.RESTOCK, self.additionalLaff])

    def __updateLaffMeter(self, amount):
        self.additionalLaff += amount
        hitLimit = 0
        newLaff = base.localAvatar.getHp() + self.additionalLaff

        if (newLaff - 1) <= base.localAvatar.getHp():
            self.downArrow['state'] = DGG.DISABLED
            hitLimit = 1
        else:
            self.downArrow['state'] = DGG.NORMAL

        if newLaff >= base.localAvatar.getMaxHp():
            self.upArrow['state'] = DGG.DISABLED
            hitLimit = 1
        else:
            self.upArrow['state'] = DGG.NORMAL

        cost = self.additionalLaff * ToontownGlobals.CostPerLaffRestock
        self['text'] = TTLocalizer.RestockAskMessage % (self.additionalLaff,
                                                        cost)

        if cost > base.localAvatar.getTotalMoney():
            self.okButton['state'] = DGG.DISABLED
            self['text'] += TTLocalizer.RestockNoMoneyGuiMessage
        else:
            self.okButton['state'] = DGG.NORMAL

        self.laffMeter.hp = newLaff
        self.laffMeter.start()

        return hitLimit

    def __runTask(self, task):
        if task.time - task.prevTime < task.delayTime:
            return Task.cont
        else:
            task.delayTime = max(0.05, task.delayTime * 0.75)
            task.prevTime = task.time
            hitLimit = self.__updateLaffMeter(task.delta)

            return Task.done if hitLimit else Task.cont

    def __taskDone(self, event):
        messenger.send('wakeup')
        taskMgr.remove(self.taskName('runLaffCounter'))

    def __taskUpdate(self, delta, event):
        messenger.send('wakeup')

        task = Task(self.__runTask)
        task.delayTime = 0.4
        task.prevTime = 0.0
        task.delta = delta
        hitLimit = self.__updateLaffMeter(delta)

        if not hitLimit:
            taskMgr.add(task, self.taskName('runLaffCounter'))
Ejemplo n.º 23
0
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')
Ejemplo n.º 24
0
class PartyPlanner(DirectFrame, FSM):
    notify = DirectNotifyGlobal.directNotify.newCategory('PartyPlanner')

    def __init__(self, doneEvent = None):
        FSM.__init__(self, 'PartyPlannerFSM')
        DirectFrame.__init__(self)
        self.doneEvent = doneEvent
        self.stateArray = ['Off',
         'Welcome',
         'PartyEditor',
         'Guests',
         'Date',
         'Time',
         'Invitation',
         'Farewell']
        self.partyTime = base.cr.toontownTimeManager.getCurServerDateTime()
        self.partyNowTime = base.cr.toontownTimeManager.getCurServerDateTime()
        minutesToNextFifteen = 15 - self.partyTime.minute % 15
        self.cleanPartyTime = self.partyTime + timedelta(minutes=minutesToNextFifteen, seconds=-self.partyTime.second)
        self.partyTime = self.cleanPartyTime
        self.guests = []
        self.isPrivate = False
        self.selectedCalendarGuiDay = None
        self.gui = loader.loadModel('phase_4/models/parties/partyPlannerGUI')
        self.partyDuration = timedelta(hours=PartyGlobals.DefaultPartyDuration)
        self.timeTypeToMaxValue = {'hour': 23,
         'minute': 59}
        self.timeTypeToChangeAmount = {'hour': (1, -1),
         'minute': (15, -15),
         'ampm': (1, -1)}
        self.partyInfo = None
        self.asapMinuteRounding = base.config.GetInt('party-asap-minute-rounding', PartyGlobals.PartyPlannerAsapMinuteRounding)
        self.load()
        self.request('Welcome')
        return

    def enterWelcome(self, *args):
        self.prevButton['state'] = DirectGuiGlobals.DISABLED
        self.prevButton.hide()
        self.nextButton['state'] = DirectGuiGlobals.NORMAL
        self.welcomePage.show()
        self.partyPlannerHead.reparentTo(self.welcomePage)
        self.partyPlannerHead.startBlink()
        self.partyPlannerHead.startLookAround()
        self.nametagNP.reparentTo(self.welcomePage)
        self.chatNP.reparentTo(self.welcomePage)

    def exitWelcome(self):
        self.welcomePage.hide()
        self.prevButton.show()
        self.partyPlannerHead.stopBlink()
        self.partyPlannerHead.stopLookAround()

    def enterPartyEditor(self, *args):
        self.prevButton['state'] = DirectGuiGlobals.NORMAL
        self.nextButton['state'] = DirectGuiGlobals.DISABLED
        self.nextButton.hide()
        self.partyEditorPage.show()
        self.okWithGroundsGui.doneStatus = ''
        self.partyEditor.request('Idle')

    def exitPartyEditor(self):
        self.partyEditor.request('Hidden')
        self.partyEditorPage.hide()

    def enterGuests(self, *args):
        self.prevButton['state'] = DirectGuiGlobals.NORMAL
        self.nextButton['state'] = DirectGuiGlobals.NORMAL
        self.nextButton.show()
        self.guestPage.show()

    def exitGuests(self):
        self.guests = []
        for friendCheckBox in self.friendList['items']:
            if friendCheckBox['indicatorValue']:
                self.guests.append(friendCheckBox.getPythonTag('id'))

        self.guestPage.hide()

    def enterDate(self, *args):
        self.prevButton.show()
        self.prevButton['state'] = DirectGuiGlobals.NORMAL
        if self.selectedCalendarGuiDay is None:
            self.nextButton['state'] = DirectGuiGlobals.DISABLED
            self.nextButton.hide()
            self.makePartyNowButton.show()
        self.datePage.show()
        return

    def exitDate(self):
        self.datePage.hide()
        self.nextButton.show()
        if self.selectedCalendarGuiDay is not None:
            self.partyTime = self.cleanPartyTime
            self.alterPartyTime(year=self.selectedCalendarGuiDay.myDate.year, month=self.selectedCalendarGuiDay.myDate.month, day=self.selectedCalendarGuiDay.myDate.day)
        else:
            self.partyNowTime = self.calcAsapTime()
            self.partyTime = self.partyNowTime
        return

    def calcAsapTime(self):
        curServerTime = base.cr.toontownTimeManager.getCurServerDateTime()
        baseTime = curServerTime
        baseTime = baseTime.replace(baseTime.year, baseTime.month, baseTime.day, baseTime.hour, baseTime.minute, second=0, microsecond=0)
        minute = curServerTime.minute
        remainder = minute % self.asapMinuteRounding
        if remainder:
            baseTime += timedelta(minutes=self.asapMinuteRounding - remainder)
        else:
            baseTime += timedelta(minutes=self.asapMinuteRounding)
        return baseTime

    def enterTime(self, *args):
        self.prevButton.show()
        self.prevButton['state'] = DirectGuiGlobals.NORMAL
        self.nextButton.show()
        self.timePage.show()
        self.timePageRecapToontownTimeLabel2['text'] = '%s' % PartyUtils.formatDateTime(self.partyTime)
        self.timePageRecapLocalTimeLabel['text'] = '%s%s' % (TTLocalizer.PartyPlannerTimeLocalTime, PartyUtils.formatDateTime(self.partyTime, inLocalTime=True))

    def exitTime(self):
        self.timePage.hide()
        self.nextButton.show()

    def enterInvitation(self, *args):
        self.prevButton['state'] = DirectGuiGlobals.NORMAL
        self.nextButton.hide()
        defaultInviteTheme = PartyGlobals.InviteTheme.GenericMale
        if hasattr(base.cr, 'newsManager') and base.cr.newsManager:
            if ToontownGlobals.VICTORY_PARTY_HOLIDAY in base.cr.newsManager.getHolidayIdList():
                defaultInviteTheme = PartyGlobals.InviteTheme.VictoryParty
            elif ToontownGlobals.KARTING_TICKETS_HOLIDAY in base.cr.newsManager.getHolidayIdList() or ToontownGlobals.CIRCUIT_RACING_EVENT in base.cr.newsManager.getHolidayIdList():
                defaultInviteTheme = PartyGlobals.InviteTheme.Racing
            elif ToontownGlobals.VALENTINES_DAY in base.cr.newsManager.getHolidayIdList():
                defaultInviteTheme = PartyGlobals.InviteTheme.Valentoons
        if self.partyInfo is not None:
            del self.partyInfo
        activityList = self.partyEditor.partyEditorGrid.getActivitiesOnGrid()
        decorationList = self.partyEditor.partyEditorGrid.getDecorationsOnGrid()
        endTime = self.partyTime + self.partyDuration
        self.partyInfo = PartyInfo(0, 0, self.partyTime.year, self.partyTime.month, self.partyTime.day, self.partyTime.hour, self.partyTime.minute, endTime.year, endTime.month, endTime.day, endTime.hour, endTime.minute, self.isPrivate, defaultInviteTheme, activityList, decorationList, 0)
        if self.noFriends or len(self.getInvitees()) == 0:
            self.inviteVisual.setNoFriends(True)
            self.invitationTitleLabel['text'] = TTLocalizer.PartyPlannerConfirmTitleNoFriends
            self.inviteButton['text'] = TTLocalizer.PartyPlannerInviteButtonNoFriends
            self.selectedInviteThemeLabel.stash()
            self.nextThemeButton.stash()
            self.prevThemeButton.stash()
            self.setInviteTheme(defaultInviteTheme)
        else:
            self.inviteVisual.setNoFriends(False)
            self.invitationTitleLabel['text'] = TTLocalizer.PartyPlannerConfirmTitle
            self.inviteButton['text'] = TTLocalizer.PartyPlannerInviteButton
            self.selectedInviteThemeLabel.unstash()
            self.nextThemeButton.unstash()
            self.prevThemeButton.unstash()
            self.setInviteTheme(defaultInviteTheme)
        self.inviteVisual.updateInvitation(base.localAvatar.getName(), self.partyInfo)
        self.invitationPage.show()
        return

    def __prevTheme(self):
        self.nextThemeButton.show()
        prevTheme = self.currentInvitationTheme - 1
        while prevTheme not in self.inviteThemes:
            prevTheme -= 1
            if prevTheme == self.currentInvitationTheme:
                self.notify.warning('No previous invite theme found.')
                break
            elif prevTheme < 0:
                prevTheme = len(self.inviteVisual.inviteThemesIdToInfo) - 1

        self.setInviteTheme(prevTheme)

    def __nextTheme(self):
        self.prevThemeButton.show()
        nextTheme = self.currentInvitationTheme + 1
        while nextTheme not in self.inviteThemes:
            nextTheme += 1
            if nextTheme == self.currentInvitationTheme:
                self.notify.warning('No next invite theme found.')
                break
            elif nextTheme >= len(self.inviteVisual.inviteThemesIdToInfo):
                nextTheme = 0

        self.setInviteTheme(nextTheme)

    def setInviteTheme(self, themeNumber):
        self.currentInvitationTheme = themeNumber
        self.selectedInviteThemeLabel['text'] = '%s %s (%d/%d)' % (self.inviteVisual.inviteThemesIdToInfo[self.currentInvitationTheme][1],
         TTLocalizer.PartyPlannerInvitationTheme,
         self.inviteThemes.index(self.currentInvitationTheme) + 1,
         len(self.inviteThemes))
        self.partyInfo.inviteTheme = self.currentInvitationTheme
        self.inviteVisual.updateInvitation(base.localAvatar.getName(), self.partyInfo)

    def exitInvitation(self):
        self.invitationPage.hide()
        self.nextButton.show()

    def enterFarewell(self, goingBackAllowed):
        self.farewellPage.show()
        if goingBackAllowed:
            self.prevButton.show()
        else:
            self.prevButton.hide()
        self.nextButton.hide()
        self.partyPlannerHead.reparentTo(self.farewellPage)
        self.partyPlannerHead.startBlink()
        self.partyPlannerHead.startLookAround()
        self.nametagNP.reparentTo(self.farewellPage)
        self.chatNP.reparentTo(self.farewellPage)

    def exitFarewell(self):
        self.farewellPage.hide()
        self.nextButton.show()
        self.prevButton.show()
        self.partyPlannerHead.stopBlink()
        self.partyPlannerHead.stopLookAround()

    def load(self):
        self.frame = DirectFrame(parent=aspect2d, geom=self.gui.find('**/background'), relief=None, scale=0.85, pos=(0.05, 0.0, 0.1))
        self.titleScale = TTLocalizer.PPtitleScale
        self._createNavButtons()
        self.welcomePage = self._createWelcomePage()
        self.welcomePage.hide()
        self.datePage = self._createDatePage()
        self.datePage.hide()
        self.timePage = self._createTimePage()
        self.timePage.hide()
        self.guestPage = self._createGuestPage()
        self.guestPage.hide()
        self.partyEditorPage = self._createPartyEditorPage()
        self.partyEditorPage.hide()
        self.invitationPage = self._createInvitationPage()
        self.invitationPage.hide()
        self.farewellPage = self._createFarewellPage()
        self.farewellPage.hide()
        return

    def _createNavButtons(self):
        self.quitButton = DirectButton(parent=self.frame, relief=None, geom=(self.gui.find('**/cancelButton_up'), self.gui.find('**/cancelButton_down'), self.gui.find('**/cancelButton_rollover')), command=self.__acceptExit)
        self.nextButton = DirectButton(parent=self.frame, relief=None, geom=(self.gui.find('**/bottomNext_button/nextButton_up'), self.gui.find('**/bottomNext_button/nextButton_down'), self.gui.find('**/bottomNext_button/nextButton_rollover')), command=self.__nextItem, state=DirectGuiGlobals.DISABLED)
        self.prevButton = DirectButton(parent=self.frame, relief=None, geom=(self.gui.find('**/bottomPrevious_button/previousButton_up'), self.gui.find('**/bottomPrevious_button/previousButton_down'), self.gui.find('**/bottomPrevious_button/previousButton_rollover')), command=self.__prevItem, state=DirectGuiGlobals.DISABLED)
        self.currentItem = None
        return

    def __createNametag(self, parent):
        if self.nametagGroup == None:
            self.nametagGroup = NametagGroup()
            self.nametagGroup.setFont(OTPGlobals.getInterfaceFont())
            self.nametagGroup.setActive(0)
            self.nametagGroup.setAvatar(self.partyPlannerHead)
            self.nametagGroup.manage(base.marginManager)
            self.nametagGroup.setColorCode(self.nametagGroup.CCNonPlayer)
            self.nametagGroup.getNametag2d().setContents(0)
            self.nametagNode = NametagFloat2d()
            self.nametagNode.setContents(Nametag.CName)
            self.nametagGroup.addNametag(self.nametagNode)
            self.nametagGroup.setName(base.cr.partyManager.getPartyPlannerName())
            self.nametagNP = parent.attachNewNode(self.nametagNode.upcastToPandaNode())
            nametagPos = self.gui.find('**/step_01_partymanPeteNametag_locator').getPos()
            self.nametagNP.setPosHprScale(nametagPos[0], 0, nametagPos[2], 0, 0, 0, 0.1, 1, 0.1)
            self.chatNode = NametagFloat2d()
            self.chatNode.setContents(Nametag.CSpeech | Nametag.CThought)
            self.nametagGroup.addNametag(self.chatNode)
            self.nametagGroup.setChat(TTLocalizer.PartyPlannerInstructions, CFSpeech)
            self.chatNP = parent.attachNewNode(self.chatNode.upcastToPandaNode())
            chatPos = self.gui.find('**/step_01_partymanPeteText_locator').getPos()
            self.chatNP.setPosHprScale(chatPos[0], 0, chatPos[2], 0, 0, 0, 0.08, 1, 0.08)
        return

    def clearNametag(self):
        if self.nametagGroup != None:
            self.nametagGroup.unmanage(base.marginManager)
            self.nametagGroup.removeNametag(self.nametagNode)
            self.nametagGroup.removeNametag(self.chatNode)
            self.nametagNP.removeNode()
            self.chatNP.removeNode()
            del self.nametagNP
            del self.chatNP
            del self.nametagNode
            del self.chatNode
            self.nametagGroup.setAvatar(NodePath())
            self.nametagGroup = None
        return

    def _createWelcomePage(self):
        self.nametagGroup = None
        page = DirectFrame(self.frame)
        page.setName('PartyPlannerWelcomePage')
        self.welcomeTitleLabel = DirectLabel(parent=page, relief=None, text=TTLocalizer.PartyPlannerWelcomeTitle, pos=self.gui.find('**/title_locator').getPos(), scale=self.titleScale)
        self.partyPlannerHead = ToonHead.ToonHead()
        partyPlannerStyle = base.cr.partyManager.getPartyPlannerStyle()
        self.partyPlannerHead.setupHead(partyPlannerStyle, forGui=True)
        self.partyPlannerHead.setPos(self.gui.find('**/step_01_partymanPete_locator').getPos())
        animal = partyPlannerStyle.getAnimal()
        if animal == 'cat' or animal == 'pig':
            headScale = 0.4
        elif animal == 'dog' or animal == 'bear':
            headScale = 0.45
        elif animal == 'rabbit':
            headScale = 0.35
        else:
            headScale = 0.3
        self.partyPlannerHead.setScale(headScale)
        self.partyPlannerHead.setH(180.0)
        self.partyPlannerHead.reparentTo(page)
        self.__createNametag(page)
        return page

    def _createDatePage(self):
        page = DirectFrame(self.frame)
        page.setName('PartyPlannerDatePage')
        self.createDateTitleLabel = DirectLabel(parent=page, relief=None, text=TTLocalizer.PartyPlannerDateTitle, pos=self.gui.find('**/title_locator').getPos(), scale=self.titleScale)
        pos = self.gui.find('**/step_06_sendInvitation_locator').getPos()
        self.makePartyNowButton = DirectButton(parent=page, relief=None, geom=(self.gui.find('**/send_up'), self.gui.find('**/send_down'), self.gui.find('**/send_rollover')), text=TTLocalizer.PartyPlannerPartyNow, text_pos=(pos[0], pos[2]), text_scale=0.05, command=self.__doMakePartyNow)
        curServerDate = base.cr.toontownTimeManager.getCurServerDateTime()
        self.calendarGuiMonth = CalendarGuiMonth(page, curServerDate, scale=0.95, pos=(-0.05, 0.0, -0.33), dayClickCallback=self._dayClickCallback, onlyFutureDaysClickable=True)
        return page

    def __doMakePartyNow(self):
        self.request('Invitation')

    def _dayClickCallback(self, calendarGuiDay):
        self.selectedCalendarGuiDay = calendarGuiDay
        self.nextButton['state'] = DirectGuiGlobals.NORMAL
        self.makePartyNowButton.hide()
        self.nextButton.show()

    def alterPartyTime(self, year = None, month = None, day = None, hour = None, minute = None):
        self.partyTime = datetime(year=self.positiveTime('year', year), month=self.positiveTime('month', month), day=self.positiveTime('day', day), hour=self.positiveTime('hour', hour), minute=self.positiveTime('minute', minute), tzinfo=self.partyTime.tzinfo)

    def positiveTime(self, type, amount):
        if amount is None:
            return getattr(self.partyTime, type)
        if type == 'hour' or type == 'minute':
            if amount < 0:
                return self.timeTypeToMaxValue[type] + 1 + self.timeTypeToChangeAmount[type][1]
            elif amount > self.timeTypeToMaxValue[type]:
                return 0
        return amount

    def _createTimePage(self):
        page = DirectFrame(self.frame)
        page.setName('PartyPlannerTimePage')
        self.createTimeTitleLabel = DirectLabel(parent=page, relief=None, text=TTLocalizer.PartyPlannerTimeTitle, pos=self.gui.find('**/title_locator').getPos(), scale=self.titleScale)
        self.clockImage = DirectFrame(parent=page, relief=None, geom=self.gui.find('**/toontownTime_background'))
        self.timePageToontownLabel = DirectLabel(parent=page, relief=None, text=TTLocalizer.PartyPlannerTimeToontown, pos=self.gui.find('**/step_03_toontown_locator').getPos(), scale=0.15, text_fg=(1.0, 0.0, 0.0, 1.0), text_font=ToontownGlobals.getSignFont())
        self.timePageTimeLabel = DirectLabel(parent=page, relief=None, text=TTLocalizer.PartyPlannerTimeTime, pos=self.gui.find('**/step_03_time_locator').getPos(), scale=0.15, text_fg=(1.0, 0.0, 0.0, 1.0), text_font=ToontownGlobals.getSignFont())
        self.timePageRecapLabel = DirectLabel(parent=page, relief=None, text=TTLocalizer.PartyPlannerTimeRecap, pos=self.gui.find('**/step_03_partyDateAndTime_locator').getPos(), scale=0.09)
        self.timePageRecapToontownTimeLabel1 = DirectLabel(parent=page, relief=None, text=TTLocalizer.PartyPlannerTimeToontownTime, pos=self.gui.find('**/step_03_toontownTime_locator').getPos(), scale=0.06)
        self.timePageRecapToontownTimeLabel2 = DirectLabel(parent=page, relief=None, text='%s' % PartyUtils.formatDateTime(self.partyTime), pos=self.gui.find('**/step_03_toontownDateAndTime_loactor').getPos(), textMayChange=True, scale=0.06)
        self.timePageRecapLocalTimeLabel = DirectLabel(parent=page, relief=None, text='%s%s' % (TTLocalizer.PartyPlannerTimeLocalTime, PartyUtils.formatDateTime(self.partyTime, inLocalTime=True)), pos=self.gui.find('**/step_03_localDateAndTime_loactor').getPos(), textMayChange=True, scale=0.06, text_fg=(1.0, 0.0, 0.0, 1.0))
        self.timeInputHourLabel, self.timeInputHourUpButton, self.timeInputHourDownButton = self.getTimeWidgets(page, 'hour')
        self.timeInputMinuteLabel, self.timeInputMinuteUpButton, self.timeInputMinuteDownButton = self.getTimeWidgets(page, 'minute')
        self.timeInputAmPmLabel, self.timeInputAmPmUpButton, self.timeInputAmPmDownButton = self.getTimeWidgets(page, 'ampm')
        self.timePagecolonLabel = DirectLabel(parent=page, relief=None, text=':', pos=self.gui.find('**/step_03_colon_locator').getPos(), scale=0.15)
        return page

    def getTimeWidgets(self, page, type):
        if type == 'ampm':
            data = self.getCurrentAmPm()
        else:
            data = getattr(self.partyTime, type)
            if data == 0 and type == 'minute':
                data = '00'
            else:
                if type == 'hour':
                    data = data % 12
                    if data == 0:
                        data = 12
                data = '%d' % data
        label = DirectLabel(parent=page, relief=None, text='%s' % data, textMayChange=True, pos=self.gui.find('**/step_03_%s_locator' % type).getPos(), scale=0.12)

        def changeValue(self, amount):
            if type == 'ampm':
                self.alterPartyTime(hour=(self.partyTime.hour + 12) % 24)
                newAmount = self.getCurrentAmPm()
                label['text'] = newAmount
            else:
                if type == 'hour':
                    newAmount = getattr(self.partyTime, type) + amount
                    newAmount = newAmount % 12
                    if self.timeInputAmPmLabel['text'] == TTLocalizer.PartyTimeFormatMeridiemPM:
                        newAmount = newAmount % 12 + 12
                    self.alterPartyTime(hour=newAmount)
                elif type == 'minute':
                    newAmount = getattr(self.partyTime, type) + amount
                    self.alterPartyTime(minute=newAmount)
                else:
                    PartyPlanner.notify.error('Invalid type for changeValue in PartyPlanner: %s' % type)
                newAmount = getattr(self.partyTime, type)
                if newAmount < 10 and type == 'minute':
                    label['text'] = '0%d' % newAmount
                else:
                    if type == 'hour':
                        newAmount = newAmount % 12
                        if newAmount == 0:
                            newAmount = 12
                    label['text'] = '%d' % newAmount
            self.timePageRecapToontownTimeLabel2['text'] = '%s' % PartyUtils.formatDateTime(self.partyTime)
            self.timePageRecapLocalTimeLabel['text'] = '%s%s' % (TTLocalizer.PartyPlannerTimeLocalTime, PartyUtils.formatDateTime(self.partyTime, inLocalTime=True))

        upButton = DirectButton(parent=page, relief=None, geom=(self.gui.find('**/%sButtonUp_up' % type), self.gui.find('**/%sButtonUp_down' % type), self.gui.find('**/%sButtonUp_rollover' % type)), command=changeValue, extraArgs=[self, self.timeTypeToChangeAmount[type][0]])
        downButton = DirectButton(parent=page, relief=None, geom=(self.gui.find('**/%sButtonDown_up' % type), self.gui.find('**/%sButtonDown_down' % type), self.gui.find('**/%sButtonDown_rollover' % type)), command=changeValue, extraArgs=[self, self.timeTypeToChangeAmount[type][1]])
        return (label, upButton, downButton)

    def getCurrentAmPm(self):
        if self.partyTime.hour < 12:
            return TTLocalizer.PartyTimeFormatMeridiemAM
        else:
            return TTLocalizer.PartyTimeFormatMeridiemPM

    def _createGuestPage(self):
        page = DirectFrame(self.frame)
        page.setName('PartyPlannerGuestPage')
        self.guestTitleLabel = DirectLabel(parent=page, relief=None, text=TTLocalizer.PartyPlannerGuestTitle, pos=self.gui.find('**/title_locator').getPos(), scale=self.titleScale)
        self.guestBackgroundLabel = DirectLabel(parent=page, relief=None, image=self.gui.find('**/guestListBackground_flat'), scale=(1.2, 1.0, 1.0))
        self.friendList = ScrolledFriendList(page, self.gui, makeItemsCheckBoxes=True)
        if len(base.localAvatar.friendsList) == 0:
            self.noFriends = True
        else:
            self.noFriends = False
            for friendPair in base.localAvatar.friendsList:
                self.friendList.addFriend(determineFriendName(friendPair), friendPair[0])

            self.friendList.scrollTo(0)
        pos = self.gui.find('**/step_04_partyWillBe_locator').getPos()
        self.publicPrivateLabel = DirectLabel(parent=page, relief=None, text=TTLocalizer.PartyPlannerPublicPrivateLabel, text_align=TextNode.ACenter, text_scale=0.065, pos=pos)
        self.publicDescriptionLabel = DirectLabel(parent=page, relief=None, text=TTLocalizer.PartyPlannerPublicDescription, text_align=TextNode.ACenter, text_scale=TTLocalizer.PPpbulicDescriptionLabel, pos=(pos[0] - 0.52, pos[1], pos[2]))
        self.publicDescriptionLabel.stash()
        self.privateDescriptionLabel = DirectLabel(parent=page, relief=None, text=TTLocalizer.PartyPlannerPrivateDescription, text_align=TextNode.ACenter, text_scale=TTLocalizer.PPprivateDescriptionLabel, pos=(pos[0] + 0.55, pos[1], pos[2]))
        self.privateDescriptionLabel.stash()
        pos = self.gui.find('**/step_04_public_locator').getPos()
        self.publicButton = DirectButton(parent=page, relief=None, geom=(self.gui.find('**/publicButton_up'),
         self.gui.find('**/publicButton_down'),
         self.gui.find('**/publicButton_rollover'),
         self.gui.find('**/publicButton_inactive')), text=TTLocalizer.PartyPlannerPublic, text_pos=(pos[0], pos[2]), text_scale=TTLocalizer.PPpublicButton, command=self.__doTogglePublicPrivate)
        self.publicButton['state'] = DirectGuiGlobals.DISABLED
        self.publicButton.bind(DirectGuiGlobals.ENTER, self.__enterPublic)
        self.publicButton.bind(DirectGuiGlobals.EXIT, self.__exitPublic)
        pos = self.gui.find('**/step_04_private_locator').getPos()
        self.privateButton = DirectButton(parent=page, relief=None, geom=(self.gui.find('**/privateButton_up'),
         self.gui.find('**/privateButton_down'),
         self.gui.find('**/privateButton_rollover'),
         self.gui.find('**/privateButton_inactive')), text=TTLocalizer.PartyPlannerPrivate, text_pos=(pos[0], pos[2]), text_scale=TTLocalizer.PPprivateButton, command=self.__doTogglePublicPrivate)
        self.privateButton.bind(DirectGuiGlobals.ENTER, self.__enterPrivate)
        self.privateButton.bind(DirectGuiGlobals.EXIT, self.__exitPrivate)
        self.checkAllButton = DirectButton(parent=page, relief=None, geom=(self.gui.find('**/checkAllButton_up'), self.gui.find('**/checkAllButton_down'), self.gui.find('**/checkAllButton_rollover')), command=self.__doCheckAll)
        self.uncheckAllButton = DirectButton(parent=page, relief=None, geom=(self.gui.find('**/uncheckAllButton_up'), self.gui.find('**/uncheckAllButton_down'), self.gui.find('**/uncheckAllButton_rollover')), command=self.__doUncheckAll)
        return page

    def __doCheckAll(self):
        for friendBox in self.friendList['items']:
            friendBox['indicatorValue'] = True

    def __doUncheckAll(self):
        for friendBox in self.friendList['items']:
            friendBox['indicatorValue'] = False

    def __enterPrivate(self, mouseEvent):
        self.privateDescriptionLabel.unstash()

    def __exitPrivate(self, mouseEvent):
        self.privateDescriptionLabel.stash()

    def __enterPublic(self, mouseEvent):
        self.publicDescriptionLabel.unstash()

    def __exitPublic(self, mouseEvent):
        self.publicDescriptionLabel.stash()

    def __doTogglePublicPrivate(self):
        if self.isPrivate:
            self.isPrivate = False
            self.privateButton['state'] = DirectGuiGlobals.NORMAL
            self.publicButton['state'] = DirectGuiGlobals.DISABLED
        else:
            self.isPrivate = True
            self.privateButton['state'] = DirectGuiGlobals.DISABLED
            self.publicButton['state'] = DirectGuiGlobals.NORMAL

    def _createPartyEditorPage(self):
        page = DirectFrame(self.frame)
        page.setName('PartyPlannerEditorPage')
        self.LayoutTitleLabel = DirectLabel(parent=page, relief=None, text=TTLocalizer.PartyPlannerEditorTitle, pos=self.gui.find('**/title_locator').getPos() + Point3(0.0, 0.0, 0.075), scale=self.titleScale)
        self.costLabel = DirectLabel(parent=page, pos=(-0.74, 0.0, 0.17), relief=None, text=TTLocalizer.PartyPlannerTotalCost % 0, text_align=TextNode.ACenter, scale=TTLocalizer.PPcostLabel, textMayChange=True)
        self.partyGridBackground = DirectFrame(parent=page, relief=None, geom=self.gui.find('**/partyGrid_flat'))
        self.partyGroundsLabel = DirectLabel(parent=page, relief=None, text=TTLocalizer.PartyPlannerPartyGrounds, text_font=ToontownGlobals.getSignFont(), text_fg=VBase4(1.0, 0.0, 0.0, 1.0), text_scale=TTLocalizer.PPpartyGroundsLabel, pos=self.gui.find('**/step_05_partyGrounds_text_locator').getPos(), scale=0.1)
        self.activityBackground = DirectFrame(parent=page, relief=None, geom=self.gui.find('**/activitiesDecorations_flat1'), pos=(0.0, 0.0, 0.04))
        pos = self.gui.find('**/step_05_instructions_locator').getPos()
        self.instructionLabel = DirectLabel(parent=page, relief=None, text=' ', text_pos=(pos[0], pos[2]), text_scale=TTLocalizer.PPinstructionLabel, textMayChange=True, geom=self.gui.find('**/instructions_flat'))
        self.elementTitleLabel = DirectLabel(parent=page, relief=None, text=' ', pos=self.gui.find('**/step_05_activitiesName_text_locator').getPos() + Point3(0.0, 0.0, 0.04), text_scale=TTLocalizer.PPelementTitleLabel, textMayChange=True)
        self.elementPriceNode = TextNode('ElementPrice')
        self.elementPriceNode.setAlign(TextNode.ALeft)
        self.elementPriceNode.setTextColor(0.0, 0.0, 0.0, 1.0)
        self.elementPriceNode.setFont(ToontownGlobals.getToonFont())
        self.elementPrice = page.attachNewNode(self.elementPriceNode)
        self.elementPrice.setScale(TTLocalizer.PPelementPriceNode)
        self.elementPrice.setPos(self.gui.find('**/step_05_activityPrice_text_locator').getPos() + Point3(-0.02, 0.0, 0.04))
        self.elementDescriptionNode = TextNode('ElementDescription')
        self.elementDescriptionNode.setAlign(TextNode.ACenter)
        self.elementDescriptionNode.setWordwrap(8)
        self.elementDescriptionNode.setFont(ToontownGlobals.getToonFont())
        self.elementDescriptionNode.setTextColor(0.0, 0.0, 0.0, 1.0)
        self.elementDescription = page.attachNewNode(self.elementDescriptionNode)
        self.elementDescription.setScale(TTLocalizer.PPelementDescription)
        self.elementDescription.setPos(self.gui.find('**/step_05_activityDescription_text_locator').getPos() + Point3(0.0, 0.0, 0.04))
        self.totalMoney = base.localAvatar.getTotalMoney()
        catalogGui = loader.loadModel('phase_5.5/models/gui/catalog_gui')
        self.beanBank = DirectLabel(parent=page, relief=None, text=str(self.totalMoney), text_align=TextNode.ARight, text_scale=0.075, text_fg=(0.95, 0.95, 0, 1), text_shadow=(0, 0, 0, 1), text_pos=(0.495, -0.53), text_font=ToontownGlobals.getSignFont(), textMayChange=True, image=catalogGui.find('**/bean_bank'), image_scale=(0.65, 0.65, 0.65), scale=0.9, pos=(-0.75, 0.0, 0.6))
        catalogGui.removeNode()
        del catalogGui
        self.accept(localAvatar.uniqueName('moneyChange'), self.__moneyChange)
        self.accept(localAvatar.uniqueName('bankMoneyChange'), self.__moneyChange)
        self.partyEditor = PartyEditor(self, page)
        self.partyEditor.request('Hidden')
        pos = self.gui.find('**/step_05_add_text_locator').getPos()
        self.elementBuyButton = DirectButton(parent=page, relief=None, text=TTLocalizer.PartyPlannerBuy, text_pos=(pos[0], pos[2]), text_scale=TTLocalizer.PPelementBuyButton, geom=(self.gui.find('**/add_up'), self.gui.find('**/add_down'), self.gui.find('**/add_rollover')), geom3_color=VBase4(0.5, 0.5, 0.5, 1.0), textMayChange=True, pos=(0.0, 0.0, 0.04), command=self.partyEditor.buyCurrentElement)
        self.okWithPartyGroundsLayoutEvent = 'okWithPartyGroundsLayoutEvent'
        self.accept(self.okWithPartyGroundsLayoutEvent, self.okWithPartyGroundsLayout)
        self.okWithGroundsGui = TTDialog.TTGlobalDialog(dialogName=self.uniqueName('PartyEditorOkGui'), doneEvent=self.okWithPartyGroundsLayoutEvent, message=TTLocalizer.PartyPlannerOkWithGroundsLayout, style=TTDialog.YesNo, okButtonText=OTPLocalizer.DialogYes, cancelButtonText=OTPLocalizer.DialogNo)
        self.okWithGroundsGui.doneStatus = ''
        self.okWithGroundsGui.hide()
        return page

    def okWithPartyGroundsLayout(self):
        self.okWithGroundsGui.hide()
        if self.okWithGroundsGui.doneStatus == 'ok':
            self.__nextItem()

    def setNextButtonState(self, enabled):
        if enabled:
            self.nextButton['state'] = DirectGuiGlobals.NORMAL
            self.nextButton.show()
        else:
            self.nextButton['state'] = DirectGuiGlobals.DISABLED
            self.nextButton.hide()

    def _createInvitationPage(self):
        self.__handleHolidays()
        page = DirectFrame(self.frame)
        page.setName('PartyPlannerInvitationPage')
        self.invitationTitleLabel = DirectLabel(parent=page, relief=None, text=TTLocalizer.PartyPlannerConfirmTitle, textMayChange=True, pos=self.gui.find('**/title_locator').getPos(), scale=self.titleScale)
        self.invitationBackground = DirectFrame(parent=page, relief=None, geom=self.gui.find('**/invitationBackground'))
        self.inviteVisual = InviteVisual(page)
        self.selectedInviteThemeLabel = DirectLabel(parent=page, relief=None, pos=self.gui.find('**/step_06_theme_locator').getPos(), text='', text_scale=0.06, textMayChange=True)
        self.nextThemeButton = DirectButton(parent=page, relief=None, geom=(self.gui.find('**/topNext_button/nextButton_up'), self.gui.find('**/topNext_button/nextButton_down'), self.gui.find('**/topNext_button/nextButton_rollover')), command=self.__nextTheme)
        self.prevThemeButton = DirectButton(parent=page, relief=None, geom=(self.gui.find('**/topPrevious_button/previousButton_up'), self.gui.find('**/topPrevious_button/previousButton_down'), self.gui.find('**/topPrevious_button/previousButton_rollover')), command=self.__prevTheme)
        pos = self.gui.find('**/step_06_sendInvitation_locator').getPos()
        self.inviteButton = DirectButton(parent=page, relief=None, geom=(self.gui.find('**/send_up'), self.gui.find('**/send_down'), self.gui.find('**/send_rollover')), text=TTLocalizer.PartyPlannerInviteButton, textMayChange=True, text_scale=0.05, text_pos=(pos[0], pos[2]), command=self.__handleComplete)
        return page

    def __handleHolidays(self):
        self.inviteThemes = list(range(len(PartyGlobals.InviteTheme)))
        if hasattr(base.cr, 'newsManager') and base.cr.newsManager:
            holidayIds = base.cr.newsManager.getHolidayIdList()
            if ToontownGlobals.VALENTINES_DAY not in holidayIds:
                self.inviteThemes.remove(PartyGlobals.InviteTheme.Valentoons)
            if ToontownGlobals.VICTORY_PARTY_HOLIDAY not in holidayIds:
                self.inviteThemes.remove(PartyGlobals.InviteTheme.VictoryParty)
            if ToontownGlobals.WINTER_DECORATIONS not in holidayIds and ToontownGlobals.WACKY_WINTER_DECORATIONS not in holidayIds:
                self.inviteThemes.remove(PartyGlobals.InviteTheme.Winter)

    def _createFarewellPage(self):
        page = DirectFrame(self.frame)
        page.setName('PartyPlannerFarewellPage')
        self.confirmTitleLabel = DirectLabel(parent=page, relief=None, text=TTLocalizer.PartyPlannerConfirmationAllOkTitle, textMayChange=True, pos=self.gui.find('**/title_locator').getPos(), scale=self.titleScale)
        pos = self.gui.find('**/step_07_close_text_locator').getPos()
        self.closePlannerButton = DirectButton(parent=page, relief=None, geom=(self.gui.find('**/close_up'), self.gui.find('**/close_down'), self.gui.find('**/close_rollover')), text=TTLocalizer.PartyPlannerClosePlanner, text_scale=0.055, text_pos=(pos[0], pos[2]), command=self.__acceptExit)
        return page

    def close(self):
        self.ignore('addPartyResponseReceived')
        self.ignore(localAvatar.uniqueName('moneyChange'))
        self.ignore(localAvatar.uniqueName('bankMoneyChange'))
        self.timeInputHourUpButton.destroy()
        self.timeInputHourDownButton.destroy()
        self.timeInputMinuteUpButton.destroy()
        self.timeInputMinuteDownButton.destroy()
        self.timeInputAmPmUpButton.destroy()
        self.timeInputAmPmDownButton.destroy()
        self.privateButton.destroy()
        self.publicButton.destroy()
        self.makePartyNowButton.destroy()
        self.checkAllButton.destroy()
        self.uncheckAllButton.destroy()
        self.elementBuyButton.destroy()
        self.nextThemeButton.destroy()
        self.prevThemeButton.destroy()
        self.inviteButton.destroy()
        self.closePlannerButton.destroy()
        self.ignore(self.okWithPartyGroundsLayoutEvent)
        if hasattr(self, 'okWithGroundsGui'):
            self.okWithGroundsGui.cleanup()
            del self.okWithGroundsGui
        if hasattr(self, 'frame') and not self.frame.isEmpty():
            messenger.send(self.doneEvent)
            self.hide()
            self.cleanup()
            self.friendList.removeAndDestroyAllItems()
            self.friendList.destroy()
            self.calendarGuiMonth.destroy()
            self.frame.destroy()
        self.partyPlannerHead.delete()
        self.partyPlannerHead.removeNode()
        self.clearNametag()
        self.partyEditor.request('Cleanup')
        self.partyEditor = None
        self.destroy()
        del self
        return

    def __handleComplete(self):
        self.inviteButton['state'] = DirectGuiGlobals.DISABLED
        self.prevButton['state'] = DirectGuiGlobals.DISABLED
        endTime = self.partyTime + self.partyDuration
        hostId = base.localAvatar.doId
        self.partyActivities = self.partyEditor.partyEditorGrid.getActivitiesOnGrid()
        decorations = self.partyEditor.partyEditorGrid.getDecorationsOnGrid()
        invitees = self.getInvitees()
        self.accept('addPartyResponseReceived', self.processAddPartyResponse)
        base.cr.partyManager.sendAddParty(hostId, self.partyTime.strftime('%Y-%m-%d %H:%M:%S'), endTime.strftime('%Y-%m-%d %H:%M:%S'), self.isPrivate, self.currentInvitationTheme, self.partyActivities, decorations, invitees)

    def getInvitees(self):
        invitees = []
        for friendBox in self.friendList['items']:
            if friendBox['indicatorValue']:
                invitees.append(friendBox.getPythonTag('id'))

        return invitees

    def processAddPartyResponse(self, hostId, errorCode):
        PartyPlanner.notify.debug('processAddPartyResponse : hostId=%d errorCode=%s' % (hostId, PartyGlobals.AddPartyErrorCode.getString(errorCode)))
        goingBackAllowed = False
        if errorCode == PartyGlobals.AddPartyErrorCode.AllOk:
            goingBackAllowed = False
            self.confirmTitleLabel['text'] = TTLocalizer.PartyPlannerConfirmationAllOkTitle
            if self.noFriends or len(self.getInvitees()) == 0:
                confirmRecapText = TTLocalizer.PartyPlannerConfirmationAllOkTextNoFriends
            else:
                confirmRecapText = TTLocalizer.PartyPlannerConfirmationAllOkText
        elif errorCode == PartyGlobals.AddPartyErrorCode.ValidationError:
            self.confirmTitleLabel['text'] = TTLocalizer.PartyPlannerConfirmationErrorTitle
            confirmRecapText = TTLocalizer.PartyPlannerConfirmationValidationErrorText
        elif errorCode == PartyGlobals.AddPartyErrorCode.DatabaseError:
            self.confirmTitleLabel['text'] = TTLocalizer.PartyPlannerConfirmationErrorTitle
            confirmRecapText = TTLocalizer.PartyPlannerConfirmationDatabaseErrorText
        elif errorCode == PartyGlobals.AddPartyErrorCode.TooManyHostedParties:
            goingBackAllowed = False
            self.confirmTitleLabel['text'] = TTLocalizer.PartyPlannerConfirmationErrorTitle
            confirmRecapText = TTLocalizer.PartyPlannerConfirmationTooManyText
        self.nametagGroup.setChat(confirmRecapText, CFSpeech)
        self.request('Farewell', goingBackAllowed)

    def __acceptExit(self):
        PartyPlanner.notify.debug('__acceptExit')
        if hasattr(self, 'frame'):
            self.hide()
            messenger.send(self.doneEvent)

    def __nextItem(self):
        messenger.send('wakeup')
        if self.state == 'PartyEditor' and self.okWithGroundsGui.doneStatus != 'ok':
            self.okWithGroundsGui.show()
            return
        if self.state == 'PartyEditor' and self.noFriends:
            self.request('Date')
            self.selectedCalendarGuiDay = None
            self.calendarGuiMonth.clearSelectedDay()
            return
        if self.state == 'Guests':
            self.selectedCalendarGuiDay = None
            self.calendarGuiMonth.clearSelectedDay()
        if self.state == 'Time':
            if self.partyTime < base.cr.toontownTimeManager.getCurServerDateTime():
                self.okChooseFutureTimeEvent = 'okChooseFutureTimeEvent'
                self.acceptOnce(self.okChooseFutureTimeEvent, self.okChooseFutureTime)
                self.chooseFutureTimeDialog = TTDialog.TTGlobalDialog(dialogName=self.uniqueName('chooseFutureTimeDialog'), doneEvent=self.okChooseFutureTimeEvent, message=TTLocalizer.PartyPlannerChooseFutureTime, style=TTDialog.Acknowledge)
                self.chooseFutureTimeDialog.show()
                return
        self.requestNext()
        return

    def okChooseFutureTime(self):
        if hasattr(self, 'chooseFutureTimeDialog'):
            self.chooseFutureTimeDialog.cleanup()
            del self.chooseFutureTimeDialog
        if hasattr(self, 'okChooseFutureTimeEvent'):
            self.ignore(self.okChooseFutureTimeEvent)

    def __prevItem(self):
        messenger.send('wakeup')
        if self.state == 'Date' and self.noFriends:
            self.request('PartyEditor')
            return
        if self.state == 'Invitation' and self.selectedCalendarGuiDay is None:
            self.request('Guests')
            return
        self.requestPrev()
        return

    def __moneyChange(self, newMoney):
        if hasattr(self, 'totalMoney'):
            self.totalMoney = base.localAvatar.getTotalMoney()
        if hasattr(self, 'beanBank'):
            self.beanBank['text'] = str(int(self.totalMoney))
Ejemplo n.º 25
0
class ScrolledButtonsList(DirectObject):
    """
       A class to display a list of selectable buttons.
       It is displayed using scrollable window (DirectScrolledFrame).
    """
    def __init__(self, parent=None, frameSize=(.8,1.2), buttonTextColor=(1,1,1,1),
                 font=None, itemScale=.045, itemTextScale=0.85, itemTextZ=0,
                 command=None, contextMenu=None, autoFocus=0,
                 colorChange=1, colorChangeDuration=1, newItemColor=globals.colors['guiblue1'],
                 rolloverColor=globals.colors['guiyellow'],
                 suppressMouseWheel=1, modifier='control'):
        self.mode = None
        self.focusButton=None
        self.command=command
        self.contextMenu=contextMenu
        self.autoFocus=autoFocus
        self.colorChange=colorChange
        self.colorChangeDuration=colorChangeDuration*.5
        self.newItemColor=newItemColor
        self.rolloverColor=rolloverColor
        self.rightClickTextColors=(Vec4(0,1,0,1),Vec4(0,35,100,1))
        self.font=font
        if font:
           self.fontHeight=font.getLineHeight()
        else:
           self.fontHeight=TextNode.getDefaultFont().getLineHeight()
        self.fontHeight*=1.2 # let's enlarge font height a little
        self.xtraSideSpace=.2*self.fontHeight
        self.itemTextScale=itemTextScale
        self.itemTextZ=itemTextZ
        self.buttonTextColor=buttonTextColor
        self.suppressMouseWheel=suppressMouseWheel
        self.modifier=modifier
        self.buttonsList=[]
        self.numItems=0
        self.__eventReceivers={}
        # DirectScrolledFrame to hold items
        self.itemScale=itemScale
        self.itemVertSpacing=self.fontHeight*self.itemScale
        self.frameWidth,self.frameHeight=frameSize
        # I set canvas' Z size smaller than the frame to avoid the auto-generated vertical slider bar
        self.childrenFrame = DirectScrolledFrame(
                     parent=parent,pos=(-self.frameWidth*.5,0,.5*self.frameHeight), relief=DGG.GROOVE,
                     state=DGG.NORMAL, # to create a mouse watcher region
                     frameSize=(0, self.frameWidth, -self.frameHeight, 0), frameColor=(0,0,0,.7),
                     canvasSize=(0, 0, -self.frameHeight*.5, 0), borderWidth=(0.01,0.01),
                     manageScrollBars=0, enableEdit=0, suppressMouse=0, sortOrder=1000 )
        # the real canvas is "self.childrenFrame.getCanvas()",
        # but if the frame is hidden since the beginning,
        # no matter how I set the canvas Z pos, the transform would be resistant,
        # so just create a new node under the canvas to be my canvas
        self.canvas=self.childrenFrame.getCanvas().attachNewNode('myCanvas')
        # slider background
        SliderBG=DirectFrame( parent=self.childrenFrame,frameSize=(-.025,.025,-self.frameHeight,0),
                     frameColor=(0,0,0,.7), pos=(-.03,0,0),enableEdit=0, suppressMouse=0)
        # slider thumb track
        sliderTrack = DirectFrame( parent=SliderBG, relief=DGG.FLAT, #state=DGG.NORMAL,
                     frameColor=(1,1,1,.2), frameSize=(-.015,.015,-self.frameHeight+.01,-.01),
                     enableEdit=0, suppressMouse=0)
        # page up
        self.pageUpRegion=DirectFrame( parent=SliderBG, relief=DGG.FLAT, state=DGG.NORMAL,
                     frameColor=(1,.8,.2,.1), frameSize=(-.015,.015,0,0),
                     enableEdit=0, suppressMouse=0)
        self.pageUpRegion.setAlphaScale(0)
        self.pageUpRegion.bind(DGG.B1PRESS,self.__startScrollPage,[-1])
        self.pageUpRegion.bind(DGG.WITHIN,self.__continueScrollUp)
        self.pageUpRegion.bind(DGG.WITHOUT,self.__suspendScrollUp)
        # page down
        self.pageDnRegion=DirectFrame( parent=SliderBG, relief=DGG.FLAT, state=DGG.NORMAL,
                     frameColor=(1,.8,.2,.1), frameSize=(-.015,.015,0,0),
                     enableEdit=0, suppressMouse=0)
        self.pageDnRegion.setAlphaScale(0)
        self.pageDnRegion.bind(DGG.B1PRESS,self.__startScrollPage,[1])
        self.pageDnRegion.bind(DGG.WITHIN,self.__continueScrollDn)
        self.pageDnRegion.bind(DGG.WITHOUT,self.__suspendScrollDn)
        self.pageUpDnSuspended=[0,0]
        # slider thumb
        self.vertSliderThumb=DirectButton(parent=SliderBG, relief=DGG.FLAT,
                     frameColor=(1,1,1,.6), frameSize=(-.015,.015,0,0),
                     enableEdit=0, suppressMouse=0, rolloverSound=None, clickSound=None)
        self.vertSliderThumb.bind(DGG.B1PRESS,self.__startdragSliderThumb)
        self.vertSliderThumb.bind(DGG.WITHIN,self.__enteringThumb)
        self.vertSliderThumb.bind(DGG.WITHOUT,self.__exitingThumb)
        self.oldPrefix=base.buttonThrowers[0].node().getPrefix()
        self.sliderThumbDragPrefix='draggingSliderThumb-'
        # GOD & I DAMN IT !!!
        # These things below don't work well if the canvas has a lot of buttons.
        # So I end up checking the mouse region every frame by myself using a continuous task.
  #       self.accept(DGG.WITHIN+self.childrenFrame.guiId,self.__enteringFrame)
  #       self.accept(DGG.WITHOUT+self.childrenFrame.guiId,self.__exitingFrame)
        self.isMouseInRegion=False
        self.mouseOutInRegionCommand=(self.__exitingFrame,self.__enteringFrame)
        taskMgr.doMethodLater(.2,self.__getFrameRegion,'getFrameRegion')
  
    def __getFrameRegion(self,t):
        for g in range(base.mouseWatcherNode.getNumGroups()):
            region=base.mouseWatcherNode.getGroup(g).findRegion(self.childrenFrame.guiId)
            if region!=None:
               self.frameRegion=region
               taskMgr.add(self.__mouseInRegionCheck,'mouseInRegionCheck')
               break
  
    def __mouseInRegionCheck(self,t):
        """
           check if the mouse is within or without the scrollable frame, and
           upon within or without, run the provided command
        """
        if not base.mouseWatcherNode.hasMouse(): return Task.cont
        m=base.mouseWatcherNode.getMouse()
        bounds=self.frameRegion.getFrame()
        inRegion=bounds[0]<m[0]<bounds[1] and bounds[2]<m[1]<bounds[3]
        if self.isMouseInRegion==inRegion: return Task.cont
        self.isMouseInRegion=inRegion
        self.mouseOutInRegionCommand[inRegion]()
        return Task.cont
  
    def __startdragSliderThumb(self,m=None):
        if self.mode != None:
            if hasattr(self.mode, 'enableMouseCamControl') == 1:
                if self.mode.enableMouseCamControl == 1:
                    self.mode.game.app.disableMouseCamControl()
        mpos=base.mouseWatcherNode.getMouse()
        parentZ=self.vertSliderThumb.getParent().getZ(render2d)
        sliderDragTask=taskMgr.add(self.__dragSliderThumb,'dragSliderThumb')
        sliderDragTask.ZposNoffset=mpos[1]-self.vertSliderThumb.getZ(render2d)+parentZ
  #       sliderDragTask.mouseX=base.winList[0].getPointer(0).getX()
        self.oldPrefix=base.buttonThrowers[0].node().getPrefix()
        base.buttonThrowers[0].node().setPrefix(self.sliderThumbDragPrefix)
        self.acceptOnce(self.sliderThumbDragPrefix+'mouse1-up',self.__stopdragSliderThumb)
  
    def __dragSliderThumb(self,t):
        if not base.mouseWatcherNode.hasMouse():
           return
        mpos=base.mouseWatcherNode.getMouse()
  #       newY=base.winList[0].getPointer(0).getY()
        self.__updateCanvasZpos((t.ZposNoffset-mpos[1])/self.canvasRatio)
  #       base.winList[0].movePointer(0, t.mouseX, newY)
        return Task.cont
  
    def __stopdragSliderThumb(self,m=None):
        if self.mode != None:
            if hasattr(self.mode, 'enableMouseCamControl') == 1:
                if self.mode.enableMouseCamControl == 1:
                    self.mode.game.app.enableMouseCamControl()
        taskMgr.remove('dragSliderThumb')
        self.__stopScrollPage()
        base.buttonThrowers[0].node().setPrefix(self.oldPrefix)
        if self.isMouseInRegion:
           self.mouseOutInRegionCommand[self.isMouseInRegion]()
  
    def __startScrollPage(self,dir,m):
        self.oldPrefix=base.buttonThrowers[0].node().getPrefix()
        base.buttonThrowers[0].node().setPrefix(self.sliderThumbDragPrefix)
        self.acceptOnce(self.sliderThumbDragPrefix+'mouse1-up',self.__stopdragSliderThumb)
        t=taskMgr.add(self.__scrollPage,'scrollPage',extraArgs=[int((dir+1)*.5),dir*.01/self.canvasRatio])
        self.pageUpDnSuspended=[0,0]
  
    def __scrollPage(self,dir,scroll):
        if not self.pageUpDnSuspended[dir]:
           self.__scrollCanvas(scroll)
        return Task.cont
  
    def __stopScrollPage(self,m=None):
        taskMgr.remove('scrollPage')
  
    def __suspendScrollUp(self,m=None):
        self.pageUpRegion.setAlphaScale(0)
        self.pageUpDnSuspended[0]=1
    def __continueScrollUp(self,m=None):
        if taskMgr.hasTaskNamed('dragSliderThumb'):
           return
        self.pageUpRegion.setAlphaScale(1)
        self.pageUpDnSuspended[0]=0
   
    def __suspendScrollDn(self,m=None):
        self.pageDnRegion.setAlphaScale(0)
        self.pageUpDnSuspended[1]=1
    def __continueScrollDn(self,m=None):
        if taskMgr.hasTaskNamed('dragSliderThumb'):
           return
        self.pageDnRegion.setAlphaScale(1)
        self.pageUpDnSuspended[1]=0
  
    def __suspendScrollPage(self,m=None):
        self.__suspendScrollUp()
        self.__suspendScrollDn()
   
    def __enteringThumb(self,m=None):
        self.vertSliderThumb['frameColor']=(1,1,1,1)
        self.__suspendScrollPage()
  
    def __exitingThumb(self,m=None):
        self.vertSliderThumb['frameColor']=(1,1,1,.6)
  
    def __scrollCanvas(self,scroll):
        if self.vertSliderThumb.isHidden() or self.buttonsList == []:
           return
        self.__updateCanvasZpos(self.canvas.getZ()+scroll)
  
    def __updateCanvasZpos(self,Zpos):
        newZ=clampScalar(Zpos, .0, self.canvasLen-self.frameHeight+.015)
        self.canvas.setZ(newZ)
        thumbZ=-newZ*self.canvasRatio
        self.vertSliderThumb.setZ(thumbZ)
        self.pageUpRegion['frameSize']=(-.015,.015,thumbZ-.01,-.01)
        self.pageDnRegion['frameSize']=(-.015,.015,-self.frameHeight+.01,thumbZ+self.vertSliderThumb['frameSize'][2])
  
    def __adjustCanvasLength(self,numItem):
        self.canvasLen=float(numItem)*self.itemVertSpacing
        self.canvasRatio=(self.frameHeight-.015)/(self.canvasLen+.01)
        if self.canvasLen<=self.frameHeight-.015:
           canvasZ=.0
           self.vertSliderThumb.hide()
           self.pageUpRegion.hide()
           self.pageDnRegion.hide()
           self.canvasLen=self.frameHeight-.015
        else:
           canvasZ=self.canvas.getZ()
           self.vertSliderThumb.show()
           self.pageUpRegion.show()
           self.pageDnRegion.show()
        self.__updateCanvasZpos(canvasZ)
        self.vertSliderThumb['frameSize']=(-.015,.015,-self.frameHeight*self.canvasRatio,-.01)
        thumbZ=self.vertSliderThumb.getZ()
        self.pageUpRegion['frameSize']=(-.015,.015,thumbZ-.01,-.01)
        self.pageDnRegion['frameSize']=(-.015,.015,-self.frameHeight+.01,thumbZ+self.vertSliderThumb['frameSize'][2])
  
    def __acceptAndIgnoreWorldEvent(self,event,command,extraArgs=[]):
        receivers=messenger.whoAccepts(event)
        if receivers is None:
           self.__eventReceivers[event]={}
        else:
           self.__eventReceivers[event]=receivers.copy()
        for r in self.__eventReceivers[event].keys():
            if type(r) != types.TupleType:
                r.ignore(event)
        self.accept(event,command,extraArgs)
  
    def __ignoreAndReAcceptWorldEvent(self,events):
        for event in events:
            self.ignore(event)
            if self.__eventReceivers.has_key(event):
               for r, method_xtraArgs_persist in self.__eventReceivers[event].items():
                   if type(r) != types.TupleType:
                       messenger.accept(event,r,*method_xtraArgs_persist)
            self.__eventReceivers[event]={}
  
    def __enteringFrame(self,m=None):
        # sometimes the WITHOUT event for page down region doesn't fired,
        # so directly suspend the page scrolling here
        self.__suspendScrollPage()
        BTprefix=base.buttonThrowers[0].node().getPrefix()
        if BTprefix==self.sliderThumbDragPrefix:
           return
        self.inOutBTprefix=BTprefix
        if self.suppressMouseWheel:
           self.__acceptAndIgnoreWorldEvent(self.inOutBTprefix+'wheel_up',
                command=self.__scrollCanvas, extraArgs=[-.07])
           self.__acceptAndIgnoreWorldEvent(self.inOutBTprefix+'wheel_down',
                command=self.__scrollCanvas, extraArgs=[.07])
        else:
           self.accept(self.inOutBTprefix+self.modifier+'-wheel_up',self.__scrollCanvas, [-.07])
           self.accept(self.inOutBTprefix+self.modifier+'-wheel_down',self.__scrollCanvas, [.07])
  
    def __exitingFrame(self,m=None):
        if not hasattr(self,'inOutBTprefix'):
           return
        if self.suppressMouseWheel:
           self.__ignoreAndReAcceptWorldEvent( (
                                               self.inOutBTprefix+'wheel_up',
                                               self.inOutBTprefix+'wheel_down',
                                               ) )
        else:
           self.ignore(self.inOutBTprefix+self.modifier+'-wheel_up')
           self.ignore(self.inOutBTprefix+self.modifier+'-wheel_down')
  
    def __setFocusButton(self,button,item):
        if self.focusButton:
           self.restoreNodeButton2Normal()
        self.focusButton=button
        self.highlightNodeButton()
        if callable(self.command) and button in self.buttonsList:
           # run user command and pass the selected item, it's index, and the button
           self.command(item,self.buttonsList.index(button),button)
  
    def __rightPressed(self,button,m):
        self.__isRightIn=True
  #       text0 : normal
  #       text1 : pressed
  #       text2 : rollover
  #       text3 : disabled
        button._DirectGuiBase__componentInfo['text2'][0].setColorScale(self.rightClickTextColors[self.focusButton==button])
        button.bind(DGG.B3RELEASE,self.__rightReleased,[button])
        button.bind(DGG.WITHIN,self.__rightIn,[button])
        button.bind(DGG.WITHOUT,self.__rightOut,[button])
  
    def __rightIn(self,button,m):
        self.__isRightIn=True
        button._DirectGuiBase__componentInfo['text2'][0].setColorScale(self.rightClickTextColors[self.focusButton==button])
    def __rightOut(self,button,m):
        self.__isRightIn=False
        button._DirectGuiBase__componentInfo['text2'][0].setColorScale(Vec4(1,1,1,1))
  
    def __rightReleased(self,button,m):
        button.unbind(DGG.B3RELEASE)
        button.unbind(DGG.WITHIN)
        button.unbind(DGG.WITHOUT)
        button._DirectGuiBase__componentInfo['text2'][0].setColorScale(self.rolloverColor)
        if not self.__isRightIn:
           return
        if callable(self.contextMenu):
           # run user command and pass the selected item, it's index, and the button
           self.contextMenu(button['extraArgs'][1],self.buttonsList.index(button),button)

    def scrollToBottom(self):
        ##for i in range(0,self.numItems):
        self.__scrollCanvas(1)

    def selectButton(self, button, item):
        self.__setFocusButton(button, item)
  
    def restoreNodeButton2Normal(self):
        """
           stop highlighting item
        """
        if self.focusButton != None:
            #self.focusButton['text_fg']=(1,1,1,1)
            self.focusButton['frameColor']=(0,0,0,0)
  
    def highlightNodeButton(self,idx=None):
        """
           highlight the item
        """
        if idx is not None:
            self.focusButton=self.buttonsList[idx]
        #self.focusButton['text_fg']=(.01,.01,.01,1)
        # nice dark blue.  don't mess with the text fg color though! we want it custom
        self.focusButton['frameColor']=(0,.3,.8,1)
  
    def clear(self):
        """
           clear the list
        """
        for c in self.buttonsList:
            c.remove()
        self.buttonsList=[]
        self.focusButton=None
        self.numItems=0
  
    def addItem(self,text,extraArgs=None,atIndex=None,textColorName=None):
        """
           add item to the list
           text : text for the button
           extraArgs : the object which will be passed to user command(s)
                       (both command and contextMenu) when the button get clicked
           atIndex : where to add the item
                     <None> : put item at the end of list
                     <integer> : put item at index <integer>
                     <button> : put item at <button>'s index
            textColorName : the color name eg. 'yellow'
        """
        textColor = self.buttonTextColor
        if textColorName != None:
            textColor = globals.colors[textColorName]
            
        button = DirectButton(parent=self.canvas,
            scale=self.itemScale,
            relief=DGG.FLAT,
            frameColor=(0,0,0,0),text_scale=self.itemTextScale,
            text=text, text_pos=(0,self.itemTextZ),text_fg=textColor,
            text_font=self.font, text_align=TextNode.ALeft,
            command=self.__setFocusButton,
            enableEdit=0, suppressMouse=0, rolloverSound=None,clickSound=None)
        #button.setMyMode(self.mode)
        l,r,b,t=button.getBounds()
        # top & bottom are blindly set without knowing where exactly the baseline is,
        # but this ratio fits most fonts
        baseline=-self.fontHeight*.25
        #button['saved_color'] = textColor
        button['frameSize']=(l-self.xtraSideSpace,r+self.xtraSideSpace,baseline,baseline+self.fontHeight)
  
  #          Zc=NodePath(button).getBounds().getCenter()[1]-self.fontHeight*.5+.25
  # #          Zc=button.getCenter()[1]-self.fontHeight*.5+.25
  #          button['frameSize']=(l-self.xtraSideSpace,r+self.xtraSideSpace,Zc,Zc+self.fontHeight)
       
        button['extraArgs']=[button,extraArgs]
        button._DirectGuiBase__componentInfo['text2'][0].setColorScale(self.rolloverColor)
        button.bind(DGG.B3PRESS,self.__rightPressed,[button])
        if isinstance(atIndex,DirectButton):
           if atIndex.isEmpty():
              atIndex=None
           else:
              index=self.buttonsList.index(atIndex)
              self.buttonsList.insert(index,button)
        if atIndex==None:
           self.buttonsList.append(button)
           index=self.numItems
        elif type(atIndex)==IntType:
           index=atIndex
           self.buttonsList.insert(index,button)
        Zpos=(-.7-index)*self.itemVertSpacing
        button.setPos(.02,0,Zpos)
        if index!=self.numItems:
           for i in range(index+1,self.numItems+1):
               self.buttonsList[i].setZ(self.buttonsList[i],-self.fontHeight)
        self.numItems+=1
        self.__adjustCanvasLength(self.numItems)
        if self.autoFocus:
           self.focusViewOnItem(index)
        if self.colorChange:
           Sequence(
              button.colorScaleInterval(self.colorChangeDuration,self.newItemColor,globals.colors['guiblue3']),
              button.colorScaleInterval(self.colorChangeDuration,Vec4(1,1,1,1),self.newItemColor)
              ).start()
  
    def focusViewOnItem(self,idx):
        """
           Scroll the window so the newly added item will be displayed
           in the middle of the window, if possible.
        """
        Zpos=(idx+.7)*self.itemVertSpacing-self.frameHeight*.5
        self.__updateCanvasZpos(Zpos)
       
    def setAutoFocus(self,b):
        """
           set auto-view-focus state of newly added item
        """
        self.autoFocus=b
  
    def index(self,button):
        """
           get the index of button
        """
        if not button in self.buttonsList:
           return None
        return self.buttonsList.index(button)
       
    def getNumItems(self):
        """
           get the current number of items on the list
        """
        return self.numItems
  
    def disableItem(self,i):
        if not 0<=i<self.numItems:
           print 'DISABLING : invalid index (%s)' %i
           return
        self.buttonsList[i]['state']=DGG.DISABLED
        self.buttonsList[i].setColorScale(.3,.3,.3,1)
   
    def enableItem(self,i):
        if not 0<=i<self.numItems:
           print 'ENABLING : invalid index (%s)' %i
           return
        self.buttonsList[i]['state']=DGG.NORMAL
        self.buttonsList[i].setColorScale(1,1,1,1)
  
    def removeItem(self,index):
        if not 0<=index<self.numItems:
           print 'REMOVAL : invalid index (%s)' %index
           return
        if self.numItems==0: return
        if self.focusButton==self.buttonsList[index]:
           self.focusButton=None
        self.buttonsList[index].removeNode()
        del self.buttonsList[index]
        self.numItems-=1
        for i in range(index,self.numItems):
            self.buttonsList[i].setZ(self.buttonsList[i],self.fontHeight)
        self.__adjustCanvasLength(self.numItems)
  
    def destroy(self):
        self.clear()
        self.__exitingFrame()
        self.ignoreAll()
        self.childrenFrame.removeNode()
        taskMgr.remove('mouseInRegionCheck')
  
    def hide(self):
        self.childrenFrame.hide()
        self.isMouseInRegion=False
        self.__exitingFrame()
        taskMgr.remove('mouseInRegionCheck')
  
    def show(self):
        self.childrenFrame.show()
        if not hasattr(self,'frameRegion'):
           taskMgr.doMethodLater(.2,self.__getFrameRegion,'getFrameRegion')
        elif not taskMgr.hasTaskNamed('mouseInRegionCheck'):
           taskMgr.add(self.__mouseInRegionCheck,'mouseInRegionCheck')
  
    def toggleVisibility(self):
        if self.childrenFrame.isHidden():
           self.show()
        else:
           self.hide()
  
    def setMyMode(self, myMode):
        self.mode = myMode
Ejemplo n.º 26
0
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")
Ejemplo n.º 27
0
class LaffShopGui(DirectFrame):

    def __init__(self):
        DirectFrame.__init__(self, parent=aspect2d, relief=None, geom=DGG.getDefaultDialogGeom(), geom_color=ToontownGlobals.GlobalDialogColor, geom_scale=(1.33, 1, 1.3), pos=(0, 0, 0), text='', text_scale=0.07, text_pos=(0, 0.475))
        self.initialiseoptions(LaffShopGui)
        
        self.additionalLaff = 0
        self.timer = ToontownTimer.ToontownTimer()
        self.timer.reparentTo(aspect2d)
        self.timer.posInTopRightCorner()
        self.timer.countdown(LaffRestockGlobals.TIMER_SECONDS, self.__cancel, [LaffRestockGlobals.TIMER_END])
        self.setupButtons()
        self.bindButtons()
        self.laffMeter = LaffMeter.LaffMeter(base.localAvatar.style, base.localAvatar.getHp(), base.localAvatar.getMaxHp())
        self.laffMeter.reparentTo(self)
        self.laffMeter.setPos(0, 0, 0.065)
        self.laffMeter.setScale(0.13)
        self.__updateLaffMeter(1)

    def setupButtons(self):
        buttons = loader.loadModel('phase_3/models/gui/dialog_box_buttons_gui')
        arrowGui = loader.loadModel('phase_3/models/gui/create_a_toon_gui')
        arrowImageList = (arrowGui.find('**/CrtATn_R_Arrow_UP'), arrowGui.find('**/CrtATn_R_Arrow_DN'), arrowGui.find('**/CrtATn_R_Arrow_RLVR'), arrowGui.find('**/CrtATn_R_Arrow_UP'))

        self.cancelButton = DirectButton(parent=self, relief=None, image=(buttons.find('**/CloseBtn_UP'), buttons.find('**/CloseBtn_DN'), buttons.find('**/CloseBtn_Rllvr')), pos=(-0.2, 0, -0.5), text=OTPLocalizer.lCancel, text_scale=0.06, text_pos=(0, -0.1), command=self.__cancel, extraArgs=[LaffRestockGlobals.USER_CANCEL])
        self.okButton = DirectButton(parent=self, relief=None, image=(buttons.find('**/ChtBx_OKBtn_UP'), buttons.find('**/ChtBx_OKBtn_DN'), buttons.find('**/ChtBx_OKBtn_Rllvr')), pos=(0.2, 0, -0.5), text=OTPLocalizer.lOK, text_scale=0.06, text_pos=(0, -0.1), command=self.__restock)
        self.upArrow = DirectButton(parent=self, relief=None, image=arrowImageList, image_scale=(1, 1, 1), image3_color=Vec4(0.6, 0.6, 0.6, 0.25), pos=(0.2, 0, -0.265))
        self.downArrow = DirectButton(parent=self, relief=None, image=arrowImageList, image_scale=(-1, 1, 1), image3_color=Vec4(0.6, 0.6, 0.6, 0.25), pos=(-0.2, 0, -0.265))

        buttons.removeNode()
        arrowGui.removeNode()

    def bindButtons(self):
        self.downArrow.bind(DGG.B1PRESS, self.__taskUpdate, extraArgs=[-1])
        self.downArrow.bind(DGG.B1RELEASE, self.__taskDone)
        self.upArrow.bind(DGG.B1PRESS, self.__taskUpdate, extraArgs=[1])
        self.upArrow.bind(DGG.B1RELEASE, self.__taskDone)

    def destroy(self):
        self.ignoreAll()

        if self.timer:
            self.timer.destroy()

        taskMgr.remove(self.taskName('runLaffCounter'))
        DirectFrame.destroy(self)

    def __cancel(self, state):
        self.destroy()
        messenger.send('laffShopDone', [state, 0])

    def __restock(self):
        self.destroy()
        messenger.send('laffShopDone', [LaffRestockGlobals.RESTOCK, self.additionalLaff])

    def __updateLaffMeter(self, amount):
        self.additionalLaff += amount
        hitLimit = 0
        newLaff = base.localAvatar.getHp() + self.additionalLaff

        if (newLaff - 1) <= base.localAvatar.getHp():
            self.downArrow['state'] = DGG.DISABLED
            hitLimit = 1
        else:
            self.downArrow['state'] = DGG.NORMAL

        if newLaff >= base.localAvatar.getMaxHp():
            self.upArrow['state'] = DGG.DISABLED
            hitLimit = 1
        else:
            self.upArrow['state'] = DGG.NORMAL

        cost = self.additionalLaff * ToontownGlobals.CostPerLaffRestock
        self['text'] = TTLocalizer.RestockAskMessage % (self.additionalLaff, cost)

        if cost > base.localAvatar.getTotalMoney():
            self.okButton['state'] = DGG.DISABLED
            self['text'] += TTLocalizer.RestockNoMoneyGuiMessage
        else:
            self.okButton['state'] = DGG.NORMAL

        self.laffMeter.hp = newLaff
        self.laffMeter.start()

        return hitLimit

    def __runTask(self, task):
        if task.time - task.prevTime < task.delayTime:
            return Task.cont
        else:
            task.delayTime = max(0.05, task.delayTime * 0.75)
            task.prevTime = task.time
            hitLimit = self.__updateLaffMeter(task.delta)

            return Task.done if hitLimit else Task.cont

    def __taskDone(self, event):
        messenger.send('wakeup')
        taskMgr.remove(self.taskName('runLaffCounter'))

    def __taskUpdate(self, delta, event):
        messenger.send('wakeup')

        task = Task(self.__runTask)
        task.delayTime = 0.4
        task.prevTime = 0.0
        task.delta = delta
        hitLimit = self.__updateLaffMeter(delta)

        if not hitLimit:
            taskMgr.add(task, self.taskName('runLaffCounter'))
class GloveShopGui:

    def __init__(self):
        self.index = 0
        self.id = time.time()
        self.lastGlove = base.localAvatar.style.gloveColor
        self.timer = ToontownTimer.ToontownTimer()
        self.timer.reparentTo(aspect2d)
        self.timer.posInTopRightCorner()
        self.timer.countdown(GloveNPCGlobals.TIMER_SECONDS, self.__exit, [GloveNPCGlobals.TIMER_END])
        self.setupButtons()
        self.bindButtons()
        self.__updateIndex(0)

    def setupButtons(self):
        gui = loader.loadModel('phase_3/models/gui/tt_m_gui_mat_mainGui')
        arrowImage = (gui.find('**/tt_t_gui_mat_shuffleArrowUp'), gui.find('**/tt_t_gui_mat_shuffleArrowDown'))
        buttonImage = (gui.find('**/tt_t_gui_mat_shuffleUp'), gui.find('**/tt_t_gui_mat_shuffleDown'))

        self.title = DirectLabel(aspect2d, relief=None, text=TTLocalizer.GloveGuiTitle,
                     text_fg=(0, 1, 0, 1), text_scale=0.15, text_font=ToontownGlobals.getSignFont(),
                     pos=(0, 0, -0.30), text_shadow=(1, 1, 1, 1))

        self.notice = DirectLabel(aspect2d, relief=None, text='', text_fg=(1, 0, 0, 1), text_scale=0.11,
                      text_font=ToontownGlobals.getSignFont(), pos=(0, 0, -0.45), text_shadow=(1, 1, 1, 1))

        self.color = DirectLabel(aspect2d, relief=None, text='', text_scale=0.11, text_font=ToontownGlobals.getSignFont(),
                     pos=(0, 0, -0.70), text_shadow=(1, 1, 1, 1))

        self.buyButton = DirectButton(aspect2d, relief=None, image=buttonImage, text=TTLocalizer.GloveGuiBuy,
                         text_font=ToontownGlobals.getInterfaceFont(), text_scale=0.11, text_pos=(0, -0.02),
                         pos=(-0.60, 0, -0.90), text_fg=(1, 1, 1, 1), text_shadow=(0, 0, 0, 1), command=self.__exit, extraArgs=[GloveNPCGlobals.CHANGE])

        self.cancelButton = DirectButton(aspect2d, relief=None, image=buttonImage, text=TTLocalizer.lCancel,
                            text_font=ToontownGlobals.getInterfaceFont(), text_scale=0.11, text_pos=(0, -0.02),
                            pos=(0.60, 0, -0.90), text_fg=(1, 1, 1, 1), text_shadow=(0, 0, 0, 1), command=self.__exit, extraArgs=[GloveNPCGlobals.USER_CANCEL])

        self.downArrow = DirectButton(aspect2d, relief=None, image=arrowImage, pos=(-0.60, 0, -0.66))
        self.upArrow = DirectButton(aspect2d, relief=None, image=arrowImage, pos=(0.60, 0, -0.66), scale=-1)

        gui.removeNode()

    def bindButtons(self):
        self.downArrow.bind(DGG.B1PRESS, self.__taskUpdate, extraArgs=[-1])
        self.downArrow.bind(DGG.B1RELEASE, self.__taskDone)
        self.upArrow.bind(DGG.B1PRESS, self.__taskUpdate, extraArgs=[1])
        self.upArrow.bind(DGG.B1RELEASE, self.__taskDone)

    def destroy(self):
        if self.timer:
            self.timer.destroy()

        if not hasattr(self, 'title'):
            return

        # TODO: DirectDialog-ify
        self.title.destroy()
        self.notice.destroy()
        self.color.destroy()
        self.buyButton.destroy()
        self.cancelButton.destroy()
        self.downArrow.destroy()
        self.upArrow.destroy()
        del self.title
        del self.notice
        del self.color
        del self.buyButton
        del self.cancelButton
        del self.downArrow
        del self.upArrow

        taskMgr.remove('runGloveCounter-%s' % self.id)

    def setClientGlove(self, color):
        dna = base.localAvatar.style

        dna.gloveColor = color
        base.localAvatar.setDNA(dna)

    def __exit(self, state):
        self.destroy()
        self.setClientGlove(self.lastGlove)
        messenger.send('gloveShopDone', [state, self.index if state == GloveNPCGlobals.CHANGE else 0])

    def __updateIndex(self, offset):
        self.index += offset
        hitLimit = 0

        if self.index <= 0:
            self.downArrow['state'] = DGG.DISABLED
            hitLimit = 1
        else:
            self.downArrow['state'] = DGG.NORMAL

        if (self.index + 1) >= len(TTLocalizer.NumToColor):
            self.upArrow['state'] = DGG.DISABLED
            hitLimit = 1
        else:
            self.upArrow['state'] = DGG.NORMAL

        if self.lastGlove == self.index:
            self.buyButton['state'] = DGG.DISABLED
            self.notice['text'] = TTLocalizer.GloveGuiSameColor
        else:
            self.buyButton['state'] = DGG.NORMAL
            self.notice['text'] = TTLocalizer.GloveGuiNotice % ToontownGlobals.GloveCost

        self.color['text'] = TTLocalizer.NumToColor[self.index]
        self.color['text_fg'] = ToonDNA.allColorsList[self.index]
        self.setClientGlove(self.index)
        return hitLimit

    def __runTask(self, task):
        if task.time - task.prevTime < task.delayTime:
            return Task.cont
        else:
            task.delayTime = max(0.05, task.delayTime * 0.75)
            task.prevTime = task.time
            hitLimit = self.__updateIndex(task.delta)

            return Task.done if hitLimit else Task.cont

    def __taskDone(self, event):
        messenger.send('wakeup')
        taskMgr.remove('runGloveCounter-%s' % self.id)

    def __taskUpdate(self, delta, event):
        messenger.send('wakeup')

        task = Task(self.__runTask)
        task.delayTime = 0.4
        task.prevTime = 0.0
        task.delta = delta
        hitLimit = self.__updateIndex(delta)

        if not hitLimit:
            taskMgr.add(task, 'runGloveCounter-%s' % self.id)
Ejemplo n.º 29
0
class DirectWindow( DirectFrame ):
  def __init__( self
              , pos         = ( -.5, .5)
              , title       = 'Title'
              , bgColor  = (.5,.5,.5,1)
              , buttonColor = (1,1,1,1) #( .6, .6, .6, 1 )
              #, minSize     = ( .5, .5 )
              #, maxSize     = ( 1, 1 )
              , minWindowSize = (0,0)
              , maxWindowSize = (10000,10000)
              , virtualSize = (1,1)
              , windowBorderTextureFiles = [ DEFAULT_TITLE_TEXTURE_LEFT
                                       , DEFAULT_TITLE_TEXTURE_CENTER
                                       , DEFAULT_TITLE_TEXTURE_RIGHT
                                       , DEFAULT_RESIZE_GEOM ]
              , windowBorderGeomFiles = [ DEFAULT_TITLE_GEOM_RIGHT ]
              , windowColors    = [ ( 1, 1, 1, 1 )
                                  , ( 1, 1, 1, 1 )
                                  , ( 1, 1, 1, 1 )
                                  , ( 1, 1, 1, 1 ) ]
              , borderSize = 0.01
              , dragbarSize = 0.05
              , parent=None):
    self.windowPos = pos
    self.minWindowSize = minWindowSize
    self.maxWindowSize = maxWindowSize
    self.virtualSize = virtualSize
    self.borderSize = borderSize
    self.dragbarSize = dragbarSize
    
    if parent is None:
      parent=aspect2d
    self.parent=parent
    
    self.previousSize = (10,10)
    self.collapsed = False
    
    # maybe we should check if aspect2d doesnt already contain the aspect2dMouseNode
    self.mouseNode = self.parent.attachNewNode( 'aspect2dMouseNode', sort = 999999 )
    taskMgr.add( self.mouseNodeTask, 'mouseNodeTask' )
    
    windowBorderTextures = list()
    for windowBorder in windowBorderTextureFiles:
      if windowBorder is not None:
        mdlFile = loader.loadTexture(windowBorder)
        windowBorderTextures.append(mdlFile)
      else:
        windowBorderTextures.append(None)
    windowBorderGeoms = list()
    for windowGeom in windowBorderGeomFiles:
      if windowGeom is not None:
        mdlFile = loader.loadModel(windowGeom)
        mdls = ( mdlFile.find('**/**-default'),
                 mdlFile.find('**/**-click'),
                 mdlFile.find('**/**-rollover'),
                 mdlFile.find('**/**-disabled') )
        windowBorderGeoms.append(mdls)
      else:
        windowBorderGeoms.append((None,None,None,None,),)
    
    # the main window we want to move around
    self.parentWindow = DirectFrame(
      parent=self.parent, pos=(self.windowPos[0], 0, self.windowPos[1]),
      #frameSize=# is defined in resize
      scale=(1, 1, -1),
      frameColor=bgColor,
      borderWidth=(0, 0), relief=DGG.FLAT, sortOrder=1, )
    
    # header of the window (drag&drop with it)
    # the title part of the window, drag around to move the window
    self.headerParent = DirectButton(
        parent=self.parentWindow, pos=(0, 0, 0), 
        #frameSize=# is defined in resize
        scale=(1, 1, self.dragbarSize),
        frameColor=(1, 1, 1, 1), 
        borderWidth=(0, 0), relief=DGG.FLAT, )
    self.headerParent.bind(DGG.B1PRESS,self.startWindowDrag)
    # images in the headerParent
    self.headerCenter = DirectFrame(
        parent=self.headerParent, pos=(0, 0, 1),
        #frameSize=# is defined in resize
        scale=(1,1,-1),
        frameColor=windowColors[1], frameTexture=windowBorderTextures[1],
        borderWidth=(0, 0), relief=DGG.FLAT, )
    self.headerLeft = DirectFrame(
        parent=self.headerParent, pos=(0, 0, 1),
        frameSize=(0, self.dragbarSize, 0, 1), scale=(1,1,-1),
        frameColor=windowColors[0], frameTexture=windowBorderTextures[0],
        borderWidth=(0, 0), relief=DGG.FLAT, )
    # collapse button
    self.headerRight = DirectButton(
        parent=self.headerParent, #pos=# is defined in resize
        frameSize=(0, self.dragbarSize, 0, 1), scale=(1,1,-1),
        frameColor=windowColors[2], #frameTexture=windowBorderTextures[2],
        borderWidth=(0, 0), relief=DGG.FLAT,
        command=self.toggleCollapsed,
        geom=windowBorderGeoms[0], geom_scale=(self.dragbarSize,1,1) )
    # the resize button of the window
    self.resizeButton = DirectButton(
        parent=self.parentWindow, pos=(1-self.dragbarSize, 0, 1),
        frameSize=(0, 1, 0, 1), scale=(self.dragbarSize,1,-self.dragbarSize),
        frameColor=windowColors[3], frameTexture=windowBorderTextures[3],
        borderWidth=(0, 0), relief=DGG.FLAT, sortOrder=1, )
    self.resizeButton.bind(DGG.B1PRESS,self.startResizeDrag)
    # text in the center of the window
    text = TextNode('WindowTitleTextNode')
    text.setText(title)
    text.setAlign(TextNode.ACenter)
    text.setTextColor( 0, 0, 0, 1 )
    text.setShadow(0.05, 0.05)
    text.setShadowColor( 1, 1, 1, 1 )
    self.textNodePath = self.headerCenter.attachNewNode(text)
    self.textNodePath.setPos(.5,0,.3)
    self.textNodePath.setScale(0.8*self.dragbarSize,1,0.8)
    
    if Y_INVERTED:
      scale = (1,1,-1)
    else:
      scale = (1,1,1)
    # the content part of the window, put stuff beneath
    # contentWindow.getCanvas() to put it into it
    self.contentWindow = DirectScrolledFrame(
        parent       = self.parentWindow,
        #pos          = # is defined in resize
        scale        = scale,
        canvasSize   = (0,self.virtualSize[0],0,self.virtualSize[1]),
        frameColor   = buttonColor,
        relief       = DGG.RAISED,
        borderWidth  = (0,0),
        verticalScroll_frameSize                = [0,self.dragbarSize,0,1],
        verticalScroll_frameTexture             = loader.loadTexture( 'rightBorder.png' ),
        verticalScroll_incButton_frameTexture   = loader.loadTexture( 'scrollDown.png' ),
        verticalScroll_decButton_frameTexture   = loader.loadTexture( 'scrollDown.png' ),
        verticalScroll_thumb_frameTexture       = loader.loadTexture( 'scrollBar.png' ),
        horizontalScroll_frameSize              = [0,1,0,self.dragbarSize],
        horizontalScroll_frameTexture           = loader.loadTexture( 'bottomBorder.png' ),
        horizontalScroll_incButton_frameTexture = loader.loadTexture( 'scrollDown.png' ),
        horizontalScroll_decButton_frameTexture = loader.loadTexture( 'scrollDown.png' ),
        horizontalScroll_thumb_frameTexture     = loader.loadTexture( 'scrollBar.png' ),
      )
    # child we attach should be inside the window
    DirectFrame.__init__( self,
        parent       = self.contentWindow.getCanvas(),
        pos          = (0,0,self.virtualSize[1]),
        scale        = (1,1,1),
        frameSize    = ( 0, self.virtualSize[0]+2*self.borderSize, 0, self.virtualSize[1] ),
        #frameColor   = (0,0,0,1),
        relief       = DGG.RIDGE,
        borderWidth  = (0,0),
        )
    self.initialiseoptions(DirectWindow)
    
    # offset then clicking on the resize button from the mouse to the resizebutton
    # position, required to calculate the position / scaling
    self.offset = None
    self.resizeButtonTaskName = "resizeTask-%s" % str(hash(self))
    
    # do sizing of the window to virtualSize
    #self.resize( self.virtualSize[0]+2*self.borderSize
    #           , self.virtualSize[1]+self.dragbarSize+2*self.borderSize )
    self.resize(10,10)
  
  # a task that keeps a node at the position of the mouse-cursor
  def mouseNodeTask(self, task):
    if WindowManager.hasMouse():
      x=WindowManager.getMouseX()
      y=WindowManager.getMouseY()
      # the mouse position is read relative to render2d, so set it accordingly
      self.mouseNode.setPos( render2d, x, 0, y )
    return task.cont
  
  # dragging functions
  def startWindowDrag( self, param ):
    self.parentWindow.wrtReparentTo( self.mouseNode )
    self.ignoreAll()
    self.accept( 'mouse1-up', self.stopWindowDrag )
  def stopWindowDrag( self, param=None ):
    # this could be called even after the window has been destroyed
    #if self:
    # this is called 2 times (bug), so make sure it's not already parented to aspect2d
    if self.parentWindow.getParent() != self.parent:
      self.parentWindow.wrtReparentTo(self.parent)
    self.ignoreAll()
  
  # resize functions
  def startResizeDrag(self, param):
    self.offset = self.resizeButton.getPos(aspect2d) - self.mouseNode.getPos(aspect2d)
    taskMgr.remove( self.resizeButtonTaskName )
    taskMgr.add( self.resizeButtonTask, self.resizeButtonTaskName )
    self.accept( 'mouse1-up', self.stopResizeDrag,['x'] )
  def resize(self,windowX,windowY):
    # limit max/min size of the window
    maxX = min(self.maxWindowSize[0], self.virtualSize[0]+2*self.borderSize)
    minX = max( self.dragbarSize*3, self.minWindowSize[0])
    windowWidth = min( maxX, max( minX, windowX ) )
    maxY = min( self.maxWindowSize[1], self.virtualSize[1]+self.dragbarSize+2*self.borderSize )
    minY = max( self.dragbarSize*4, self.minWindowSize[1])
    windowHeight = min( maxY, max( minY, windowY ) )
    if self.collapsed:
      windowHeight = 2*self.dragbarSize+2*self.borderSize
      windowWidth = windowWidth
      self.contentWindow.hide()
      # store changed window width only
      self.previousSize = windowWidth, self.previousSize[1]
    else:
      self.contentWindow.show()
      self.previousSize = windowWidth, windowHeight
    # set the window size
    self.headerParent['frameSize'] = (0, windowWidth, 0, 1)
    self.headerCenter['frameSize'] = (0, windowWidth, 0, 1)
    self.parentWindow['frameSize'] = (0, windowWidth, 0, windowHeight)
    self.contentWindow['frameSize'] = (0, windowWidth-self.borderSize*2, 0, windowHeight-self.dragbarSize-2*self.borderSize)
    self.contentWindow.setPos(self.borderSize,0,windowHeight-self.borderSize)
    self.headerRight.setPos(windowWidth-self.dragbarSize, 0, 1)
    self.textNodePath.setPos(windowWidth/2.,0,.3)
    self.resizeButton.setPos(windowWidth-self.dragbarSize, 0, windowHeight)
  def resizeButtonTask(self, task=None):
    mPos = self.mouseNode.getPos(self.parentWindow)
    # max height, the smaller of (given maxWindowSize and real size of content and borders
    windowX = mPos.getX() + self.offset.getX() + self.dragbarSize
    windowY = mPos.getZ() - self.offset.getZ()
    self.resize(windowX,windowY)
    return task.cont
  def stopResizeDrag(self, param):
    taskMgr.remove( self.resizeButtonTaskName )
    self.ignoreAll()
  
  
  # a bugfix for a wrong implementation
  def detachNode( self ):
    self.parentWindow.detachNode()
    #self. = None
    #DirectFrame.detachNode( self )
  def removeNode( self ):
    self.parentWindow.removeNode()
    #DirectFrame.removeNode( self )
  
  def toggleCollapsed(self,state=None):
    if state is None:
      state=not self.collapsed
    if state:
      self.collapse()
    else:
      self.uncollapse()
  def collapse(self):
    self.collapsed = True
    self.resize(*self.previousSize)
  def uncollapse(self):
    self.collapsed = False
    self.resize(*self.previousSize)