1 /* bzflag
2  * Copyright (c) 1993-2021 Tim Riker
3  *
4  * This package is free software;  you can redistribute it and/or
5  * modify it under the terms of the license found in the file
6  * named COPYING that should have accompanied this file.
7  *
8  * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
9  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
10  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
11  */
12 
13 /* interface header */
14 #include "GUIOptionsMenu.h"
15 
16 /* common implementation headers */
17 #include "BZDBCache.h"
18 #include "TextUtils.h"
19 #include "FontManager.h"
20 
21 /* local implementation headers */
22 #include "MainMenu.h"
23 #include "HUDDialogStack.h"
24 #include "HUDuiList.h"
25 #include "HUDuiLabel.h"
26 #include "ScoreboardRenderer.h"
27 #include "playing.h"
28 
GUIOptionsMenu()29 GUIOptionsMenu::GUIOptionsMenu()
30 {
31     // add controls
32     std::vector<HUDuiControl*>& listHUD = getControls();
33 
34     // cache font face ID
35     int fontFace = MainMenu::getFontFace();
36 
37     HUDuiLabel* label = new HUDuiLabel;
38     label->setFontFace(fontFace);
39     label->setString("GUI Settings");
40     listHUD.push_back(label);
41 
42     HUDuiList* option;
43 
44     option = new HUDuiList;
45     option->setFontFace(fontFace);
46     option->setLabel("Scoreboard Font Size:");
47     option->setCallback(callback, "S");
48     std::vector<std::string>* options = &option->getList();
49     options->push_back(std::string("Auto"));
50     option->createSlider(4);
51     option->update();
52     listHUD.push_back(option);
53 
54     option = new HUDuiList;
55     option->setFontFace(fontFace);
56     option->setLabel("Scoreboard Sort:");
57     option->setCallback(callback, "p");
58     options = &option->getList();
59     const char **sortLabels = ScoreboardRenderer::getSortLabels();
60     while (*sortLabels != NULL)
61         options->push_back(std::string(*sortLabels++));
62     option->update();
63     listHUD.push_back(option);
64 
65     // set motto display length
66     option = new HUDuiList;
67     option->setFontFace(fontFace);
68     option->setLabel("Motto Display Length:");
69     option->setCallback(callback, "E");
70     option->createSlider(32 + 1);
71     option->update();
72     listHUD.push_back(option);
73 
74 
75     // set Radar Translucency
76     option = new HUDuiList;
77     option->setFontFace(fontFace);
78     option->setLabel("Radar Opacity:");
79     option->setCallback(callback, "Y");
80     option->createSlider(11);
81     option->update();
82     listHUD.push_back(option);
83 
84     // set radar size
85     option = new HUDuiList;
86     option->setFontFace(fontFace);
87     option->setLabel("Radar Size:");
88     option->setCallback(callback, "R");
89     option->createSlider(maxRadarSize + 1);
90     option->update();
91     listHUD.push_back(option);
92 
93     option = new HUDuiList;
94     option->setFontFace(fontFace);
95     option->setLabel("Radar Style:");
96     option->setCallback(callback, "e");
97     options = &option->getList();
98     options->push_back(std::string("Normal"));
99     options->push_back(std::string("Fast"));
100     options->push_back(std::string("Fast Sorted"));
101     options->push_back(std::string("Enhanced"));
102     option->update();
103     listHUD.push_back(option);
104 
105     // set radar shot size
106     option = new HUDuiList;
107     option->setFontFace(fontFace);
108     option->setLabel("Radar Shot Size:");
109     option->setCallback(callback, "s");
110     option->createSlider(11);
111     option->update();
112     listHUD.push_back(option);
113 
114     // set radar shot length
115     option = new HUDuiList;
116     option->setFontFace(fontFace);
117     option->setLabel("Radar Shot Length:");
118     option->setCallback(callback, "l");
119     option->createSlider(11);
120     option->update();
121     listHUD.push_back(option);
122 
123     // radar shot leading line
124     option = new HUDuiList;
125     option->setFontFace(fontFace);
126     option->setLabel("Radar Shot Line:");
127     option->setCallback(callback, "F");
128     options = &option->getList();
129     options->push_back(std::string("Lagging"));
130     options->push_back(std::string("Leading"));
131     options->push_back(std::string("Leading & Lagging"));
132     option->update();
133     listHUD.push_back(option);
134 
135     // set radar position
136     option = new HUDuiList;
137     option->setFontFace(fontFace);
138     option->setLabel("Radar Position:");
139     option->setCallback(callback, "P");
140     options = &option->getList();
141     options->push_back(std::string("Left"));
142     options->push_back(std::string("Right"));
143     option->update();
144     listHUD.push_back(option);
145 
146     // toggle coloring of shots on radar
147     option = new HUDuiList;
148     option->setFontFace(fontFace);
149     option->setLabel("Colored shots on radar:");
150     option->setCallback(callback, "z");
151     options = &option->getList();
152     options->push_back(std::string("Off"));
153     options->push_back(std::string("On"));
154     option->update();
155     listHUD.push_back(option);
156 
157 
158 
159     // set Panel Translucency
160     option = new HUDuiList;
161     option->setFontFace(fontFace);
162     option->setLabel("Panel Opacity:");
163     option->setCallback(callback, "y");
164     option->createSlider(11);
165     option->update();
166     listHUD.push_back(option);
167 
168     // set panel size
169     option = new HUDuiList;
170     option->setFontFace(fontFace);
171     option->setLabel("Panel Height:");
172     option->setCallback(callback, "a");
173     option->createSlider(maxRadarSize + 1);
174     option->update();
175     listHUD.push_back(option);
176 
177     option = new HUDuiList;
178     option->setFontFace(fontFace);
179     option->setLabel("ControlPanel Font Size:");
180     option->setCallback(callback, "C");
181     options = &option->getList();
182     options->push_back(std::string("Auto"));
183     option->createSlider(4);
184     option->update();
185     listHUD.push_back(option);
186 
187     // Tabs
188     option = new HUDuiList;
189     option->setFontFace(fontFace);
190     option->setLabel("Control panel tabs:");
191     option->setCallback(callback, "t");
192     options = &option->getList();
193     options->push_back(std::string("Off"));
194     options->push_back(std::string("Left"));
195     options->push_back(std::string("Right"));
196     option->update();
197     listHUD.push_back(option);
198 
199     // Automatic pausing of the console
200     option = new HUDuiList;
201     option->setFontFace(fontFace);
202     option->setLabel("Automatically pause the control panel:");
203     option->setCallback(callback, "o");
204     options = &option->getList();
205     options->push_back(std::string("Off"));
206     options->push_back(std::string("On"));
207     option->update();
208     listHUD.push_back(option);
209 
210     // Time/date display settings
211     option = new HUDuiList;
212     option->setFontFace(fontFace);
213     option->setLabel("Timestamps in console:");
214     option->setCallback(callback, "Z");
215     options = &option->getList();
216     options->push_back(std::string("Off"));
217     options->push_back(std::string("Time"));
218     options->push_back(std::string("Date and Time"));
219     option->update();
220     listHUD.push_back(option);
221 
222     // GUI coloring
223     option = new HUDuiList;
224     option->setFontFace(fontFace);
225     option->setLabel("Control panel coloring:");
226     option->setCallback(callback, "c");
227     options = &option->getList();
228     options->push_back(std::string("Off"));
229     options->push_back(std::string("On"));
230     option->update();
231     listHUD.push_back(option);
232 
233     // Underline color
234     option = new HUDuiList;
235     option->setFontFace(fontFace);
236     option->setLabel("Underline color:");
237     option->setCallback(callback, "u");
238     options = &option->getList();
239     options->push_back(std::string("Cyan"));
240     options->push_back(std::string("Grey"));
241     options->push_back(std::string("Text"));
242     option->update();
243     listHUD.push_back(option);
244 
245     // Killer Highlight
246     option = new HUDuiList;
247     option->setFontFace(fontFace);
248     option->setLabel("Killer Highlight:");
249     option->setCallback(callback, "k");
250     options = &option->getList();
251     options->push_back(std::string("None"));
252     options->push_back(std::string("Pulsating"));
253     options->push_back(std::string("Underline"));
254     option->update();
255     listHUD.push_back(option);
256 
257     // Pulsate Rate
258     option = new HUDuiList;
259     option->setFontFace(fontFace);
260     option->setLabel("Pulsation Rate:");
261     option->setCallback(callback, "r");
262     option->createSlider(9);
263     option->update();
264     listHUD.push_back(option);
265 
266     // Pulsate Depth
267     option = new HUDuiList;
268     option->setFontFace(fontFace);
269     option->setLabel("Pulsation Depth:");
270     option->setCallback(callback, "d");
271     option->createSlider(9);
272     option->update();
273     listHUD.push_back(option);
274 
275 
276 
277     // Time/date display settings
278     option = new HUDuiList;
279     option->setFontFace(fontFace);
280     option->setLabel("Time / Date Display:");
281     option->setCallback(callback, "h");
282     options = &option->getList();
283     options->push_back(std::string("Time"));
284     options->push_back(std::string("Date"));
285     options->push_back(std::string("Date and Time"));
286     option->update();
287     listHUD.push_back(option);
288 
289     // HUD Reload timer
290     option = new HUDuiList;
291     option->setFontFace(fontFace);
292     option->setLabel("Reload timer on HUD:");
293     option->setCallback(callback, "T");
294     options = &option->getList();
295     options->push_back(std::string("Off"));
296     options->push_back(std::string("On"));
297     option->update();
298     listHUD.push_back(option);
299 
300     option = new HUDuiList;
301     option->setFontFace(fontFace);
302     option->setLabel("Always Show Team Scores:");
303     option->setCallback(callback, "q");
304     options = &option->getList();
305     options->push_back(std::string("Off"));
306     options->push_back(std::string("On"));
307     option->update();
308     listHUD.push_back(option);
309 
310     // set observer info
311     option = new HUDuiList;
312     option->setFontFace(fontFace);
313     option->setLabel("Extended Observer Info:");
314     option->setCallback(callback, "O");
315     options = &option->getList();
316     options->push_back(std::string("Off"));
317     options->push_back(std::string("On"));
318     options->push_back(std::string("On With Apparent Speeds"));
319     options->push_back(std::string("Full"));
320     option->update();
321     listHUD.push_back(option);
322 
323     option = new HUDuiList;
324     option->setFontFace(fontFace);
325     option->setLabel("Show Coordinates:");
326     option->setCallback(callback, "D");
327     options = &option->getList();
328     options->push_back(std::string("Off"));
329     options->push_back(std::string("On"));
330     option->update();
331     listHUD.push_back(option);
332 
333     initNavigation(listHUD, 1, listHUD.size()-1);
334 }
335 
~GUIOptionsMenu()336 GUIOptionsMenu::~GUIOptionsMenu()
337 {
338 }
339 
execute()340 void            GUIOptionsMenu::execute()
341 {
342 }
343 
resize(int _width,int _height)344 void            GUIOptionsMenu::resize(int _width, int _height)
345 {
346     HUDDialog::resize(_width, _height);
347 
348     // use a big font for title, smaller font for the rest
349     const float titleFontSize = (float)_height / 15.0f;
350     const float fontSize = (float)_height / 70.0f;
351     FontManager &fm = FontManager::instance();
352 
353     // reposition title
354     std::vector<HUDuiControl*>& listHUD = getControls();
355     HUDuiLabel* title = (HUDuiLabel*)listHUD[0];
356     title->setFontSize(titleFontSize);
357     const float titleWidth = fm.getStrLength(MainMenu::getFontFace(), titleFontSize, title->getString());
358     const float titleHeight = fm.getStrHeight(MainMenu::getFontFace(), titleFontSize, " ");
359     float x = 0.5f * ((float)_width - titleWidth);
360     float y = (float)_height - titleHeight;
361     title->setPosition(x, y);
362 
363     // reposition options
364     x = 0.54f * (float)_width;
365     y -= 0.6f * titleHeight;
366     const float h = fm.getStrHeight(MainMenu::getFontFace(), fontSize, " ");
367     const int count = listHUD.size();
368     for (int i = 1; i < count; i++)
369     {
370         listHUD[i]->setFontSize(fontSize);
371         listHUD[i]->setPosition(x, y);
372         // Add extra space after Motto Display Length, Colored shots on radar, and Pulsation Depth
373         if (i == 3 || i == 11 || i == 22)
374             y -= 1.75f * h;
375         else
376             y -= 1.0f * h;
377     }
378 
379     // load current settings
380     SceneRenderer* renderer = getSceneRenderer();
381     if (renderer)
382     {
383         int i = 1;
384         // Scoreboard Font Size
385         ((HUDuiList*)listHUD[i++])->setIndex(static_cast<int>(BZDB.eval("scorefontsize")));
386         // Scoreboard Sort
387         ((HUDuiList*)listHUD[i++])->setIndex(ScoreboardRenderer::getSort());
388         // Motto Display Length
389         if (BZDB.isTrue("hideMottos"))
390             ((HUDuiList*)listHUD[i++])->setIndex(0);
391         else
392             ((HUDuiList*)listHUD[i++])->setIndex(BZDB.evalInt("mottoDispLen") / 4);
393 
394         // Radar Opacity
395         ((HUDuiList*)listHUD[i++])->setIndex((int)(10.0f * renderer->getRadarOpacity() + 0.5));
396         // Radar Size
397         ((HUDuiList*)listHUD[i++])->setIndex(renderer->getRadarSize());
398         // Radar Style
399         ((HUDuiList*)listHUD[i++])->setIndex(BZDBCache::radarStyle);
400         // Radar Shot Size
401         ((HUDuiList*)listHUD[i++])->setIndex(static_cast<int>(BZDB.eval("sizedradarshots")));
402         // Radar Shot Length
403         ((HUDuiList*)listHUD[i++])->setIndex(static_cast<int>(BZDB.eval("linedradarshots")));
404         // Radar Shot Line
405         ((HUDuiList*)listHUD[i++])->setIndex(static_cast<int>(BZDB.eval("leadingShotLine")));
406         // Radar Position
407         ((HUDuiList*)listHUD[i++])->setIndex(static_cast<int>(BZDB.eval("radarPosition")));
408         // Colored shots on radar
409         ((HUDuiList*)listHUD[i++])->setIndex(BZDB.isTrue("coloredradarshots") ? 1 : 0);
410 
411 
412         // Panel Opacity
413         ((HUDuiList*)listHUD[i++])->setIndex((int)(10.0f * renderer->getPanelOpacity() + 0.5));
414         // Panel Height
415         ((HUDuiList*)listHUD[i++])->setIndex(renderer->getPanelHeight());
416         // ControlPanel Font Size
417         ((HUDuiList*)listHUD[i++])->setIndex(static_cast<int>(BZDB.eval("cpanelfontsize")));
418         // Control Panel Tabs
419         ((HUDuiList*)listHUD[i++])->setIndex(static_cast<int>(BZDB.eval("showtabs")));
420         // Automatically pause the computer panel
421         ((HUDuiList*)listHUD[i++])->setIndex(BZDB.isTrue("pauseConsole") ? 1 : 0);
422         // Timestamps in console
423         ((HUDuiList*)listHUD[i++])->setIndex(BZDB.evalInt("controlPanelTimestamp"));
424         // Control panel coloring
425         ((HUDuiList*)listHUD[i++])->setIndex(BZDB.isTrue("colorful") ? 1 : 0);
426         // Underline color - find index of mode string in options
427         const std::vector<std::string> &opts = ((HUDuiList*)listHUD[i])->getList();
428         std::string uColor = BZDB.get("underlineColor");
429         ((HUDuiList*)listHUD[i++])->setIndex(std::find(opts.begin(), opts.end(), uColor) - opts.begin());
430         // Killer Highlight
431         ((HUDuiList*)listHUD[i++])->setIndex(static_cast<int>(BZDB.eval("killerhighlight")));
432         // Pulsation Rate
433         ((HUDuiList*)listHUD[i++])->setIndex(static_cast<int>(BZDB.eval("pulseRate") * 5) - 1);
434         // Pulsating Depth
435         ((HUDuiList*)listHUD[i++])->setIndex(static_cast<int>(BZDB.eval("pulseDepth") * 10) - 1);
436 
437 
438         // Time / Date Display
439         ((HUDuiList*)listHUD[i++])->setIndex(static_cast<int>(BZDB.eval("timedate")));
440         // Reload timer on HUD
441         ((HUDuiList*)listHUD[i++])->setIndex(BZDB.isTrue("displayReloadTimer") ? 1 : 0);
442         // Always Show Team Scores
443         ((HUDuiList*)listHUD[i++])->setIndex(ScoreboardRenderer::getAlwaysTeamScore());
444         // Extended Observer Info
445         ((HUDuiList*)listHUD[i++])->setIndex(static_cast<int>(BZDB.eval("showVelocities")));
446         // Show coordinates
447         ((HUDuiList*)listHUD[i++])->setIndex(BZDB.isTrue("showCoordinates") ? 1 : 0);
448     }
449 }
450 
callback(HUDuiControl * w,const void * data)451 void            GUIOptionsMenu::callback(HUDuiControl* w, const void* data)
452 {
453     HUDuiList* list = (HUDuiList*)w;
454 
455     SceneRenderer* sceneRenderer = getSceneRenderer();
456     switch (((const char*)data)[0])
457     {
458     case 'e':
459         BZDB.setInt("radarStyle", list->getIndex());
460         break;
461 
462     case 'C':
463     {
464         BZDB.setInt("cpanelfontsize", list->getIndex());
465         getMainWindow()->getWindow()->callResizeCallbacks();
466         break;
467     }
468 
469     case 'h':
470     {
471         BZDB.setInt("timedate", list->getIndex());
472         break;
473     }
474 
475     case 'Z':
476     {
477         BZDB.setInt("controlPanelTimestamp", list->getIndex());
478         break;
479     }
480 
481     case 'S':
482     {
483         BZDB.setInt("scorefontsize", list->getIndex());
484         getMainWindow()->getWindow()->callResizeCallbacks();
485         break;
486     }
487 
488     case 'O':
489     {
490         BZDB.setInt("showVelocities", list->getIndex());
491         getMainWindow()->getWindow()->callResizeCallbacks();
492         break;
493     }
494 
495     case 'y':
496     {
497         const float newOpacity = (float)list->getIndex() / 10.0f;
498         if (newOpacity == 1.0f || sceneRenderer->getRadarOpacity() == 1.0f)
499             sceneRenderer->setRadarOpacity(newOpacity);
500         sceneRenderer->setPanelOpacity(newOpacity);
501         break;
502     }
503 
504     case 'Y':
505     {
506         const float newOpacity = (float)list->getIndex() / 10.0f;
507         sceneRenderer->setRadarOpacity(newOpacity);
508         if (newOpacity == 1.0f || sceneRenderer->getPanelOpacity() == 1.0f)
509             sceneRenderer->setPanelOpacity(newOpacity);
510         break;
511     }
512 
513     case 'z':
514         BZDB.set("coloredradarshots", list->getIndex() ? "1" : "0");
515         break;
516 
517     case 'l':
518         BZDB.set("linedradarshots", TextUtils::format("%d", list->getIndex()));
519         break;
520 
521     case 's':
522         BZDB.set("sizedradarshots", TextUtils::format("%d", list->getIndex()));
523         break;
524 
525     case 'F':
526         BZDB.setInt("leadingShotLine", list->getIndex());
527         break;
528 
529     case 'P':
530         BZDB.setInt("radarPosition", list->getIndex());
531         controlPanel->resize();
532         break;
533 
534     case 'R':
535     {
536         BZDB.setInt("radarsize", list->getIndex());
537         break;
538     }
539 
540     case 'a':
541     {
542         BZDB.setInt("panelheight", list->getIndex());
543         break;
544     }
545 
546     case 'o':
547     {
548         BZDB.set("pauseConsole", list->getIndex() ? "1" : "0");
549         break;
550     }
551 
552     case 'c':
553     {
554         BZDB.set("colorful", list->getIndex() ? "1" : "0");
555         break;
556     }
557 
558     case 't':
559     {
560         BZDB.set("showtabs", TextUtils::format("%d", list->getIndex()));
561         break;
562     }
563 
564     case 'u':
565     {
566         std::vector<std::string>* options = &list->getList();
567         std::string color = (*options)[list->getIndex()];
568         BZDB.set("underlineColor", color);
569         break;
570     }
571 
572     case 'k':
573     {
574         BZDB.set("killerhighlight", TextUtils::format("%d", list->getIndex()));
575         break;
576     }
577 
578     case 'r':
579     {
580         BZDB.set("pulseRate", TextUtils::format("%f", (float)(list->getIndex() + 1) / 5.0f));
581         break;
582     }
583 
584     case 'd':
585     {
586         BZDB.set("pulseDepth", TextUtils::format("%f", (float)(list->getIndex() + 1) / 10.0f));
587         break;
588     }
589 
590     case 'T':
591     {
592         BZDB.set("displayReloadTimer", list->getIndex() ? "1" : "0");
593         break;
594     }
595 
596     case 'p':
597         ScoreboardRenderer::setSort(list->getIndex());
598         break;
599 
600     case 'q':
601         ScoreboardRenderer::setAlwaysTeamScore(list->getIndex() ? true : false);
602         break;
603 
604     case 'E':
605         BZDB.set("mottoDispLen",  TextUtils::format("%d", list->getIndex() * 4));
606         BZDB.set("hideMottos", list->getIndex() ? "0" : "1");
607         break;
608     case 'D':
609     {
610         BZDB.setBool("showCoordinates", list->getIndex() == 1);
611     }
612 
613 
614     }
615 }
616 
617 
618 // Local Variables: ***
619 // mode: C++ ***
620 // tab-width: 4 ***
621 // c-basic-offset: 4 ***
622 // indent-tabs-mode: nil ***
623 // End: ***
624 // ex: shiftwidth=4 tabstop=4
625