1
0
Fork 0

Add SubViewportContainer `stretch_factor`

- Deprecate SubViewportContainer `shrink`.
- Add SubViewportContainer `apply_viewport_stretch_transform`.
This commit is contained in:
Adam Scott 2025-02-01 16:24:10 -05:00
parent f60f69aa57
commit 13dda81913
No known key found for this signature in database
GPG Key ID: F6BA2A0302E21A77
5 changed files with 86 additions and 29 deletions

View File

@ -20,6 +20,9 @@
</method>
</methods>
<members>
<member name="apply_viewport_stretch_transform" type="bool" setter="set_apply_viewport_stretch_transform" getter="is_applying_viewport_stretch_transform" default="false">
If [code]true[/code], the sub-viewport will be automatically resized according to the viewport stretch transform. It is especially useful for DPI-aware projects. See [method Viewport.get_stretch_transform] for more details about stretch transform.
</member>
<member name="focus_mode" type="int" setter="set_focus_mode" getter="get_focus_mode" overrides="Control" enum="Control.FocusMode" default="1" />
<member name="mouse_target" type="bool" setter="set_mouse_target" getter="is_mouse_target_enabled" default="false">
Configure, if either the [SubViewportContainer] or alternatively the [Control] nodes of its [SubViewport] children should be available as targets of mouse-related functionalities, like identifying the drop target in drag-and-drop operations or cursor shape of hovered [Control] node.
@ -30,7 +33,12 @@
If [code]true[/code], the sub-viewport will be automatically resized to the control's size.
[b]Note:[/b] If [code]true[/code], this will prohibit changing [member SubViewport.size] of its children manually.
</member>
<member name="stretch_shrink" type="int" setter="set_stretch_shrink" getter="get_stretch_shrink" default="1">
<member name="stretch_factor" type="float" setter="set_stretch_factor" getter="get_stretch_factor" default="1.0">
Multiplies the sub-viewport's effective resolution by this value while preserving its scale. This can be used either to speed up rendering or to render at an higher resolution.
For example, a 1280×720 sub-viewport with [member stretch_shrink] set to [code]0.5[/code] will be rendered at 640×360 while occupying the same size in the container.
[b]Note:[/b] [member stretch] must be [code]true[/code] for this property to work.
</member>
<member name="stretch_shrink" type="int" setter="set_stretch_shrink" getter="get_stretch_shrink" default="1" deprecated="Use [member stretch_factor] instead.">
Divides the sub-viewport's effective resolution by this value while preserving its scale. This can be used to speed up rendering.
For example, a 1280×720 sub-viewport with [member stretch_shrink] set to [code]2[/code] will be rendered at 640×360 while occupying the same size in the container.
[b]Note:[/b] [member stretch] must be [code]true[/code] for this property to work.

View File

