Skip to content

Commit

Permalink
Rework content scale to provide more options, add integer scaling
Browse files Browse the repository at this point in the history
- Add content stretch modes Fractional (default), Integer and Hybrid.
  - All modes with with any stretch mode and aspect.
  - Fractional behaves as Godot currently does when scaling viewports.
    Pixel art will only look good when the window is scaled at multiples
    of the original size.
  - Integer enforces an integer scale for the final display (rounded down
    from the automatically computed fractional scale). Black bars may be
    displayed on all sides when using the `viewport` stretch mode.
    This provides crisp pixel art appearance.
  - Hybrid enforces an integer scale on the internal rendering resolution,
    but the viewport will be stretched down to the final display with
    linear filtering. This provides good pixel art appearance, though
    not as crisp as the Integer mode.

- Tweak project setting for stretch scale to allow values as low as 0.5
  (values below 1 are valid, and can be useful for UI testing purposes).

TODO:

- Implement hybrid filtering mode.
  • Loading branch information
Calinou committed Jul 19, 2022
1 parent 715f556 commit 3490b9b
Show file tree
Hide file tree
Showing 3 changed files with 84 additions and 5 deletions.
21 changes: 20 additions & 1 deletion main/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2500,6 +2500,7 @@ bool Main::start() {

String stretch_mode = GLOBAL_DEF_BASIC("display/window/stretch/mode", "disabled");
String stretch_aspect = GLOBAL_DEF_BASIC("display/window/stretch/aspect", "keep");
String stretch_stretch = GLOBAL_DEF_BASIC("display/window/stretch/stretch", "fractional");
Size2i stretch_size = Size2i(GLOBAL_DEF_BASIC("display/window/size/viewport_width", 0),
GLOBAL_DEF_BASIC("display/window/size/viewport_height", 0));
real_t stretch_scale = GLOBAL_DEF_BASIC("display/window/stretch/scale", 1.0);
Expand All @@ -2522,8 +2523,16 @@ bool Main::start() {
cs_aspect = Window::CONTENT_SCALE_ASPECT_EXPAND;
}

Window::ContentScaleStretch cs_stretch = Window::CONTENT_SCALE_STRETCH_FRACTIONAL;
if (stretch_stretch == "integer") {
cs_stretch = Window::CONTENT_SCALE_STRETCH_INTEGER;
} else if (stretch_stretch == "hybrid") {
cs_stretch = Window::CONTENT_SCALE_STRETCH_HYBRID;
}

sml->get_root()->set_content_scale_mode(cs_sm);
sml->get_root()->set_content_scale_aspect(cs_aspect);
sml->get_root()->set_content_scale_stretch(cs_stretch);
sml->get_root()->set_content_scale_size(stretch_size);
sml->get_root()->set_content_scale_factor(stretch_scale);

Expand Down Expand Up @@ -2564,18 +2573,28 @@ bool Main::start() {
"display/window/stretch/mode",
PROPERTY_HINT_ENUM,
"disabled,canvas_items,viewport"));

GLOBAL_DEF_BASIC("display/window/stretch/aspect", "keep");
ProjectSettings::get_singleton()->set_custom_property_info("display/window/stretch/aspect",
PropertyInfo(Variant::STRING,
"display/window/stretch/aspect",
PROPERTY_HINT_ENUM,
"ignore,keep,keep_width,keep_height,expand"));

GLOBAL_DEF_BASIC("display/window/stretch/stretch", "fractional");
ProjectSettings::get_singleton()->set_custom_property_info("display/window/stretch/stretch",
PropertyInfo(Variant::STRING,
"display/window/stretch/stretch",
PROPERTY_HINT_ENUM,
"fractional,integer,hybrid"));

GLOBAL_DEF_BASIC("display/window/stretch/scale", 1.0);
ProjectSettings::get_singleton()->set_custom_property_info("display/window/stretch/scale",
PropertyInfo(Variant::FLOAT,
"display/window/stretch/scale",
PROPERTY_HINT_RANGE,
"1.0,8.0,0.1"));
"0.5,8.0,0.01"));

