fheroes2 icon indicating copy to clipboard operation
fheroes2 copied to clipboard

Add Screen Scaling Type to graphics settings dialog and Interface Type to the game settings dialog

Open Districh-ru opened this issue 5 months ago • 31 comments

Thanks to @PusshPop for the Linear/Nearest scaling icon!

This PR adds new settings:

  • Screen Scaling Type to the Graphics Settings dialog;
  • Interface Type to Game Settings dialog.

The parameter names, description texts and place in the dialog can be discussed.

The new Screen Scaling Type option must be tested on all supported platforms.

Districh-ru avatar Jul 06 '25 15:07 Districh-ru

@Districh-ru, nice job adding all of these. I was thinking if we should have the scaling filters and mouse rendering under the graphics settings? Consider that we're probably soon-ish going to add the numeric army estimate option too, then we could add that to the main options page? I'm talking about this one: image #9678 We would still need 1 more option to have 3 (gotta admit I don't like that we always have to add several options just to fit the grid), so for the last option maybe we could just add the battle mode button (quick, manual, spell casting etc.) to the main options page. What do you think?

EDIT: I guess it would also make sense to have the cursor rendering option under a sub menu for cursor settings, in which we would include the color/b&w setting.

zenseii avatar Jul 06 '25 15:07 zenseii

@ihhub and @zenseii, we can add a UI option for "numeric army estimate" in this PR after https://github.com/ihhub/fheroes2/pull/9678 is merged.

@zenseii First of all we need to test scaling type and cursor renderer options on different systems (PS Vita, Android, ...).

We can move the made options to the other dialog. It is not difficult. :) On the next days I'll move the options to the Graphics menu or to some other suitable place.

Making an extra dialog for two options sounds not good to me: a user has to make more clicks to get to the option ... but I'll give it a chance. :)

And IMHO we can make not all lines with 3 options, what do you think about the next approach: изображение

PS @zenseii could you please check the new added strings when you have time? We can move the items to the other place but the text will be the same.

Districh-ru avatar Jul 06 '25 16:07 Districh-ru

@Districh-ru, I agree about your sentiments about 2 options for cursor so we can drop that idea. My main concern is that the cursor rendering setting is so technical that having it on the main page of settings will confuse users, which means it might be better on the graphics page. Ideally we would not need an option for it but apply this whenever an integer or larger than 640x480 resolution is selected (?). But this is a much bigger discussion and not necessary here.

I think it looks good to have the grid you showed: xxx xxx x x

zenseii avatar Jul 06 '25 16:07 zenseii

Hi @Districh-ru please note that on devices with touchpad/touchscreen software-rendered mouse cursor is mandatory, because automatic conversion of mouse events to touch events and vice versa is disabled because we need to reliably distinguish between them. Please see the initTouchpad() in the engine/localevent.cpp. On these platforms, hardware mouse cursor is harmful and should never be enabled regardless of the config setting.

oleg-derevenetz avatar Jul 06 '25 22:07 oleg-derevenetz

Hi @Districh-ru please note that on devices with touchpad/touchscreen software-rendered mouse cursor is mandatory, because automatic conversion of mouse events to touch events and vice versa is disabled because we need to reliably distinguish between them. Please see the initTouchpad() in the engine/localevent.cpp. On these platforms, hardware mouse cursor is harmful and should never be enabled regardless of the config setting.

Thanks for the warning, @oleg-derevenetz!

But as I can see the cursor "software emulation" stays only for how to render it on the screen:

  • "hardware" - by using SDL cursor setting (SDL_SetCursor()) and rendering;
  • "software" - by rendering cursor sprite to the display image before calling _renderFrame() in render() method.

The events processing in localevent.cpp does not rely on cursor software emulation state, as I can see... but I might miss something important. I'll do some test in the evening on Android and PS Vita emulator.

Districh-ru avatar Jul 07 '25 08:07 Districh-ru

The events processing in localevent.cpp does not rely on cursor software emulation state, as I can see...