@ -697,7 +697,7 @@ void Node3DEditorViewport::cancel_transform() {
void Node3DEditorViewport::_update_shrink() {
bool shrink = view_menu->get_popup()->is_item_checked(view_menu->get_popup()->get_item_index(VIEW_HALF_RESOLUTION));
subviewport_container->set_stretch_shrink(shrink ? 2 : 1);
subviewport_container->set_stretch_factor(shrink ? 0.5 : 1.0);
subviewport_container->set_texture_filter(shrink ? TEXTURE_FILTER_NEAREST : TEXTURE_FILTER_PARENT_NODE);
}
@ -722,11 +722,11 @@ Vector3 Node3DEditorViewport::_get_camera_position() const {
}
Point2 Node3DEditorViewport::point_to_screen(const Vector3 &p_point) {
return camera->unproject_position(p_point) * subviewport_container->get_stretch_shrink();
return camera->unproject_position(p_point) / subviewport_container->get_stretch_factor();
}
Vector3 Node3DEditorViewport::get_ray_pos(const Vector2 &p_pos) const {
return camera->project_ray_origin(p_pos / subviewport_container->get_stretch_shrink());
return camera->project_ray_origin(p_pos * subviewport_container->get_stretch_factor());
}
Vector3 Node3DEditorViewport::_get_camera_normal() const {
@ -734,7 +734,7 @@ Vector3 Node3DEditorViewport::_get_camera_normal() const {
}
Vector3 Node3DEditorViewport::get_ray(const Vector2 &p_pos) const {
return camera->project_ray_normal(p_pos / subviewport_container->get_stretch_shrink());
return camera->project_ray_normal(p_pos * subviewport_container->get_stretch_factor());
}
void Node3DEditorViewport::_clear_selected() {
@ -813,7 +813,7 @@ void Node3DEditorViewport::_select_clicked(bool p_allow_locked) {
ObjectID Node3DEditorViewport::_select_ray(const Point2 &p_pos) const {
Vector3 ray = get_ray(p_pos);
Vector3 pos = get_ray_pos(p_pos);
Vector2 shrinked_pos = p_pos / subviewport_container->get_stretch_shrink();
Vector2 shrinked_pos = p_pos * subviewport_container->get_stretch_factor();
if (viewport->get_debug_draw() == Viewport::DEBUG_DRAW_SDFGI_PROBES) {
RS::get_singleton()->sdfgi_set_debug_probe_select(pos, ray);
@ -4085,8 +4085,8 @@ void Node3DEditorViewport::update_transform_gizmo_view() {
const int viewport_base_height = 400 * MAX(1, EDSCALE);
gizmo_scale =
(gizmo_size / Math::abs(dd)) * MAX(1, EDSCALE) *
MIN(viewport_base_height, subviewport_container->get_size().height) / viewport_base_height /
subviewport_container->get_stretch_shrink();
MIN(viewport_base_height, subviewport_container->get_size().height) / viewport_base_height *
subviewport_container->get_stretch_ratio();
Vector3 scale = Vector3(1, 1, 1) * gizmo_scale;
// if the determinant is zero, we should disable the gizmo from being rendered
@ -4310,7 +4310,7 @@ Dictionary Node3DEditorViewport::get_state() const {
d["grid"] = view_menu->get_popup()->is_item_checked(view_menu->get_popup()->get_item_index(VIEW_GRID));
d["information"] = view_menu->get_popup()->is_item_checked(view_menu->get_popup()->get_item_index(VIEW_INFORMATION));
d["frame_time"] = view_menu->get_popup()->is_item_checked(view_menu->get_popup()->get_item_index(VIEW_FRAME_TIME));
d["half_res"] = subviewport_container->get_stretch_shrink() > 1;
d["half_res"] = subviewport_container->get_stretch_factor() < 1.0;
d["cinematic_preview"] = view_menu->get_popup()->is_item_checked(view_menu->get_popup()->get_item_index(VIEW_CINEMATIC_PREVIEW));
if (previewing) {
d["previewing"] = EditorNode::get_singleton()->get_edited_scene()->get_path_to(previewing);

View File

@ -67,18 +67,6 @@ bool SubViewportContainer::is_stretch_enabled() const {
return stretch;
}
void SubViewportContainer::set_stretch_shrink(int p_shrink) {
ERR_FAIL_COND(p_shrink < 1);
if (shrink == p_shrink) {
return;
}
shrink = p_shrink;
recalc_force_viewport_sizes();
queue_redraw();
}
void SubViewportContainer::recalc_force_viewport_sizes() {
if (!stretch) {
return;
@ -91,12 +79,54 @@ void SubViewportContainer::recalc_force_viewport_sizes() {
continue;
}
c->set_size_force(get_size() / shrink);
Vector2 new_size = get_size();
if (apply_viewport_stretch_transform) {
new_size *= get_viewport()->get_stretch_transform().get_scale().x;
}
new_size *= stretch_factor;
c->set_size_force(new_size);
}
}
void SubViewportContainer::set_apply_viewport_stretch_transform(bool p_apply_viewport_stretch_transform) {
if (p_apply_viewport_stretch_transform == apply_viewport_stretch_transform) {
return;
}
apply_viewport_stretch_transform = p_apply_viewport_stretch_transform;
recalc_force_viewport_sizes();
queue_redraw();
}
bool SubViewportContainer::is_applying_viewport_stretch_transform() const {
return apply_viewport_stretch_transform;
}
#ifndef DISABLE_DEPRECATED
void SubViewportContainer::set_stretch_shrink(int p_shrink) {
ERR_FAIL_COND(p_shrink < 1);
set_stretch_factor(1.0 / p_shrink);
}
int SubViewportContainer::get_stretch_shrink() const {
return shrink;
return Math::round(1.0 / get_stretch_factor());
}
#endif
void SubViewportContainer::set_stretch_factor(float p_stretch_factor) {
if (p_stretch_factor == stretch_factor) {
return;
}
stretch_factor = p_stretch_factor;
recalc_force_viewport_sizes();
queue_redraw();
}
float SubViewportContainer::get_stretch_factor() const {
return stretch_factor;
}
Vector<int> SubViewportContainer::get_allowed_size_flags_horizontal() const {
@ -217,9 +247,9 @@ void SubViewportContainer::gui_input(const Ref<InputEvent> &p_event) {
}
}
if (stretch && shrink > 1) {
if (stretch && stretch_factor < 1) {
Transform2D xform;
xform.scale(Vector2(1, 1) / shrink);
xform.scale(Vector2(1, 1) * stretch_factor);
_send_event_to_viewports(p_event->xformed_by(xform));
} else {
_send_event_to_viewports(p_event);
@ -291,14 +321,25 @@ void SubViewportContainer::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_stretch", "enable"), &SubViewportContainer::set_stretch);
ClassDB::bind_method(D_METHOD("is_stretch_enabled"), &SubViewportContainer::is_stretch_enabled);
ClassDB::bind_method(D_METHOD("set_apply_viewport_stretch_transform", "apply_viewport_stretch_transform"), &SubViewportContainer::set_apply_viewport_stretch_transform);
ClassDB::bind_method(D_METHOD("is_applying_viewport_stretch_transform"), &SubViewportContainer::is_applying_viewport_stretch_transform);
#ifndef DISABLE_DEPRECATED
ClassDB::bind_method(D_METHOD("set_stretch_shrink", "amount"), &SubViewportContainer::set_stretch_shrink);
ClassDB::bind_method(D_METHOD("get_stretch_shrink"), &SubViewportContainer::get_stretch_shrink);
#endif
ClassDB::bind_method(D_METHOD("set_stretch_factor", "stretch_factor"), &SubViewportContainer::set_stretch_factor);
ClassDB::bind_method(D_METHOD("get_stretch_factor"), &SubViewportContainer::get_stretch_factor);
ClassDB::bind_method(D_METHOD("set_mouse_target", "amount"), &SubViewportContainer::set_mouse_target);
ClassDB::bind_method(D_METHOD("is_mouse_target_enabled"), &SubViewportContainer::is_mouse_target_enabled);
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "stretch"), "set_stretch", "is_stretch_enabled");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "apply_viewport_stretch_transform"), "set_apply_viewport_stretch_transform", "is_applying_viewport_stretch_transform");
#ifndef DISABLE_DEPRECTED
ADD_PROPERTY(PropertyInfo(Variant::INT, "stretch_shrink", PROPERTY_HINT_RANGE, "1,32,1,or_greater"), "set_stretch_shrink", "get_stretch_shrink");
#endif
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "stretch_factor", PROPERTY_HINT_RANGE, "0.0,2.0,0.01,or_greater"), "set_stretch_factor", "get_stretch_factor");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "mouse_target"), "set_mouse_target", "is_mouse_target_enabled");
GDVIRTUAL_BIND(_propagate_input_event, "event");

View File

@ -37,7 +37,8 @@ class SubViewportContainer : public Container {
GDCLASS(SubViewportContainer, Container);
bool stretch = false;
int shrink = 1;
bool apply_viewport_stretch_transform = false;
float stretch_factor = 1.0f;
bool mouse_target = false;
void _notify_viewports(int p_notification);
@ -61,8 +62,15 @@ public:
virtual void input(const Ref<InputEvent> &p_event) override;
virtual void unhandled_input(const Ref<InputEvent> &p_event) override;
virtual void gui_input(const Ref<InputEvent> &p_event) override;
void set_apply_viewport_stretch_transform(bool p_apply_viewport_stretch_transform);
bool is_applying_viewport_stretch_transform() const;
#ifndef DISABLE_DEPRECATED
void set_stretch_shrink(int p_shrink);
int get_stretch_shrink() const;
#endif
void set_stretch_factor(float p_stretch_factor);
float get_stretch_factor() const;
void recalc_force_viewport_sizes();
void set_mouse_target(bool p_enable);

View File

@ -3147,7 +3147,7 @@ void Viewport::_update_mouse_over(Vector2 p_pos) {
}
Vector2 pos = c->get_global_transform_with_canvas().affine_inverse().xform(p_pos);
if (c->is_stretch_enabled()) {
pos /= c->get_stretch_shrink();
pos *= c->get_stretch_factor();
}
for (int i = 0; i < c->get_child_count(); i++) {
@ -5256,7 +5256,7 @@ Transform2D SubViewport::get_screen_transform_internal(bool p_absolute_position)
SubViewportContainer *c = Object::cast_to<SubViewportContainer>(get_parent());
if (c) {
if (c->is_stretch_enabled()) {
container_transform.scale(Vector2(c->get_stretch_shrink(), c->get_stretch_shrink()));
container_transform.scale(Vector2(1.0 / c->get_stretch_factor(), 1.0 / c->get_stretch_factor()));
}
container_transform = c->get_viewport()->get_screen_transform_internal(p_absolute_position) * c->get_global_transform_with_canvas() * container_transform;
} else {
@ -5276,7 +5276,7 @@ Transform2D SubViewport::get_popup_base_transform() const {
}
Transform2D container_transform;
if (c->is_stretch_enabled()) {
container_transform.scale(Vector2(c->get_stretch_shrink(), c->get_stretch_shrink()));
container_transform.scale(Vector2(1.0 / c->get_stretch_factor(), 1.0 / c->get_stretch_factor()));
}
return c->get_screen_transform() * container_transform * get_final_transform();
}