OpenClonk
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros
C4GameOptions.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 // Custom game options and configuration dialog
17 
18 #include "C4Include.h"
19 #include "gui/C4GameOptions.h"
20 
21 #include "game/C4Application.h"
22 #include "game/C4Game.h"
23 #include "control/C4GameControl.h"
25 #include "gui/C4GameLobby.h"
26 #include "gui/C4Startup.h"
27 
28 // ----------- C4GameOptionsList::Option ----------------------------------------------------------------
29 
30 C4GameOptionsList::Option::Option(C4GameOptionsList *pForDlg) :
31  BaseClass(C4Rect(0, 0, 0, 0)), pForDlg(pForDlg), pPrimarySubcomponent(nullptr)
32 {}
33 
34 void C4GameOptionsList::Option::InitOption(C4GameOptionsList *pForDlg)
35 {
36  // post-call after initialization: Adds to list box and does initial update
37  // add to listbox (will eventually get moved)
38  pForDlg->AddElement(this);
39  // first-time update
40  Update();
41 }
42 
43 
44 
45 // ----------- C4GameOptionsList::OptionDropdown ----------------------------------------------------------------
46 
47 C4GameOptionsList::OptionDropdown::OptionDropdown(class C4GameOptionsList *pForDlg, const char *szCaption, bool fReadOnly)
48  : Option(pForDlg), fReadOnly(fReadOnly)
49 {
50  bool fIsPreGame = pForDlg->IsPreGame();
52  uint32_t dwFontClr = fIsPreGame ? C4StartupFontClr : 0xffffffff;
53  // get size of caption label
54  bool fTabular = pForDlg->IsTabular();
55  int32_t iCaptWidth, iCaptHeight;
56  if (fTabular)
57  {
58  // tabular layout: Caption label width by largest caption on runtime; fixed 1/3rd on startup
59  rUseFont.GetTextExtent(LoadResStr("IDS_NET_RUNTIMEJOIN"), iCaptWidth, iCaptHeight, true);
60  if (pForDlg->IsPreGame())
61  {
62  iCaptWidth = pForDlg->GetItemWidth() * 1 / 3;
63  }
64  else
65  {
66  iCaptWidth = iCaptWidth * 5 / 4;
67  }
68  }
69  else
70  {
71  rUseFont.GetTextExtent(szCaption, iCaptWidth, iCaptHeight, true);
72  }
73  // calc total height for component
74  int iHorizontalMargin = 1;
75  int iVerticalMargin = 1;
76  int iComboMargin = 5;
77  int iSelComboHgt = C4GUI::ComboBox::GetDefaultHeight();
78  SetBounds(C4Rect(0, 0, pForDlg->GetItemWidth(), (!fTabular) * (iCaptHeight + iVerticalMargin*2) + iVerticalMargin*2 + iSelComboHgt));
79  C4GUI::ComponentAligner ca(GetContainedClientRect(), iHorizontalMargin, iVerticalMargin);
80  // create subcomponents
81  AddElement(pCaption = new C4GUI::Label(FormatString("%s:", szCaption).getData(), fTabular ? ca.GetFromLeft(iCaptWidth, iCaptHeight) : ca.GetFromTop(iCaptHeight), ALeft, dwFontClr, &rUseFont, false, false));
82  ca.ExpandLeft(-iComboMargin);
83  AddElement(pPrimarySubcomponent = pDropdownList = new C4GUI::ComboBox(ca.GetAll()));
84  pDropdownList->SetReadOnly(fReadOnly);
85  pDropdownList->SetComboCB(new C4GUI::ComboBox_FillCallback<C4GameOptionsList::OptionDropdown>(this, &C4GameOptionsList::OptionDropdown::OnDropdownFill, &C4GameOptionsList::OptionDropdown::OnDropdownSelChange));
86  if (fIsPreGame)
87  {
89  pDropdownList->SetFont(&rUseFont);
90  pDropdownList->SetDecoration(&(C4Startup::Get()->Graphics.fctContext));
91  }
92  // final init
93  InitOption(pForDlg);
94 }
95 
96 
97 
98 // ----------- C4GameOptionsList::OptionScenarioParameter----------------------------------------------------------------
99 
100 C4GameOptionsList::OptionScenarioParameter::OptionScenarioParameter(class C4GameOptionsList *pForDlg, const class C4ScenarioParameterDef *parameter_def)
101  : C4GameOptionsList::OptionDropdown(pForDlg, parameter_def->GetName(), !pForDlg->IsPreGame() && (!::Control.isCtrlHost() || ::Game.C4S.Head.SaveGame)), ParameterDef(parameter_def), LastValue(0), LastValueValid(false)
102 {
103  SetToolTip(parameter_def->GetDescription());
104 }
105 
106 void C4GameOptionsList::OptionScenarioParameter::DoDropdownFill(C4GUI::ComboBox_FillCB *pFiller)
107 {
108  // Fill dropdown menuy with known possible options for this parameter
109  size_t idx=0; const C4ScenarioParameterDef::Option *option;
110  while ((option = ParameterDef->GetOptionByIndex(idx++)))
111  {
112  pFiller->AddEntry(option->Name.getData(), option->Value);
113  }
114 }
115 
116 void C4GameOptionsList::OptionScenarioParameter::DoDropdownSelChange(int32_t idNewSelection)
117 {
118  // runtime change needs to be synchronized
119  if (!pForDlg->IsPreGame())
120  {
121  // change possible?
122  if (!::Control.isCtrlHost()) return;
123  // Then initiate an update of the parameters on all clients
124  C4GameLobby::C4PacketSetScenarioParameter pck(ParameterDef->GetID(), idNewSelection);
126  }
127  // also process on host (and standalone pre-game)
128  pForDlg->GetParameters()->SetValue(ParameterDef->GetID(), idNewSelection, false);
129  if (pForDlg->IsPreGame()) Update();
130 }
131 
132 void C4GameOptionsList::OptionScenarioParameter::Update()
133 {
134  int32_t val=0;
135  // display forced league value?
136  bool fLeagueReadOnly = false;
137  if (::Config.Network.LeagueServerSignUp && !fReadOnly && !pForDlg->IsPreGameSingle()) val = ParameterDef->GetLeagueValue();
138  if (val)
139  fLeagueReadOnly = true;
140  else
141  val = pForDlg->GetParameters()->GetValueByID(ParameterDef->GetID(), ParameterDef->GetDefault());
142  if (!fReadOnly) pDropdownList->SetReadOnly(fLeagueReadOnly);
143  // update data to currently set option
144  if (LastValueValid && val == LastValue) return;
145  const C4ScenarioParameterDef::Option *option = ParameterDef->GetOptionByValue(val);
146  if (option)
147  pDropdownList->SetText(option->Name.getData());
148  else
149  pDropdownList->SetText(FormatString("%d", (int)val).getData());
150  LastValueValid = true;
151  LastValue = val;
152 }
153 
154 
155 
156 // ----------- C4GameOptionsList::OptionControlMode ----------------------------------------------------------------
157 
158 // Unfortunately, the control mode cannot be changed in the lobby
159 C4GameOptionsList::OptionControlMode::OptionControlMode(class C4GameOptionsList *pForDlg)
160  : C4GameOptionsList::OptionDropdown(pForDlg, LoadResStr("IDS_TEXT_CONTROLMODE"), !::Control.isCtrlHost() || !::Control.isNetwork() || !::Control.Network.IsEnabled())
161 {
162  SetToolTip(LoadResStr("IDS_DESC_CHANGESTHEWAYCONTROLDATAI"));
163 }
164 
165 void C4GameOptionsList::OptionControlMode::DoDropdownFill(C4GUI::ComboBox_FillCB *pFiller)
166 {
167  // change possible?
168  if (!::Control.isNetwork() || !::Control.Network.IsEnabled() || !::Control.isCtrlHost()) return;
169  // add possible modes
170  pFiller->AddEntry(LoadResStr("IDS_NET_CTRLMODE_CENTRAL"), CNM_Central);
171  pFiller->AddEntry(LoadResStr("IDS_NET_CTRLMODE_DECENTRAL"), CNM_Decentral);
172 }
173 
174 void C4GameOptionsList::OptionControlMode::DoDropdownSelChange(int32_t idNewSelection)
175 {
176  // change possible?
177  if (!::Control.isNetwork() || !::Control.Network.IsEnabled() || !::Control.isCtrlHost()) return;
178  // perform it
179  ::Network.SetCtrlMode(idNewSelection);
180  // update for clients done by packet; host needs to set it manually
181  Update();
182 }
183 
184 void C4GameOptionsList::OptionControlMode::Update()
185 {
186  const char *szControlMode;
188  szControlMode = LoadResStr("IDS_NET_NONET");
189  else
190  {
191  switch (::Network.Status.getCtrlMode())
192  {
193  case CNM_Central: szControlMode = LoadResStr("IDS_NET_CTRLMODE_CENTRAL"); break;
194  case CNM_Decentral: szControlMode = LoadResStr("IDS_NET_CTRLMODE_DECENTRAL"); break;
195  default: szControlMode = LoadResStr("IDS_NET_CTRLMODE_NONE"); break;
196  }
197  }
198  pDropdownList->SetText(szControlMode);
199 }
200 
201 
202 // ----------- C4GameOptionsList::OptionControlRate ----------------------------------------------------------------
203 
204 C4GameOptionsList::OptionControlRate::OptionControlRate(class C4GameOptionsList *pForDlg)
205  : C4GameOptionsList::OptionDropdown(pForDlg, LoadResStr("IDS_CTL_CONTROLRATE"), !::Control.isCtrlHost())
206 {
207  SetToolTip(LoadResStr("IDS_CTL_CONTROLRATE_DESC"));
208 }
209 
210 void C4GameOptionsList::OptionControlRate::DoDropdownFill(C4GUI::ComboBox_FillCB *pFiller)
211 {
212  for (int i = 1; i < std::min(C4MaxControlRate, 10); ++i)
213  pFiller->AddEntry(FormatString("%d", i).getData(), i);
214 }
215 
216 void C4GameOptionsList::OptionControlRate::DoDropdownSelChange(int32_t idNewSelection)
217 {
218  // adjust rate
219  int32_t iNewRate = idNewSelection;
220  if (!iNewRate || iNewRate == ::Control.ControlRate) return;
222 }
223 
224 void C4GameOptionsList::OptionControlRate::Update()
225 {
226  if (atoi(pDropdownList->GetText().getData()) == ::Control.ControlRate) return;
227  pDropdownList->SetText(FormatString("%d", ::Control.ControlRate).getData());
228 }
229 
230 
231 // ----------- C4GameOptionsList::OptionRuntimeJoin ----------------------------------------------------------------
232 
233 C4GameOptionsList::OptionRuntimeJoin::OptionRuntimeJoin(class C4GameOptionsList *pForDlg)
234  : C4GameOptionsList::OptionDropdown(pForDlg, LoadResStr("IDS_NET_RUNTIMEJOIN"), !::Network.isHost())
235 {
236  SetToolTip(LoadResStr("IDS_NET_RUNTIMEJOIN_DESC"));
237 }
238 
239 void C4GameOptionsList::OptionRuntimeJoin::DoDropdownFill(C4GUI::ComboBox_FillCB *pFiller)
240 {
241  pFiller->AddEntry(LoadResStr("IDS_NET_RUNTIMEJOINBARRED"), 0);
242  pFiller->AddEntry(LoadResStr("IDS_NET_RUNTIMEJOINFREE"), 1);
243 }
244 
245 void C4GameOptionsList::OptionRuntimeJoin::DoDropdownSelChange(int32_t idNewSelection)
246 {
247  // adjust mode
248  bool fAllowed = !!idNewSelection;
249  Config.Network.NoRuntimeJoin = !fAllowed;
250  if (Game.IsRunning) ::Network.AllowJoin(fAllowed);
251 }
252 
253 void C4GameOptionsList::OptionRuntimeJoin::Update()
254 {
255  const char *szText;
257  szText = LoadResStr("IDS_NET_RUNTIMEJOINBARRED");
258  else
259  szText = LoadResStr("IDS_NET_RUNTIMEJOINFREE");
260  pDropdownList->SetText(szText);
261 }
262 
263 
264 // ----------- C4GameOptionsList::OptionTeamDist ----------------------------------------------------------------
265 
266 C4GameOptionsList::OptionTeamDist::OptionTeamDist(class C4GameOptionsList *pForDlg)
267  : C4GameOptionsList::OptionDropdown(pForDlg, LoadResStr("IDS_MSG_TEAMDIST"), !::Control.isCtrlHost())
268 {
269  SetToolTip(LoadResStr("IDS_MSG_TEAMDIST_DESC"));
270 }
271 
272 void C4GameOptionsList::OptionTeamDist::DoDropdownFill(C4GUI::ComboBox_FillCB *pFiller)
273 {
274  Game.Teams.FillTeamDistOptions(pFiller);
275 }
276 
277 void C4GameOptionsList::OptionTeamDist::DoDropdownSelChange(int32_t idNewSelection)
278 {
279  // adjust team distribution
281 }
282 
283 void C4GameOptionsList::OptionTeamDist::Update()
284 {
285  StdStrBuf sOption; sOption.Take(Game.Teams.GetTeamDistString());
286  pDropdownList->SetText(sOption.getData());
287 }
288 
289 
290 // ----------- C4GameOptionsList::OptionTeamColors ----------------------------------------------------------------
291 
292 C4GameOptionsList::OptionTeamColors::OptionTeamColors(class C4GameOptionsList *pForDlg)
293  : C4GameOptionsList::OptionDropdown(pForDlg, LoadResStr("IDS_MSG_TEAMCOLORS"), !::Control.isCtrlHost())
294 {
295  SetToolTip(LoadResStr("IDS_MSG_TEAMCOLORS_DESC"));
296 }
297 
298 void C4GameOptionsList::OptionTeamColors::DoDropdownFill(C4GUI::ComboBox_FillCB *pFiller)
299 {
300  pFiller->AddEntry(LoadResStr("IDS_MSG_ENABLED"), 1);
301  pFiller->AddEntry(LoadResStr("IDS_MSG_DISABLED"), 0);
302 }
303 
304 void C4GameOptionsList::OptionTeamColors::DoDropdownSelChange(int32_t idNewSelection)
305 {
306  bool fEnabled = !!idNewSelection;
307  Game.Teams.SendSetTeamColors(fEnabled);
308 }
309 
310 void C4GameOptionsList::OptionTeamColors::Update()
311 {
312  pDropdownList->SetText(Game.Teams.IsTeamColors() ? LoadResStr("IDS_MSG_ENABLED") : LoadResStr("IDS_MSG_DISABLED"));
313 }
314 
315 // ----------- C4GameOptionsList -----------------------------------------------------------------------
316 
318  : C4GUI::ListBox(rcBounds), source(source), param_defs(param_defs), params(params)
319 {
320  // default parameter defs
321  if (!IsPreGame())
322  {
323  if (!this->param_defs) this->param_defs = &::Game.ScenarioParameterDefs;
324  if (!this->params) this->params = &::Game.Parameters.ScenarioParameters;
325  }
326  // initial option fill
327  InitOptions();
328  if (fActive) Activate();
329 }
330 
331 void C4GameOptionsList::InitOptions()
332 {
333  // create options for custom scenario parameters
334  if (param_defs)
335  {
336  size_t idx = 0; const C4ScenarioParameterDef *def;
337  while ((def = param_defs->GetParameterDefByIndex(idx++)))
338  if (!def->IsAchievement()) // achievements are displayed in scenario selection. no need to repeat them here
339  new OptionScenarioParameter(this, def);
340  }
341  // create lobby and runtime option selection components
342  if (!IsPreGame())
343  {
344  new OptionControlMode(this);
345  new OptionControlRate(this);
346  if (::Network.isHost()) new OptionRuntimeJoin(this);
347  if (!IsRuntime())
348  {
349  if (Game.Teams.HasTeamDistOptions()) new OptionTeamDist(this);
350  if (Game.Teams.IsMultiTeams()) new OptionTeamColors(this);
351  }
352  }
353 }
354 
355 void C4GameOptionsList::ClearOptions()
356 {
358  while ((pFirst = GetFirst())) delete pFirst;
359 }
360 
362 {
363  // update all option items
364  for (Option *pItem = static_cast<Option *>(pClientWindow->GetFirst()); pItem; pItem = pItem->GetNext())
365  pItem->Update();
366 }
367 
369 {
370  // register timer if necessary
371  Application.Add(this);
372  // force an update
373  Update();
374 }
375 
377 {
378  // release timer if set
379  Application.Remove(this);
380 }
381 
383 {
384  // update to new parameter set
385  ClearOptions();
386  this->param_defs = param_defs;
387  this->params = params;
388  InitOptions();
389 }
390 
const char * getData() const
Definition: StdBuf.h:450
bool IsRunning
Definition: C4Game.h:141
bool IsPreGame() const
void SendSetTeamDist(TeamDist eNewDist)
Definition: C4Teams.cpp:778
const C4ScenarioParameterDef * GetParameterDefByIndex(size_t idx) const
C4Config Config
Definition: C4Config.cpp:831
void SetCtrlMode(int32_t iCtrlMode)
Definition: C4Network2.cpp:841
bool isHost() const
Definition: C4Network2.h:209
bool isCtrlHost() const
Definition: C4GameControl.h:99
C4Game Game
Definition: C4Globals.cpp:52
bool IsTeamColors() const
Definition: C4Teams.h:170
bool AddElement(Element *pChild, int32_t iIndent=0)
bool IsPreGameSingle() const
bool BroadcastMsgToClients(const C4NetIOPacket &rPkt)
Element * pFirst
Definition: C4Gui.h:750
Definition: C4Rect.h:29
bool GetTextExtent(const char *szText, int32_t &rsx, int32_t &rsy, bool fCheckMarkup=true)
C4GameOptionsList(const C4Rect &rcBounds, bool fActive, C4GameOptionsListSource source, class C4ScenarioParameterDefs *param_defs=nullptr, class C4ScenarioParameters *params=nullptr)
void SendSetTeamColors(bool fEnabled)
Definition: C4Teams.cpp:821
bool IsMultiTeams() const
Definition: C4Teams.h:163
const int32_t C4StartupEditBorderColor
Definition: C4Startup.h:30
Element * GetFirst()
Definition: C4Gui.h:1571
class C4ScenarioParameterDefs & ScenarioParameterDefs
Definition: C4Game.h:77
C4GraphicsResource GraphicsResource
const int32_t C4StartupFontClr
Definition: C4Startup.h:27
C4GameParameters & Parameters
Definition: C4Game.h:69
void Add(StdSchedulerProc *pProc)
bool IsTabular() const
C4TeamList & Teams
Definition: C4Game.h:72
const char * LoadResStr(const char *id)
Definition: C4Language.h:83
void AllowJoin(bool fAllow)
Definition: C4Network2.cpp:824
bool isNetwork() const
Definition: C4GameControl.h:97
C4Network2 Network
Definition: C4Globals.cpp:53
void AdjustControlRate(int32_t iBy)
C4ScenarioParameters ScenarioParameters
Element * GetFirst()
Definition: C4Gui.h:829
C4GameControl Control
C4NetIOPacket MkC4NetIOPacket(char cStatus, const class C4PacketBase &Pkt, const C4NetIO::addr_t &addr=C4NetIO::addr_t())
Definition: C4PacketBase.h:40
void Take(char *pnData)
Definition: StdBuf.h:465
C4ConfigNetwork Network
Definition: C4Config.h:256
static int32_t GetDefaultHeight()
C4Network2Status Status
Definition: C4Network2.h:122
const char * GetDescription() const
CStdFont BookFont
Definition: C4Startup.h:65
int32_t LeagueServerSignUp
Definition: C4Config.h:152
int32_t getCtrlMode() const
Definition: C4Network2.h:81
bool HasTeamDistOptions() const
Definition: C4Teams.cpp:791
void Remove(StdSchedulerProc *pProc)
C4Network2ClientList Clients
Definition: C4Network2.h:116
int32_t GetItemWidth()
Definition: C4Gui.h:1545
const int32_t C4StartupEditBGColor
Definition: C4Startup.h:29
C4GameControlNetwork Network
Definition: C4GameControl.h:67
const int ALeft
Definition: C4Surface.h:43
void FillTeamDistOptions(C4GUI::ComboBox_FillCB *pFiller) const
Definition: C4Teams.cpp:766
static C4Startup * Get()
Definition: C4Startup.h:133
int32_t NoRuntimeJoin
Definition: C4Config.h:143
void AddEntry(const char *szText, int32_t id)
StdStrBuf GetTeamDistString() const
Definition: C4Teams.cpp:785
C4ScenarioParameters * GetParameters()
bool IsRuntime() const
C4StartupGraphics Graphics
Definition: C4Startup.h:100
void SetParameters(C4ScenarioParameterDefs *param_defs, C4ScenarioParameters *params)
C4Application Application
Definition: C4Globals.cpp:44
int32_t ControlRate
Definition: C4GameControl.h:88
int32_t GetValueByID(const char *id, int32_t default_value) const
void SetValue(const char *id, int32_t value, bool only_if_larger)
const int C4MaxControlRate
Definition: C4Constants.h:33
StdStrBuf FormatString(const char *szFmt,...)
Definition: StdBuf.cpp:277
ScrollWindow * pClientWindow
Definition: C4Gui.h:1509