sml->set_auto_accept_quit(GLOBAL_DEF("application/config/auto_accept_quit", true));
sml->set_quit_on_go_back(GLOBAL_DEF("application/config/quit_on_go_back", true));
GLOBAL_DEF_BASIC("gui/common/snap_controls_to_pixels", true);
Expand Down
57 changes: 53 additions & 4 deletions scene/main/window.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -626,6 +626,16 @@ void Window::_update_viewport_size() {
float font_oversampling = 1.0;

if (content_scale_mode == CONTENT_SCALE_MODE_DISABLED || content_scale_size.x == 0 || content_scale_size.y == 0) {
if (content_scale_stretch == Window::CONTENT_SCALE_STRETCH_INTEGER) {
// Enforce integer scaling to ensure pixel-perfect appearance of pixel art.
content_scale_factor = Math::floor(content_scale_factor);
} else if (content_scale_stretch == Window::CONTENT_SCALE_STRETCH_HYBRID) {
// Scale up to the nearest greater integer value, then scale down with linear filtering.
// This provides good (but not pixel-perfect) appearance for pixel art, and allows
// displaying at any output resolution.
WARN_PRINT("Hybrid content scaling for disabled stretch mode is not implemented yet.");
}

font_oversampling = content_scale_factor;
final_size = size;
final_size_override = Size2(size) / content_scale_factor;
Expand Down Expand Up @@ -702,18 +712,40 @@ void Window::_update_viewport_size() {
//_update_font_oversampling(1.0);
} break;
case CONTENT_SCALE_MODE_CANVAS_ITEMS: {
attach_to_screen_rect = Rect2(margin, screen_size);
final_size = screen_size;
final_size_override = viewport_size / content_scale_factor;
attach_to_screen_rect = Rect2(margin, screen_size);
font_oversampling = (screen_size.x / viewport_size.x) * content_scale_factor;

font_oversampling = (screen_size.x / viewport_size.x) * content_scale_factor;
Size2 scale = Vector2(screen_size) / Vector2(final_size_override);

if (content_scale_stretch == Window::CONTENT_SCALE_STRETCH_INTEGER) {
// Enforce integer scaling to ensure pixel-perfect appearance of pixel art.
font_oversampling = Math::floor(font_oversampling);
scale = scale.floor();
} else if (content_scale_stretch == Window::CONTENT_SCALE_STRETCH_HYBRID) {
// Scale up to the nearest greater integer value, then scale down with linear filtering.
// This provides good (but not pixel-perfect) appearance for pixel art, and allows
// displaying at any output resolution.
WARN_PRINT("Hybrid content scaling for canvas items stretch mode is not implemented yet.");
}

stretch_transform.scale(scale);

} break;
case CONTENT_SCALE_MODE_VIEWPORT: {
final_size = (viewport_size / content_scale_factor).floor();
attach_to_screen_rect = Rect2(margin, screen_size);
final_size = (viewport_size / content_scale_factor).floor();

if (content_scale_stretch == Window::CONTENT_SCALE_STRETCH_INTEGER) {
// Enforce integer scaling to ensure pixel-perfect appearance of pixel art.
WARN_PRINT("Integer content scaling for viewport stretch mode is not implemented yet.");
} else if (content_scale_stretch == Window::CONTENT_SCALE_STRETCH_HYBRID) {
// Scale up to the nearest greater integer value, then scale down with linear filtering.
// This provides good (but not pixel-perfect) appearance for pixel art, and allows
// displaying at any output resolution.
WARN_PRINT("Hybrid content scaling for viewport stretch mode is not implemented yet.");
}

} break;
}
Expand Down Expand Up @@ -920,6 +952,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;
Expand Down Expand Up @@ -1588,6 +1629,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);

Expand Down Expand Up @@ -1663,7 +1707,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,Hybrid"), "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("Theme", "theme_");
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "theme", PROPERTY_HINT_RESOURCE_TYPE, "Theme"), "set_theme", "get_theme");
Expand Down Expand Up @@ -1710,6 +1755,10 @@ 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(CONTENT_SCALE_STRETCH_HYBRID);

BIND_ENUM_CONSTANT(LAYOUT_DIRECTION_INHERITED);
BIND_ENUM_CONSTANT(LAYOUT_DIRECTION_LOCALE);
BIND_ENUM_CONSTANT(LAYOUT_DIRECTION_LTR);
Expand Down
11 changes: 11 additions & 0 deletions scene/main/window.h
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,12 @@ class Window : public Viewport {
CONTENT_SCALE_ASPECT_EXPAND,
};

enum ContentScaleStretch {
CONTENT_SCALE_STRETCH_FRACTIONAL,
CONTENT_SCALE_STRETCH_INTEGER,
CONTENT_SCALE_STRETCH_HYBRID,
};

enum LayoutDirection {
LAYOUT_DIRECTION_INHERITED,
LAYOUT_DIRECTION_LOCALE,
Expand Down Expand Up @@ -114,6 +120,7 @@ class Window : public Viewport {
Size2i content_scale_size;
ContentScaleMode content_scale_mode = CONTENT_SCALE_MODE_DISABLED;
ContentScaleAspect content_scale_aspect = CONTENT_SCALE_ASPECT_IGNORE;
ContentScaleStretch content_scale_stretch = CONTENT_SCALE_STRETCH_FRACTIONAL;
real_t content_scale_factor = 1.0;

void _make_window();
Expand Down Expand Up @@ -233,6 +240,9 @@ class Window : public Viewport {
void set_content_scale_aspect(ContentScaleAspect p_aspect);
ContentScaleAspect get_content_scale_aspect() const;

void set_content_scale_stretch(ContentScaleStretch p_stretch);
ContentScaleStretch get_content_scale_stretch() const;

void set_content_scale_factor(real_t p_factor);
real_t get_content_scale_factor() const;

Expand Down Expand Up @@ -304,6 +314,7 @@ VARIANT_ENUM_CAST(Window::Mode);
VARIANT_ENUM_CAST(Window::Flags);
VARIANT_ENUM_CAST(Window::ContentScaleMode);
VARIANT_ENUM_CAST(Window::ContentScaleAspect);
VARIANT_ENUM_CAST(Window::ContentScaleStretch);
VARIANT_ENUM_CAST(Window::LayoutDirection);

#endif // WINDOW_H

0 comments on commit 3490b9b

Please sign in to comment.