Add content scale stretch modes, implement integer scaling

Integer scaling is achieved (after aspect expansion) by "lying" to the
stretching code about the window's size, telling it that it's always an
integer multiple of the viewport so that it only gets stretched to an
integer factor.

This approach works with all stretch and aspect modes and doesn't
require handling for each, only requiring to "loosen up" some
self-excluding conditions (in other words, replacing some `else if`s
with just `if`s) regarding viewport offset and margin calculation (black
bars).

Includes a tiny usability change that adds a range hint for the content
scale factor between 0.5 to 8.0.

Co-Authored-By: Hugo Locurcio <hugo.locurcio@hugo.pro>
This commit is contained in:
Riteo 2023-04-06 23:41:27 +02:00
parent b5f532094e
commit 87cfc415a3
6 changed files with 74 additions and 3 deletions

View file

@ -929,6 +929,17 @@ void Window::_update_viewport_size() {
float font_oversampling = 1.0;
window_transform = Transform2D();
if (content_scale_stretch == Window::CONTENT_SCALE_STRETCH_INTEGER) {
// We always want to make sure that the content scale factor is a whole
// number, else there will be pixel wobble no matter what.
content_scale_factor = Math::floor(content_scale_factor);
// A content scale factor of zero is pretty useless.
if (content_scale_factor < 1) {
content_scale_factor = 1;
}
}
if (content_scale_mode == CONTENT_SCALE_MODE_DISABLED || content_scale_size.x == 0 || content_scale_size.y == 0) {
font_oversampling = content_scale_factor;
final_size = size;
@ -982,13 +993,26 @@ void Window::_update_viewport_size() {
screen_size = screen_size.floor();
viewport_size = viewport_size.floor();
if (content_scale_stretch == Window::CONTENT_SCALE_STRETCH_INTEGER) {
Size2i screen_scale = (screen_size / viewport_size).floor();
int scale_factor = MIN(screen_scale.x, screen_scale.y);
if (scale_factor < 1) {
scale_factor = 1;
}
screen_size = viewport_size * scale_factor;
}
Size2 margin;
Size2 offset;
if (content_scale_aspect != CONTENT_SCALE_ASPECT_EXPAND && screen_size.x < video_mode.x) {
if (screen_size.x < video_mode.x) {
margin.x = Math::round((video_mode.x - screen_size.x) / 2.0);
offset.x = Math::round(margin.x * viewport_size.y / screen_size.y);
} else if (content_scale_aspect != CONTENT_SCALE_ASPECT_EXPAND && screen_size.y < video_mode.y) {
}
if (screen_size.y < video_mode.y) {
margin.y = Math::round((video_mode.y - screen_size.y) / 2.0);
offset.y = Math::round(margin.y * viewport_size.x / screen_size.x);
}
@ -1236,6 +1260,15 @@ Window::ContentScaleAspect Window::get_content_scale_aspect() const {
return content_scale_aspect;
}
void Window::set_content_scale_stretch(ContentScaleStretch p_stretch) {
content_scale_stretch = p_stretch;
_update_viewport_size();
}
Window::ContentScaleStretch Window::get_content_scale_stretch() const {
return content_scale_stretch;
}
void Window::set_content_scale_factor(real_t p_factor) {
ERR_FAIL_COND(p_factor <= 0);
content_scale_factor = p_factor;
@ -2350,6 +2383,9 @@ void Window::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_content_scale_aspect", "aspect"), &Window::set_content_scale_aspect);
ClassDB::bind_method(D_METHOD("get_content_scale_aspect"), &Window::get_content_scale_aspect);
ClassDB::bind_method(D_METHOD("set_content_scale_stretch", "stretch"), &Window::set_content_scale_stretch);
ClassDB::bind_method(D_METHOD("get_content_scale_stretch"), &Window::get_content_scale_stretch);
ClassDB::bind_method(D_METHOD("set_content_scale_factor", "factor"), &Window::set_content_scale_factor);
ClassDB::bind_method(D_METHOD("get_content_scale_factor"), &Window::get_content_scale_factor);
@ -2460,7 +2496,8 @@ void Window::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::VECTOR2I, "content_scale_size"), "set_content_scale_size", "get_content_scale_size");
ADD_PROPERTY(PropertyInfo(Variant::INT, "content_scale_mode", PROPERTY_HINT_ENUM, "Disabled,Canvas Items,Viewport"), "set_content_scale_mode", "get_content_scale_mode");
ADD_PROPERTY(PropertyInfo(Variant::INT, "content_scale_aspect", PROPERTY_HINT_ENUM, "Ignore,Keep,Keep Width,Keep Height,Expand"), "set_content_scale_aspect", "get_content_scale_aspect");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "content_scale_factor"), "set_content_scale_factor", "get_content_scale_factor");
ADD_PROPERTY(PropertyInfo(Variant::INT, "content_scale_stretch", PROPERTY_HINT_ENUM, "Fractional,Integer"), "set_content_scale_stretch", "get_content_scale_stretch");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "content_scale_factor", PROPERTY_HINT_RANGE, "0.5,8.0,0.01"), "set_content_scale_factor", "get_content_scale_factor");
ADD_GROUP("Localization", "");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "auto_translate"), "set_auto_translate", "is_auto_translating");
@ -2512,6 +2549,9 @@ void Window::_bind_methods() {
BIND_ENUM_CONSTANT(CONTENT_SCALE_ASPECT_KEEP_HEIGHT);
BIND_ENUM_CONSTANT(CONTENT_SCALE_ASPECT_EXPAND);
BIND_ENUM_CONSTANT(CONTENT_SCALE_STRETCH_FRACTIONAL);
BIND_ENUM_CONSTANT(CONTENT_SCALE_STRETCH_INTEGER);
BIND_ENUM_CONSTANT(LAYOUT_DIRECTION_INHERITED);
BIND_ENUM_CONSTANT(LAYOUT_DIRECTION_LOCALE);
BIND_ENUM_CONSTANT(LAYOUT_DIRECTION_LTR);