diff options
Diffstat (limited to 'src/gui/widgets/tabs/setup_video.cpp')
-rw-r--r-- | src/gui/widgets/tabs/setup_video.cpp | 576 |
1 files changed, 576 insertions, 0 deletions
diff --git a/src/gui/widgets/tabs/setup_video.cpp b/src/gui/widgets/tabs/setup_video.cpp new file mode 100644 index 000000000..bd53763cc --- /dev/null +++ b/src/gui/widgets/tabs/setup_video.cpp @@ -0,0 +1,576 @@ +/* + * The ManaPlus Client + * Copyright (C) 2004-2009 The Mana World Development Team + * Copyright (C) 2009-2010 The Mana Developers + * Copyright (C) 2011-2013 The ManaPlus Developers + * + * This file is part of The ManaPlus Client. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include "gui/widgets/tabs/setup_video.h" + +#include "client.h" +#include "configuration.h" + +#include "graphicsmanager.h" + +#include "gui/windows/okdialog.h" +#include "gui/windows/textdialog.h" + +#include "gui/widgets/button.h" +#include "gui/widgets/checkbox.h" +#include "gui/widgets/label.h" +#include "gui/widgets/layouthelper.h" +#include "gui/widgets/listbox.h" +#include "gui/widgets/scrollarea.h" +#include "gui/widgets/slider.h" +#include "gui/widgets/dropdown.h" + +#include "render/rendererslistsdl.h" + +#include "utils/gettext.h" +#include "utils/sdlhelper.h" + +#include "test/testmain.h" + +#include <guichan/listmodel.hpp> + +#include <algorithm> + +#include "debug.h" + +extern Graphics *mainGraphics; + +class ModeListModel final : public gcn::ListModel +{ + public: + ModeListModel(); + + A_DELETE_COPY(ModeListModel) + + ~ModeListModel() + { } + + /** + * Returns the number of elements in container. + */ + int getNumberOfElements() override + { return static_cast<int>(mVideoModes.size()); } + + /** + * Returns element from container. + */ + std::string getElementAt(int i) + { return mVideoModes[i]; } + + /** + * Returns the index corresponding to the given video mode. + * E.g.: "800x600". + * or -1 if not found. + */ + int getIndexOf(const std::string &widthXHeightMode); + + private: + void addCustomMode(const std::string &mode); + + StringVect mVideoModes; +}; + +#ifndef ANDROID +static bool modeSorter(const std::string &mode1, const std::string &mode2) +{ + const int width1 = atoi(mode1.substr(0, mode1.find("x")).c_str()); + const int height1 = atoi(mode1.substr(mode1.find("x") + 1).c_str()); + if (!width1 || !height1) + return false; + + const int width2 = atoi(mode2.substr(0, mode2.find("x")).c_str()); + const int height2 = atoi(mode2.substr(mode2.find("x") + 1).c_str()); + if (!width2 || !height2) + return false; + if (width1 != width2) + return width1 < width2; + + if (height1 != height2) + return height1 < height2; + + return false; +} +#endif + +ModeListModel::ModeListModel() : + mVideoModes() +{ + SDL::getAllVideoModes(mVideoModes); +#ifndef ANDROID + addCustomMode("640x480"); + addCustomMode("800x600"); + addCustomMode("1024x768"); + addCustomMode("1280x1024"); + addCustomMode("1400x900"); + addCustomMode("1500x990"); + addCustomMode(toString(mainGraphics->mWidth).append("x") + .append(toString(mainGraphics->mHeight))); + + std::sort(mVideoModes.begin(), mVideoModes.end(), modeSorter); + mVideoModes.push_back("custom"); +#endif +} + +void ModeListModel::addCustomMode(const std::string &mode) +{ + StringVectCIter it = mVideoModes.begin(); + const StringVectCIter it_end = mVideoModes.end(); + while (it != it_end) + { + if (*it == mode) + return; + ++ it; + } + mVideoModes.push_back(mode); +} + +int ModeListModel::getIndexOf(const std::string &widthXHeightMode) +{ + std::string currentMode(""); + for (int i = 0; i < getNumberOfElements(); i++) + { + currentMode = getElementAt(i); + if (currentMode == widthXHeightMode) + return i; + } + return -1; +} + +class OpenGLListModel final : public gcn::ListModel +{ +public: + ~OpenGLListModel() + { } + + int getNumberOfElements() override + { return renderModesListSize; } + + std::string getElementAt(int i) override + { + if (i >= getNumberOfElements() || i < 0) + return "???"; + return gettext(OPENGL_NAME[i]); + } +}; + +Setup_Video::Setup_Video(const Widget2 *const widget) : + SetupTab(widget), + gcn::KeyListener(), + mFullScreenEnabled(config.getBoolValue("screen")), + mOpenGLEnabled(intToRenderType(config.getIntValue("opengl"))), + mFps(config.getIntValue("fpslimit")), + mAltFps(config.getIntValue("altfpslimit")), + mModeListModel(new ModeListModel), + mOpenGLListModel(new OpenGLListModel), + mModeList(new ListBox(widget, mModeListModel, "")), + // TRANSLATORS: video settings checkbox + mFsCheckBox(new CheckBox(this, _("Full screen"), mFullScreenEnabled)), + mOpenGLDropDown(new DropDown(widget, mOpenGLListModel)), + // TRANSLATORS: video settings checkbox + mFpsCheckBox(new CheckBox(this, _("FPS limit:"))), + mFpsSlider(new Slider(2, 160)), + mFpsLabel(new Label(this)), + mAltFpsSlider(new Slider(2, 160)), + // TRANSLATORS: video settings label + mAltFpsLabel(new Label(this, _("Alt FPS limit: "))), +#if !defined(ANDROID) && !defined(__APPLE__) + // TRANSLATORS: video settings button + mDetectButton(new Button(this, _("Detect best mode"), "detect", this)), +#endif + mDialog(nullptr), + mCustomCursorEnabled(config.getBoolValue("customcursor")), + mEnableResize(config.getBoolValue("enableresize")), + mNoFrame(config.getBoolValue("noframe")), + mCustomCursorCheckBox(new CheckBox(this, +#ifdef ANDROID + // TRANSLATORS: video settings checkbox + _("Show cursor"), +#else + // TRANSLATORS: video settings checkbox + _("Custom cursor"), +#endif + mCustomCursorEnabled)), + // TRANSLATORS: video settings checkbox + mEnableResizeCheckBox(new CheckBox(this, _("Enable resize"), + mEnableResize)), + // TRANSLATORS: video settings checkbox + mNoFrameCheckBox(new CheckBox(this, _("No frame"), mNoFrame)) +{ + // TRANSLATORS: video settings tab name + setName(_("Video")); + + ScrollArea *const scrollArea = new ScrollArea(mModeList, + true, "setup_video_background.xml"); + scrollArea->setWidth(150); + scrollArea->setHorizontalScrollPolicy(gcn::ScrollArea::SHOW_NEVER); + + mOpenGLDropDown->setSelected(renderToIndex[mOpenGLEnabled]); + + mModeList->setEnabled(true); + + // TRANSLATORS: video settings label + mFpsLabel->setCaption(mFps > 0 ? toString(mFps) : _("None")); + mFpsLabel->setWidth(60); + // TRANSLATORS: video settings label + mAltFpsLabel->setCaption(_("Alt FPS limit: ") + (mAltFps > 0 + ? toString(mAltFps) : _("None"))); + mAltFpsLabel->setWidth(150); + mFpsSlider->setValue(mFps); + mFpsSlider->setEnabled(mFps > 0); + mAltFpsSlider->setValue(mAltFps); + mAltFpsSlider->setEnabled(mAltFps > 0); + mFpsCheckBox->setSelected(mFps > 0); + + // Pre-select the current video mode. + const std::string videoMode = toString(mainGraphics->mWidth).append("x") + .append(toString(mainGraphics->mHeight)); + mModeList->setSelected(mModeListModel->getIndexOf(videoMode)); + + mModeList->setActionEventId("videomode"); + mCustomCursorCheckBox->setActionEventId("customcursor"); + mFpsCheckBox->setActionEventId("fpslimitcheckbox"); + mFpsSlider->setActionEventId("fpslimitslider"); + mAltFpsSlider->setActionEventId("altfpslimitslider"); + mOpenGLDropDown->setActionEventId("opengl"); + mEnableResizeCheckBox->setActionEventId("enableresize"); + mNoFrameCheckBox->setActionEventId("noframe"); + + mModeList->addActionListener(this); + mCustomCursorCheckBox->addActionListener(this); + mFpsCheckBox->addActionListener(this); + mFpsSlider->addActionListener(this); + mAltFpsSlider->addActionListener(this); + mOpenGLDropDown->addActionListener(this); + mEnableResizeCheckBox->addActionListener(this); + mNoFrameCheckBox->addActionListener(this); + + // Do the layout + LayoutHelper h(this); + ContainerPlacer place = h.getPlacer(0, 0); + + place(0, 0, scrollArea, 1, 5).setPadding(2); + place(0, 5, mOpenGLDropDown, 1); + + place(1, 0, mFsCheckBox, 2); + + place(1, 1, mCustomCursorCheckBox, 3); + + place(1, 2, mEnableResizeCheckBox, 2); + place(1, 3, mNoFrameCheckBox, 2); + + place(0, 6, mFpsSlider); + place(1, 6, mFpsCheckBox).setPadding(3); + place(2, 6, mFpsLabel).setPadding(1); + + place(0, 7, mAltFpsSlider); + place(1, 7, mAltFpsLabel).setPadding(3); + +#if !defined(ANDROID) && !defined(__APPLE__) + place(0, 8, mDetectButton); +#else + mNoFrameCheckBox->setEnabled(false); + mEnableResizeCheckBox->setEnabled(false); + mFsCheckBox->setEnabled(false); +#endif + + int width = 600; + + if (config.getIntValue("screenwidth") >= 730) + width += 100; + + setDimension(gcn::Rectangle(0, 0, width, 300)); +} + +Setup_Video::~Setup_Video() +{ + delete mModeListModel; + mModeListModel = nullptr; + delete mModeList; + mModeList = nullptr; + delete mOpenGLListModel; + mOpenGLListModel = nullptr; + delete mDialog; + mDialog = nullptr; +} + +void Setup_Video::apply() +{ + // Full screen changes + bool fullscreen = mFsCheckBox->isSelected(); + if (fullscreen != config.getBoolValue("screen")) + { + /* The OpenGL test is only necessary on Windows, since switching + * to/from full screen works fine on Linux. On Windows we'd have to + * reinitialize the OpenGL state and reload all textures. + * + * See http://libsdl.org/cgi/docwiki.cgi/SDL_SetVideoMode + */ + +#if defined(WIN32) || defined(__APPLE__) || defined(ANDROID) + // checks for opengl usage + if (intToRenderType(config.getIntValue("opengl")) == RENDER_SOFTWARE) + { +#endif + if (!mainGraphics->setFullscreen(fullscreen)) + { + fullscreen = !fullscreen; + if (!mainGraphics->setFullscreen(fullscreen)) + { + std::stringstream errorMsg; + if (fullscreen) + { + // TRANSLATORS: video error message + errorMsg << _("Failed to switch to windowed mode " + "and restoration of old mode also " + "failed!") << std::endl; + } + else + { + // TRANSLATORS: video error message + errorMsg << _("Failed to switch to fullscreen mode" + " and restoration of old mode also " + "failed!") << std::endl; + } + logger->safeError(errorMsg.str()); + } + } +#if defined(WIN32) || defined(__APPLE__) || defined(ANDROID) + } + else + { + // TRANSLATORS: video settings warning + new OkDialog(_("Switching to Full Screen"), + // TRANSLATORS: video settings warning + _("Restart needed for changes to take effect.")); + } +#endif + config.setValue("screen", fullscreen); + } + + const int sel = mOpenGLDropDown->getSelected(); + RenderType mode = RENDER_SOFTWARE; + if (sel >= 0 && static_cast<unsigned int>(sel) < sizeof(indexToRender)) + mode = indexToRender[mOpenGLDropDown->getSelected()]; + + // OpenGL change + if (mode != mOpenGLEnabled) + { + config.setValue("opengl", static_cast<int>(mode)); + + // OpenGL can currently only be changed by restarting, notify user. + // TRANSLATORS: video settings warning + new OkDialog(_("Changing to OpenGL"), + // TRANSLATORS: video settings warning + _("Applying change to OpenGL requires restart.")); + } + + mFps = mFpsCheckBox->isSelected() ? + static_cast<int>(mFpsSlider->getValue()) : 0; + + mAltFps = static_cast<int>(mAltFpsSlider->getValue()); + + mFpsSlider->setEnabled(mFps > 0); + + mAltFpsSlider->setEnabled(mAltFps > 0); + + // FPS change + config.setValue("fpslimit", mFps); + config.setValue("altfpslimit", mAltFps); + + // We sync old and new values at apply time + mFullScreenEnabled = config.getBoolValue("screen"); + mCustomCursorEnabled = config.getBoolValue("customcursor"); + + mOpenGLEnabled = intToRenderType(config.getIntValue("opengl")); + mEnableResize = config.getBoolValue("enableresize"); + mNoFrame = config.getBoolValue("noframe"); +} + +void Setup_Video::cancel() +{ + mFpsCheckBox->setSelected(mFps > 0); + mFsCheckBox->setSelected(mFullScreenEnabled); + mOpenGLDropDown->setSelected(renderToIndex[mOpenGLEnabled]); + mCustomCursorCheckBox->setSelected(mCustomCursorEnabled); + mFpsSlider->setValue(mFps); + mFpsSlider->setEnabled(mFps > 0); + mAltFpsSlider->setValue(mAltFps); + mAltFpsSlider->setEnabled(mAltFps > 0); + mFpsLabel->setCaption(mFpsCheckBox->isSelected() + // TRANSLATORS: video settings label + ? toString(mFps) : _("None")); + // TRANSLATORS: video settings label + mAltFpsLabel->setCaption(_("Alt FPS limit: ") + toString(mAltFps)); + mEnableResizeCheckBox->setSelected(mEnableResize); + mNoFrameCheckBox->setSelected(mNoFrame); + + config.setValue("screen", mFullScreenEnabled); + + // Set back to the current video mode. + std::string videoMode = toString(mainGraphics->mWidth).append("x") + .append(toString(mainGraphics->mHeight)); + mModeList->setSelected(mModeListModel->getIndexOf(videoMode)); + config.setValue("screenwidth", mainGraphics->mWidth); + config.setValue("screenheight", mainGraphics->mHeight); + + config.setValue("customcursor", mCustomCursorEnabled); + config.setValue("opengl", static_cast<int>(mOpenGLEnabled)); + config.setValue("enableresize", mEnableResize); + config.setValue("noframe", mNoFrame); +} + +void Setup_Video::action(const gcn::ActionEvent &event) +{ + const std::string &id = event.getId(); + + if (id == "videomode") + { + std::string mode = mModeListModel->getElementAt( + mModeList->getSelected()); + + if (mode == "custom") + { + if (mDialog) + { + mode = mDialog->getText(); + mDialog = nullptr; + } + else + { + mDialog = new TextDialog( + // TRANSLATORS: resolution question dialog + _("Custom resolution (example: 1024x768)"), + // TRANSLATORS: resolution question dialog + _("Enter new resolution: ")); + mDialog->setActionEventId("videomode"); + mDialog->addActionListener(this); + return; + } + } + const int width = atoi(mode.substr(0, mode.find("x")).c_str()); + const int height = atoi(mode.substr(mode.find("x") + 1).c_str()); + if (!width || !height) + return; + + if (width != mainGraphics->mWidth || height != mainGraphics->mHeight) + { +#if defined(WIN32) || defined(__APPLE__) || defined(ANDROID) + if (intToRenderType(config.getIntValue("opengl")) + == RENDER_SOFTWARE) + { + client->resizeVideo(width, height); + } + else + { + if (width < mainGraphics->mWidth + || height < mainGraphics->mHeight) + { + // TRANSLATORS: video settings warning + new OkDialog(_("Screen Resolution Changed"), + // TRANSLATORS: video settings warning + _("Restart your client for the change to take effect.") + + std::string("\n") + _("Some windows may be moved to " + "fit the lowered resolution.")); + } + else + { + // TRANSLATORS: video settings warning + new OkDialog(_("Screen Resolution Changed"), + // TRANSLATORS: video settings warning + _("Restart your client for the change" + " to take effect.")); + } + } +#else + mainGraphics->setWindowSize(width, height); + client->resizeVideo(width, height); +#endif + } + + config.setValue("oldscreen", config.getBoolValue("screen")); + config.setValue("oldscreenwidth", mainGraphics->mWidth); + config.setValue("oldscreenheight", mainGraphics->mHeight); + config.setValue("screenwidth", width); + config.setValue("screenheight", height); + } + if (id == "~videomode") + { + mDialog = nullptr; + } + else if (id == "customcursor") + { + config.setValue("customcursor", mCustomCursorCheckBox->isSelected()); + } + else if (id == "fpslimitcheckbox" || id == "fpslimitslider") + { + int tempFps = static_cast<int>(mFpsSlider->getValue()); + if (id == "fpslimitcheckbox" && !mFpsSlider->isEnabled()) + tempFps = 60; + else + tempFps = tempFps > 0 ? tempFps : 60; + mFps = mFpsCheckBox->isSelected() ? tempFps : 0; + // TRANSLATORS: video settings label + const std::string text = mFps > 0 ? toString(mFps) : _("None"); + + mFpsLabel->setCaption(text); + mFpsSlider->setValue(mFps); + mFpsSlider->setEnabled(mFps > 0); + } + else if (id == "altfpslimitslider") + { + int tempFps = static_cast<int>(mAltFpsSlider->getValue()); + tempFps = tempFps > 0 ? tempFps : static_cast<int>( + mAltFpsSlider->getScaleStart()); + mAltFps = tempFps; + // TRANSLATORS: video settings label + const std::string text = mAltFps > 0 ? toString(mAltFps) : _("None"); + + // TRANSLATORS: video settings label + mAltFpsLabel->setCaption(_("Alt FPS limit: ") + text); + mAltFpsSlider->setValue(mAltFps); + mAltFpsSlider->setEnabled(mAltFps > 0); + } + else if (id == "enableresize") + { + config.setValue("enableresize", mEnableResizeCheckBox->isSelected()); + } + else if (id == "noframe") + { + config.setValue("noframe", mNoFrameCheckBox->isSelected()); + } +#if defined(USE_OPENGL) && !defined(ANDROID) && !defined(__APPLE__) + else if (id == "detect") + { + TestMain *test = graphicsManager.startDetection(); + if (test) + { + const int val = test->getConfig().getValueInt("opengl", -1); + if (val >= 0 && static_cast<unsigned int>(val) + < sizeof(renderToIndex) / sizeof(int)) + { + mOpenGLDropDown->setSelected(renderToIndex[val]); + } + delete test; + } + } +#endif +} |