summaryrefslogtreecommitdiff
path: root/src/gui
diff options
context:
space:
mode:
authorThorbjørn Lindeijer <bjorn@lindeijer.nl>2024-03-05 10:21:43 +0100
committerThorbjørn Lindeijer <bjorn@lindeijer.nl>2024-03-22 20:26:26 +0100
commita06db62288bc3fdbf3f25bcfa046c20510036665 (patch)
tree5ad510ebc223364f8d8f59f84d5bb8081a2822b1 /src/gui
parent944b99f3a2e87a080666174dc1e2e2b543519904 (diff)
downloadmana-a06db62288bc3fdbf3f25bcfa046c20510036665.tar.gz
mana-a06db62288bc3fdbf3f25bcfa046c20510036665.tar.bz2
mana-a06db62288bc3fdbf3f25bcfa046c20510036665.tar.xz
mana-a06db62288bc3fdbf3f25bcfa046c20510036665.zip
Added support for scaling the output
* Added "Scale" user option, which can either by "Auto" or an explicit scaling factor. Its maximum value depends on the current resolution. The "Auto" factor is based on keeping the logical resolution on at least 800x600, wheres the maximum scale is based on keeping the logical resolution on at least 640x480. * Enabled support for High DPI. This means the rendering target can now have a different resolution than the window size, which can happen on macOS, Windows and Wayland. The resulting scale is multiplied by the above user-controlled scale. Currently, this looks ugly for non-integer scales, which are not used on macOS and can only be configured on some Wayland compositors. Has not been tested on Windows. * Simplified OpenGL initialization (moved out of _beginDraw). * Made sure _beginDraw/_endDraw sets a clip area also for SDLGraphics.
Diffstat (limited to 'src/gui')
-rw-r--r--src/gui/equipmentwindow.cpp3
-rw-r--r--src/gui/gui.cpp21
-rw-r--r--src/gui/sdlinput.cpp25
-rw-r--r--src/gui/setup_video.cpp106
-rw-r--r--src/gui/setup_video.h5
-rw-r--r--src/gui/viewport.cpp19
6 files changed, 135 insertions, 44 deletions
diff --git a/src/gui/equipmentwindow.cpp b/src/gui/equipmentwindow.cpp
index 45f3dcd1..e6230aed 100644
--- a/src/gui/equipmentwindow.cpp
+++ b/src/gui/equipmentwindow.cpp
@@ -246,9 +246,6 @@ void EquipmentWindow::mouseMoved(gcn::MouseEvent &event)
const int x = event.getX();
const int y = event.getY();
- int mouseX, mouseY;
- SDL_GetMouseState(&mouseX, &mouseY);
-
// Show ItemTooltip
std::string slotName = getSlotName(x, y);
if (!slotName.empty())
diff --git a/src/gui/gui.cpp b/src/gui/gui.cpp
index 2d470a3e..62350f99 100644
--- a/src/gui/gui.cpp
+++ b/src/gui/gui.cpp
@@ -193,11 +193,18 @@ void Gui::logic()
void Gui::draw()
{
- mGraphics->pushClipArea(getTop()->getDimension());
- getTop()->draw(mGraphics);
+ mGraphics->_beginDraw();
- int mouseX, mouseY;
+ mGraphics->pushClipArea(mTop->getDimension());
+ mTop->draw(mGraphics);
+ mGraphics->popClipArea();
+
+ int mouseX;
+ int mouseY;
Uint8 button = SDL_GetMouseState(&mouseX, &mouseY);
+ float logicalX;
+ float logicalY;
+ graphics->windowToLogical(mouseX, mouseY, logicalX, logicalY);
if ((Client::hasMouseFocus() || button & SDL_BUTTON(1))
&& mCustomCursor
@@ -208,11 +215,11 @@ void Gui::draw()
static_cast<Graphics*>(mGraphics)->drawImage(
mouseCursor,
- mouseX - 15,
- mouseY - 17);
+ logicalX - 15,
+ logicalY - 17);
}
- mGraphics->popClipArea();
+ mGraphics->_endDraw();
}
void Gui::videoResized(int width, int height)
@@ -221,6 +228,8 @@ void Gui::videoResized(int width, int height)
int oldWidth = top->getWidth();
int oldHeight = top->getHeight();
+ if (oldWidth == width && oldHeight == height)
+ return;
top->setSize(width, height);
top->adjustAfterResize(oldWidth, oldHeight);
diff --git a/src/gui/sdlinput.cpp b/src/gui/sdlinput.cpp
index 8396418c..3c8e3ecc 100644
--- a/src/gui/sdlinput.cpp
+++ b/src/gui/sdlinput.cpp
@@ -57,6 +57,7 @@
*/
#include "sdlinput.h"
+#include "graphics.h"
#include <guichan/exception.hpp>
@@ -119,6 +120,15 @@ TextInput SDLInput::dequeueTextInput()
return textInput;
}
+static void setMouseCoordinates(gcn::MouseInput &mouseInput, int x, int y)
+{
+ float logicalX;
+ float logicalY;
+ graphics->windowToLogical(x, y, logicalX, logicalY);
+ mouseInput.setX(static_cast<int>(logicalX));
+ mouseInput.setY(static_cast<int>(logicalY));
+}
+
void SDLInput::pushInput(SDL_Event event)
{
gcn::KeyInput keyInput;
@@ -154,8 +164,7 @@ void SDLInput::pushInput(SDL_Event event)
case SDL_MOUSEBUTTONDOWN:
mMouseDown = true;
- mouseInput.setX(event.button.x);
- mouseInput.setY(event.button.y);
+ setMouseCoordinates(mouseInput, event.button.x, event.button.y);
mouseInput.setButton(convertMouseButton(event.button.button));
mouseInput.setType(gcn::MouseInput::PRESSED);
mouseInput.setTimeStamp(SDL_GetTicks());
@@ -164,8 +173,7 @@ void SDLInput::pushInput(SDL_Event event)
case SDL_MOUSEBUTTONUP:
mMouseDown = false;
- mouseInput.setX(event.button.x);
- mouseInput.setY(event.button.y);
+ setMouseCoordinates(mouseInput, event.button.x, event.button.y);
mouseInput.setButton(convertMouseButton(event.button.button));
mouseInput.setType(gcn::MouseInput::RELEASED);
mouseInput.setTimeStamp(SDL_GetTicks());
@@ -173,8 +181,7 @@ void SDLInput::pushInput(SDL_Event event)
break;
case SDL_MOUSEMOTION:
- mouseInput.setX(event.button.x);
- mouseInput.setY(event.button.y);
+ setMouseCoordinates(mouseInput, event.button.x, event.button.y);
mouseInput.setButton(gcn::MouseInput::EMPTY);
mouseInput.setType(gcn::MouseInput::MOVED);
mouseInput.setTimeStamp(SDL_GetTicks());
@@ -184,13 +191,11 @@ void SDLInput::pushInput(SDL_Event event)
case SDL_MOUSEWHEEL:
if (event.wheel.y) {
#if SDL_VERSION_ATLEAST(2, 26, 0)
- mouseInput.setX(event.wheel.mouseX);
- mouseInput.setY(event.wheel.mouseY);
+ setMouseCoordinates(mouseInput, event.wheel.mouseX, event.wheel.mouseY);
#else
int x, y;
SDL_GetMouseState(&x, &y);
- mouseInput.setX(x);
- mouseInput.setY(y);
+ setMouseCoordinates(mouseInput, x, y);
#endif
mouseInput.setButton(gcn::MouseInput::EMPTY);
mouseInput.setType(event.wheel.y > 0 ? gcn::MouseInput::WHEEL_MOVED_UP
diff --git a/src/gui/setup_video.cpp b/src/gui/setup_video.cpp
index 6f2f0d26..21f1935a 100644
--- a/src/gui/setup_video.cpp
+++ b/src/gui/setup_video.cpp
@@ -148,6 +148,40 @@ private:
std::vector<DisplayMode> mDisplayModes;
};
+/**
+ * The list model for choosing the scale.
+ *
+ * \ingroup Interface
+ */
+class ScaleListModel : public gcn::ListModel
+{
+public:
+ ScaleListModel(const VideoSettings &videoSettings)
+ : mVideoSettings(videoSettings)
+ {}
+
+ void setVideoSettings(const VideoSettings &videoSettings)
+ {
+ mVideoSettings = videoSettings;
+ }
+
+ int getNumberOfElements() override
+ {
+ return mVideoSettings.maxScale() + 1;
+ }
+
+ std::string getElementAt(int i) override
+ {
+ if (i == 0)
+ return strprintf(_("Auto (%dx)"), mVideoSettings.autoScale());
+
+ return strprintf(_("%dx"), i);
+ }
+
+private:
+ VideoSettings mVideoSettings;
+};
+
static const char *overlayDetailToString(int detail)
{
@@ -186,8 +220,10 @@ Setup_Video::Setup_Video():
mSDLTransparencyDisabled(config.getBoolValue("disableTransparency")),
mWindowModeListModel(new StringListModel({ _("Windowed"), _("Windowed Fullscreen"), _("Fullscreen") })),
mResolutionListModel(new ResolutionListModel),
+ mScaleListModel(new ScaleListModel(mVideoSettings)),
mWindowModeDropDown(new DropDown(mWindowModeListModel.get())),
mResolutionDropDown(new DropDown(mResolutionListModel.get())),
+ mScaleDropDown(new DropDown(mScaleListModel.get())),
mVSyncCheckBox(new CheckBox(_("VSync"), mVideoSettings.vsync)),
mOpenGLCheckBox(new CheckBox(_("OpenGL (Legacy)"), mVideoSettings.openGL)),
mCustomCursorCheckBox(new CheckBox(_("Custom cursor"), mCustomCursorEnabled)),
@@ -232,9 +268,11 @@ Setup_Video::Setup_Video():
mResolutionDropDown->setSelected(mResolutionListModel->getIndexOf(mVideoSettings.width,
mVideoSettings.height));
mResolutionDropDown->setEnabled(mVideoSettings.windowMode != WindowMode::WindowedFullscreen);
+ mScaleDropDown->setSelected(mVideoSettings.userScale);
// Set actions
mWindowModeDropDown->setActionEventId("windowmode");
+ mResolutionDropDown->setActionEventId("resolution");
mCustomCursorCheckBox->setActionEventId("customcursor");
mParticleEffectsCheckBox->setActionEventId("particleeffects");
mDisableSDLTransparencyCheckBox->setActionEventId("disableTransparency");
@@ -248,6 +286,7 @@ Setup_Video::Setup_Video():
// Set listeners
mWindowModeDropDown->addActionListener(this);
+ mResolutionDropDown->addActionListener(this);
mCustomCursorCheckBox->addActionListener(this);
mOpenGLCheckBox->addActionListener(this);
mParticleEffectsCheckBox->addActionListener(this);
@@ -270,11 +309,13 @@ Setup_Video::Setup_Video():
place.getCell().setHAlign(LayoutCell::FILL);
place(0, 0, new Label(_("Window mode:")));
- place(1, 0, mWindowModeDropDown, 2);
+ place(1, 0, mWindowModeDropDown, 2).setPadding(2);
place(0, 1, new Label(_("Resolution:")));
- place(1, 1, mResolutionDropDown, 2);
- place(0, 2, mVSyncCheckBox, 4);
- place(0, 3, mOpenGLCheckBox, 4);
+ place(1, 1, mResolutionDropDown, 2).setPadding(2);
+ place(0, 2, new Label(_("Scale:")));
+ place(1, 2, mScaleDropDown, 2).setPadding(2);
+ place(0, 3, mVSyncCheckBox, 4);
+ place(0, 4, mOpenGLCheckBox, 4);
place = getPlacer(0, 1);
place.getCell().setHAlign(LayoutCell::FILL);
@@ -304,24 +345,29 @@ void Setup_Video::apply()
{
// Video mode changes
auto &video = Client::getVideo();
- auto videoSettings = video.settings();
+ mVideoSettings = video.settings();
+
+ mVideoSettings.windowMode = static_cast<WindowMode>(mWindowModeDropDown->getSelected());
if (mResolutionDropDown->getSelected() > 0)
{
const auto &mode = mResolutionListModel->getModeAt(mResolutionDropDown->getSelected());
- videoSettings.width = mode.width;
- videoSettings.height = mode.height;
+ mVideoSettings.width = mode.width;
+ mVideoSettings.height = mode.height;
}
- videoSettings.windowMode = static_cast<WindowMode>(mWindowModeDropDown->getSelected());
- videoSettings.vsync = mVSyncCheckBox->isSelected();
+ mVideoSettings.userScale = std::max(0, mScaleDropDown->getSelected());
+ mVideoSettings.vsync = mVSyncCheckBox->isSelected();
- if (video.apply(videoSettings))
+ if (video.apply(mVideoSettings))
{
- config.setValue("windowmode", static_cast<int>(videoSettings.windowMode));
- config.setValue("vsync", videoSettings.vsync);
- config.setValue("screenwidth", videoSettings.width);
- config.setValue("screenheight", videoSettings.height);
+ config.setValue("windowmode", static_cast<int>(mVideoSettings.windowMode));
+ config.setValue("scale", mVideoSettings.userScale);
+ config.setValue("vsync", mVideoSettings.vsync);
+ config.setValue("screenwidth", mVideoSettings.width);
+ config.setValue("screenheight", mVideoSettings.height);
+
+ Client::instance()->checkGraphicsSize();
}
else
{
@@ -387,9 +433,11 @@ void Setup_Video::apply()
void Setup_Video::cancel()
{
// Set back to the current video mode.
+ mVideoSettings = Client::getVideo().settings();
+ mWindowModeDropDown->setSelected(static_cast<int>(mVideoSettings.windowMode));
mResolutionDropDown->setSelected(mResolutionListModel->getIndexOf(mVideoSettings.width,
mVideoSettings.height));
-
+ mScaleDropDown->setSelected(mVideoSettings.userScale);
mVSyncCheckBox->setSelected(mVideoSettings.vsync);
mOpenGLCheckBox->setSelected(mVideoSettings.openGL);
mCustomCursorCheckBox->setSelected(mCustomCursorEnabled);
@@ -416,7 +464,7 @@ void Setup_Video::action(const gcn::ActionEvent &event)
{
const std::string &id = event.getId();
- if (id == "windowmode")
+ if (id == "windowmode" || id == "resolution")
{
auto windowMode = static_cast<WindowMode>(mWindowModeDropDown->getSelected());
@@ -433,6 +481,12 @@ void Setup_Video::action(const gcn::ActionEvent &event)
{
mResolutionDropDown->setEnabled(true);
}
+
+ refreshScaleList();
+ }
+ else if (id == "resolution")
+ {
+ refreshScaleList();
}
else if (id == "customcursor")
{
@@ -488,3 +542,23 @@ void Setup_Video::action(const gcn::ActionEvent &event)
}
}
}
+
+void Setup_Video::refreshScaleList()
+{
+ if (mResolutionDropDown->getSelected() > 0)
+ {
+ const auto &mode = mResolutionListModel->getModeAt(mResolutionDropDown->getSelected());
+ mVideoSettings.width = mode.width;
+ mVideoSettings.height = mode.height;
+ }
+ else
+ {
+ auto &videoSettings = Client::getVideo().settings();
+ mVideoSettings.width = videoSettings.width;
+ mVideoSettings.height = videoSettings.height;
+ }
+
+ mScaleListModel->setVideoSettings(mVideoSettings);
+ mScaleDropDown->setListModel(mScaleListModel.get());
+ mScaleDropDown->setSelected(mVideoSettings.userScale);
+}
diff --git a/src/gui/setup_video.h b/src/gui/setup_video.h
index d16f6d73..0914f6b1 100644
--- a/src/gui/setup_video.h
+++ b/src/gui/setup_video.h
@@ -31,6 +31,7 @@
#include <guichan/keylistener.hpp>
class ResolutionListModel;
+class ScaleListModel;
class Setup_Video : public SetupTab, public gcn::ActionListener,
public gcn::KeyListener
@@ -45,6 +46,8 @@ class Setup_Video : public SetupTab, public gcn::ActionListener,
void action(const gcn::ActionEvent &event) override;
private:
+ void refreshScaleList();
+
VideoSettings mVideoSettings;
bool mCustomCursorEnabled;
bool mParticleEffectsEnabled;
@@ -53,6 +56,7 @@ class Setup_Video : public SetupTab, public gcn::ActionListener,
std::unique_ptr<gcn::ListModel> mWindowModeListModel;
std::unique_ptr<ResolutionListModel> mResolutionListModel;
+ std::unique_ptr<ScaleListModel> mScaleListModel;
//gcn::Label *scrollRadiusLabel;
//gcn::Label *scrollLazinessLabel;
@@ -61,6 +65,7 @@ class Setup_Video : public SetupTab, public gcn::ActionListener,
gcn::DropDown *mWindowModeDropDown;
gcn::DropDown *mResolutionDropDown;
+ gcn::DropDown *mScaleDropDown;
gcn::CheckBox *mVSyncCheckBox;
gcn::CheckBox *mOpenGLCheckBox;
gcn::CheckBox *mCustomCursorCheckBox;
diff --git a/src/gui/viewport.cpp b/src/gui/viewport.cpp
index a31a65f6..b71e6530 100644
--- a/src/gui/viewport.cpp
+++ b/src/gui/viewport.cpp
@@ -39,14 +39,10 @@
#include "net/net.h"
#include "net/playerhandler.h"
-#include "resources/resourcemanager.h"
-
#include "utils/stringutils.h"
#include <cmath>
-extern volatile int tick_time;
-
Viewport::Viewport()
{
setOpaque(false);
@@ -81,8 +77,6 @@ void Viewport::setMap(Map *map)
mMap = map;
}
-extern MiniStatusWindow *miniStatusWindow;
-
void Viewport::draw(gcn::Graphics *gcnGraphics)
{
static int lastTick = tick_time;
@@ -291,7 +285,13 @@ void Viewport::logic()
void Viewport::_followMouse()
{
- Uint8 button = SDL_GetMouseState(&mMouseX, &mMouseY);
+ const Uint8 button = SDL_GetMouseState(&mMouseX, &mMouseY);
+ float logicalX;
+ float logicalY;
+ graphics->windowToLogical(mMouseX, mMouseY, logicalX, logicalY);
+ mMouseX = static_cast<int>(logicalX);
+ mMouseY = static_cast<int>(logicalY);
+
// If the left button is dragged
if (mPlayerFollowMouse && button & SDL_BUTTON(1))
{
@@ -459,7 +459,8 @@ void Viewport::mousePressed(gcn::MouseEvent &event)
mPopupMenu->showPopup(event.getX(), event.getY(), mHoverBeing);
return;
}
- else if (mHoverItem)
+
+ if (mHoverItem)
{
mPopupMenu->showPopup(event.getX(), event.getY(), mHoverItem);
return;
@@ -541,7 +542,7 @@ void Viewport::mouseDragged(gcn::MouseEvent &event)
{
mLocalWalkTime = tick_time;
local_player->setDestination(event.getX() + (int) mPixelViewX,
- event.getY() + (int) mPixelViewY);
+ event.getY() + (int) mPixelViewY);
local_player->pathSetByMouse();
}
}