diff options
Diffstat (limited to 'scene/main/viewport.cpp')
-rw-r--r-- | scene/main/viewport.cpp | 357 |
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); |