forked from Mirrors/openclonk
350 lines
13 KiB
C++
350 lines
13 KiB
C++
/*
|
|
* 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
|