| 1 | /* |
| 2 | * LegacyClonk |
| 3 | * |
| 4 | * Copyright (c) RedWolf Design |
| 5 | * Copyright (c) 2005, Sven2 |
| 6 | * Copyright (c) 2017-2022, 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: Options dialog |
| 19 | |
| 20 | #include "C4GuiComboBox.h" |
| 21 | #include "C4GuiEdit.h" |
| 22 | #include "C4GuiResource.h" |
| 23 | #include "C4GuiTabular.h" |
| 24 | |
| 25 | #include <C4Include.h> |
| 26 | #include <C4StartupOptionsDlg.h> |
| 27 | #include <C4StartupOptionsAdvancedConfigDialog.h> |
| 28 | |
| 29 | #include <C4StartupMainDlg.h> |
| 30 | #include <C4Language.h> |
| 31 | #include <C4GamePadCon.h> |
| 32 | #include <C4Game.h> |
| 33 | #include <C4Log.h> |
| 34 | #include <C4Wrappers.h> |
| 35 | |
| 36 | #include <StdGL.h> |
| 37 | |
| 38 | class C4StartupOptionsDlg::ScaleEdit : public C4GUI::SpinBox<int32_t> |
| 39 | { |
| 40 | using Base = C4GUI::SpinBox<int32_t>; |
| 41 | C4StartupOptionsDlg *pDlg; |
| 42 | |
| 43 | public: |
| 44 | ScaleEdit(C4StartupOptionsDlg *pDlg, const C4Rect &rtBounds, bool fFocusEdit = false); |
| 45 | |
| 46 | protected: |
| 47 | virtual void OnTextChange() override; |
| 48 | virtual C4GUI::InputResult OnFinishInput(bool fPasting, bool fPastingMore) override; |
| 49 | }; |
| 50 | |
| 51 | class C4StartupOptionsDlg::EditConfig : public C4GUI::LabeledEdit |
| 52 | { |
| 53 | public: |
| 54 | EditConfig(const C4Rect &rcBounds, const char *szName, ValidatedStdStrBufBase *psConfigVal, int32_t *piConfigVal, bool fMultiline); |
| 55 | |
| 56 | private: |
| 57 | ValidatedStdStrBufBase *psConfigVal; |
| 58 | int32_t *piConfigVal; |
| 59 | |
| 60 | public: |
| 61 | void Save2Config(); // control to config |
| 62 | static bool GetControlSize(int *piWdt, int *piHgt, const char *szForText, bool fMultiline); |
| 63 | int32_t GetIntVal(); |
| 64 | void SetIntVal(int32_t iToVal); |
| 65 | }; |
| 66 | |
| 67 | // C4StartupOptionsDlg::SmallButton |
| 68 | |
| 69 | void C4StartupOptionsDlg::SmallButton::DrawElement(C4FacetEx &cgo) |
| 70 | { |
| 71 | // draw the button |
| 72 | CStdFont &rUseFont = C4Startup::Get()->Graphics.BookFont; |
| 73 | // get text pos |
| 74 | int32_t x0 = cgo.TargetX + rcBounds.x, y0 = cgo.TargetY + rcBounds.y, x1 = cgo.TargetX + rcBounds.x + rcBounds.Wdt, y1 = cgo.TargetY + rcBounds.y + rcBounds.Hgt; |
| 75 | int32_t iTextHgt = rUseFont.GetLineHeight(); |
| 76 | // draw frame |
| 77 | uint32_t dwClrHigh = C4StartupBtnBorderColor1, dwClrLow = C4StartupBtnBorderColor2; |
| 78 | if (fDown) std::swap(a&: dwClrHigh, b&: dwClrLow); |
| 79 | int32_t iIndent = BoundBy<int32_t>(bval: (rcBounds.Hgt - iTextHgt) / 3, lbound: 2, rbound: 5); |
| 80 | int iDrawQuadTop[8] = { x0, y0, x1, y0, x1 - iIndent, y0 + iIndent, x0, y0 + iIndent }; |
| 81 | int iDrawQuadLeft[8] = { x0, y0, x0 + iIndent, y0, x0 + iIndent, y1 - iIndent, x0, y1 }; |
| 82 | int iDrawQuadRight[8] = { x1, y0, x1, y1, x1 - iIndent, y1, x1 - iIndent, y0 + iIndent }; |
| 83 | int iDrawQuadBottom[8] = { x1, y1, x0, y1, x0 + iIndent, y1 - iIndent, x1, y1 - iIndent }; |
| 84 | lpDDraw->DrawQuadDw(sfcTarget: cgo.Surface, ipVtx: iDrawQuadTop, dwClr1: dwClrHigh, dwClr2: dwClrHigh, dwClr3: dwClrHigh, dwClr4: dwClrHigh); |
| 85 | lpDDraw->DrawQuadDw(sfcTarget: cgo.Surface, ipVtx: iDrawQuadLeft, dwClr1: dwClrHigh, dwClr2: dwClrHigh, dwClr3: dwClrHigh, dwClr4: dwClrHigh); |
| 86 | lpDDraw->DrawQuadDw(sfcTarget: cgo.Surface, ipVtx: iDrawQuadRight, dwClr1: dwClrLow, dwClr2: dwClrLow, dwClr3: dwClrLow, dwClr4: dwClrLow); |
| 87 | lpDDraw->DrawQuadDw(sfcTarget: cgo.Surface, ipVtx: iDrawQuadBottom, dwClr1: dwClrLow, dwClr2: dwClrLow, dwClr3: dwClrLow, dwClr4: dwClrLow); |
| 88 | // draw selection highlight |
| 89 | int32_t iTxtOff = fDown ? iIndent : 0; |
| 90 | if (fEnabled) if (HasDrawFocus() || (fMouseOver && IsInActiveDlg(fForKeyboard: false))) |
| 91 | { |
| 92 | lpDDraw->SetBlitMode(C4GFXBLIT_ADDITIVE); |
| 93 | C4GUI::GetRes()->fctButtonHighlight.DrawX(sfcTarget: cgo.Surface, iX: x0 + 5 + iTxtOff, iY: y0 + 3 + iTxtOff, iWdt: rcBounds.Wdt - 10, iHgt: rcBounds.Hgt - 6); |
| 94 | lpDDraw->ResetBlitMode(); |
| 95 | } |
| 96 | // draw button text |
| 97 | lpDDraw->TextOut(szText: sText.getData(), rFont&: rUseFont, fZoom: 1.0f, sfcDest: cgo.Surface, iTx: (x0 + x1) / 2 + iTxtOff, iTy: (y0 + y1 - iTextHgt) / 2 + iTxtOff, dwFCol: C4StartupBtnFontClr, byForm: ACenter, fDoMarkup: true); |
| 98 | } |
| 99 | |
| 100 | int32_t C4StartupOptionsDlg::SmallButton::GetDefaultButtonHeight() |
| 101 | { |
| 102 | // button height is used font height plus a small indent |
| 103 | CStdFont *pUseFont = &(C4Startup::Get()->Graphics.BookFont); |
| 104 | return pUseFont->GetLineHeight() * 6 / 5 + 6; |
| 105 | } |
| 106 | |
| 107 | // C4StartupOptionsDlg::ResChangeConfirmDlg |
| 108 | |
| 109 | C4StartupOptionsDlg::ResChangeConfirmDlg::ResChangeConfirmDlg() |
| 110 | : C4GUI::TimedDialog{12, "" , LoadResStr(id: C4ResStrTableKey::IDS_MNU_SWITCHRESOLUTION), C4GUI::MessageDialog::btnYesNo, C4GUI::Ico_None} |
| 111 | { |
| 112 | UpdateText(); |
| 113 | } |
| 114 | |
| 115 | void C4StartupOptionsDlg::ResChangeConfirmDlg::UpdateText() |
| 116 | { |
| 117 | StdStrBuf text; |
| 118 | C4GUI::GetRes()->TextFont.BreakMessage( |
| 119 | szMsg: LoadResStr(id: C4ResStrTableKey::IDS_MNU_SWITCHRESOLUTION_TEXT, args: GetRemainingTime()).c_str(), |
| 120 | iWdt: GetClientRect().Wdt, |
| 121 | pOut: &text, |
| 122 | fCheckMarkup: false |
| 123 | ); |
| 124 | SetText(text.getData()); |
| 125 | } |
| 126 | |
| 127 | // C4StartupOptionsDlg::ScaleEdit |
| 128 | |
| 129 | namespace |
| 130 | { |
| 131 | constexpr int minScale = 100; |
| 132 | constexpr int maxScale = 300; |
| 133 | } |
| 134 | |
| 135 | C4StartupOptionsDlg::ScaleEdit::ScaleEdit(C4StartupOptionsDlg *pDlg, const C4Rect &rtBounds, bool fFocusEdit) : Base{rtBounds, fFocusEdit, minScale, maxScale}, pDlg{pDlg} |
| 136 | { |
| 137 | SetColors(dwNewBGClr: C4StartupEditBGColor, dwNewFontClr: C4StartupFontClr, dwNewBorderColor: C4StartupEditBorderColor); |
| 138 | } |
| 139 | |
| 140 | void C4StartupOptionsDlg::ScaleEdit::OnTextChange() |
| 141 | { |
| 142 | Base::OnTextChange(); |
| 143 | const auto val = GetValue(); |
| 144 | const auto sliderVal = val - minScale; |
| 145 | pDlg->pScaleSlider->SetScrollPos(sliderVal); |
| 146 | pDlg->iNewScale = val; |
| 147 | } |
| 148 | |
| 149 | C4GUI::InputResult C4StartupOptionsDlg::ScaleEdit::OnFinishInput(bool fPasting, bool fPastingMore) |
| 150 | { |
| 151 | Base::OnFinishInput(pasting: fPasting, pastingMore: fPastingMore); |
| 152 | const auto val = GetValue(); |
| 153 | const auto sliderVal = val - minScale; |
| 154 | pDlg->pScaleSlider->SetScrollPos(sliderVal); |
| 155 | pDlg->OnScaleSliderChanged(val: sliderVal); |
| 156 | pDlg->OnTestScaleBtn(nullptr); |
| 157 | return C4GUI::IR_Abort; |
| 158 | } |
| 159 | |
| 160 | // C4StartupOptionsDlg::KeySelDialog |
| 161 | |
| 162 | const char *LoadKeyDescResStr(const int32_t iKeyID) |
| 163 | { |
| 164 | static constexpr C4ResStrTableKeyFormat<> KeyIDStringIDs[C4MaxKey] |
| 165 | { |
| 166 | C4ResStrTableKey::IDS_CTL_SELECTLEFT, C4ResStrTableKey::IDS_CTL_SELECTTOGGLE, C4ResStrTableKey::IDS_CTL_SELECTRIGHT, |
| 167 | C4ResStrTableKey::IDS_CTL_THROW, C4ResStrTableKey::IDS_CTL_UPJUMP, C4ResStrTableKey::IDS_CTL_DIG, |
| 168 | C4ResStrTableKey::IDS_CTL_LEFT, C4ResStrTableKey::IDS_CTL_DOWNSTOP, C4ResStrTableKey::IDS_CTL_RIGHT, |
| 169 | C4ResStrTableKey::IDS_CTL_PLAYERMENU, C4ResStrTableKey::IDS_CTL_SPECIAL1, C4ResStrTableKey::IDS_CTL_SPECIAL2 |
| 170 | }; |
| 171 | if (!Inside<int32_t>(ival: iKeyID, lbound: 0, rbound: C4MaxKey)) return nullptr; |
| 172 | return LoadResStr(id: KeyIDStringIDs[iKeyID]); |
| 173 | } |
| 174 | |
| 175 | C4StartupOptionsDlg::KeySelDialog::KeySelDialog(int32_t iKeyID, int32_t iCtrlSet, bool fGamepad) |
| 176 | : C4GUI::MessageDialog(LoadResStrChoice(condition: !fGamepad, ifTrue: C4ResStrTableKey::IDS_MSG_PRESSKEY, ifFalse: C4ResStrTableKey::IDS_MSG_PRESSBTN, |
| 177 | args: LoadKeyDescResStr(iKeyID), args: iCtrlSet + 1).c_str(), LoadResStr(id: C4ResStrTableKey::IDS_MSG_DEFINEKEY), |
| 178 | C4GUI::MessageDialog::btnAbort, fGamepad ? C4GUI::Ico_Gamepad : C4GUI::Ico_Keyboard, C4GUI::MessageDialog::dsRegular), |
| 179 | key(KEY_Undefined), fGamepad(fGamepad), iCtrlSet(iCtrlSet) |
| 180 | { |
| 181 | pKeyListener = new C4KeyBinding(C4KeyCodeEx(KEY_Any, KEYS_None), "DefineKey" , KEYSCOPE_Gui, new C4GUI::DlgKeyCBPassKey<C4StartupOptionsDlg::KeySelDialog>(*this, &C4StartupOptionsDlg::KeySelDialog::KeyDown), C4CustomKey::PRIO_PlrControl); |
| 182 | } |
| 183 | |
| 184 | C4StartupOptionsDlg::KeySelDialog::~KeySelDialog() |
| 185 | { |
| 186 | delete pKeyListener; |
| 187 | } |
| 188 | |
| 189 | bool C4StartupOptionsDlg::KeySelDialog::KeyDown(C4KeyCodeEx key) |
| 190 | { |
| 191 | // check if key is valid for this set |
| 192 | // do not mix gamepad and keyboard keys |
| 193 | if (Key_IsGamepad(key: key.Key) != fGamepad) return false; |
| 194 | // allow selected gamepad only |
| 195 | if (fGamepad && Key_GetGamepad(key: key.Key) != iCtrlSet) return false; |
| 196 | // okay, use it |
| 197 | this->key = key.Key; |
| 198 | Close(fOK: true); |
| 199 | return true; |
| 200 | } |
| 201 | |
| 202 | // C4StartupOptionsDlg::KeySelButton |
| 203 | |
| 204 | // key display arrangement - -1 denotes no key |
| 205 | // every key from 0 to C4MaxKey-1 MUST BE present here, or the engine will crash |
| 206 | const int32_t iKeyPosMaxX = 3, iKeyPosMaxY = 4; // arrange keys in a 4-by-5-array |
| 207 | const int32_t iKeyPosis[iKeyPosMaxY][iKeyPosMaxX] = |
| 208 | { |
| 209 | { 0, 1, 2 }, |
| 210 | { 3, 4, 5 }, |
| 211 | { 6, 7, 8 }, |
| 212 | { 9, 10, 11 } |
| 213 | }; |
| 214 | |
| 215 | void C4StartupOptionsDlg::KeySelButton::DrawElement(C4FacetEx &cgo) |
| 216 | { |
| 217 | // draw key |
| 218 | C4Facet cgoDraw(cgo.Surface, rcBounds.x + cgo.TargetX, rcBounds.y + cgo.TargetY, rcBounds.Wdt, rcBounds.Hgt); |
| 219 | Game.GraphicsResource.fctKey.Draw(cgo&: cgoDraw, fAspect: true, iPhaseX: fDown); |
| 220 | int32_t iKeyIndent = cgoDraw.Wdt / 5; |
| 221 | cgoDraw.X += iKeyIndent; cgoDraw.Wdt -= 2 * iKeyIndent; |
| 222 | cgoDraw.Y += iKeyIndent * 3 / 4; cgoDraw.Hgt -= 2 * iKeyIndent; |
| 223 | if (fDown) cgoDraw.Y += iKeyIndent / 2; |
| 224 | bool fDoHightlight = fHighlight || HasDrawFocus() || (fMouseOver && IsInActiveDlg(fForKeyboard: false)); |
| 225 | bool fHadBlitMod = false; uint32_t dwOldBlitModClr = 0xffffff; |
| 226 | if (!fDoHightlight) |
| 227 | { |
| 228 | uint32_t dwModClr = 0x7f7f7f; |
| 229 | if (fHadBlitMod = lpDDraw->GetBlitModulation(rdwColor&: dwOldBlitModClr)) |
| 230 | ModulateClr(dst&: dwModClr, src: dwOldBlitModClr); |
| 231 | lpDDraw->ActivateBlitModulation(dwWithClr: dwModClr); |
| 232 | } |
| 233 | Game.GraphicsResource.fctCommand.Draw(cgo&: cgoDraw, fAspect: true, iPhaseX: iKeyID, iPhaseY: 0); |
| 234 | if (!fDoHightlight) |
| 235 | if (fHadBlitMod) |
| 236 | lpDDraw->ActivateBlitModulation(dwWithClr: dwOldBlitModClr); |
| 237 | else |
| 238 | lpDDraw->DeactivateBlitModulation(); |
| 239 | // draw the labels - beside the key |
| 240 | float fZoom; |
| 241 | CStdFont &rUseFont = C4Startup::Get()->Graphics.GetBlackFontByHeight(iHgt: cgoDraw.Hgt / 2 + 5, pfZoom: &fZoom); |
| 242 | lpDDraw->TextOut(szText: LoadKeyDescResStr(iKeyID), rFont&: rUseFont, fZoom, sfcDest: cgo.Surface, iTx: cgo.TargetX + rcBounds.x + rcBounds.Wdt + 5, iTy: cgoDraw.Y - 3, dwFCol: fDoHightlight ? 0xffff0000 : C4StartupFontClr, byForm: ALeft, fDoMarkup: false); |
| 243 | lpDDraw->TextOut(szText: C4KeyCodeEx::KeyCode2String(wCode: key, fHumanReadable: true, fShort: false).c_str(), rFont&: rUseFont, fZoom, sfcDest: cgo.Surface, iTx: cgo.TargetX + rcBounds.x + rcBounds.Wdt + 5, iTy: cgoDraw.Y + cgoDraw.Hgt / 2, dwFCol: fDoHightlight ? 0xffff0000 : C4StartupFontClr, byForm: ALeft, fDoMarkup: false); |
| 244 | } |
| 245 | |
| 246 | C4StartupOptionsDlg::KeySelButton::KeySelButton(int32_t iKeyID, const C4Rect &rcBounds, char cHotkey) |
| 247 | : C4GUI::IconButton(C4GUI::Ico_None, rcBounds, cHotkey), iKeyID(iKeyID), key(KEY_Undefined) {} |
| 248 | |
| 249 | // C4StartupOptionsDlg::ControlConfigArea |
| 250 | |
| 251 | C4StartupOptionsDlg::ControlConfigArea::ControlConfigArea(const C4Rect &rcArea, int32_t iHMargin, int32_t iVMargin, bool fGamepad, C4StartupOptionsDlg *pOptionsDlg) |
| 252 | : C4GUI::Window(), fGamepad(fGamepad), pGamepadOpener(nullptr), pOptionsDlg(pOptionsDlg), pGUICtrl(nullptr) |
| 253 | { |
| 254 | CStdFont *pUseFont = &(C4Startup::Get()->Graphics.BookFont); |
| 255 | SetBounds(rcArea); |
| 256 | C4GUI::ComponentAligner caArea(rcArea, iHMargin, iVMargin, true); |
| 257 | // get number of control sets to be configured |
| 258 | iMaxControlSets = 1; // do not devide by zero |
| 259 | if (fGamepad && Application.pGamePadControl) |
| 260 | iMaxControlSets = (std::max)(a: 1, b: Application.pGamePadControl->GetGamePadCount()); |
| 261 | if (!fGamepad) |
| 262 | iMaxControlSets = C4MaxKeyboardSet; |
| 263 | ppKeyControlSetBtns = new C4GUI::IconButton *[iMaxControlSets]; |
| 264 | // top line buttons to select keyboard set or gamepad |
| 265 | C4Facet fctCtrlPic = fGamepad ? Game.GraphicsResource.fctGamepad : Game.GraphicsResource.fctKeyboard; |
| 266 | int32_t iCtrlSetWdt = caArea.GetWidth() - caArea.GetHMargin() * 2; |
| 267 | int32_t iCtrlSetHMargin = 5, iCtrlSetVMargin = 5; |
| 268 | int32_t iCtrlSetBtnWdt = BoundBy<int32_t>(bval: (iCtrlSetWdt - iMaxControlSets * iCtrlSetHMargin * 2) / iMaxControlSets, lbound: 5, rbound: fctCtrlPic.Wdt); |
| 269 | int32_t iCtrlSetBtnHgt = fctCtrlPic.GetHeightByWidth(iWidth: iCtrlSetBtnWdt); |
| 270 | iCtrlSetHMargin = (iCtrlSetWdt - iCtrlSetBtnWdt * iMaxControlSets) / (iMaxControlSets * 2); |
| 271 | C4GUI::ComponentAligner caKeyboardSetSel(caArea.GetFromTop(iHgt: 2 * iCtrlSetVMargin + iCtrlSetBtnHgt), iCtrlSetHMargin, iCtrlSetVMargin); |
| 272 | const char *szCtrlSetHotkeys = "1234567890" ; /* 2do */ |
| 273 | uint32_t i; |
| 274 | for (i = 0; i < static_cast<uint32_t>(iMaxControlSets); ++i) |
| 275 | { |
| 276 | char cCtrlSetHotkey = 0; |
| 277 | if (i <= strlen(s: szCtrlSetHotkeys)) cCtrlSetHotkey = szCtrlSetHotkeys[i]; |
| 278 | C4GUI::CallbackButton<C4StartupOptionsDlg::ControlConfigArea, C4GUI::IconButton> *pBtn = new C4GUI::CallbackButton<C4StartupOptionsDlg::ControlConfigArea, C4GUI::IconButton>(C4GUI::Ico_None, caKeyboardSetSel.GetFromLeft(iWdt: iCtrlSetBtnWdt), cCtrlSetHotkey, &C4StartupOptionsDlg::ControlConfigArea::OnCtrlSetBtn, this); |
| 279 | pBtn->SetFacet(rCpy: fctCtrlPic); |
| 280 | fctCtrlPic.X += fctCtrlPic.Wdt; |
| 281 | AddElement(pChild: ppKeyControlSetBtns[i] = pBtn); |
| 282 | pBtn->SetToolTip(LoadResStr(id: C4ResStrTableKey::IDS_MSG_SELECTKEYSET)); |
| 283 | } |
| 284 | iSelectedCtrlSet = fGamepad ? 0 : C4P_Control_Keyboard1; |
| 285 | caArea.ExpandTop(iByHgt: caArea.GetVMargin()); |
| 286 | AddElement(pChild: new C4GUI::HorizontalLine(caArea.GetFromTop(iHgt: 2))); |
| 287 | caArea.ExpandTop(iByHgt: caArea.GetVMargin()); |
| 288 | C4Facet &rfctKey = Game.GraphicsResource.fctKey; |
| 289 | int32_t iKeyAreaMaxWdt = caArea.GetWidth() - 2 * caArea.GetHMargin(), iKeyAreaMaxHgt = caArea.GetHeight() - 2 * caArea.GetVMargin(); |
| 290 | int32_t iKeyWdt = rfctKey.Wdt * 3 / 2, iKeyHgt = rfctKey.Hgt * 3 / 2; |
| 291 | int32_t iKeyUseWdt = iKeyWdt + iKeyHgt * 3; // add space for label |
| 292 | int32_t iKeyMargin = 20; |
| 293 | int32_t iKeyAreaWdt = (iKeyUseWdt + 2 * iKeyMargin) * iKeyPosMaxX, iKeyAreaHgt = (iKeyHgt + 2 * iKeyMargin) * iKeyPosMaxY; |
| 294 | if (iKeyAreaWdt > iKeyAreaMaxWdt || iKeyAreaHgt > iKeyAreaMaxHgt) |
| 295 | { |
| 296 | // scale down |
| 297 | float fScaleX = float(iKeyAreaMaxWdt) / float(std::max<int32_t>(a: iKeyAreaWdt, b: 1)), |
| 298 | fScaleY = float(iKeyAreaMaxHgt) / float(std::max<int32_t>(a: iKeyAreaHgt, b: 1)), fScale; |
| 299 | if (fScaleX > fScaleY) fScale = fScaleY; else fScale = fScaleX; |
| 300 | iKeyMargin = int32_t(fScale * iKeyMargin); |
| 301 | iKeyWdt = int32_t(fScale * iKeyWdt); |
| 302 | iKeyUseWdt = int32_t(fScale * iKeyUseWdt); |
| 303 | iKeyHgt = int32_t(fScale * iKeyHgt); |
| 304 | iKeyAreaWdt = int32_t(fScale * iKeyAreaWdt); |
| 305 | iKeyAreaHgt = int32_t(fScale * iKeyAreaHgt); |
| 306 | } |
| 307 | C4GUI::ComponentAligner caCtrlKeys(caArea.GetFromTop(iHgt: iKeyAreaHgt, iWdt: iKeyAreaWdt), 0, iKeyMargin); |
| 308 | int32_t iKeyNum; |
| 309 | for (int iY = 0; iY < iKeyPosMaxY; ++iY) |
| 310 | { |
| 311 | C4GUI::ComponentAligner caCtrlKeysLine(caCtrlKeys.GetFromTop(iHgt: iKeyHgt), iKeyMargin, 0); |
| 312 | for (int iX = 0; iX < iKeyPosMaxX; ++iX) |
| 313 | { |
| 314 | C4Rect rcKey = caCtrlKeysLine.GetFromLeft(iWdt: iKeyWdt); |
| 315 | caCtrlKeysLine.ExpandLeft(iByWdt: iKeyWdt - iKeyUseWdt); |
| 316 | if ((iKeyNum = iKeyPosis[iY][iX]) < 0) continue; |
| 317 | KeySelButton *pKeyBtn = new C4GUI::CallbackButton<C4StartupOptionsDlg::ControlConfigArea, KeySelButton>(iKeyNum, rcKey, 0 /* no hotkey :( */, &C4StartupOptionsDlg::ControlConfigArea::OnCtrlKeyBtn, this); |
| 318 | AddElement(pChild: KeyControlBtns[iKeyNum] = pKeyBtn); |
| 319 | pKeyBtn->SetToolTip(LoadKeyDescResStr(iKeyID: iKeyNum)); |
| 320 | } |
| 321 | } |
| 322 | // bottom area controls |
| 323 | caArea.ExpandBottom(iByHgt: -iKeyHgt / 2); |
| 324 | C4GUI::ComponentAligner caKeyBottomBtns(caArea.GetFromBottom(C4GUI_ButtonHgt), 2, 0); |
| 325 | // gamepad: Use for GUI |
| 326 | if (fGamepad) |
| 327 | { |
| 328 | int iWdt = 100, iHgt = 20; |
| 329 | const char *szResetText = LoadResStr(id: C4ResStrTableKey::IDS_CTL_GAMEPADFORMENU); |
| 330 | C4GUI::CheckBox::GetStandardCheckBoxSize(piWdt: &iWdt, piHgt: &iHgt, szForCaptionText: szResetText, pUseFont); |
| 331 | pGUICtrl = new C4GUI::CheckBox(caKeyBottomBtns.GetFromLeft(iWdt, iHgt), szResetText, !!Config.Controls.GamepadGuiControl); |
| 332 | pGUICtrl->SetOnChecked(new C4GUI::CallbackHandler<C4StartupOptionsDlg::ControlConfigArea>(this, &C4StartupOptionsDlg::ControlConfigArea::OnGUIGamepadCheckChange)); |
| 333 | pGUICtrl->SetToolTip(LoadResStr(id: C4ResStrTableKey::IDS_DESC_GAMEPADFORMENU)); |
| 334 | pGUICtrl->SetFont(pFont: pUseFont, dwEnabledClr: C4StartupFontClr, dwDisabledClr: C4StartupFontClrDisabled); |
| 335 | AddElement(pChild: pGUICtrl); |
| 336 | } |
| 337 | // reset button |
| 338 | const char *szBtnText = LoadResStr(id: C4ResStrTableKey::IDS_BTN_RESETKEYBOARD); |
| 339 | int32_t iButtonWidth = 100, iButtonHeight = 20; C4GUI::Button *btn; |
| 340 | C4GUI::GetRes()->CaptionFont.GetTextExtent(szText: szBtnText, rsx&: iButtonWidth, rsy&: iButtonHeight, fCheckMarkup: true); |
| 341 | C4Rect rcResetBtn = caKeyBottomBtns.GetFromRight(iWdt: std::min<int32_t>(a: iButtonWidth + iButtonHeight * 4, b: caKeyBottomBtns.GetInnerWidth())); |
| 342 | AddElement(pChild: btn = new C4GUI::CallbackButton<C4StartupOptionsDlg::ControlConfigArea, SmallButton>(szBtnText, rcResetBtn, &C4StartupOptionsDlg::ControlConfigArea::OnResetKeysBtn, this)); |
| 343 | btn->SetToolTip(LoadResStr(id: C4ResStrTableKey::IDS_MSG_RESETKEYSETS)); |
| 344 | |
| 345 | UpdateCtrlSet(); |
| 346 | } |
| 347 | |
| 348 | C4StartupOptionsDlg::ControlConfigArea::~ControlConfigArea() |
| 349 | { |
| 350 | delete[] ppKeyControlSetBtns; |
| 351 | delete pGamepadOpener; |
| 352 | } |
| 353 | |
| 354 | void C4StartupOptionsDlg::ControlConfigArea::OnCtrlSetBtn(C4GUI::Control *btn) |
| 355 | { |
| 356 | // select Ctrl set of pressed btn |
| 357 | int i; |
| 358 | for (i = 0; i < iMaxControlSets; ++i) |
| 359 | if (btn == ppKeyControlSetBtns[i]) |
| 360 | { |
| 361 | iSelectedCtrlSet = i; |
| 362 | break; |
| 363 | } |
| 364 | // update shown keys |
| 365 | UpdateCtrlSet(); |
| 366 | } |
| 367 | |
| 368 | void C4StartupOptionsDlg::ControlConfigArea::UpdateCtrlSet() |
| 369 | { |
| 370 | // selected keyboard set btn gets a highlight |
| 371 | int i; |
| 372 | for (i = 0; i < iMaxControlSets; ++i) |
| 373 | ppKeyControlSetBtns[i]->SetHighlight(i == iSelectedCtrlSet); |
| 374 | // update keys by config |
| 375 | if (fGamepad) |
| 376 | { |
| 377 | for (i = 0; i < C4MaxKey; ++i) |
| 378 | KeyControlBtns[i]->SetKey(Config.Gamepads[iSelectedCtrlSet].Button[i]); |
| 379 | } |
| 380 | else |
| 381 | for (i = 0; i < C4MaxKey; ++i) |
| 382 | KeyControlBtns[i]->SetKey(Config.Controls.Keyboard[iSelectedCtrlSet][i]); |
| 383 | // open gamepad |
| 384 | if (fGamepad && Config.General.GamepadEnabled) |
| 385 | { |
| 386 | if (!pGamepadOpener) pGamepadOpener = new C4GamePadOpener(iSelectedCtrlSet); |
| 387 | else pGamepadOpener->SetGamePad(iSelectedCtrlSet); |
| 388 | } |
| 389 | // show/hide gamepad-gui-control checkbox |
| 390 | if (fGamepad && pGUICtrl) |
| 391 | pGUICtrl->SetVisibility(iSelectedCtrlSet == 0); |
| 392 | } |
| 393 | |
| 394 | void C4StartupOptionsDlg::ControlConfigArea::OnCtrlKeyBtn(C4GUI::Control *btn) |
| 395 | { |
| 396 | // determine which key has been pressed |
| 397 | int32_t idKey; |
| 398 | for (idKey = 0; idKey < C4MaxKey; ++idKey) if (KeyControlBtns[idKey] == btn) break; |
| 399 | if (idKey == C4MaxKey) return; // can't happen |
| 400 | // show key selection dialog for it |
| 401 | KeySelDialog *pDlg = new KeySelDialog(idKey, iSelectedCtrlSet, fGamepad); |
| 402 | pDlg->SetDelOnClose(false); |
| 403 | bool fSuccess = GetScreen()->ShowModalDlg(pDlg, fDestruct: false); |
| 404 | C4KeyCode key = pDlg->GetKeyCode(); |
| 405 | delete pDlg; |
| 406 | if (!fSuccess) return; |
| 407 | // key defined: Set it |
| 408 | KeyControlBtns[idKey]->SetKey(key); |
| 409 | // and update config |
| 410 | if (fGamepad) |
| 411 | Config.Gamepads[iSelectedCtrlSet].Button[idKey] = key; |
| 412 | else |
| 413 | Config.Controls.Keyboard[iSelectedCtrlSet][idKey] = key; |
| 414 | } |
| 415 | |
| 416 | void C4StartupOptionsDlg::ControlConfigArea::OnResetKeysBtn(C4GUI::Control *btn) |
| 417 | { |
| 418 | // default keys and axis reset |
| 419 | if (fGamepad) |
| 420 | { |
| 421 | for (int i = 0; i < C4ConfigMaxGamepads; ++i) |
| 422 | Config.Gamepads[i].Reset(); |
| 423 | } |
| 424 | else |
| 425 | Config.Controls.ResetKeys(); |
| 426 | UpdateCtrlSet(); |
| 427 | } |
| 428 | |
| 429 | void C4StartupOptionsDlg::ControlConfigArea::OnGUIGamepadCheckChange(C4GUI::Element *pCheckBox) |
| 430 | { |
| 431 | // same as before? |
| 432 | bool fChecked = static_cast<C4GUI::CheckBox *>(pCheckBox)->GetChecked(); |
| 433 | if (fChecked == !!Config.Controls.GamepadGuiControl) return; |
| 434 | // reflect change |
| 435 | Config.Controls.GamepadGuiControl = fChecked; |
| 436 | Game.pGUI->UpdateGamepadGUIControlEnabled(); |
| 437 | pOptionsDlg->RecreateDialog(fFade: false); |
| 438 | } |
| 439 | |
| 440 | // C4StartupOptionsDlg::NetworkPortConfig |
| 441 | |
| 442 | C4StartupOptionsDlg::NetworkPortConfig::NetworkPortConfig(const C4Rect &rcBounds, const char *szName, int32_t *pConfigValue, int32_t iDefault) |
| 443 | : C4GUI::Window(), pConfigValue(pConfigValue) |
| 444 | { |
| 445 | CStdFont *pUseFont = &(C4Startup::Get()->Graphics.BookFont); |
| 446 | SetBounds(rcBounds); |
| 447 | C4GUI::ComponentAligner caMain(GetClientRect(), 0, 2, true); |
| 448 | bool fEnabled = (*pConfigValue != 0); |
| 449 | C4GUI::Label *pLbl = new C4GUI::Label(szName, caMain.GetFromTop(iHgt: pUseFont->GetLineHeight()), ALeft, C4StartupFontClr, pUseFont, false); |
| 450 | AddElement(pChild: pLbl); |
| 451 | C4GUI::ComponentAligner caBottomLine(caMain.GetAll(), 2, 0, false); |
| 452 | const char *szText = LoadResStr(id: C4ResStrTableKey::IDS_CTL_ACTIVE); |
| 453 | int iWdt = 100, iHgt = 12; |
| 454 | C4GUI::CheckBox::GetStandardCheckBoxSize(piWdt: &iWdt, piHgt: &iHgt, szForCaptionText: szText, pUseFont); |
| 455 | pEnableCheck = new C4GUI::CheckBox(caBottomLine.GetFromLeft(iWdt, iHgt), szText, fEnabled); |
| 456 | pEnableCheck->SetFont(pFont: pUseFont, dwEnabledClr: C4StartupFontClr, dwDisabledClr: C4StartupFontClrDisabled); |
| 457 | pEnableCheck->SetOnChecked(new C4GUI::CallbackHandler<C4StartupOptionsDlg::NetworkPortConfig>(this, &C4StartupOptionsDlg::NetworkPortConfig::OnEnabledCheckChange)); |
| 458 | AddElement(pChild: pEnableCheck); |
| 459 | pPortEdit = new C4GUI::SpinBox<std::int32_t>(caBottomLine.GetAll(), true); |
| 460 | pPortEdit->SetMinimum(1); |
| 461 | pPortEdit->SetMaximum(65535); |
| 462 | pPortEdit->SetColors(dwNewBGClr: C4StartupEditBGColor, dwNewFontClr: C4StartupFontClr, dwNewBorderColor: C4StartupEditBorderColor); |
| 463 | pPortEdit->SetFont(pUseFont); |
| 464 | pPortEdit->SetValue(value: fEnabled ? *pConfigValue : iDefault, user: false); |
| 465 | pPortEdit->SetMaxText(10); // 65535 is five characters long - but allow some more for easier editing |
| 466 | pPortEdit->SetVisibility(fEnabled); |
| 467 | AddElement(pChild: pPortEdit); |
| 468 | } |
| 469 | |
| 470 | void C4StartupOptionsDlg::NetworkPortConfig::OnEnabledCheckChange(C4GUI::Element *pCheckBox) |
| 471 | { |
| 472 | pPortEdit->SetVisibility(pEnableCheck->GetChecked()); |
| 473 | } |
| 474 | |
| 475 | void C4StartupOptionsDlg::NetworkPortConfig::SavePort() |
| 476 | { |
| 477 | *pConfigValue = GetPort(); |
| 478 | } |
| 479 | |
| 480 | int32_t C4StartupOptionsDlg::NetworkPortConfig::GetPort() |
| 481 | { |
| 482 | // controls to config |
| 483 | if (!pEnableCheck->GetChecked()) |
| 484 | return 0; |
| 485 | else |
| 486 | return pPortEdit->GetValue(); |
| 487 | } |
| 488 | |
| 489 | bool C4StartupOptionsDlg::NetworkPortConfig::GetControlSize(int *piWdt, int *piHgt) |
| 490 | { |
| 491 | CStdFont *pUseFont = &(C4Startup::Get()->Graphics.BookFont); |
| 492 | // get size needed for control |
| 493 | if (piWdt) |
| 494 | { |
| 495 | const char *szText = LoadResStr(id: C4ResStrTableKey::IDS_CTL_ACTIVE); |
| 496 | if (!C4GUI::CheckBox::GetStandardCheckBoxSize(piWdt, piHgt, szForCaptionText: szText, pUseFont)) return false; |
| 497 | *piWdt *= 2; |
| 498 | } |
| 499 | if (piHgt) *piHgt = C4GUI::Edit::GetCustomEditHeight(pUseFont) + pUseFont->GetLineHeight() + 2 * 4; |
| 500 | return true; |
| 501 | } |
| 502 | |
| 503 | // C4StartupOptionsDlg::NetworkServerAddressConfig |
| 504 | |
| 505 | C4StartupOptionsDlg::NetworkServerAddressConfig::NetworkServerAddressConfig(const C4Rect &rcBounds, const char *szName, bool *pbConfigEnableValue, char *szConfigAddressValue, int iTabWidth) |
| 506 | : C4GUI::Window(), pbConfigEnableValue(pbConfigEnableValue), szConfigAddressValue(szConfigAddressValue) |
| 507 | { |
| 508 | CStdFont *pUseFont = &(C4Startup::Get()->Graphics.BookFont); |
| 509 | SetBounds(rcBounds); |
| 510 | C4GUI::ComponentAligner caMain(GetClientRect(), 0, 2, true); |
| 511 | pEnableCheck = new C4GUI::CheckBox(caMain.GetFromLeft(iWdt: iTabWidth, iHgt: pUseFont->GetLineHeight()), szName, *pbConfigEnableValue); |
| 512 | pEnableCheck->SetFont(pFont: pUseFont, dwEnabledClr: C4StartupFontClr, dwDisabledClr: C4StartupFontClrDisabled); |
| 513 | pEnableCheck->SetOnChecked(new C4GUI::CallbackHandler<C4StartupOptionsDlg::NetworkServerAddressConfig>(this, &C4StartupOptionsDlg::NetworkServerAddressConfig::OnEnabledCheckChange)); |
| 514 | AddElement(pChild: pEnableCheck); |
| 515 | caMain.ExpandLeft(iByWdt: -2); |
| 516 | pAddressEdit = new C4GUI::Edit(caMain.GetAll(), true); |
| 517 | pAddressEdit->SetColors(dwNewBGClr: C4StartupEditBGColor, dwNewFontClr: C4StartupFontClr, dwNewBorderColor: C4StartupEditBorderColor); |
| 518 | pAddressEdit->SetFont(pUseFont); |
| 519 | pAddressEdit->InsertText(text: szConfigAddressValue, fUser: false); |
| 520 | pAddressEdit->SetMaxText(CFG_MaxString); |
| 521 | pAddressEdit->SetVisibility(*pbConfigEnableValue); |
| 522 | AddElement(pChild: pAddressEdit); |
| 523 | } |
| 524 | |
| 525 | void C4StartupOptionsDlg::NetworkServerAddressConfig::OnEnabledCheckChange(C4GUI::Element *pCheckBox) |
| 526 | { |
| 527 | // warn about using alternate servers |
| 528 | if (pEnableCheck->GetChecked()) |
| 529 | { |
| 530 | GetScreen()->ShowMessage(szMessage: LoadResStr(id: C4ResStrTableKey::IDS_NET_NOOFFICIALLEAGUE), szCaption: LoadResStr(id: C4ResStrTableKey::IDS_NET_QUERY_MASTERSRV), icoIcon: C4GUI::Ico_Notify, pbConfigDontShowAgainSetting: &Config.Startup.HideMsgNoOfficialLeague); |
| 531 | } |
| 532 | // callback when checkbox is ticked |
| 533 | pAddressEdit->SetVisibility(pEnableCheck->GetChecked()); |
| 534 | } |
| 535 | |
| 536 | void C4StartupOptionsDlg::NetworkServerAddressConfig::Save2Config() |
| 537 | { |
| 538 | // controls to config |
| 539 | *pbConfigEnableValue = pEnableCheck->GetChecked(); |
| 540 | SCopy(szSource: pAddressEdit->GetText(), sTarget: szConfigAddressValue, iMaxL: CFG_MaxString); |
| 541 | } |
| 542 | |
| 543 | bool C4StartupOptionsDlg::NetworkServerAddressConfig::GetControlSize(int *piWdt, int *piHgt, int *piTabPos, const char *szForText) |
| 544 | { |
| 545 | CStdFont *pUseFont = &(C4Startup::Get()->Graphics.BookFont); |
| 546 | int iWdt = 120; |
| 547 | C4GUI::CheckBox::GetStandardCheckBoxSize(piWdt: &iWdt, piHgt, szForCaptionText: szForText, pUseFont); |
| 548 | int32_t iEdtWdt = 120, iEdtHgt = 24; |
| 549 | pUseFont->GetTextExtent(szText: "sorgentelefon@treffpunktclonk.net" , rsx&: iEdtWdt, rsy&: iEdtHgt, fCheckMarkup: false); |
| 550 | if (piWdt) *piWdt = iWdt + iEdtWdt + 2; |
| 551 | if (piTabPos) *piTabPos = iWdt + 2; |
| 552 | if (piHgt) *piHgt = C4GUI::Edit::GetCustomEditHeight(pUseFont) + 2 * 2; |
| 553 | return true; |
| 554 | } |
| 555 | |
| 556 | // C4StartupOptionsDlg::BoolConfig |
| 557 | |
| 558 | C4StartupOptionsDlg::BoolConfig::BoolConfig(const C4Rect &rcBounds, const char *szName, bool *pbVal, bool fInvert, bool *pbRestartChangeCfgVal) |
| 559 | : C4GUI::CheckBox(rcBounds, szName, fInvert != *pbVal), pbVal(pbVal), fInvert(fInvert), pbRestartChangeCfgVal(pbRestartChangeCfgVal) |
| 560 | { |
| 561 | SetOnChecked(new C4GUI::CallbackHandler<BoolConfig>(this, &BoolConfig::OnCheckChange)); |
| 562 | } |
| 563 | |
| 564 | void C4StartupOptionsDlg::BoolConfig::OnCheckChange(C4GUI::Element *pCheckBox) |
| 565 | { |
| 566 | if (pbVal) *pbVal = (GetChecked() != fInvert); |
| 567 | if (pbRestartChangeCfgVal) GetScreen()->ShowMessage(szMessage: LoadResStr(id: C4ResStrTableKey::IDS_MSG_RESTARTCHANGECFG), szCaption: GetText(), |
| 568 | icoIcon: C4GUI::Ico_Notify, pbConfigDontShowAgainSetting: pbRestartChangeCfgVal); |
| 569 | } |
| 570 | |
| 571 | // C4StartupOptionsDlg::EditConfig |
| 572 | |
| 573 | C4StartupOptionsDlg::EditConfig::EditConfig(const C4Rect &rcBounds, const char *szName, ValidatedStdStrBufBase *psConfigVal, int32_t *piConfigVal, bool fMultiline) |
| 574 | : C4GUI::LabeledEdit(rcBounds, szName, fMultiline, psConfigVal ? psConfigVal->getData() : nullptr, &(C4Startup::Get()->Graphics.BookFont), C4StartupFontClr), psConfigVal(psConfigVal), piConfigVal(piConfigVal) |
| 575 | { |
| 576 | GetEdit()->SetColors(dwNewBGClr: C4StartupEditBGColor, dwNewFontClr: C4StartupFontClr, dwNewBorderColor: C4StartupEditBorderColor); |
| 577 | if (piConfigVal) SetIntVal(*piConfigVal); |
| 578 | GetEdit()->SetMaxText(CFG_MaxString); |
| 579 | } |
| 580 | |
| 581 | void C4StartupOptionsDlg::EditConfig::Save2Config() |
| 582 | { |
| 583 | // controls to config |
| 584 | if (psConfigVal) |
| 585 | psConfigVal->CopyValidated(szFromVal: GetEdit()->GetText()); |
| 586 | if (piConfigVal) |
| 587 | *piConfigVal = GetIntVal(); |
| 588 | } |
| 589 | |
| 590 | bool C4StartupOptionsDlg::EditConfig::GetControlSize(int *piWdt, int *piHgt, const char *szForText, bool fMultiline) |
| 591 | { |
| 592 | CStdFont *pUseFont = &(C4Startup::Get()->Graphics.BookFont); |
| 593 | typedef C4GUI::LabeledEdit BaseEdit; |
| 594 | return BaseEdit::GetControlSize(piWdt, piHgt, szForText, pForFont: pUseFont, fMultiline); |
| 595 | } |
| 596 | |
| 597 | struct |
| 598 | { |
| 599 | C4ResStrTableKeyFormat<> caption; |
| 600 | DisplayMode mode; |
| 601 | } static constexpr DisplayModes[] |
| 602 | { |
| 603 | {.caption: C4ResStrTableKey::IDS_MSG_FULLSCREEN, .mode: DisplayMode::Fullscreen}, |
| 604 | {.caption: C4ResStrTableKey::IDS_MSG_WINDOW, .mode: DisplayMode::Window} |
| 605 | }; |
| 606 | |
| 607 | // C4StartupOptionsDlg |
| 608 | |
| 609 | C4StartupOptionsDlg::C4StartupOptionsDlg() : C4StartupDlg(LoadResStrNoAmp(id: C4ResStrTableKey::IDS_DLG_OPTIONS).c_str()), fConfigSaved(false), fCanGoBack(true) |
| 610 | { |
| 611 | UpdateSize(); |
| 612 | bool fSmall = (GetClientRect().Wdt < 750); |
| 613 | CStdFont *pUseFont = &(C4Startup::Get()->Graphics.BookFont); |
| 614 | |
| 615 | // key bindings |
| 616 | C4CustomKey::CodeList keys; |
| 617 | keys.push_back(x: C4KeyCodeEx(K_BACK)); keys.push_back(x: C4KeyCodeEx(K_LEFT)); |
| 618 | pKeyBack = new C4KeyBinding(keys, "StartupOptionsBack" , KEYSCOPE_Gui, |
| 619 | new C4GUI::DlgKeyCB<C4StartupOptionsDlg>(*this, &C4StartupOptionsDlg::KeyBack), C4CustomKey::PRIO_Dlg); |
| 620 | keys.clear(); |
| 621 | keys.push_back(x: C4KeyCodeEx(K_F3)); // overloading global toggle with higher priority here, so a new name is required |
| 622 | pKeyToggleMusic = new C4KeyBinding(keys, "OptionsMusicToggle" , KEYSCOPE_Gui, |
| 623 | new C4GUI::DlgKeyCB<C4StartupOptionsDlg>(*this, &C4StartupOptionsDlg::KeyMusicToggle), C4CustomKey::PRIO_Dlg); |
| 624 | |
| 625 | // screen calculations |
| 626 | int32_t iButtonWidth, iCaptionFontHgt; |
| 627 | int32_t iButtonHeight = C4GUI_ButtonHgt; |
| 628 | C4GUI::GetRes()->CaptionFont.GetTextExtent(szText: "<< BACK" , rsx&: iButtonWidth, rsy&: iCaptionFontHgt, fCheckMarkup: true); |
| 629 | iButtonWidth *= 3; |
| 630 | int iIndentX1, iIndentX2, iIndentY1, iIndentY2; |
| 631 | if (fSmall) |
| 632 | { |
| 633 | iIndentX1 = 20; iIndentX2 = 1; |
| 634 | } |
| 635 | else |
| 636 | { |
| 637 | iIndentX1 = GetClientRect().Wdt / 40; |
| 638 | iIndentX2 = iIndentX1 / 2; |
| 639 | } |
| 640 | if (fSmall) |
| 641 | { |
| 642 | iIndentY1 = 1; iIndentY2 = 1; |
| 643 | } |
| 644 | else |
| 645 | { |
| 646 | iIndentY1 = GetClientRect().Hgt / 200; |
| 647 | iIndentY2 = std::max<int32_t>(a: 1, b: iIndentY1 / 2); |
| 648 | } |
| 649 | C4GUI::ComponentAligner caMain(GetClientRect(), 0, 0, true); |
| 650 | C4GUI::ComponentAligner caButtonArea(caMain.GetFromBottom(iHgt: caMain.GetHeight() / (fSmall ? 20 : 7)), 0, 0); |
| 651 | C4GUI::ComponentAligner caButtons(caButtonArea.GetCentered(iWdt: caMain.GetWidth() * 7 / 8, iHgt: iButtonHeight), 0, 0); |
| 652 | C4GUI::ComponentAligner caConfigArea(caMain.GetAll(), fSmall ? 0 : (caMain.GetWidth() * 69 / 1730), fSmall ? 0 : (caMain.GetHeight() / 200)); |
| 653 | |
| 654 | // back button |
| 655 | C4GUI::CallbackButton<C4StartupOptionsDlg> *btn; |
| 656 | AddElement(pChild: btn = new C4GUI::CallbackButton<C4StartupOptionsDlg>(LoadResStr(id: C4ResStrTableKey::IDS_BTN_BACK), caButtons.GetFromLeft(iWdt: iButtonWidth), &C4StartupOptionsDlg::OnBackBtn)); |
| 657 | btn->SetToolTip(LoadResStr(id: C4ResStrTableKey::IDS_DLGTIP_BACKMAIN)); |
| 658 | |
| 659 | // main config area tabular |
| 660 | pOptionsTabular = new C4GUI::Tabular(caConfigArea.GetAll(), C4GUI::Tabular::tbLeft); |
| 661 | pOptionsTabular->SetGfx(pafctBack: &C4Startup::Get()->Graphics.fctOptionsDlgPaper, pafctClip: &C4Startup::Get()->Graphics.fctOptionsTabClip, pafctIcons: &C4Startup::Get()->Graphics.fctOptionsIcons, paSheetCaptionFont: &C4Startup::Get()->Graphics.BookSmallFont, fResizeByAspect: true); |
| 662 | AddElement(pChild: pOptionsTabular); |
| 663 | C4GUI::Tabular::Sheet *pSheetGeneral = pOptionsTabular->AddSheet(szTitle: LoadResStr(id: C4ResStrTableKey::IDS_DLG_PROGRAM), icoTitle: 0); |
| 664 | C4GUI::Tabular::Sheet *pSheetGraphics = pOptionsTabular->AddSheet(szTitle: LoadResStr(id: C4ResStrTableKey::IDS_DLG_GRAPHICS), icoTitle: 1); |
| 665 | C4GUI::Tabular::Sheet *pSheetSound = pOptionsTabular->AddSheet(szTitle: LoadResStr(id: C4ResStrTableKey::IDS_DLG_SOUND), icoTitle: 2); |
| 666 | C4GUI::Tabular::Sheet *pSheetKeyboard = pOptionsTabular->AddSheet(szTitle: LoadResStr(id: C4ResStrTableKey::IDS_DLG_KEYBOARD), icoTitle: 3); |
| 667 | C4GUI::Tabular::Sheet *pSheetGamepad = pOptionsTabular->AddSheet(szTitle: LoadResStr(id: C4ResStrTableKey::IDS_DLG_GAMEPAD), icoTitle: 4); |
| 668 | C4GUI::Tabular::Sheet *pSheetNetwork = pOptionsTabular->AddSheet(szTitle: LoadResStr(id: C4ResStrTableKey::IDS_DLG_NETWORK), icoTitle: 5); |
| 669 | |
| 670 | C4GUI::CheckBox *pCheck; C4GUI::Label *pLbl; |
| 671 | int iCheckWdt = 100, iCheckHgt = 20, iEdit2Wdt = 100, iEdit2Hgt = 40; |
| 672 | BoolConfig::GetStandardCheckBoxSize(piWdt: &iCheckWdt, piHgt: &iCheckHgt, szForCaptionText: "Default text" , pUseFont); |
| 673 | EditConfig::GetControlSize(piWdt: &iEdit2Wdt, piHgt: &iEdit2Hgt, szForText: "Default text" , fMultiline: false); |
| 674 | |
| 675 | // page program |
| 676 | C4GUI::ComponentAligner caSheetProgram(pSheetGeneral->GetClientRect(), caMain.GetWidth() / 20, caMain.GetHeight() / 20, true); |
| 677 | // language |
| 678 | const char *szLangTip = LoadResStr(id: C4ResStrTableKey::IDS_MSG_SELECTLANG); |
| 679 | C4GUI::ComponentAligner caLanguage(caSheetProgram.GetGridCell(iSectX: 0, iSectXMax: 1, iSectY: 0, iSectYMax: 8, iSectSizeX: -1, iSectSizeY: -1, fCenterPos: true, iSectNumX: 1, iSectNumY: 2), 0, C4GUI_DefDlgSmallIndent, false); |
| 680 | C4GUI::ComponentAligner caLanguageBox(caLanguage.GetFromTop(iHgt: C4GUI::ComboBox::GetDefaultHeight()), 0, 0, false); |
| 681 | StdStrBuf sLangStr; sLangStr.Copy(pnData: LoadResStr(id: C4ResStrTableKey::IDS_CTL_LANGUAGE)); sLangStr.AppendChar(cChar: ':'); |
| 682 | int32_t w, q; |
| 683 | pUseFont->GetTextExtent(szText: sLangStr.getData(), rsx&: w, rsy&: q, fCheckMarkup: true); |
| 684 | pLbl = new C4GUI::Label(sLangStr.getData(), caLanguageBox.GetFromLeft(iWdt: w + C4GUI_DefDlgSmallIndent), ALeft, C4StartupFontClr, pUseFont, false); |
| 685 | pLbl->SetToolTip(szLangTip); |
| 686 | pSheetGeneral->AddElement(pChild: pLbl); |
| 687 | pUseFont->GetTextExtent(szText: "XX: Top Secret Language" , rsx&: w, rsy&: q, fCheckMarkup: true); |
| 688 | pLangCombo = new C4GUI::ComboBox(caLanguageBox.GetFromLeft(iWdt: (std::min)(a: w, b: caLanguageBox.GetWidth()))); |
| 689 | pLangCombo->SetToolTip(szLangTip); |
| 690 | pLangCombo->SetComboCB(new C4GUI::ComboBox_FillCallback<C4StartupOptionsDlg>(this, &C4StartupOptionsDlg::OnLangComboFill, &C4StartupOptionsDlg::OnLangComboSelChange)); |
| 691 | pLangCombo->SetColors(dwFontClr: C4StartupFontClr, dwBGClr: C4StartupEditBGColor, dwBorderClr: C4StartupEditBorderColor); |
| 692 | pLangCombo->SetFont(pUseFont); |
| 693 | pLangCombo->SetDecoration(&(C4Startup::Get()->Graphics.fctContext)); |
| 694 | pSheetGeneral->AddElement(pChild: pLangCombo); |
| 695 | pLangInfoLabel = new C4GUI::Label("" , caLanguage.GetFromTop(iHgt: C4GUI::GetRes()->TextFont.GetLineHeight() * 3), ALeft, C4StartupFontClr, pUseFont, false); |
| 696 | pLangInfoLabel->SetToolTip(szLangTip); |
| 697 | pSheetGeneral->AddElement(pChild: pLangInfoLabel); |
| 698 | UpdateLanguage(); |
| 699 | // font |
| 700 | const char *szFontTip = LoadResStr(id: C4ResStrTableKey::IDS_DESC_SELECTFONT); |
| 701 | C4GUI::ComponentAligner caFontBox(caSheetProgram.GetGridCell(iSectX: 0, iSectXMax: 1, iSectY: 2, iSectYMax: 9, iSectSizeX: -1, iSectSizeY: C4GUI::ComboBox::GetDefaultHeight(), fCenterPos: true), 0, 0, false); |
| 702 | StdStrBuf sFontStr; sFontStr.Copy(pnData: LoadResStr(id: C4ResStrTableKey::IDS_CTL_FONT)); sFontStr.AppendChar(cChar: ':'); |
| 703 | pUseFont->GetTextExtent(szText: sFontStr.getData(), rsx&: w, rsy&: q, fCheckMarkup: true); |
| 704 | pLbl = new C4GUI::Label(sFontStr.getData(), caFontBox.GetFromLeft(iWdt: w + C4GUI_DefDlgSmallIndent), ALeft, C4StartupFontClr, pUseFont, false); |
| 705 | pLbl->SetToolTip(szFontTip); |
| 706 | pSheetGeneral->AddElement(pChild: pLbl); |
| 707 | pUseFont->GetTextExtent(szText: "Comic Sans MS" , rsx&: w, rsy&: q, fCheckMarkup: true); |
| 708 | pFontFaceCombo = new C4GUI::ComboBox(caFontBox.GetFromLeft(iWdt: std::min<int32_t>(a: caFontBox.GetInnerWidth() * 3 / 4, b: w * 3))); |
| 709 | pFontFaceCombo->SetToolTip(szFontTip); |
| 710 | pFontFaceCombo->SetComboCB(new C4GUI::ComboBox_FillCallback<C4StartupOptionsDlg>(this, &C4StartupOptionsDlg::OnFontFaceComboFill, &C4StartupOptionsDlg::OnFontComboSelChange)); |
| 711 | pFontFaceCombo->SetColors(dwFontClr: C4StartupFontClr, dwBGClr: C4StartupEditBGColor, dwBorderClr: C4StartupEditBorderColor); |
| 712 | pFontFaceCombo->SetFont(pUseFont); |
| 713 | pFontFaceCombo->SetDecoration(&(C4Startup::Get()->Graphics.fctContext)); |
| 714 | caFontBox.ExpandLeft(iByWdt: -C4GUI_DefDlgSmallIndent); |
| 715 | pSheetGeneral->AddElement(pChild: pFontFaceCombo); |
| 716 | pFontSizeCombo = new C4GUI::ComboBox(caFontBox.GetFromLeft(iWdt: std::min<int32_t>(a: caFontBox.GetInnerWidth(), b: w))); |
| 717 | pFontSizeCombo->SetToolTip(LoadResStr(id: C4ResStrTableKey::IDS_DESC_FONTSIZE)); |
| 718 | pFontSizeCombo->SetComboCB(new C4GUI::ComboBox_FillCallback<C4StartupOptionsDlg>(this, &C4StartupOptionsDlg::OnFontSizeComboFill, &C4StartupOptionsDlg::OnFontComboSelChange)); |
| 719 | pFontSizeCombo->SetColors(dwFontClr: C4StartupFontClr, dwBGClr: C4StartupEditBGColor, dwBorderClr: C4StartupEditBorderColor); |
| 720 | pFontSizeCombo->SetFont(pUseFont); |
| 721 | pFontSizeCombo->SetDecoration(&(C4Startup::Get()->Graphics.fctContext)); |
| 722 | pSheetGeneral->AddElement(pChild: pFontSizeCombo); |
| 723 | UpdateFontControls(); |
| 724 | |
| 725 | // white chat |
| 726 | C4GUI::ComponentAligner caWhiteChat(caSheetProgram.GetGridCell(iSectX: 0, iSectXMax: 1, iSectY: 3, iSectYMax: 9, iSectSizeX: -1, iSectSizeY: C4GUI::ComboBox::GetDefaultHeight(), fCenterPos: true), 0, 0, false); |
| 727 | |
| 728 | StdStrBuf sWhiteChat(LoadResStr(id: C4ResStrTableKey::IDS_MNU_WHITECHAT), false); |
| 729 | sWhiteChat.AppendChar(cChar: ':'); |
| 730 | pUseFont->GetTextExtent(szText: sWhiteChat.getData(), rsx&: w, rsy&: q, fCheckMarkup: true); |
| 731 | pLbl = new C4GUI::Label(sWhiteChat.getData(), caWhiteChat.GetFromLeft(iWdt: w + C4GUI_DefDlgSmallIndent + C4GUI::ComboBox::GetDefaultHeight()), ALeft, C4StartupFontClr, pUseFont, false); |
| 732 | pLbl->SetToolTip(LoadResStr(id: C4ResStrTableKey::IDS_DESC_WHITECHAT)); |
| 733 | pSheetGeneral->AddElement(pChild: pLbl); |
| 734 | // - ingame |
| 735 | const auto szIngame = LoadResStr(id: C4ResStrTableKey::IDS_CTL_WHITECHAT_INGAME); |
| 736 | pUseFont->GetTextExtent(szText: szIngame, rsx&: w, rsy&: q, fCheckMarkup: true); |
| 737 | pCheck = new BoolConfig(caWhiteChat.GetFromLeft(iWdt: w + C4GUI_DefDlgSmallIndent + 2 * C4GUI::ComboBox::GetDefaultHeight()), szIngame, &Config.General.UseWhiteIngameChat); |
| 738 | pCheck->SetToolTip(LoadResStr(id: C4ResStrTableKey::IDS_DESC_WHITECHAT_INGAME)); |
| 739 | pCheck->SetFont(pFont: pUseFont, dwEnabledClr: C4StartupFontClr, dwDisabledClr: C4StartupFontClrDisabled); |
| 740 | pSheetGeneral->AddElement(pChild: pCheck); |
| 741 | // - lobby |
| 742 | const auto szLobby = LoadResStr(id: C4ResStrTableKey::IDS_CTL_WHITECHAT_LOBBY); |
| 743 | pUseFont->GetTextExtent(szText: szLobby, rsx&: w, rsy&: q, fCheckMarkup: true); |
| 744 | pCheck = new BoolConfig(caWhiteChat.GetFromLeft(iWdt: w + C4GUI_DefDlgSmallIndent + 2 * C4GUI::ComboBox::GetDefaultHeight()), szLobby, &Config.General.UseWhiteLobbyChat); |
| 745 | pCheck->SetToolTip(LoadResStr(id: C4ResStrTableKey::IDS_DESC_WHITECHAT_LOBBY)); |
| 746 | pCheck->SetFont(pFont: pUseFont, dwEnabledClr: C4StartupFontClr, dwDisabledClr: C4StartupFontClrDisabled); |
| 747 | pSheetGeneral->AddElement(pChild: pCheck); |
| 748 | |
| 749 | // timestamps |
| 750 | pCheck = new BoolConfig(caSheetProgram.GetGridCell(iSectX: 0, iSectXMax: 1, iSectY: 4, iSectYMax: 9, iSectSizeX: -1, iSectSizeY: iCheckHgt, fCenterPos: true), LoadResStr(id: C4ResStrTableKey::IDS_CTL_TIMESTAMPS), &Config.General.ShowLogTimestamps); |
| 751 | pCheck->SetToolTip(LoadResStr(id: C4ResStrTableKey::IDS_DESC_TIMESTAMPS)); |
| 752 | pCheck->SetFont(pFont: pUseFont, dwEnabledClr: C4StartupFontClr, dwDisabledClr: C4StartupFontClrDisabled); |
| 753 | pSheetGeneral->AddElement(pChild: pCheck); |
| 754 | |
| 755 | // preloading |
| 756 | pCheck = new BoolConfig{caSheetProgram.GetGridCell(iSectX: 0, iSectXMax: 1, iSectY: 5, iSectYMax: 9, iSectSizeX: -1, iSectSizeY: iCheckHgt, fCenterPos: true), LoadResStr(id: C4ResStrTableKey::IDS_CTL_PRELOADING), &Config.General.Preloading}; |
| 757 | pCheck->SetToolTip(LoadResStr(id: C4ResStrTableKey::IDS_MSG_PRELOADING_DESC)); |
| 758 | pCheck->SetFont(pFont: pUseFont, dwEnabledClr: C4StartupFontClr, dwDisabledClr: C4StartupFontClrDisabled); |
| 759 | pSheetGeneral->AddElement(pChild: pCheck); |
| 760 | |
| 761 | // fair crew strength |
| 762 | C4GUI::GroupBox *pGroupFairCrewStrength = new C4GUI::GroupBox(caSheetProgram.GetGridCell(iSectX: 0, iSectXMax: 2, iSectY: 6, iSectYMax: 9, iSectSizeX: -1, iSectSizeY: pUseFont->GetLineHeight() * 2 + iIndentY2 * 2 + C4GUI_ScrollBarHgt, fCenterPos: true, iSectNumX: 1, iSectNumY: 2)); |
| 763 | pGroupFairCrewStrength->SetTitle(LoadResStr(id: C4ResStrTableKey::IDS_CTL_FAIRCREWSTRENGTH)); |
| 764 | pGroupFairCrewStrength->SetFont(pUseFont); |
| 765 | pGroupFairCrewStrength->SetColors(dwFrameClr: C4StartupEditBorderColor, dwTitleClr: C4StartupFontClr); |
| 766 | pSheetGeneral->AddElement(pChild: pGroupFairCrewStrength); |
| 767 | C4GUI::ComponentAligner caGroupFairCrewStrength(pGroupFairCrewStrength->GetClientRect(), 1, 0, true); |
| 768 | StdStrBuf sLabelTxt; sLabelTxt.Copy(pnData: LoadResStr(id: C4ResStrTableKey::IDS_CTL_FAIRCREWWEAK)); |
| 769 | w = 20; q = 12; pUseFont->GetTextExtent(szText: sLabelTxt.getData(), rsx&: w, rsy&: q, fCheckMarkup: true); |
| 770 | pGroupFairCrewStrength->AddElement(pChild: new C4GUI::Label(sLabelTxt.getData(), caGroupFairCrewStrength.GetFromLeft(iWdt: w, iHgt: q), ACenter, C4StartupFontClr, pUseFont, false, false)); |
| 771 | sLabelTxt.Copy(pnData: LoadResStr(id: C4ResStrTableKey::IDS_CTL_FAIRCREWSTRONG)); |
| 772 | pUseFont->GetTextExtent(szText: sLabelTxt.getData(), rsx&: w, rsy&: q, fCheckMarkup: true); |
| 773 | pGroupFairCrewStrength->AddElement(pChild: new C4GUI::Label(sLabelTxt.getData(), caGroupFairCrewStrength.GetFromRight(iWdt: w, iHgt: q), ACenter, C4StartupFontClr, pUseFont, false, false)); |
| 774 | C4GUI::ParCallbackHandler<C4StartupOptionsDlg, int32_t> *pCB = new C4GUI::ParCallbackHandler<C4StartupOptionsDlg, int32_t>(this, &C4StartupOptionsDlg::OnFairCrewStrengthSliderChange); |
| 775 | C4GUI::ScrollBar *pSlider = new C4GUI::ScrollBar(caGroupFairCrewStrength.GetCentered(iWdt: caGroupFairCrewStrength.GetInnerWidth(), C4GUI_ScrollBarHgt), true, pCB, 101); |
| 776 | pSlider->SetDecoration(pToGfx: &C4Startup::Get()->Graphics.sfctBookScroll, fAutoHide: false); |
| 777 | pGroupFairCrewStrength->SetToolTip(LoadResStr(id: C4ResStrTableKey::IDS_DESC_FAIRCREWSTRENGTH)); |
| 778 | pSlider->SetScrollPos(FairCrewStrength2Slider(iStrengthVal: Config.General.FairCrewStrength)); |
| 779 | pGroupFairCrewStrength->AddElement(pChild: pSlider); |
| 780 | // reset configuration |
| 781 | const char *szBtnText = LoadResStr(id: C4ResStrTableKey::IDS_BTN_RESETCONFIG); |
| 782 | C4GUI::CallbackButton<C4StartupOptionsDlg, SmallButton> *pSmallBtn; |
| 783 | C4GUI::GetRes()->CaptionFont.GetTextExtent(szText: szBtnText, rsx&: iButtonWidth, rsy&: iButtonHeight, fCheckMarkup: true); |
| 784 | C4Rect rcResetBtn = caSheetProgram.GetGridCell(iSectX: 1, iSectXMax: 2, iSectY: 8, iSectYMax: 9, iSectSizeX: std::min<int32_t>(a: iButtonWidth + iButtonHeight * 4, b: caSheetProgram.GetInnerWidth() * 2 / 5), iSectSizeY: SmallButton::GetDefaultButtonHeight(), fCenterPos: true); |
| 785 | pSheetGeneral->AddElement(pChild: pSmallBtn = new C4GUI::CallbackButton<C4StartupOptionsDlg, SmallButton>(szBtnText, rcResetBtn, &C4StartupOptionsDlg::OnResetConfigBtn, this)); |
| 786 | pSmallBtn->SetToolTip(LoadResStr(id: C4ResStrTableKey::IDS_DESC_RESETCONFIG)); |
| 787 | |
| 788 | szBtnText = LoadResStr(id: C4ResStrTableKey::IDS_DLG_ADVANCED_SETTINGS); |
| 789 | C4GUI::GetRes()->CaptionFont.GetTextExtent(szText: szBtnText, rsx&: iButtonWidth, rsy&: iButtonHeight, fCheckMarkup: true); |
| 790 | C4Rect rcAdvancedBtn = caSheetProgram.GetGridCell(iSectX: 0, iSectXMax: 2, iSectY: 8, iSectYMax: 9, iSectSizeX: std::min<int32_t>(a: iButtonWidth + iButtonHeight * 4, b: caSheetProgram.GetInnerWidth() * 2 / 5), iSectSizeY: SmallButton::GetDefaultButtonHeight(), fCenterPos: true); |
| 791 | pSheetGeneral->AddElement(pChild: pSmallBtn = new C4GUI::CallbackButton<C4StartupOptionsDlg, SmallButton>(szBtnText, rcAdvancedBtn, &C4StartupOptionsDlg::OnAdvancedConfigBtn, this)); |
| 792 | pSmallBtn->SetToolTip(LoadResStr(id: C4ResStrTableKey::IDS_DESC_ADVANCED_SETTINGS)); |
| 793 | |
| 794 | // page graphics |
| 795 | C4GUI::ComponentAligner caSheetGraphics(pSheetGraphics->GetClientRect(), iIndentX1, iIndentY1, true); |
| 796 | |
| 797 | C4GUI::GroupBox *pGroupDisplaySettings = new C4GUI::GroupBox(caSheetGraphics.GetGridCell(iSectX: 0, iSectXMax: 1, iSectY: 0, iSectYMax: 3)); |
| 798 | pGroupDisplaySettings->SetTitle(LoadResStrNoAmp(id: C4ResStrTableKey::IDS_CTL_DISPLAY).c_str()); |
| 799 | pGroupDisplaySettings->SetFont(pUseFont); |
| 800 | pGroupDisplaySettings->SetColors(dwFrameClr: C4StartupEditBorderColor, dwTitleClr: C4StartupFontClr); |
| 801 | pSheetGraphics->AddElement(pChild: pGroupDisplaySettings); |
| 802 | |
| 803 | C4GUI::ComponentAligner caDisplaySettings(pGroupDisplaySettings->GetClientRect(), iIndentX1, iIndentY2, true); |
| 804 | |
| 805 | C4GUI::ComponentAligner caDisplayModeRow(caDisplaySettings.GetGridCell(iSectX: 0, iSectXMax: 1, iSectY: 0, iSectYMax: 2, iSectSizeX: -1, iSectSizeY: C4GUI::ComboBox::GetDefaultHeight(), fCenterPos: true), 0, 0, false); |
| 806 | |
| 807 | StdStrBuf sDisplayModeStr; sDisplayModeStr.Copy(pnData: LoadResStr(id: C4ResStrTableKey::IDS_CTL_DISPLAYMODE)); sDisplayModeStr.AppendChar(cChar: ':'); |
| 808 | pUseFont->GetTextExtent(szText: sDisplayModeStr.getData(), rsx&: w, rsy&: q, fCheckMarkup: true); |
| 809 | pLbl = new C4GUI::Label(sDisplayModeStr.getData(), caDisplayModeRow.GetFromLeft(iWdt: w + C4GUI_DefDlgSmallIndent), ALeft, C4StartupFontClr, pUseFont, false); |
| 810 | pGroupDisplaySettings->AddElement(pChild: pLbl); |
| 811 | pDisplayModeCombo = new C4GUI::ComboBox(caDisplayModeRow.GetAll()); |
| 812 | pDisplayModeCombo->SetComboCB(new C4GUI::ComboBox_FillCallback<C4StartupOptionsDlg>(this, &C4StartupOptionsDlg::OnDisplayModeComboFill, &C4StartupOptionsDlg::OnDisplayModeComboSelChange)); |
| 813 | pDisplayModeCombo->SetColors(dwFontClr: C4StartupFontClr, dwBGClr: C4StartupEditBGColor, dwBorderClr: C4StartupEditBorderColor); |
| 814 | pDisplayModeCombo->SetFont(pUseFont); |
| 815 | pDisplayModeCombo->SetDecoration(&(C4Startup::Get()->Graphics.fctContext)); |
| 816 | pGroupDisplaySettings->AddElement(pChild: pDisplayModeCombo); |
| 817 | |
| 818 | for (const auto &mode : DisplayModes) |
| 819 | { |
| 820 | if (mode.mode == Config.Graphics.UseDisplayMode) |
| 821 | { |
| 822 | pDisplayModeCombo->SetText(LoadResStr(id: mode.caption)); |
| 823 | } |
| 824 | } |
| 825 | |
| 826 | C4GUI::ComponentAligner caScaleRow(caDisplaySettings.GetGridCell(iSectX: 0, iSectXMax: 1, iSectY: 1, iSectYMax: 2, iSectSizeX: -1, iSectSizeY: iEdit2Hgt, fCenterPos: true), 0, 0, false); |
| 827 | |
| 828 | StdStrBuf sScaleStr; sScaleStr.Copy(pnData: LoadResStr(id: C4ResStrTableKey::IDS_CTL_GRAPHICSSCALE)); sScaleStr.AppendChar(cChar: ':'); |
| 829 | pUseFont->GetTextExtent(szText: sScaleStr.getData(), rsx&: w, rsy&: q, fCheckMarkup: true); |
| 830 | pLbl = new C4GUI::Label(sScaleStr.getData(), caScaleRow.GetFromLeft(iWdt: w + C4GUI_DefDlgSmallIndent), ALeft, C4StartupFontClr, pUseFont, false); |
| 831 | pGroupDisplaySettings->AddElement(pChild: pLbl); |
| 832 | |
| 833 | szBtnText = LoadResStr(id: C4ResStrTableKey::IDS_BTN_TESTGRAPHICSSCALE); |
| 834 | C4GUI::CallbackButton<C4StartupOptionsDlg, SmallButton> *pTestScaleBtn; |
| 835 | C4GUI::GetRes()->CaptionFont.GetTextExtent(szText: szBtnText, rsx&: w, rsy&: q, fCheckMarkup: true); |
| 836 | pGroupDisplaySettings->AddElement(pChild: pTestScaleBtn = new C4GUI::CallbackButton<C4StartupOptionsDlg, SmallButton>(szBtnText, caScaleRow.GetFromRight(iWdt: w), &C4StartupOptionsDlg::OnTestScaleBtn, this)); |
| 837 | caScaleRow.GetFromRight(iWdt: 4 * C4GUI_DefDlgSmallIndent); |
| 838 | |
| 839 | pUseFont->GetTextExtent(szText: " %" , rsx&: w, rsy&: q, fCheckMarkup: true); |
| 840 | pLbl = new C4GUI::Label(" %" , caScaleRow.GetFromRight(iWdt: w), ARight, C4StartupFontClr, pUseFont, false); |
| 841 | pGroupDisplaySettings->AddElement(pChild: pLbl); |
| 842 | |
| 843 | pUseFont->GetTextExtent(szText: "30000" , rsx&: w, rsy&: q, fCheckMarkup: true); |
| 844 | pScaleEdit = new ScaleEdit(this, caScaleRow.GetFromRight(iWdt: w + C4GUI_DefDlgSmallIndent)); |
| 845 | pScaleEdit->SetFont(pUseFont); |
| 846 | pScaleEdit->SetToolTip(LoadResStr(id: C4ResStrTableKey::IDS_DESC_GRAPHICSSCALE)); |
| 847 | pGroupDisplaySettings->AddElement(pChild: pScaleEdit); |
| 848 | |
| 849 | caScaleRow.GetFromTop(iHgt: (caScaleRow.GetHeight() - C4GUI_ScrollBarHgt) / 2); |
| 850 | caScaleRow.GetFromBottom(iHgt: caScaleRow.GetHeight() - C4GUI_ScrollBarHgt); |
| 851 | auto *pScaleCB = new C4GUI::ParCallbackHandler<C4StartupOptionsDlg, int32_t>(this, &C4StartupOptionsDlg::OnScaleSliderChanged); |
| 852 | pScaleSlider = new C4GUI::ScrollBar(caScaleRow.GetAll(), true, pScaleCB, maxScale - minScale + 1); |
| 853 | |
| 854 | pScaleSlider->SetDecoration(pToGfx: &C4Startup::Get()->Graphics.sfctBookScroll, fAutoHide: false); |
| 855 | pScaleSlider->SetToolTip(LoadResStr(id: C4ResStrTableKey::IDS_DESC_GRAPHICSSCALE)); |
| 856 | pScaleSlider->SetScrollPos(Config.Graphics.Scale - minScale); |
| 857 | pGroupDisplaySettings->AddElement(pChild: pScaleSlider); |
| 858 | |
| 859 | OnScaleSliderChanged(val: Config.Graphics.Scale - minScale); |
| 860 | ; |
| 861 | // --subgroup options |
| 862 | int32_t iNumGfxOptions = 5, iOpt = 0; |
| 863 | C4GUI::GroupBox *pGroupOptions = new C4GUI::GroupBox(caSheetGraphics.GetGridCell(iSectX: 0, iSectXMax: 2, iSectY: 1, iSectYMax: 3)); |
| 864 | pGroupOptions->SetTitle(LoadResStrNoAmp(id: C4ResStrTableKey::IDS_DLG_OPTIONS).c_str()); |
| 865 | pGroupOptions->SetFont(pUseFont); |
| 866 | pGroupOptions->SetColors(dwFrameClr: C4StartupEditBorderColor, dwTitleClr: C4StartupFontClr); |
| 867 | pSheetGraphics->AddElement(pChild: pGroupOptions); |
| 868 | C4GUI::ComponentAligner caGroupOptions(pGroupOptions->GetClientRect(), iIndentX1, iIndentY2, true); |
| 869 | // add new crew portraits |
| 870 | pCheck = new BoolConfig(caGroupOptions.GetGridCell(iSectX: 0, iSectXMax: 1, iSectY: iOpt++, iSectYMax: iNumGfxOptions, iSectSizeX: -1, iSectSizeY: iCheckHgt, fCenterPos: true), LoadResStr(id: C4ResStrTableKey::IDS_MSG_ADDPORTRAITS), &Config.Graphics.AddNewCrewPortraits); |
| 871 | pCheck->SetToolTip(LoadResStr(id: C4ResStrTableKey::IDS_MSG_ADDPORTRAITS_DESC)); |
| 872 | pCheck->SetFont(pFont: pUseFont, dwEnabledClr: C4StartupFontClr, dwDisabledClr: C4StartupFontClrDisabled); |
| 873 | pGroupOptions->AddElement(pChild: pCheck); |
| 874 | // store default portraits in crew |
| 875 | pCheck = new BoolConfig(caGroupOptions.GetGridCell(iSectX: 0, iSectXMax: 1, iSectY: iOpt++, iSectYMax: iNumGfxOptions, iSectSizeX: -1, iSectSizeY: iCheckHgt, fCenterPos: true), LoadResStr(id: C4ResStrTableKey::IDS_MSG_STOREPORTRAITS), &Config.Graphics.SaveDefaultPortraits); |
| 876 | pCheck->SetToolTip(LoadResStr(id: C4ResStrTableKey::IDS_DESC_STOREPORTRAITS)); |
| 877 | pCheck->SetFont(pFont: pUseFont, dwEnabledClr: C4StartupFontClr, dwDisabledClr: C4StartupFontClrDisabled); |
| 878 | pGroupOptions->AddElement(pChild: pCheck); |
| 879 | // automatic gfx frame skip |
| 880 | pCheck = new BoolConfig(caGroupOptions.GetGridCell(iSectX: 0, iSectXMax: 1, iSectY: iOpt++, iSectYMax: iNumGfxOptions, iSectSizeX: -1, iSectSizeY: iCheckHgt, fCenterPos: true), LoadResStr(id: C4ResStrTableKey::IDS_MSG_AUTOFRAMESKIP), &Config.Graphics.AutoFrameSkip); |
| 881 | pCheck->SetToolTip(LoadResStr(id: C4ResStrTableKey::IDS_DESC_AUTOFRAMESKIP)); |
| 882 | pCheck->SetFont(pFont: pUseFont, dwEnabledClr: C4StartupFontClr, dwDisabledClr: C4StartupFontClrDisabled); |
| 883 | pGroupOptions->AddElement(pChild: pCheck); |
| 884 | // hide folder maps |
| 885 | pCheck = new BoolConfig(caGroupOptions.GetGridCell(iSectX: 0, iSectXMax: 1, iSectY: iOpt++, iSectYMax: iNumGfxOptions, iSectSizeX: -1, iSectSizeY: iCheckHgt, fCenterPos: true), LoadResStr(id: C4ResStrTableKey::IDS_MSG_SHOWFOLDERMAPS), &Config.Graphics.ShowFolderMaps); |
| 886 | pCheck->SetToolTip(LoadResStr(id: C4ResStrTableKey::IDS_DESC_SHOWFOLDERMAPS)); |
| 887 | pCheck->SetFont(pFont: pUseFont, dwEnabledClr: C4StartupFontClr, dwDisabledClr: C4StartupFontClrDisabled); |
| 888 | pGroupOptions->AddElement(pChild: pCheck); |
| 889 | // disable gamma |
| 890 | pCheck = new BoolConfig(caGroupOptions.GetGridCell(iSectX: 0, iSectXMax: 1, iSectY: iOpt++, iSectYMax: iNumGfxOptions, iSectSizeX: -1, iSectSizeY: iCheckHgt, fCenterPos: true), LoadResStr(id: C4ResStrTableKey::IDS_CTL_DISABLEGAMMA), &Config.Graphics.DisableGamma); |
| 891 | pCheck->SetToolTip(LoadResStr(id: C4ResStrTableKey::IDS_MSG_DISABLEGAMMA_DESC)); |
| 892 | pCheck->SetFont(pFont: pUseFont, dwEnabledClr: C4StartupFontClr, dwDisabledClr: C4StartupFontClrDisabled); |
| 893 | pGroupOptions->AddElement(pChild: pCheck); |
| 894 | // --subgroup effects |
| 895 | C4GUI::GroupBox *pGroupEffects = new C4GUI::GroupBox(caSheetGraphics.GetGridCell(iSectX: 1, iSectXMax: 2, iSectY: 1, iSectYMax: 3)); |
| 896 | pGroupEffects->SetTitle(LoadResStrNoAmp(id: C4ResStrTableKey::IDS_CTL_SMOKE).c_str()); |
| 897 | pGroupEffects->SetFont(pUseFont); |
| 898 | pGroupEffects->SetColors(dwFrameClr: C4StartupEditBorderColor, dwTitleClr: C4StartupFontClr); |
| 899 | pSheetGraphics->AddElement(pChild: pGroupEffects); |
| 900 | C4GUI::ComponentAligner caGroupEffects(pGroupEffects->GetClientRect(), iIndentX1, iIndentY2, true); |
| 901 | iNumGfxOptions = 2; iOpt = 0; |
| 902 | // effects level slider |
| 903 | C4GUI::ComponentAligner caEffectsLevel(caGroupEffects.GetGridCell(iSectX: 0, iSectXMax: 1, iSectY: iOpt++, iSectYMax: iNumGfxOptions), 1, 0, false); |
| 904 | StdStrBuf sEffectsTxt; sEffectsTxt.Copy(pnData: LoadResStr(id: C4ResStrTableKey::IDS_CTL_SMOKELOW)); |
| 905 | w = 20; q = 12; pUseFont->GetTextExtent(szText: sEffectsTxt.getData(), rsx&: w, rsy&: q, fCheckMarkup: true); |
| 906 | pGroupEffects->AddElement(pChild: new C4GUI::Label(sEffectsTxt.getData(), caEffectsLevel.GetFromLeft(iWdt: w, iHgt: q), ACenter, C4StartupFontClr, pUseFont, false, false)); |
| 907 | sEffectsTxt.Copy(pnData: LoadResStr(id: C4ResStrTableKey::IDS_CTL_SMOKEHI)); |
| 908 | w = 20; q = 12; pUseFont->GetTextExtent(szText: sEffectsTxt.getData(), rsx&: w, rsy&: q, fCheckMarkup: true); |
| 909 | pGroupEffects->AddElement(pChild: new C4GUI::Label(sEffectsTxt.getData(), caEffectsLevel.GetFromRight(iWdt: w, iHgt: q), ACenter, C4StartupFontClr, pUseFont, false, false)); |
| 910 | pEffectLevelSlider = new C4GUI::ScrollBar(caEffectsLevel.GetCentered(iWdt: caEffectsLevel.GetInnerWidth(), C4GUI_ScrollBarHgt), true, new C4GUI::ParCallbackHandler<C4StartupOptionsDlg, int32_t>(this, &C4StartupOptionsDlg::OnEffectsSliderChange), 301); |
| 911 | pEffectLevelSlider->SetDecoration(pToGfx: &C4Startup::Get()->Graphics.sfctBookScroll, fAutoHide: false); |
| 912 | pEffectLevelSlider->SetToolTip(LoadResStr(id: C4ResStrTableKey::IDS_MSG_PARTICLES_DESC)); |
| 913 | pEffectLevelSlider->SetScrollPos(Config.Graphics.SmokeLevel); |
| 914 | pGroupEffects->AddElement(pChild: pEffectLevelSlider); |
| 915 | // fire particles |
| 916 | pCheck = new BoolConfig(caGroupEffects.GetGridCell(iSectX: 0, iSectXMax: 1, iSectY: iOpt++, iSectYMax: iNumGfxOptions, iSectSizeX: -1, iSectSizeY: iCheckHgt, fCenterPos: true), LoadResStr(id: C4ResStrTableKey::IDS_MSG_FIREPARTICLES), &Config.Graphics.FireParticles); |
| 917 | pCheck->SetToolTip(LoadResStr(id: C4ResStrTableKey::IDS_MSG_FIREPARTICLES_DESC)); |
| 918 | pCheck->SetFont(pFont: pUseFont, dwEnabledClr: C4StartupFontClr, dwDisabledClr: C4StartupFontClrDisabled); |
| 919 | pGroupEffects->AddElement(pChild: pCheck); |
| 920 | |
| 921 | // page sound |
| 922 | C4GUI::ComponentAligner caSheetSound(pSheetSound->GetClientRect(), iIndentX1, iIndentY1, true); |
| 923 | if (!C4GUI::CheckBox::GetStandardCheckBoxSize(piWdt: &iCheckWdt, piHgt: &iCheckHgt, szForCaptionText: "Lorem ipsum" , pUseFont)) { iCheckWdt = 100; iCheckHgt = 20; } |
| 924 | int32_t iGridWdt = iCheckWdt * 2, iGridHgt = iCheckHgt * 5 / 2; |
| 925 | // --subgroup menu system sound |
| 926 | C4GUI::GroupBox *pGroupFESound = new C4GUI::GroupBox(caSheetSound.GetGridCell(iSectX: 0, iSectXMax: 2, iSectY: 0, iSectYMax: 5, iSectSizeX: iGridWdt, iSectSizeY: iGridHgt, fCenterPos: false, iSectNumX: 1, iSectNumY: 2)); |
| 927 | pGroupFESound->SetTitle(LoadResStrNoAmp(id: C4ResStrTableKey::IDS_CTL_FRONTEND).c_str()); |
| 928 | pGroupFESound->SetFont(pUseFont); |
| 929 | pGroupFESound->SetColors(dwFrameClr: C4StartupEditBorderColor, dwTitleClr: C4StartupFontClr); |
| 930 | pSheetSound->AddElement(pChild: pGroupFESound); |
| 931 | C4GUI::ComponentAligner caGroupFESound(pGroupFESound->GetClientRect(), iIndentX1, iIndentY2, true); |
| 932 | // menu system music |
| 933 | pCheck = pFEMusicCheck = new C4GUI::CheckBox(caGroupFESound.GetGridCell(iSectX: 0, iSectXMax: 1, iSectY: 0, iSectYMax: 2, iSectSizeX: -1, iSectSizeY: iCheckHgt, fCenterPos: true), LoadResStr(id: C4ResStrTableKey::IDS_CTL_MUSIC), !!Config.Sound.FEMusic); |
| 934 | pCheck->SetToolTip(LoadResStr(id: C4ResStrTableKey::IDS_DESC_MENUMUSIC)); |
| 935 | pCheck->SetFont(pFont: pUseFont, dwEnabledClr: C4StartupFontClr, dwDisabledClr: C4StartupFontClrDisabled); |
| 936 | pCheck->SetOnChecked(new C4GUI::CallbackHandler<C4StartupOptionsDlg>(this, &C4StartupOptionsDlg::OnFEMusicCheck)); |
| 937 | pGroupFESound->AddElement(pChild: pCheck); |
| 938 | // menu system sound effects |
| 939 | pCheck = new BoolConfig(caGroupFESound.GetGridCell(iSectX: 0, iSectXMax: 1, iSectY: 1, iSectYMax: 2, iSectSizeX: -1, iSectSizeY: iCheckHgt, fCenterPos: true), LoadResStr(id: C4ResStrTableKey::IDS_CTL_SOUNDFX), &Config.Sound.FESamples); |
| 940 | pCheck->SetToolTip(LoadResStr(id: C4ResStrTableKey::IDS_DESC_MENUSOUND)); |
| 941 | pCheck->SetFont(pFont: pUseFont, dwEnabledClr: C4StartupFontClr, dwDisabledClr: C4StartupFontClrDisabled); |
| 942 | pGroupFESound->AddElement(pChild: pCheck); |
| 943 | // --subgroup game sound |
| 944 | C4GUI::GroupBox *pGroupRXSound = new C4GUI::GroupBox(caSheetSound.GetGridCell(iSectX: 1, iSectXMax: 2, iSectY: 0, iSectYMax: 5, iSectSizeX: iGridWdt, iSectSizeY: iGridHgt, fCenterPos: false, iSectNumX: 1, iSectNumY: 2)); |
| 945 | pGroupRXSound->SetTitle(LoadResStrNoAmp(id: C4ResStrTableKey::IDS_CTL_GAME).c_str()); |
| 946 | pGroupRXSound->SetFont(pUseFont); |
| 947 | pGroupRXSound->SetColors(dwFrameClr: C4StartupEditBorderColor, dwTitleClr: C4StartupFontClr); |
| 948 | pSheetSound->AddElement(pChild: pGroupRXSound); |
| 949 | C4GUI::ComponentAligner caGroupRXSound(pGroupRXSound->GetClientRect(), iIndentX1, iIndentY2, true); |
| 950 | // game music |
| 951 | pCheck = new BoolConfig(caGroupRXSound.GetGridCell(iSectX: 0, iSectXMax: 1, iSectY: 0, iSectYMax: 2, iSectSizeX: -1, iSectSizeY: iCheckHgt, fCenterPos: true), LoadResStr(id: C4ResStrTableKey::IDS_CTL_MUSIC), &Config.Sound.RXMusic); |
| 952 | pCheck->SetToolTip(LoadResStr(id: C4ResStrTableKey::IDS_DESC_GAMEMUSIC)); |
| 953 | pCheck->SetFont(pFont: pUseFont, dwEnabledClr: C4StartupFontClr, dwDisabledClr: C4StartupFontClrDisabled); |
| 954 | pGroupRXSound->AddElement(pChild: pCheck); |
| 955 | // game sound effects |
| 956 | pCheck = new BoolConfig(caGroupRXSound.GetGridCell(iSectX: 0, iSectXMax: 1, iSectY: 1, iSectYMax: 2, iSectSizeX: -1, iSectSizeY: iCheckHgt, fCenterPos: true), LoadResStr(id: C4ResStrTableKey::IDS_CTL_SOUNDFX), &Config.Sound.RXSound); |
| 957 | pCheck->SetToolTip(LoadResStr(id: C4ResStrTableKey::IDS_DESC_GAMESOUND)); |
| 958 | pCheck->SetFont(pFont: pUseFont, dwEnabledClr: C4StartupFontClr, dwDisabledClr: C4StartupFontClrDisabled); |
| 959 | pGroupRXSound->AddElement(pChild: pCheck); |
| 960 | // -- subgroup volume |
| 961 | C4GUI::GroupBox *pGroupVolume = new C4GUI::GroupBox(caSheetSound.GetGridCell(iSectX: 0, iSectXMax: 2, iSectY: 2, iSectYMax: 5, iSectSizeX: iGridWdt, iSectSizeY: iGridHgt, fCenterPos: false, iSectNumX: 2, iSectNumY: 3)); |
| 962 | pGroupVolume->SetTitle(LoadResStrNoAmp(id: C4ResStrTableKey::IDS_BTN_VOLUME).c_str()); |
| 963 | pGroupVolume->SetFont(pUseFont); |
| 964 | pGroupVolume->SetColors(dwFrameClr: C4StartupEditBorderColor, dwTitleClr: C4StartupFontClr); |
| 965 | pSheetSound->AddElement(pChild: pGroupVolume); |
| 966 | C4GUI::ComponentAligner caGroupVolume(pGroupVolume->GetClientRect(), iIndentX1, iIndentY2, true); |
| 967 | // volume sliders |
| 968 | int32_t i; |
| 969 | for (i = 0; i < 2; ++i) |
| 970 | { |
| 971 | C4GUI::ComponentAligner caVolumeSlider(caGroupVolume.GetGridCell(iSectX: 0, iSectXMax: 1, iSectY: i, iSectYMax: 2, iSectSizeX: -1, iSectSizeY: pUseFont->GetLineHeight() + iIndentY2 * 2 + C4GUI_ScrollBarHgt, fCenterPos: true), 1, 0, false); |
| 972 | pGroupVolume->AddElement(pChild: new C4GUI::Label(std::format(fmt: "{}:" , args: LoadResStrChoice(condition: i, ifTrue: C4ResStrTableKey::IDS_CTL_SOUNDFX, ifFalse: C4ResStrTableKey::IDS_CTL_MUSIC)).c_str(), caVolumeSlider.GetFromTop(iHgt: pUseFont->GetLineHeight()), ALeft, C4StartupFontClr, pUseFont, false, false)); |
| 973 | sLabelTxt.Copy(pnData: LoadResStr(id: C4ResStrTableKey::IDS_CTL_SILENT)); |
| 974 | w = 20; q = 12; pUseFont->GetTextExtent(szText: sLabelTxt.getData(), rsx&: w, rsy&: q, fCheckMarkup: true); |
| 975 | pGroupVolume->AddElement(pChild: new C4GUI::Label(sLabelTxt.getData(), caVolumeSlider.GetFromLeft(iWdt: w, iHgt: q), ACenter, C4StartupFontClr, pUseFont, false, false)); |
| 976 | sLabelTxt.Copy(pnData: LoadResStr(id: C4ResStrTableKey::IDS_CTL_LOUD)); |
| 977 | pUseFont->GetTextExtent(szText: sLabelTxt.getData(), rsx&: w, rsy&: q, fCheckMarkup: true); |
| 978 | pGroupVolume->AddElement(pChild: new C4GUI::Label(sLabelTxt.getData(), caVolumeSlider.GetFromRight(iWdt: w, iHgt: q), ACenter, C4StartupFontClr, pUseFont, false, false)); |
| 979 | C4GUI::ParCallbackHandler<C4StartupOptionsDlg, int32_t> *pCB = new C4GUI::ParCallbackHandler<C4StartupOptionsDlg, int32_t>(this, i ? &C4StartupOptionsDlg::OnSoundVolumeSliderChange : &C4StartupOptionsDlg::OnMusicVolumeSliderChange); |
| 980 | C4GUI::ScrollBar *pSlider = new C4GUI::ScrollBar(caVolumeSlider.GetCentered(iWdt: caVolumeSlider.GetInnerWidth(), C4GUI_ScrollBarHgt), true, pCB, 101); |
| 981 | pSlider->SetDecoration(pToGfx: &C4Startup::Get()->Graphics.sfctBookScroll, fAutoHide: false); |
| 982 | pSlider->SetToolTip(i ? LoadResStr(id: C4ResStrTableKey::IDS_DESC_VOLUMESOUND) : LoadResStr(id: C4ResStrTableKey::IDS_DESC_VOLUMEMUSIC)); |
| 983 | pSlider->SetScrollPos(i ? Config.Sound.SoundVolume : Config.Sound.MusicVolume); |
| 984 | pGroupVolume->AddElement(pChild: pSlider); |
| 985 | } |
| 986 | |
| 987 | // page keyboard controls |
| 988 | pSheetKeyboard->AddElement(pChild: new ControlConfigArea(pSheetKeyboard->GetClientRect(), caMain.GetWidth() / 20, caMain.GetHeight() / 40, false, this)); |
| 989 | |
| 990 | // page gamepad |
| 991 | pSheetGamepad->AddElement(pChild: new ControlConfigArea(pSheetGamepad->GetClientRect(), caMain.GetWidth() / 20, caMain.GetHeight() / 40, true, this)); |
| 992 | |
| 993 | // page network |
| 994 | C4GUI::ComponentAligner caSheetNetwork(pSheetNetwork->GetClientRect(), caMain.GetWidth() / 20, caMain.GetHeight() / 20, true); |
| 995 | int iPortCfgWdt = 200, iPortCfgHgt = 48; NetworkPortConfig::GetControlSize(piWdt: &iPortCfgWdt, piHgt: &iPortCfgHgt); |
| 996 | pPortCfgTCP = new NetworkPortConfig(caSheetNetwork.GetGridCell(iSectX: 0, iSectXMax: 2, iSectY: 0, iSectYMax: 2, iSectSizeX: iPortCfgWdt, iSectSizeY: iPortCfgHgt), LoadResStr(id: C4ResStrTableKey::IDS_NET_PORT_TCP), &(Config.Network.PortTCP), C4NetStdPortTCP); |
| 997 | pPortCfgUDP = new NetworkPortConfig(caSheetNetwork.GetGridCell(iSectX: 1, iSectXMax: 2, iSectY: 0, iSectYMax: 2, iSectSizeX: iPortCfgWdt, iSectSizeY: iPortCfgHgt), LoadResStr(id: C4ResStrTableKey::IDS_NET_PORT_UDP), &(Config.Network.PortUDP), C4NetStdPortUDP); |
| 998 | pPortCfgRef = new NetworkPortConfig(caSheetNetwork.GetGridCell(iSectX: 0, iSectXMax: 2, iSectY: 1, iSectYMax: 2, iSectSizeX: iPortCfgWdt, iSectSizeY: iPortCfgHgt), LoadResStr(id: C4ResStrTableKey::IDS_NET_PORT_REFERENCE), &(Config.Network.PortRefServer), C4NetStdPortRefServer); |
| 999 | pPortCfgDsc = new NetworkPortConfig(caSheetNetwork.GetGridCell(iSectX: 1, iSectXMax: 2, iSectY: 1, iSectYMax: 2, iSectSizeX: iPortCfgWdt, iSectSizeY: iPortCfgHgt), LoadResStr(id: C4ResStrTableKey::IDS_NET_PORT_DISCOVERY), &(Config.Network.PortDiscovery), C4NetStdPortDiscovery); |
| 1000 | pPortCfgTCP->SetToolTip(LoadResStr(id: C4ResStrTableKey::IDS_NET_PORT_TCP_DESC)); |
| 1001 | pPortCfgUDP->SetToolTip(LoadResStr(id: C4ResStrTableKey::IDS_NET_PORT_UDP_DESC)); |
| 1002 | pPortCfgRef->SetToolTip(LoadResStr(id: C4ResStrTableKey::IDS_NET_PORT_REFERENCE_DESC)); |
| 1003 | pPortCfgDsc->SetToolTip(LoadResStr(id: C4ResStrTableKey::IDS_NET_PORT_DISCOVERY_DESC)); |
| 1004 | pSheetNetwork->AddElement(pChild: pPortCfgTCP); |
| 1005 | pSheetNetwork->AddElement(pChild: pPortCfgUDP); |
| 1006 | pSheetNetwork->AddElement(pChild: pPortCfgRef); |
| 1007 | pSheetNetwork->AddElement(pChild: pPortCfgDsc); |
| 1008 | int iNetHgt0 = pPortCfgDsc->GetBounds().GetBottom(); |
| 1009 | caSheetNetwork.ExpandTop(iByHgt: -iNetHgt0); |
| 1010 | int iServerCfgWdt = 120, iServerCfgHgt = 20, iServerCfgWdtMid = 0; |
| 1011 | StdStrBuf sServerText; sServerText.Copy(pnData: LoadResStr(id: C4ResStrTableKey::IDS_CTL_USEOTHERSERVER)); |
| 1012 | NetworkServerAddressConfig::GetControlSize(piWdt: &iServerCfgWdt, piHgt: &iServerCfgHgt, piTabPos: &iServerCfgWdtMid, szForText: sServerText.getData()); |
| 1013 | pLeagueServerCfg = new NetworkServerAddressConfig(caSheetNetwork.GetFromTop(iHgt: iServerCfgHgt), sServerText.getData(), &(Config.Network.UseAlternateServer), Config.Network.AlternateServerAddress, iServerCfgWdtMid); |
| 1014 | pLeagueServerCfg->SetToolTip(LoadResStr(id: C4ResStrTableKey::IDS_NET_MASTERSRV_DESC)); |
| 1015 | pSheetNetwork->AddElement(pChild: pLeagueServerCfg); |
| 1016 | pCheck = new BoolConfig(caSheetNetwork.GetFromTop(iHgt: pUseFont->GetLineHeight()), LoadResStr(id: C4ResStrTableKey::IDS_CTL_AUTOMATICUPDATES), &Config.Network.AutomaticUpdate, false); |
| 1017 | pCheck->SetToolTip(LoadResStr(id: C4ResStrTableKey::IDS_DESC_AUTOMATICUPDATES)); |
| 1018 | pCheck->SetFont(pFont: pUseFont, dwEnabledClr: C4StartupFontClr, dwDisabledClr: C4StartupFontClrDisabled); |
| 1019 | pSheetNetwork->AddElement(pChild: pCheck); |
| 1020 | // UPnP |
| 1021 | pCheck = new BoolConfig{caSheetNetwork.GetFromTop(iHgt: pUseFont->GetLineHeight()), LoadResStr(id: C4ResStrTableKey::IDS_CTL_UPNP), &Config.Network.EnableUPnP, false}; |
| 1022 | pCheck->SetToolTip(LoadResStr(id: C4ResStrTableKey::IDS_DESC_UPNP)); |
| 1023 | pCheck->SetFont(pFont: pUseFont, dwEnabledClr: C4StartupFontClr, dwDisabledClr: C4StartupFontClrDisabled); |
| 1024 | pSheetNetwork->AddElement(pChild: pCheck); |
| 1025 | const char *szNameCfgText = LoadResStr(id: C4ResStrTableKey::IDS_NET_COMPUTERNAME); |
| 1026 | int iNameCfgWdt = 200, iNameCfgHgt = 48; C4StartupOptionsDlg::EditConfig::GetControlSize(piWdt: &iNameCfgWdt, piHgt: &iNameCfgHgt, szForText: szNameCfgText, fMultiline: false); |
| 1027 | iNameCfgWdt += 5; |
| 1028 | pNetworkNameEdit = new EditConfig(caSheetNetwork.GetGridCell(iSectX: 0, iSectXMax: 2, iSectY: 0, iSectYMax: 1, iSectSizeX: iNameCfgWdt, iSectSizeY: iNameCfgHgt), szNameCfgText, &Config.Network.LocalName, nullptr, false); |
| 1029 | pNetworkNickEdit = new EditConfig(caSheetNetwork.GetGridCell(iSectX: 1, iSectXMax: 2, iSectY: 0, iSectYMax: 1, iSectSizeX: iNameCfgWdt, iSectSizeY: iNameCfgHgt), LoadResStr(id: C4ResStrTableKey::IDS_NET_USERNAME), &Config.Network.Nick, nullptr, false); |
| 1030 | pNetworkNameEdit->SetToolTip(LoadResStr(id: C4ResStrTableKey::IDS_NET_COMPUTERNAME_DESC)); |
| 1031 | pNetworkNickEdit->SetToolTip(LoadResStr(id: C4ResStrTableKey::IDS_NET_USERNAME_DESC)); |
| 1032 | pSheetNetwork->AddElement(pChild: pNetworkNameEdit); |
| 1033 | pSheetNetwork->AddElement(pChild: pNetworkNickEdit); |
| 1034 | StdStrBuf NickBuf(Config.Network.Nick); |
| 1035 | if (!NickBuf.getLength()) NickBuf.Copy(Buf2: Config.Network.LocalName); |
| 1036 | pNetworkNickEdit->GetEdit()->SetText(text: NickBuf.getData(), fUser: false); |
| 1037 | |
| 1038 | // initial focus is on tab selection |
| 1039 | SetFocus(pCtrl: pOptionsTabular, fByMouse: false); |
| 1040 | } |
| 1041 | |
| 1042 | C4StartupOptionsDlg::~C4StartupOptionsDlg() |
| 1043 | { |
| 1044 | delete pKeyToggleMusic; |
| 1045 | delete pKeyBack; |
| 1046 | } |
| 1047 | |
| 1048 | void C4StartupOptionsDlg::OnClosed(bool fOK) |
| 1049 | { |
| 1050 | // callback when dlg got closed - save config |
| 1051 | SaveConfig(fForce: true, fKeepOpen: false); |
| 1052 | C4StartupDlg::OnClosed(fOK); |
| 1053 | } |
| 1054 | |
| 1055 | int32_t C4StartupOptionsDlg::FairCrewSlider2Strength(int32_t iSliderVal) |
| 1056 | { |
| 1057 | // slider linear in rank to value linear in exp |
| 1058 | return int32_t(pow(x: double(iSliderVal) / 9.5, y: 1.5) * 1000.0); |
| 1059 | } |
| 1060 | |
| 1061 | int32_t C4StartupOptionsDlg::FairCrewStrength2Slider(int32_t iStrengthVal) |
| 1062 | { |
| 1063 | // value linear in exp to slider linear in rank |
| 1064 | return int32_t(pow(x: double(iStrengthVal) / 1000.0, y: 1.0 / 1.5) * 9.5); |
| 1065 | } |
| 1066 | |
| 1067 | void C4StartupOptionsDlg::OnFairCrewStrengthSliderChange(int32_t iNewVal) |
| 1068 | { |
| 1069 | // fair crew strength determined by exponential fn |
| 1070 | Config.General.FairCrewStrength = FairCrewSlider2Strength(iSliderVal: iNewVal); |
| 1071 | } |
| 1072 | |
| 1073 | void C4StartupOptionsDlg::OnResetConfigBtn(C4GUI::Control *btn) |
| 1074 | { |
| 1075 | // confirmation |
| 1076 | StdStrBuf sWarningText; sWarningText.Copy(pnData: LoadResStr(id: C4ResStrTableKey::IDS_MSG_PROMPTRESETCONFIG)); |
| 1077 | sWarningText.AppendChar(cChar: '|'); |
| 1078 | sWarningText.Append(pnData: LoadResStr(id: C4ResStrTableKey::IDS_MSG_RESTARTCHANGECFG)); |
| 1079 | if (!GetScreen()->ShowMessageModal(szMessage: sWarningText.getData(), szCaption: LoadResStr(id: C4ResStrTableKey::IDS_BTN_RESETCONFIG), dwButtons: C4GUI::MessageDialog::btnYesNo, icoIcon: C4GUI::Ico_Notify)) |
| 1080 | // user cancelled |
| 1081 | return; |
| 1082 | // reset cfg |
| 1083 | Config.Default(); |
| 1084 | Config.fConfigLoaded = true; |
| 1085 | // engine must be restarted now, because some crucial fields such as resolution and used gfx engine do not match their initialization |
| 1086 | Application.Quit(); |
| 1087 | } |
| 1088 | |
| 1089 | void C4StartupOptionsDlg::OnAdvancedConfigBtn(C4GUI::Control *) |
| 1090 | { |
| 1091 | if (C4StartupOptionsAdvancedConfigDialog::ShowModal(screen: Game.pGUI)) |
| 1092 | { |
| 1093 | RecreateDialog(fFade: false); |
| 1094 | } |
| 1095 | } |
| 1096 | |
| 1097 | void C4StartupOptionsDlg::OnScaleSliderChanged(int32_t val) |
| 1098 | { |
| 1099 | iNewScale = val + minScale; |
| 1100 | pScaleEdit->SetValue(value: iNewScale, user: true); |
| 1101 | } |
| 1102 | |
| 1103 | void C4StartupOptionsDlg::OnTestScaleBtn(C4GUI::Control *) |
| 1104 | { |
| 1105 | const auto oldScaleInt = Config.Graphics.Scale; |
| 1106 | const auto oldScale = Application.GetScale(); |
| 1107 | if (iNewScale == oldScaleInt) return; |
| 1108 | |
| 1109 | const auto oldResX = Config.Graphics.ResX; |
| 1110 | const auto oldResY = Config.Graphics.ResY; |
| 1111 | |
| 1112 | Config.Graphics.Scale = iNewScale; |
| 1113 | const auto realResX = static_cast<int32_t>(floorf(x: oldResX * oldScale)); |
| 1114 | const auto realResY = static_cast<int32_t>(floorf(x: oldResY * oldScale)); |
| 1115 | |
| 1116 | Application.SetResolution(iNewResX: realResX, iNewResY: realResY); |
| 1117 | Application.SetGameFont(szFontFace: Config.General.RXFontName, iFontSize: Config.General.RXFontSize); |
| 1118 | |
| 1119 | // do it manually and temporarily here, beacuse RecreateDialog would delete this the second time which leads to a crash after this function returns |
| 1120 | FadeOut(fCloseWithOK: true); |
| 1121 | |
| 1122 | int32_t iPage = pOptionsTabular->GetActiveSheetIndex(); |
| 1123 | std::unique_ptr<C4StartupOptionsDlg> pNewDlg{new C4StartupOptionsDlg}; |
| 1124 | pNewDlg->FadeIn(pOnScreen: Game.pGUI); |
| 1125 | pNewDlg->pOptionsTabular->SelectSheet(iIndex: iPage, fByUser: false); |
| 1126 | pNewDlg->fCanGoBack = false; |
| 1127 | |
| 1128 | ResChangeConfirmDlg *pConfirmDlg = new ResChangeConfirmDlg; |
| 1129 | |
| 1130 | if (!GetScreen()->ShowModalDlg(pDlg: pConfirmDlg, fDestruct: true)) |
| 1131 | { |
| 1132 | Config.Graphics.Scale = oldScaleInt; |
| 1133 | |
| 1134 | if (C4GUI::IsGUIValid()) |
| 1135 | { |
| 1136 | Application.SetResolution(iNewResX: realResX, iNewResY: realResY); |
| 1137 | Application.SetGameFont(szFontFace: Config.General.RXFontName, iFontSize: Config.General.RXFontSize); |
| 1138 | } |
| 1139 | else |
| 1140 | { |
| 1141 | // make sure config is restored even if the program is closed during the confirmation dialog |
| 1142 | Config.Graphics.ResX = oldResX; |
| 1143 | Config.Graphics.ResY = oldResY; |
| 1144 | } |
| 1145 | } |
| 1146 | |
| 1147 | RecreateDialog(fFade: false); |
| 1148 | } |
| 1149 | |
| 1150 | bool C4StartupOptionsDlg::SaveConfig(bool fForce, bool fKeepOpen) |
| 1151 | { |
| 1152 | // prevent double save |
| 1153 | if (fConfigSaved) return true; |
| 1154 | // store some config values |
| 1155 | SaveGfxTroubleshoot(); |
| 1156 | // save any config fields that are not stored directly; return whether all values are OK |
| 1157 | // check port validity |
| 1158 | if (!fForce) |
| 1159 | { |
| 1160 | StdStrBuf strError(LoadResStr(id: C4ResStrTableKey::IDS_ERR_CONFIG)); |
| 1161 | if (pPortCfgTCP->GetPort() > 0 && pPortCfgTCP->GetPort() == pPortCfgRef->GetPort()) |
| 1162 | { |
| 1163 | GetScreen()->ShowMessage(szMessage: LoadResStr(id: C4ResStrTableKey::IDS_NET_ERR_PORT_TCPREF), szCaption: strError.getData(), icoIcon: C4GUI::Ico_Error); |
| 1164 | return false; |
| 1165 | } |
| 1166 | if (pPortCfgUDP->GetPort() > 0 && pPortCfgUDP->GetPort() == pPortCfgDsc->GetPort()) |
| 1167 | { |
| 1168 | GetScreen()->ShowMessage(szMessage: LoadResStr(id: C4ResStrTableKey::IDS_NET_ERR_PORT_UDPDISC), szCaption: strError.getData(), icoIcon: C4GUI::Ico_Error); |
| 1169 | return false; |
| 1170 | } |
| 1171 | } |
| 1172 | pPortCfgTCP->SavePort(); |
| 1173 | pPortCfgUDP->SavePort(); |
| 1174 | pPortCfgRef->SavePort(); |
| 1175 | pPortCfgDsc->SavePort(); |
| 1176 | pLeagueServerCfg->Save2Config(); |
| 1177 | pNetworkNameEdit->Save2Config(); |
| 1178 | pNetworkNickEdit->Save2Config(); |
| 1179 | // if nick is same as LocalName, don't save in config |
| 1180 | // so LocalName updates will change the nick as well |
| 1181 | if (SEqual(szStr1: Config.Network.Nick.getData(), szStr2: Config.Network.LocalName.getData())) Config.Network.Nick.Clear(); |
| 1182 | // make sure config is saved, in case the game crashes later on or another instance is started |
| 1183 | Config.Save(); |
| 1184 | if (!fKeepOpen) fConfigSaved = true; |
| 1185 | // done; config OK |
| 1186 | return true; |
| 1187 | } |
| 1188 | |
| 1189 | void C4StartupOptionsDlg::DoBack() |
| 1190 | { |
| 1191 | if (!SaveConfig(fForce: false, fKeepOpen: false)) return; |
| 1192 | // back 2 main |
| 1193 | C4Startup::Get()->SwitchDialog(eToDlg: fCanGoBack ? (C4Startup::SDID_Back) : (C4Startup::SDID_Main)); |
| 1194 | } |
| 1195 | |
| 1196 | void C4StartupOptionsDlg::UpdateLanguage() |
| 1197 | { |
| 1198 | // find currently specified language in language list and display its info |
| 1199 | const C4LanguageInfo *const info{Languages.FindInfo(code: Config.General.Language)}; |
| 1200 | if (info) |
| 1201 | { |
| 1202 | pLangCombo->SetText(std::format(fmt: "{}{} - {}" , args: info->Code[0], args: info->Code[1], args: info->Name.c_str()).c_str()); |
| 1203 | pLangInfoLabel->SetText(toText: info->Info); |
| 1204 | } |
| 1205 | else |
| 1206 | { |
| 1207 | pLangCombo->SetText(std::format(fmt: "unknown ({})" , args: +Config.General.Language).c_str()); |
| 1208 | pLangInfoLabel->SetText(szText: LoadResStr(id: C4ResStrTableKey::IDS_CTL_NOLANGINFO)); |
| 1209 | return; // no need to mess with fallbacks |
| 1210 | } |
| 1211 | // update language fallbacks |
| 1212 | char *szLang = Config.General.LanguageEx; |
| 1213 | szLang[0] = info->Code[0]; |
| 1214 | szLang[1] = info->Code[1]; |
| 1215 | szLang[2] = '\0'; |
| 1216 | if (!info->Fallback.empty()) |
| 1217 | { |
| 1218 | SAppend(szSource: "," , szTarget: szLang); |
| 1219 | Config.General.GetLanguageSequence(strSource: info->Fallback.c_str(), strTarget: szLang + SLen(sptr: szLang)); |
| 1220 | } |
| 1221 | // internal fallbacks |
| 1222 | if (!SSearch(szString: Config.General.LanguageEx, szIndex: "US" )) |
| 1223 | { |
| 1224 | if (*szLang) SAppendChar(cChar: ',', szStr: szLang); |
| 1225 | SAppend(szSource: "US" , szTarget: szLang); |
| 1226 | } |
| 1227 | if (!SSearch(szString: Config.General.LanguageEx, szIndex: "DE" )) |
| 1228 | { |
| 1229 | if (*szLang) SAppendChar(cChar: ',', szStr: szLang); |
| 1230 | SAppend(szSource: "DE" , szTarget: szLang); |
| 1231 | } |
| 1232 | } |
| 1233 | |
| 1234 | void C4StartupOptionsDlg::OnLangComboFill(C4GUI::ComboBox_FillCB *pFiller) |
| 1235 | { |
| 1236 | // fill with all possible languages |
| 1237 | for (const auto &info : Languages) |
| 1238 | { |
| 1239 | pFiller->AddEntry(szText: std::format(fmt: "{}{} - {}" , args: info.Code[0], args: info.Code[1], args: info.Name.c_str()).c_str(), id: static_cast<unsigned char>(info.Code[0]) + (static_cast<unsigned char>(info.Code[1]) << 8)); |
| 1240 | } |
| 1241 | } |
| 1242 | |
| 1243 | bool C4StartupOptionsDlg::OnLangComboSelChange(C4GUI::ComboBox *pForCombo, int32_t idNewSelection) |
| 1244 | { |
| 1245 | // set new language by two-character-code |
| 1246 | Config.General.Language[0] = idNewSelection & 0xff; |
| 1247 | Config.General.Language[1] = (idNewSelection & 0xff00) >> 8; |
| 1248 | Config.General.Language[2] = '\0'; |
| 1249 | UpdateLanguage(); |
| 1250 | Languages.LoadLanguage(strLanguages: Config.General.LanguageEx); |
| 1251 | // recreate everything to reflect language changes |
| 1252 | RecreateDialog(fFade: true); |
| 1253 | return true; |
| 1254 | } |
| 1255 | |
| 1256 | void C4StartupOptionsDlg::UpdateFontControls() |
| 1257 | { |
| 1258 | // display current language and size in comboboxes |
| 1259 | pFontFaceCombo->SetText(Config.General.RXFontName); |
| 1260 | pFontSizeCombo->SetText(std::to_string(val: Config.General.RXFontSize).c_str()); |
| 1261 | } |
| 1262 | |
| 1263 | const char *DefaultFonts[] = { "Arial Unicode MS" , "Comic Sans MS" , "Endeavour" , "Verdana" , nullptr }; |
| 1264 | |
| 1265 | void C4StartupOptionsDlg::OnFontFaceComboFill(C4GUI::ComboBox_FillCB *pFiller) |
| 1266 | { |
| 1267 | // 2do: enumerate Fonts.txt fonts; then enumerate system fonts |
| 1268 | for (int32_t i = 0; DefaultFonts[i]; ++i) pFiller->AddEntry(szText: DefaultFonts[i], id: i); |
| 1269 | } |
| 1270 | |
| 1271 | void C4StartupOptionsDlg::OnFontSizeComboFill(C4GUI::ComboBox_FillCB *pFiller) |
| 1272 | { |
| 1273 | // 2do: enumerate possible font sizes by the font here |
| 1274 | // 2do: Hide font sizes that would be too large for the selected resolution |
| 1275 | pFiller->AddEntry(szText: "8" , id: 8); |
| 1276 | pFiller->AddEntry(szText: "10" , id: 10); |
| 1277 | pFiller->AddEntry(szText: "12" , id: 12); |
| 1278 | pFiller->AddEntry(szText: "14" , id: 14); |
| 1279 | pFiller->AddEntry(szText: "16" , id: 16); |
| 1280 | pFiller->AddEntry(szText: "18" , id: 18); |
| 1281 | pFiller->AddEntry(szText: "20" , id: 20); |
| 1282 | pFiller->AddEntry(szText: "24" , id: 24); |
| 1283 | pFiller->AddEntry(szText: "28" , id: 28); |
| 1284 | } |
| 1285 | |
| 1286 | bool C4StartupOptionsDlg::OnFontComboSelChange(C4GUI::ComboBox *pForCombo, int32_t idNewSelection) |
| 1287 | { |
| 1288 | // set new value |
| 1289 | const char *szNewFontFace = Config.General.RXFontName; |
| 1290 | int32_t iNewFontSize = Config.General.RXFontSize; |
| 1291 | if (pForCombo == pFontFaceCombo) |
| 1292 | szNewFontFace = DefaultFonts[idNewSelection]; |
| 1293 | else if (pForCombo == pFontSizeCombo) |
| 1294 | iNewFontSize = idNewSelection; |
| 1295 | else |
| 1296 | // can't happen |
| 1297 | return true; |
| 1298 | // set new fonts |
| 1299 | if (!Application.SetGameFont(szFontFace: szNewFontFace, iFontSize: iNewFontSize)) |
| 1300 | { |
| 1301 | GetScreen()->ShowErrorMessage(szMessage: LoadResStr(id: C4ResStrTableKey::IDS_ERR_INITFONTS)); |
| 1302 | return true; |
| 1303 | } |
| 1304 | // recreate everything to reflect font changes |
| 1305 | RecreateDialog(fFade: true); |
| 1306 | return true; |
| 1307 | } |
| 1308 | |
| 1309 | void C4StartupOptionsDlg::OnDisplayModeComboFill(C4GUI::ComboBox_FillCB *pFiller) |
| 1310 | { |
| 1311 | for (const auto &mode : DisplayModes) |
| 1312 | { |
| 1313 | pFiller->AddEntry(szText: LoadResStr(id: mode.caption), id: static_cast<int>(mode.mode)); |
| 1314 | } |
| 1315 | } |
| 1316 | |
| 1317 | bool C4StartupOptionsDlg::OnDisplayModeComboSelChange(C4GUI::ComboBox *pForCombo, int32_t idNewSelection) |
| 1318 | { |
| 1319 | Config.Graphics.UseDisplayMode = static_cast<DisplayMode>(idNewSelection); |
| 1320 | Application.SetDisplayMode(Config.Graphics.UseDisplayMode); |
| 1321 | RecreateDialog(fFade: true); |
| 1322 | return true; |
| 1323 | } |
| 1324 | |
| 1325 | void C4StartupOptionsDlg::RecreateDialog(bool fFade) |
| 1326 | { |
| 1327 | // MUST fade for now, or calling function will fail because dialog is deleted immediately |
| 1328 | fFade = true; |
| 1329 | // this actually breaks the possibility to go back :( |
| 1330 | int32_t iPage = pOptionsTabular->GetActiveSheetIndex(); |
| 1331 | C4StartupOptionsDlg *pNewDlg = static_cast<C4StartupOptionsDlg *>(C4Startup::Get()->SwitchDialog(eToDlg: C4Startup::SDID_Options, fFade)); |
| 1332 | pNewDlg->pOptionsTabular->SelectSheet(iIndex: iPage, fByUser: false); |
| 1333 | pNewDlg->fCanGoBack = false; |
| 1334 | } |
| 1335 | |
| 1336 | void C4StartupOptionsDlg::SaveGfxTroubleshoot() |
| 1337 | { |
| 1338 | lpDDraw->InvalidateDeviceObjects(); |
| 1339 | lpDDraw->RestoreDeviceObjects(); |
| 1340 | } |
| 1341 | |
| 1342 | void C4StartupOptionsDlg::OnEffectsSliderChange(int32_t iNewVal) |
| 1343 | { |
| 1344 | Config.Graphics.SmokeLevel = iNewVal; |
| 1345 | } |
| 1346 | |
| 1347 | void C4StartupOptionsDlg::OnFEMusicCheck(C4GUI::Element *pCheckBox) |
| 1348 | { |
| 1349 | // option change is reflected immediately |
| 1350 | bool fIsOn = static_cast<C4GUI::CheckBox *>(pCheckBox)->GetChecked(); |
| 1351 | if (Config.Sound.FEMusic = fIsOn) |
| 1352 | { |
| 1353 | Application.MusicSystem->PlayFrontendMusic(); |
| 1354 | } |
| 1355 | else |
| 1356 | { |
| 1357 | Application.MusicSystem->Stop(); |
| 1358 | } |
| 1359 | } |
| 1360 | |
| 1361 | void C4StartupOptionsDlg::OnMusicVolumeSliderChange(int32_t iNewVal) |
| 1362 | { |
| 1363 | // option change is reflected immediately; |
| 1364 | Config.Sound.MusicVolume = iNewVal; |
| 1365 | Application.MusicSystem->UpdateVolume(); |
| 1366 | } |
| 1367 | |
| 1368 | void C4StartupOptionsDlg::OnSoundVolumeSliderChange(int32_t iNewVal) |
| 1369 | { |
| 1370 | // sound system reads this value directly |
| 1371 | Config.Sound.SoundVolume = iNewVal; |
| 1372 | // test sound |
| 1373 | StartSoundEffect(name: "ArrowHit" , loop: false, volume: 100, obj: nullptr); |
| 1374 | } |
| 1375 | |
| 1376 | bool C4StartupOptionsDlg::KeyMusicToggle() |
| 1377 | { |
| 1378 | // do toggle and reflect in checkbox |
| 1379 | pFEMusicCheck->SetChecked(Application.MusicSystem->ToggleOnOff()); |
| 1380 | // key processed |
| 1381 | return true; |
| 1382 | } |
| 1383 | |
| 1384 | int32_t C4StartupOptionsDlg::EditConfig::GetIntVal() |
| 1385 | { |
| 1386 | return atoi(nptr: GetEdit()->GetText()); |
| 1387 | } |
| 1388 | |
| 1389 | void C4StartupOptionsDlg::EditConfig::SetIntVal(int32_t iToVal) |
| 1390 | { |
| 1391 | GetEdit()->SetText(text: std::format(fmt: "{}" , args&: iToVal).c_str(), fUser: false); |
| 1392 | } |
| 1393 | |