Example #1
0
class UnoGameCardDeck(DirectFrame):
    def __init__(self, ug):
        DirectFrame.__init__(self,
                             relief=None,
                             sortOrder=50,
                             parent=base.a2dBottomCenter)
        self.initialiseoptions(UnoGameCardDeck)
        self.container = DirectFrame(parent=self, relief=None)
        self.title = None
        self.cards = []
        self.cardBtns = []
        self.numCards = 0
        self.unoGame = ug
        self.deck = None
        self.cardToFollowGui = None
        self.holiday = base.cr.holidayManager.getHoliday()
        self.gui = None
        self.loadCards()
        return

    def loadCards(self):
        self.gui = loader.loadModel(
            "phase_4/models/minigames/mg_uno_game_cards.egg")
        if self.holiday == HolidayType.CHRISTMAS:
            cards = self.gui.find(
                '**/mg_uno_numcards_green_7').getParent().getChildren()
            for child in cards:
                child.setTexture(
                    loader.loadTexture('winter/maps/uno/%s.png' %
                                       (child.getName())), 1)

    def updateCardToFollowGui(self):
        self.deleteCardToFollowGui()
        if self.unoGame.cardToFollow[-2:] == str(UGG.CARD_BLUE):
            self.cardToFollowGui = OnscreenImage(
                image=self.getCard('mg_uno_numcards_blue_blank'),
                parent=base.a2dRightCenter)
        elif self.unoGame.cardToFollow[-2:] == str(UGG.CARD_RED):
            self.cardToFollowGui = OnscreenImage(
                image=self.getCard('mg_uno_numcards_red_blank'),
                parent=base.a2dRightCenter)
        elif self.unoGame.cardToFollow[-2:] == str(UGG.CARD_GREEN):
            self.cardToFollowGui = OnscreenImage(
                image=self.getCard('mg_uno_numcards_green_blank'),
                parent=base.a2dRightCenter)
        elif self.unoGame.cardToFollow[-2:] == str(UGG.CARD_YELLOW):
            self.cardToFollowGui = OnscreenImage(
                image=self.getCard('mg_uno_numcards_yellow_blank'),
                parent=base.a2dRightCenter)

        if self.cardToFollowGui:
            self.cardToFollowGui.setScale(0.25, 0.3, 0.3)
            self.cardToFollowGui.setPos(-0.175, 0, -0.75)

    def deleteCardToFollowGui(self):
        if self.cardToFollowGui:
            self.cardToFollowGui.destroy()
            self.cardToFollowGui = None

    def getCard(self, cardType):
        cards = loader.loadModel(
            "phase_4/models/minigames/mg_uno_game_cards.egg")
        card = cards.find('**/' + cardType)
        if self.holiday == HolidayType.CHRISTMAS:
            holidayTexture = loader.loadTexture('winter/maps/uno/%s.png' %
                                                (card.getName()))
            card.setTexture(holidayTexture, 1)
        return card

    def generate(self):
        self.container["image"] = "phase_4/maps/mg_uno_card_deck.png"
        self.container.setTransparency(True)
        self.container.setZ(-0.456)
        self.container.setSx(2)
        self.container.setSz(1)
        gui = loader.loadModel("phase_3.5/models/gui/friendslist_gui.bam")
        numItemsVisible = 5
        itemHeight = -0.25
        self.deck = DirectScrolledList(
            itemFrame_relief=DGG.SUNKEN,
            decButton_pos=(0.35, 0, -0.02),
            decButton_geom=(gui.find('**/Horiz_Arrow_UP'),
                            gui.find('**/Horiz_Arrow_DN'),
                            gui.find('**/Horiz_Arrow_Rllvr'),
                            gui.find('**/Horiz_Arrow_UP')),
            decButton_relief=None,
            decButton_hpr=(0, 0, 90),
            incButton_pos=(0.35, 0, 1.95),
            incButton_geom=(gui.find('**/Horiz_Arrow_UP'),
                            gui.find('**/Horiz_Arrow_DN'),
                            gui.find('**/Horiz_Arrow_Rllvr'),
                            gui.find('**/Horiz_Arrow_UP')),
            incButton_hpr=(0, 0, -90),
            incButton_relief=None,
            pos=(-0.936, 0, -0.41),
            hpr=(0, 0, 90),
            scale=0.97,
            numItemsVisible=numItemsVisible,
            forceHeight=itemHeight,
            itemFrame_frameSize=(-0.2, 0.2, -0.37, 1.5),
            itemFrame_pos=(0.35, 0, 0.4),
            itemFrame_borderWidth=(0.02, 0.02),
        )

    def disable(self):
        if self.deck:
            self.deck.destroy()
            self.deck = None
        for btn in self.cardBtns:
            btn.destroy()
            del btn
        self.deleteCardToFollowGui()
        return

    def delete(self):
        DirectFrame.destroy(self)
        self.disable()
        self.gui.removeNode()
        self.gui = None
        self.cards = None
        self.title = None
        self.container = None
        self.cardBtns = None
        self.numCards = None
        self.unoGame = None
        self.deck = None
        return

    def drawCard(self, id):
        card = self.getCard(UGG.cardId2cardTex[id])
        card.setScale(0.225, 0.3, 0.3)
        card.setR(-90)
        cardBtn = DirectButton(geom=card,
                               relief=None,
                               scale=(0.3, 0.3, 0.23),
                               command=self.placeCard)
        cardBtn.setPythonTag('id', id)
        cardBtn['extraArgs'] = [id, cardBtn]
        cardBtn['state'] = DGG.DISABLED
        if not self.deck:
            self.generate()
        self.deck.addItem(cardBtn)
        self.cardBtns.append(cardBtn)
        self.enableAll(self.unoGame.cardToFollow)
        # Scroll to the card we just added to the deck.
        self.deck.scrollTo(len(self.cardBtns))
        card.removeNode()
        del card

    def enableAll(self, cardToFollow=None):
        for btn in self.cardBtns:
            if cardToFollow != None:
                if (cardToFollow == btn.getPythonTag('id')
                        or cardToFollow[:2] == btn.getPythonTag('id')[:2]
                        or cardToFollow[-2:] == btn.getPythonTag('id')[-2:]
                        or btn.getPythonTag('id') == str(UGG.CARD_WILD)
                        or btn.getPythonTag('id') == str(
                            UGG.CARD_WILD_DRAW_FOUR)):
                    btn['state'] = DGG.NORMAL
                else:
                    btn['state'] = DGG.DISABLED
            else:
                btn['state'] = DGG.NORMAL

    def disableAll(self):
        for btn in self.cardBtns:
            btn['state'] = DGG.DISABLED

    def placeCard(self, id, btn):
        self.deck.removeItem(btn)
        self.cardBtns.remove(btn)
        self.disableAll()
        self.unoGame.d_requestPlaceCard(id)
