Mana
Loading...
Searching...
No Matches
setup_video.cpp
Go to the documentation of this file.
1/*
2 * The Mana Client
3 * Copyright (C) 2004-2009 The Mana World Development Team
4 * Copyright (C) 2009-2012 The Mana Developers
5 *
6 * This file is part of The Mana Client.
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program. If not, see <http://www.gnu.org/licenses/>.
20 */
21
22#include "gui/setup_video.h"
23
24#include "client.h"
25#include "configuration.h"
26#include "game.h"
27#include "graphics.h"
28#include "localplayer.h"
29#include "particle.h"
30
31#include "gui/okdialog.h"
32
35#include "gui/widgets/label.h"
36#include "gui/widgets/layout.h"
37#include "gui/widgets/slider.h"
38#include "gui/widgets/spacer.h"
39
40#include "utils/gettext.h"
41#include "utils/stringutils.h"
42
43#include <guichan/key.hpp>
44#include <guichan/listmodel.hpp>
45
46#include <SDL.h>
47
48#include <numeric>
49#include <string>
50#include <vector>
51
57class StringListModel : public gcn::ListModel
58{
59public:
60 StringListModel(std::vector<std::string> strings)
61 : mStrings(std::move(strings))
62 {}
63
64 int getNumberOfElements() override
65 {
66 return mStrings.size();
67 }
68
69 std::string getElementAt(int i) override
70 {
71 return mStrings[i];
72 }
73
74private:
75 const std::vector<std::string> mStrings;
76};
77
83class ResolutionListModel : public gcn::ListModel
84{
85public:
87 {
89
90 // Add a dummy mode for "current window size"
91 mDisplayModes.insert(mDisplayModes.begin(), DisplayMode());
92 }
93
94 int getNumberOfElements() override
95 {
96 return mDisplayModes.size();
97 }
98
99 std::string getElementAt(int i) override
100 {
101 if (i == 0)
102 return _("Custom");
103
104 const auto &mode = getModeAt(i);
105 auto result = toString(mode.width) + "x" + toString(mode.height);
106
107 // Append the aspect ratio
108 const int gcd = std::gcd(mode.width, mode.height);
109 int aspectWidth = mode.width / gcd;
110 int aspectHeight = mode.height / gcd;
111 if (aspectWidth == 8 && aspectHeight == 5)
112 {
113 aspectWidth = 16;
114 aspectHeight = 10;
115 }
116 if (aspectWidth == 7 && aspectHeight == 3)
117 {
118 aspectWidth = 21;
119 aspectHeight = 9;
120 }
121 if (aspectWidth <= 32)
122 result += " (" + toString(aspectWidth) + ":" + toString(aspectHeight) + ")";
123
124 return result;
125 }
126
127 const DisplayMode &getModeAt(int i) const
128 {
129 return mDisplayModes.at(i);
130 }
131
136 int getIndexOf(int width, int height) const
137 {
138 for (unsigned i = 1; i < mDisplayModes.size(); i++) {
139 const auto &mode = mDisplayModes[i];
140 if (mode.width == width && mode.height == height)
141 return i;
142 }
143
144 return 0;
145 }
146
147private:
148 std::vector<DisplayMode> mDisplayModes;
149};
150
156class ScaleListModel : public gcn::ListModel
157{
158public:
159 ScaleListModel(const VideoSettings &videoSettings)
160 : mVideoSettings(videoSettings)
161 {}
162
163 void setVideoSettings(const VideoSettings &videoSettings)
164 {
165 mVideoSettings = videoSettings;
166 }
167
168 int getNumberOfElements() override
169 {
170 return mVideoSettings.maxScale() + 1;
171 }
172
173 std::string getElementAt(int i) override
174 {
175 if (i == 0)
176 return strprintf(_("Auto (%dx)"), mVideoSettings.autoScale());
177
178 return strprintf(_("%dx"), i);
179 }
180
181private:
183};
184
185
186static const char *overlayDetailToString(int detail)
187{
188 if (detail == -1)
189 detail = config.overlayDetail;
190
191 switch (detail)
192 {
193 case 0: return _("off");
194 case 1: return _("low");
195 case 2: return _("high");
196 }
197 return "";
198}
199
200static const char *particleDetailToString(int detail)
201{
202 if (detail == -1)
203 detail = 3 - config.particleEmitterSkip;
204
205 switch (detail)
206 {
207 case 0: return _("low");
208 case 1: return _("medium");
209 case 2: return _("high");
210 case 3: return _("max");
211 }
212 return "";
213}
214
216 mVideoSettings(Client::getVideo().settings()),
217 mCustomCursorEnabled(config.customCursor),
218 mParticleEffectsEnabled(config.particleEffects),
219 mFps(config.fpsLimit),
220 mSDLTransparencyDisabled(config.disableTransparency),
221 mWindowModeListModel(new StringListModel({ _("Windowed"), _("Windowed Fullscreen"), _("Fullscreen") })),
222 mResolutionListModel(new ResolutionListModel),
223 mScaleListModel(new ScaleListModel(mVideoSettings)),
224 mWindowModeDropDown(new DropDown(mWindowModeListModel.get())),
225 mResolutionDropDown(new DropDown(mResolutionListModel.get())),
226 mScaleDropDown(new DropDown(mScaleListModel.get())),
227 mVSyncCheckBox(new CheckBox(_("VSync"), mVideoSettings.vsync)),
228 mOpenGLCheckBox(new CheckBox(_("OpenGL (Legacy)"), mVideoSettings.openGL)),
229 mCustomCursorCheckBox(new CheckBox(_("Custom cursor"), mCustomCursorEnabled)),
230 mParticleEffectsCheckBox(new CheckBox(_("Particle effects"), mParticleEffectsEnabled)),
231 mFpsCheckBox(new CheckBox(_("FPS limit:"))),
232 mFpsSlider(new Slider(10, 120)),
233 mFpsLabel(new Label),
234 mOverlayDetail(config.overlayDetail),
235 mOverlayDetailSlider(new Slider(0, 2)),
236 mOverlayDetailField(new Label),
237 mParticleDetail(3 - config.particleEmitterSkip),
238 mParticleDetailSlider(new Slider(0, 3)),
239 mParticleDetailField(new Label),
240 mDisableSDLTransparencyCheckBox(
241 new CheckBox(_("Disable transparency (Low CPU mode)"),
242 mSDLTransparencyDisabled))
243{
244 setName(_("Video"));
245
246 auto overlayDetailLabel = new Label(_("Ambient FX:"));
247 auto particleDetailLabel = new Label(_("Particle detail:"));
248
249#ifndef USE_OPENGL
250 mOpenGLCheckBox->setEnabled(false);
251#endif
252
253 mFpsLabel->setCaption(mFps > 0 ? toString(mFps) : _("None"));
254 mFpsLabel->setWidth(60);
255 mFpsSlider->setValue(mFps);
256 mFpsSlider->setEnabled(mFps > 0);
257 mFpsCheckBox->setSelected(mFps > 0);
258
259 overlayDetailLabel->setAlignment(Graphics::RIGHT);
260 particleDetailLabel->setAlignment(Graphics::RIGHT);
261
262 // If the openGL Mode is enabled, disabling the transaprency
263 // is irrelevant.
264 mDisableSDLTransparencyCheckBox->setEnabled(!mVideoSettings.openGL);
265
266 // Pre-select the current video mode.
267 mWindowModeDropDown->setSelected(static_cast<int>(mVideoSettings.windowMode));
268 mResolutionDropDown->setSelected(mResolutionListModel->getIndexOf(mVideoSettings.width,
269 mVideoSettings.height));
270 mResolutionDropDown->setEnabled(mVideoSettings.windowMode != WindowMode::WindowedFullscreen);
271 mScaleDropDown->setSelected(mVideoSettings.userScale);
272
273 // Set actions
274 mWindowModeDropDown->setActionEventId("windowmode");
275 mResolutionDropDown->setActionEventId("resolution");
276 mCustomCursorCheckBox->setActionEventId("customcursor");
277 mParticleEffectsCheckBox->setActionEventId("particleeffects");
278 mDisableSDLTransparencyCheckBox->setActionEventId("disableTransparency");
279 mFpsCheckBox->setActionEventId("fpslimitcheckbox");
280 mFpsSlider->setActionEventId("fpslimitslider");
281 mOverlayDetailSlider->setActionEventId("overlaydetailslider");
282 mOverlayDetailField->setActionEventId("overlaydetailfield");
283 mOpenGLCheckBox->setActionEventId("opengl");
284 mParticleDetailSlider->setActionEventId("particledetailslider");
285 mParticleDetailField->setActionEventId("particledetailfield");
286
287 // Set listeners
288 mWindowModeDropDown->addActionListener(this);
289 mResolutionDropDown->addActionListener(this);
290 mCustomCursorCheckBox->addActionListener(this);
291 mOpenGLCheckBox->addActionListener(this);
292 mParticleEffectsCheckBox->addActionListener(this);
293 mDisableSDLTransparencyCheckBox->addActionListener(this);
294 mFpsCheckBox->addActionListener(this);
295 mFpsSlider->addActionListener(this);
296 mOverlayDetailSlider->addActionListener(this);
297 mOverlayDetailField->addKeyListener(this);
298 mParticleDetailSlider->addActionListener(this);
299 mParticleDetailField->addKeyListener(this);
300
301 mOverlayDetailField->setCaption(overlayDetailToString(mOverlayDetail));
302 mOverlayDetailSlider->setValue(mOverlayDetail);
303
304 mParticleDetailField->setCaption(particleDetailToString(mParticleDetail));
305 mParticleDetailSlider->setValue(mParticleDetail);
306
307 // Do the layout
308 ContainerPlacer place = getPlacer(0, 0);
310
311 place(0, 0, new Label(_("Window mode:")));
312 place(1, 0, mWindowModeDropDown, 2).setPadding(2);
313 place(0, 1, new Label(_("Resolution:")));
314 place(1, 1, mResolutionDropDown, 2).setPadding(2);
315 place(0, 2, new Label(_("Scale:")));
316 place(1, 2, mScaleDropDown, 2).setPadding(2);
317 place(0, 3, mVSyncCheckBox, 4);
318 place(0, 4, mOpenGLCheckBox, 4);
319
320 place = getPlacer(0, 1);
322
323 place(0, 0, new Spacer(), 4);
324 place(0, 1, mCustomCursorCheckBox, 4);
325 place(0, 2, mDisableSDLTransparencyCheckBox, 4);
326
327 place(0, 3, mFpsCheckBox);
328 place(1, 3, mFpsSlider, 2).setVAlign(LayoutCell::CENTER);
329 place(3, 3, mFpsLabel);
330
331 place(0, 4, mParticleEffectsCheckBox, 4);
332
333 place(0, 5, particleDetailLabel);
334 place(1, 5, mParticleDetailSlider, 2).setVAlign(LayoutCell::CENTER);
335 place(3, 5, mParticleDetailField);
336
337 place(0, 6, overlayDetailLabel);
338 place(1, 6, mOverlayDetailSlider, 2).setVAlign(LayoutCell::CENTER);
339 place(3, 6, mOverlayDetailField);
340}
341
342Setup_Video::~Setup_Video() = default;
343
345{
346 // Video mode changes
347 auto &video = Client::getVideo();
348 mVideoSettings = video.settings();
349
350 mVideoSettings.windowMode = static_cast<WindowMode>(mWindowModeDropDown->getSelected());
351
352 if (mResolutionDropDown->getSelected() > 0)
353 {
354 const auto &mode = mResolutionListModel->getModeAt(mResolutionDropDown->getSelected());
355 mVideoSettings.width = mode.width;
356 mVideoSettings.height = mode.height;
357 }
358
359 mVideoSettings.userScale = std::max(0, mScaleDropDown->getSelected());
360 mVideoSettings.vsync = mVSyncCheckBox->isSelected();
361
362 if (video.apply(mVideoSettings))
363 {
369
371 }
372 else
373 {
374 new OkDialog(_("Error"), _("Failed to change video mode."));
375 }
376
377 // OpenGL change
378 if (mOpenGLCheckBox->isSelected() != mVideoSettings.openGL)
379 {
380 config.opengl = mOpenGLCheckBox->isSelected();
381
382 // OpenGL can currently only be changed by restarting, notify user.
383 if (mOpenGLCheckBox->isSelected())
384 {
385 new OkDialog(_("Changing to OpenGL"),
386 _("Applying change to OpenGL requires restart.\n\n"
387 "In case OpenGL messes up your game graphics, "
388 "restart the game with the command line option "
389 "\"--no-opengl\"."));
390 }
391 else
392 {
393 new OkDialog(_("Deactivating OpenGL"),
394 _("Applying change to OpenGL requires restart."));
395 }
396 }
397 // If LowCPU is enabled from a disabled state we warn the user
398 else if (mDisableSDLTransparencyCheckBox->isSelected())
399 {
401 {
402 new OkDialog(_("Transparency disabled"),
403 _("You must restart to apply changes."));
404 }
405 }
406 else
407 {
409 {
410 new OkDialog(_("Transparency enabled"),
411 _("You must restart to apply changes."));
412 }
413 }
415
416 mFps = mFpsCheckBox->isSelected() ? (int) mFpsSlider->getValue() : 0;
417 mFpsSlider->setEnabled(mFps > 0);
418
419 // FPS change
421
422 // We sync old and new values at apply time
430}
431
461
462void Setup_Video::action(const gcn::ActionEvent &event)
463{
464 const std::string &id = event.getId();
465
466 if (id == "windowmode" || id == "resolution")
467 {
468 auto windowMode = static_cast<WindowMode>(mWindowModeDropDown->getSelected());
469
470 // When the window mode is "windowed fullscreen" we should select the
471 // desktop resolution and disable the option to change it
472 if (windowMode == WindowMode::WindowedFullscreen)
473 {
474 const auto &desktop = Client::getVideo().desktopDisplayMode();
475 mResolutionDropDown->setSelected(
476 mResolutionListModel->getIndexOf(desktop.width, desktop.height));
477 mResolutionDropDown->setEnabled(false);
478 }
479 else
480 {
481 mResolutionDropDown->setEnabled(true);
482 }
483
485 }
486 else if (id == "resolution")
487 {
489 }
490 else if (id == "customcursor")
491 {
493 }
494 else if (id == "particleeffects")
495 {
498
499 if (Game::instance())
500 {
501 new OkDialog(_("Particle Effect Settings Changed."),
502 _("Changes will take effect on map change."));
503 }
504 }
505 else if (id == "overlaydetailslider")
506 {
507 int val = (int) mOverlayDetailSlider->getValue();
508 mOverlayDetailField->setCaption(overlayDetailToString(val));
509 config.overlayDetail = val;
510 }
511 else if (id == "particledetailslider")
512 {
513 int val = (int) mParticleDetailSlider->getValue();
514 mParticleDetailField->setCaption(particleDetailToString(val));
515 config.particleEmitterSkip = 3 - val;
516 Particle::emitterSkip = 4 - val;
517 }
518 else if (id == "fpslimitcheckbox" || id == "fpslimitslider")
519 {
520 int fps = (int) mFpsSlider->getValue();
521 fps = fps > 0 ? fps : mFpsSlider->getScaleStart();
522 mFps = mFpsCheckBox->isSelected() ? fps : 0;
523 const std::string text = mFps > 0 ? toString(mFps) : _("None");
524
525 mFpsLabel->setCaption(text);
526 mFpsSlider->setValue(mFps);
527 mFpsSlider->setEnabled(mFps > 0);
528 }
529 else if (id == "opengl" || id == "disableTransparency")
530 {
531 // Disable transparency disabling when in OpenGL.
532 if (mOpenGLCheckBox->isSelected())
533 {
534 mDisableSDLTransparencyCheckBox->setSelected(false);
535 mDisableSDLTransparencyCheckBox->setEnabled(false);
536 }
537 else
538 {
539 mDisableSDLTransparencyCheckBox->setEnabled(true);
540 }
541 }
542}
543
545{
546 if (mResolutionDropDown->getSelected() > 0)
547 {
548 const auto &mode = mResolutionListModel->getModeAt(mResolutionDropDown->getSelected());
549 mVideoSettings.width = mode.width;
550 mVideoSettings.height = mode.height;
551 }
552 else
553 {
554 auto &videoSettings = Client::getVideo().settings();
555 mVideoSettings.width = videoSettings.width;
556 mVideoSettings.height = videoSettings.height;
557 }
558
559 mScaleListModel->setVideoSettings(mVideoSettings);
562}
Check box widget.
Definition checkbox.h:32
The core part of the client.
Definition client.h:113
void checkGraphicsSize()
Definition client.cpp:1253
static Video & getVideo()
Definition client.h:187
static Client * instance()
Provides access to the client instance.
Definition client.h:149
This class is a helper for adding widgets to nested tables in a window.
Definition layout.h:34
LayoutCell & getCell()
Gets the pointed cell.
Definition layout.h:43
A drop down box from which you can select different values.
Definition dropdown.h:34
void adjustHeight()
Definition dropdown.cpp:111
static Game * instance()
Provides access to the game instance.
Definition game.h:53
Label widget.
Definition label.h:34
LayoutCell & setHAlign(Alignment a)
Sets the horizontal alignment of the cell content.
Definition layout.h:185
An 'Ok' button dialog.
Definition okdialog.h:34
static int emitterSkip
Duration of pause between two emitter updates in ticks.
Definition particle.h:58
static bool enabled
true when non-crucial particle effects are disabled
Definition particle.h:59
The list model for mode list.
int getNumberOfElements() override
std::string getElementAt(int i) override
const DisplayMode & getModeAt(int i) const
std::vector< DisplayMode > mDisplayModes
int getIndexOf(int width, int height) const
Returns the index corresponding to the given video resolution or 0 ("Custom") if not found.
The list model for choosing the scale.
void setVideoSettings(const VideoSettings &videoSettings)
int getNumberOfElements() override
std::string getElementAt(int i) override
VideoSettings mVideoSettings
ScaleListModel(const VideoSettings &videoSettings)
std::unique_ptr< ResolutionListModel > mResolutionListModel
Definition setup_video.h:58
bool mSDLTransparencyDisabled
Definition setup_video.h:55
gcn::CheckBox * mCustomCursorCheckBox
Definition setup_video.h:66
gcn::DropDown * mWindowModeDropDown
Definition setup_video.h:61
bool mParticleEffectsEnabled
Definition setup_video.h:53
gcn::Slider * mFpsSlider
Definition setup_video.h:70
void apply() override
Called when the Apply button is pressed in the setup window.
void cancel() override
Called when the Cancel button is pressed in the setup window.
gcn::DropDown * mResolutionDropDown
Definition setup_video.h:62
VideoSettings mVideoSettings
Definition setup_video.h:51
int mParticleDetail
Definition setup_video.h:77
gcn::Slider * mParticleDetailSlider
Definition setup_video.h:78
std::unique_ptr< ScaleListModel > mScaleListModel
Definition setup_video.h:59
gcn::CheckBox * mOpenGLCheckBox
Definition setup_video.h:65
gcn::Slider * mOverlayDetailSlider
Definition setup_video.h:74
DropDown * mScaleDropDown
Definition setup_video.h:63
void action(const gcn::ActionEvent &event) override
gcn::CheckBox * mParticleEffectsCheckBox
Definition setup_video.h:67
gcn::Label * mParticleDetailField
Definition setup_video.h:79
gcn::Label * mOverlayDetailField
Definition setup_video.h:75
gcn::CheckBox * mVSyncCheckBox
Definition setup_video.h:64
gcn::Label * mFpsLabel
Definition setup_video.h:71
gcn::CheckBox * mDisableSDLTransparencyCheckBox
Definition setup_video.h:81
~Setup_Video() override
void refreshScaleList()
int mOverlayDetail
Definition setup_video.h:73
gcn::CheckBox * mFpsCheckBox
Definition setup_video.h:69
bool mCustomCursorEnabled
Definition setup_video.h:52
Slider widget.
Definition slider.h:32
A space.
Definition spacer.h:33
A list model for a given list of strings.
StringListModel(std::vector< std::string > strings)
const std::vector< std::string > mStrings
std::string getElementAt(int i) override
int getNumberOfElements() override
const std::vector< DisplayMode > & displayModes() const
Definition video.h:106
const VideoSettings & settings() const
Definition video.h:77
const DisplayMode & desktopDisplayMode() const
Definition video.h:101
Config config
Global settings (config.xml)
Definition client.cpp:97
volatile int fps
Frames counted in the last second.
Definition client.cpp:111
void setConfigValue(T Config::*member, const T &value)
Sets the given Config member and sends a change event.
#define _(s)
Definition gettext.h:38
std::string strprintf(char const *format,...)
A safe version of sprintf that returns a std::string of the result.
std::string toString(const T &arg)
Converts the given value to a string using std::stringstream.
Definition stringutils.h:68
bool opengl
int screenWidth
bool customCursor
int overlayDetail
bool particleEffects
WindowMode windowMode
int screenHeight
bool disableTransparency
int particleEmitterSkip
WindowMode windowMode
Definition video.h:47
bool vsync
Definition video.h:52
int height
Definition video.h:49
bool openGL
Definition video.h:53
int maxScale() const
Definition video.cpp:51
int width
Definition video.h:48
int userScale
Definition video.h:51
int autoScale() const
Definition video.cpp:45
WindowMode
Definition video.h:33
@ WindowedFullscreen