/* * OpenClonk, http://www.openclonk.org * * Copyright (c) 2008-2009, RedWolf Design GmbH, http://www.clonk.de/ * Copyright (c) 2009-2016, The OpenClonk Team and contributors * * Distributed under the terms of the ISC license; see accompanying file * "COPYING" for details. * * "Clonk" is a registered trademark of Matthes Bender, used with permission. * See accompanying file "TRADEMARK" for details. * * To redistribute this file separately, substitute the full license texts * for the above references. */ // player listbox used in lobby and game over dlg #ifndef INC_C4PlayerInfoListBox #define INC_C4PlayerInfoListBox #include "gui/C4Gui.h" class C4PlayerInfoListBox : public C4GUI::ListBox { public: enum Spacings { // some spacings IconLabelSpacing = 2, // space between an icon and its text ClientListBoxSpacing = 8, // space between two clients in the list PlayerListBoxIndent = 3, // indent of player list box items NoneLabelSpacing = 20, // indent of "- none -"-label in list box SoundIconShowTime = 1 // seconds. min time a sound icon is shown }; // list box mode enum Mode { PILBM_LobbyClientSort, PILBM_LobbyTeamSort, PILBM_Evaluation, PILBM_EvaluationNoWinners }; private: // generic player list item class ListItem : public C4GUI::Window { protected: C4PlayerInfoListBox *pList; uint32_t dwBackground; // not drawn if 0 public: struct ID { enum IDType { PLI_NONE=0, PLI_SCRIPTPLR, // script player caption (ID=0) - script players themselbed are regular PLI_PLAYER PLI_SAVEGAMEPLR, // restore savegame player (ID>0), or caption (ID=0) PLI_PLAYER, // player PLI_CLIENT, // client label PLI_TEAM, // team label PLI_REPLAY // replay player (ID>0), or caption (ID=0) } idType{PLI_NONE}; int32_t id{0}; // player file ID or team ID or client ID ID() = default; ID(IDType eType, int32_t id) : idType(eType), id(id) {} inline bool operator ==(const ID &r2) { return idType == r2.idType && id == r2.id; } }; ID idListItemID; C4GameLobby::MainDlg *GetLobby() const; virtual void Update() {} // periodic update callback protected: void DrawElement(C4TargetFacet &cgo) override; // draw background bool CanLocalChooseTeams(int32_t idPlayer=0) const; // whether the local client can change any teams public: ListItem(C4PlayerInfoListBox *pList) : C4GUI::Window(), pList(pList), dwBackground(0) {} }; // lobby information and display of joined players class PlayerListItem : public ListItem { private: // subcomponents C4GUI::Icon *pIcon; // player icon C4GUI::Label *pNameLabel; // label indicating player name C4GUI::Label *pScoreLabel; // label showing some player score (league) C4GUI::Label *pTimeLabel; // evaluation only: label showing total playing time C4GUI::Label *pExtraLabel; // evaluation only: label showing extra data set by script C4GUI::Icon *pRankIcon; // league rank icon C4GUI::ComboBox *pTeamCombo; // team selection combo - nullptr for no-team-scens C4GUI::Picture *pTeamPic; // evaluation only: Team icon spec bool fIconSet; // whether custom icon has been set bool fJoinedInfoSet; // join info for savegame recreation DWORD dwJoinClr, dwPlrClr;//colors currently reflected in icon protected: int32_t idClient, idPlayer; // referenced IDs bool fFreeSavegamePlayer; // if set, the player is an (unassociated) savegame player bool fShownCollapsed; // true if small view is shown protected: void UpdateOwnPos() override; // recalculate item positioning int32_t GetListItemTopSpacing() override; public: PlayerListItem(C4PlayerInfoListBox *pForListBox, int32_t idClient, int32_t idPlayer, bool fSavegamePlayer, C4GUI::Element *pInsertBeforeElement); // ctor ~PlayerListItem() override = default;; // dtor void UpdateIcon(C4PlayerInfo *pInfo, C4PlayerInfo *pJoinedInfo); // update player icon void UpdateTeam(); void UpdateScoreLabel(C4PlayerInfo *pInfo); // update league score labels and icons void UpdateCollapsed(); public: C4GUI::ContextMenu *OnContext(C4GUI::Element *pListItem, int32_t iX, int32_t iY); // open context menu C4GUI::ContextMenu *OnContextTakeOver(C4GUI::Element *pListItem, int32_t iX, int32_t iY); // takeover savegame player submenu void OnCtxTakeOver(C4GUI::Element *pListItem, const int32_t &idPlayer); void OnCtxRemove(C4GUI::Element *pListItem); void OnCtxNewColor(C4GUI::Element *pListItem); void OnTeamComboFill(C4GUI::ComboBox_FillCB *pFiller); bool OnTeamComboSelChange(C4GUI::ComboBox *pForCombo, int32_t idNewSelection); void Update() override; // update icon and team int32_t GetInfoID() const { return idPlayer; } C4Network2Client *GetNetClient() const; // return associated network client C4PlayerInfo *GetPlayerInfo() const; C4PlayerInfo *GetJoinedInfo() const; // if this player is joined or associated to a joined info, return the joined info bool IsLocalClientPlayer() const; // whether this player is going to join locally bool CanLocalChooseTeam() const; // whether the local client can change team for this player }; // lobby information and display of connected clients class ClientListItem : public ListItem { private: // subcomponents C4GUI::Icon *pStatusIcon; // icon indicating client status (host, etc.) C4GUI::Label *pNameLabel; // label indicating client name C4GUI::Label *pPingLabel; // label indicating ping to client - may be nullptr protected: int32_t idClient; // associated network interface ID DWORD dwClientClr; // client color used for chatting bool fIsShownActive; // whether client was active in last update time_t tLastSoundTime; // now() when the client last issued a sound (display as sound icon). 0 for no sound. public: ClientListItem(C4PlayerInfoListBox *pForListBox, const C4ClientCore &rClientInfo, ListItem *pInsertBefore); // ctor ~ClientListItem() override = default; // dtor void SetColor(DWORD dwToClr) // update color of client name label { pNameLabel->SetColor((dwClientClr=dwToClr) | C4GUI_MessageFontAlpha); } void SetStatus(C4GUI::Icons icoNewStatus) // set new status { pStatusIcon->SetIcon(icoNewStatus); } void SetPing(int32_t iToPing); // update ping label; iToPing=-1 removes the label void UpdateCore(const C4ClientCore &rCore); // core update: re-set name and indicate whether active or not void SetSoundIcon(); // sets the sound icon as current icon and schedules reset after some time // spacing inserted between two client list items int32_t GetListItemTopSpacing() override { return ClientListBoxSpacing; } bool GetListItemTopSpacingBar() override { return true; } public: void Init(const C4ClientCore &rClientInfo); // init members void UpdateInfo(); // update for changed player info DWORD GetColor() const { return dwClientClr; } // client chat color C4Client *GetClient() const; // get client associated with this list item bool IsLocalClientPlayer() const; // whether this player is going to join locally C4GUI::Icons GetCurrentStatusIcon(); // get status icon that shows the current client state class C4Network2Client *GetNetClient() const; // return assicuated network client; nullptr for local bool IsLocal() const; void Update() override { UpdatePing(); UpdateInfo(); } void UpdatePing(); // update ping label C4GUI::ContextMenu *OnContext(C4GUI::Element *pListItem, int32_t iX, int32_t iY); // open context menu void OnCtxKick(C4GUI::Element *pListItem); // kick item selected in client ctx menu void OnCtxActivate(C4GUI::Element *pListItem); // toggle player/observer void OnCtxInfo(C4GUI::Element *pListItem); // show info dlg (modal) void OnCtxIgnore(C4GUI::Element *pListItem); void OnBtnAddPlr(C4GUI::Control *btn); }; // team label class TeamListItem : public ListItem { private: // subcomponents C4GUI::Icon *pIcon; C4GUI::Label *pNameLabel; int32_t idTeam; // team ID protected: void UpdateOwnPos() override; // recalculate item positioning public: TeamListItem(C4PlayerInfoListBox *pForListBox, int32_t idTeam, ListItem *pInsertBefore); // ctor void MouseInput(C4GUI::CMouse &rMouse, int32_t iButton, int32_t iX, int32_t iY, DWORD dwKeyParam) override; // input: mouse movement or buttons // spacing inserted between of those list items; usually this is top anyway... bool GetListItemTopSpacingBar() override { return true; } int32_t GetListItemTopSpacing() override { return ClientListBoxSpacing; } void Update() override; private: void MoveLocalPlayersIntoTeam(); // move all local players into team marked by this label }; // list of unassigned savegame recreation players class FreeSavegamePlayersListItem : public ListItem { private: // subcomponents C4GUI::Icon *pIcon; C4GUI::Label *pNameLabel; public: FreeSavegamePlayersListItem(C4PlayerInfoListBox *pForListBox, ListItem *pInsertBefore); // ctor // spacing inserted between of those list items; usually this is top anyway... virtual bool ListItemTopSpacingBar() { return true; } int32_t GetListItemTopSpacing() override { return ClientListBoxSpacing; } public: void Update() override; }; // list of script players (both savegame recreation and regular) class ScriptPlayersListItem : public ListItem { private: // subcomponents C4GUI::Icon *pIcon; C4GUI::Label *pNameLabel; C4GUI::IconButton *btnAddPlayer; public: ScriptPlayersListItem(C4PlayerInfoListBox *pForListBox, ListItem *pInsertBefore); // ctor // spacing inserted between of those list items; usually this is top anyway... virtual bool ListItemTopSpacingBar() { return true; } int32_t GetListItemTopSpacing() override { return ClientListBoxSpacing; } protected: void OnBtnAddPlr(C4GUI::Control *btn); public: void Update() override; }; // list of players in record (currently not used, because replays in network are not allowed :C) class ReplayPlayersListItem : public ListItem { private: // subcomponents C4GUI::Icon *pIcon; C4GUI::Label *pNameLabel; public: ReplayPlayersListItem(C4PlayerInfoListBox *pForListBox, ListItem *pInsertBefore); // ctor // spacing inserted between of those list items; usually this is top anyway... bool GetListItemTopSpacingBar() override { return true; } int32_t GetListItemTopSpacing() override { return ClientListBoxSpacing; } }; // ----------------------------------------------------------------------------------------------- private: Mode eMode; int32_t iMaxUncollapsedPlayers; // maximum number of players that can be displayed without collapse - valid only if fIsCollapsed bool fIsCollapsed; int32_t iTeamFilter; // if nonzero, only playeers of this team are shown in the listbox uint32_t dwTextColor; CStdFont *pCustomFont; enum AddMode { AM_Winners, AM_Losers, AM_All }; void UpdateSavegamePlayers(ListItem **ppCurrInList); void UpdateReplayPlayers(ListItem **ppCurrInList); void UpdateScriptPlayers(ListItem **ppCurrInList); void UpdatePlayersByTeam(ListItem **ppCurrInList); void UpdatePlayersByRandomTeam(ListItem **ppCurrInList); void UpdatePlayersByClient(ListItem **ppCurrInList); void UpdatePlayersByEvaluation(ListItem **ppCurrInList, bool fShowWinners); void UpdatePlayersByEvaluation(ListItem **ppCurrInList, C4Team *pTeam, AddMode eAddMode); ListItem *GetPlayerListItem(ListItem::ID::IDType eType, int32_t id); // search for a player list item bool PlrListItemUpdate(ListItem::ID::IDType eType, int32_t id, class ListItem **pEnsurePos); // search for player list item with given ID in the list starting at ensurepos; ensure it's positioned at given pos; update and return true if found bool IsEvaluation() const { return eMode == PILBM_Evaluation || eMode == PILBM_EvaluationNoWinners; } bool IsLobby() const { return eMode == PILBM_LobbyClientSort || eMode == PILBM_LobbyTeamSort; } bool IsTeamFilter() const { return !!iTeamFilter; } protected: bool IsPlayerItemCollapsed(PlayerListItem *pItem); // CB from list item: return true if it should be shown small void OnPlrListSelChange(class C4GUI::Element *pEl) { Update(); } uint32_t GetTextColor() const { return dwTextColor; } CStdFont *GetCustomFont() const { return pCustomFont; } public: C4PlayerInfoListBox(const C4Rect &rcBounds, Mode eMode, int32_t iTeamFilter=0); ~C4PlayerInfoListBox() override = default; void Update(); // update player list void SetClientSoundIcon(int32_t iForClientID); void SetMode(Mode eNewMode); void SetTeamFilter(int32_t idNewTeamFilter) { iTeamFilter = idNewTeamFilter; } void SetCustomFont(CStdFont *pNewFont, uint32_t dwTextColor); Mode GetMode() const { return eMode; } friend class PlayerListItem; friend class TeamListItem; }; #endif // INC_C4PlayerInfoListBox