Example #2
0
class JoinScreenHelper(object):
    def __init__(self, app, scene):
        self.app = app
        self.scene = scene

        self.joinLogBox = None
        self.playConnector = None

    def stop(self):
        self.playConnector.cancel()

    def show(self, servers=None):
        promptToHost = (servers is None)

        while len(self.joinLogBox['items']):
            self.joinLogBox.removeItem(self.joinLogBox['items'][0])

        if servers is None:
            servers = [const.JOIN_LOCAL_GAME]
            if self.app.connectionSettings.lanGames == 'beforeinet':
                servers.append(const.JOIN_LAN_GAME)
            servers += list(self.app.connectionSettings.servers)
            if self.app.connectionSettings.lanGames == 'afterinet':
                servers.append(const.JOIN_LAN_GAME)
            if self.app.connectionSettings.createGames:
                servers.append(const.CREATE_GAME)

        self.playConnector.begin(tuple(servers), promptToHost)

    def setup(self, joinNode):
        self.playConnector = PlayConnector(
            self.app,
            onSucceed=self.scene.showMainMenu,
            onFail=self.joinFailed,
            onLogLine=self.addJoinLogEntry,
            passwordGetFunction=self.getUserDetails,
            hostGameQueryFunction=self.askToHostGame,
        )

        colours = self.app.theme.colours
        self.joinLogBox = DirectScrolledList(
            decButton_text='',
            decButton_borderWidth=(0, 0),
            incButton_text='',
            incButton_borderWidth=(0, 0),
            pos=(-0.85, 0, 0.4),
            color=colours.joinScreenBackground,
            itemFrame_frameSize=(-0.05, 1.75, -0.888, 0.088),
            parent=joinNode,
            numItemsVisible=MAX_LOG_ITEMS,
        )
        self.joinLogBox.setTransparency(TransparencyAttrib.MAlpha)
        self.scene.button(
            'cancel',
            self.scene.showMainMenu,
            right=0.87,
            z=-0.67,
            parent=joinNode,
        )

    @defer.inlineCallbacks
    def joinFailed(self):
        yield self.scene.showOkDialog('Could not join any games')
        self.scene.showMainMenu()

    def getUserDetails(self, host, errorText=''):
        return ServerLoginDialogMaker(self.app).run(host, errorText)

    def askToHostGame(self):
        d = defer.Deferred()

        def gotResponse(result):
            dialog.cleanup()
            d.callback(result)

        dialog = YesNoDialog(
            dialogName='hostGameQuery',
            text='No games found. Host a game?',
            command=gotResponse,
            fadeScreen=0.3,
            button_pad=(0.1, 0.03),
            buttonPadSF=1.3,
        )
        dialog.show()
        return d

    def addJoinLogEntry(self, text):
        colours = self.app.theme.colours
        font = self.app.screenManager.fonts.consoleFont
        label = DirectLabel(
            text=text,
            text_scale=font.getPandaScale(),
            text_fg=colours.mainMenuColour,
            text_font=font.getPandaFont(self.app),
            text_align=TextNode.ALeft,
            relief=None,
        )
        while len(self.joinLogBox['items']) >= MAX_LOG_ITEMS:
            self.joinLogBox.removeItem(self.joinLogBox['items'][0])
        self.joinLogBox.addItem(label)