Please note the _mouseCursorPos and _globalMouseMotionEventHook in the LocalEvent. The latter effectively calls the Cursor::updateCursorPosition(), which moves the software mouse cursor to the correct position. Where do you think a "hardware mouse cursor" can come from in a device without a mouse? :) This could be (in theory) emulated by SDL to some extent... but the automatic translation of touch events to the mouse events is disabled (not to mention joysticks, for which this translation logic is not provided by SDL at all).

oleg-derevenetz avatar Jul 07 '25 08:07 oleg-derevenetz

Please note the _mouseCursorPos and _globalMouseMotionEventHook in the LocalEvent. The latter effectively calls the Cursor::updateCursorPosition(), which moves the software mouse cursor to the correct position. Where do you think a "hardware mouse cursor" can come from in a device without a mouse? :) This could be (in theory) emulated by SDL to some extent... but the automatic translation of touch events to the mouse events is disabled (not to mention joysticks, for which this translation logic is not provided by SDL at all).

You are absolutely right.

I guess for now we need to disable this option for systems with touchscreen by making it gray or simply not showing it.

Later we can think about if we can use SDL_WarpMouseInWindow() to set the hardware cursor position by touch or by gamepad controller.

Districh-ru avatar Jul 07 '25 12:07 Districh-ru

Later we can think about if we can use SDL_WarpMouseInWindow() to set the hardware cursor position by touch or by gamepad controller.

I strongly doubt that SDL_WarpMouseInWindow() will somehow help if there is actually no mouse in the system (and its driver is not running). Even in Windows, the system mouse cursor disappears completely when the mouse is disconnected from the USB port (at least in Windows 10, I just tested this). Which cursor will this function move in this case?

oleg-derevenetz avatar Jul 07 '25 12:07 oleg-derevenetz

I strongly doubt that SDL_WarpMouseInWindow() will somehow help if there is actually no mouse in the system (and its driver is not running). Even in Windows, the system mouse cursor disappears completely when the mouse is disconnected from the USB port (at least in Windows 10, I just tested this). Which cursor will this function move in this case?

Agree. If there is no cursor then there is nothing to move and the only way is to use software cursor.

I'll add the corresponding comments about why we must use hardware cursor for touchscreen devices.

I did a test for Android and it acts the same as Windows - the system (hardware) cursor is visible only if mouse if plugged.

Districh-ru avatar Jul 07 '25 16:07 Districh-ru

Hi @Districh-ru what do you think about making the software cursor the only option (or perhaps a default with config file-only configuration)? Pros of the software cursor:

  • It is scaled along with the game area itself (so it has an adequate size in case of xN resolutions);
  • It does work even if there is no "real" mouse.

Cons of the software cursor:

  • It can move sloppily when event processing loop is busy (e.g. during the AI turn);
  • ???

oleg-derevenetz avatar Jul 08 '25 12:07 oleg-derevenetz

Hi @oleg-derevenetz, I prefer to keep as it is now - "software" default with config file-only configuration. I'll remove this option from this PR (probably tomorrow). I use hardware cursor when I play the game at 1366x768 resolution maximized to 1920x1080 and I have not so "small" game image and 1:1 unscaled cursor. It looks good for me. :) And, yes, it moves smooth during AI turn.

But I'm also OK with leaving only software cursor. We can discuss it separately with the team and active players and remove the hardware cursor ability from the engine in a new PR if we decide to do this.

Districh-ru avatar Jul 08 '25 13:07 Districh-ru

Hello @ihhub, @oleg-derevenetz and @zenseii! From tomorrow until August 6th I will be on vacation and away from the internet. If you find any issues in this PR or want to apply changes, you are free to commit to this PR.

Districh-ru avatar Jul 27 '25 08:07 Districh-ru

Enjoy your vacation, @Districh-ru !

zenseii avatar Jul 27 '25 09:07 zenseii

Hello @ihhub, @oleg-derevenetz and @zenseii! From tomorrow until August 6th I will be on vacation and away from the internet. If you find any issues in this PR or want to apply changes, you are free to commit to this PR.

