| 1 | /* |
| 2 | * LegacyClonk |
| 3 | * |
| 4 | * Copyright (c) RedWolf Design |
| 5 | * Copyright (c) 2005, Sven2 |
| 6 | * Copyright (c) 2017-2020, The LegacyClonk Team and contributors |
| 7 | * |
| 8 | * Distributed under the terms of the ISC license; see accompanying file |
| 9 | * "COPYING" for details. |
| 10 | * |
| 11 | * "Clonk" is a registered trademark of Matthes Bender, used with permission. |
| 12 | * See accompanying file "TRADEMARK" for details. |
| 13 | * |
| 14 | * To redistribute this file separately, substitute the full license texts |
| 15 | * for the above references. |
| 16 | */ |
| 17 | |
| 18 | // Startup screen for non-parameterized engine start: Player selection dialog |
| 19 | // Also contains player creation, editing and crew management |
| 20 | |
| 21 | #pragma once |
| 22 | |
| 23 | #include "C4InfoCore.h" |
| 24 | #include "C4Group.h" |
| 25 | #include "C4Startup.h" |
| 26 | |
| 27 | // startup dialog: Player selection |
| 28 | class C4StartupPlrSelDlg : public C4StartupDlg |
| 29 | { |
| 30 | private: |
| 31 | enum Mode { PSDM_Player = 0, PSDM_Crew }; // player selection list, or crew editing mode |
| 32 | enum { IconLabelSpacing = 2 }; // space between an icon and its text |
| 33 | |
| 34 | private: |
| 35 | // one item in the player or crew list |
| 36 | class ListItem : public C4GUI::Control |
| 37 | { |
| 38 | private: |
| 39 | typedef C4GUI::Window BaseClass; |
| 40 | // subcomponents |
| 41 | |
| 42 | protected: |
| 43 | C4GUI::CheckBox *pCheck; // check box to mark participation |
| 44 | C4GUI::Label *pNameLabel; // item caption |
| 45 | class C4StartupPlrSelDlg *pPlrSelDlg; |
| 46 | C4GUI::Icon *pIcon; // item icon |
| 47 | |
| 48 | private: |
| 49 | class C4KeyBinding *pKeyCheck; // space activates/deactivates selected player |
| 50 | C4FacetExSurface fctPortrait, fctPortraitBase; // big portrait |
| 51 | StdStrBuf Filename; // file info was loaded from |
| 52 | |
| 53 | public: |
| 54 | ListItem(C4StartupPlrSelDlg *pForDlg, C4GUI::ListBox *pForListBox, C4GUI::Element *pInsertBeforeElement = nullptr, bool fActivated = false); |
| 55 | virtual ~ListItem(); |
| 56 | |
| 57 | protected: |
| 58 | virtual C4GUI::ContextMenu *() = 0; |
| 59 | |
| 60 | C4GUI::ContextMenu *(C4GUI::Element *pEl, int32_t iX, int32_t iY) |
| 61 | { |
| 62 | return ContextMenu(); |
| 63 | } |
| 64 | |
| 65 | void LoadPortrait(C4Group &rGrp, bool fUseDefault); |
| 66 | void CreateColoredPortrait(); |
| 67 | void SetDefaultPortrait(); |
| 68 | |
| 69 | virtual void UpdateOwnPos() override; // recalculate item positioning |
| 70 | bool KeyCheck() { pCheck->ToggleCheck(fByUser: true); return true; } |
| 71 | virtual bool IsFocusOnClick() override { return false; } // do not focus; keep focus on listbox |
| 72 | |
| 73 | void SetName(const char *szNewName); |
| 74 | void SetIcon(C4GUI::Icons icoNew); |
| 75 | |
| 76 | void SetFilename(const StdStrBuf &sNewFN); |
| 77 | |
| 78 | public: |
| 79 | ListItem *GetNext() const { return static_cast<ListItem *>(BaseClass::GetNext()); } |
| 80 | const C4FacetEx &GetPortrait() const { return fctPortrait; } |
| 81 | virtual uint32_t GetColorDw() const = 0; // get drawing color for portrait |
| 82 | bool IsActivated() const { return pCheck->GetChecked(); } |
| 83 | void SetActivated(bool fToVal) { pCheck->SetChecked(fToVal); } |
| 84 | const char *GetName() const; |
| 85 | virtual void SetSelectionInfo(C4GUI::TextWindow *pSelectionInfo) = 0; // clears text field and writes selection info text into it |
| 86 | const StdStrBuf &GetFilename() const { return Filename; } |
| 87 | virtual std::string GetDelWarning() = 0; |
| 88 | void GrabIcon(C4FacetExSurface &rFromFacet); |
| 89 | void GrabPortrait(C4FacetExSurface *pFromFacet); |
| 90 | |
| 91 | virtual bool CheckNameHotkey(const char *c) override; // return whether this item can be selected by entering given char |
| 92 | |
| 93 | class LoadError : public std::runtime_error |
| 94 | { |
| 95 | public: |
| 96 | using runtime_error::runtime_error; |
| 97 | }; // class thrown off load function if load failed |
| 98 | }; |
| 99 | |
| 100 | public: |
| 101 | // a list item when in player selection mode |
| 102 | class PlayerListItem : public ListItem |
| 103 | { |
| 104 | private: |
| 105 | C4PlayerInfoCore Core; // player info core loaded from player file |
| 106 | bool fHasCustomIcon; // set for players with a BigIcon.png |
| 107 | |
| 108 | public: |
| 109 | PlayerListItem(C4StartupPlrSelDlg *pForDlg, C4GUI::ListBox *pForListBox, C4GUI::Element *pInsertBeforeElement = nullptr, bool fActivated = false); |
| 110 | ~PlayerListItem() {} |
| 111 | |
| 112 | void Load(const StdStrBuf &rsFilename); // may throw LoadError |
| 113 | |
| 114 | protected: |
| 115 | virtual C4GUI::ContextMenu *() override; |
| 116 | |
| 117 | public: |
| 118 | const C4PlayerInfoCore &GetCore() const { return Core; } |
| 119 | void UpdateCore(C4PlayerInfoCore &NewCore); // Save Core to disk and update this item |
| 120 | void GrabCustomIcon(C4FacetExSurface &fctGrabFrom); |
| 121 | virtual void SetSelectionInfo(C4GUI::TextWindow *pSelectionInfo) override; |
| 122 | virtual uint32_t GetColorDw() const override { return Core.PrefColorDw; } |
| 123 | virtual std::string GetDelWarning() override; |
| 124 | bool MoveFilename(const char *szToFilename); // change filename to given |
| 125 | }; |
| 126 | |
| 127 | private: |
| 128 | // a list item when in crew editing mode |
| 129 | class CrewListItem : public ListItem |
| 130 | { |
| 131 | private: |
| 132 | bool fLoaded; |
| 133 | C4ObjectInfoCore Core; |
| 134 | uint32_t dwPlrClr; |
| 135 | C4Group *pParentGrp; |
| 136 | |
| 137 | public: |
| 138 | CrewListItem(C4StartupPlrSelDlg *pForDlg, C4GUI::ListBox *pForListBox, uint32_t dwPlrClr); |
| 139 | ~CrewListItem() {} |
| 140 | |
| 141 | void Load(C4Group &rGrp, const StdStrBuf &rsFilename); // may throw LoadError |
| 142 | |
| 143 | protected: |
| 144 | virtual C4GUI::ContextMenu *() override; |
| 145 | |
| 146 | void RewriteCore(); |
| 147 | |
| 148 | struct RenameParams {}; |
| 149 | void AbortRenaming(RenameParams par); |
| 150 | C4GUI::RenameResult DoRenaming(RenameParams par, const char *szNewName); |
| 151 | |
| 152 | private: |
| 153 | std::string GetPhysicalTextLine(int32_t iPhysValue, C4ResStrTableKeyFormat<> idsName); // get string for physical info bar |
| 154 | |
| 155 | public: |
| 156 | void UpdateClonkEnabled(); |
| 157 | |
| 158 | virtual uint32_t GetColorDw() const override { return dwPlrClr; } // get drawing color for portrait |
| 159 | virtual void SetSelectionInfo(C4GUI::TextWindow *pSelectionInfo) override; // clears text field and writes selection info text into it |
| 160 | virtual std::string GetDelWarning() override; |
| 161 | const C4ObjectInfoCore &GetCore() const { return Core; } |
| 162 | |
| 163 | CrewListItem *GetNext() const { return static_cast<CrewListItem *>(ListItem::GetNext()); } |
| 164 | |
| 165 | void CrewRename(); // shows the edit-field to rename a crew member |
| 166 | bool SetName(const char *szNewName); // update clonk name and core |
| 167 | void OnDeathMessageCtx(C4GUI::Element *el); |
| 168 | void OnDeathMessageSet(const StdStrBuf &rsNewMessage); |
| 169 | }; |
| 170 | |
| 171 | public: |
| 172 | C4StartupPlrSelDlg(); |
| 173 | ~C4StartupPlrSelDlg(); |
| 174 | |
| 175 | private: |
| 176 | class C4KeyBinding *pKeyBack, *pKeyProperties, *pKeyCrew, *pKeyDelete, *pKeyRename, *pKeyNew; |
| 177 | class C4GUI::ListBox *pPlrListBox; |
| 178 | C4GUI::TextWindow *pSelectionInfo; |
| 179 | class C4GUI::Picture *pPortraitPict; |
| 180 | Mode eMode; |
| 181 | |
| 182 | // in crew mode: |
| 183 | struct CurrPlayer_t |
| 184 | { |
| 185 | C4PlayerInfoCore Core; // loaded player main core |
| 186 | C4Group Grp; // group to player file; opened when in crew mode |
| 187 | } |
| 188 | CurrPlayer; |
| 189 | |
| 190 | private: |
| 191 | C4Rect rcBottomButtons; int32_t iBottomButtonWidth; |
| 192 | class C4GUI::Button *btnActivatePlr, *btnCrew, *btnProperties, *btnDelete, *btnBack, *btnNew; |
| 193 | |
| 194 | void UpdateBottomButtons(); // update command button texts and positions |
| 195 | void UpdatePlayerList(); // refill pPlrListBox with players in player folder, or with crew in selected player |
| 196 | void UpdateSelection(); |
| 197 | void OnSelChange(class C4GUI::Element *pEl) { UpdateSelection(); } |
| 198 | void OnSelDblClick(class C4GUI::Element *pEl) { C4GUI::GUISound(szSound: "Click" ); OnPropertyBtn(btn: nullptr); } |
| 199 | void UpdateActivatedPlayers(); // update Config.General.Participants by currently activated players |
| 200 | void SelectItem(const std::string &filename, bool fActivate); // find item by filename and select (and activate it, if desired) |
| 201 | |
| 202 | void SetPlayerMode(); // change view to listing players |
| 203 | void SetCrewMode(PlayerListItem *pForPlayer); // change view to listing crew of a player |
| 204 | |
| 205 | static int32_t CrewSortFunc(const C4GUI::Element *pEl1, const C4GUI::Element *pEl2, void *par); |
| 206 | void ResortCrew(); |
| 207 | |
| 208 | protected: |
| 209 | void OnItemCheckChange(C4GUI::Element *pCheckBox); |
| 210 | static bool CheckPlayerName(const StdStrBuf &Playername, std::string &filename, const StdStrBuf *pPrevFilename, bool fWarnEmpty); |
| 211 | ListItem *GetSelection(); |
| 212 | void SetSelection(ListItem *pNewItem); |
| 213 | |
| 214 | C4GUI::RenameEdit *pRenameEdit; // hack: set by crew list item renaming. Must be cleared when something is done in the dlg |
| 215 | void AbortRenaming(); |
| 216 | |
| 217 | friend class ListItem; friend class PlayerListItem; friend class CrewListItem; |
| 218 | friend class C4StartupPlrPropertiesDlg; |
| 219 | |
| 220 | protected: |
| 221 | virtual int32_t GetMarginTop() override { return (rcBounds.Hgt / 7); } |
| 222 | virtual bool HasBackground() override { return true; } |
| 223 | virtual void DrawElement(C4FacetEx &cgo) override; |
| 224 | |
| 225 | virtual bool OnEnter() override { return false; } // Enter ignored |
| 226 | virtual bool OnEscape() override { DoBack(); return true; } |
| 227 | bool KeyBack() { DoBack(); return true; } |
| 228 | bool KeyProperties() { OnPropertyBtn(btn: nullptr); return true; } |
| 229 | bool KeyCrew() { OnCrewBtn (btn: nullptr); return true; } |
| 230 | bool KeyDelete() { OnDelBtn (btn: nullptr); return true; } |
| 231 | bool KeyNew() { OnNewBtn (btn: nullptr); return true; } |
| 232 | |
| 233 | void OnNewBtn(C4GUI::Control *btn); |
| 234 | void OnActivateBtn(C4GUI::Control *btn); |
| 235 | void OnPropertyBtn(C4GUI::Control *btn); |
| 236 | void OnPropertyCtx(C4GUI::Element *el) { OnPropertyBtn(btn: nullptr); } |
| 237 | void OnCrewBtn(C4GUI::Control *btn); |
| 238 | void OnDelBtn(C4GUI::Control *btn); |
| 239 | void OnDelCtx(C4GUI::Element *el) { OnDelBtn(btn: nullptr); } |
| 240 | void OnDelBtnConfirm(ListItem *pSel); |
| 241 | void OnBackBtn(C4GUI::Control *btn) { DoBack(); } |
| 242 | |
| 243 | public: |
| 244 | void DoBack(); // back to main menu |
| 245 | }; |
| 246 | |
| 247 | // player creation or property editing dialog |
| 248 | class C4StartupPlrPropertiesDlg : public C4GUI::Dialog |
| 249 | { |
| 250 | protected: |
| 251 | C4StartupPlrSelDlg *pMainDlg; // may be nullptr if shown as creation dialog in main menu! |
| 252 | C4StartupPlrSelDlg::PlayerListItem *pForPlayer; |
| 253 | C4GUI::Edit *pNameEdit; // player name edit box |
| 254 | C4GUI::Picture *pClrPreview; |
| 255 | C4GUI::ScrollBar *pClrSliderR, *pClrSliderG, *pClrSliderB; |
| 256 | C4GUI::Picture *pCtrlImg; |
| 257 | C4GUI::IconButton *pMouseBtn, *pJumpNRunBtn, *pClassicBtn, *pPictureBtn; |
| 258 | C4PlayerInfoCore C4P; // player info core copy currently being edited |
| 259 | C4FacetExSurface fctOldBigIcon; |
| 260 | C4FacetExSurface fctNewPicture, fctNewBigIcon; // if assigned, save new picture/bigicon |
| 261 | bool fClearPicture, fClearBigIcon; // if true, delete current picture/bigicon |
| 262 | virtual const char *GetID() override { return "PlrPropertiesDlg" ; } |
| 263 | |
| 264 | void DrawElement(C4FacetEx &cgo) override; |
| 265 | virtual int32_t GetMarginTop() override { return 16; } |
| 266 | virtual int32_t GetMarginLeft() override { return 45; } |
| 267 | virtual int32_t GetMarginRight() override { return 55; } |
| 268 | virtual int32_t GetMarginBottom() override { return 30; } |
| 269 | |
| 270 | virtual void UserClose(bool fOK) override; // OK only with a valid name |
| 271 | virtual bool IsComponentOutsideClientArea() override { return true; } // OK and close btn |
| 272 | |
| 273 | void OnClrChangeLeft(C4GUI::Control *pBtn); |
| 274 | void OnClrChangeRight(C4GUI::Control *pBtn); |
| 275 | void OnClrSliderRChange(int32_t iNewVal); |
| 276 | void OnClrSliderGChange(int32_t iNewVal); |
| 277 | void OnClrSliderBChange(int32_t iNewVal); |
| 278 | void OnCtrlChangeLeft(C4GUI::Control *pBtn); |
| 279 | void OnCtrlChangeRight(C4GUI::Control *pBtn); |
| 280 | void OnCtrlChangeMouse(C4GUI::Control *pBtn); |
| 281 | void OnMovementBtn(C4GUI::Control *pBtn); |
| 282 | void OnPictureBtn(C4GUI::Control *pBtn); |
| 283 | |
| 284 | private: |
| 285 | void UpdatePlayerColor(bool fUpdateSliders); |
| 286 | void UpdatePlayerControl(); |
| 287 | void UpdatePlayerMovement(); // updates Jump'n'Run vs Classic |
| 288 | void UpdateBigIcon(); |
| 289 | |
| 290 | bool SetNewPicture(C4Surface &srcSfc, C4FacetExSurface *trgFct, int32_t iMaxSize, bool fColorize); |
| 291 | void SetNewPicture(const char *szFromFilename, bool fSetPicture, bool fSetBigIcon); // set new picture/bigicon by loading and scaling if necessary. If szFromFilename==nullptr, clear picture/bigicon |
| 292 | |
| 293 | public: |
| 294 | C4StartupPlrPropertiesDlg(C4StartupPlrSelDlg::PlayerListItem *pForPlayer, C4StartupPlrSelDlg *pMainDlg); |
| 295 | ~C4StartupPlrPropertiesDlg() {} |
| 296 | |
| 297 | virtual void OnClosed(bool fOK) override; // close CB |
| 298 | }; |
| 299 | |