Example #3
0
class GroupTrackerPage(ShtikerPage.ShtikerPage):
    notify = directNotify.newCategory('GroupTrackerPage')

    def __init__(self):
        ShtikerPage.ShtikerPage.__init__(self)
        self.groupWidgets = []
        self.playerWidgets = []
        self.images = []  # image nodes: Possible images to apply on groups
        self.scrollList = None  # DirectScrolledList: Holds the GroupTrackerGroup widgets
        self.scrollTitle = None  # DirectLabel: Title of the list that holds the groups
        self.playerList = None  # DirectScrolledList: Holds players when showing a specific group details
        self.playerListTitle = None  # DirectLabel: Title of the playerList
        self.groupInfoTitle = None  # DirectLabel: holds the group detail title to show on the right
        self.groupInfoDistrict = None  # DirectLabel: shows group detail district on the right
        self.statusMessage = None  # DirectLabel: Shows important messages like Loading... or "No boarding groups available"
        self.groupIcon = None  # DirectButton: Icon to associate with the group ex. sellbot icon or cashbot icon depending on group info
        self.wantGroupToggle = None  # DirectButton: Allows the toon to toggle his listing

    def load(self):
        self.listXorigin = -0.02
        self.listFrameSizeX = 0.67
        self.listZorigin = -0.96
        self.listFrameSizeZ = 1.04
        self.arrowButtonScale = 1.3
        self.itemFrameXorigin = -0.237
        self.itemFrameZorigin = 0.365
        self.buttonXstart = self.itemFrameXorigin + 0.293
        self.gui = loader.loadModel('phase_3.5/models/gui/friendslist_gui')
        guiButton = loader.loadModel('phase_3/models/gui/quit_button')
        self.scrollList = DirectScrolledList(
            parent=self,
            relief=None,
            pos=(-0.5, 0, 0),
            incButton_image=(self.gui.find('**/FndsLst_ScrollUp'),
                             self.gui.find('**/FndsLst_ScrollDN'),
                             self.gui.find('**/FndsLst_ScrollUp_Rllvr'),
                             self.gui.find('**/FndsLst_ScrollUp')),
            incButton_relief=None,
            incButton_scale=(self.arrowButtonScale, self.arrowButtonScale,
                             -self.arrowButtonScale),
            incButton_pos=(self.buttonXstart, 0,
                           self.itemFrameZorigin - 0.999),
            incButton_image3_color=Vec4(1, 1, 1, 0.2),
            decButton_image=(self.gui.find('**/FndsLst_ScrollUp'),
                             self.gui.find('**/FndsLst_ScrollDN'),
                             self.gui.find('**/FndsLst_ScrollUp_Rllvr'),
                             self.gui.find('**/FndsLst_ScrollUp')),
            decButton_relief=None,
            decButton_scale=(self.arrowButtonScale, self.arrowButtonScale,
                             self.arrowButtonScale),
            decButton_pos=(self.buttonXstart, 0,
                           self.itemFrameZorigin + 0.227),
            decButton_image3_color=Vec4(1, 1, 1, 0.2),
            itemFrame_pos=(self.itemFrameXorigin, 0, self.itemFrameZorigin),
            itemFrame_scale=1.0,
            itemFrame_relief=DGG.SUNKEN,
            itemFrame_frameSize=(self.listXorigin,
                                 self.listXorigin + self.listFrameSizeX,
                                 self.listZorigin,
                                 self.listZorigin + self.listFrameSizeZ),
            itemFrame_frameColor=(0.85, 0.95, 1, 1),
            itemFrame_borderWidth=(0.01, 0.01),
            numItemsVisible=15,
            forceHeight=0.065,
            items=self.groupWidgets)

        self.scrollTitle = DirectFrame(parent=self.scrollList,
                                       text=TTLocalizer.GroupTrackerListTitle,
                                       text_scale=0.06,
                                       text_align=TextNode.ACenter,
                                       relief=None,
                                       pos=(self.buttonXstart, 0,
                                            self.itemFrameZorigin + 0.127))

        self.playerList = DirectScrolledList(
            parent=self,
            relief=None,
            pos=(0.45, 0, 0.1),
            incButton_image=(self.gui.find('**/FndsLst_ScrollUp'),
                             self.gui.find('**/FndsLst_ScrollDN'),
                             self.gui.find('**/FndsLst_ScrollUp_Rllvr'),
                             self.gui.find('**/FndsLst_ScrollUp')),
            incButton_relief=None,
            incButton_scale=(1.0, 1.0, -1.0),
            incButton_pos=(0, 0, -0.28),
            incButton_image3_color=Vec4(1, 1, 1, 0.05),
            decButton_image=(self.gui.find('**/FndsLst_ScrollUp'),
                             self.gui.find('**/FndsLst_ScrollDN'),
                             self.gui.find('**/FndsLst_ScrollUp_Rllvr'),
                             self.gui.find('**/FndsLst_ScrollUp')),
            decButton_relief=None,
            decButton_scale=(1.0, 1.0, 1.0),
            decButton_pos=(0.0, 0, 0.04),
            decButton_image3_color=Vec4(1, 1, 1, 0.25),
            itemFrame_pos=(0, 0, -0.05),
            itemFrame_scale=1.0,
            itemFrame_relief=DGG.SUNKEN,
            itemFrame_frameSize=(
                -0.3,
                0.3,  #x
                -0.2,
                0.06),  #z
            itemFrame_frameColor=(0.85, 0.95, 1, 1),
            itemFrame_borderWidth=(0.01, 0.01),
            numItemsVisible=4,
            forceHeight=0.05,
            items=self.playerWidgets)

        self.playerListTitle = DirectFrame(parent=self.playerList,
                                           text='',
                                           text_scale=0.05,
                                           text_align=TextNode.ACenter,
                                           relief=None,
                                           pos=(0, 0, 0.08))
        self.groupInfoTitle = DirectLabel(parent=self,
                                          text='',
                                          text_scale=0.080,
                                          text_align=TextNode.ACenter,
                                          text_wordwrap=15,
                                          relief=None,
                                          pos=(0.45, 0, 0.5))
        self.groupInfoDistrict = DirectLabel(parent=self,
                                             text='',
                                             text_scale=0.050,
                                             text_align=TextNode.ACenter,
                                             text_wordwrap=15,
                                             relief=None,
                                             pos=(0.45, 0, 0.4))

        self.statusMessage = DirectLabel(parent=self,
                                         text='',
                                         text_scale=0.060,
                                         text_align=TextNode.ACenter,
                                         text_wordwrap=5,
                                         relief=None,
                                         pos=(0.45, 0, 0.1))

        # Group Image:
        self.groupIcon = DirectButton(parent=self,
                                      relief=None,
                                      state=DGG.DISABLED,
                                      image=None,
                                      image_scale=(0.35, 1, 0.35),
                                      image_color=Vec4(1.0, 1.0, 1.0, 0.75),
                                      pos=(0.45, 10, -0.45),
                                      command=self.doNothing)

        # Group Toggle:
        self.wantGroupToggle = DirectButton(
            parent=self,
            relief=None,
            image=(guiButton.find('**/QuitBtn_UP'),
                   guiButton.find('**/QuitBtn_DN'),
                   guiButton.find('**/QuitBtn_RLVR')),
            image_scale=(0.7, 1, 1),
            text='',
            text_scale=0.052,
            text_pos=(0, -0.02),
            pos=(0.2, 0, -0.65),
            command=self.toggleWantGroup)
        self.updateWantGroupButton()

        # Loading possible group icons
        suitIcons = loader.loadModel('phase_3/models/gui/cog_icons')
        bossbotIcon = suitIcons.find('**/CorpIcon')
        bossbotIcon.setColor(SUIT_ICON_COLORS[0])
        self.images.append(bossbotIcon)

        lawbotIcon = suitIcons.find('**/LegalIcon')
        lawbotIcon.setColor(SUIT_ICON_COLORS[1])
        self.images.append(lawbotIcon)

        cashbotIcon = suitIcons.find('**/MoneyIcon')
        cashbotIcon.setColor(SUIT_ICON_COLORS[2])
        self.images.append(cashbotIcon)

        sellbotIcon = suitIcons.find('**/SalesIcon')
        sellbotIcon.setColor(SUIT_ICON_COLORS[3])
        self.images.append(sellbotIcon)

        # Clean up
        self.clearGroupInfo()
        self.statusMessage.hide()

        suitIcons.removeNode()
        self.gui.removeNode()
        guiButton.removeNode()

        self.accept('GroupTrackerResponse', self.updatePage)

    def unload(self):
        self.scrollList.destroy()
        self.groupInfoDistrict.destroy()
        self.playerList.destroy()
        self.groupInfoTitle.destroy()
        self.groupIcon.destroy()
        self.wantGroupToggle.destroy()
        for widget in self.playerWidgets:
            widget.destroy()
        for widget in self.groupWidgets:
            widget.destroy()
        self.playerWidgets = []

        del self.scrollList
        del self.groupInfoDistrict
        del self.playerList
        del self.groupInfoTitle
        del self.groupIcon
        del self.wantGroupToggle
        ShtikerPage.ShtikerPage.unload(self)

    def enter(self):
        ShtikerPage.ShtikerPage.enter(self)
        self.setGroups([])  # CLEAR IT ALL
        self.setPlayers()  # CLEAR IT ALL
        if (self.scrollList['items'] == []):
            self.statusMessage['text'] = TTLocalizer.GroupTrackerLoading
            self.statusMessage.show()
        base.cr.globalGroupTracker.requestGroups()
        taskMgr.doMethodLater(3, self.displayNoGroupsTaskHandler,
                              self.uniqueName('timeout'))

    def displayNoGroups(self):
        self.statusMessage['text'] = TTLocalizer.GroupTrackerEmpty
        self.statusMessage.show()
        self.clearGroupInfo()

    def displayNoGroupsTaskHandler(self, task):
        self.displayNoGroups()
        return task.done

    def updatePage(self):
        taskMgr.remove(self.uniqueName('timeout'))
        groups = base.cr.globalGroupTracker.getGroupInfo()
        self.setGroups(groups)

    def exit(self):
        self.clearGroupInfo()
        ShtikerPage.ShtikerPage.exit(self)
        base.cr.globalGroupTracker.doneRequesting()

    def updateGroupInfoEventHandle(self, groupWidget, mouseEvent):
        self.updateGroupInfo(groupWidget)

    def updateGroupInfo(self, groupWidget):
        ''' Updates the Right Page of the Group Tracker Page with new Info '''
        self.statusMessage.hide()

        # Update the Player List
        self.setPlayers(groupWidget)
        self.playerList.show()

        # Update the Player List Title
        self.playerListTitle['text'] = ('Players ' +
                                        str(groupWidget.getCurrentPlayers()) +
                                        '/' +
                                        str(groupWidget.getMaxPlayers()) + ':')
        self.playerListTitle.show()

        # Update the District
        self.groupInfoDistrict[
            'text'] = TTLocalizer.BoardingGroupDistrictInformation % {
                'district': groupWidget.getDistrict()
            }
        self.groupInfoDistrict.show()

        # Update the Title
        self.groupInfoTitle['text'] = groupWidget.getTitle()
        self.groupInfoTitle.show()

        # Update the Image
        self.groupIcon['image'] = self.images[
            GroupTrackerGlobals.CATEGORY_TO_IMAGE_ID[
                groupWidget.getCategory()]]
        self.groupIcon['image_scale'] = (0.35, 1, 0.35)
        self.groupIcon.show()

    def clearGroupInfo(self):
        self.playerList.hide()
        self.playerListTitle.hide()
        self.groupInfoDistrict.hide()
        self.groupInfoTitle.hide()
        self.groupIcon.hide()

    def setPlayers(self, groupWidget=None):
        ''' Calls updatePlayerList '''

        # Clear the Widgets that were held in the listings
        for playerWidget in self.playerWidgets:
            playerWidget.destroy()
        self.playerWidgets = []

        # Make a player widget for each player
        # TODO: Edit this stuff when avIds come from players
        if groupWidget:
            leaderId = groupWidget.getLeaderId()
            playerNames = groupWidget.getMemberNames()
            playerIds = groupWidget.getMemberIds()
            for playerName in playerNames:
                playerId = playerIds[playerNames.index(playerName)]
                isLeader = playerId == leaderId
                self.playerWidgets.append(
                    GroupTrackerPlayer(parent=self,
                                       avId=playerId,
                                       name=playerName,
                                       isLeader=isLeader))

        self.updatePlayerList()

    def reconsiderGroupInfo(self, groupWidget):
        ''' If someone is viewing this info and it was updated, we also want to update the info being viewed '''
        if self.playerWidgets is None or self.playerList['items'] == []:
            return  # No Info is being viewed at the moment since you cant have an empty group

        # We have to update if this group's leader is the leader in the playerlist being viewed right now
        leaderId = groupWidget.getLeaderId()

        # Check all the players in the playerList being viewed for the same leader
        for playerWidget in self.playerWidgets:
            if playerWidget.getLeader():
                if leaderId == playerWidget.getId():
                    self.updateGroupInfo(groupWidget)
                    return False

        return True

    def setGroups(self, groups):
        ''' Calls updateGroupList '''

        # Clear our Group Widgets
        for group in self.groupWidgets:
            group.destroy()
        self.groupWidgets = []

        wantReconsiderInfo = True

        # Create a new group widget for each group
        for group in groups:
            if not group[GroupTrackerGlobals.SHOW] or len(
                    group[GroupTrackerGlobals.MEMBER_IDS]) == 0:
                continue  # We are using this to see if this group is dead or if someone doesnt want it up
            leaderId = 0
            for i, g in base.cr.globalGroupTracker.leader2Group.items():
                if g == group:
                    leaderId = i
            if not leaderId:
                continue

            leaderName = group[GroupTrackerGlobals.LEADER_NAME]
            shardName = group[GroupTrackerGlobals.SHARD_NAME]
            category = group[GroupTrackerGlobals.CATEGORY]
            memberIds = group[GroupTrackerGlobals.MEMBER_IDS]
            memberNames = group[GroupTrackerGlobals.MEMBER_NAMES]

            groupWidget = GroupTrackerGroup(parent=self,
                                            leaderId=leaderId,
                                            leaderName=leaderName,
                                            shardName=shardName,
                                            category=category,
                                            memberIds=memberIds,
                                            memberNames=memberNames)
            groupWidget.bind(DGG.WITHIN,
                             self.updateGroupInfoEventHandle,
                             extraArgs=[groupWidget])
            self.groupWidgets.append(groupWidget)
            if wantReconsiderInfo:
                wantReconsiderInfo = self.reconsiderGroupInfo(groupWidget)

        # Edge case where a group that was removed, info might remain on the screen if it didn't exist any more
        if wantReconsiderInfo:
            self.clearGroupInfo()

        # There are no groups, hide the information
        if len(self.groupWidgets) == 0:
            self.displayNoGroups()
        self.updateGroupList()

    def updateGroupList(self):
        self.statusMessage.hide()
        if self.scrollList is None:
            return

        # Clear the Group Listing
        for item in self.scrollList['items']:
            if item:
                self.scrollList.removeItem(item, refresh=True)
        self.scrollList['items'] = []

        # Re-populate the Group Listing
        for groupWidget in self.groupWidgets:
            self.scrollList.addItem(groupWidget, refresh=True)

        if len(self.groupWidgets) == 0:
            self.displayNoGroups()

    def updatePlayerList(self):
        if self.playerList is None:
            return

        # Clear the Player Listing
        for item in self.playerList['items']:
            if item:
                self.playerList.removeItem(item)
        self.playerList['items'] = []

        # Re-Populate the List
        for playerWidget in self.playerWidgets:
            self.playerList.addItem(playerWidget)

    def toggleWantGroup(self):
        if settings.get('grouptracker', False):
            settings['grouptracker'] = False
            base.cr.globalGroupTracker.showMe(False)
        else:
            settings['grouptracker'] = True
            base.cr.globalGroupTracker.showMe(True)

        base.localAvatar.wantGroupTracker()

        base.localAvatar.wantGroupTracker(
        )  # Updates the ai toon so the boarding group AI could know what he wants
        self.updateWantGroupButton()

    def updateWantGroupButton(self):
        if settings.get('grouptracker', False):
            self.wantGroupToggle['text'] = 'Hide Me'
        else:
            self.wantGroupToggle['text'] = 'Show Me'

    def doNothing(self):
        pass