Have a nice vacation!

ihhub avatar Jul 27 '25 10:07 ihhub

Thanks guys!

Districh-ru avatar Jul 27 '25 11:07 Districh-ru

Hi @Districh-ru ,

I have big doubts about the usage of the images. This is a proposed image in comparison with the original image from ICN::MONS32, image 38. As you can see they are the same: image Therefore, we shouldn't use such an image to be stored in the resurrection.h2d file. We can store only the rest of the image and blit it on top of the existing image resized by 2x.

The same applies for Linear Scaling: image It is the same image scaled by 2x with linear scaling filter. We can use SubpixelResize() function for this matter.

What do you think @Districh-ru and @PusshPop?

ihhub avatar Aug 10 '25 03:08 ihhub

What do you think @Districh-ru and @PusshPop?

We will need the background image (the purple gradient one). Then we can "Blit" a resized image of creature. We will also need a monocle image to "Blit" it over the result image.

Hi @PusshPop, could you please mate these two images: the purple gradient background and the monocle. The white shine effects of the monocle can be done withe the engine: like the shading the engine can do whitening with 4 levels of effect strength, you only need to say what color is for what whitening strength.

Districh-ru avatar Aug 10 '25 04:08 Districh-ru

@Districh-ru sorry for the very late reply. I dont check github very often and when I do I usually dont log in (mainly because I dont have much going on on github). I do check discord almost every day so if you ping me there or message me directly, I will respond much faster.

Anyways, here are the seperated images: Monocle Menu button.zip

There is 1 purple background image, and 2 different monocle images. 1 where I have baked in the shine, and another where the shine is partially made by the engine.

Background: color 96 Shadow: 62 - 60 - 58 Shine (for engine version only): 17 - 18 - 19

I am not sure which one will look better, I dont know what effect the engine will create on different strengths so it is difficult for me to adjust based on a guess. But my intention was that the inner parts of the shine is not see-through. So ill let you decide which comes out best 😉.

PusshPop avatar Sep 21 '25 13:09 PusshPop

@PusshPop, sorry for the late response. Thank you for the images. I'll update PR in the next days.

Districh-ru avatar Sep 30 '25 12:09 Districh-ru

Hi @Districh-ru , would it be possible for you to update this pull request?

ihhub avatar Oct 28 '25 04:10 ihhub

If @Districh-ru is busy and the remaining part of this PR is to add the icons, then I can wrap up the PR for him.

zenseii avatar Oct 28 '25 12:10 zenseii

Hi @ihhub, sadly I'll have no time in the next days - tomorrow I'll be preparing for a long business trip and will be on a train until November 1st. I believe I'll have some time while in the business trip, I'll take my laptop.

Hi @zenseii, if you have some time could you please assist with updating the icons. I'll update the other logic if it is needed.

Districh-ru avatar Oct 28 '25 18:10 Districh-ru

@Districh-ru, I'll finish it. Have a nice trip!

zenseii avatar Oct 28 '25 19:10 zenseii

Hi, @Districh-ru. I realized that the engine's own transparency for the inner lens created a much worse effect than the one @PusshPop made in their images. This lead me to believe that we need to "pre-render" the inner lens shine and just paste it on top of the upscaled halflings.

What I was going to do:

  1. Provide @PusshPop with the two upscaled halflings (linear and subpixel) so that @PusshPop can make the pre-rendered lens shines. We will need two: one for each scaling type.
  2. Add this to the lens image in the h2d file. What do you think, @Districh-ru ?

zenseii avatar Nov 16 '25 08:11 zenseii

Hi @zenseii, many thanks for adding the monocle. I just move the transform layer update logic to image preparation before saving it to h2d file:

Code

