summaryrefslogtreecommitdiff
path: root/scene/main/viewport.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'scene/main/viewport.cpp')
-rw-r--r--scene/main/viewport.cpp357
1 files changed, 258 insertions, 99 deletions
diff --git a/scene/main/viewport.cpp b/scene/main/viewport.cpp
index b29b40ea5f..c96dd4ad35 100644
--- a/scene/main/viewport.cpp
+++ b/scene/main/viewport.cpp
@@ -30,11 +30,13 @@
#include "viewport.h"
+#include "core/config/project_settings.h"
#include "core/core_string_names.h"
#include "core/debugger/engine_debugger.h"
#include "core/input/input.h"
#include "core/os/os.h"
-#include "core/project_settings.h"
+#include "core/string/translation.h"
+
#include "scene/2d/collision_object_2d.h"
#include "scene/3d/camera_3d.h"
#include "scene/3d/collision_object_3d.h"
@@ -161,6 +163,11 @@ ViewportTexture::~ViewportTexture() {
/////////////////////////////////////
+// Aliases used to provide custom styles to tooltips in the default
+// theme and editor theme.
+// TooltipPanel is also used for custom tooltips, while TooltipLabel
+// is only relevant for default tooltips.
+
class TooltipPanel : public PopupPanel {
GDCLASS(TooltipPanel, PopupPanel);
@@ -175,6 +182,8 @@ public:
TooltipLabel() {}
};
+/////////////////////////////////////
+
Viewport::GUI::GUI() {
embed_subwindows_hint = false;
embedding_subwindows = false;
@@ -188,7 +197,7 @@ Viewport::GUI::GUI() {
mouse_over = nullptr;
drag_mouse_over = nullptr;
- tooltip = nullptr;
+ tooltip_control = nullptr;
tooltip_popup = nullptr;
tooltip_label = nullptr;
}
@@ -278,16 +287,19 @@ void Viewport::_sub_window_update(Window *p_window) {
// Draw the title bar text.
Ref<Font> title_font = p_window->get_theme_font("title_font");
+ int font_size = p_window->get_theme_font_size("title_font_size");
Color title_color = p_window->get_theme_color("title_color");
int title_height = p_window->get_theme_constant("title_height");
- int font_height = title_font->get_height() - title_font->get_descent() * 2;
- int x = (r.size.width - title_font->get_string_size(p_window->get_title()).x) / 2;
- int y = (-title_height + font_height) / 2;
-
int close_h_ofs = p_window->get_theme_constant("close_h_ofs");
int close_v_ofs = p_window->get_theme_constant("close_v_ofs");
- title_font->draw(sw.canvas_item, r.position + Point2(x, y), p_window->get_title(), title_color, r.size.width - panel->get_minimum_size().x - close_h_ofs);
+ TextLine title_text = TextLine(p_window->get_title(), title_font, font_size, Dictionary(), TranslationServer::get_singleton()->get_tool_locale());
+ title_text.set_width(r.size.width - panel->get_minimum_size().x - close_h_ofs);
+ title_text.set_direction(p_window->is_layout_rtl() ? TextServer::DIRECTION_RTL : TextServer::DIRECTION_LTR);
+ int x = (r.size.width - title_text.get_size().x) / 2;
+ int y = (-title_height - title_text.get_size().y) / 2;
+
+ title_text.draw(sw.canvas_item, r.position + Point2(x, y), title_color);
bool hl = gui.subwindow_focused == sw.window && gui.subwindow_drag == SUB_WINDOW_DRAG_CLOSE && gui.subwindow_drag_close_inside;
@@ -814,7 +826,14 @@ void Viewport::_notification(int p_what) {
}
} break;
- case NOTIFICATION_WM_MOUSE_EXIT:
+ case NOTIFICATION_WM_MOUSE_EXIT: {
+ _drop_physics_mouseover();
+
+ // Unlike on loss of focus (NOTIFICATION_WM_WINDOW_FOCUS_OUT), do not
+ // drop the gui mouseover here, as a scrollbar may be dragged while the
+ // mouse is outside the window (without the window having lost focus).
+ // See bug #39634
+ } break;
case NOTIFICATION_WM_WINDOW_FOCUS_OUT: {
_drop_physics_mouseover();
@@ -1465,7 +1484,7 @@ void Viewport::_gui_sort_roots() {
}
void Viewport::_gui_cancel_tooltip() {
- gui.tooltip = nullptr;
+ gui.tooltip_control = nullptr;
gui.tooltip_timer = -1;
if (gui.tooltip_popup) {
gui.tooltip_popup->queue_delete();
@@ -1474,29 +1493,34 @@ void Viewport::_gui_cancel_tooltip() {
}
}
-String Viewport::_gui_get_tooltip(Control *p_control, const Vector2 &p_pos, Control **r_which) {
+String Viewport::_gui_get_tooltip(Control *p_control, const Vector2 &p_pos, Control **r_tooltip_owner) {
Vector2 pos = p_pos;
String tooltip;
while (p_control) {
tooltip = p_control->get_tooltip(pos);
- if (r_which) {
- *r_which = p_control;
+ if (r_tooltip_owner) {
+ *r_tooltip_owner = p_control;
}
- if (tooltip != String()) {
+ // If we found a tooltip, we stop here.
+ if (!tooltip.empty()) {
break;
}
- pos = p_control->get_transform().xform(pos);
+
+ // Otherwise, we check parent controls unless some conditions prevent it.
if (p_control->data.mouse_filter == Control::MOUSE_FILTER_STOP) {
break;
}
- if (p_control->is_set_as_toplevel()) {
+ if (p_control->is_set_as_top_level()) {
break;
}
+ // Transform cursor pos for parent control.
+ pos = p_control->get_transform().xform(pos);
+
p_control = p_control->get_parent_control();
}
@@ -1504,34 +1528,40 @@ String Viewport::_gui_get_tooltip(Control *p_control, const Vector2 &p_pos, Cont
}
void Viewport::_gui_show_tooltip() {
- if (!gui.tooltip) {
+ if (!gui.tooltip_control) {
return;
}
- Control *which = nullptr;
- String tooltip = _gui_get_tooltip(gui.tooltip, gui.tooltip->get_global_transform().xform_inv(gui.last_mouse_pos), &which);
- tooltip = tooltip.strip_edges();
- if (tooltip.length() == 0) {
- return; // bye
+ // Get the Control under cursor and the relevant tooltip text, if any.
+ Control *tooltip_owner = nullptr;
+ String tooltip_text = _gui_get_tooltip(
+ gui.tooltip_control,
+ gui.tooltip_control->get_global_transform().xform_inv(gui.last_mouse_pos),
+ &tooltip_owner);
+ tooltip_text.strip_edges();
+ if (tooltip_text.empty()) {
+ return; // Nothing to show.
}
+ // Remove previous popup if we change something.
if (gui.tooltip_popup) {
memdelete(gui.tooltip_popup);
gui.tooltip_popup = nullptr;
gui.tooltip_label = nullptr;
}
- if (!which) {
+ if (!tooltip_owner) {
return;
}
- Control *rp = which;
-
- Control *base_tooltip = which->make_custom_tooltip(tooltip);
+ // Controls can implement `make_custom_tooltip` to provide their own tooltip.
+ // This should be a Control node which will be added as child to a TooltipPanel.
+ Control *base_tooltip = tooltip_owner->make_custom_tooltip(tooltip_text);
+ // If no custom tooltip is given, use a default implementation.
if (!base_tooltip) {
gui.tooltip_label = memnew(TooltipLabel);
- gui.tooltip_label->set_text(tooltip);
+ gui.tooltip_label->set_text(tooltip_text);
base_tooltip = gui.tooltip_label;
}
@@ -1545,10 +1575,7 @@ void Viewport::_gui_show_tooltip() {
gui.tooltip_popup = panel;
- rp->add_child(gui.tooltip_popup);
-
- //if (gui.tooltip) // Avoids crash when rapidly switching controls.
- // gui.tooltip_popup->set_scale(gui.tooltip->get_global_transform().get_scale());
+ tooltip_owner->add_child(gui.tooltip_popup);
Point2 tooltip_offset = ProjectSettings::get_singleton()->get("display/mouse_cursor/tooltip_position_offset");
Rect2 r(gui.tooltip_pos + tooltip_offset, gui.tooltip_popup->get_contents_minimum_size());
@@ -1620,7 +1647,7 @@ void Viewport::_gui_call_input(Control *p_control, const Ref<InputEvent> &p_inpu
}
}
- if (!control->is_inside_tree() || control->is_set_as_toplevel()) {
+ if (!control->is_inside_tree() || control->is_set_as_top_level()) {
break;
}
if (gui.key_event_accepted) {
@@ -1631,7 +1658,7 @@ void Viewport::_gui_call_input(Control *p_control, const Ref<InputEvent> &p_inpu
}
}
- if (ci->is_set_as_toplevel()) {
+ if (ci->is_set_as_top_level()) {
break;
}
@@ -1655,7 +1682,7 @@ void Viewport::_gui_call_notification(Control *p_control, int p_what) {
break;
}
- if (!control->is_inside_tree() || control->is_set_as_toplevel()) {
+ if (!control->is_inside_tree() || control->is_set_as_top_level()) {
break;
}
if (control->data.mouse_filter == Control::MOUSE_FILTER_STOP) {
@@ -1663,7 +1690,7 @@ void Viewport::_gui_call_notification(Control *p_control, int p_what) {
}
}
- if (ci->is_set_as_toplevel()) {
+ if (ci->is_set_as_top_level()) {
break;
}
@@ -1721,7 +1748,7 @@ Control *Viewport::_gui_find_control_at_pos(CanvasItem *p_node, const Point2 &p_
if (!c || !c->clips_input() || c->has_point(matrix.affine_inverse().xform(p_global))) {
for (int i = p_node->get_child_count() - 1; i >= 0; i--) {
CanvasItem *ci = Object::cast_to<CanvasItem>(p_node->get_child(i));
- if (!ci || ci->is_set_as_toplevel()) {
+ if (!ci || ci->is_set_as_top_level()) {
continue;
}
@@ -1768,7 +1795,7 @@ bool Viewport::_gui_drop(Control *p_at_control, Point2 p_at_pos, bool p_just_che
p_at_pos = ci->get_transform().xform(p_at_pos);
- if (ci->is_set_as_toplevel()) {
+ if (ci->is_set_as_top_level()) {
break;
}
@@ -1782,18 +1809,12 @@ bool Viewport::_gui_drop(Control *p_at_control, Point2 p_at_pos, bool p_just_che
void Viewport::_gui_input_event(Ref<InputEvent> p_event) {
ERR_FAIL_COND(p_event.is_null());
- //?
- /*
- if (!is_visible()) {
- return; //simple and plain
- }
- */
-
Ref<InputEventMouseButton> mb = p_event;
-
if (mb.is_valid()) {
gui.key_event_accepted = false;
+ Control *over = nullptr;
+
Point2 mpos = mb->get_position();
if (mb->is_pressed()) {
Size2 pos = mpos;
@@ -1865,7 +1886,7 @@ void Viewport::_gui_input_event(Ref<InputEvent> p_event) {
}
}
- if (ci->is_set_as_toplevel()) {
+ if (ci->is_set_as_top_level()) {
break;
}
@@ -1897,8 +1918,6 @@ void Viewport::_gui_input_event(Ref<InputEvent> p_event) {
}
_gui_cancel_tooltip();
- //gui.tooltip_popup->hide();
-
} else {
if (gui.drag_data.get_type() != Variant::NIL && mb->get_button_index() == BUTTON_LEFT) {
if (gui.drag_mouse_over) {
@@ -1948,12 +1967,36 @@ void Viewport::_gui_input_event(Ref<InputEvent> p_event) {
gui.drag_data=Variant(); //always clear
}*/
+ // In case the mouse was released after for example dragging a scrollbar,
+ // check whether the current control is different from the stored one. If
+ // it is different, rather than wait for it to be updated the next time the
+ // mouse is moved, notify the control so that it can e.g. drop the highlight.
+ // This code is duplicated from the mm.is_valid()-case further below.
+ if (gui.mouse_focus) {
+ over = gui.mouse_focus;
+ } else {
+ over = _gui_find_control(mpos);
+ }
+
+ if (gui.mouse_focus_mask == 0 && over != gui.mouse_over) {
+ if (gui.mouse_over) {
+ _gui_call_notification(gui.mouse_over, Control::NOTIFICATION_MOUSE_EXIT);
+ }
+
+ _gui_cancel_tooltip();
+
+ if (over) {
+ _gui_call_notification(over, Control::NOTIFICATION_MOUSE_ENTER);
+ }
+ }
+
+ gui.mouse_over = over;
+
set_input_as_handled();
}
}
Ref<InputEventMouseMotion> mm = p_event;
-
if (mm.is_valid()) {
gui.key_event_accepted = false;
Point2 mpos = mm->get_position();
@@ -1993,7 +2036,7 @@ void Viewport::_gui_input_event(Ref<InputEvent> p_event) {
}
}
- if (ci->is_set_as_toplevel()) {
+ if (ci->is_set_as_top_level()) {
break;
}
@@ -2008,10 +2051,11 @@ void Viewport::_gui_input_event(Ref<InputEvent> p_event) {
}
}
+ // These sections of code are reused in the mb.is_valid() case further up
+ // for the purpose of notifying controls about potential changes in focus
+ // when the mousebutton is released.
if (gui.mouse_focus) {
over = gui.mouse_focus;
- //recompute focus_inv_xform again here
-
} else {
over = _gui_find_control(mpos);
}
@@ -2052,8 +2096,8 @@ void Viewport::_gui_input_event(Ref<InputEvent> p_event) {
bool is_tooltip_shown = false;
if (gui.tooltip_popup) {
- if (can_tooltip && gui.tooltip) {
- String tooltip = _gui_get_tooltip(over, gui.tooltip->get_global_transform().xform_inv(mpos));
+ if (can_tooltip && gui.tooltip_control) {
+ String tooltip = _gui_get_tooltip(over, gui.tooltip_control->get_global_transform().xform_inv(mpos));
if (tooltip.length() == 0) {
_gui_cancel_tooltip();
@@ -2078,14 +2122,12 @@ void Viewport::_gui_input_event(Ref<InputEvent> p_event) {
}
if (can_tooltip && !is_tooltip_shown) {
- gui.tooltip = over;
- gui.tooltip_pos = over->get_screen_transform().xform(pos); //(parent_xform * get_transform()).affine_inverse().xform(pos);
+ gui.tooltip_control = over;
+ gui.tooltip_pos = over->get_screen_transform().xform(pos);
gui.tooltip_timer = gui.tooltip_delay;
}
}
- //pos = gui.focus_inv_xform.xform(pos);
-
mm->set_position(pos);
Control::CursorShape cursor_shape = Control::CURSOR_ARROW;
@@ -2105,7 +2147,7 @@ void Viewport::_gui_input_event(Ref<InputEvent> p_event) {
if (c->data.mouse_filter == Control::MOUSE_FILTER_STOP) {
break;
}
- if (c->is_set_as_toplevel()) {
+ if (c->is_set_as_top_level()) {
break;
}
c = c->get_parent_control();
@@ -2332,7 +2374,6 @@ void Viewport::_gui_input_event(Ref<InputEvent> p_event) {
//keyboard focus
//if (from && p_event->is_pressed() && !p_event->get_alt() && !p_event->get_metakey() && !p_event->key->get_command()) {
-
Ref<InputEventKey> k = p_event;
//need to check for mods, otherwise any combination of alt/ctrl/shift+<up/down/left/righ/etc> is handled here when it shouldn't be.
bool mods = k.is_valid() && (k->get_control() || k->get_alt() || k->get_shift() || k->get_metakey());
@@ -2351,19 +2392,19 @@ void Viewport::_gui_input_event(Ref<InputEvent> p_event) {
}
if (!mods && p_event->is_action_pressed("ui_up") && input->is_action_just_pressed("ui_up")) {
- next = from->_get_focus_neighbour(MARGIN_TOP);
+ next = from->_get_focus_neighbor(MARGIN_TOP);
}
if (!mods && p_event->is_action_pressed("ui_left") && input->is_action_just_pressed("ui_left")) {
- next = from->_get_focus_neighbour(MARGIN_LEFT);
+ next = from->_get_focus_neighbor(MARGIN_LEFT);
}
if (!mods && p_event->is_action_pressed("ui_right") && input->is_action_just_pressed("ui_right")) {
- next = from->_get_focus_neighbour(MARGIN_RIGHT);
+ next = from->_get_focus_neighbor(MARGIN_RIGHT);
}
if (!mods && p_event->is_action_pressed("ui_down") && input->is_action_just_pressed("ui_down")) {
- next = from->_get_focus_neighbour(MARGIN_BOTTOM);
+ next = from->_get_focus_neighbor(MARGIN_BOTTOM);
}
if (next) {
@@ -2404,7 +2445,7 @@ void Viewport::_gui_set_drag_preview(Control *p_base, Control *p_control) {
if (gui.drag_preview) {
memdelete(gui.drag_preview);
}
- p_control->set_as_toplevel(true);
+ p_control->set_as_top_level(true);
p_control->set_position(gui.last_mouse_pos);
p_base->get_root_parent_control()->add_child(p_control); //add as child of viewport
p_control->raise();
@@ -2422,7 +2463,7 @@ void Viewport::_gui_unfocus_control(Control *p_control) {
}
}
-void Viewport::_gui_hid_control(Control *p_control) {
+void Viewport::_gui_hide_control(Control *p_control) {
if (gui.mouse_focus == p_control) {
_drop_mouse_focus();
}
@@ -2436,7 +2477,7 @@ void Viewport::_gui_hid_control(Control *p_control) {
if (gui.drag_mouse_over == p_control) {
gui.drag_mouse_over = nullptr;
}
- if (gui.tooltip == p_control) {
+ if (gui.tooltip_control == p_control) {
_gui_cancel_tooltip();
}
}
@@ -2459,8 +2500,8 @@ void Viewport::_gui_remove_control(Control *p_control) {
if (gui.drag_mouse_over == p_control) {
gui.drag_mouse_over = nullptr;
}
- if (gui.tooltip == p_control) {
- gui.tooltip = nullptr;
+ if (gui.tooltip_control == p_control) {
+ gui.tooltip_control = nullptr;
}
}
@@ -2998,7 +3039,10 @@ void Viewport::unhandled_input(const Ref<InputEvent> &p_event, bool p_local_coor
ev = p_event;
}
+ // Unhandled Input
get_tree()->_call_input_pause(unhandled_input_group, "_unhandled_input", ev, this);
+
+ // Unhandled key Input - used for performance reasons - This is called a lot less then _unhandled_input since it ignores MouseMotion, etc
if (!is_input_handled() && Object::cast_to<InputEventKey>(*ev) != nullptr) {
get_tree()->_call_input_pause(unhandled_key_input_group, "_unhandled_key_input", ev, this);
}
@@ -3089,14 +3133,18 @@ Variant Viewport::gui_get_drag_data() const {
String Viewport::get_configuration_warning() const {
/*if (get_parent() && !Object::cast_to<Control>(get_parent()) && !render_target) {
-
return TTR("This viewport is not set as render target. If you intend for it to display its contents directly to the screen, make it a child of a Control so it can obtain a size. Otherwise, make it a RenderTarget and assign its internal texture to some node for display.");
}*/
+ String warning = Node::get_configuration_warning();
+
if (size.x == 0 || size.y == 0) {
- return TTR("Viewport size must be greater than 0 to render anything.");
+ if (!warning.empty()) {
+ warning += "\n\n";
+ }
+ warning += TTR("Viewport size must be greater than 0 to render anything.");
}
- return String();
+ return warning;
}
void Viewport::gui_reset_canvas_sort_index() {
@@ -3133,6 +3181,25 @@ Viewport::ScreenSpaceAA Viewport::get_screen_space_aa() const {
return screen_space_aa;
}
+void Viewport::set_use_debanding(bool p_use_debanding) {
+ if (use_debanding == p_use_debanding)
+ return;
+ use_debanding = p_use_debanding;
+ RS::get_singleton()->viewport_set_use_debanding(viewport, p_use_debanding);
+}
+
+bool Viewport::is_using_debanding() const {
+ return use_debanding;
+}
+
+void Viewport::set_lod_threshold(float p_pixels) {
+ lod_threshold = p_pixels;
+ RS::get_singleton()->viewport_set_lod_threshold(viewport, lod_threshold);
+}
+float Viewport::get_lod_threshold() const {
+ return lod_threshold;
+}
+
void Viewport::set_debug_draw(DebugDraw p_debug_draw) {
debug_draw = p_debug_draw;
RS::get_singleton()->viewport_set_debug_draw(viewport, RS::ViewportDebugDraw(p_debug_draw));
@@ -3154,6 +3221,24 @@ bool Viewport::is_snap_controls_to_pixels_enabled() const {
return snap_controls_to_pixels;
}
+void Viewport::set_snap_2d_transforms_to_pixel(bool p_enable) {
+ snap_2d_transforms_to_pixel = p_enable;
+ RS::get_singleton()->viewport_set_snap_2d_transforms_to_pixel(viewport, snap_2d_transforms_to_pixel);
+}
+
+bool Viewport::is_snap_2d_transforms_to_pixel_enabled() const {
+ return snap_2d_transforms_to_pixel;
+}
+
+void Viewport::set_snap_2d_vertices_to_pixel(bool p_enable) {
+ snap_2d_vertices_to_pixel = p_enable;
+ RS::get_singleton()->viewport_set_snap_2d_vertices_to_pixel(viewport, snap_2d_vertices_to_pixel);
+}
+
+bool Viewport::is_snap_2d_vertices_to_pixel_enabled() const {
+ return snap_2d_vertices_to_pixel;
+}
+
bool Viewport::gui_is_dragging() const {
return gui.dragging;
}
@@ -3208,11 +3293,28 @@ void Viewport::_validate_property(PropertyInfo &property) const {
}
void Viewport::set_default_canvas_item_texture_filter(DefaultCanvasItemTextureFilter p_filter) {
+ ERR_FAIL_INDEX(p_filter, DEFAULT_CANVAS_ITEM_TEXTURE_FILTER_MAX);
+
if (default_canvas_item_texture_filter == p_filter) {
return;
}
default_canvas_item_texture_filter = p_filter;
- _propagate_update_default_filter(this);
+ switch (default_canvas_item_texture_filter) {
+ case DEFAULT_CANVAS_ITEM_TEXTURE_FILTER_NEAREST:
+ RS::get_singleton()->viewport_set_default_canvas_item_texture_filter(viewport, RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST);
+ break;
+ case DEFAULT_CANVAS_ITEM_TEXTURE_FILTER_LINEAR:
+ RS::get_singleton()->viewport_set_default_canvas_item_texture_filter(viewport, RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR);
+ break;
+ case DEFAULT_CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS:
+ RS::get_singleton()->viewport_set_default_canvas_item_texture_filter(viewport, RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS);
+ break;
+ case DEFAULT_CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS:
+ RS::get_singleton()->viewport_set_default_canvas_item_texture_filter(viewport, RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS);
+ break;
+ default: {
+ }
+ }
}
Viewport::DefaultCanvasItemTextureFilter Viewport::get_default_canvas_item_texture_filter() const {
@@ -3220,37 +3322,31 @@ Viewport::DefaultCanvasItemTextureFilter Viewport::get_default_canvas_item_textu
}
void Viewport::set_default_canvas_item_texture_repeat(DefaultCanvasItemTextureRepeat p_repeat) {
+ ERR_FAIL_INDEX(p_repeat, DEFAULT_CANVAS_ITEM_TEXTURE_REPEAT_MAX);
+
if (default_canvas_item_texture_repeat == p_repeat) {
return;
}
- default_canvas_item_texture_repeat = p_repeat;
- _propagate_update_default_repeat(this);
-}
-
-Viewport::DefaultCanvasItemTextureRepeat Viewport::get_default_canvas_item_texture_repeat() const {
- return default_canvas_item_texture_repeat;
-}
-void Viewport::_propagate_update_default_filter(Node *p_node) {
- CanvasItem *ci = Object::cast_to<CanvasItem>(p_node);
- if (ci) {
- ci->_update_texture_filter_changed(false);
- }
+ default_canvas_item_texture_repeat = p_repeat;
- for (int i = 0; i < p_node->get_child_count(); i++) {
- _propagate_update_default_filter(p_node->get_child(i));
+ switch (default_canvas_item_texture_repeat) {
+ case DEFAULT_CANVAS_ITEM_TEXTURE_REPEAT_DISABLED:
+ RS::get_singleton()->viewport_set_default_canvas_item_texture_repeat(viewport, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
+ break;
+ case DEFAULT_CANVAS_ITEM_TEXTURE_REPEAT_ENABLED:
+ RS::get_singleton()->viewport_set_default_canvas_item_texture_repeat(viewport, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED);
+ break;
+ case DEFAULT_CANVAS_ITEM_TEXTURE_REPEAT_MIRROR:
+ RS::get_singleton()->viewport_set_default_canvas_item_texture_repeat(viewport, RS::CANVAS_ITEM_TEXTURE_REPEAT_MIRROR);
+ break;
+ default: {
+ }
}
}
-void Viewport::_propagate_update_default_repeat(Node *p_node) {
- CanvasItem *ci = Object::cast_to<CanvasItem>(p_node);
- if (ci) {
- ci->_update_texture_repeat_changed(false);
- }
-
- for (int i = 0; i < p_node->get_child_count(); i++) {
- _propagate_update_default_repeat(p_node->get_child(i));
- }
+Viewport::DefaultCanvasItemTextureRepeat Viewport::get_default_canvas_item_texture_repeat() const {
+ return default_canvas_item_texture_repeat;
}
DisplayServer::WindowID Viewport::get_window_id() const {
@@ -3294,6 +3390,24 @@ void Viewport::pass_mouse_focus_to(Viewport *p_viewport, Control *p_control) {
}
}
+void Viewport::set_sdf_oversize(SDFOversize p_sdf_oversize) {
+ ERR_FAIL_INDEX(p_sdf_oversize, SDF_OVERSIZE_MAX);
+ sdf_oversize = p_sdf_oversize;
+ RS::get_singleton()->viewport_set_sdf_oversize_and_scale(viewport, RS::ViewportSDFOversize(sdf_oversize), RS::ViewportSDFScale(sdf_scale));
+}
+Viewport::SDFOversize Viewport::get_sdf_oversize() const {
+ return sdf_oversize;
+}
+
+void Viewport::set_sdf_scale(SDFScale p_sdf_scale) {
+ ERR_FAIL_INDEX(p_sdf_scale, SDF_SCALE_MAX);
+ sdf_scale = p_sdf_scale;
+ RS::get_singleton()->viewport_set_sdf_oversize_and_scale(viewport, RS::ViewportSDFOversize(sdf_oversize), RS::ViewportSDFScale(sdf_scale));
+}
+Viewport::SDFScale Viewport::get_sdf_scale() const {
+ return sdf_scale;
+}
+
void Viewport::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_world_2d", "world_2d"), &Viewport::set_world_2d);
ClassDB::bind_method(D_METHOD("get_world_2d"), &Viewport::get_world_2d);
@@ -3319,6 +3433,9 @@ void Viewport::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_screen_space_aa", "screen_space_aa"), &Viewport::set_screen_space_aa);
ClassDB::bind_method(D_METHOD("get_screen_space_aa"), &Viewport::get_screen_space_aa);
+ ClassDB::bind_method(D_METHOD("set_use_debanding", "enable"), &Viewport::set_use_debanding);
+ ClassDB::bind_method(D_METHOD("is_using_debanding"), &Viewport::is_using_debanding);
+
ClassDB::bind_method(D_METHOD("set_debug_draw", "debug_draw"), &Viewport::set_debug_draw);
ClassDB::bind_method(D_METHOD("get_debug_draw"), &Viewport::get_debug_draw);
@@ -3365,6 +3482,12 @@ void Viewport::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_snap_controls_to_pixels", "enabled"), &Viewport::set_snap_controls_to_pixels);
ClassDB::bind_method(D_METHOD("is_snap_controls_to_pixels_enabled"), &Viewport::is_snap_controls_to_pixels_enabled);
+ ClassDB::bind_method(D_METHOD("set_snap_2d_transforms_to_pixel", "enabled"), &Viewport::set_snap_2d_transforms_to_pixel);
+ ClassDB::bind_method(D_METHOD("is_snap_2d_transforms_to_pixel_enabled"), &Viewport::is_snap_2d_transforms_to_pixel_enabled);
+
+ ClassDB::bind_method(D_METHOD("set_snap_2d_vertices_to_pixel", "enabled"), &Viewport::set_snap_2d_vertices_to_pixel);
+ ClassDB::bind_method(D_METHOD("is_snap_2d_vertices_to_pixel_enabled"), &Viewport::is_snap_2d_vertices_to_pixel_enabled);
+
ClassDB::bind_method(D_METHOD("set_shadow_atlas_quadrant_subdiv", "quadrant", "subdiv"), &Viewport::set_shadow_atlas_quadrant_subdiv);
ClassDB::bind_method(D_METHOD("get_shadow_atlas_quadrant_subdiv", "quadrant"), &Viewport::get_shadow_atlas_quadrant_subdiv);
@@ -3384,14 +3507,27 @@ void Viewport::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_default_canvas_item_texture_repeat", "mode"), &Viewport::set_default_canvas_item_texture_repeat);
ClassDB::bind_method(D_METHOD("get_default_canvas_item_texture_repeat"), &Viewport::get_default_canvas_item_texture_repeat);
+ ClassDB::bind_method(D_METHOD("set_sdf_oversize", "oversize"), &Viewport::set_sdf_oversize);
+ ClassDB::bind_method(D_METHOD("get_sdf_oversize"), &Viewport::get_sdf_oversize);
+
+ ClassDB::bind_method(D_METHOD("set_sdf_scale", "scale"), &Viewport::set_sdf_scale);
+ ClassDB::bind_method(D_METHOD("get_sdf_scale"), &Viewport::get_sdf_scale);
+
+ ClassDB::bind_method(D_METHOD("set_lod_threshold", "pixels"), &Viewport::set_lod_threshold);
+ ClassDB::bind_method(D_METHOD("get_lod_threshold"), &Viewport::get_lod_threshold);
+
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "own_world_3d"), "set_use_own_world_3d", "is_using_own_world_3d");
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "world_3d", PROPERTY_HINT_RESOURCE_TYPE, "World3D"), "set_world_3d", "get_world_3d");
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "world_2d", PROPERTY_HINT_RESOURCE_TYPE, "World2D", 0), "set_world_2d", "get_world_2d");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "transparent_bg"), "set_transparent_background", "has_transparent_background");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "handle_input_locally"), "set_handle_input_locally", "is_handling_input_locally");
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL, "snap_2d_transforms_to_pixel"), "set_snap_2d_transforms_to_pixel", "is_snap_2d_transforms_to_pixel_enabled");
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL, "snap_2d_vertices_to_pixel"), "set_snap_2d_vertices_to_pixel", "is_snap_2d_vertices_to_pixel_enabled");
ADD_GROUP("Rendering", "");
ADD_PROPERTY(PropertyInfo(Variant::INT, "msaa", PROPERTY_HINT_ENUM, "Disabled,2x,4x,8x,16x,AndroidVR 2x,AndroidVR 4x"), "set_msaa", "get_msaa");
ADD_PROPERTY(PropertyInfo(Variant::INT, "screen_space_aa", PROPERTY_HINT_ENUM, "Disabled,FXAA"), "set_screen_space_aa", "get_screen_space_aa");
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL, "use_debanding"), "set_use_debanding", "is_using_debanding");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "lod_threshold", PROPERTY_HINT_RANGE, "0,1024,0.1"), "set_lod_threshold", "get_lod_threshold");
ADD_PROPERTY(PropertyInfo(Variant::INT, "debug_draw", PROPERTY_HINT_ENUM, "Disabled,Unshaded,Overdraw,Wireframe"), "set_debug_draw", "get_debug_draw");
ADD_GROUP("Canvas Items", "canvas_item_");
ADD_PROPERTY(PropertyInfo(Variant::INT, "canvas_item_default_texture_filter", PROPERTY_HINT_ENUM, "Nearest,Linear,MipmapLinear,MipmapNearest"), "set_default_canvas_item_texture_filter", "get_default_canvas_item_texture_filter");
@@ -3405,6 +3541,9 @@ void Viewport::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "gui_disable_input"), "set_disable_input", "is_input_disabled");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "gui_snap_controls_to_pixels"), "set_snap_controls_to_pixels", "is_snap_controls_to_pixels_enabled");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "gui_embed_subwindows"), "set_embed_subwindows_hint", "get_embed_subwindows_hint");
+ ADD_GROUP("SDF", "sdf_");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "sdf_oversize", PROPERTY_HINT_ENUM, "100%,120%,150%,200%"), "set_sdf_oversize", "get_sdf_oversize");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "sdf_scale", PROPERTY_HINT_ENUM, "100%,50%,25%"), "set_sdf_scale", "get_sdf_scale");
ADD_GROUP("Shadow Atlas", "shadow_atlas_");
ADD_PROPERTY(PropertyInfo(Variant::INT, "shadow_atlas_size"), "set_shadow_atlas_size", "get_shadow_atlas_size");
ADD_PROPERTYI(PropertyInfo(Variant::INT, "shadow_atlas_quad_0", PROPERTY_HINT_ENUM, "Disabled,1 Shadow,4 Shadows,16 Shadows,64 Shadows,256 Shadows,1024 Shadows"), "set_shadow_atlas_quadrant_subdiv", "get_shadow_atlas_quadrant_subdiv", 0);
@@ -3463,6 +3602,7 @@ void Viewport::_bind_methods() {
BIND_ENUM_CONSTANT(DEBUG_DRAW_SDFGI);
BIND_ENUM_CONSTANT(DEBUG_DRAW_SDFGI_PROBES);
BIND_ENUM_CONSTANT(DEBUG_DRAW_GI_BUFFER);
+ BIND_ENUM_CONSTANT(DEBUG_DRAW_DISABLE_LOD);
BIND_ENUM_CONSTANT(DEFAULT_CANVAS_ITEM_TEXTURE_FILTER_NEAREST);
BIND_ENUM_CONSTANT(DEFAULT_CANVAS_ITEM_TEXTURE_FILTER_LINEAR);
@@ -3474,6 +3614,17 @@ void Viewport::_bind_methods() {
BIND_ENUM_CONSTANT(DEFAULT_CANVAS_ITEM_TEXTURE_REPEAT_ENABLED);
BIND_ENUM_CONSTANT(DEFAULT_CANVAS_ITEM_TEXTURE_REPEAT_MIRROR);
BIND_ENUM_CONSTANT(DEFAULT_CANVAS_ITEM_TEXTURE_REPEAT_MAX);
+
+ BIND_ENUM_CONSTANT(SDF_OVERSIZE_100_PERCENT);
+ BIND_ENUM_CONSTANT(SDF_OVERSIZE_120_PERCENT);
+ BIND_ENUM_CONSTANT(SDF_OVERSIZE_150_PERCENT);
+ BIND_ENUM_CONSTANT(SDF_OVERSIZE_200_PERCENT);
+ BIND_ENUM_CONSTANT(SDF_OVERSIZE_MAX);
+
+ BIND_ENUM_CONSTANT(SDF_SCALE_100_PERCENT);
+ BIND_ENUM_CONSTANT(SDF_SCALE_50_PERCENT);
+ BIND_ENUM_CONSTANT(SDF_SCALE_25_PERCENT);
+ BIND_ENUM_CONSTANT(SDF_SCALE_MAX);
}
Viewport::Viewport() {
@@ -3514,6 +3665,8 @@ Viewport::Viewport() {
set_shadow_atlas_quadrant_subdiv(2, SHADOW_ATLAS_QUADRANT_SUBDIV_16);
set_shadow_atlas_quadrant_subdiv(3, SHADOW_ATLAS_QUADRANT_SUBDIV_64);
+ set_lod_threshold(lod_threshold);
+
String id = itos(get_instance_id());
input_group = "_vp_input" + id;
gui_input_group = "_vp_gui_input" + id;
@@ -3522,14 +3675,13 @@ Viewport::Viewport() {
disable_input = false;
- //window tooltip
+ // Window tooltip.
gui.tooltip_timer = -1;
- //gui.tooltip_timer->force_parent_owned();
gui.tooltip_delay = GLOBAL_DEF("gui/timers/tooltip_delay_sec", 0.5);
ProjectSettings::get_singleton()->set_custom_property_info("gui/timers/tooltip_delay_sec", PropertyInfo(Variant::FLOAT, "gui/timers/tooltip_delay_sec", PROPERTY_HINT_RANGE, "0,5,0.01,or_greater")); // No negative numbers
- gui.tooltip = nullptr;
+ gui.tooltip_control = nullptr;
gui.tooltip_label = nullptr;
gui.drag_preview = nullptr;
gui.drag_attempted = false;
@@ -3546,6 +3698,9 @@ Viewport::Viewport() {
debug_draw = DEBUG_DRAW_DISABLED;
snap_controls_to_pixels = true;
+ snap_2d_transforms_to_pixel = false;
+ snap_2d_vertices_to_pixel = false;
+
physics_last_mouse_state.alt = false;
physics_last_mouse_state.control = false;
physics_last_mouse_state.shift = false;
@@ -3558,6 +3713,10 @@ Viewport::Viewport() {
default_canvas_item_texture_filter = DEFAULT_CANVAS_ITEM_TEXTURE_FILTER_LINEAR;
default_canvas_item_texture_repeat = DEFAULT_CANVAS_ITEM_TEXTURE_REPEAT_DISABLED;
+
+ sdf_oversize = SDF_OVERSIZE_120_PERCENT;
+ sdf_scale = SDF_SCALE_50_PERCENT;
+ set_sdf_oversize(SDF_OVERSIZE_120_PERCENT); //set to server
}
Viewport::~Viewport() {
@@ -3680,7 +3839,7 @@ void SubViewport::_bind_methods() {
BIND_ENUM_CONSTANT(CLEAR_MODE_ALWAYS);
BIND_ENUM_CONSTANT(CLEAR_MODE_NEVER);
- BIND_ENUM_CONSTANT(CLEAR_MODE_ONLY_NEXT_FRAME);
+ BIND_ENUM_CONSTANT(CLEAR_MODE_ONCE);
BIND_ENUM_CONSTANT(UPDATE_DISABLED);
BIND_ENUM_CONSTANT(UPDATE_ONCE);