class GroupTrackerPage(ShtikerPage.ShtikerPage):
    notify = directNotify.newCategory('GroupTrackerPage')

    def __init__(self):
        ShtikerPage.ShtikerPage.__init__(self)
        self.groupWidgets = []
        self.playerWidgets = []
        self.images = []                # image nodes: Possible images to apply on groups
        self.scrollList = None          # DirectScrolledList: Holds the GroupTrackerGroup widgets
        self.scrollTitle = None         # DirectLabel: Title of the list that holds the groups
        self.playerList = None          # DirectScrolledList: Holds players when showing a specific group details
        self.playerListTitle = None     # DirectLabel: Title of the playerList
        self.groupInfoTitle = None      # DirectLabel: holds the group detail title to show on the right
        self.groupInfoDistrict = None   # DirectLabel: shows group detail district on the right
        self.statusMessage = None       # DirectLabel: Shows important messages like Loading... or "No boarding groups available"
        self.groupIcon = None           # DirectButton: Icon to associate with the group ex. sellbot icon or cashbot icon depending on group info
        self.wantGroupToggle = None     # DirectButton: Allows the toon to toggle his listing

    def load(self):
        self.listXorigin = -0.02
        self.listFrameSizeX = 0.67
        self.listZorigin = -0.96
        self.listFrameSizeZ = 1.04
        self.arrowButtonScale = 1.3
        self.itemFrameXorigin = -0.237
        self.itemFrameZorigin = 0.365
        self.buttonXstart = self.itemFrameXorigin + 0.293
        self.gui = loader.loadModel('phase_3.5/models/gui/friendslist_gui')
        guiButton = loader.loadModel('phase_3/models/gui/quit_button')
        self.scrollList = DirectScrolledList(parent=self, 
                                            relief=None, 
                                            pos=(-0.5, 0, 0), 
                                            incButton_image=(self.gui.find('**/FndsLst_ScrollUp'), 
                                                             self.gui.find('**/FndsLst_ScrollDN'),
                                                             self.gui.find('**/FndsLst_ScrollUp_Rllvr'),
                                                             self.gui.find('**/FndsLst_ScrollUp')
                                                             ), 
                                            incButton_relief=None, 
                                            incButton_scale=(self.arrowButtonScale, self.arrowButtonScale, -self.arrowButtonScale), 
                                            incButton_pos=(self.buttonXstart, 0, self.itemFrameZorigin - 0.999), 
                                            incButton_image3_color=Vec4(1, 1, 1, 0.2), 
                                            decButton_image=(self.gui.find('**/FndsLst_ScrollUp'), 
                                                             self.gui.find('**/FndsLst_ScrollDN'),
                                                             self.gui.find('**/FndsLst_ScrollUp_Rllvr'), 
                                                             self.gui.find('**/FndsLst_ScrollUp')
                                                             ), 
                                            decButton_relief=None, 
                                            decButton_scale=(self.arrowButtonScale, self.arrowButtonScale, self.arrowButtonScale), 
                                            decButton_pos=(self.buttonXstart, 0, self.itemFrameZorigin + 0.227), 
                                            decButton_image3_color=Vec4(1, 1, 1, 0.2), 
                                            itemFrame_pos=(self.itemFrameXorigin, 0, self.itemFrameZorigin), 
                                            itemFrame_scale=1.0,
                                            itemFrame_relief=DGG.SUNKEN, 
                                            itemFrame_frameSize=(self.listXorigin, self.listXorigin + self.listFrameSizeX,
                                                                 self.listZorigin, self.listZorigin + self.listFrameSizeZ
                                                                 ), 
                                            itemFrame_frameColor=(0.85, 0.95, 1, 1), 
                                            itemFrame_borderWidth=(0.01, 0.01), 
                                            numItemsVisible=15, 
                                            forceHeight=0.065, 
                                            items=self.groupWidgets
                                            )
                                            
        self.scrollTitle = DirectFrame(parent=self.scrollList, 
                                       text=TTLocalizer.GroupTrackerListTitle, 
                                       text_scale=0.06, 
                                       text_align=TextNode.ACenter, 
                                       relief=None,
                                       pos=(self.buttonXstart, 0, self.itemFrameZorigin + 0.127)
                                       )
        
        self.playerList = DirectScrolledList(parent=self, 
                                            relief=None, 
                                            pos=(0.45, 0, 0.1), 
                                            
                                            incButton_image=(self.gui.find('**/FndsLst_ScrollUp'), 
                                                             self.gui.find('**/FndsLst_ScrollDN'),
                                                             self.gui.find('**/FndsLst_ScrollUp_Rllvr'),
                                                             self.gui.find('**/FndsLst_ScrollUp')
                                                             ), 
                                            incButton_relief=None, 
                                            incButton_scale=(1.0, 1.0, -1.0), 
                                            incButton_pos=(0, 0, -0.28), 
                                            incButton_image3_color=Vec4(1, 1, 1, 0.05),
                                            
                                            decButton_image=(self.gui.find('**/FndsLst_ScrollUp'), 
                                                             self.gui.find('**/FndsLst_ScrollDN'),
                                                             self.gui.find('**/FndsLst_ScrollUp_Rllvr'), 
                                                             self.gui.find('**/FndsLst_ScrollUp')
                                                             ), 
                                            decButton_relief=None, 
                                            decButton_scale=(1.0, 1.0, 1.0),
                                            decButton_pos=(0.0, 0, 0.04), 
                                            decButton_image3_color=Vec4(1, 1, 1, 0.25), 
                                            
                                            itemFrame_pos=(0, 0, -0.05), 
                                            itemFrame_scale=1.0,
                                            itemFrame_relief=DGG.SUNKEN, 
                                            itemFrame_frameSize=(-0.3, 0.3,  #x
                                                                 -0.2, 0.06),  #z
                                            itemFrame_frameColor=(0.85, 0.95, 1, 1), 
                                            itemFrame_borderWidth=(0.01, 0.01), 
                                            numItemsVisible=4,
                                            forceHeight=0.05, 
                                            items=self.playerWidgets
                                            )
                                            
        self.playerListTitle = DirectFrame(parent=self.playerList, 
                                       text='', 
                                       text_scale=0.05, 
                                       text_align=TextNode.ACenter, 
                                       relief=None,
                                       pos=(0, 0, 0.08)
                                       )
        self.groupInfoTitle = DirectLabel(parent=self, text='', 
                                          text_scale=0.080, text_align=TextNode.ACenter,
                                          text_wordwrap=15, relief=None, pos=(0.45, 0, 0.5))
        self.groupInfoDistrict = DirectLabel(parent=self,
                                     text='',
                                     text_scale=0.050,
                                     text_align=TextNode.ACenter, 
                                     text_wordwrap=15, 
                                     relief=None, 
                                     pos=(0.45, 0, 0.4)
                                     )
        
        self.statusMessage = DirectLabel(parent=self, text='', text_scale=0.060, text_align=TextNode.ACenter, text_wordwrap=5, relief=None, pos=(0.45,0,0.1))
                                     
        # Group Image:
        self.groupIcon = DirectButton(parent=self, relief=None, state=DGG.DISABLED, image=None, image_scale=(0.35, 1, 0.35), image_color=Vec4(1.0, 1.0, 1.0, 0.75), pos=(0.45, 10, -0.45), command=self.doNothing)
        
        # Group Toggle:
        self.wantGroupToggle = DirectButton(parent=self, relief=None, image=(guiButton.find('**/QuitBtn_UP'), guiButton.find('**/QuitBtn_DN'), guiButton.find('**/QuitBtn_RLVR')), image_scale=(0.7, 1, 1), text='', text_scale=0.052, text_pos=(0, -0.02), pos=(0.2, 0, -0.65), command=self.toggleWantGroup)
        self.updateWantGroupButton()
        
        
        # Loading possible group icons
        suitIcons = loader.loadModel('phase_3/models/gui/cog_icons')     
        bossbotIcon = suitIcons.find('**/CorpIcon')
        bossbotIcon.setColor(SUIT_ICON_COLORS[0])
        self.images.append(bossbotIcon)
        
        lawbotIcon = suitIcons.find('**/LegalIcon')
        lawbotIcon.setColor(SUIT_ICON_COLORS[1])
        self.images.append(lawbotIcon)
        
        cashbotIcon = suitIcons.find('**/MoneyIcon')
        cashbotIcon.setColor(SUIT_ICON_COLORS[2])
        self.images.append(cashbotIcon)
        
        sellbotIcon = suitIcons.find('**/SalesIcon')
        sellbotIcon.setColor(SUIT_ICON_COLORS[3])
        self.images.append(sellbotIcon)
        
        # Clean up
        self.clearGroupInfo()
        self.statusMessage.hide()
        
        suitIcons.removeNode()
        self.gui.removeNode()
        guiButton.removeNode()

        self.accept('GroupTrackerResponse', self.updatePage)

    def unload(self):
        self.scrollList.destroy()
        self.groupInfoDistrict.destroy()
        self.playerList.destroy()
        self.groupInfoTitle.destroy()
        self.groupIcon.destroy()
        self.wantGroupToggle.destroy()
        for widget in self.playerWidgets:
            widget.destroy()
        for widget in self.groupWidgets:
            widget.destroy()
        self.playerWidgets = []
        
        del self.scrollList
        del self.groupInfoDistrict
        del self.playerList
        del self.groupInfoTitle
        del self.groupIcon
        del self.wantGroupToggle
        ShtikerPage.ShtikerPage.unload(self)

    def enter(self):
        ShtikerPage.ShtikerPage.enter(self)
        self.setGroups([]) # CLEAR IT ALL
        self.setPlayers()  # CLEAR IT ALL
        if(self.scrollList['items'] == []):
            self.statusMessage['text'] = TTLocalizer.GroupTrackerLoading
            self.statusMessage.show()
        base.cr.globalGroupTracker.requestGroups()
        taskMgr.doMethodLater(3, self.displayNoGroupsTaskHandler, self.uniqueName('timeout'))

    def displayNoGroups(self):
        self.statusMessage['text'] = TTLocalizer.GroupTrackerEmpty
        self.statusMessage.show()
        self.clearGroupInfo()
    
    def displayNoGroupsTaskHandler(self, task):
        self.displayNoGroups()
        return task.done

    def updatePage(self):
        taskMgr.remove(self.uniqueName('timeout'))
        groups = base.cr.globalGroupTracker.getGroupInfo()
        self.setGroups(groups)
        
    def exit(self):
        self.clearGroupInfo()
        ShtikerPage.ShtikerPage.exit(self)
        base.cr.globalGroupTracker.doneRequesting()
    
    def updateGroupInfoEventHandle(self, groupWidget, mouseEvent):
        self.updateGroupInfo(groupWidget)
        
    def updateGroupInfo(self, groupWidget):
        ''' Updates the Right Page of the Group Tracker Page with new Info '''
        self.statusMessage.hide()

        # Update the Player List
        self.setPlayers(groupWidget)
        self.playerList.show()

        # Update the Player List Title
        self.playerListTitle['text'] = ('Players ' + str(groupWidget.getCurrentPlayers()) + '/' + str(groupWidget.getMaxPlayers()) + ':')
        self.playerListTitle.show()

        # Update the District
        self.groupInfoDistrict['text'] = TTLocalizer.BoardingGroupDistrictInformation % { 'district' : groupWidget.getDistrict() }
        self.groupInfoDistrict.show()

        # Update the Title
        self.groupInfoTitle['text'] = groupWidget.getTitle()
        self.groupInfoTitle.show()

        # Update the Image
        self.groupIcon['image'] = self.images[GroupTrackerGlobals.CATEGORY_TO_IMAGE_ID[groupWidget.getCategory()]]
        self.groupIcon['image_scale'] = (0.35, 1, 0.35)
        self.groupIcon.show()

    def clearGroupInfo(self):
        self.playerList.hide()
        self.playerListTitle.hide()
        self.groupInfoDistrict.hide()
        self.groupInfoTitle.hide()
        self.groupIcon.hide()

    def setPlayers(self, groupWidget=None):
        ''' Calls updatePlayerList '''

        # Clear the Widgets that were held in the listings
        for playerWidget in self.playerWidgets:
            playerWidget.destroy()
        self.playerWidgets = []

        # Make a player widget for each player
        # TODO: Edit this stuff when avIds come from players
        if groupWidget:
            leaderId = groupWidget.getLeaderId()
            playerNames = groupWidget.getMemberNames()
            playerIds = groupWidget.getMemberIds()
            for playerName in playerNames:
                playerId = playerIds[playerNames.index(playerName)]
                isLeader = playerId == leaderId
                self.playerWidgets.append(GroupTrackerPlayer(parent=self, avId=playerId, name=playerName, isLeader=isLeader))

        self.updatePlayerList()

    def reconsiderGroupInfo(self, groupWidget):
        ''' If someone is viewing this info and it was updated, we also want to update the info being viewed '''
        if self.playerWidgets is None or self.playerList['items'] == []:
            return # No Info is being viewed at the moment since you cant have an empty group
        
        # We have to update if this group's leader is the leader in the playerlist being viewed right now
        leaderId = groupWidget.getLeaderId()
        
        # Check all the players in the playerList being viewed for the same leader
        for playerWidget in self.playerWidgets:
            if playerWidget.getLeader():
                if leaderId == playerWidget.getId():
                    self.updateGroupInfo(groupWidget)
                    return False
        
        return True
                
    def setGroups(self, groups):
        ''' Calls updateGroupList '''
        
        # Clear our Group Widgets
        for group in self.groupWidgets:
            group.destroy()
        self.groupWidgets = []
        
        wantReconsiderInfo = True
    
        # Create a new group widget for each group
        for group in groups:
            if not group[GroupTrackerGlobals.SHOW] or len(group[GroupTrackerGlobals.MEMBER_IDS]) == 0:
                continue # We are using this to see if this group is dead or if someone doesnt want it up
            leaderId = 0
            for i, g in base.cr.globalGroupTracker.leader2Group.items():
                if g == group:
                    leaderId = i
            if not leaderId:
                continue
                
            leaderName = group[GroupTrackerGlobals.LEADER_NAME]
            shardName = group[GroupTrackerGlobals.SHARD_NAME]
            category = group[GroupTrackerGlobals.CATEGORY]
            memberIds = group[GroupTrackerGlobals.MEMBER_IDS]
            memberNames = group[GroupTrackerGlobals.MEMBER_NAMES]
            
            groupWidget = GroupTrackerGroup(parent=self, leaderId=leaderId, leaderName=leaderName, shardName=shardName, category=category, memberIds=memberIds, memberNames=memberNames)
            groupWidget.bind(DGG.WITHIN, self.updateGroupInfoEventHandle, extraArgs=[groupWidget])
            self.groupWidgets.append(groupWidget)
            if wantReconsiderInfo:
                wantReconsiderInfo = self.reconsiderGroupInfo(groupWidget)
        
        # Edge case where a group that was removed, info might remain on the screen if it didn't exist any more
        if wantReconsiderInfo:
            self.clearGroupInfo()
        
        # There are no groups, hide the information
        if len(self.groupWidgets) == 0:
            self.displayNoGroups()
        self.updateGroupList()

    def updateGroupList(self): 
        self.statusMessage.hide()
        if self.scrollList is None:
            return
            
        # Clear the Group Listing
        for item in self.scrollList['items']:
            if item:
                self.scrollList.removeItem(item, refresh=True)
        self.scrollList['items'] = []
        
        # Re-populate the Group Listing
        for groupWidget in self.groupWidgets:
            self.scrollList.addItem(groupWidget, refresh=True)
        
        if len(self.groupWidgets) == 0:
            self.displayNoGroups()

    def updatePlayerList(self):
        if self.playerList is None:
            return

        # Clear the Player Listing
        for item in self.playerList['items']:
            if item:
                self.playerList.removeItem(item)
        self.playerList['items'] = []

        # Re-Populate the List
        for playerWidget in self.playerWidgets:
            self.playerList.addItem(playerWidget)

    def toggleWantGroup(self):
        if settings.get('grouptracker', False):
            settings['grouptracker'] = False
            base.cr.globalGroupTracker.showMe(False)
        else:
            settings['grouptracker'] = True
            base.cr.globalGroupTracker.showMe(True)
            
        base.localAvatar.wantGroupTracker()
        
        base.localAvatar.wantGroupTracker() # Updates the ai toon so the boarding group AI could know what he wants
        self.updateWantGroupButton()
    
    def updateWantGroupButton(self):
        if settings.get('grouptracker', False):
            self.wantGroupToggle['text'] = 'Hide Me'
        else:
            self.wantGroupToggle['text'] = 'Show Me'
            
    def doNothing(self):
        pass