OpenClonk
C4StartupOptionsDlg.cpp
Go to the documentation of this file.
1 /*
2  * OpenClonk, http://www.openclonk.org
3  *
4  * Copyright (c) 2005-2009, RedWolf Design GmbH, http://www.clonk.de/
5  * Copyright (c) 2009-2016, The OpenClonk Team and contributors
6  *
7  * Distributed under the terms of the ISC license; see accompanying file
8  * "COPYING" for details.
9  *
10  * "Clonk" is a registered trademark of Matthes Bender, used with permission.
11  * See accompanying file "TRADEMARK" for details.
12  *
13  * To redistribute this file separately, substitute the full license texts
14  * for the above references.
15  */
16 // Startup screen for non-parameterized engine start: Options dialog
17 
18 #include "C4Include.h"
21 
22 #include "game/C4Application.h"
23 #include "graphics/C4Draw.h"
25 #include "gui/C4MouseControl.h"
26 #include "gui/C4KeyboardInput.h"
27 #include "gui/C4StartupMainDlg.h"
28 #include "network/C4Network2.h"
29 #include "platform/C4GamePadCon.h"
30 
31 #include "graphics/C4DrawGL.h"
32 
33 // ------------------------------------------------
34 // --- C4StartupOptionsDlg::SmallButton
35 
36 void C4StartupOptionsDlg::SmallButton::DrawElement(C4TargetFacet &cgo)
37 {
38  // draw the button
40  // get text pos
41  float x0 = cgo.TargetX + rcBounds.x, y0 = cgo.TargetY + rcBounds.y, x1 = cgo.TargetX + rcBounds.x + rcBounds.Wdt, y1 = cgo.TargetY + rcBounds.y + rcBounds.Hgt;
42  int32_t iTextHgt = rUseFont.GetLineHeight();
43  // draw frame
44  uint32_t dwClrHigh = C4StartupBtnBorderColor1, dwClrLow = C4StartupBtnBorderColor2;
45  if (fDown) std::swap(dwClrHigh, dwClrLow);
46  int32_t iIndent = Clamp<int32_t>((rcBounds.Hgt-iTextHgt)/3, 2, 5);
47  float iDrawQuadTop[8] = { x0,y0, x1,y0, x1-iIndent,y0+iIndent, x0,y0+iIndent };
48  float iDrawQuadLeft[8] = { x0,y0, x0+iIndent,y0, x0+iIndent,y1-iIndent, x0,y1 };
49  float iDrawQuadRight[8] = { x1,y0, x1,y1, x1-iIndent,y1, x1-iIndent,y0+iIndent };
50  float iDrawQuadBottom[8] = { x1,y1, x0,y1, x0+iIndent,y1-iIndent, x1,y1-iIndent };
51  // TODO: Switch to PerformMultiTris
52  pDraw->DrawQuadDw(cgo.Surface, iDrawQuadTop, dwClrHigh,dwClrHigh,dwClrHigh,dwClrHigh, nullptr);
53  pDraw->DrawQuadDw(cgo.Surface, iDrawQuadLeft, dwClrHigh,dwClrHigh,dwClrHigh,dwClrHigh, nullptr);
54  pDraw->DrawQuadDw(cgo.Surface, iDrawQuadRight, dwClrLow,dwClrLow,dwClrLow,dwClrLow, nullptr);
55  pDraw->DrawQuadDw(cgo.Surface, iDrawQuadBottom, dwClrLow,dwClrLow,dwClrLow,dwClrLow, nullptr);
56  // draw selection highlight
57  int32_t iTxtOff = fDown ? iIndent : 0;
58  if (fEnabled) if (HasDrawFocus() || (fMouseOver && IsInActiveDlg(false)))
59  {
61  ::GraphicsResource.fctButtonHighlight.DrawX(cgo.Surface, x0+5+iTxtOff, y0+3+iTxtOff, rcBounds.Wdt-10, rcBounds.Hgt-6);
63  }
64  // draw button text
65  pDraw->TextOut(sText.getData(), rUseFont, 1.0f, cgo.Surface, (x0+x1)/2 + iTxtOff, (y0+y1-iTextHgt)/2 + iTxtOff, C4StartupBtnFontClr, ACenter, true);
66 }
67 
68 int32_t C4StartupOptionsDlg::SmallButton::GetDefaultButtonHeight()
69 {
70  // button height is used font height plus a small indent
71  CStdFont *pUseFont = &(C4Startup::Get()->Graphics.BookFont);
72  return pUseFont->GetLineHeight()*6/5+6;
73 }
74 
75 
76 // ------------------------------------------------
77 // --- C4StartupOptionsDlg::ResChangeConfirmDlg
78 
79 C4StartupOptionsDlg::ResChangeConfirmDlg::ResChangeConfirmDlg()
80  : C4GUI::Dialog(C4GUI_MessageDlgWdt, 100 /* will be resized */, LoadResStr("IDS_MNU_SWITCHRESOLUTION"), false)
81 {
82  // update-timer
83  Application.Add(this);
84  // An independant group of fourteen highly trained apes and one blind lawnmower have determined
85  // that twelve seconds is just right for normal people
86  iResChangeSwitchTime = 12;
87  // However, some people need more time
88  // Those can be identified by their configuration settings
89  if (SEqualNoCase(Config.GetRegistrationData("Nick"), "flgr")) iResChangeSwitchTime *= 10;
90  // get positions
92  // place icon
93  C4Rect rcIcon = caMain.GetFromLeft(C4GUI_IconWdt); rcIcon.Hgt = C4GUI_IconHgt;
94  C4GUI::Icon *pIcon = new C4GUI::Icon(rcIcon, C4GUI::Ico_Confirm); AddElement(pIcon);
95  // place message labels
96  // use text with line breaks
97  StdStrBuf sMsgBroken;
98  int iMsgHeight = ::GraphicsResource.TextFont.BreakMessage(LoadResStr("IDS_MNU_SWITCHRESOLUTION_LIKEIT"), caMain.GetInnerWidth(), &sMsgBroken, true);
99  C4GUI::Label *pLblMessage = new C4GUI::Label(sMsgBroken.getData(), caMain.GetFromTop(iMsgHeight), ACenter, C4GUI_MessageFontClr, &::GraphicsResource.TextFont, false);
100  AddElement(pLblMessage);
101  iMsgHeight = ::GraphicsResource.TextFont.BreakMessage(FormatString(LoadResStr("IDS_MNU_SWITCHRESOLUTION_UNDO"),
102  (int)iResChangeSwitchTime).getData(),
103  caMain.GetInnerWidth(), &sMsgBroken, true);
104  pOperationCancelLabel = new C4GUI::Label(sMsgBroken.getData(), caMain.GetFromTop(iMsgHeight), ACenter, C4GUI_MessageFontClr, &::GraphicsResource.TextFont, false, false);
105  AddElement(pOperationCancelLabel);
106  // place buttons
107  C4GUI::ComponentAligner caButtonArea(caMain.GetFromTop(C4GUI_ButtonAreaHgt), 0,0);
108  int32_t iButtonCount = 2;
109  C4Rect rcBtn = caButtonArea.GetCentered(iButtonCount*C4GUI_DefButton2Wdt+(iButtonCount-1)*C4GUI_DefButton2HSpace, C4GUI_ButtonHgt);
110  rcBtn.Wdt = C4GUI_DefButton2Wdt;
111  // Yes
112  C4GUI::Button *pBtnYes = new C4GUI::YesButton(rcBtn);
113  AddElement(pBtnYes);
115  // No
116  C4GUI::Button *pBtnNo = new C4GUI::NoButton(rcBtn);
117  AddElement(pBtnNo);
118  // initial focus on abort button, to prevent accidental acceptance of setting by "blind" users
119  SetFocus(pBtnNo, false);
120  // resize to actually needed size
121  SetClientSize(GetClientRect().Wdt, GetClientRect().Hgt - caMain.GetHeight());
122 }
123 
124 C4StartupOptionsDlg::ResChangeConfirmDlg::~ResChangeConfirmDlg()
125 {
126  Application.Remove(this);
127 }
128 
129 void C4StartupOptionsDlg::ResChangeConfirmDlg::OnSec1Timer()
130 {
131  // timer ran out? Then cancel dlg
132  if (!--iResChangeSwitchTime)
133  {
134  Close(false); return;
135  }
136  // update timer label
137  StdStrBuf sTimerText;
138  ::GraphicsResource.TextFont.BreakMessage(FormatString(LoadResStr("IDS_MNU_SWITCHRESOLUTION_UNDO"),
139  (int)iResChangeSwitchTime).getData(),
140  pOperationCancelLabel->GetBounds().Wdt, &sTimerText, true);
141  pOperationCancelLabel->SetText(sTimerText.getData());
142 }
143 
144 // ------------------------------------------------
145 // --- C4StartupOptionsDlg::KeySelDialog
146 
147 C4StartupOptionsDlg::KeySelDialog::KeySelDialog(const C4PlayerControlAssignment *assignment, const C4PlayerControlAssignmentSet *assignment_set)
148  : C4GUI::MessageDialog(GetDlgMessage(assignment, assignment_set).getData(), LoadResStr("IDS_MSG_DEFINEKEY"), C4GUI::MessageDialog::btnAbort | C4GUI::MessageDialog::btnReset, GetDlgIcon(assignment_set), C4GUI::MessageDialog::dsRegular),
149  key(KEY_Undefined), assignment(assignment), assignment_set(assignment_set)
150 {
151  const uint32_t KEYS_Allmod = KEYS_Shift | KEYS_Control | KEYS_Alt;
153  static_assert(KEYS_None == 0, "");
154  for (uint32_t k = KEYS_None; k <= KEYS_Allmod; k++) {
155  if (~KEYS_Allmod & k) // There is some efficient bit-twiddling (k = KEYS_Allmod & (k - KEYS_Allmod) instead of k++), but I figure that's overkill. (Relies on (defined) unsigned overflow)
156  continue;
157  keys.emplace_back(KEY_Any, k);
158  }
159  KeyListeners = std::make_unique<C4KeyBinding>(
160  keys,
161  "DefineKey",
162  KEYSCOPE_Gui,
164  *this,
165  &C4StartupOptionsDlg::KeySelDialog::KeyDown,
166  &C4StartupOptionsDlg::KeySelDialog::KeyUp
167  ),
169  );
170 }
171 
172 StdStrBuf C4StartupOptionsDlg::KeySelDialog::GetDlgMessage(const C4PlayerControlAssignment *assignment, const C4PlayerControlAssignmentSet *assignment_set)
173 {
174  // compose message asking for key, gamepad button and/or mouse button depending on used control set
175  if (!assignment || !assignment_set) return StdStrBuf("err");
176  StdStrBuf result_string;
177  if (assignment_set->HasGamepad())
178  result_string.Take(FormatString(LoadResStr("IDS_MSG_PRESSBTN"), assignment->GetGUIName(Game.PlayerControlDefs)));
179  else
180  result_string.Take(FormatString(LoadResStr("IDS_MSG_PRESSKEY"), assignment->GetGUIName(Game.PlayerControlDefs)));
181  const char *ctrl_desc = assignment->GetGUIDesc(Game.PlayerControlDefs);
182 
183  if (ctrl_desc && *ctrl_desc)
184  {
185  result_string.Append("||");
186  result_string.Append(ctrl_desc);
187  }
188  return result_string;
189 }
190 
191 C4GUI::Icons C4StartupOptionsDlg::KeySelDialog::GetDlgIcon(const C4PlayerControlAssignmentSet *assignment_set)
192 {
193  if (!assignment_set) return C4GUI::Ico_Error;
194  if (assignment_set->HasGamepad()) return C4GUI::Ico_Gamepad;
195  return C4GUI::Ico_Keyboard;
196 }
197 
198 void C4StartupOptionsDlg::KeySelDialog::MouseInput(C4GUI::CMouse& rMouse, int32_t iButton, int32_t iX, int32_t iY, DWORD dwKeyParam)
199 {
200  // Original action
201  C4GUI::MessageDialog::MouseInput(rMouse, iButton, iX, iY, dwKeyParam);
202 
203  // Find out to where the input was made (code duplication with C4GUI::Window::MouseInput)
204  // get client pos
206  iX -= rcClientRect.x - rcBounds.x; iY -= rcClientRect.y - rcBounds.y;
207  // forward to topmost child element
208  for (Element *pChild = pLast; pChild; pChild = pChild->GetPrev())
209  if (pChild->fVisible && pChild->GetBounds().Contains(iX, iY))
210  {
211  if (dynamic_cast<C4GUI::Label*>(pChild))
212  break;
213  else
214  return;
215  }
216  // Only process the input event if the user certainly didn't click a button or anything...
217 
218  if (iButton == C4MC_Button_None) // mouse got moved
219  return;
220  bool down;
221  auto key = C4KeyCodeEx::FromC4MC(0 /* FIXME: more mice! */, iButton, dwKeyParam, &down);
222  KeyPress(key, down);
223 }
224 
225 bool C4StartupOptionsDlg::KeySelDialog::KeyPress(const C4KeyCodeEx &key, bool fDown)
226 {
227  // safety
228  if (!assignment || !assignment_set) return false;
229  // check if key is valid for this set
230  if (Key_IsGamepad(key.Key))
231  {
232  if (!assignment_set->HasGamepad()) return false;
233  }
234  else if (Key_IsMouse(key.Key))
235  {
236  if (!assignment_set->HasMouse()) return false;
237  }
238  else
239  {
240  if (!assignment_set->HasKeyboard()) return false;
241  }
242  // FIXME: There doesn't seem to be any kind of KEY_IsModifier function…
243  if ((KEY_IsModifier(key.Key) && fDown) ||
244  (!KEY_IsModifier(key.Key) && !fDown))
245  return false;
246  // okay, use it
247  this->key=key;
248  Close(true);
249  return true;
250 }
251 
252 
253 // ------------------------------------------------
254 // --- C4StartupOptionsDlg::ControlConfigListBox::ControlAssignmentLabel
255 
256 C4StartupOptionsDlg::ControlConfigListBox::ControlAssignmentLabel::ControlAssignmentLabel(class C4PlayerControlAssignment *assignment, class C4PlayerControlAssignmentSet *assignment_set, const C4Rect &bounds)
257  : C4GUI::Label("", bounds, ALeft, 0xffffffff, nullptr, false, false, true), assignment(assignment), assignment_set(assignment_set)
258 {
259  UpdateAssignmentString();
260 }
261 
262 void C4StartupOptionsDlg::ControlConfigListBox::ControlAssignmentLabel::MouseInput(C4GUI::CMouse &rMouse, int32_t iButton, int32_t iX, int32_t iY, DWORD dwKeyParam)
263  {
264  // left-click to change key
265  if (iButton == C4MC_Button_LeftDown && assignment)
266  {
267  if(!assignment->IsGUIDisabled())
268  {
269  KeySelDialog *dlg = new KeySelDialog(assignment, assignment_set);
270  dlg->SetDelOnClose(false);
271  bool success = GetScreen()->ShowModalDlg(dlg, false);
272  C4KeyCodeEx key = dlg->GetKeyCode();
273  delete dlg;
274  if (success)
275  {
276  // dialog closed by pressing a key or by the Reset button (in which case, key==KEY_Undefined)
277  // assign new config
278  C4StartupOptionsDlg::ControlConfigListBox::SetUserKey(assignment_set, assignment, key);
279  UpdateAssignmentString();
280  }
281  }
282  }
283  // inherited
284  Element::MouseInput(rMouse, iButton, iX, iY, dwKeyParam);
285  }
286 
287 void C4StartupOptionsDlg::ControlConfigListBox::ControlAssignmentLabel::UpdateAssignmentString()
288 {
289  // assignment label text from assigned key
290  StdStrBuf strKey;
291  C4KeyCodeEx key(0);
292  if (assignment)
293  {
294  SetText(assignment->GetKeysAsString(true, false).getData());
295  }
296  else
297  {
298  SetText("");
299  }
300  DWORD color = C4GUI_CaptionFontClr;
301  if (assignment)
302  {
303  if(assignment->IsGUIDisabled())
305  else if(assignment->IsKeyChanged())
306  color = C4GUI_Caption2FontClr;
307  }
308  SetColor(color);
309 }
310 
311 // ------------------------------------------------
312 // --- C4StartupOptionsDlg::ControlConfigListBox::ListItem
313 
314 C4StartupOptionsDlg::ControlConfigListBox::ListItem::ListItem(ControlConfigListBox *parent_list, class C4PlayerControlAssignment *assignment, class C4PlayerControlAssignmentSet *assignment_set, bool has_extra_spacing)
315  : C4GUI::Window(), parent_list(parent_list), assignment_label(nullptr), has_extra_spacing(has_extra_spacing)
316 {
317  int32_t margin = 2;
318  // adding to listbox will size the element horizontally and move to proper position
319  int32_t height = ::GraphicsResource.TextFont.GetLineHeight() + 2 * margin;
320  SetBounds(C4Rect(0,0,42,height));
321  parent_list->InsertElement(this, nullptr);
322  int32_t name_col_width = GetBounds().Wdt * 2/3;
323  // child elements: two labels for two columns
324  const char *gui_name = assignment->GetGUIName(Game.PlayerControlDefs);
325  const char *gui_desc = assignment->GetGUIDesc(Game.PlayerControlDefs);
326  C4GUI::Label *name_label = new C4GUI::Label(gui_name ? gui_name : "?undefined?", margin, margin);
327  C4Rect assignment_label_bounds = C4Rect(name_col_width + margin, margin, GetBounds().Wdt - name_col_width - margin, GetBounds().Hgt - 2 * margin);
328  assignment_label = new ControlAssignmentLabel(assignment, assignment_set, assignment_label_bounds);
329  AddElement(name_label);
330  AddElement(assignment_label);
331  if (gui_desc && *gui_desc) SetToolTip(gui_desc);
332 }
333 
334 
335 // ------------------------------------------------
336 // --- C4StartupOptionsDlg::ControlConfigListBox
337 
338 C4StartupOptionsDlg::ControlConfigListBox::ControlConfigListBox(const C4Rect &rcBounds, class C4PlayerControlAssignmentSet *set)
339  : C4GUI::ListBox(rcBounds), set(nullptr)
340 {
341  SetAssignmentSet(set);
342 }
343 
344 void C4StartupOptionsDlg::ControlConfigListBox::SetAssignmentSet(class C4PlayerControlAssignmentSet *new_set)
345 {
346  set = new_set;
347  // clear previous elements
348  if (pClientWindow) pClientWindow->ClearChildren();
349  // populate with new assignments
350  if (set)
351  {
352  C4PlayerControlAssignment *assignment;
353 
354  std::vector<C4PlayerControlAssignment *> grouped_assignments;
355  for (int32_t i=0; (assignment = set->GetAssignmentByIndex(i)); ++i)
356  grouped_assignments.push_back(assignment);
357 
358  std::stable_sort(grouped_assignments.begin(),grouped_assignments.end(),&C4StartupOptionsDlg::ControlConfigListBox::sort_by_group);
359 
360  int32_t current_group = 0;
361  for (auto & grouped_assignment : grouped_assignments)
362  {
363  assignment = grouped_assignment;
364  bool first_element_of_group = assignment->GetGUIGroup() > current_group;
365  current_group = assignment->GetGUIGroup();
366  // only show assignments of GUI-named controls
367  const char *gui_name = assignment->GetGUIName(Game.PlayerControlDefs);
368  if (gui_name && *gui_name)
369  {
370  ListItem *element = new ListItem(this, assignment, set, first_element_of_group);
371  AddElement(element);
372  }
373  }
374  }
375 }
376 
377 void C4StartupOptionsDlg::ControlConfigListBox::SetUserKey(class C4PlayerControlAssignmentSet *assignment_set, class C4PlayerControlAssignment *assignment, C4KeyCodeEx &key)
378 {
379  // change key in the specified assignment set to the specified value
380  // also changes config values so change is kept after restart
381  // safety
382  if (!assignment || !assignment_set) return;
383  class C4PlayerControlAssignmentSet *config_set = Config.Controls.UserSets.GetSetByName(assignment_set->GetName());
384  // change key
385  if (key.Key == KEY_Undefined)
386  {
387  // reset to default
388  assignment->ResetKeyToInherited();
389  // also reset in config
390  if (config_set)
391  {
392  config_set->RemoveAssignmentByControlName(assignment->GetControlName());
393  if (!config_set->GetAssignmentByIndex(0))
394  {
395  // if config set is empty, no overrides exist and the set can be deleted (unless it's a custom config set)
397  {
398  Config.Controls.UserSets.RemoveSetByName(assignment_set->GetName());
399  }
400  }
401  }
402  }
403  else
404  {
405  // set to specified value
406  assignment->SetKey(key);
407  // also set in config
408  if (!config_set) config_set = Config.Controls.UserSets.CreateEmptySetByTemplate(*assignment_set);
409  C4PlayerControlAssignment *config_assignment = config_set->GetAssignmentByControlName(assignment->GetControlName());
410  if (!config_assignment) config_assignment = config_set->CreateAssignmentForControl(assignment->GetControlName());
411  config_assignment->SetKey(key);
412  // check for duplicates. Allow them in principle because they can be used with priorities
413  // however, do warn because usually it may be unintended
414  // Just deleting the old assignments is also usually undesirable, because half of the time a newbi changes a control and creates a conflict,
415  // they may want to change the key they just assigned to something else instead
416  C4PlayerControlAssignment *other_assignment;
417  for (int32_t i = 0; (other_assignment = assignment_set->GetAssignmentByIndex(i)); ++i)
418  if (other_assignment != assignment)
419  if (other_assignment->GetTriggerKey() == key)
420  {
421  const char *gui_name = other_assignment->GetGUIName(Game.PlayerControlDefs);
422  // only warn for assignable keys, because other keys are typically derived from the settable keys
423  if (gui_name && *gui_name)
424  {
425  C4GUI::TheScreen.ShowMessage(FormatString(LoadResStr("IDS_MSG_DEFINEKEYDUPLICATE"), key.ToString(true, false).getData(), gui_name).getData(), LoadResStr("IDS_MSG_DEFINEKEY"), C4GUI::Ico_Error);
426  }
427  }
428 
429  }
430 }
431 
432 // ------------------------------------------------
433 // --- C4StartupOptionsDlg::ControlConfigArea
434 
435 C4StartupOptionsDlg::ControlConfigArea::ControlConfigArea(const C4Rect &rcArea, int32_t iHMargin, int32_t iVMargin, bool fGamepad, C4StartupOptionsDlg *pOptionsDlg)
436  : C4GUI::Window(), fGamepad(fGamepad), pOptionsDlg(pOptionsDlg), pGUICtrl(nullptr)
437 {
438  CStdFont *pUseFontSmall = &(C4Startup::Get()->Graphics.BookSmallFont);
439  SetBounds(rcArea);
440  C4GUI::ComponentAligner caArea(rcArea, iHMargin, iVMargin, true);
441  // get number of control sets to be configured
443  iMaxControlSets = std::max<size_t>(assignment_sets.GetSetCount(),1u); // do not devide by zero
444  ppKeyControlSetBtns = new C4GUI::IconButton *[iMaxControlSets];
445  // top line buttons to select control configuration
446  C4Facet fctCtrlDefPic = ::GraphicsResource.fctKeyboard; //
447  int32_t iCtrlSetWdt = caArea.GetWidth() - caArea.GetHMargin()*2;
448  int32_t iCtrlSetHMargin = 5, iCtrlSetVMargin = 5;
449  int32_t iCtrlSetBtnWdt = Clamp<int32_t>((iCtrlSetWdt - iMaxControlSets*iCtrlSetHMargin*2) / iMaxControlSets, 5, fctCtrlDefPic.Wdt);
450  int32_t iCtrlSetBtnHgt = fctCtrlDefPic.GetHeightByWidth(iCtrlSetBtnWdt);
451  iCtrlSetHMargin = (iCtrlSetWdt - iCtrlSetBtnWdt*iMaxControlSets) / (iMaxControlSets*2);
452  C4GUI::ComponentAligner caKeyboardSetSel(caArea.GetFromTop(2*iCtrlSetVMargin+iCtrlSetBtnHgt), iCtrlSetHMargin, iCtrlSetVMargin);
453  const char *szCtrlSetHotkeys = "1234567890"; /* 2do */
454  uint32_t i;
455  for (i = 0; i < assignment_sets.GetSetCount(); ++i)
456  {
457  C4PlayerControlAssignmentSet *assignment_set = assignment_sets.GetSetByIndex(i);
458  char cCtrlSetHotkey = 0;
459  if (i <= strlen(szCtrlSetHotkeys)) cCtrlSetHotkey = szCtrlSetHotkeys[i];
460  C4GUI::CallbackButton<C4StartupOptionsDlg::ControlConfigArea, C4GUI::IconButton> *pBtn = new C4GUI::CallbackButton<C4StartupOptionsDlg::ControlConfigArea, C4GUI::IconButton>(C4GUI::Ico_None, caKeyboardSetSel.GetFromLeft(iCtrlSetBtnWdt), cCtrlSetHotkey, &C4StartupOptionsDlg::ControlConfigArea::OnCtrlSetBtn, this);
461  C4Facet fctCtrlPic = assignment_set->GetPicture();
462  pBtn->SetFacet(fctCtrlPic);
463  AddElement(ppKeyControlSetBtns[i] = pBtn);
464  pBtn->SetText(assignment_set->GetGUIName());
465  pBtn->SetFont(pUseFontSmall, C4StartupFontClr);
466  pBtn->SetToolTip(LoadResStr("IDS_DLGTIP_CHANGECTRL"));
467  }
468  iSelectedCtrlSet = 0;
469  caArea.ExpandTop(caArea.GetVMargin());
470  AddElement(new C4GUI::HorizontalLine(caArea.GetFromTop(2)));
471  caArea.ExpandTop(caArea.GetVMargin());
472  control_list = new ControlConfigListBox(caArea.GetFromLeft(caArea.GetInnerWidth()), nullptr);
473  AddElement(control_list);
474 
475  UpdateCtrlSet();
476 }
477 
478 C4StartupOptionsDlg::ControlConfigArea::~ControlConfigArea()
479 {
480  delete [] ppKeyControlSetBtns;
481 }
482 
483 void C4StartupOptionsDlg::ControlConfigArea::OnCtrlSetBtn(C4GUI::Control *btn)
484 {
485  // select Ctrl set of pressed btn
486  int i;
487  for (i = 0; i < iMaxControlSets; ++i)
488  if (btn == ppKeyControlSetBtns[i])
489  {
490  iSelectedCtrlSet = i;
491  break;
492  }
493  // update shown keys
494  UpdateCtrlSet();
495 }
496 
497 void C4StartupOptionsDlg::ControlConfigArea::UpdateCtrlSet()
498 {
499  // selected keyboard set btn gets a highlight
500  int i;
501  for (i = 0; i < iMaxControlSets; ++i)
502  ppKeyControlSetBtns[i]->SetHighlight(i == iSelectedCtrlSet);
503  // update list
504  control_list->SetAssignmentSet(Game.PlayerControlUserAssignmentSets.GetSetByIndex(iSelectedCtrlSet));
505 }
506 
507 void C4StartupOptionsDlg::ControlConfigArea::OnResetKeysBtn(C4GUI::Control *btn)
508 {
509  // default keys and axis reset
511  UpdateCtrlSet();
512 }
513 
514 void C4StartupOptionsDlg::ControlConfigArea::OnGUIGamepadCheckChange(C4GUI::Element *pCheckBox)
515 {
516  // same as before?
517  bool fChecked = ((C4GUI::CheckBox *)(pCheckBox))->GetChecked();
518  if (fChecked == !!Config.Controls.GamepadGuiControl) return;
519  // reflect change
520  Config.Controls.GamepadGuiControl = fChecked;
522  pOptionsDlg->RecreateDialog(false);
523 }
524 
525 
526 
527 // ------------------------------------------------
528 // --- C4StartupOptionsDlg::NetworkPortConfig
529 
530 C4StartupOptionsDlg::NetworkPortConfig::NetworkPortConfig(const C4Rect &rcBounds, const char *szName, int32_t *pConfigValue, int32_t iDefault)
531  : C4GUI::Window(), pConfigValue(pConfigValue)
532 {
533  // ctor
534  CStdFont *pUseFont = &(C4Startup::Get()->Graphics.BookFont);
535  SetBounds(rcBounds);
536  C4GUI::ComponentAligner caMain(GetClientRect(), 0,2, true);
537  bool fEnabled = (*pConfigValue != -1);
538  C4GUI::Label *pLbl = new C4GUI::Label(szName, caMain.GetFromTop(pUseFont->GetLineHeight()), ALeft, C4StartupFontClr, pUseFont, false);
539  AddElement(pLbl);
540  C4GUI::ComponentAligner caBottomLine(caMain.GetAll(), 2,0, false);
541  const char *szText = LoadResStr("IDS_CTL_ACTIVE");
542  int iWdt=100, iHgt=12;
543  C4GUI::CheckBox::GetStandardCheckBoxSize(&iWdt, &iHgt, szText, pUseFont);
544  pEnableCheck = new C4GUI::CheckBox(caBottomLine.GetFromLeft(iWdt, iHgt), szText, fEnabled);
545  pEnableCheck->SetFont(pUseFont, C4StartupFontClr, C4StartupFontClrDisabled);
546  pEnableCheck->SetOnChecked(new C4GUI::CallbackHandler<C4StartupOptionsDlg::NetworkPortConfig>(this, &C4StartupOptionsDlg::NetworkPortConfig::OnEnabledCheckChange));
547  AddElement(pEnableCheck);
548  pPortEdit = new C4GUI::Edit(caBottomLine.GetAll(), true);
550  pPortEdit->SetFont(pUseFont);
551  pPortEdit->InsertText(FormatString("%d", fEnabled ? ((int) *pConfigValue) : (int) iDefault).getData(), false);
552  pPortEdit->SetMaxText(10); // 65535 is five characters long - but allow some more for easier editing
553  pPortEdit->SetVisibility(fEnabled);
554  AddElement(pPortEdit);
555 }
556 
557 void C4StartupOptionsDlg::NetworkPortConfig::OnEnabledCheckChange(C4GUI::Element *pCheckBox)
558 {
559  pPortEdit->SetVisibility(pEnableCheck->GetChecked());
560 }
561 
562 void C4StartupOptionsDlg::NetworkPortConfig::SavePort()
563 {
564  *pConfigValue=GetPort();
565 }
566 
567 int32_t C4StartupOptionsDlg::NetworkPortConfig::GetPort()
568 {
569  // controls to config
570  if (!pEnableCheck->GetChecked())
571  return -1;
572  else
573  return atoi(pPortEdit->GetText());
574 }
575 
576 bool C4StartupOptionsDlg::NetworkPortConfig::GetControlSize(int *piWdt, int *piHgt)
577 {
578  CStdFont *pUseFont = &(C4Startup::Get()->Graphics.BookFont);
579  // get size needed for control
580  if (piWdt)
581  {
582  const char *szText = LoadResStr("IDS_CTL_ACTIVE");
583  if (!C4GUI::CheckBox::GetStandardCheckBoxSize(piWdt, piHgt, szText, pUseFont)) return false;
584  *piWdt *= 2;
585  }
586  if (piHgt) *piHgt = C4GUI::Edit::GetCustomEditHeight(pUseFont) + pUseFont->GetLineHeight()+2*4;
587  return true;
588 }
589 
590 
591 // ------------------------------------------------
592 // --- C4StartupOptionsDlg::NetworkServerAddressConfig
593 
594 C4StartupOptionsDlg::NetworkServerAddressConfig::NetworkServerAddressConfig(const C4Rect &rcBounds, const char *szName, int32_t *piConfigEnableValue, char *szConfigAddressValue, int iTabWidth)
595  : C4GUI::Window(), piConfigEnableValue(piConfigEnableValue), szConfigAddressValue(szConfigAddressValue)
596 {
597  // ctor
598  CStdFont *pUseFont = &(C4Startup::Get()->Graphics.BookFont);
599  SetBounds(rcBounds);
600  C4GUI::ComponentAligner caMain(GetClientRect(), 0,2, true);
601  pEnableCheck = new C4GUI::CheckBox(caMain.GetFromLeft(iTabWidth, pUseFont->GetLineHeight()), szName, !!*piConfigEnableValue);
602  pEnableCheck->SetFont(pUseFont, C4StartupFontClr, C4StartupFontClrDisabled);
603  pEnableCheck->SetOnChecked(new C4GUI::CallbackHandler<C4StartupOptionsDlg::NetworkServerAddressConfig>(this, &C4StartupOptionsDlg::NetworkServerAddressConfig::OnEnabledCheckChange));
604  AddElement(pEnableCheck);
605  caMain.ExpandLeft(-2);
606  pAddressEdit = new C4GUI::Edit(caMain.GetAll(), true);
608  pAddressEdit->SetFont(pUseFont);
609  pAddressEdit->InsertText(szConfigAddressValue, false);
610  pAddressEdit->SetMaxText(CFG_MaxString);
611  pAddressEdit->SetVisibility(!!*piConfigEnableValue);
612  AddElement(pAddressEdit);
613 }
614 
615 void C4StartupOptionsDlg::NetworkServerAddressConfig::OnEnabledCheckChange(C4GUI::Element *pCheckBox)
616 {
617  // warn about using alternate servers
618  if (pEnableCheck->GetChecked())
619  {
620  GetScreen()->ShowMessage(LoadResStr("IDS_NET_NOOFFICIALLEAGUE"), LoadResStr("IDS_NET_QUERY_MASTERSRV"), C4GUI::Ico_Notify, &Config.Startup.HideMsgNoOfficialLeague);
621  }
622  // callback when checkbox is ticked
623  pAddressEdit->SetVisibility(pEnableCheck->GetChecked());
624 }
625 
626 void C4StartupOptionsDlg::NetworkServerAddressConfig::Save2Config()
627 {
628  // controls to config
629  *piConfigEnableValue = pEnableCheck->GetChecked();
630  SCopy(pAddressEdit->GetText(), szConfigAddressValue, CFG_MaxString);
631 }
632 
633 bool C4StartupOptionsDlg::NetworkServerAddressConfig::GetControlSize(int *piWdt, int *piHgt, int *piTabPos, const char *szForText)
634 {
635  CStdFont *pUseFont = &(C4Startup::Get()->Graphics.BookFont);
636  int iWdt=120;
637  C4GUI::CheckBox::GetStandardCheckBoxSize(&iWdt, piHgt, szForText, pUseFont);
638  int32_t iEdtWdt=120, iEdtHgt=24;
639  pUseFont->GetTextExtent("sorgentelefon@treffpunktclonk.net", iEdtWdt, iEdtHgt, false);
640  if (piWdt) *piWdt = iWdt+iEdtWdt+2;
641  if (piTabPos) *piTabPos = iWdt+2;
642  if (piHgt) *piHgt = C4GUI::Edit::GetCustomEditHeight(pUseFont)+2*2;
643  return true;
644 }
645 
646 
647 
648 // ------------------------------------------------
649 // --- C4StartupOptionsDlg::BoolConfig
650 
651 C4StartupOptionsDlg::BoolConfig::BoolConfig(const C4Rect &rcBounds, const char *szName, bool *pbVal, int32_t *piVal, bool fInvert, int32_t *piRestartChangeCfgVal)
652  : C4GUI::CheckBox(rcBounds, szName, fInvert != (pbVal ? *pbVal : !!*piVal)), pbVal(pbVal), fInvert(fInvert), piVal(piVal), piRestartChangeCfgVal(piRestartChangeCfgVal)
653 {
654  SetOnChecked(new C4GUI::CallbackHandler<BoolConfig>(this, &BoolConfig::OnCheckChange));
655 }
656 
657 void C4StartupOptionsDlg::BoolConfig::OnCheckChange(C4GUI::Element *pCheckBox)
658 {
659  if (pbVal) *pbVal = (GetChecked() != fInvert);
660  if (piVal) *piVal = (GetChecked() != fInvert);
661  if (piRestartChangeCfgVal) GetScreen()->ShowMessage(LoadResStr("IDS_MSG_RESTARTCHANGECFG"), GetText(),
662  C4GUI::Ico_Notify, piRestartChangeCfgVal);
663 }
664 
665 // ------------------------------------------------
666 // --- C4StartupOptionsDlg::EditConfig
667 
668 C4StartupOptionsDlg::EditConfig::EditConfig(const C4Rect &rcBounds, const char *szName, ValidatedStdCopyStrBufBase *psConfigVal, int32_t *piConfigVal, bool fMultiline)
669  : C4GUI::LabeledEdit(rcBounds, szName, fMultiline, psConfigVal ? psConfigVal->getData() : nullptr, &(C4Startup::Get()->Graphics.BookFont), C4StartupFontClr), psConfigVal(psConfigVal), piConfigVal(piConfigVal)
670 {
671  // ctor
673  if (piConfigVal) SetIntVal(*piConfigVal);
674  GetEdit()->SetMaxText(CFG_MaxString);
675 }
676 
677 void C4StartupOptionsDlg::EditConfig::Save2Config()
678 {
679  // controls to config
680  if (psConfigVal)
681  psConfigVal->CopyValidated(GetEdit()->GetText());
682  if (piConfigVal)
683  *piConfigVal = GetIntVal();
684 }
685 
686 bool C4StartupOptionsDlg::EditConfig::GetControlSize(int *piWdt, int *piHgt, const char *szForText, bool fMultiline)
687 {
688  CStdFont *pUseFont = &(C4Startup::Get()->Graphics.BookFont);
689  typedef C4GUI::LabeledEdit BaseEdit;
690  return BaseEdit::GetControlSize(piWdt, piHgt, szForText, pUseFont, fMultiline);
691 }
692 
693 // ------------------------------------------------
694 // --- C4StartupOptionsDlg
695 
697 {
698  // ctor
699  UpdateSize();
700  bool fSmall = (GetClientRect().Wdt < 750);
701  CStdFont *pUseFont = &(C4Startup::Get()->Graphics.BookFont);
702 
703  // key bindings
705  keys.emplace_back(K_BACK); keys.emplace_back(K_LEFT);
706  pKeyBack = new C4KeyBinding(keys, "StartupOptionsBack", KEYSCOPE_Gui,
708  keys.clear();
709  keys.emplace_back(K_F3); // overloading global toggle with higher priority here, so a new name is required
710  pKeyToggleMusic = new C4KeyBinding(keys, "OptionsMusicToggle", KEYSCOPE_Gui,
712 
713  // screen calculations
714  int32_t iButtonWidth,iCaptionFontHgt;
715  int32_t iButtonHeight = C4GUI_ButtonHgt;
716  ::GraphicsResource.CaptionFont.GetTextExtent("<< BACK", iButtonWidth, iCaptionFontHgt, true);
717  iButtonWidth *= 3;
718  int iIndentX1, iIndentY1, iIndentY2;
719  if (fSmall)
720  {
721  iIndentX1=20;
722  }
723  else
724  {
725  iIndentX1 = GetClientRect().Wdt/40;
726  }
727  if (fSmall)
728  {
729  iIndentY1=1; iIndentY2=1;
730  }
731  else
732  {
733  iIndentY1 = GetClientRect().Hgt/200;
734  iIndentY2 = std::max<int32_t>(1, iIndentY1/2);
735  }
736  C4GUI::ComponentAligner caMain(GetClientRect(), 0,0, true);
737  C4GUI::ComponentAligner caButtonArea(caMain.GetFromBottom(caMain.GetHeight()/(fSmall ? 20 : 7)),0,0);
738  C4GUI::ComponentAligner caButtons(caButtonArea.GetCentered(caMain.GetWidth()*7/8, iButtonHeight),0,0);
739  C4GUI::ComponentAligner caConfigArea(caMain.GetAll(), fSmall ? 0 : (caMain.GetWidth()*69/1730), fSmall ? 0 : (caMain.GetHeight()/200));
740 
741  // back button
743  AddElement(btn = new C4GUI::CallbackButton<C4StartupOptionsDlg>(LoadResStr("IDS_BTN_BACK"), caButtons.GetFromLeft(iButtonWidth), &C4StartupOptionsDlg::OnBackBtn));
744  btn->SetToolTip(LoadResStr("IDS_DLGTIP_BACKMAIN"));
745 
746  // main config area tabular
747  pOptionsTabular = new C4GUI::Tabular(caConfigArea.GetAll(), C4GUI::Tabular::tbLeft);
749  AddElement(pOptionsTabular);
750  C4GUI::Tabular::Sheet *pSheetGeneral = pOptionsTabular->AddSheet(LoadResStr("IDS_DLG_PROGRAM") , 0);
751  C4GUI::Tabular::Sheet *pSheetGraphics = pOptionsTabular->AddSheet(LoadResStr("IDS_DLG_GRAPHICS"), 1);
752  C4GUI::Tabular::Sheet *pSheetSound = pOptionsTabular->AddSheet(LoadResStr("IDS_DLG_SOUND") , 2);
753  C4GUI::Tabular::Sheet *pSheetControls= pOptionsTabular->AddSheet(LoadResStr("IDS_DLG_CONTROLS"), 3);
754  C4GUI::Tabular::Sheet *pSheetNetwork = pOptionsTabular->AddSheet(LoadResStr("IDS_DLG_NETWORK") , 5);
755 
756  C4GUI::CheckBox *pCheck; C4GUI::Label *pLbl;
757  int iCheckWdt=100, iCheckHgt=20, iEdit2Wdt=100, iEdit2Hgt=40;
758  BoolConfig::GetStandardCheckBoxSize(&iCheckWdt, &iCheckHgt, "Default text", pUseFont);
759  EditConfig::GetControlSize(&iEdit2Wdt, &iEdit2Hgt, "Default text", false);
760 
761  // --- page program
762  C4GUI::ComponentAligner caSheetProgram(pSheetGeneral->GetClientRect(), caMain.GetWidth()/20, caMain.GetHeight()/20, true);
763  // language
764  const char *szLangTip = LoadResStr("IDS_MSG_SELECTLANG");
765  C4GUI::ComponentAligner caLanguage(caSheetProgram.GetGridCell(0,1,0,7,-1,-1,true,1,2), 0, C4GUI_DefDlgSmallIndent, false);
766  C4GUI::ComponentAligner caLanguageBox(caLanguage.GetFromTop(C4GUI::ComboBox::GetDefaultHeight()), 0, 0, false);
767  StdStrBuf sLangStr; sLangStr.Copy(LoadResStr("IDS_CTL_LANGUAGE")); sLangStr.AppendChar(':');
768  int32_t w,q;
769  pUseFont->GetTextExtent(sLangStr.getData(), w,q,true);
770  pLbl = new C4GUI::Label(sLangStr.getData(), caLanguageBox.GetFromLeft(w+C4GUI_DefDlgSmallIndent), ALeft, C4StartupFontClr, pUseFont, false);
771  pLbl->SetToolTip(szLangTip);
772  pSheetGeneral->AddElement(pLbl);
773  pUseFont->GetTextExtent("XX: Top Secret Language", w,q,true);
774  pLangCombo = new C4GUI::ComboBox(caLanguageBox.GetFromLeft(std::min(w, caLanguageBox.GetWidth())));
775  pLangCombo->SetToolTip(szLangTip);
776  pLangCombo->SetComboCB(new C4GUI::ComboBox_FillCallback<C4StartupOptionsDlg>(this, &C4StartupOptionsDlg::OnLangComboFill, &C4StartupOptionsDlg::OnLangComboSelChange));
777  pLangCombo->SetColors(C4StartupFontClr, C4StartupEditBGColor, C4StartupEditBorderColor);
778  pLangCombo->SetFont(pUseFont);
779  pLangCombo->SetDecoration(&(C4Startup::Get()->Graphics.fctContext));
780  pSheetGeneral->AddElement(pLangCombo);
781  pLangInfoLabel = new C4GUI::Label(nullptr, caLanguage.GetFromTop(::GraphicsResource.TextFont.GetLineHeight()*3), ALeft, C4StartupFontClr, pUseFont, false);
782  pLangInfoLabel->SetToolTip(szLangTip);
783  pSheetGeneral->AddElement(pLangInfoLabel);
784  UpdateLanguage();
785  // font
786  const char *szFontTip = LoadResStr("IDS_DESC_SELECTFONT");
787  C4GUI::ComponentAligner caFontBox(caSheetProgram.GetGridCell(0,1,2,7,-1,C4GUI::ComboBox::GetDefaultHeight(), true), 0, 0, false);
788  StdStrBuf sFontStr; sFontStr.Copy(LoadResStr("IDS_CTL_FONT")); sFontStr.AppendChar(':');
789  pUseFont->GetTextExtent(sFontStr.getData(), w,q,true);
790  pLbl = new C4GUI::Label(sFontStr.getData(), caFontBox.GetFromLeft(w+C4GUI_DefDlgSmallIndent), ALeft, C4StartupFontClr, pUseFont, false);
791  pLbl->SetToolTip(szFontTip);
792  pSheetGeneral->AddElement(pLbl);
793  pUseFont->GetTextExtent("Comic Sans MS", w,q,true);
794  pFontFaceCombo = new C4GUI::ComboBox(caFontBox.GetFromLeft(std::min<int32_t>(caFontBox.GetInnerWidth()*3/4, w*3)));
795  pFontFaceCombo->SetToolTip(szFontTip);
796  pFontFaceCombo->SetComboCB(new C4GUI::ComboBox_FillCallback<C4StartupOptionsDlg>(this, &C4StartupOptionsDlg::OnFontFaceComboFill, &C4StartupOptionsDlg::OnFontComboSelChange));
797  pFontFaceCombo->SetColors(C4StartupFontClr, C4StartupEditBGColor, C4StartupEditBorderColor);
798  pFontFaceCombo->SetFont(pUseFont);
799  pFontFaceCombo->SetDecoration(&(C4Startup::Get()->Graphics.fctContext));
800  caFontBox.ExpandLeft(-C4GUI_DefDlgSmallIndent);
801  pSheetGeneral->AddElement(pFontFaceCombo);
802  pFontSizeCombo = new C4GUI::ComboBox(caFontBox.GetFromLeft(std::min<int32_t>(caFontBox.GetInnerWidth(), w)));
803  pFontSizeCombo->SetToolTip(LoadResStr("IDS_DESC_FONTSIZE"));
804  pFontSizeCombo->SetComboCB(new C4GUI::ComboBox_FillCallback<C4StartupOptionsDlg>(this, &C4StartupOptionsDlg::OnFontSizeComboFill, &C4StartupOptionsDlg::OnFontComboSelChange));
805  pFontSizeCombo->SetColors(C4StartupFontClr, C4StartupEditBGColor, C4StartupEditBorderColor);
806  pFontSizeCombo->SetFont(pUseFont);
807  pFontSizeCombo->SetDecoration(&(C4Startup::Get()->Graphics.fctContext));
808  pSheetGeneral->AddElement(pFontSizeCombo);
809  UpdateFontControls();
810  // MM timer
811  pCheck = new BoolConfig(caSheetProgram.GetGridCell(0,1,3,7,-1,iCheckHgt, true), LoadResStr("IDS_CTL_MMTIMER"), nullptr, &Config.General.MMTimer, true, &Config.Startup.HideMsgMMTimerChange);
812  pCheck->SetToolTip(LoadResStr("IDS_MSG_MMTIMER_DESC"));
813  pCheck->SetFont(pUseFont, C4StartupFontClr, C4StartupFontClrDisabled);
814  pSheetGeneral->AddElement(pCheck);
815  // reset configuration
816  const char *szBtnText = LoadResStr("IDS_BTN_RESETCONFIG");
818  ::GraphicsResource.CaptionFont.GetTextExtent(szBtnText, iButtonWidth, iButtonHeight, true);
819  C4Rect rcResetBtn = caSheetProgram.GetGridCell(1,2,6,7, std::min<int32_t>(iButtonWidth+iButtonHeight*4, caSheetProgram.GetInnerWidth()*2/5), SmallButton::GetDefaultButtonHeight(), true);
820  pSmallBtn = new C4GUI::CallbackButton<C4StartupOptionsDlg, SmallButton>(szBtnText, rcResetBtn, &C4StartupOptionsDlg::OnResetConfigBtn, this);
821  pSheetGeneral->AddElement(pSmallBtn);
822  pSmallBtn->SetToolTip(LoadResStr("IDS_DESC_RESETCONFIG"));
823 
824  // --- page graphics
825  C4GUI::ComponentAligner caSheetGraphics(pSheetGraphics->GetClientRect(), iIndentX1, iIndentY1, true);
826  // --subgroup display
827  C4GUI::GroupBox *pGroupResolution = new C4GUI::GroupBox(caSheetGraphics.GetGridCell(0,1,0,2));
828  pGroupResolution->SetTitle(LoadResStrNoAmp("IDS_CTL_DISPLAY"));
829  pGroupResolution->SetFont(pUseFont);
830  pGroupResolution->SetColors(C4StartupEditBorderColor, C4StartupFontClr);
831  pSheetGraphics->AddElement(pGroupResolution);
832  C4GUI::ComponentAligner caGroupResolution(pGroupResolution->GetClientRect(), iIndentX1, iIndentY2, true);
833  int32_t iNumGfxOptions = 3, iOpt = 0;
834  // resolution combobox
835  C4GUI::ComponentAligner resBox(caGroupResolution.GetGridCell(0,1,iOpt++,iNumGfxOptions), 0, 0, false);
836  w=20; q=12; pUseFont->GetTextExtent(LoadResStr("IDS_CTL_RESOLUTION"), w,q, true);
837  pGroupResolution->AddElement(new C4GUI::Label(LoadResStr("IDS_CTL_RESOLUTION"), resBox.GetFromLeft(w+C4GUI_DefDlgSmallIndent,q), ALeft, C4StartupFontClr, pUseFont, false, false));
838  pUseFont->GetTextExtent("1600 x 1200", w,q,true); w = std::min<int32_t>(caGroupResolution.GetInnerWidth(), w+40);
839  C4GUI::ComboBox *pGfxResCombo = new C4GUI::ComboBox(resBox.GetFromLeft(w+40,C4GUI::ComboBox::GetDefaultHeight()));
840  pGfxResCombo->SetToolTip(LoadResStr("IDS_MSG_RESOLUTION_DESC"));
841  pGfxResCombo->SetComboCB(new C4GUI::ComboBox_FillCallback<C4StartupOptionsDlg>(this, &C4StartupOptionsDlg::OnGfxResComboFill, &C4StartupOptionsDlg::OnGfxResComboSelChange));
842  pGfxResCombo->SetColors(C4StartupFontClr, C4StartupEditBGColor, C4StartupEditBorderColor);
843  pGfxResCombo->SetFont(pUseFont);
844  pGfxResCombo->SetDecoration(&(C4Startup::Get()->Graphics.fctContext));
845  pGfxResCombo->SetText(GetGfxResString(Config.Graphics.ResX, Config.Graphics.ResY).getData());
846  pGroupResolution->AddElement(pGfxResCombo);
847  // fullscreen combobox
848  C4GUI::ComponentAligner fsBox(caGroupResolution.GetGridCell(0,1,iOpt++,iNumGfxOptions), 0, 0, false);
849  w=20; q=12; pUseFont->GetTextExtent(LoadResStr("IDS_CTL_FULLSCREENMODE"), w,q, true);
850  pGroupResolution->AddElement(new C4GUI::Label(LoadResStr("IDS_CTL_FULLSCREENMODE"), fsBox.GetFromLeft(w+C4GUI_DefDlgSmallIndent,q), ALeft, C4StartupFontClr, pUseFont, false, false));
851  uint32_t wmax = 0;
852  for(int i = 0; i < 3; ++i)
853  {
854  pUseFont->GetTextExtent(GetWindowedName(i),w,q,true);
855  wmax = std::max<int32_t>(w, wmax);
856  }
857  C4GUI::ComboBox * pCombo = new C4GUI::ComboBox(fsBox.GetFromLeft(w+40,C4GUI::ComboBox::GetDefaultHeight()));
858  pCombo->SetComboCB(new C4GUI::ComboBox_FillCallback<C4StartupOptionsDlg>(this, &C4StartupOptionsDlg::OnWindowedModeComboFill, &C4StartupOptionsDlg::OnWindowedModeComboSelChange));
859  pCombo->SetToolTip(LoadResStr("IDS_MSG_FULLSCREEN_DESC"));
860  pCombo->SetColors(C4StartupFontClr, C4StartupEditBGColor, C4StartupEditBorderColor);
861  pCombo->SetFont(pUseFont);
862  pCombo->SetDecoration(&(C4Startup::Get()->Graphics.fctContext));
863  pCombo->SetText(GetWindowedName());
864  pGroupResolution->AddElement(pCombo);
865  // --subgroup options
866  iNumGfxOptions = 5, iOpt=0;
867  C4GUI::GroupBox *pGroupOptions = new C4GUI::GroupBox(caSheetGraphics.GetGridCell(0,1,1,2));
868  pGroupOptions->SetTitle(LoadResStrNoAmp("IDS_DLG_OPTIONS"));
869  pGroupOptions->SetFont(pUseFont);
870  pGroupOptions->SetColors(C4StartupEditBorderColor, C4StartupFontClr);
871  pSheetGraphics->AddElement(pGroupOptions);
872  C4GUI::ComponentAligner caGroupOptions(pGroupOptions->GetClientRect(), iIndentX1, iIndentY2, true);
873  // multisampling
874  C4GUI::ComponentAligner msBox(caGroupOptions.GetFromTop(C4GUI::ComboBox::GetDefaultHeight()), 0, 0, false);
875  w=20; q=12; pUseFont->GetTextExtent(LoadResStr("IDS_CTL_ANTIALIASING"), w,q, true);
876  pGroupOptions->AddElement(new C4GUI::Label(LoadResStr("IDS_CTL_ANTIALIASING"), msBox.GetFromLeft(w+C4GUI_DefDlgSmallIndent), ALeft, C4StartupFontClr, pUseFont, false, false));
877 
878  pUseFont->GetTextExtent("Off", w, q, true);
879  C4GUI::ComboBox *pGfxMSCombo = new C4GUI::ComboBox(msBox.GetFromLeft(w+40,C4GUI::ComboBox::GetDefaultHeight()));
880  pGfxMSCombo->SetToolTip(LoadResStr("IDS_MSG_ANTIALIASING_DESC"));
881  pGfxMSCombo->SetComboCB(new C4GUI::ComboBox_FillCallback<C4StartupOptionsDlg>(this, &C4StartupOptionsDlg::OnGfxMSComboFill, &C4StartupOptionsDlg::OnGfxMSComboSelChange));
882  pGfxMSCombo->SetColors(C4StartupFontClr, C4StartupEditBGColor, C4StartupEditBorderColor);
883  pGfxMSCombo->SetFont(pUseFont);
884  pGfxMSCombo->SetDecoration(&(C4Startup::Get()->Graphics.fctContext));
885  // Pre-Select current setting
886  StdStrBuf Current;
888  else Current.Copy("Off");
889  pGfxMSCombo->SetText(Current.getData());
890  // Set control read only if multisampling is not available
891  std::vector<int> multisamples;
893  pGfxMSCombo->SetReadOnly(multisamples.empty());
894  pGroupOptions->AddElement(pGfxMSCombo);
895  // automatic gfx frame skip
896  pCheck = new BoolConfig(caGroupOptions.GetGridCell(0,1,iOpt++,iNumGfxOptions,-1,iCheckHgt,true), LoadResStr("IDS_MSG_AUTOFRAMESKIP"), nullptr, &Config.Graphics.AutoFrameSkip);
897  pCheck->SetToolTip(LoadResStr("IDS_DESC_AUTOFRAMESKIP"));
898  pCheck->SetFont(pUseFont, C4StartupFontClr, C4StartupFontClrDisabled);
899  pGroupOptions->AddElement(pCheck);
900 
901  // --- page sound
902  C4GUI::ComponentAligner caSheetSound(pSheetSound->GetClientRect(), iIndentX1, iIndentY1, true);
903  if (!C4GUI::CheckBox::GetStandardCheckBoxSize(&iCheckWdt, &iCheckHgt, "Lorem ipsum", pUseFont)) { iCheckWdt=100; iCheckHgt=20; }
904  int32_t iGridWdt = iCheckWdt * 2, iGridHgt = iCheckHgt * 5/2;
905  // --subgroup menu system sound
906  C4GUI::GroupBox *pGroupFESound = new C4GUI::GroupBox(caSheetSound.GetGridCell(0,2,0,5, iGridWdt, iGridHgt, false, 1,2));
907  pGroupFESound->SetTitle(LoadResStrNoAmp("IDS_CTL_FRONTEND"));
908  pGroupFESound->SetFont(pUseFont);
909  pGroupFESound->SetColors(C4StartupEditBorderColor, C4StartupFontClr);
910  pSheetSound->AddElement(pGroupFESound);
911  C4GUI::ComponentAligner caGroupFESound(pGroupFESound->GetClientRect(), iIndentX1, iIndentY2, true);
912  // menu system music
913  pCheck = pFEMusicCheck = new C4GUI::CheckBox(caGroupFESound.GetGridCell(0,1,0,2,-1,iCheckHgt,true), LoadResStr("IDS_CTL_MUSIC"), !!Config.Sound.FEMusic);
914  pCheck->SetToolTip(LoadResStr("IDS_DESC_MENUMUSIC"));
915  pCheck->SetFont(pUseFont, C4StartupFontClr, C4StartupFontClrDisabled);
916  pCheck->SetOnChecked(new C4GUI::CallbackHandler<C4StartupOptionsDlg>(this, &C4StartupOptionsDlg::OnFEMusicCheck));
917  pGroupFESound->AddElement(pCheck);
918  // menu system sound effects
919  pCheck = pFESoundCheck = new BoolConfig(caGroupFESound.GetGridCell(0,1,1,2,-1,iCheckHgt,true), LoadResStr("IDS_CTL_SOUNDFX"), nullptr, &Config.Sound.FESamples);
920  pCheck->SetToolTip(LoadResStr("IDS_DESC_MENUSOUND"));
921  pCheck->SetFont(pUseFont, C4StartupFontClr, C4StartupFontClrDisabled);
922  pGroupFESound->AddElement(pCheck);
923  // --subgroup game sound
924  C4GUI::GroupBox *pGroupRXSound = new C4GUI::GroupBox(caSheetSound.GetGridCell(1,2,0,5, iGridWdt, iGridHgt, false, 1,2));
925  pGroupRXSound->SetTitle(LoadResStrNoAmp("IDS_CTL_GAME"));
926  pGroupRXSound->SetFont(pUseFont);
927  pGroupRXSound->SetColors(C4StartupEditBorderColor, C4StartupFontClr);
928  pSheetSound->AddElement(pGroupRXSound);
929  C4GUI::ComponentAligner caGroupRXSound(pGroupRXSound->GetClientRect(), iIndentX1, iIndentY2, true);
930  // game music
931  pCheck = new BoolConfig(caGroupRXSound.GetGridCell(0,1,0,2,-1,iCheckHgt,true), LoadResStr("IDS_CTL_MUSIC"), nullptr, &Config.Sound.RXMusic);
932  pCheck->SetToolTip(LoadResStr("IDS_DESC_GAMEMUSIC"));
933  pCheck->SetFont(pUseFont, C4StartupFontClr, C4StartupFontClrDisabled);
934  pGroupRXSound->AddElement(pCheck);
935  // game sound effects
936  pCheck = new C4GUI::CheckBox(caGroupRXSound.GetGridCell(0,1,1,2,-1,iCheckHgt,true), LoadResStr("IDS_CTL_SOUNDFX"), !!Config.Sound.RXSound);
937  pCheck->SetToolTip(LoadResStr("IDS_DESC_GAMESOUND"));
938  pCheck->SetFont(pUseFont, C4StartupFontClr, C4StartupFontClrDisabled);
939  pCheck->SetOnChecked(new C4GUI::CallbackHandler<C4StartupOptionsDlg>(this, &C4StartupOptionsDlg::OnRXSoundCheck));
940  pGroupRXSound->AddElement(pCheck);
941  // -- subgroup volume
942  C4GUI::GroupBox *pGroupVolume = new C4GUI::GroupBox(caSheetSound.GetGridCell(0,2,2,5, iGridWdt, iGridHgt, false, 2,3));
943  pGroupVolume->SetTitle(LoadResStrNoAmp("IDS_BTN_VOLUME"));
944  pGroupVolume->SetFont(pUseFont);
945  pGroupVolume->SetColors(C4StartupEditBorderColor, C4StartupFontClr);
946  pSheetSound->AddElement(pGroupVolume);
947  C4GUI::ComponentAligner caGroupVolume(pGroupVolume->GetClientRect(), iIndentX1, iIndentY2, true);
948  // volume sliders
949  int32_t i;
950  for (i=0; i<2; ++i)
951  {
952  StdStrBuf sLabelTxt;
953  C4GUI::ComponentAligner caVolumeSlider(caGroupVolume.GetGridCell(0,1,i,2, -1, pUseFont->GetLineHeight()+iIndentY2*2+C4GUI_ScrollBarHgt, true), 1,0,false);
954  pGroupVolume->AddElement(new C4GUI::Label(FormatString("%s:", LoadResStr(i ? "IDS_CTL_SOUNDFX" : "IDS_CTL_MUSIC")).getData(), caVolumeSlider.GetFromTop(pUseFont->GetLineHeight()), ALeft, C4StartupFontClr, pUseFont, false, false));
955  sLabelTxt.Copy(LoadResStr("IDS_CTL_SILENT"));
956  w=20; q=12; pUseFont->GetTextExtent(sLabelTxt.getData(), w,q, true);
957  pGroupVolume->AddElement(new C4GUI::Label(sLabelTxt.getData(), caVolumeSlider.GetFromLeft(w,q), ACenter, C4StartupFontClr, pUseFont, false, false));
958  sLabelTxt.Copy(LoadResStr("IDS_CTL_LOUD"));
959  pUseFont->GetTextExtent(sLabelTxt.getData(), w,q, true);
960  pGroupVolume->AddElement(new C4GUI::Label(sLabelTxt.getData(), caVolumeSlider.GetFromRight(w,q), ACenter, C4StartupFontClr, pUseFont, false, false));
961  auto *pCB = new C4GUI::ParCallbackHandler<C4StartupOptionsDlg, int32_t>(this, i ? &C4StartupOptionsDlg::OnSoundVolumeSliderChange : &C4StartupOptionsDlg::OnMusicVolumeSliderChange);
962  auto *pSlider = new C4GUI::ScrollBar(caVolumeSlider.GetCentered(caVolumeSlider.GetInnerWidth(), C4GUI_ScrollBarHgt), true, pCB, 101);
963  pSlider->SetDecoration(&C4Startup::Get()->Graphics.sfctBookScroll, false);
964  pSlider->SetToolTip(i ? LoadResStr("IDS_DESC_VOLUMESOUND") : LoadResStr("IDS_DESC_VOLUMEMUSIC"));
965  pSlider->SetScrollPos(i ? Config.Sound.SoundVolume : Config.Sound.MusicVolume);
966  pGroupVolume->AddElement(pSlider);
967  }
968 
969  // --- page controls
970  pSheetControls->AddElement(pControlConfigArea = new ControlConfigArea(pSheetControls->GetClientRect(), caMain.GetWidth()/20, caMain.GetHeight()/40, false, this));
971 
972  // --- page network
973  int iPortCfgWdt=200, iPortCfgHgt=48; NetworkPortConfig::GetControlSize(&iPortCfgWdt, &iPortCfgHgt);
974  int iServerCfgWdt = 120, iServerCfgHgt = 20, iServerCfgWdtMid = 0;
975  StdStrBuf sServerText; sServerText.Copy(LoadResStr("IDS_CTL_USEOTHERSERVER"));
976  NetworkServerAddressConfig::GetControlSize(&iServerCfgWdt, &iServerCfgHgt, &iServerCfgWdtMid, sServerText.getData());
977  int32_t net_component_hgt = iPortCfgHgt * 4 + iServerCfgHgt + 3 * pUseFont->GetLineHeight();
978  C4GUI::ComponentAligner caSheetNetwork(pSheetNetwork->GetClientRect(), caMain.GetWidth() / 20, std::max<int32_t>(0, (caMain.GetHeight() - net_component_hgt)/20), true);
979  pPortCfgTCP = new NetworkPortConfig(caSheetNetwork.GetGridCell(0,2,0,2, iPortCfgWdt, iPortCfgHgt), LoadResStr("IDS_NET_PORT_TCP"), &(Config.Network.PortTCP), C4NetStdPortTCP);
980  pPortCfgUDP = new NetworkPortConfig(caSheetNetwork.GetGridCell(1,2,0,2, iPortCfgWdt, iPortCfgHgt), LoadResStr("IDS_NET_PORT_UDP"), &(Config.Network.PortUDP), C4NetStdPortUDP);
981  pPortCfgRef = new NetworkPortConfig(caSheetNetwork.GetGridCell(0,2,1,2, iPortCfgWdt, iPortCfgHgt), LoadResStr("IDS_NET_PORT_REFERENCE"), &(Config.Network.PortRefServer), C4NetStdPortRefServer);
982  pPortCfgDsc = new NetworkPortConfig(caSheetNetwork.GetGridCell(1,2,1,2, iPortCfgWdt, iPortCfgHgt), LoadResStr("IDS_NET_PORT_DISCOVERY"), &(Config.Network.PortDiscovery), C4NetStdPortDiscovery);
983  pPortCfgTCP->SetToolTip(LoadResStr("IDS_NET_PORT_TCP_DESC"));
984  pPortCfgUDP->SetToolTip(LoadResStr("IDS_NET_PORT_UDP_DESC"));
985  pPortCfgRef->SetToolTip(LoadResStr("IDS_NET_PORT_REFERENCE_DESC"));
986  pPortCfgDsc->SetToolTip(LoadResStr("IDS_NET_PORT_DISCOVERY_DESC"));
987  pSheetNetwork->AddElement(pPortCfgTCP);
988  pSheetNetwork->AddElement(pPortCfgUDP);
989  pSheetNetwork->AddElement(pPortCfgRef);
990  pSheetNetwork->AddElement(pPortCfgDsc);
991  int iNetHgt0=pPortCfgDsc->GetBounds().GetBottom();
992  caSheetNetwork.ExpandTop(-iNetHgt0);
993  pLeagueServerCfg = new NetworkServerAddressConfig(caSheetNetwork.GetFromTop(iServerCfgHgt), sServerText.getData(), &(Config.Network.UseAlternateServer), Config.Network.AlternateServerAddress, iServerCfgWdtMid);
994  pLeagueServerCfg->SetToolTip(LoadResStr("IDS_NET_MASTERSRV_DESC"));
995  pSheetNetwork->AddElement(pLeagueServerCfg);
996 #ifdef WITH_AUTOMATIC_UPDATE
997  pCheck = new BoolConfig(caSheetNetwork.GetFromTop(pUseFont->GetLineHeight()), LoadResStr("IDS_CTL_AUTOMATICUPDATES"), nullptr, &Config.Network.AutomaticUpdate, false);
998  pCheck->SetToolTip(LoadResStr("IDS_DESC_AUTOMATICUPDATES"));
999  pCheck->SetFont(pUseFont, C4StartupFontClr, C4StartupFontClrDisabled);
1000  pSheetNetwork->AddElement(pCheck);
1001 #endif
1002  pCheck = new BoolConfig(caSheetNetwork.GetFromTop(pUseFont->GetLineHeight()), LoadResStr("IDS_CTL_UPNP"), nullptr, &Config.Network.EnableUPnP, false);
1003  pCheck->SetToolTip(LoadResStr("IDS_DESC_UPNP"));
1004  pCheck->SetFont(pUseFont, C4StartupFontClr, C4StartupFontClrDisabled);
1005  pSheetNetwork->AddElement(pCheck);
1006  pCheck = new BoolConfig(caSheetNetwork.GetFromTop(pUseFont->GetLineHeight()), LoadResStr("IDS_CTL_PACKETLOGGING"), nullptr, &Config.Network.PacketLogging, false);
1007  pCheck->SetToolTip(LoadResStr("IDS_DESC_PACKETLOGGING"));
1008  pCheck->SetFont(pUseFont, C4StartupFontClr, C4StartupFontClrDisabled);
1009  pSheetNetwork->AddElement(pCheck);
1010  const char *szNameCfgText = LoadResStr("IDS_NET_USERNAME");
1011  int iNameCfgWdt=200, iNameCfgHgt=48; C4StartupOptionsDlg::EditConfig::GetControlSize(&iNameCfgWdt, &iNameCfgHgt, szNameCfgText, false);
1012  iNameCfgWdt += 5;
1013  pNetworkNickEdit = new EditConfig(caSheetNetwork.GetFromTop(iNameCfgHgt), szNameCfgText, &Config.Network.Nick, nullptr, false);
1014  pNetworkNickEdit->SetToolTip(LoadResStr("IDS_NET_USERNAME_DESC"));
1015  pSheetNetwork->AddElement(pNetworkNickEdit);
1016 
1017  StdCopyStrBuf NickBuf(Config.Network.Nick);
1018  if (!NickBuf.getLength()) NickBuf.Copy(Config.GetRegistrationData("Nick"));
1019  pNetworkNickEdit->GetEdit()->SetText(NickBuf.getData(), false);
1020 
1021  // initial focus is on tab selection
1022  SetFocus(pOptionsTabular, false);
1023 }
1024 
1026 {
1027  delete pKeyToggleMusic;
1028  delete pKeyBack;
1029 }
1030 
1032 {
1033  // callback when dlg got closed - save config
1034  SaveConfig(true, false);
1036 }
1037 
1038 void C4StartupOptionsDlg::OnResetConfigBtn(C4GUI::Control *btn)
1039 {
1040  // confirmation
1041  StdStrBuf sWarningText; sWarningText.Copy(LoadResStr("IDS_MSG_PROMPTRESETCONFIG"));
1042  sWarningText.AppendChar('|');
1043  sWarningText.Append(LoadResStr("IDS_MSG_RESTARTCHANGECFG"));
1044  if (!GetScreen()->ShowMessageModal(sWarningText.getData(), LoadResStr("IDS_BTN_RESETCONFIG"), C4GUI::MessageDialog::btnYesNo, C4GUI::Ico_Notify))
1045  // user cancelled
1046  return;
1047  // reset cfg
1048  Config.Default();
1049  Config.fConfigLoaded = true;
1050  // engine must be restarted now, because some crucial fields such as resolution and used gfx engine do not match their initialization
1051  Application.Quit();
1052 }
1053 
1054 void C4StartupOptionsDlg::OnGfxMSComboFill(C4GUI::ComboBox_FillCB *pFiller)
1055 {
1056  // clear all old entries first to allow a clean refill
1057  pFiller->ClearEntries();
1058 
1059  pFiller->AddEntry("Off", 0);
1060 
1061  std::vector<int> multisamples;
1062  Application.pWindow->EnumerateMultiSamples(multisamples);
1063 
1064  std::sort(multisamples.begin(), multisamples.end());
1065  for(int multisample : multisamples)
1066  {
1067  StdStrBuf text;
1068  text.Format("%dx", multisample);
1069  pFiller->AddEntry(text.getData(), multisample);
1070  }
1071 }
1072 
1073 bool C4StartupOptionsDlg::OnGfxMSComboSelChange(C4GUI::ComboBox *pForCombo, int32_t idNewSelection)
1074 {
1075  if(pTexMgr) pTexMgr->IntLock();
1076 #ifndef USE_CONSOLE
1078  // Note: This assumes there is only one GL context (the main context). This
1079  // is true in fullscreen mode, and since the startup dlg is only shown in
1080  // fullscreen mode we are safe this way.
1081  if(pGL) pGL->pMainCtx->Clear(true);
1082 #endif
1083  int32_t PrevMultiSampling = Config.Graphics.MultiSampling;
1084  Config.Graphics.MultiSampling = idNewSelection;
1085  bool success = Application.pWindow->ReInit(&Application);
1086 
1087 #ifndef USE_CONSOLE
1091 #endif
1092  if(pTexMgr) pTexMgr->IntUnlock();
1093  if(!success) Config.Graphics.MultiSampling = PrevMultiSampling;
1094  return !success;
1095 }
1096 
1097 void C4StartupOptionsDlg::OnGfxResComboFill(C4GUI::ComboBox_FillCB *pFiller)
1098 {
1099  // clear all old entries first to allow a clean refill
1100  pFiller->ClearEntries();
1101  pFiller->AddEntry(LoadResStr("IDS_MNU_DEFAULTRESOLUTION"), -1);
1102  // fill with all possible resolutions
1103  int32_t idx = 0, iXRes, iYRes, iBitDepth, iRefreshRate;
1104  while (Application.GetIndexedDisplayMode(idx++, &iXRes, &iYRes, &iBitDepth, &iRefreshRate, Config.Graphics.Monitor))
1105 #ifdef _WIN32 // why only WIN32?
1106  if (iBitDepth == C4Draw::COLOR_DEPTH)
1107 #endif
1108  {
1109  StdStrBuf sGfxString = GetGfxResString(iXRes, iYRes);
1110  if (!pFiller->FindEntry(sGfxString.getData()))
1111  pFiller->AddEntry(sGfxString.getData(), iXRes + (uint32_t(iYRes) << 12) + (uint32_t(iRefreshRate) << 24));
1112  }
1113 }
1114 
1115 bool C4StartupOptionsDlg::OnGfxResComboSelChange(C4GUI::ComboBox *pForCombo, int32_t idNewSelection)
1116 {
1117  // get new resolution from string
1118  int iResX=(idNewSelection & 0xfff), iResY=(uint32_t(idNewSelection) >> 12) & 0xfff, iRefreshRate = (uint32_t(idNewSelection) >> 24) & 0xff;
1119  if (idNewSelection == -1)
1120  {
1121  iResX = iResY = -1;
1122  iRefreshRate = 0;
1123  }
1124 
1125  // different than current?
1126  if (iResX == Config.Graphics.ResX && iResY == Config.Graphics.ResY && iRefreshRate == Config.Graphics.RefreshRate) return true;
1127 
1128  // try setting it
1129  if (!TryNewResolution(iResX, iResY, iRefreshRate))
1130  {
1131  // didn't work or declined by user
1132  return true; // do not change label, because dialog might hae been recreated!
1133  }
1134  // dialog has been recreated; so do not change the combo label
1135  return true;
1136 }
1137 
1138 bool C4StartupOptionsDlg::TryNewResolution(int32_t iResX, int32_t iResY, int32_t iRefreshRate)
1139 {
1140  int32_t iOldResX = Config.Graphics.ResX, iOldResY = Config.Graphics.ResY;
1141  int32_t iOldRefreshRate = Config.Graphics.RefreshRate;
1142  int32_t iOldFontSize = Config.General.RXFontSize;
1143  C4GUI::Screen *pScreen = GetScreen();
1144  // resolution change may imply font size change
1145  int32_t iNewFontSize = 14; // default (at 800x600)
1146  if (iResY >= 0 && iResY < 600)
1147  iNewFontSize = 12;
1148  else if (iResY > 800)
1149  iNewFontSize = 16;
1150  // call application to set it
1151  if (!Application.SetVideoMode(iResX, iResY, iRefreshRate, Config.Graphics.Monitor, !Config.Graphics.Windowed))
1152  {
1153  StdCopyStrBuf strChRes(LoadResStr("IDS_MNU_SWITCHRESOLUTION"));
1154  pScreen->ShowMessage(FormatString(LoadResStr("IDS_ERR_SWITCHRES"), Application.GetLastError()).getData(), strChRes.getData(), C4GUI::Ico_Clonk, nullptr);
1155  return false;
1156  }
1157  // implied font change
1158  if (iNewFontSize != iOldFontSize)
1159  if (!Application.SetGameFont(Config.General.RXFontName, iNewFontSize))
1160  {
1161  // not changing font size is not fatal - just keep old size
1162  iNewFontSize = iOldFontSize;
1163  }
1164  // Set new resolution in config before dialog recreation so that the initial combo box value is correct (#230)
1165  Config.Graphics.ResX = iResX;
1166  Config.Graphics.ResY = iResY;
1167  Config.Graphics.RefreshRate = iRefreshRate;
1168  // since the resolution was changed, everything needs to be moved around a bit
1169  RecreateDialog(false);
1170  // Now set old resolution again to make sure config is restored even if the program is closed during the confirmation dialog
1171  Config.Graphics.ResX = iOldResX;
1172  Config.Graphics.ResY = iOldResY;
1173  Config.Graphics.RefreshRate = iOldRefreshRate;
1174  // Show confirmation dialog
1175  ResChangeConfirmDlg *pConfirmDlg = new ResChangeConfirmDlg();
1176  if (!pScreen->ShowModalDlg(pConfirmDlg, true))
1177  {
1178  // abort: Restore screen, if this was not some program abort
1179  if (Application.SetVideoMode(iOldResX, iOldResY, iOldRefreshRate, Config.Graphics.Monitor, !Config.Graphics.Windowed))
1180  {
1181  if (iNewFontSize != iOldFontSize) Application.SetGameFont(Config.General.RXFontName, iOldFontSize);
1182  RecreateDialog(false);
1183  }
1184 
1185  return false;
1186  }
1187  // resolution may be kept!
1188  Config.Graphics.ResX = iResX;
1189  Config.Graphics.ResY = iResY;
1190  Config.Graphics.RefreshRate = iRefreshRate;
1193  return true;
1194 }
1195 
1196 StdStrBuf C4StartupOptionsDlg::GetGfxResString(int32_t iResX, int32_t iResY)
1197 {
1198  // Display in format like "640 x 480"
1199  if (iResX == -1)
1200  return StdStrBuf(LoadResStr("IDS_MNU_DEFAULTRESOLUTION"));
1201  return FormatString("%d x %d", (int)iResX, (int)iResY);
1202 }
1203 
1204 const char * C4StartupOptionsDlg::GetWindowedName(int32_t mode /* = -1*/)
1205 {
1206  if(mode == -1)
1207  mode = Config.Graphics.Windowed;
1208  if(mode == 0) return LoadResStr("IDS_MSG_FULLSCREEN");
1209  else if(mode == 1) return LoadResStr("IDS_MSG_WINDOWED");
1210  else if(mode == 2) return LoadResStr("IDS_MSG_AUTOWINDOWED");
1211  assert(!"Requested name for config value which does not exist");
1212  return "ERR: Unknown";
1213 }
1214 
1215 void C4StartupOptionsDlg::OnWindowedModeComboFill(C4GUI::ComboBox_FillCB *pFiller)
1216 {
1217  pFiller->ClearEntries();
1218  for(int32_t i = 0; i < 3; ++i)
1219  pFiller->AddEntry(GetWindowedName(i), i);
1220 }
1221 
1222 bool C4StartupOptionsDlg::OnWindowedModeComboSelChange(C4GUI::ComboBox *pForCombo, int32_t idNewSelection)
1223 {
1224  Config.Graphics.Windowed = idNewSelection;
1226  pForCombo->SetText(GetWindowedName(idNewSelection));
1227  return true;
1228 }
1229 
1230 bool C4StartupOptionsDlg::SaveConfig(bool fForce, bool fKeepOpen)
1231 {
1232  // prevent double save
1233  if (fConfigSaved) return true;
1234  // save any config fields that are not stored directly; return whether all values are OK
1235  // check port validity
1236  if (!fForce)
1237  {
1238  StdCopyStrBuf strError(LoadResStr("IDS_ERR_CONFIG"));
1239  if (pPortCfgTCP->GetPort()>0 && pPortCfgTCP->GetPort() == pPortCfgRef->GetPort())
1240  {
1241  GetScreen()->ShowMessage(LoadResStr("IDS_NET_ERR_PORT_TCPREF"), strError.getData(), C4GUI::Ico_Error);
1242  return false;
1243  }
1244  if (pPortCfgUDP->GetPort()>0 && pPortCfgUDP->GetPort() == pPortCfgDsc->GetPort())
1245  {
1246  GetScreen()->ShowMessage(LoadResStr("IDS_NET_ERR_PORT_UDPDISC"), strError.getData(), C4GUI::Ico_Error);
1247  return false;
1248  }
1249  }
1250  // store some config values
1251  pPortCfgTCP->SavePort();
1252  pPortCfgUDP->SavePort();
1253  pPortCfgRef->SavePort();
1254  pPortCfgDsc->SavePort();
1255  pLeagueServerCfg->Save2Config();
1256  pNetworkNickEdit->Save2Config();
1257  // if nick is same as default by registry, don't save in config
1258  // so regkey updates will change the nick as well
1259  const char *szRegNick = Config.GetRegistrationData("Nick");
1260  if (SEqual(Config.Network.Nick.getData(), szRegNick)) Config.Network.Nick.Clear();
1261  // make sure config is saved, in case the game crashes later on or another instance is started
1262  Config.Save();
1263  if (!fKeepOpen) fConfigSaved = true;
1264  // done; config OK
1265  return true;
1266 }
1267 
1269 {
1270  if (!SaveConfig(false, false)) return;
1271  // back 2 main
1273 }
1274 
1275 bool C4StartupOptionsDlg::SetSubscreen(const char *szToScreen)
1276 {
1277  // go to specified property sheet
1278  // option sheets do not have a good identifier associated to them - just lookup from a static array
1279  const char *page_names[] = { "general", "graphics", "sound", "controls", "network", nullptr };
1280  int32_t i = 0;
1281  while (page_names[i])
1282  {
1283  if (SEqualNoCase(szToScreen, page_names[i])) break;
1284  ++i;
1285  }
1286  // page name does not match?
1287  if (!page_names[i]) return false;
1288  // page name OK; switch it
1289  pOptionsTabular->SelectSheet(i, false);
1290  return true;
1291 }
1292 
1293 void C4StartupOptionsDlg::UpdateLanguage()
1294 {
1295  // find currently specified language in language list and display its info
1297  if (pNfo)
1298  {
1299  pLangCombo->SetText(FormatString("%s - %s", pNfo->Code, pNfo->Name).getData());
1300  pLangInfoLabel->SetText(pNfo->Info);
1301  }
1302  else
1303  {
1304  pLangCombo->SetText(FormatString("unknown (%s)", Config.General.Language).getData());
1305  pLangInfoLabel->SetText(LoadResStr("IDS_CTL_NOLANGINFO"));
1306  return; // no need to mess with fallbacks
1307  }
1308  // update language fallbacks
1309  char *szLang = Config.General.LanguageEx;
1310  SCopy(pNfo->Code, szLang);
1311  if (*(pNfo->Fallback))
1312  {
1313  SAppend(",", szLang);
1314  Config.General.GetLanguageSequence(pNfo->Fallback, szLang + SLen(szLang));
1315  }
1316  // internal fallbacks
1317  if (!SSearch(Config.General.LanguageEx, "US"))
1318  {
1319  if (*szLang) SAppendChar(',', szLang);
1320  SAppend("US", szLang);
1321  }
1322  if (!SSearch(Config.General.LanguageEx, "DE"))
1323  {
1324  if (*szLang) SAppendChar(',', szLang);
1325  SAppend("DE", szLang);
1326  }
1327 }
1328 
1329 void C4StartupOptionsDlg::OnLangComboFill(C4GUI::ComboBox_FillCB *pFiller)
1330 {
1331  // fill with all possible languages
1332  C4LanguageInfo *pNfo;
1333  for (int i=0; i<Languages.GetInfoCount(); ++i)
1334  if ((pNfo = Languages.GetInfo(i)))
1335  pFiller->AddEntry(FormatString("%s - %s", pNfo->Code, pNfo->Name).getData(), (unsigned char)(pNfo->Code[0]) + ((unsigned char)(pNfo->Code[1])<<8));
1336 }
1337 
1338 bool C4StartupOptionsDlg::OnLangComboSelChange(C4GUI::ComboBox *pForCombo, int32_t idNewSelection)
1339 {
1340  // set new language by two-character-code
1341  Config.General.Language[0] = idNewSelection & 0xff;
1342  Config.General.Language[1] = (idNewSelection & 0xff00) >> 8;
1343  Config.General.Language[2] = '\0';
1344  UpdateLanguage();
1346  Game.UpdateLanguage();
1347  // recreate everything to reflect language changes
1348  RecreateDialog(true);
1349  return true;
1350 }
1351 
1352 void C4StartupOptionsDlg::UpdateFontControls()
1353 {
1354  // display current language and size in comboboxes
1355  pFontFaceCombo->SetText(Config.General.RXFontName);
1356  StdStrBuf sSize; sSize.Format("%d", (int) Config.General.RXFontSize);
1357  pFontSizeCombo->SetText(sSize.getData());
1358 }
1359 
1360 #ifdef _WIN32
1361 const char *DefaultFonts[] = { "Arial Unicode MS", "Comic Sans MS", C4DEFAULT_FONT_NAME, "Verdana", nullptr };
1362 #else
1363 const char *DefaultFonts[] = { C4DEFAULT_FONT_NAME, nullptr };
1364 #endif
1365 
1366 void C4StartupOptionsDlg::OnFontFaceComboFill(C4GUI::ComboBox_FillCB *pFiller)
1367 {
1368  // 2do: enumerate Fonts.txt fonts; then enumerate system fonts
1369  for (int32_t i=0; DefaultFonts[i]; ++i) pFiller->AddEntry(DefaultFonts[i], i);
1370 }
1371 
1372 void C4StartupOptionsDlg::OnFontSizeComboFill(C4GUI::ComboBox_FillCB *pFiller)
1373 {
1374  // 2do: enumerate possible font sizes by the font here
1375  // 2do: Hide font sizes that would be too large for the selected resolution
1376  pFiller->AddEntry("10", 10);
1377  pFiller->AddEntry("12", 12);
1378  pFiller->AddEntry("14", 14);
1379  pFiller->AddEntry("16", 16);
1380  pFiller->AddEntry("18", 18);
1381  pFiller->AddEntry("20", 20);
1382  pFiller->AddEntry("22", 22);
1383  pFiller->AddEntry("24", 24);
1384  pFiller->AddEntry("26", 26);
1385  pFiller->AddEntry("28", 28);
1386 }
1387 
1388 bool C4StartupOptionsDlg::OnFontComboSelChange(C4GUI::ComboBox *pForCombo, int32_t idNewSelection)
1389 {
1390  // set new value
1391  const char *szNewFontFace = Config.General.RXFontName;
1392  int32_t iNewFontSize = Config.General.RXFontSize;
1393  if (pForCombo == pFontFaceCombo)
1394  szNewFontFace = DefaultFonts[idNewSelection];
1395  else if (pForCombo == pFontSizeCombo)
1396  iNewFontSize = idNewSelection;
1397  else
1398  // can't happen
1399  return true;
1400  // set new fonts
1401  if (!Application.SetGameFont(szNewFontFace, iNewFontSize))
1402  {
1403  GetScreen()->ShowErrorMessage(LoadResStr("IDS_ERR_INITFONTS"));
1404  return true;
1405  }
1406  // recreate everything to reflect font changes
1407  RecreateDialog(true);
1408  return true;
1409 }
1410 
1412 {
1413  // MUST fade for now, or calling function will fail because dialog is deleted immediately
1414  fFade = true;
1415  // this actually breaks the possibility to go back :(
1416  int32_t iPage = pOptionsTabular->GetActiveSheetIndex();
1418  pNewDlg->pOptionsTabular->SelectSheet(iPage, false);
1419  pNewDlg->fCanGoBack = false;
1420 }
1421 
1422 void C4StartupOptionsDlg::OnFEMusicCheck(C4GUI::Element *pCheckBox)
1423 {
1424  // option change is reflected immediately
1425  bool fIsOn = static_cast<C4GUI::CheckBox *>(pCheckBox)->GetChecked();
1426  if ((Config.Sound.FEMusic = fIsOn))
1428  else
1430 }
1431 
1432 void C4StartupOptionsDlg::OnMusicVolumeSliderChange(int32_t iNewVal)
1433 {
1434  // option change is reflected immediately;
1435  Config.Sound.MusicVolume = iNewVal;
1437 }
1438 
1439 void C4StartupOptionsDlg::OnSoundVolumeSliderChange(int32_t iNewVal)
1440 {
1441  // sound system reads this value directly
1442  Config.Sound.SoundVolume = iNewVal;
1443  // test sound
1444  StartSoundEffect("Objects::Arrow::HitGround", false, 100, nullptr);
1445 }
1446 
1447 void C4StartupOptionsDlg::OnRXSoundCheck(C4GUI::Element *pCheckBox)
1448 {
1449  // toggling sounds on off must init/deinit sound system
1450  bool fIsOn = static_cast<C4GUI::CheckBox *>(pCheckBox)->GetChecked();
1451  if (fIsOn == !!Config.Sound.RXSound) return;
1452  if (fIsOn)
1453  {
1454  Config.Sound.RXSound = true;
1455  if (!Application.SoundSystem.Init())
1456  {
1457  GetScreen()->ShowMessage(StdCopyStrBuf(LoadResStr("IDS_PRC_NOSND")).getData(), StdCopyStrBuf(LoadResStr("IDS_DLG_LOG")).getData(), C4GUI::Ico_Error);
1459  Config.Sound.RXSound = false;
1460  static_cast<C4GUI::CheckBox *>(pCheckBox)->SetChecked(false);
1461  fIsOn = false;
1462  }
1463  }
1464  else
1465  {
1467  Config.Sound.RXSound = false;
1468  }
1469  // FE sound only enabled if global sound is enabled
1470  pFESoundCheck->SetEnabled(fIsOn);
1471  pFESoundCheck->SetChecked(fIsOn ? !!Config.Sound.FESamples : false);
1472 }
1473 
1475 {
1476  // do toggle
1478  // reflect in checkbox
1479  pFEMusicCheck->SetChecked(!!Config.Sound.FEMusic);
1480  // key processed
1481  return true;
1482 }
1483 
1485 {
1486  // keyboard layout changed and thus some keys might have been updated from scan codes
1487  // update display in control set
1488  pControlConfigArea->UpdateCtrlSet();
1489 }
C4SoundSystem SoundSystem
Definition: C4Application.h:42
int32_t RefreshRate
Definition: C4Config.h:105
void Default()
Definition: C4Config.cpp:283
static C4KeyCodeEx FromC4MC(int8_t mouse_id, int32_t button, DWORD param, bool *is_down=nullptr)
#define C4GUI_CaptionFontClr
Definition: C4Gui.h:37
#define C4GUI_ButtonAreaHgt
Definition: C4Gui.h:113
int32_t MultiSampling
Definition: C4Config.h:115
C4Config Config
Definition: C4Config.cpp:833
const int32_t C4MC_Button_LeftDown
C4ConfigStartup Startup
Definition: C4Config.h:260
void SetComboCB(ComboBox_FillCB *pNewFillCallback)
#define C4GUI_MessageDlgWdt
Definition: C4Gui.h:127
#define C4GUI_ButtonHgt
Definition: C4Gui.h:111
void SetClientSize(int32_t iToWdt, int32_t iToHgt)
void SCopy(const char *szSource, char *sTarget, size_t iMaxL)
Definition: Standard.cpp:152
void GetAll(C4Rect &rcOut)
Definition: C4Gui.cpp:1125
const char * GetGUIName() const
void SAppendChar(char cChar, char *szStr)
Definition: Standard.cpp:265
int32_t PortDiscovery
Definition: C4Config.h:153
const int32_t C4StartupBtnFontClr
Definition: C4Startup.h:31
bool SetSubscreen(const char *szToScreen) override
C4PlayerControlAssignmentSet * GetSetByName(const char *szName)
virtual bool RestoreDeviceObjects()=0
#define C4GUI_MessageFontClr
Definition: C4Gui.h:43
const int16_t C4NetStdPortUDP
Definition: C4Network2.h:30
void SAppend(const char *szSource, char *szTarget, int iMaxL)
Definition: Standard.cpp:257
static int GetLanguageSequence(const char *strSource, char *strTarget)
Definition: C4Config.cpp:724
C4Game Game
Definition: C4Globals.cpp:52
void OnClosed(bool fOK) override
void Clear()
Definition: StdBuf.h:466
void IntLock()
Definition: C4Surface.cpp:840
C4ConfigGeneral General
Definition: C4Config.h:251
void ResetBlitMode()
Definition: C4Draw.h:192
static constexpr int COLOR_DEPTH
Definition: C4Draw.h:89
int32_t FEMusic
Definition: C4Config.h:128
int32_t PacketLogging
Definition: C4Config.h:168
const char * SSearch(const char *szString, const char *szIndex)
Definition: Standard.cpp:363
void SetToolTip(const char *szNewTooltip, bool is_immediate=false)
Definition: C4Gui.cpp:409
void SetFont(CStdFont *pToFont)
Definition: C4Gui.h:2017
#define C4GUI_DefDlgSmallIndent
Definition: C4Gui.h:133
CStdGLCtx * pMainCtx
Definition: C4DrawGL.h:179
int32_t RXSound
Definition: C4Config.h:126
int32_t Windowed
Definition: C4Config.h:106
int32_t PortRefServer
Definition: C4Config.h:153
bool TextOut(const char *szText, CStdFont &rFont, float fZoom, C4Surface *sfcDest, float iTx, float iTy, DWORD dwFCol=0xffffffff, BYTE byForm=ALeft, bool fDoMarkup=true)
Definition: C4Draw.cpp:567
#define C4GFXBLIT_ADDITIVE
Definition: C4Surface.h:26
void MouseInput(CMouse &rMouse, int32_t iButton, int32_t iX, int32_t iY, DWORD dwKeyParam) override
bool SEqualNoCase(const char *szStr1, const char *szStr2, int iLen)
Definition: Standard.cpp:207
bool SetVideoMode(int iXRes, int iYRes, unsigned int iRefreshRate, unsigned int iMonitor, bool fFullScreen)
Definition: C4AppSDL.cpp:354
#define C4GUI_DefButton2HSpace
Definition: C4Gui.h:116
void Close(bool fOK)
const char * GetGUIDesc(const C4PlayerControlDefs &defs) const
friend class ListBox
Definition: C4Gui.h:472
void OnBackBtn(C4GUI::Control *btn)
Element * pLast
Definition: C4Gui.h:750
Definition: C4Rect.h:27
bool GetTextExtent(const char *szText, int32_t &rsx, int32_t &rsy, bool fCheckMarkup=true)
void Format(const char *szFmt,...) GNUC_FORMAT_ATTRIBUTE_O
Definition: StdBuf.cpp:174
virtual void EnumerateMultiSamples(std::vector< int > &samples) const
Definition: C4AppT.cpp:105
char Name[C4MaxLanguageInfo+1]
Definition: C4Language.h:33
void AddElement(Element *pChild)
const int32_t C4StartupEditBorderColor
Definition: C4Startup.h:30
int32_t HideMsgMMTimerChange
Definition: C4Config.h:183
const int32_t C4StartupFontClrDisabled
Definition: C4Startup.h:28
C4Rect rcClientRect
Definition: C4Gui.h:851
int32_t SoundVolume
Definition: C4Config.h:132
const int32_t C4StartupBtnBorderColor2
Definition: C4Startup.h:33
size_t SLen(const char *sptr)
Definition: Standard.h:74
C4GraphicsResource GraphicsResource
void SelectSheet(int32_t iIndex, bool fByUser)
bool SEqual(const char *szStr1, const char *szStr2)
Definition: Standard.h:93
void SetFont(CStdFont *pFont, uint32_t dwEnabledClr, uint32_t dwDisabledClr)
Definition: C4Gui.h:1483
const int32_t C4StartupFontClr
Definition: C4Startup.h:27
void Add(StdSchedulerProc *pProc)
#define C4GUI_DefButton2Wdt
Definition: C4Gui.h:115
void SetBlitMode(DWORD dwBlitMode)
Definition: C4Draw.h:191
const char * GetGUIName(const C4PlayerControlDefs &defs) const
C4PlayerControlAssignment * GetAssignmentByControlName(const char *szControlName)
bool fOK
Definition: C4Gui.h:2082
ValidatedStdCopyStrBuf< C4InVal::VAL_NameAllowEmpty > Nick
Definition: C4Config.h:156
const char * LoadResStr(const char *id)
Definition: C4Language.h:83
const char * GetRegistrationData(const char *strField)
Definition: C4Config.h:281
virtual bool ReInit(C4AbstractApp *pApp)
Definition: C4AppT.cpp:110
void SetReadOnly(bool fToVal)
Definition: C4Gui.h:2014
void AppendChar(char cChar)
Definition: StdBuf.h:588
char Code[2+1]
Definition: C4Language.h:32
static bool GetControlSize(int *piWdt, int *piHgt, const char *szForText, CStdFont *pForFont, bool fMultiline)
Definition: C4GuiEdit.cpp:812
C4SoundInstance * StartSoundEffect(const char *szSndName, bool fLoop, int32_t iVolume, C4Object *pObj, int32_t iCustomFalloffDistance, int32_t iPitch, C4SoundModifier *modifier)
C4ConfigGraphics Graphics
Definition: C4Config.h:253
int32_t Wdt
Definition: C4Rect.h:30
C4PlayerControlAssignmentSet * GetSetByIndex(int32_t index)
std::vector< C4KeyCodeEx > CodeList
void OnKeyboardLayoutChanged() override
C4GUIScreen * pGUI
Definition: C4Gui.cpp:1191
#define C4DEFAULT_FONT_NAME
Definition: C4Config.h:27
const int16_t C4NetStdPortTCP
Definition: C4Network2.h:29
C4TexMgr * pTexMgr
Definition: C4Surface.cpp:880
CStdFont BookSmallFont
Definition: C4Startup.h:77
bool GetFromTop(int32_t iHgt, int32_t iWdt, C4Rect &rcOut)
Definition: C4Gui.cpp:1059
const int16_t C4NetStdPortRefServer
Definition: C4Network2.h:32
const char * LoadResStrNoAmp(const char *id)
Definition: StdResStr2.cpp:23
int32_t y
Definition: C4Rect.h:30
const int16_t C4NetStdPortDiscovery
Definition: C4Network2.h:31
#define C4GUI_IconWdt
Definition: C4Gui.h:93
const int ACenter
Definition: C4Surface.h:41
StdStrBuf ToString(bool fHumanReadable, bool fShort) const
C4FacetID fctOptionsIcons
Definition: C4Startup.h:83
Element * GetPrev() const
Definition: C4Gui.h:450
void SetChecked(bool fToVal)
Definition: C4Gui.h:1476
C4Language Languages
Definition: C4Language.cpp:42
void SetTitle(const char *szToTitle)
Definition: C4Gui.h:1018
bool ShowErrorMessage(const char *szMessage)
void SetGfx(C4Facet *pafctBack, C4Facet *pafctClip, C4Facet *pafctIcons, CStdFont *paSheetCaptionFont, bool fResizeByAspect)
void UpdateLanguage()
Definition: C4Game.cpp:3027
C4Rect rcBounds
Definition: C4Gui.h:385
void DrawQuadDw(C4Surface *sfcTarget, float *ipVtx, DWORD dwClr1, DWORD dwClr2, DWORD dwClr3, DWORD dwClr4, C4ShaderCall *shader_call)
Definition: C4Draw.cpp:659
void Take(char *pnData)
Definition: StdBuf.h:457
void Append(const char *pnData, size_t iChars)
Definition: StdBuf.h:519
bool SetGameFont(const char *szFontFace, int32_t iFontSize)
bool Key_IsMouse(C4KeyCode key)
C4Rect & GetClientRect() override
Definition: C4Gui.h:864
void SetDecoration(C4Facet *pFctSideArrow)
Definition: C4Gui.h:2020
#define C4GUI_IconHgt
Definition: C4Gui.h:94
char Fallback[C4MaxLanguageInfo+1]
Definition: C4Language.h:35
#define C4GUI_InactCaptionFontClr
Definition: C4Gui.h:39
C4ConfigNetwork Network
Definition: C4Config.h:255
char AlternateServerAddress[CFG_MaxString+1]
Definition: C4Config.h:159
static int32_t GetDefaultHeight()
class C4StartupDlg * SwitchDialog(DialogID eToDlg, bool fFade=true, const char *szSubDialog=nullptr)
Definition: C4Startup.cpp:137
C4LanguageInfo * GetInfo(int iIndex)
Definition: C4Language.cpp:343
bool Key_IsGamepad(C4KeyCode key)
C4Draw * pDraw
Definition: C4Draw.cpp:42
int32_t HideMsgNoOfficialLeague
Definition: C4Config.h:187
void UpdateSize() override
void SetColors(uint32_t dwFontClr, uint32_t dwBGClr, uint32_t dwBorderClr)
Definition: C4Gui.h:2018
#define C4GUI_ScrollBarHgt
Definition: C4Gui.h:104
C4PlayerControlDefs PlayerControlDefs
Definition: C4Game.h:92
char LanguageEx[CFG_MaxString+1]
Definition: C4Config.h:37
CStdFont BookFont
Definition: C4Startup.h:77
bool SaveConfig(bool fForce, bool fKeepOpen)
const char * getData() const
Definition: StdBuf.h:442
C4Rect & GetBounds()
Definition: C4Gui.h:445
int GetInfoCount()
Definition: C4Language.cpp:138
char Language[CFG_MaxString+1]
Definition: C4Config.h:36
void RecreateDialog(bool fFade)
int GetConfigWidth()
Definition: C4Application.h:83
std::tuple< std::string, int > BreakMessage(const char *szMsg, int iWdt, bool fCheckMarkup, float fZoom=1.0f)
const char * GetName() const
void SetColors(uint32_t dwNewBGClr, uint32_t dwNewFontClr, uint32_t dwNewBorderColor)
Definition: C4Gui.h:1348
Icons
Definition: C4Gui.h:637
static bool GetStandardCheckBoxSize(int *piWdt, int *piHgt, const char *szForCaptionText, CStdFont *pUseFont)
C4KeyCode Key
void SetColors(uint32_t dwFrameClr, uint32_t dwTitleClr, uint32_t dwBackClr=0xffffffff)
Definition: C4Gui.h:1017
void Quit() override
C4PlayerControlAssignmentSet * CreateEmptySetByTemplate(const C4PlayerControlAssignmentSet &template_set)
C4LanguageInfo * FindInfo(const char *strCode)
Definition: C4Language.cpp:353
int32_t x
Definition: C4Rect.h:30
bool ShowMessage(const char *szMessage, const char *szCaption, Icons icoIcon, int32_t *piConfigDontShowAgainSetting=nullptr)
void SetKey(const C4KeyCodeEx &key)
void Remove(StdSchedulerProc *pProc)
int32_t GamepadGuiControl
Definition: C4Config.h:229
bool GetIndexedDisplayMode(int32_t iIndex, int32_t *piXRes, int32_t *piYRes, int32_t *piBitDepth, int32_t *piRefreshRate, uint32_t iMonitor)
Definition: C4AppSDL.cpp:335
int32_t Monitor
Definition: C4Config.h:112
const C4KeyCode KEY_Undefined
C4PlayerControlAssignment * CreateAssignmentForControl(const char *control_name)
static int32_t GetCustomEditHeight(CStdFont *pUseFont)
Definition: C4GuiEdit.cpp:119
bool LoadLanguage(const char *strLanguages)
Definition: C4Language.cpp:361
float TargetX
Definition: C4Facet.h:165
char RXFontName[CFG_MaxString+1]
Definition: C4Config.h:41
void SetFocus(Control *pCtrl, bool fByMouse)
C4ConfigControls Controls
Definition: C4Config.h:259
const C4KeyCodeEx & GetTriggerKey() const
const int32_t C4StartupEditBGColor
Definition: C4Startup.h:29
void SetBounds(const C4Rect &rcNewBound)
Definition: C4Gui.h:446
bool FindEntry(const char *szText)
int32_t RXFontSize
Definition: C4Config.h:42
bool KEY_IsModifier(C4KeyCode k)
int32_t MMTimer
Definition: C4Config.h:48
const int32_t C4StartupBtnBorderColor1
Definition: C4Startup.h:32
int32_t ResX
Definition: C4Config.h:103
#define C4GUI_Caption2FontClr
Definition: C4Gui.h:38
C4PlayerControlAssignment * GetAssignmentByIndex(int32_t index)
const int ALeft
Definition: C4Surface.h:41
virtual bool Init(C4Window *pWindow, C4AbstractApp *pApp)
virtual void OnClosed(bool fOK)
int GetLineHeight() const
Definition: C4FontLoader.h:125
StdStrBuf GetKeysAsString(bool human_readable, bool short_name) const
const int32_t C4MC_Button_None
int32_t ResY
Definition: C4Config.h:103
bool InitShaders(C4GroupSet *pGroups)
Definition: C4DrawGL.cpp:728
const char * DefaultFonts[]
#define C4GUI_DefDlgIndent
Definition: C4Gui.h:132
static C4Startup * Get()
Definition: C4Startup.h:145
bool Save()
Definition: C4Config.cpp:400
const C4KeyCode KEY_Any
bool fConfigLoaded
Definition: C4Config.h:262
void DrawX(C4Surface *sfcTarget, float iX, float iY, float iWdt, float iHgt, int32_t iPhaseX=0, int32_t iPhaseY=0) const
Definition: C4Facet.cpp:358
const char * GetLastError()
Definition: C4App.h:98
void AddEntry(const char *szText, int32_t id)
bool GetFromRight(int32_t iWdt, int32_t iHgt, C4Rect &rcOut)
Definition: C4Gui.cpp:1093
const char * GetControlName() const
int32_t FESamples
Definition: C4Config.h:129
Sheet * AddSheet(const char *szTitle, int32_t icoTitle=Ico_None)
virtual void Clear(bool multisample_change=false)
int32_t MusicVolume
Definition: C4Config.h:131
int GetConfigHeight()
Definition: C4Application.h:84
bool ShowModalDlg(Dialog *pDlg, bool fDestruct=true)
virtual Screen * GetScreen()
Definition: C4Gui.cpp:289
C4PlayerControlAssignmentSets UserSets
Definition: C4Config.h:231
CStdGL * pGL
Definition: C4DrawGL.cpp:918
int32_t Hgt
Definition: C4Rect.h:30
int32_t EnableUPnP
Definition: C4Config.h:154
int32_t GetHeightByWidth(int32_t iWidth)
Definition: C4Facet.h:155
C4Surface * Surface
Definition: C4Facet.h:117
bool GetFromLeft(int32_t iWdt, int32_t iHgt, C4Rect &rcOut)
Definition: C4Gui.cpp:1076
float TargetY
Definition: C4Facet.h:165
int32_t UseAlternateServer
Definition: C4Config.h:152
C4FacetID fctOptionsTabClip
Definition: C4Startup.h:83
void SetText(const char *szToText)
int32_t GetInnerWidth() const
Definition: C4Gui.h:2805
Screen TheScreen
Definition: C4Gui.cpp:1054
uint32_t DWORD
C4ConfigSound Sound
Definition: C4Config.h:254
int32_t AutoFrameSkip
Definition: C4Config.h:116
C4PlayerControlAssignmentSets PlayerControlDefaultAssignmentSets
Definition: C4Game.h:93
void SetFont(CStdFont *pToFont)
Definition: C4Gui.h:1016
void Copy()
Definition: StdBuf.h:467
size_t getLength() const
Definition: StdBuf.h:445
float Wdt
Definition: C4Facet.h:118
int32_t PortTCP
Definition: C4Config.h:153
void CopyValidated(const char *szFromVal)
C4PlayerControlAssignmentSets PlayerControlUserAssignmentSets
Definition: C4Game.h:93
C4StartupGraphics Graphics
Definition: C4Startup.h:112
C4Window * pWindow
Definition: C4App.h:80
C4Application Application
Definition: C4Globals.cpp:44
bool GetCentered(int32_t iWdt, int32_t iHgt, C4Rect &rcOut)
Definition: C4Gui.cpp:1133
virtual bool InvalidateDeviceObjects()=0
void IntUnlock()
Definition: C4Surface.cpp:864
void RemoveAssignmentByControlName(const char *control_name)
bool IsInActiveDlg(bool fForKeyboard)
Definition: C4Gui.cpp:435
void SetText(const char *szToText, bool fAllowHotkey=true)
Definition: C4GuiLabels.cpp:74
int32_t GetActiveSheetIndex()
int32_t PortUDP
Definition: C4Config.h:153
int32_t RXMusic
Definition: C4Config.h:127
bool Play(const char *szSongname=nullptr, bool fLoop=false, int fadetime_ms=0, double max_resume_time=0.0, bool allow_break=false)
void UpdateGamepadGUIControlEnabled()
Definition: C4Gui.cpp:1049
StdStrBuf FormatString(const char *szFmt,...)
Definition: StdBuf.cpp:270
void RemoveSetByName(const char *set_name)
char Info[C4MaxLanguageInfo+1]
Definition: C4Language.h:34
C4MusicSystem MusicSystem
Definition: C4Application.h:41