#include "h2d_file.h"
#include "image_tool.h"

        fheroes2::H2DReader re;
        re.open( "..\\files\\data\\resurrection.h2d" );
        fheroes2::H2DWriter wr;
        wr.add( re );

        const std::string imgPath = "..\\filter_button\\";

        fheroes2::Sprite temp;
        fheroes2::Load( imgPath + "Monocle.bmp", temp );

        uint8_t transp = temp.image()[0];
        fheroes2::ReplaceColorIdByTransformId( temp, transp, 1 );
        fheroes2::ReplaceColorId( temp, transp, 0 );
        // Shadows
        // transp = temp.image()[0];
        fheroes2::ReplaceColorIdByTransformId( temp, 58, 4U );
        fheroes2::ReplaceColorId( temp, 58, 0 );
        fheroes2::ReplaceColorIdByTransformId( temp, 60, 3U );
        fheroes2::ReplaceColorId( temp, 60, 0 );
        fheroes2::ReplaceColorIdByTransformId( temp, 62, 2U );
        fheroes2::ReplaceColorId( temp, 62, 0 );
        // Inner lens glass shine
        fheroes2::ReplaceColorIdByTransformId( temp, 19, 9U );
        fheroes2::ReplaceColorId( temp, 19, 0 );
        fheroes2::ReplaceColorIdByTransformId( temp, 18, 8U );
        fheroes2::ReplaceColorId( temp, 18, 0 );
        fheroes2::ReplaceColorIdByTransformId( temp, 17, 7U );
        fheroes2::ReplaceColorId( temp, 17, 0 );

        fheroes2::writeImageToH2D( wr, "monocle.image", temp );

        wr.write( imgPath + "resurrection.h2d" );

@ihhub and @zenseii, this PR is ready for review.

Districh-ru avatar Nov 16 '25 08:11 Districh-ru

Hi, @Districh-ru. I realized that the engine's own transparency for the inner lens created a much worse effect than the one @PusshPop made in their images. This lead me to believe that we need to "pre-render" the inner lens shine and just paste it on top of the upscaled halflings.

What I was going to do:

1. Provide @PusshPop with the two upscaled halflings (linear and subpixel) so that @PusshPop can make the pre-rendered lens shines. We will need two: one for each scaling type.

2. Add this to the lens image in the h2d file.
   What do you think, @Districh-ru ?

@zenseii, yes, we can add these two special lens for the images. Only the lower-left shine covers the Halfling sprite, so we can have one image for the upper-right shine and two lower-left for two types of scales.

Could you please contact @PusshPop.

Districh-ru avatar Nov 16 '25 08:11 Districh-ru

@Districh-ru, I agree about the lower left shine. I will contact @PusshPop.

zenseii avatar Nov 16 '25 08:11 zenseii

Anyways, here are the seperated images: Monocle Menu button.zip

There is 1 purple background image, and 2 different monocle images. 1 where I have baked in the shine, and another where the shine is partially made by the engine.

Background: color 96 Shadow: 62 - 60 - 58 Shine (for engine version only): 17 - 18 - 19

@Districh-ru @zenseii Sorry for the late reply. But the zip file I posted contained 2 versions of the monocle. 1 with the Shine baked in where the engine is not supposed to make the glare transparent. This should be able to be pasted on top of the menu button. Or is the result of that one not good enough? Does it create weird pixels/artifacts?

PusshPop avatar Nov 21 '25 21:11 PusshPop

Hi @zenseii and @PusshPop, I've updated the "subpixel" scaling algorithm to do scaling when the next right or bottom pixel is transparent. Previously these pixels were not interpolated so we had the square left eye (or it is nose) of Halfling.

Also I've updated the GetPALColorId() function to avoid using the originally undefined colors. These colors are 0 that is black, but they are not in the lightening/darkening tables to the lens effect was not properly applied to the halfling contour after subpixel resize.

Districh-ru avatar Nov 23 '25 17:11 Districh-ru

@Districh-ru, thanks for fixing this and good job fixing that contour too! In the end I think we can go with the engine transparency effect as this will allow us to use the monocle on top of other backgrounds/objects if we ever want to for whatever reason.

The only thing that remains to be solved now is the contour of the halfling's feet that are sticking out from the bottom edge of the monocle.

zenseii avatar Nov 23 '25 18:11 zenseii