2014-02-10 02:10:30 +01:00
/**************************************************************************/
/* viewport.cpp */
/**************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/**************************************************************************/
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
/* "Software"), to deal in the Software without restriction, including */
/* without limitation the rights to use, copy, modify, merge, publish, */
/* distribute, sublicense, and/or sell copies of the Software, and to */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions: */
/* */
/* The above copyright notice and this permission notice shall be */
/* included in all copies or substantial portions of the Software. */
/* */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
2018-01-05 00:50:27 +01:00
2014-02-10 02:10:30 +01:00
# include "viewport.h"
2017-08-27 21:07:15 +02:00
2022-02-12 02:46:22 +01:00
# include "core/config/project_settings.h"
2020-02-27 03:30:20 +01:00
# include "core/debugger/engine_debugger.h"
2020-09-03 13:22:16 +02:00
# include "core/string/translation.h"
2021-08-13 01:05:59 +02:00
# include "core/templates/pair.h"
2022-11-10 22:55:57 +01:00
# include "core/templates/sort_array.h"
2021-09-16 21:28:20 +02:00
# include "scene/2d/audio_listener_2d.h"
2020-04-28 17:04:07 +02:00
# include "scene/2d/camera_2d.h"
2024-02-26 07:15:31 +01:00
# include "scene/2d/physics/collision_object_2d.h"
2021-07-04 03:43:23 +02:00
# ifndef _3D_DISABLED
2021-09-16 21:28:20 +02:00
# include "scene/3d/audio_listener_3d.h"
2020-03-26 22:49:16 +01:00
# include "scene/3d/camera_3d.h"
2024-02-26 07:15:31 +01:00
# include "scene/3d/physics/collision_object_3d.h"
2019-02-12 17:18:13 +01:00
# include "scene/3d/world_environment.h"
2021-07-04 03:43:23 +02:00
# endif // _3D_DISABLED
2014-09-15 16:33:30 +02:00
# include "scene/gui/control.h"
2016-01-17 02:41:10 +01:00
# include "scene/gui/label.h"
2021-08-13 01:05:59 +02:00
# include "scene/gui/popup.h"
2021-08-20 11:49:19 +02:00
# include "scene/gui/popup_menu.h"
2020-11-21 22:32:26 +01:00
# include "scene/gui/subviewport_container.h"
2018-08-25 00:03:26 +02:00
# include "scene/main/canvas_layer.h"
2020-03-04 17:36:09 +01:00
# include "scene/main/window.h"
2017-08-27 21:07:15 +02:00
# include "scene/resources/mesh.h"
2021-08-13 01:05:59 +02:00
# include "scene/resources/text_line.h"
# include "scene/resources/world_2d.h"
2016-01-17 02:41:10 +01:00
# include "scene/scene_string_names.h"
2021-08-27 19:28:23 +02:00
# include "servers/audio_server.h"
2021-11-23 22:16:03 +01:00
# include "servers/rendering/rendering_server_globals.h"
2016-01-17 02:41:10 +01:00
2017-01-10 05:04:31 +01:00
void ViewportTexture : : setup_local_to_scene ( ) {
2023-05-18 16:49:10 +02:00
// For the same target viewport, setup is only allowed once to prevent multiple free or multiple creations.
if ( ! vp_changed ) {
return ;
}
2023-04-06 14:47:49 +02:00
if ( vp_pending ) {
return ;
}
2022-09-29 11:53:28 +02:00
Node * loc_scene = get_local_scene ( ) ;
if ( ! loc_scene ) {
2021-09-03 02:40:52 +02:00
return ;
}
2017-01-10 05:04:31 +01:00
if ( vp ) {
vp - > viewport_textures . erase ( this ) ;
2022-08-14 13:17:45 +02:00
vp = nullptr ;
2017-01-10 05:04:31 +01:00
}
2023-04-06 14:47:49 +02:00
if ( loc_scene - > is_ready ( ) ) {
_setup_local_to_scene ( loc_scene ) ;
2019-06-24 21:13:06 +02:00
} else {
2023-04-06 14:47:49 +02:00
loc_scene - > connect ( SNAME ( " ready " ) , callable_mp ( this , & ViewportTexture : : _setup_local_to_scene ) . bind ( loc_scene ) , CONNECT_ONE_SHOT ) ;
vp_pending = true ;
2019-06-24 21:13:06 +02:00
}
2017-01-10 05:04:31 +01:00
}
2023-07-08 13:38:27 +02:00
void ViewportTexture : : reset_local_to_scene ( ) {
2023-05-18 16:49:10 +02:00
vp_changed = true ;
2017-01-10 05:04:31 +01:00
2022-08-14 13:17:45 +02:00
if ( vp ) {
vp - > viewport_textures . erase ( this ) ;
vp = nullptr ;
}
2023-05-18 16:49:10 +02:00
if ( proxy . is_valid ( ) & & proxy_ph . is_null ( ) ) {
proxy_ph = RS : : get_singleton ( ) - > texture_2d_placeholder_create ( ) ;
RS : : get_singleton ( ) - > texture_proxy_update ( proxy , proxy_ph ) ;
2022-08-14 13:17:45 +02:00
}
2023-07-08 13:38:27 +02:00
}
void ViewportTexture : : set_viewport_path_in_scene ( const NodePath & p_path ) {
if ( path = = p_path ) {
return ;
}
path = p_path ;
reset_local_to_scene ( ) ;
2022-08-14 13:17:45 +02:00
if ( get_local_scene ( ) & & ! path . is_empty ( ) ) {
2017-01-10 05:04:31 +01:00
setup_local_to_scene ( ) ;
2022-08-14 13:17:45 +02:00
} else {
emit_changed ( ) ;
2017-01-10 05:04:31 +01:00
}
}
NodePath ViewportTexture : : get_viewport_path_in_scene ( ) const {
return path ;
}
2016-10-05 06:26:35 +02:00
int ViewportTexture : : get_width ( ) const {
2023-04-06 14:47:49 +02:00
if ( ! vp ) {
if ( ! vp_pending ) {
ERR_PRINT ( " Viewport Texture must be set to use it. " ) ;
}
return 0 ;
}
2016-10-03 21:33:42 +02:00
return vp - > size . width ;
2014-02-10 02:10:30 +01:00
}
2020-05-14 14:29:06 +02:00
2016-10-05 06:26:35 +02:00
int ViewportTexture : : get_height ( ) const {
2023-04-06 14:47:49 +02:00
if ( ! vp ) {
if ( ! vp_pending ) {
ERR_PRINT ( " Viewport Texture must be set to use it. " ) ;
}
return 0 ;
}
2016-10-03 21:33:42 +02:00
return vp - > size . height ;
2014-02-10 02:10:30 +01:00
}
2020-05-14 14:29:06 +02:00
2016-10-05 06:26:35 +02:00
Size2 ViewportTexture : : get_size ( ) const {
2023-04-06 14:47:49 +02:00
if ( ! vp ) {
if ( ! vp_pending ) {
ERR_PRINT ( " Viewport Texture must be set to use it. " ) ;
}
return Size2 ( ) ;
}
2016-10-03 21:33:42 +02:00
return vp - > size ;
2014-02-10 02:10:30 +01:00
}
2020-05-14 14:29:06 +02:00
2016-10-05 06:26:35 +02:00
RID ViewportTexture : : get_rid ( ) const {
2019-06-24 21:13:06 +02:00
if ( proxy . is_null ( ) ) {
2020-03-27 19:21:27 +01:00
proxy_ph = RS : : get_singleton ( ) - > texture_2d_placeholder_create ( ) ;
proxy = RS : : get_singleton ( ) - > texture_proxy_create ( proxy_ph ) ;
2019-06-24 21:13:06 +02:00
}
2017-12-04 19:55:20 +01:00
return proxy ;
2014-02-10 02:10:30 +01:00
}
2016-10-05 06:26:35 +02:00
bool ViewportTexture : : has_alpha ( ) const {
2014-02-10 02:10:30 +01:00
return false ;
}
2020-05-14 14:29:06 +02:00
2021-03-28 13:32:17 +02:00
Ref < Image > ViewportTexture : : get_image ( ) const {
2023-04-06 14:47:49 +02:00
if ( ! vp ) {
if ( ! vp_pending ) {
ERR_PRINT ( " Viewport Texture must be set to use it. " ) ;
}
return Ref < Image > ( ) ;
}
2020-03-27 19:21:27 +01:00
return RS : : get_singleton ( ) - > texture_2d_get ( vp - > texture_rid ) ;
2017-01-10 05:04:31 +01:00
}
2023-04-06 14:47:49 +02:00
void ViewportTexture : : _setup_local_to_scene ( const Node * p_loc_scene ) {
2023-06-27 00:12:50 +02:00
// Always reset this, even if this call fails with an error.
vp_pending = false ;
2023-06-05 14:56:54 +02:00
Node * vpn = p_loc_scene - > get_node_or_null ( path ) ;
ERR_FAIL_NULL_MSG ( vpn , " Path to node is invalid: ' " + path + " '. " ) ;
2023-04-06 14:47:49 +02:00
vp = Object : : cast_to < Viewport > ( vpn ) ;
2023-06-05 14:56:54 +02:00
ERR_FAIL_NULL_MSG ( vp , " Path to node does not point to a viewport: ' " + path + " '. " ) ;
2023-04-06 14:47:49 +02:00
vp - > viewport_textures . insert ( this ) ;
ERR_FAIL_NULL ( RenderingServer : : get_singleton ( ) ) ;
if ( proxy_ph . is_valid ( ) ) {
RS : : get_singleton ( ) - > texture_proxy_update ( proxy , vp - > texture_rid ) ;
RS : : get_singleton ( ) - > free ( proxy_ph ) ;
2023-05-18 16:49:10 +02:00
proxy_ph = RID ( ) ;
2023-04-06 14:47:49 +02:00
} else {
ERR_FAIL_COND ( proxy . is_valid ( ) ) ; // Should be invalid.
proxy = RS : : get_singleton ( ) - > texture_proxy_create ( vp - > texture_rid ) ;
}
2023-05-18 16:49:10 +02:00
vp_changed = false ;
2022-08-14 13:17:45 +02:00
emit_changed ( ) ;
2023-04-06 14:47:49 +02:00
}
2017-01-10 05:04:31 +01:00
void ViewportTexture : : _bind_methods ( ) {
2017-02-13 12:47:24 +01:00
ClassDB : : bind_method ( D_METHOD ( " set_viewport_path_in_scene " , " path " ) , & ViewportTexture : : set_viewport_path_in_scene ) ;
ClassDB : : bind_method ( D_METHOD ( " get_viewport_path_in_scene " ) , & ViewportTexture : : get_viewport_path_in_scene ) ;
2017-01-10 05:04:31 +01:00
2023-05-21 16:28:41 +02:00
ADD_PROPERTY ( PropertyInfo ( Variant : : NODE_PATH , " viewport_path " , PROPERTY_HINT_NODE_PATH_VALID_TYPES , " Viewport " , PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_NODE_PATH_FROM_SCENE_ROOT ) , " set_viewport_path_in_scene " , " get_viewport_path_in_scene " ) ;
2017-01-10 05:04:31 +01:00
}
ViewportTexture : : ViewportTexture ( ) {
set_local_to_scene ( true ) ;
2014-02-10 02:10:30 +01:00
}
2017-01-10 05:04:31 +01:00
ViewportTexture : : ~ ViewportTexture ( ) {
if ( vp ) {
vp - > viewport_textures . erase ( this ) ;
}
2017-12-04 19:55:20 +01:00
2022-12-12 18:42:37 +01:00
ERR_FAIL_NULL ( RenderingServer : : get_singleton ( ) ) ;
2019-06-24 21:13:06 +02:00
if ( proxy_ph . is_valid ( ) ) {
2020-03-27 19:21:27 +01:00
RS : : get_singleton ( ) - > free ( proxy_ph ) ;
2019-06-24 21:13:06 +02:00
}
2019-07-29 23:19:31 +02:00
if ( proxy . is_valid ( ) ) {
2020-03-27 19:21:27 +01:00
RS : : get_singleton ( ) - > free ( proxy ) ;
2019-07-29 23:19:31 +02:00
}
2014-02-10 02:10:30 +01:00
}
2023-04-05 18:53:32 +02:00
void Viewport : : _process_dirty_canvas_parent_orders ( ) {
for ( const ObjectID & id : gui . canvas_parents_with_dirty_order ) {
Object * obj = ObjectDB : : get_instance ( id ) ;
if ( ! obj ) {
continue ; // May have been deleted.
}
Node * n = static_cast < Node * > ( obj ) ;
for ( int i = 0 ; i < n - > get_child_count ( ) ; i + + ) {
Node * c = n - > get_child ( i ) ;
CanvasItem * ci = Object : : cast_to < CanvasItem > ( c ) ;
if ( ci ) {
ci - > update_draw_order ( ) ;
continue ;
}
CanvasLayer * cl = Object : : cast_to < CanvasLayer > ( c ) ;
if ( cl ) {
cl - > update_draw_order ( ) ;
}
}
}
gui . canvas_parents_with_dirty_order . clear ( ) ;
}
2020-03-14 17:06:39 +01:00
void Viewport : : _sub_window_update_order ( ) {
2022-10-30 15:03:01 +01:00
if ( gui . sub_windows . size ( ) < 2 ) {
return ;
}
if ( ! gui . sub_windows [ gui . sub_windows . size ( ) - 1 ] . window - > get_flag ( Window : : FLAG_ALWAYS_ON_TOP ) ) {
int index = gui . sub_windows . size ( ) - 1 ;
while ( index > 0 & & gui . sub_windows [ index - 1 ] . window - > get_flag ( Window : : FLAG_ALWAYS_ON_TOP ) ) {
- - index ;
}
if ( index ! = ( gui . sub_windows . size ( ) - 1 ) ) {
SubWindow sw = gui . sub_windows [ gui . sub_windows . size ( ) - 1 ] ;
gui . sub_windows . remove_at ( gui . sub_windows . size ( ) - 1 ) ;
gui . sub_windows . insert ( index , sw ) ;
}
}
2020-03-14 17:06:39 +01:00
for ( int i = 0 ; i < gui . sub_windows . size ( ) ; i + + ) {
2020-03-27 19:21:27 +01:00
RS : : get_singleton ( ) - > canvas_item_set_draw_index ( gui . sub_windows [ i ] . canvas_item , i ) ;
2020-03-14 17:06:39 +01:00
}
}
void Viewport : : _sub_window_register ( Window * p_window ) {
ERR_FAIL_COND ( ! is_inside_tree ( ) ) ;
for ( int i = 0 ; i < gui . sub_windows . size ( ) ; i + + ) {
ERR_FAIL_COND ( gui . sub_windows [ i ] . window = = p_window ) ;
}
if ( gui . sub_windows . size ( ) = = 0 ) {
2020-03-27 19:21:27 +01:00
subwindow_canvas = RS : : get_singleton ( ) - > canvas_create ( ) ;
RS : : get_singleton ( ) - > viewport_attach_canvas ( viewport , subwindow_canvas ) ;
RS : : get_singleton ( ) - > viewport_set_canvas_stacking ( viewport , subwindow_canvas , SUBWINDOW_CANVAS_LAYER , 0 ) ;
2020-03-14 17:06:39 +01:00
}
SubWindow sw ;
2020-03-27 19:21:27 +01:00
sw . canvas_item = RS : : get_singleton ( ) - > canvas_item_create ( ) ;
RS : : get_singleton ( ) - > canvas_item_set_parent ( sw . canvas_item , subwindow_canvas ) ;
2020-03-14 17:06:39 +01:00
sw . window = p_window ;
gui . sub_windows . push_back ( sw ) ;
2023-06-04 19:09:54 +02:00
if ( gui . subwindow_drag = = SUB_WINDOW_DRAG_DISABLED ) {
2023-06-11 12:22:59 +02:00
if ( p_window - > get_flag ( Window : : FLAG_NO_FOCUS ) ) {
_sub_window_update_order ( ) ;
} else {
_sub_window_grab_focus ( p_window ) ;
}
2023-06-04 19:09:54 +02:00
} else {
int index = _sub_window_find ( gui . currently_dragged_subwindow ) ;
sw = gui . sub_windows [ index ] ;
gui . sub_windows . remove_at ( index ) ;
gui . sub_windows . push_back ( sw ) ;
_sub_window_update_order ( ) ;
}
2020-03-14 17:06:39 +01:00
2020-03-27 19:21:27 +01:00
RenderingServer : : get_singleton ( ) - > viewport_set_parent_viewport ( p_window - > viewport , viewport ) ;
2020-03-14 17:06:39 +01:00
}
void Viewport : : _sub_window_update ( Window * p_window ) {
2022-08-30 21:57:03 +02:00
int index = _sub_window_find ( p_window ) ;
2020-03-14 17:06:39 +01:00
ERR_FAIL_COND ( index = = - 1 ) ;
const SubWindow & sw = gui . sub_windows [ index ] ;
Transform2D pos ;
pos . set_origin ( p_window - > get_position ( ) ) ;
2020-03-27 19:21:27 +01:00
RS : : get_singleton ( ) - > canvas_item_clear ( sw . canvas_item ) ;
2020-03-14 17:06:39 +01:00
Rect2i r = Rect2i ( p_window - > get_position ( ) , sw . window - > get_size ( ) ) ;
if ( ! p_window - > get_flag ( Window : : FLAG_BORDERLESS ) ) {
2023-09-12 15:01:42 +02:00
Ref < StyleBox > panel = gui . subwindow_focused = = p_window ? p_window - > theme_cache . embedded_border : p_window - > theme_cache . embedded_unfocused_border ;
2020-03-14 17:06:39 +01:00
panel - > draw ( sw . canvas_item , r ) ;
// Draw the title bar text.
2023-09-12 15:01:42 +02:00
Ref < Font > title_font = p_window - > theme_cache . title_font ;
int font_size = p_window - > theme_cache . title_font_size ;
Color title_color = p_window - > theme_cache . title_color ;
int title_height = p_window - > theme_cache . title_height ;
int close_h_ofs = p_window - > theme_cache . close_h_offset ;
int close_v_ofs = p_window - > theme_cache . close_v_offset ;
2020-03-14 17:06:39 +01:00
2022-05-09 11:47:10 +02:00
TextLine title_text = TextLine ( p_window - > atr ( p_window - > get_title ( ) ) , title_font , font_size ) ;
2020-09-03 13:22:16 +02:00
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 ;
2023-09-12 15:01:42 +02:00
Color font_outline_color = p_window - > theme_cache . title_outline_modulate ;
int outline_size = p_window - > theme_cache . title_outline_size ;
2020-12-25 22:45:28 +01:00
if ( outline_size > 0 & & font_outline_color . a > 0 ) {
title_text . draw_outline ( sw . canvas_item , r . position + Point2 ( x , y ) , outline_size , font_outline_color ) ;
}
2020-09-03 13:22:16 +02:00
title_text . draw ( sw . canvas_item , r . position + Point2 ( x , y ) , title_color ) ;
2020-03-14 17:06:39 +01:00
2021-07-28 04:32:03 +02:00
bool pressed = gui . subwindow_focused = = sw . window & & gui . subwindow_drag = = SUB_WINDOW_DRAG_CLOSE & & gui . subwindow_drag_close_inside ;
2023-09-12 15:01:42 +02:00
Ref < Texture2D > close_icon = pressed ? p_window - > theme_cache . close_pressed : p_window - > theme_cache . close ;
2020-03-14 17:06:39 +01:00
close_icon - > draw ( sw . canvas_item , r . position + Vector2 ( r . size . width - close_h_ofs , - close_v_ofs ) ) ;
}
2020-03-27 19:21:27 +01:00
RS : : get_singleton ( ) - > canvas_item_add_texture_rect ( sw . canvas_item , r , sw . window - > get_texture ( ) - > get_rid ( ) ) ;
2020-03-14 17:06:39 +01:00
}
void Viewport : : _sub_window_grab_focus ( Window * p_window ) {
if ( p_window = = nullptr ) {
2021-09-10 16:58:33 +02:00
// Release current focus.
2020-03-14 17:06:39 +01:00
if ( gui . subwindow_focused ) {
gui . subwindow_focused - > _event_callback ( DisplayServer : : WINDOW_EVENT_FOCUS_OUT ) ;
gui . subwindow_focused = nullptr ;
gui . subwindow_drag = SUB_WINDOW_DRAG_DISABLED ;
}
Window * this_window = Object : : cast_to < Window > ( this ) ;
if ( this_window ) {
this_window - > _event_callback ( DisplayServer : : WINDOW_EVENT_FOCUS_IN ) ;
}
return ;
}
2020-03-20 21:51:53 +01:00
2023-08-19 11:20:38 +02:00
// The index needs to be update before every usage in case an event callback changed the window list.
2022-08-30 21:57:03 +02:00
int index = _sub_window_find ( p_window ) ;
2020-03-14 17:06:39 +01:00
ERR_FAIL_COND ( index = = - 1 ) ;
2020-03-20 21:51:53 +01:00
if ( p_window - > get_flag ( Window : : FLAG_NO_FOCUS ) ) {
2023-06-04 19:09:54 +02:00
// Release current focus.
if ( gui . subwindow_focused ) {
gui . subwindow_focused - > _event_callback ( DisplayServer : : WINDOW_EVENT_FOCUS_OUT ) ;
gui . subwindow_focused = nullptr ;
gui . subwindow_drag = SUB_WINDOW_DRAG_DISABLED ;
}
2021-09-10 16:58:33 +02:00
// Can only move to foreground, but no focus granted.
2023-08-19 11:20:38 +02:00
index = _sub_window_find ( p_window ) ;
ERR_FAIL_COND ( index = = - 1 ) ;
2020-03-20 21:51:53 +01:00
SubWindow sw = gui . sub_windows [ index ] ;
2021-07-04 00:17:03 +02:00
gui . sub_windows . remove_at ( index ) ;
2020-03-20 21:51:53 +01:00
gui . sub_windows . push_back ( sw ) ;
_sub_window_update_order ( ) ;
2021-09-10 16:58:33 +02:00
return ;
2020-03-20 21:51:53 +01:00
}
2020-03-14 17:06:39 +01:00
if ( gui . subwindow_focused ) {
if ( gui . subwindow_focused = = p_window ) {
2021-09-10 16:58:33 +02:00
return ; // Nothing to do.
2020-03-14 17:06:39 +01:00
}
gui . subwindow_focused - > _event_callback ( DisplayServer : : WINDOW_EVENT_FOCUS_OUT ) ;
gui . subwindow_drag = SUB_WINDOW_DRAG_DISABLED ;
} else {
Window * this_window = Object : : cast_to < Window > ( this ) ;
if ( this_window ) {
this_window - > _event_callback ( DisplayServer : : WINDOW_EVENT_FOCUS_OUT ) ;
}
}
Window * old_focus = gui . subwindow_focused ;
gui . subwindow_focused = p_window ;
gui . subwindow_focused - > _event_callback ( DisplayServer : : WINDOW_EVENT_FOCUS_IN ) ;
2021-09-10 16:58:33 +02:00
{ // Move to foreground.
2023-08-19 11:20:38 +02:00
index = _sub_window_find ( p_window ) ;
ERR_FAIL_COND ( index = = - 1 ) ;
2020-03-14 17:06:39 +01:00
SubWindow sw = gui . sub_windows [ index ] ;
2021-07-04 00:17:03 +02:00
gui . sub_windows . remove_at ( index ) ;
2020-03-14 17:06:39 +01:00
gui . sub_windows . push_back ( sw ) ;
index = gui . sub_windows . size ( ) - 1 ;
_sub_window_update_order ( ) ;
}
if ( old_focus ) {
_sub_window_update ( old_focus ) ;
}
_sub_window_update ( p_window ) ;
}
void Viewport : : _sub_window_remove ( Window * p_window ) {
2022-08-30 21:57:03 +02:00
int index = _sub_window_find ( p_window ) ;
ERR_FAIL_COND ( index = = - 1 ) ;
2022-12-12 18:42:37 +01:00
ERR_FAIL_NULL ( RenderingServer : : get_singleton ( ) ) ;
2023-01-06 21:48:20 +01:00
SubWindow sw = gui . sub_windows [ index ] ;
if ( gui . subwindow_over = = sw . window ) {
sw . window - > _mouse_leave_viewport ( ) ;
gui . subwindow_over = nullptr ;
}
RS : : get_singleton ( ) - > free ( sw . canvas_item ) ;
2022-08-30 21:57:03 +02:00
gui . sub_windows . remove_at ( index ) ;
2020-03-14 17:06:39 +01:00
if ( gui . sub_windows . size ( ) = = 0 ) {
2020-03-27 19:21:27 +01:00
RS : : get_singleton ( ) - > free ( subwindow_canvas ) ;
2020-03-14 17:06:39 +01:00
subwindow_canvas = RID ( ) ;
}
2023-06-04 19:09:54 +02:00
if ( gui . currently_dragged_subwindow = = p_window ) {
gui . subwindow_drag = SUB_WINDOW_DRAG_DISABLED ;
gui . currently_dragged_subwindow = nullptr ;
}
2020-03-14 17:06:39 +01:00
if ( gui . subwindow_focused = = p_window ) {
2022-08-30 21:57:03 +02:00
Window * new_focused_window ;
2020-03-14 17:06:39 +01:00
Window * parent_visible = p_window - > get_parent_visible_window ( ) ;
gui . subwindow_focused - > _event_callback ( DisplayServer : : WINDOW_EVENT_FOCUS_OUT ) ;
2022-08-30 21:57:03 +02:00
if ( parent_visible ) {
new_focused_window = parent_visible ;
2020-03-14 17:06:39 +01:00
} else {
2022-08-30 21:57:03 +02:00
new_focused_window = Object : : cast_to < Window > ( this ) ;
}
if ( new_focused_window ) {
int new_focused_index = _sub_window_find ( new_focused_window ) ;
if ( new_focused_index ! = - 1 ) {
gui . subwindow_focused = new_focused_window ;
} else {
gui . subwindow_focused = nullptr ;
2020-03-14 17:06:39 +01:00
}
2022-08-30 21:57:03 +02:00
new_focused_window - > _event_callback ( DisplayServer : : WINDOW_EVENT_FOCUS_IN ) ;
} else {
gui . subwindow_focused = nullptr ;
2020-03-14 17:06:39 +01:00
}
}
2020-03-27 19:21:27 +01:00
RenderingServer : : get_singleton ( ) - > viewport_set_parent_viewport ( p_window - > viewport , p_window - > parent ? p_window - > parent - > viewport : RID ( ) ) ;
2020-03-14 17:06:39 +01:00
}
2023-06-20 15:50:44 +02:00
int Viewport : : _sub_window_find ( Window * p_window ) const {
2022-08-30 21:57:03 +02:00
for ( int i = 0 ; i < gui . sub_windows . size ( ) ; i + + ) {
if ( gui . sub_windows [ i ] . window = = p_window ) {
return i ;
}
}
return - 1 ;
}
2022-08-14 13:17:45 +02:00
void Viewport : : _update_viewport_path ( ) {
if ( viewport_textures . is_empty ( ) ) {
return ;
}
Node * scene_root = get_scene_file_path ( ) . is_empty ( ) ? get_owner ( ) : this ;
if ( ! scene_root & & is_inside_tree ( ) ) {
scene_root = get_tree ( ) - > get_edited_scene_root ( ) ;
}
if ( scene_root & & ( scene_root = = this | | scene_root - > is_ancestor_of ( this ) ) ) {
NodePath path_in_scene = scene_root - > get_path_to ( this ) ;
for ( ViewportTexture * E : viewport_textures ) {
E - > path = path_in_scene ;
}
}
}
2014-02-10 02:10:30 +01:00
void Viewport : : _notification ( int p_what ) {
2023-05-12 13:53:15 +02:00
ERR_MAIN_THREAD_GUARD ;
2014-02-10 02:10:30 +01:00
switch ( p_what ) {
2014-11-06 01:20:42 +01:00
case NOTIFICATION_ENTER_TREE : {
2022-08-14 13:17:45 +02:00
_update_viewport_path ( ) ;
2016-01-18 23:49:11 +01:00
if ( get_parent ( ) ) {
2016-10-05 06:26:35 +02:00
parent = get_parent ( ) - > get_viewport ( ) ;
2020-03-27 19:21:27 +01:00
RenderingServer : : get_singleton ( ) - > viewport_set_parent_viewport ( viewport , parent - > get_viewport_rid ( ) ) ;
2016-10-05 06:26:35 +02:00
} else {
2020-04-02 01:20:12 +02:00
parent = nullptr ;
2014-02-10 02:10:30 +01:00
}
current_canvas = find_world_2d ( ) - > get_canvas ( ) ;
2020-03-27 19:21:27 +01:00
RenderingServer : : get_singleton ( ) - > viewport_attach_canvas ( viewport , current_canvas ) ;
2022-11-22 23:04:23 +01:00
RenderingServer : : get_singleton ( ) - > viewport_set_canvas_transform ( viewport , current_canvas , canvas_transform ) ;
2021-09-02 20:07:04 +02:00
RenderingServer : : get_singleton ( ) - > viewport_set_canvas_cull_mask ( viewport , canvas_cull_mask ) ;
2021-09-16 21:28:20 +02:00
_update_audio_listener_2d ( ) ;
2021-07-04 03:43:23 +02:00
# ifndef _3D_DISABLED
2021-08-02 19:31:51 +02:00
RenderingServer : : get_singleton ( ) - > viewport_set_scenario ( viewport , find_world_3d ( ) - > get_scenario ( ) ) ;
2021-09-16 21:28:20 +02:00
_update_audio_listener_3d ( ) ;
2021-07-04 03:43:23 +02:00
# endif // _3D_DISABLED
2014-02-10 02:10:30 +01:00
2015-09-20 22:29:36 +02:00
add_to_group ( " _viewports " ) ;
2015-09-20 18:03:46 +02:00
if ( get_tree ( ) - > is_debugging_collisions_hint ( ) ) {
2020-03-27 19:21:27 +01:00
PhysicsServer2D : : get_singleton ( ) - > space_set_debug_contacts ( find_world_2d ( ) - > get_space ( ) , get_tree ( ) - > get_collision_debug_contact_count ( ) ) ;
contact_2d_debug = RenderingServer : : get_singleton ( ) - > canvas_item_create ( ) ;
2022-11-22 23:09:30 +01:00
RenderingServer : : get_singleton ( ) - > canvas_item_set_parent ( contact_2d_debug , current_canvas ) ;
2021-07-04 03:43:23 +02:00
# ifndef _3D_DISABLED
2020-04-18 11:00:51 +02:00
PhysicsServer3D : : get_singleton ( ) - > space_set_debug_contacts ( find_world_3d ( ) - > get_space ( ) , get_tree ( ) - > get_collision_debug_contact_count ( ) ) ;
2020-03-27 19:21:27 +01:00
contact_3d_debug_multimesh = RenderingServer : : get_singleton ( ) - > multimesh_create ( ) ;
2021-11-30 17:35:12 +01:00
RenderingServer : : get_singleton ( ) - > multimesh_allocate_data ( contact_3d_debug_multimesh , get_tree ( ) - > get_collision_debug_contact_count ( ) , RS : : MULTIMESH_TRANSFORM_3D , false ) ;
2020-03-27 19:21:27 +01:00
RenderingServer : : get_singleton ( ) - > multimesh_set_visible_instances ( contact_3d_debug_multimesh , 0 ) ;
RenderingServer : : get_singleton ( ) - > multimesh_set_mesh ( contact_3d_debug_multimesh , get_tree ( ) - > get_debug_contact_mesh ( ) - > get_rid ( ) ) ;
contact_3d_debug_instance = RenderingServer : : get_singleton ( ) - > instance_create ( ) ;
RenderingServer : : get_singleton ( ) - > instance_set_base ( contact_3d_debug_instance , contact_3d_debug_multimesh ) ;
2020-04-18 11:00:51 +02:00
RenderingServer : : get_singleton ( ) - > instance_set_scenario ( contact_3d_debug_instance , find_world_3d ( ) - > get_scenario ( ) ) ;
2021-11-30 17:35:12 +01:00
RenderingServer : : get_singleton ( ) - > instance_geometry_set_flag ( contact_3d_debug_instance , RS : : INSTANCE_FLAG_DRAW_NEXT_FRAME_IF_VISIBLE , true ) ;
2021-07-04 03:43:23 +02:00
# endif // _3D_DISABLED
2021-11-30 17:35:12 +01:00
set_physics_process_internal ( true ) ;
2015-09-20 18:03:46 +02:00
}
2014-02-10 02:10:30 +01:00
} break ;
2022-02-15 18:06:48 +01:00
2014-02-10 02:10:30 +01:00
case NOTIFICATION_READY : {
2021-07-04 03:43:23 +02:00
# ifndef _3D_DISABLED
2021-09-16 21:28:20 +02:00
if ( audio_listener_3d_set . size ( ) & & ! audio_listener_3d ) {
AudioListener3D * first = nullptr ;
2022-05-19 01:43:40 +02:00
for ( AudioListener3D * E : audio_listener_3d_set ) {
if ( first = = nullptr | | first - > is_greater_than ( E ) ) {
first = E ;
2016-03-20 03:10:04 +01:00
}
}
2020-05-14 16:41:43 +02:00
if ( first ) {
2016-03-20 03:10:04 +01:00
first - > make_current ( ) ;
2020-05-14 16:41:43 +02:00
}
2016-03-20 03:10:04 +01:00
}
2021-08-02 19:31:51 +02:00
if ( camera_3d_set . size ( ) & & ! camera_3d ) {
2021-09-10 16:58:33 +02:00
// There are cameras but no current camera, pick first in tree and make it current.
2020-04-02 01:20:12 +02:00
Camera3D * first = nullptr ;
2022-05-19 01:43:40 +02:00
for ( Camera3D * E : camera_3d_set ) {
if ( first = = nullptr | | first - > is_greater_than ( E ) ) {
first = E ;
2014-02-10 02:10:30 +01:00
}
}
2020-05-14 16:41:43 +02:00
if ( first ) {
2014-02-10 02:10:30 +01:00
first - > make_current ( ) ;
2020-05-14 16:41:43 +02:00
}
2014-02-10 02:10:30 +01:00
}
2021-07-04 03:43:23 +02:00
# endif // _3D_DISABLED
2014-02-10 02:10:30 +01:00
} break ;
2022-02-15 18:06:48 +01:00
2014-11-06 01:20:42 +01:00
case NOTIFICATION_EXIT_TREE : {
2016-01-25 14:30:03 +01:00
_gui_cancel_tooltip ( ) ;
2014-02-10 02:10:30 +01:00
2020-03-27 19:21:27 +01:00
RenderingServer : : get_singleton ( ) - > viewport_set_scenario ( viewport , RID ( ) ) ;
RenderingServer : : get_singleton ( ) - > viewport_remove_canvas ( viewport , current_canvas ) ;
2015-09-20 18:03:46 +02:00
if ( contact_2d_debug . is_valid ( ) ) {
2020-03-27 19:21:27 +01:00
RenderingServer : : get_singleton ( ) - > free ( contact_2d_debug ) ;
2015-09-20 18:03:46 +02:00
contact_2d_debug = RID ( ) ;
}
if ( contact_3d_debug_multimesh . is_valid ( ) ) {
2020-03-27 19:21:27 +01:00
RenderingServer : : get_singleton ( ) - > free ( contact_3d_debug_multimesh ) ;
RenderingServer : : get_singleton ( ) - > free ( contact_3d_debug_instance ) ;
2015-09-20 18:03:46 +02:00
contact_3d_debug_instance = RID ( ) ;
contact_3d_debug_multimesh = RID ( ) ;
}
2014-02-10 02:10:30 +01:00
remove_from_group ( " _viewports " ) ;
2021-07-19 19:25:15 +02:00
set_physics_process_internal ( false ) ;
2016-10-05 06:26:35 +02:00
2020-03-27 19:21:27 +01:00
RS : : get_singleton ( ) - > viewport_set_active ( viewport , false ) ;
RenderingServer : : get_singleton ( ) - > viewport_set_parent_viewport ( viewport , RID ( ) ) ;
2018-03-01 14:44:45 +01:00
} break ;
2022-02-15 18:06:48 +01:00
2022-08-14 13:17:45 +02:00
case NOTIFICATION_PATH_RENAMED : {
_update_viewport_path ( ) ;
} break ;
2018-03-01 14:44:45 +01:00
case NOTIFICATION_INTERNAL_PHYSICS_PROCESS : {
2021-12-13 09:55:52 +01:00
if ( ! get_tree ( ) ) {
return ;
}
2015-09-20 18:03:46 +02:00
if ( get_tree ( ) - > is_debugging_collisions_hint ( ) & & contact_2d_debug . is_valid ( ) ) {
2020-03-27 19:21:27 +01:00
RenderingServer : : get_singleton ( ) - > canvas_item_clear ( contact_2d_debug ) ;
RenderingServer : : get_singleton ( ) - > canvas_item_set_draw_index ( contact_2d_debug , 0xFFFFF ) ; //very high index
2015-09-20 18:03:46 +02:00
2020-03-27 19:21:27 +01:00
Vector < Vector2 > points = PhysicsServer2D : : get_singleton ( ) - > space_get_contacts ( find_world_2d ( ) - > get_space ( ) ) ;
int point_count = PhysicsServer2D : : get_singleton ( ) - > space_get_contact_count ( find_world_2d ( ) - > get_space ( ) ) ;
2015-09-20 18:03:46 +02:00
Color ccol = get_tree ( ) - > get_debug_collision_contact_color ( ) ;
for ( int i = 0 ; i < point_count ; i + + ) {
2020-03-27 19:21:27 +01:00
RenderingServer : : get_singleton ( ) - > canvas_item_add_rect ( contact_2d_debug , Rect2 ( points [ i ] - Vector2 ( 2 , 2 ) , Vector2 ( 5 , 5 ) ) , ccol ) ;
2015-09-20 18:03:46 +02:00
}
}
2021-07-04 03:43:23 +02:00
# ifndef _3D_DISABLED
2015-09-20 18:03:46 +02:00
if ( get_tree ( ) - > is_debugging_collisions_hint ( ) & & contact_3d_debug_multimesh . is_valid ( ) ) {
2020-04-18 11:00:51 +02:00
Vector < Vector3 > points = PhysicsServer3D : : get_singleton ( ) - > space_get_contacts ( find_world_3d ( ) - > get_space ( ) ) ;
int point_count = PhysicsServer3D : : get_singleton ( ) - > space_get_contact_count ( find_world_3d ( ) - > get_space ( ) ) ;
2015-09-20 18:03:46 +02:00
2020-03-27 19:21:27 +01:00
RS : : get_singleton ( ) - > multimesh_set_visible_instances ( contact_3d_debug_multimesh , point_count ) ;
2021-02-10 02:36:38 +01:00
for ( int i = 0 ; i < point_count ; i + + ) {
2020-10-17 07:08:21 +02:00
Transform3D point_transform ;
2021-02-10 02:36:38 +01:00
point_transform . origin = points [ i ] ;
RS : : get_singleton ( ) - > multimesh_instance_set_transform ( contact_3d_debug_multimesh , i , point_transform ) ;
}
2015-09-20 18:03:46 +02:00
}
2021-07-04 03:43:23 +02:00
# endif // _3D_DISABLED
2021-02-06 21:14:35 +01:00
} break ;
2022-02-15 18:06:48 +01:00
2022-02-15 22:14:39 +01:00
case NOTIFICATION_VP_MOUSE_ENTER : {
2022-02-19 09:19:15 +01:00
gui . mouse_in_viewport = true ;
2021-04-24 14:03:38 +02:00
} break ;
2022-02-15 18:06:48 +01:00
2022-02-15 22:14:39 +01:00
case NOTIFICATION_VP_MOUSE_EXIT : {
2022-02-19 09:19:15 +01:00
gui . mouse_in_viewport = false ;
2021-02-06 21:14:35 +01:00
_drop_physics_mouseover ( ) ;
2023-01-06 21:48:20 +01:00
// When the mouse exits the viewport, we don't want to end
// mouse_focus, because, for example, we want to continue
2022-02-19 09:19:15 +01:00
// dragging a scrollbar even if the mouse has left the viewport.
2021-02-06 21:14:35 +01:00
} break ;
2022-02-15 18:06:48 +01:00
2021-02-06 21:14:35 +01:00
case NOTIFICATION_WM_WINDOW_FOCUS_OUT : {
2022-11-09 12:48:19 +01:00
_gui_cancel_tooltip ( ) ;
2021-02-06 21:14:35 +01:00
_drop_physics_mouseover ( ) ;
if ( gui . mouse_focus & & ! gui . forced_mouse_focus ) {
_drop_mouse_focus ( ) ;
}
2021-04-24 14:03:38 +02:00
// When the window focus changes, we want to end mouse_focus, but
// not the mouse_over. Note: The OS will trigger a separate mouse
// exit event if the change in focus results in the mouse exiting
// the window.
2021-02-06 21:14:35 +01:00
} break ;
2022-10-04 04:12:11 +02:00
case NOTIFICATION_PREDELETE : {
if ( gui_parent ) {
gui_parent - > gui . tooltip_popup = nullptr ;
gui_parent - > gui . tooltip_label = nullptr ;
}
} break ;
2021-02-06 21:14:35 +01:00
}
}
void Viewport : : _process_picking ( ) {
if ( ! is_inside_tree ( ) ) {
return ;
}
if ( ! physics_object_picking ) {
return ;
}
2023-02-02 19:00:07 +01:00
if ( Object : : cast_to < Window > ( this ) & & Input : : get_singleton ( ) - > get_mouse_mode ( ) = = Input : : MOUSE_MODE_CAPTURED ) {
2021-02-06 21:14:35 +01:00
return ;
}
2022-02-27 23:57:51 +01:00
if ( ! gui . mouse_in_viewport ) {
// Clear picking events if mouse has left viewport.
physics_picking_events . clear ( ) ;
return ;
}
2024-03-21 08:58:24 +01:00
# ifndef _3D_DISABLED
if ( use_xr ) {
if ( XRServer : : get_singleton ( ) ! = nullptr ) {
Ref < XRInterface > xr_interface = XRServer : : get_singleton ( ) - > get_primary_interface ( ) ;
if ( xr_interface . is_valid ( ) & & xr_interface - > is_initialized ( ) & & xr_interface - > get_view_count ( ) > 1 ) {
WARN_PRINT_ONCE ( " Object picking can't be used when stereo rendering, this will be turned off! " ) ;
physics_object_picking = false ; // don't try again.
return ;
}
}
}
# endif
2021-02-06 21:14:35 +01:00
_drop_physics_mouseover ( true ) ;
2015-09-20 18:03:46 +02:00
2022-01-24 02:39:00 +01:00
# ifndef _3D_DISABLED
Vector2 last_pos ( 1e20 , 1e20 ) ;
CollisionObject3D * last_object = nullptr ;
ObjectID last_id ;
PhysicsDirectSpaceState3D : : RayResult result ;
# endif // _3D_DISABLED
2021-02-06 21:14:35 +01:00
PhysicsDirectSpaceState2D * ss2d = PhysicsServer2D : : get_singleton ( ) - > space_get_direct_state ( find_world_2d ( ) - > get_space ( ) ) ;
2023-07-13 23:23:08 +02:00
SubViewportContainer * parent_svc = Object : : cast_to < SubViewportContainer > ( get_parent ( ) ) ;
bool parent_ignore_mouse = ( parent_svc & & parent_svc - > get_mouse_filter ( ) = = Control : : MOUSE_FILTER_IGNORE ) ;
bool create_passive_hover_event = true ;
if ( gui . mouse_over | | parent_ignore_mouse ) {
// When the mouse is over a Control node, passive hovering would cause input events for Colliders, that are behind Control nodes.
// When parent SubViewportContainer ignores mouse, that setting should be respected.
create_passive_hover_event = false ;
} else {
for ( const Ref < InputEvent > & e : physics_picking_events ) {
Ref < InputEventMouse > m = e ;
if ( m . is_valid ( ) ) {
// A mouse event exists, so passive hovering isn't necessary.
create_passive_hover_event = false ;
break ;
}
2023-06-08 21:04:38 +02:00
}
}
2023-07-13 23:23:08 +02:00
if ( create_passive_hover_event ) {
// Create a mouse motion event. This is necessary because objects or camera may have moved.
2021-09-10 16:58:33 +02:00
// While this extra event is sent, it is checked if both camera and last object and last ID did not move.
// If nothing changed, the event is discarded to avoid flooding with unnecessary motion events every frame.
2023-06-08 21:04:38 +02:00
Ref < InputEventMouseMotion > mm ;
mm . instantiate ( ) ;
2018-11-15 17:54:26 +01:00
2023-06-08 21:04:38 +02:00
mm - > set_device ( InputEvent : : DEVICE_ID_INTERNAL ) ;
mm - > set_position ( get_mouse_position ( ) ) ;
mm - > set_global_position ( mm - > get_position ( ) ) ;
mm - > set_alt_pressed ( Input : : get_singleton ( ) - > is_key_pressed ( Key : : ALT ) ) ;
mm - > set_shift_pressed ( Input : : get_singleton ( ) - > is_key_pressed ( Key : : SHIFT ) ) ;
mm - > set_ctrl_pressed ( Input : : get_singleton ( ) - > is_key_pressed ( Key : : CTRL ) ) ;
mm - > set_meta_pressed ( Input : : get_singleton ( ) - > is_key_pressed ( Key : : META ) ) ;
mm - > set_button_mask ( Input : : get_singleton ( ) - > get_mouse_button_mask ( ) ) ;
physics_picking_events . push_back ( mm ) ;
2021-02-06 21:14:35 +01:00
}
2014-09-15 16:33:30 +02:00
2021-02-06 21:14:35 +01:00
while ( physics_picking_events . size ( ) ) {
2023-07-16 14:36:18 +02:00
local_input_handled = false ;
2023-12-02 17:04:17 +01:00
if ( ! handle_input_locally ) {
Viewport * vp = this ;
while ( ! Object : : cast_to < Window > ( vp ) & & vp - > get_parent ( ) ) {
vp = vp - > get_parent ( ) - > get_viewport ( ) ;
}
vp - > local_input_handled = false ;
}
2021-02-06 21:14:35 +01:00
Ref < InputEvent > ev = physics_picking_events . front ( ) - > get ( ) ;
physics_picking_events . pop_front ( ) ;
2017-05-20 17:38:03 +02:00
2021-02-06 21:14:35 +01:00
Vector2 pos ;
bool is_mouse = false ;
2017-05-20 17:38:03 +02:00
2021-02-06 21:14:35 +01:00
Ref < InputEventMouseMotion > mm = ev ;
2019-03-05 22:31:02 +01:00
2021-02-06 21:14:35 +01:00
if ( mm . is_valid ( ) ) {
pos = mm - > get_position ( ) ;
is_mouse = true ;
}
2017-05-20 17:38:03 +02:00
2021-02-06 21:14:35 +01:00
Ref < InputEventMouseButton > mb = ev ;
2019-03-05 22:31:02 +01:00
2021-02-06 21:14:35 +01:00
if ( mb . is_valid ( ) ) {
pos = mb - > get_position ( ) ;
is_mouse = true ;
}
2017-05-20 17:38:03 +02:00
2021-02-06 21:14:35 +01:00
Ref < InputEventScreenDrag > sd = ev ;
2017-05-20 17:38:03 +02:00
2021-02-06 21:14:35 +01:00
if ( sd . is_valid ( ) ) {
pos = sd - > get_position ( ) ;
}
2017-05-20 17:38:03 +02:00
2021-02-06 21:14:35 +01:00
Ref < InputEventScreenTouch > st = ev ;
2014-09-15 16:33:30 +02:00
2021-02-06 21:14:35 +01:00
if ( st . is_valid ( ) ) {
pos = st - > get_position ( ) ;
}
2015-03-22 05:46:18 +01:00
2021-02-06 21:14:35 +01:00
if ( ss2d ) {
2021-09-10 16:58:33 +02:00
// Send to 2D.
2015-03-22 05:46:18 +01:00
2021-02-06 21:14:35 +01:00
uint64_t frame = get_tree ( ) - > get_frame ( ) ;
2018-08-25 00:03:26 +02:00
2021-02-06 21:14:35 +01:00
PhysicsDirectSpaceState2D : : ShapeResult res [ 64 ] ;
2022-05-19 01:43:40 +02:00
for ( const CanvasLayer * E : canvas_layers ) {
2022-09-29 11:53:28 +02:00
Transform2D canvas_layer_transform ;
2021-02-06 21:14:35 +01:00
ObjectID canvas_layer_id ;
2022-05-19 01:43:40 +02:00
if ( E ) {
2021-09-10 16:58:33 +02:00
// A descendant CanvasLayer.
2022-10-07 12:17:10 +02:00
canvas_layer_transform = E - > get_final_transform ( ) ;
2022-05-19 01:43:40 +02:00
canvas_layer_id = E - > get_instance_id ( ) ;
2021-02-06 21:14:35 +01:00
} else {
2021-09-10 16:58:33 +02:00
// This Viewport's builtin canvas.
2022-09-29 11:53:28 +02:00
canvas_layer_transform = get_canvas_transform ( ) ;
2021-02-06 21:14:35 +01:00
canvas_layer_id = ObjectID ( ) ;
}
2022-09-29 11:53:28 +02:00
Vector2 point = canvas_layer_transform . affine_inverse ( ) . xform ( pos ) ;
2021-02-06 21:14:35 +01:00
2021-11-02 02:00:58 +01:00
PhysicsDirectSpaceState2D : : PointParameters point_params ;
point_params . position = point ;
point_params . canvas_instance_id = canvas_layer_id ;
point_params . collide_with_areas = true ;
point_params . pick_point = true ;
int rc = ss2d - > intersect_point ( point_params , res , 64 ) ;
2022-11-10 22:55:57 +01:00
if ( physics_object_picking_sort ) {
struct ComparatorCollisionObjects {
bool operator ( ) ( const PhysicsDirectSpaceState2D : : ShapeResult & p_a , const PhysicsDirectSpaceState2D : : ShapeResult & p_b ) const {
CollisionObject2D * a = Object : : cast_to < CollisionObject2D > ( p_a . collider ) ;
CollisionObject2D * b = Object : : cast_to < CollisionObject2D > ( p_b . collider ) ;
if ( ! a | | ! b ) {
return false ;
}
int za = a - > get_effective_z_index ( ) ;
int zb = b - > get_effective_z_index ( ) ;
if ( za ! = zb ) {
return zb < za ;
}
return a - > is_greater_than ( b ) ;
}
} ;
SortArray < PhysicsDirectSpaceState2D : : ShapeResult , ComparatorCollisionObjects > sorter ;
sorter . sort ( res , rc ) ;
}
2021-02-06 21:14:35 +01:00
for ( int i = 0 ; i < rc ; i + + ) {
2021-05-17 20:12:52 +02:00
if ( is_input_handled ( ) ) {
break ;
}
2021-02-06 21:14:35 +01:00
if ( res [ i ] . collider_id . is_valid ( ) & & res [ i ] . collider ) {
CollisionObject2D * co = Object : : cast_to < CollisionObject2D > ( res [ i ] . collider ) ;
if ( co & & co - > can_process ( ) ) {
bool send_event = true ;
if ( is_mouse ) {
2022-05-13 15:04:37 +02:00
HashMap < ObjectID , uint64_t > : : Iterator F = physics_2d_mouseover . find ( res [ i ] . collider_id ) ;
2021-02-06 21:14:35 +01:00
if ( ! F ) {
physics_2d_mouseover . insert ( res [ i ] . collider_id , frame ) ;
co - > _mouse_enter ( ) ;
} else {
2022-05-13 15:04:37 +02:00
F - > value = frame ;
2021-09-10 16:58:33 +02:00
// It was already hovered, so don't send the event if it's faked.
2021-02-06 21:14:35 +01:00
if ( mm . is_valid ( ) & & mm - > get_device ( ) = = InputEvent : : DEVICE_ID_INTERNAL ) {
send_event = false ;
2018-08-25 00:03:26 +02:00
}
2015-03-22 05:46:18 +01:00
}
2022-05-13 15:04:37 +02:00
HashMap < Pair < ObjectID , int > , uint64_t , PairHash < ObjectID , int > > : : Iterator SF = physics_2d_shape_mouseover . find ( Pair ( res [ i ] . collider_id , res [ i ] . shape ) ) ;
2021-03-26 18:39:05 +01:00
if ( ! SF ) {
physics_2d_shape_mouseover . insert ( Pair ( res [ i ] . collider_id , res [ i ] . shape ) , frame ) ;
co - > _mouse_shape_enter ( res [ i ] . shape ) ;
} else {
2022-05-13 15:04:37 +02:00
SF - > value = frame ;
2021-03-26 18:39:05 +01:00
}
2015-03-22 05:46:18 +01:00
}
2021-02-06 21:14:35 +01:00
if ( send_event ) {
2021-08-22 17:37:22 +02:00
co - > _input_event_call ( this , ev , res [ i ] . shape ) ;
2024-03-18 12:19:22 +01:00
}
if ( physics_object_picking_first_only ) {
break ;
2015-03-22 05:46:18 +01:00
}
2021-02-06 21:14:35 +01:00
}
}
}
}
2015-03-22 05:46:18 +01:00
2021-02-06 21:14:35 +01:00
if ( is_mouse ) {
2021-03-26 18:39:05 +01:00
_cleanup_mouseover_colliders ( false , false , frame ) ;
2021-02-06 21:14:35 +01:00
}
}
2015-03-22 05:46:18 +01:00
2021-07-04 03:43:23 +02:00
# ifndef _3D_DISABLED
2022-10-29 10:05:52 +02:00
CollisionObject3D * capture_object = nullptr ;
2021-02-06 21:14:35 +01:00
if ( physics_object_capture . is_valid ( ) ) {
2022-10-29 10:05:52 +02:00
capture_object = Object : : cast_to < CollisionObject3D > ( ObjectDB : : get_instance ( physics_object_capture ) ) ;
if ( ! capture_object | | ! camera_3d | | ( mb . is_valid ( ) & & mb - > get_button_index ( ) = = MouseButton : : LEFT & & ! mb - > is_pressed ( ) ) ) {
2021-02-06 21:14:35 +01:00
physics_object_capture = ObjectID ( ) ;
2023-06-18 00:14:41 +02:00
} else {
last_id = physics_object_capture ;
last_object = capture_object ;
2021-02-06 21:14:35 +01:00
}
}
2022-10-29 10:05:52 +02:00
if ( pos = = last_pos ) {
2021-02-06 21:14:35 +01:00
if ( last_id . is_valid ( ) ) {
if ( ObjectDB : : get_instance ( last_id ) & & last_object ) {
2021-09-10 16:58:33 +02:00
// Good, exists.
2021-08-02 19:31:51 +02:00
_collision_object_3d_input_event ( last_object , camera_3d , ev , result . position , result . normal , result . shape ) ;
2021-08-13 23:31:57 +02:00
if ( last_object - > get_capture_input_on_drag ( ) & & mb . is_valid ( ) & & mb - > get_button_index ( ) = = MouseButton : : LEFT & & mb - > is_pressed ( ) ) {
2021-02-06 21:14:35 +01:00
physics_object_capture = last_id ;
}
}
}
} else {
2020-04-28 17:04:07 +02:00
if ( camera_3d ) {
Vector3 from = camera_3d - > project_ray_origin ( pos ) ;
Vector3 dir = camera_3d - > project_ray_normal ( pos ) ;
2024-02-13 06:19:23 +01:00
real_t depth_far = camera_3d - > get_far ( ) ;
2021-02-06 21:14:35 +01:00
PhysicsDirectSpaceState3D * space = PhysicsServer3D : : get_singleton ( ) - > space_get_direct_state ( find_world_3d ( ) - > get_space ( ) ) ;
if ( space ) {
2021-11-02 02:00:58 +01:00
PhysicsDirectSpaceState3D : : RayParameters ray_params ;
ray_params . from = from ;
2024-02-13 06:19:23 +01:00
ray_params . to = from + dir * depth_far ;
2021-11-02 02:00:58 +01:00
ray_params . collide_with_areas = true ;
ray_params . pick_ray = true ;
bool col = space - > intersect_ray ( ray_params , result ) ;
2021-02-06 21:14:35 +01:00
ObjectID new_collider ;
2022-10-29 10:05:52 +02:00
CollisionObject3D * co = col ? Object : : cast_to < CollisionObject3D > ( result . collider ) : nullptr ;
if ( co & & co - > can_process ( ) ) {
new_collider = result . collider_id ;
if ( ! capture_object ) {
2021-02-06 21:14:35 +01:00
last_object = co ;
last_id = result . collider_id ;
2021-08-13 23:31:57 +02:00
if ( co - > get_capture_input_on_drag ( ) & & mb . is_valid ( ) & & mb - > get_button_index ( ) = = MouseButton : : LEFT & & mb - > is_pressed ( ) ) {
2021-02-06 21:14:35 +01:00
physics_object_capture = last_id ;
}
2014-09-15 16:33:30 +02:00
}
}
2021-02-06 21:14:35 +01:00
if ( is_mouse & & new_collider ! = physics_object_over ) {
if ( physics_object_over . is_valid ( ) ) {
2022-10-29 10:05:52 +02:00
CollisionObject3D * previous_co = Object : : cast_to < CollisionObject3D > ( ObjectDB : : get_instance ( physics_object_over ) ) ;
if ( previous_co ) {
previous_co - > _mouse_exit ( ) ;
2014-09-15 16:33:30 +02:00
}
}
2021-02-06 21:14:35 +01:00
if ( new_collider . is_valid ( ) ) {
2023-01-26 16:10:32 +01:00
DEV_ASSERT ( co ) ;
2022-10-29 10:05:52 +02:00
co - > _mouse_enter ( ) ;
2019-03-05 22:31:02 +01:00
}
2021-02-06 21:14:35 +01:00
physics_object_over = new_collider ;
2014-09-15 16:33:30 +02:00
}
2022-10-29 10:05:52 +02:00
if ( capture_object ) {
_collision_object_3d_input_event ( capture_object , camera_3d , ev , result . position , result . normal , result . shape ) ;
} else if ( new_collider . is_valid ( ) ) {
_collision_object_3d_input_event ( co , camera_3d , ev , result . position , result . normal , result . shape ) ;
}
2015-03-22 05:46:18 +01:00
}
2020-08-06 15:05:43 +02:00
2021-02-06 21:14:35 +01:00
last_pos = pos ;
2018-01-05 19:39:10 +01:00
}
2021-02-06 21:14:35 +01:00
}
2021-07-04 03:43:23 +02:00
# endif // _3D_DISABLED
2014-02-10 02:10:30 +01:00
}
}
2017-01-14 15:07:57 +01:00
RID Viewport : : get_viewport_rid ( ) const {
2023-05-12 13:53:15 +02:00
ERR_READ_THREAD_GUARD_V ( RID ( ) ) ;
2016-03-09 00:00:52 +01:00
return viewport ;
2014-02-10 02:10:30 +01:00
}
2019-01-26 18:56:22 +01:00
void Viewport : : update_canvas_items ( ) {
2023-05-12 13:53:15 +02:00
ERR_MAIN_THREAD_GUARD ;
2020-05-14 16:41:43 +02:00
if ( ! is_inside_tree ( ) ) {
2019-01-26 18:56:22 +01:00
return ;
2020-05-14 16:41:43 +02:00
}
2019-01-26 18:56:22 +01:00
_update_canvas_items ( this ) ;
}
2023-02-02 19:00:07 +01:00
void Viewport : : _set_size ( const Size2i & p_size , const Size2i & p_size_2d_override , bool p_allocated ) {
2022-10-13 02:17:04 +02:00
Transform2D stretch_transform_new = Transform2D ( ) ;
if ( is_size_2d_override_stretch_enabled ( ) & & p_size_2d_override . width > 0 & & p_size_2d_override . height > 0 ) {
Size2 scale = Size2 ( p_size ) / Size2 ( p_size_2d_override ) ;
stretch_transform_new . scale ( scale ) ;
}
2024-03-03 14:37:52 +01:00
Size2i new_size = p_size . maxi ( 2 ) ;
2023-02-09 23:14:46 +01:00
if ( size = = new_size & & size_allocated = = p_allocated & & stretch_transform = = stretch_transform_new & & p_size_2d_override = = size_2d_override ) {
2014-02-10 02:10:30 +01:00
return ;
2020-05-14 16:41:43 +02:00
}
2020-04-01 05:47:58 +02:00
2023-02-09 23:14:46 +01:00
size = new_size ;
2020-03-04 02:51:12 +01:00
size_allocated = p_allocated ;
2020-04-01 05:47:58 +02:00
size_2d_override = p_size_2d_override ;
2022-10-13 02:17:04 +02:00
stretch_transform = stretch_transform_new ;
2020-03-04 02:51:12 +01:00
2022-08-16 23:54:55 +02:00
# ifndef _3D_DISABLED
if ( ! use_xr ) {
# endif
if ( p_allocated ) {
RS : : get_singleton ( ) - > viewport_set_size ( viewport , size . width , size . height ) ;
} else {
RS : : get_singleton ( ) - > viewport_set_size ( viewport , 0 , 0 ) ;
}
# ifndef _3D_DISABLED
} // if (!use_xr)
# endif
2020-03-04 02:51:12 +01:00
_update_global_transform ( ) ;
2021-10-01 16:36:28 +02:00
update_configuration_warnings ( ) ;
2014-10-28 02:54:32 +01:00
2020-03-04 02:51:12 +01:00
update_canvas_items ( ) ;
2014-02-10 02:10:30 +01:00
2022-08-22 16:34:47 +02:00
for ( ViewportTexture * E : viewport_textures ) {
E - > emit_changed ( ) ;
}
2021-07-17 23:22:52 +02:00
emit_signal ( SNAME ( " size_changed " ) ) ;
2023-03-19 17:26:22 +01:00
Rect2i limit = get_visible_rect ( ) ;
for ( int i = 0 ; i < gui . sub_windows . size ( ) ; + + i ) {
Window * sw = gui . sub_windows [ i ] . window ;
Rect2i rect = Rect2i ( sw - > position , sw - > size ) ;
Rect2i new_rect = sw - > fit_rect_in_parent ( rect , limit ) ;
if ( new_rect ! = rect ) {
sw - > set_position ( new_rect . position ) ;
sw - > set_size ( new_rect . size ) ;
}
}
2014-02-10 02:10:30 +01:00
}
2020-03-04 02:51:12 +01:00
Size2i Viewport : : _get_size ( ) const {
2022-08-16 23:54:55 +02:00
# ifndef _3D_DISABLED
if ( use_xr ) {
if ( XRServer : : get_singleton ( ) ! = nullptr ) {
Ref < XRInterface > xr_interface = XRServer : : get_singleton ( ) - > get_primary_interface ( ) ;
if ( xr_interface . is_valid ( ) & & xr_interface - > is_initialized ( ) ) {
Size2 xr_size = xr_interface - > get_render_target_size ( ) ;
return ( Size2i ) xr_size ;
}
}
return Size2i ( ) ;
}
# endif // _3D_DISABLED
2020-03-04 02:51:12 +01:00
return size ;
}
2020-05-14 14:29:06 +02:00
2020-04-01 05:47:58 +02:00
Size2i Viewport : : _get_size_2d_override ( ) const {
return size_2d_override ;
}
2020-05-14 14:29:06 +02:00
2020-03-04 02:51:12 +01:00
bool Viewport : : _is_size_allocated ( ) const {
return size_allocated ;
}
2014-02-10 02:10:30 +01:00
Rect2 Viewport : : get_visible_rect ( ) const {
2023-05-12 13:53:15 +02:00
ERR_READ_THREAD_GUARD_V ( Rect2 ( ) ) ;
2014-02-10 02:10:30 +01:00
Rect2 r ;
2016-03-09 00:00:52 +01:00
2016-10-03 21:33:42 +02:00
if ( size = = Size2 ( ) ) {
2020-03-03 14:36:29 +01:00
r = Rect2 ( Point2 ( ) , DisplayServer : : get_singleton ( ) - > window_get_size ( ) ) ;
2014-02-10 02:10:30 +01:00
} else {
2016-10-03 21:33:42 +02:00
r = Rect2 ( Point2 ( ) , size ) ;
2014-02-10 02:10:30 +01:00
}
2020-04-01 05:47:58 +02:00
if ( size_2d_override ! = Size2i ( ) ) {
r . size = size_2d_override ;
2014-02-10 02:10:30 +01:00
}
return r ;
}
2023-04-05 18:53:32 +02:00
void Viewport : : canvas_parent_mark_dirty ( Node * p_node ) {
2023-05-12 13:53:15 +02:00
ERR_MAIN_THREAD_GUARD ;
2023-04-05 18:53:32 +02:00
bool request_update = gui . canvas_parents_with_dirty_order . is_empty ( ) ;
gui . canvas_parents_with_dirty_order . insert ( p_node - > get_instance_id ( ) ) ;
if ( request_update ) {
2023-12-18 15:46:56 +01:00
callable_mp ( this , & Viewport : : _process_dirty_canvas_parent_orders ) . call_deferred ( ) ;
2023-04-05 18:53:32 +02:00
}
}
2019-04-06 22:55:01 +02:00
void Viewport : : enable_canvas_transform_override ( bool p_enable ) {
2023-05-12 13:53:15 +02:00
ERR_MAIN_THREAD_GUARD ;
2019-04-06 22:55:01 +02:00
if ( override_canvas_transform = = p_enable ) {
return ;
}
override_canvas_transform = p_enable ;
if ( p_enable ) {
2020-03-27 19:21:27 +01:00
RenderingServer : : get_singleton ( ) - > viewport_set_canvas_transform ( viewport , find_world_2d ( ) - > get_canvas ( ) , canvas_transform_override ) ;
2019-04-06 22:55:01 +02:00
} else {
2020-03-27 19:21:27 +01:00
RenderingServer : : get_singleton ( ) - > viewport_set_canvas_transform ( viewport , find_world_2d ( ) - > get_canvas ( ) , canvas_transform ) ;
2019-04-06 22:55:01 +02:00
}
}
2023-08-07 12:59:23 +02:00
bool Viewport : : is_canvas_transform_override_enabled ( ) const {
2023-05-12 13:53:15 +02:00
ERR_READ_THREAD_GUARD_V ( false ) ;
2019-04-06 22:55:01 +02:00
return override_canvas_transform ;
}
void Viewport : : set_canvas_transform_override ( const Transform2D & p_transform ) {
2023-05-12 13:53:15 +02:00
ERR_MAIN_THREAD_GUARD ;
2019-04-06 22:55:01 +02:00
if ( canvas_transform_override = = p_transform ) {
return ;
}
canvas_transform_override = p_transform ;
if ( override_canvas_transform ) {
2020-03-27 19:21:27 +01:00
RenderingServer : : get_singleton ( ) - > viewport_set_canvas_transform ( viewport , find_world_2d ( ) - > get_canvas ( ) , canvas_transform_override ) ;
2019-04-06 22:55:01 +02:00
}
}
Transform2D Viewport : : get_canvas_transform_override ( ) const {
2023-05-12 13:53:15 +02:00
ERR_READ_THREAD_GUARD_V ( Transform2D ( ) ) ;
2019-04-06 22:55:01 +02:00
return canvas_transform_override ;
}
2017-01-11 04:52:51 +01:00
void Viewport : : set_canvas_transform ( const Transform2D & p_transform ) {
2023-05-12 13:53:15 +02:00
ERR_MAIN_THREAD_GUARD ;
2014-02-10 02:10:30 +01:00
canvas_transform = p_transform ;
2019-04-06 22:55:01 +02:00
if ( ! override_canvas_transform ) {
2020-03-27 19:21:27 +01:00
RenderingServer : : get_singleton ( ) - > viewport_set_canvas_transform ( viewport , find_world_2d ( ) - > get_canvas ( ) , canvas_transform ) ;
2019-04-06 22:55:01 +02:00
}
2014-02-10 02:10:30 +01:00
}
2017-01-11 04:52:51 +01:00
Transform2D Viewport : : get_canvas_transform ( ) const {
2023-05-12 13:53:15 +02:00
ERR_READ_THREAD_GUARD_V ( Transform2D ( ) ) ;
2014-02-10 02:10:30 +01:00
return canvas_transform ;
}
void Viewport : : _update_global_transform ( ) {
2017-01-11 04:52:51 +01:00
Transform2D sxform = stretch_transform * global_canvas_transform ;
2014-02-10 02:10:30 +01:00
2020-03-27 19:21:27 +01:00
RenderingServer : : get_singleton ( ) - > viewport_set_global_canvas_transform ( viewport , sxform ) ;
2014-02-10 02:10:30 +01:00
}
2017-01-11 04:52:51 +01:00
void Viewport : : set_global_canvas_transform ( const Transform2D & p_transform ) {
2023-05-12 13:53:15 +02:00
ERR_MAIN_THREAD_GUARD ;
2014-02-10 02:10:30 +01:00
global_canvas_transform = p_transform ;
_update_global_transform ( ) ;
}
2017-01-11 04:52:51 +01:00
Transform2D Viewport : : get_global_canvas_transform ( ) const {
2023-05-12 13:53:15 +02:00
ERR_READ_THREAD_GUARD_V ( Transform2D ( ) ) ;
2014-02-10 02:10:30 +01:00
return global_canvas_transform ;
}
2018-08-25 00:03:26 +02:00
void Viewport : : _canvas_layer_add ( CanvasLayer * p_canvas_layer ) {
canvas_layers . insert ( p_canvas_layer ) ;
}
void Viewport : : _canvas_layer_remove ( CanvasLayer * p_canvas_layer ) {
canvas_layers . erase ( p_canvas_layer ) ;
}
2014-02-10 02:10:30 +01:00
void Viewport : : set_transparent_background ( bool p_enable ) {
2023-05-12 13:53:15 +02:00
ERR_MAIN_THREAD_GUARD ;
2014-02-10 02:10:30 +01:00
transparent_bg = p_enable ;
2020-03-27 19:21:27 +01:00
RS : : get_singleton ( ) - > viewport_set_transparent_background ( viewport , p_enable ) ;
2014-02-10 02:10:30 +01:00
}
bool Viewport : : has_transparent_background ( ) const {
2023-05-12 13:53:15 +02:00
ERR_READ_THREAD_GUARD_V ( false ) ;
2014-02-10 02:10:30 +01:00
return transparent_bg ;
}
2023-08-03 14:10:01 +02:00
void Viewport : : set_use_hdr_2d ( bool p_enable ) {
ERR_MAIN_THREAD_GUARD ;
use_hdr_2d = p_enable ;
RS : : get_singleton ( ) - > viewport_set_use_hdr_2d ( viewport , p_enable ) ;
}
bool Viewport : : is_using_hdr_2d ( ) const {
ERR_READ_THREAD_GUARD_V ( false ) ;
return use_hdr_2d ;
}
2014-02-10 02:10:30 +01:00
void Viewport : : set_world_2d ( const Ref < World2D > & p_world_2d ) {
2023-05-12 13:53:15 +02:00
ERR_MAIN_THREAD_GUARD ;
2020-05-14 16:41:43 +02:00
if ( world_2d = = p_world_2d ) {
2016-07-13 20:51:38 +02:00
return ;
2020-05-14 16:41:43 +02:00
}
2016-07-13 20:51:38 +02:00
if ( is_inside_tree ( ) ) {
2020-03-27 19:21:27 +01:00
RenderingServer : : get_singleton ( ) - > viewport_remove_canvas ( viewport , current_canvas ) ;
2016-07-13 20:51:38 +02:00
}
2023-05-03 22:57:15 +02:00
if ( world_2d . is_valid ( ) ) {
world_2d - > remove_viewport ( this ) ;
}
2020-05-14 16:41:43 +02:00
if ( p_world_2d . is_valid ( ) ) {
2022-01-25 04:01:59 +01:00
bool do_propagate = world_2d . is_valid ( ) & & is_inside_tree ( ) ;
2016-07-13 20:51:38 +02:00
world_2d = p_world_2d ;
2022-01-25 04:01:59 +01:00
if ( do_propagate ) {
_propagate_world_2d_changed ( this ) ;
}
2020-05-14 16:41:43 +02:00
} else {
2021-03-15 12:45:28 +01:00
WARN_PRINT ( " Invalid world_2d " ) ;
2016-07-13 20:51:38 +02:00
world_2d = Ref < World2D > ( memnew ( World2D ) ) ;
}
2014-02-10 02:10:30 +01:00
2023-05-03 22:57:15 +02:00
world_2d - > register_viewport ( this ) ;
2021-09-16 21:28:20 +02:00
_update_audio_listener_2d ( ) ;
2014-02-10 02:10:30 +01:00
2016-07-13 20:51:38 +02:00
if ( is_inside_tree ( ) ) {
2014-02-10 02:10:30 +01:00
current_canvas = find_world_2d ( ) - > get_canvas ( ) ;
2020-03-27 19:21:27 +01:00
RenderingServer : : get_singleton ( ) - > viewport_attach_canvas ( viewport , current_canvas ) ;
2014-02-10 02:10:30 +01:00
}
}
Ref < World2D > Viewport : : find_world_2d ( ) const {
2023-05-12 13:53:15 +02:00
ERR_READ_THREAD_GUARD_V ( Ref < World2D > ( ) ) ;
2020-05-14 16:41:43 +02:00
if ( world_2d . is_valid ( ) ) {
2014-02-10 02:10:30 +01:00
return world_2d ;
2020-05-14 16:41:43 +02:00
} else if ( parent ) {
2014-02-10 02:10:30 +01:00
return parent - > find_world_2d ( ) ;
2020-05-14 16:41:43 +02:00
} else {
2014-02-10 02:10:30 +01:00
return Ref < World2D > ( ) ;
2020-05-14 16:41:43 +02:00
}
2014-02-10 02:10:30 +01:00
}
2016-05-11 16:46:08 +02:00
void Viewport : : _propagate_viewport_notification ( Node * p_node , int p_what ) {
p_node - > notification ( p_what ) ;
for ( int i = 0 ; i < p_node - > get_child_count ( ) ; i + + ) {
Node * c = p_node - > get_child ( i ) ;
2020-05-14 16:41:43 +02:00
if ( Object : : cast_to < Viewport > ( c ) ) {
2016-05-11 16:46:08 +02:00
continue ;
2020-05-14 16:41:43 +02:00
}
2016-05-11 16:46:08 +02:00
_propagate_viewport_notification ( c , p_what ) ;
}
}
2014-02-10 02:10:30 +01:00
2021-08-02 19:31:51 +02:00
Ref < World2D > Viewport : : get_world_2d ( ) const {
2023-05-12 13:53:15 +02:00
ERR_READ_THREAD_GUARD_V ( Ref < World2D > ( ) ) ;
2021-08-02 19:31:51 +02:00
return world_2d ;
}
Transform2D Viewport : : get_final_transform ( ) const {
2023-05-12 13:53:15 +02:00
ERR_READ_THREAD_GUARD_V ( Transform2D ( ) ) ;
2023-02-02 19:28:14 +01:00
return stretch_transform * global_canvas_transform ;
2021-08-02 19:31:51 +02:00
}
void Viewport : : _update_canvas_items ( Node * p_node ) {
2014-02-10 02:10:30 +01:00
if ( p_node ! = this ) {
2022-03-29 09:44:09 +02:00
Window * w = Object : : cast_to < Window > ( p_node ) ;
if ( w & & ( ! w - > is_inside_tree ( ) | | ! w - > is_embedded ( ) ) ) {
2014-02-10 02:10:30 +01:00
return ;
2020-05-14 16:41:43 +02:00
}
2014-02-10 02:10:30 +01:00
2021-08-02 19:31:51 +02:00
CanvasItem * ci = Object : : cast_to < CanvasItem > ( p_node ) ;
if ( ci ) {
2022-08-13 23:21:24 +02:00
ci - > queue_redraw ( ) ;
2014-02-10 02:10:30 +01:00
}
2020-05-14 16:41:43 +02:00
}
2014-02-10 02:10:30 +01:00
2021-08-02 19:31:51 +02:00
int cc = p_node - > get_child_count ( ) ;
2014-02-10 02:10:30 +01:00
2021-08-02 19:31:51 +02:00
for ( int i = 0 ; i < cc ; i + + ) {
_update_canvas_items ( p_node - > get_child ( i ) ) ;
2019-11-29 07:41:25 +01:00
}
2021-08-02 19:31:51 +02:00
}
2019-11-29 07:41:25 +01:00
2021-08-02 19:31:51 +02:00
Ref < ViewportTexture > Viewport : : get_texture ( ) const {
2023-05-12 13:53:15 +02:00
ERR_READ_THREAD_GUARD_V ( Ref < ViewportTexture > ( ) ) ;
2021-08-02 19:31:51 +02:00
return default_texture ;
}
2014-02-10 02:10:30 +01:00
2022-05-01 01:40:30 +02:00
void Viewport : : set_positional_shadow_atlas_size ( int p_size ) {
2023-05-12 13:53:15 +02:00
ERR_MAIN_THREAD_GUARD ;
2022-05-01 01:40:30 +02:00
positional_shadow_atlas_size = p_size ;
RS : : get_singleton ( ) - > viewport_set_positional_shadow_atlas_size ( viewport , p_size , positional_shadow_atlas_16_bits ) ;
2021-08-02 19:31:51 +02:00
}
2019-11-29 07:41:25 +01:00
2022-05-01 01:40:30 +02:00
int Viewport : : get_positional_shadow_atlas_size ( ) const {
2023-05-12 13:53:15 +02:00
ERR_READ_THREAD_GUARD_V ( 0 ) ;
2022-05-01 01:40:30 +02:00
return positional_shadow_atlas_size ;
2021-08-02 19:31:51 +02:00
}
2014-02-10 02:10:30 +01:00
2022-05-01 01:40:30 +02:00
void Viewport : : set_positional_shadow_atlas_16_bits ( bool p_16_bits ) {
2023-05-12 13:53:15 +02:00
ERR_MAIN_THREAD_GUARD ;
2022-05-01 01:40:30 +02:00
if ( positional_shadow_atlas_16_bits = = p_16_bits ) {
2021-08-02 19:31:51 +02:00
return ;
2014-02-10 02:10:30 +01:00
}
2022-05-01 01:40:30 +02:00
positional_shadow_atlas_16_bits = p_16_bits ;
RS : : get_singleton ( ) - > viewport_set_positional_shadow_atlas_size ( viewport , positional_shadow_atlas_size , positional_shadow_atlas_16_bits ) ;
2014-02-10 02:10:30 +01:00
}
2022-05-01 01:40:30 +02:00
bool Viewport : : get_positional_shadow_atlas_16_bits ( ) const {
2023-05-12 13:53:15 +02:00
ERR_READ_THREAD_GUARD_V ( false ) ;
2022-05-01 01:40:30 +02:00
return positional_shadow_atlas_16_bits ;
2021-01-24 20:00:20 +01:00
}
2022-05-01 01:40:30 +02:00
void Viewport : : set_positional_shadow_atlas_quadrant_subdiv ( int p_quadrant , PositionalShadowAtlasQuadrantSubdiv p_subdiv ) {
2023-05-12 13:53:15 +02:00
ERR_MAIN_THREAD_GUARD ;
2016-11-10 03:55:06 +01:00
ERR_FAIL_INDEX ( p_quadrant , 4 ) ;
ERR_FAIL_INDEX ( p_subdiv , SHADOW_ATLAS_QUADRANT_SUBDIV_MAX ) ;
2014-05-14 06:22:15 +02:00
2022-05-01 01:40:30 +02:00
if ( positional_shadow_atlas_quadrant_subdiv [ p_quadrant ] = = p_subdiv ) {
2016-11-10 03:55:06 +01:00
return ;
2020-05-14 16:41:43 +02:00
}
2014-05-14 06:22:15 +02:00
2022-05-01 01:40:30 +02:00
positional_shadow_atlas_quadrant_subdiv [ p_quadrant ] = p_subdiv ;
2016-11-10 03:55:06 +01:00
static const int subdiv [ SHADOW_ATLAS_QUADRANT_SUBDIV_MAX ] = { 0 , 1 , 4 , 16 , 64 , 256 , 1024 } ;
2014-08-14 15:31:38 +02:00
2022-05-01 01:40:30 +02:00
RS : : get_singleton ( ) - > viewport_set_positional_shadow_atlas_quadrant_subdivision ( viewport , p_quadrant , subdiv [ p_subdiv ] ) ;
2014-08-14 15:31:38 +02:00
}
2020-05-14 14:29:06 +02:00
2022-05-01 01:40:30 +02:00
Viewport : : PositionalShadowAtlasQuadrantSubdiv Viewport : : get_positional_shadow_atlas_quadrant_subdiv ( int p_quadrant ) const {
2023-05-12 13:53:15 +02:00
ERR_READ_THREAD_GUARD_V ( SHADOW_ATLAS_QUADRANT_SUBDIV_DISABLED ) ;
2016-11-10 03:55:06 +01:00
ERR_FAIL_INDEX_V ( p_quadrant , 4 , SHADOW_ATLAS_QUADRANT_SUBDIV_DISABLED ) ;
2022-05-01 01:40:30 +02:00
return positional_shadow_atlas_quadrant_subdiv [ p_quadrant ] ;
2016-11-10 03:55:06 +01:00
}
2017-05-20 17:38:03 +02:00
Ref < InputEvent > Viewport : : _make_input_local ( const Ref < InputEvent > & ev ) {
2021-10-09 22:30:14 +02:00
if ( ev . is_null ( ) ) {
return ev ; // No transformation defined for null event
}
2014-04-10 05:18:27 +02:00
2022-10-01 08:40:11 +02:00
Transform2D ai = get_final_transform ( ) . affine_inverse ( ) ;
2024-02-18 02:49:48 +01:00
Ref < InputEventMouse > me = ev ;
if ( me . is_valid ( ) ) {
me = me - > xformed_by ( ai ) ;
// For InputEventMouse, the global position is not adjusted by ev->xformed_by() and needs to be set separately.
me - > set_global_position ( me - > get_position ( ) ) ;
return me ;
}
2020-03-14 17:06:39 +01:00
return ev - > xformed_by ( ai ) ;
2014-04-10 05:18:27 +02:00
}
2017-03-29 17:29:38 +02:00
Vector2 Viewport : : get_mouse_position ( ) const {
2023-05-12 13:53:15 +02:00
ERR_READ_THREAD_GUARD_V ( Vector2 ( ) ) ;
2023-06-06 20:42:41 +02:00
if ( ! is_directly_attached_to_screen ( ) ) {
// Rely on the most recent mouse coordinate from an InputEventMouse in push_input.
// In this case get_screen_transform is not applicable, because it is ambiguous.
return gui . last_mouse_pos ;
} else if ( DisplayServer : : get_singleton ( ) - > has_feature ( DisplayServer : : FEATURE_MOUSE ) ) {
2023-07-22 00:02:37 +02:00
Transform2D xform = get_screen_transform_internal ( true ) ;
if ( xform . determinant ( ) = = 0 ) {
// Screen transform can be non-invertible when the Window is minimized.
return Vector2 ( ) ;
}
return xform . affine_inverse ( ) . xform ( DisplayServer : : get_singleton ( ) - > mouse_get_position ( ) ) ;
2023-01-20 22:33:05 +01:00
} else {
// Fallback to Input for getting mouse position in case of emulated mouse.
return get_screen_transform_internal ( ) . affine_inverse ( ) . xform ( Input : : get_singleton ( ) - > get_mouse_position ( ) ) ;
}
2015-05-12 13:17:09 +02:00
}
2022-03-27 11:17:36 +02:00
void Viewport : : warp_mouse ( const Vector2 & p_position ) {
2023-05-12 13:53:15 +02:00
ERR_MAIN_THREAD_GUARD ;
2023-01-20 22:33:05 +01:00
Transform2D xform = get_screen_transform_internal ( ) ;
2022-08-18 11:16:29 +02:00
Vector2 gpos = xform . xform ( p_position ) ;
2022-03-27 11:17:36 +02:00
Input : : get_singleton ( ) - > warp_mouse ( gpos ) ;
2015-02-14 23:22:06 +01:00
}
2016-01-17 02:41:10 +01:00
void Viewport : : _gui_sort_roots ( ) {
2020-05-14 16:41:43 +02:00
if ( ! gui . roots_order_dirty ) {
2016-01-17 02:41:10 +01:00
return ;
2020-05-14 16:41:43 +02:00
}
2016-01-17 02:41:10 +01:00
gui . roots . sort_custom < Control : : CComparator > ( ) ;
gui . roots_order_dirty = false ;
}
void Viewport : : _gui_cancel_tooltip ( ) {
2020-11-02 17:18:29 +01:00
gui . tooltip_control = nullptr ;
2023-09-24 07:18:17 +02:00
gui . tooltip_text = " " ;
2021-02-27 00:37:20 +01:00
if ( gui . tooltip_timer . is_valid ( ) ) {
gui . tooltip_timer - > release_connections ( ) ;
gui . tooltip_timer = Ref < SceneTreeTimer > ( ) ;
}
2016-01-25 14:30:03 +01:00
if ( gui . tooltip_popup ) {
2022-10-24 23:07:02 +02:00
gui . tooltip_popup - > queue_free ( ) ;
2016-01-25 14:30:03 +01:00
}
2016-01-17 02:41:10 +01:00
}
2020-11-02 17:18:29 +01:00
String Viewport : : _gui_get_tooltip ( Control * p_control , const Vector2 & p_pos , Control * * r_tooltip_owner ) {
2018-06-07 17:46:14 +02:00
Vector2 pos = p_pos ;
String tooltip ;
while ( p_control ) {
2023-12-16 00:56:06 +01:00
tooltip = p_control - > atr ( p_control - > get_tooltip ( pos ) ) ;
2018-06-07 17:46:14 +02:00
2021-09-10 16:58:33 +02:00
// Temporary solution for PopupMenus.
2021-08-20 11:49:19 +02:00
PopupMenu * menu = Object : : cast_to < PopupMenu > ( this ) ;
if ( menu ) {
tooltip = menu - > get_tooltip ( pos ) ;
}
2020-11-02 17:18:29 +01:00
if ( r_tooltip_owner ) {
* r_tooltip_owner = p_control ;
2018-07-20 23:14:33 +02:00
}
2020-11-02 17:18:29 +01:00
// If we found a tooltip, we stop here.
2020-12-15 13:04:21 +01:00
if ( ! tooltip . is_empty ( ) ) {
2018-06-07 17:46:14 +02:00
break ;
2020-05-14 16:41:43 +02:00
}
2020-11-02 17:18:29 +01:00
// Otherwise, we check parent controls unless some conditions prevent it.
2018-06-07 17:46:14 +02:00
2020-05-14 16:41:43 +02:00
if ( p_control - > data . mouse_filter = = Control : : MOUSE_FILTER_STOP ) {
2018-06-07 17:46:14 +02:00
break ;
2020-05-14 16:41:43 +02:00
}
2020-10-01 09:17:33 +02:00
if ( p_control - > is_set_as_top_level ( ) ) {
2018-06-07 17:46:14 +02:00
break ;
2020-05-14 16:41:43 +02:00
}
2018-06-07 17:46:14 +02:00
2020-11-02 17:18:29 +01:00
// Transform cursor pos for parent control.
pos = p_control - > get_transform ( ) . xform ( pos ) ;
2018-06-07 17:46:14 +02:00
p_control = p_control - > get_parent_control ( ) ;
}
return tooltip ;
}
2016-01-17 02:41:10 +01:00
void Viewport : : _gui_show_tooltip ( ) {
2020-11-02 17:18:29 +01:00
if ( ! gui . tooltip_control ) {
2016-01-17 02:41:10 +01:00
return ;
}
2020-11-02 17:18:29 +01:00
// Get the Control under cursor and the relevant tooltip text, if any.
Control * tooltip_owner = nullptr ;
2023-09-24 07:18:17 +02:00
gui . tooltip_text = _gui_get_tooltip (
2020-11-02 17:18:29 +01:00
gui . tooltip_control ,
2021-12-12 09:12:26 +01:00
gui . tooltip_control - > get_global_transform ( ) . xform_inv ( gui . last_mouse_pos ) ,
2020-11-02 17:18:29 +01:00
& tooltip_owner ) ;
2023-09-24 07:18:17 +02:00
gui . tooltip_text = gui . tooltip_text . strip_edges ( ) ;
if ( gui . tooltip_text . is_empty ( ) ) {
2020-11-02 17:18:29 +01:00
return ; // Nothing to show.
2020-05-14 16:41:43 +02:00
}
2016-01-17 02:41:10 +01:00
2020-11-02 17:18:29 +01:00
// Remove previous popup if we change something.
2016-01-25 14:30:03 +01:00
if ( gui . tooltip_popup ) {
memdelete ( gui . tooltip_popup ) ;
2023-09-24 07:18:17 +02:00
gui . tooltip_popup = nullptr ;
2016-01-25 14:30:03 +01:00
}
2016-01-17 02:41:10 +01:00
2020-11-02 17:18:29 +01:00
if ( ! tooltip_owner ) {
2017-08-21 03:48:03 +02:00
return ;
}
2021-04-25 16:53:50 +02:00
// Popup window which houses the tooltip content.
2022-06-09 22:23:11 +02:00
PopupPanel * panel = memnew ( PopupPanel ) ;
panel - > set_theme_type_variation ( SNAME ( " TooltipPanel " ) ) ;
2021-04-25 16:53:50 +02:00
2023-09-14 23:37:28 +02:00
// Ensure no opaque background behind the panel as its StyleBox can be partially transparent (e.g. corners).
panel - > set_transparent_background ( true ) ;
2020-11-02 17:18:29 +01:00
// 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.
2023-09-24 07:18:17 +02:00
Control * base_tooltip = tooltip_owner - > make_custom_tooltip ( gui . tooltip_text ) ;
2018-07-20 23:14:33 +02:00
2020-11-02 17:18:29 +01:00
// If no custom tooltip is given, use a default implementation.
2020-03-20 21:51:53 +01:00
if ( ! base_tooltip ) {
2022-06-09 22:23:11 +02:00
gui . tooltip_label = memnew ( Label ) ;
gui . tooltip_label - > set_theme_type_variation ( SNAME ( " TooltipLabel " ) ) ;
2023-09-24 07:18:17 +02:00
gui . tooltip_label - > set_text ( gui . tooltip_text ) ;
2020-03-20 21:51:53 +01:00
base_tooltip = gui . tooltip_label ;
2021-04-25 16:53:50 +02:00
panel - > connect ( " mouse_entered " , callable_mp ( this , & Viewport : : _gui_cancel_tooltip ) ) ;
2018-07-20 23:14:33 +02:00
}
2016-01-25 14:30:03 +01:00
2022-03-19 01:02:57 +01:00
base_tooltip - > set_anchors_and_offsets_preset ( Control : : PRESET_FULL_RECT ) ;
2020-03-20 21:51:53 +01:00
2022-01-28 10:19:53 +01:00
panel - > set_transient ( true ) ;
2020-03-20 21:51:53 +01:00
panel - > set_flag ( Window : : FLAG_NO_FOCUS , true ) ;
2022-02-24 10:21:23 +01:00
panel - > set_flag ( Window : : FLAG_POPUP , false ) ;
2023-01-15 11:05:25 +01:00
panel - > set_flag ( Window : : FLAG_MOUSE_PASSTHROUGH , true ) ;
2023-12-27 17:19:52 +01:00
// A non-embedded tooltip window will only be transparent if per_pixel_transparency is allowed in the main Viewport.
panel - > set_flag ( Window : : FLAG_TRANSPARENT , true ) ;
2020-03-20 21:51:53 +01:00
panel - > set_wrap_controls ( true ) ;
panel - > add_child ( base_tooltip ) ;
2022-10-04 04:12:11 +02:00
panel - > gui_parent = this ;
2020-03-20 21:51:53 +01:00
gui . tooltip_popup = panel ;
2020-11-02 17:18:29 +01:00
tooltip_owner - > add_child ( gui . tooltip_popup ) ;
2016-01-17 02:41:10 +01:00
2023-12-27 17:19:52 +01:00
Window * window = Object : : cast_to < Window > ( gui . tooltip_popup - > get_embedder ( ) ) ;
if ( ! window ) { // Not embedded.
window = gui . tooltip_popup - > get_parent_visible_window ( ) ;
}
float win_scale = window - > content_scale_factor ;
2022-10-18 16:43:37 +02:00
Point2 tooltip_offset = GLOBAL_GET ( " display/mouse_cursor/tooltip_position_offset " ) ;
2023-12-27 17:19:52 +01:00
if ( ! gui . tooltip_popup - > is_embedded ( ) ) {
tooltip_offset * = win_scale ;
}
2020-03-20 21:51:53 +01:00
Rect2 r ( gui . tooltip_pos + tooltip_offset , gui . tooltip_popup - > get_contents_minimum_size ( ) ) ;
2022-10-07 19:14:41 +02:00
Rect2i vr ;
if ( gui . tooltip_popup - > is_embedded ( ) ) {
2023-02-05 17:35:39 +01:00
vr = gui . tooltip_popup - > get_embedder ( ) - > get_visible_rect ( ) ;
2022-10-07 19:14:41 +02:00
} else {
2023-12-27 17:19:52 +01:00
panel - > content_scale_factor = win_scale ;
r . size * = win_scale ;
2022-10-07 19:14:41 +02:00
vr = window - > get_usable_parent_rect ( ) ;
}
2023-12-27 17:19:52 +01:00
r . size = r . size . min ( panel - > get_max_size ( ) ) ;
2020-03-20 21:51:53 +01:00
2020-05-14 16:41:43 +02:00
if ( r . size . x + r . position . x > vr . size . x + vr . position . x ) {
2022-07-23 19:51:06 +02:00
// Place it in the opposite direction. If it fails, just hug the border.
r . position . x = gui . tooltip_pos . x - r . size . x - tooltip_offset . x ;
if ( r . position . x < vr . position . x ) {
r . position . x = vr . position . x + vr . size . x - r . size . x ;
}
2020-05-14 16:41:43 +02:00
} else if ( r . position . x < vr . position . x ) {
2020-03-20 21:51:53 +01:00
r . position . x = vr . position . x ;
2020-05-14 16:41:43 +02:00
}
2020-03-20 21:51:53 +01:00
2020-05-14 16:41:43 +02:00
if ( r . size . y + r . position . y > vr . size . y + vr . position . y ) {
2022-07-23 19:51:06 +02:00
// Same as above.
r . position . y = gui . tooltip_pos . y - r . size . y - tooltip_offset . y ;
if ( r . position . y < vr . position . y ) {
r . position . y = vr . position . y + vr . size . y - r . size . y ;
}
2020-05-14 16:41:43 +02:00
} else if ( r . position . y < vr . position . y ) {
2020-03-20 21:51:53 +01:00
r . position . y = vr . position . y ;
2020-05-14 16:41:43 +02:00
}
2020-03-20 21:51:53 +01:00
gui . tooltip_popup - > set_position ( r . position ) ;
2016-01-17 02:41:10 +01:00
gui . tooltip_popup - > set_size ( r . size ) ;
2022-02-24 10:21:23 +01:00
DisplayServer : : WindowID active_popup = DisplayServer : : get_singleton ( ) - > window_get_active_popup ( ) ;
if ( active_popup = = DisplayServer : : INVALID_WINDOW_ID | | active_popup = = window - > get_window_id ( ) ) {
gui . tooltip_popup - > show ( ) ;
}
2020-03-20 21:51:53 +01:00
gui . tooltip_popup - > child_controls_changed ( ) ;
2016-01-17 02:41:10 +01:00
}
2022-05-16 15:10:30 +02:00
bool Viewport : : _gui_call_input ( Control * p_control , const Ref < InputEvent > & p_input ) {
bool stopped = false ;
2017-05-20 17:38:03 +02:00
Ref < InputEvent > ev = p_input ;
2016-06-27 14:59:43 +02:00
2022-05-16 15:10:30 +02:00
// Returns true if an event should be impacted by a control's mouse filter.
2023-01-19 14:56:32 +01:00
bool is_pointer_event = Ref < InputEventMouse > ( p_input ) . is_valid ( ) | | Ref < InputEventScreenDrag > ( p_input ) . is_valid ( ) | | Ref < InputEventScreenTouch > ( p_input ) . is_valid ( ) ;
2017-05-20 17:38:03 +02:00
2022-05-16 15:10:30 +02:00
Ref < InputEventMouseButton > mb = p_input ;
bool is_scroll_event = mb . is_valid ( ) & &
2021-08-13 23:31:57 +02:00
( mb - > get_button_index ( ) = = MouseButton : : WHEEL_DOWN | |
mb - > get_button_index ( ) = = MouseButton : : WHEEL_UP | |
mb - > get_button_index ( ) = = MouseButton : : WHEEL_LEFT | |
2022-05-16 15:10:30 +02:00
mb - > get_button_index ( ) = = MouseButton : : WHEEL_RIGHT ) ;
2016-06-20 22:16:52 +02:00
2016-06-07 07:39:40 +02:00
CanvasItem * ci = p_control ;
while ( ci ) {
2017-08-24 22:58:51 +02:00
Control * control = Object : : cast_to < Control > ( ci ) ;
2016-06-07 07:39:40 +02:00
if ( control ) {
2018-11-16 17:46:42 +01:00
if ( control - > data . mouse_filter ! = Control : : MOUSE_FILTER_IGNORE ) {
2021-08-22 17:37:22 +02:00
control - > _call_gui_input ( ev ) ;
2018-11-16 17:46:42 +01:00
}
2018-06-07 17:46:14 +02:00
2020-10-01 09:17:33 +02:00
if ( ! control - > is_inside_tree ( ) | | control - > is_set_as_top_level ( ) ) {
2016-06-07 07:39:40 +02:00
break ;
2020-05-14 16:41:43 +02:00
}
if ( gui . key_event_accepted ) {
2022-05-16 15:10:30 +02:00
stopped = true ;
2016-06-07 07:39:40 +02:00
break ;
2020-05-14 16:41:43 +02:00
}
2023-01-19 14:56:32 +01:00
if ( control - > data . mouse_filter = = Control : : MOUSE_FILTER_STOP & & is_pointer_event & & ! ( is_scroll_event & & control - > data . force_pass_scroll_events ) ) {
// Mouse, ScreenDrag and ScreenTouch events are stopped by default with MOUSE_FILTER_STOP, unless we have a scroll event and force_pass_scroll_events set to true
2022-05-16 15:10:30 +02:00
stopped = true ;
2016-06-07 07:39:40 +02:00
break ;
2020-05-14 16:41:43 +02:00
}
2016-06-07 07:39:40 +02:00
}
2023-05-29 00:29:44 +02:00
if ( is_input_handled ( ) ) {
// Break after Physics Picking in SubViewport.
break ;
}
2020-10-01 09:17:33 +02:00
if ( ci - > is_set_as_top_level ( ) ) {
2016-06-07 07:39:40 +02:00
break ;
2020-05-14 16:41:43 +02:00
}
2016-06-07 07:39:40 +02:00
2021-09-10 16:58:33 +02:00
ev = ev - > xformed_by ( ci - > get_transform ( ) ) ; // Transform event upwards.
2016-06-07 07:39:40 +02:00
ci = ci - > get_parent_item ( ) ;
2016-01-17 02:41:10 +01:00
}
2022-05-16 15:10:30 +02:00
return stopped ;
2016-01-17 02:41:10 +01:00
}
2019-01-18 21:53:36 +01:00
void Viewport : : _gui_call_notification ( Control * p_control , int p_what ) {
CanvasItem * ci = p_control ;
while ( ci ) {
Control * control = Object : : cast_to < Control > ( ci ) ;
if ( control ) {
if ( control - > data . mouse_filter ! = Control : : MOUSE_FILTER_IGNORE ) {
control - > notification ( p_what ) ;
}
2020-05-14 16:41:43 +02:00
if ( ! control - > is_inside_tree ( ) ) {
2019-01-18 21:53:36 +01:00
break ;
2020-05-14 16:41:43 +02:00
}
2019-01-18 21:53:36 +01:00
2020-10-01 09:17:33 +02:00
if ( ! control - > is_inside_tree ( ) | | control - > is_set_as_top_level ( ) ) {
2019-01-18 21:53:36 +01:00
break ;
2020-05-14 16:41:43 +02:00
}
if ( control - > data . mouse_filter = = Control : : MOUSE_FILTER_STOP ) {
2019-01-18 21:53:36 +01:00
break ;
2020-05-14 16:41:43 +02:00
}
2019-01-18 21:53:36 +01:00
}
2020-10-01 09:17:33 +02:00
if ( ci - > is_set_as_top_level ( ) ) {
2019-01-18 21:53:36 +01:00
break ;
2020-05-14 16:41:43 +02:00
}
2019-01-18 21:53:36 +01:00
ci = ci - > get_parent_item ( ) ;
}
}
2020-05-14 14:29:06 +02:00
2021-07-19 22:09:23 +02:00
Control * Viewport : : gui_find_control ( const Point2 & p_global ) {
2023-05-12 13:53:15 +02:00
ERR_MAIN_THREAD_GUARD_V ( nullptr ) ;
2021-09-10 16:58:33 +02:00
// Handle subwindows.
2016-01-25 14:39:55 +01:00
_gui_sort_roots ( ) ;
2016-01-17 02:41:10 +01:00
for ( List < Control * > : : Element * E = gui . roots . back ( ) ; E ; E = E - > prev ( ) ) {
Control * sw = E - > get ( ) ;
2020-05-14 16:41:43 +02:00
if ( ! sw - > is_visible_in_tree ( ) ) {
2016-01-17 02:41:10 +01:00
continue ;
2020-05-14 16:41:43 +02:00
}
2016-01-17 02:41:10 +01:00
2017-01-11 04:52:51 +01:00
Transform2D xform ;
2016-01-17 02:41:10 +01:00
CanvasItem * pci = sw - > get_parent_item ( ) ;
2020-05-14 16:41:43 +02:00
if ( pci ) {
2016-01-20 00:27:27 +01:00
xform = pci - > get_global_transform_with_canvas ( ) ;
2020-05-14 16:41:43 +02:00
} else {
2016-02-03 13:31:18 +01:00
xform = sw - > get_canvas_transform ( ) ;
2020-05-14 16:41:43 +02:00
}
2016-01-17 02:41:10 +01:00
2022-12-05 10:41:32 +01:00
Control * ret = _gui_find_control_at_pos ( sw , p_global , xform ) ;
2020-05-14 16:41:43 +02:00
if ( ret ) {
2016-01-17 02:41:10 +01:00
return ret ;
2020-05-14 16:41:43 +02:00
}
2016-01-17 02:41:10 +01:00
}
2020-04-02 01:20:12 +02:00
return nullptr ;
2016-01-17 02:41:10 +01:00
}
2022-12-05 10:41:32 +01:00
Control * Viewport : : _gui_find_control_at_pos ( CanvasItem * p_node , const Point2 & p_global , const Transform2D & p_xform ) {
2017-01-13 14:45:50 +01:00
if ( ! p_node - > is_visible ( ) ) {
2021-09-10 16:58:33 +02:00
return nullptr ; // Canvas item hidden, discard.
2016-01-17 02:41:10 +01:00
}
2017-01-11 04:52:51 +01:00
Transform2D matrix = p_xform * p_node - > get_transform ( ) ;
2023-04-21 08:21:59 +02:00
// matrix.determinant() == 0.0f implies that node does not exist on scene
if ( matrix . determinant ( ) = = 0.0f ) {
2020-04-02 01:20:12 +02:00
return nullptr ;
2020-05-14 16:41:43 +02:00
}
2016-01-17 02:41:10 +01:00
2018-08-24 09:35:07 +02:00
Control * c = Object : : cast_to < Control > ( p_node ) ;
2021-06-25 15:46:37 +02:00
if ( ! c | | ! c - > is_clipping_contents ( ) | | c - > has_point ( matrix . affine_inverse ( ) . xform ( p_global ) ) ) {
2016-01-17 02:41:10 +01:00
for ( int i = p_node - > get_child_count ( ) - 1 ; i > = 0 ; i - - ) {
2017-08-24 22:58:51 +02:00
CanvasItem * ci = Object : : cast_to < CanvasItem > ( p_node - > get_child ( i ) ) ;
2020-10-01 09:17:33 +02:00
if ( ! ci | | ci - > is_set_as_top_level ( ) ) {
2016-01-17 02:41:10 +01:00
continue ;
2020-05-14 16:41:43 +02:00
}
2016-01-17 02:41:10 +01:00
2022-12-05 10:41:32 +01:00
Control * ret = _gui_find_control_at_pos ( ci , p_global , matrix ) ;
2020-05-14 16:41:43 +02:00
if ( ret ) {
2016-01-17 02:41:10 +01:00
return ret ;
2020-05-14 16:41:43 +02:00
}
2016-01-17 02:41:10 +01:00
}
}
2021-02-24 12:47:14 +01:00
if ( ! c | | c - > data . mouse_filter = = Control : : MOUSE_FILTER_IGNORE ) {
2020-04-02 01:20:12 +02:00
return nullptr ;
2020-05-14 16:41:43 +02:00
}
2016-01-17 02:41:10 +01:00
matrix . affine_invert ( ) ;
2021-02-24 12:47:14 +01:00
if ( ! c - > has_point ( matrix . xform ( p_global ) ) ) {
return nullptr ;
}
2016-01-17 02:41:10 +01:00
2021-02-24 12:47:14 +01:00
Control * drag_preview = _gui_get_drag_preview ( ) ;
2021-06-19 00:02:50 +02:00
if ( ! drag_preview | | ( c ! = drag_preview & & ! drag_preview - > is_ancestor_of ( c ) ) ) {
2016-01-17 02:41:10 +01:00
return c ;
2020-05-14 16:41:43 +02:00
}
2021-02-24 12:47:14 +01:00
return nullptr ;
2016-01-17 02:41:10 +01:00
}
2017-01-24 03:12:08 +01:00
bool Viewport : : _gui_drop ( Control * p_at_control , Point2 p_at_pos , bool p_just_check ) {
2021-09-10 16:58:33 +02:00
// Attempt grab, try parent controls too.
CanvasItem * ci = p_at_control ;
while ( ci ) {
Control * control = Object : : cast_to < Control > ( ci ) ;
if ( control ) {
if ( control - > can_drop_data ( p_at_pos , gui . drag_data ) ) {
if ( ! p_just_check ) {
control - > drop_data ( p_at_pos , gui . drag_data ) ;
2017-01-24 03:12:08 +01:00
}
2021-09-10 16:58:33 +02:00
return true ;
2017-01-24 03:12:08 +01:00
}
2021-09-10 16:58:33 +02:00
if ( control - > data . mouse_filter = = Control : : MOUSE_FILTER_STOP ) {
2017-01-24 03:12:08 +01:00
break ;
2020-05-14 16:41:43 +02:00
}
2021-09-10 16:58:33 +02:00
}
p_at_pos = ci - > get_transform ( ) . xform ( p_at_pos ) ;
2017-01-24 03:12:08 +01:00
2021-09-10 16:58:33 +02:00
if ( ci - > is_set_as_top_level ( ) ) {
break ;
2017-01-24 03:12:08 +01:00
}
2021-09-10 16:58:33 +02:00
ci = ci - > get_parent_item ( ) ;
2017-01-24 03:12:08 +01:00
}
return false ;
}
2017-05-20 17:38:03 +02:00
void Viewport : : _gui_input_event ( Ref < InputEvent > p_event ) {
2019-11-07 10:37:44 +01:00
ERR_FAIL_COND ( p_event . is_null ( ) ) ;
2019-06-22 14:52:51 +02:00
2017-05-20 17:38:03 +02:00
Ref < InputEventMouseButton > mb = p_event ;
if ( mb . is_valid ( ) ) {
gui . key_event_accepted = false ;
2016-01-17 02:41:10 +01:00
2017-06-03 10:54:24 +02:00
Point2 mpos = mb - > get_position ( ) ;
2017-05-20 17:38:03 +02:00
if ( mb - > is_pressed ( ) ) {
2024-03-26 22:20:02 +01:00
MouseButtonMask button_mask = mouse_button_to_mask ( mb - > get_button_index ( ) ) ;
if ( ! gui . mouse_focus_mask . is_empty ( ) & & ! gui . mouse_focus_mask . has_flag ( button_mask ) ) {
// Do not steal mouse focus and stuff while a focus mask without the current mouse button exists.
gui . mouse_focus_mask . set_flag ( button_mask ) ;
2017-05-20 17:38:03 +02:00
} else {
2022-12-05 10:41:32 +01:00
gui . mouse_focus = gui_find_control ( mpos ) ;
2016-01-17 02:41:10 +01:00
2017-05-20 17:38:03 +02:00
if ( ! gui . mouse_focus ) {
return ;
}
2016-01-17 02:41:10 +01:00
2023-01-08 00:55:54 +01:00
gui . mouse_focus_mask . set_flag ( mouse_button_to_mask ( mb - > get_button_index ( ) ) ) ;
2019-03-04 14:26:48 +01:00
2021-08-13 23:31:57 +02:00
if ( mb - > get_button_index ( ) = = MouseButton : : LEFT ) {
2017-05-20 17:38:03 +02:00
gui . drag_accum = Vector2 ( ) ;
gui . drag_attempted = false ;
2016-01-17 02:41:10 +01:00
}
2017-05-20 17:38:03 +02:00
}
2023-02-08 18:39:05 +01:00
DEV_ASSERT ( gui . mouse_focus ) ;
2017-05-20 17:38:03 +02:00
2021-09-10 16:58:33 +02:00
mb = mb - > xformed_by ( Transform2D ( ) ) ; // Make a copy of the event.
2017-05-20 17:38:03 +02:00
2022-12-05 10:41:32 +01:00
Point2 pos = gui . mouse_focus - > get_global_transform_with_canvas ( ) . affine_inverse ( ) . xform ( mpos ) ;
2017-06-03 10:54:24 +02:00
mb - > set_position ( pos ) ;
2016-01-17 02:41:10 +01:00
# ifdef DEBUG_ENABLED
2023-02-08 18:39:05 +01:00
if ( EngineDebugger : : get_singleton ( ) ) {
2017-05-20 17:38:03 +02:00
Array arr ;
arr . push_back ( gui . mouse_focus - > get_path ( ) ) ;
arr . push_back ( gui . mouse_focus - > get_class ( ) ) ;
2020-02-27 03:30:20 +01:00
EngineDebugger : : get_singleton ( ) - > send_message ( " scene:click_ctrl " , arr ) ;
2017-05-20 17:38:03 +02:00
}
2016-01-17 02:41:10 +01:00
# endif
2021-08-13 23:31:57 +02:00
if ( mb - > get_button_index ( ) = = MouseButton : : LEFT ) { // Assign focus.
2017-05-20 17:38:03 +02:00
CanvasItem * ci = gui . mouse_focus ;
while ( ci ) {
2017-08-24 22:58:51 +02:00
Control * control = Object : : cast_to < Control > ( ci ) ;
2017-05-20 17:38:03 +02:00
if ( control ) {
if ( control - > get_focus_mode ( ) ! = Control : : FOCUS_NONE ) {
if ( control ! = gui . key_focus ) {
control - > grab_focus ( ) ;
2017-01-21 23:00:25 +01:00
}
2017-05-20 17:38:03 +02:00
break ;
2017-01-21 23:00:25 +01:00
}
2020-05-14 16:41:43 +02:00
if ( control - > data . mouse_filter = = Control : : MOUSE_FILTER_STOP ) {
2017-01-21 23:00:25 +01:00
break ;
2020-05-14 16:41:43 +02:00
}
2017-01-21 23:00:25 +01:00
}
2016-01-17 02:41:10 +01:00
2020-10-01 09:17:33 +02:00
if ( ci - > is_set_as_top_level ( ) ) {
2017-05-20 17:38:03 +02:00
break ;
2020-05-14 16:41:43 +02:00
}
2016-01-17 02:41:10 +01:00
2017-05-20 17:38:03 +02:00
ci = ci - > get_parent_item ( ) ;
}
}
2016-01-17 02:41:10 +01:00
2023-06-22 21:58:19 +02:00
bool stopped = gui . mouse_focus & & gui . mouse_focus - > can_process ( ) & & _gui_call_input ( gui . mouse_focus , mb ) ;
2022-05-16 15:10:30 +02:00
if ( stopped ) {
set_input_as_handled ( ) ;
}
2016-07-01 15:34:38 +02:00
2022-11-08 19:02:47 +01:00
if ( gui . dragging & & mb - > get_button_index ( ) = = MouseButton : : LEFT ) {
2021-09-10 16:58:33 +02:00
// Alternate drop use (when using force_drag(), as proposed by #5342).
2022-11-08 19:02:47 +01:00
_perform_drop ( gui . mouse_focus , pos ) ;
2017-05-20 17:38:03 +02:00
}
2016-01-17 02:41:10 +01:00
2017-05-20 17:38:03 +02:00
_gui_cancel_tooltip ( ) ;
} else {
2022-11-08 19:02:47 +01:00
if ( gui . dragging & & mb - > get_button_index ( ) = = MouseButton : : LEFT ) {
_perform_drop ( gui . drag_mouse_over , gui . drag_mouse_over_pos ) ;
2017-05-20 17:38:03 +02:00
}
2016-01-17 02:41:10 +01:00
2023-01-08 00:55:54 +01:00
gui . mouse_focus_mask . clear_flag ( mouse_button_to_mask ( mb - > get_button_index ( ) ) ) ; // Remove from mask.
2018-11-28 13:31:17 +01:00
2017-05-20 17:38:03 +02:00
if ( ! gui . mouse_focus ) {
2021-09-10 16:58:33 +02:00
// Release event is only sent if a mouse focus (previously pressed button) exists.
2017-05-20 17:38:03 +02:00
return ;
}
2016-01-17 02:41:10 +01:00
2021-09-10 16:58:33 +02:00
mb = mb - > xformed_by ( Transform2D ( ) ) ; // Make a copy.
2022-12-05 10:41:32 +01:00
Point2 pos = gui . mouse_focus - > get_global_transform_with_canvas ( ) . affine_inverse ( ) . xform ( mpos ) ;
2017-06-03 10:54:24 +02:00
mb - > set_position ( pos ) ;
2016-01-17 02:41:10 +01:00
2017-12-21 15:03:17 +01:00
Control * mouse_focus = gui . mouse_focus ;
2016-01-17 02:41:10 +01:00
2021-09-10 16:58:33 +02:00
// Disable mouse focus if needed before calling input,
// this makes popups on mouse press event work better,
// as the release will never be received otherwise.
2023-01-08 00:55:54 +01:00
if ( gui . mouse_focus_mask . is_empty ( ) ) {
2020-04-02 01:20:12 +02:00
gui . mouse_focus = nullptr ;
2020-03-20 03:32:09 +01:00
gui . forced_mouse_focus = false ;
2017-05-20 17:38:03 +02:00
}
2016-01-17 02:41:10 +01:00
2023-02-08 18:39:05 +01:00
bool stopped = mouse_focus & & mouse_focus - > can_process ( ) & & _gui_call_input ( mouse_focus , mb ) ;
2022-05-16 15:10:30 +02:00
if ( stopped ) {
set_input_as_handled ( ) ;
}
2017-05-20 17:38:03 +02:00
}
}
2016-01-17 02:41:10 +01:00
2017-05-20 17:38:03 +02:00
Ref < InputEventMouseMotion > mm = p_event ;
if ( mm . is_valid ( ) ) {
gui . key_event_accepted = false ;
2017-06-03 10:54:24 +02:00
Point2 mpos = mm - > get_position ( ) ;
2017-01-24 03:12:08 +01:00
2021-09-10 16:58:33 +02:00
// Drag & drop.
2023-01-08 00:55:54 +01:00
if ( ! gui . drag_attempted & & gui . mouse_focus & & ( mm - > get_button_mask ( ) . has_flag ( MouseButtonMask : : LEFT ) ) ) {
2017-05-20 17:38:03 +02:00
gui . drag_accum + = mm - > get_relative ( ) ;
float len = gui . drag_accum . length ( ) ;
if ( len > 10 ) {
2021-09-10 16:58:33 +02:00
{ // Attempt grab, try parent controls too.
2017-05-20 17:38:03 +02:00
CanvasItem * ci = gui . mouse_focus ;
while ( ci ) {
2017-08-24 22:58:51 +02:00
Control * control = Object : : cast_to < Control > ( ci ) ;
2017-05-20 17:38:03 +02:00
if ( control ) {
2018-08-24 15:29:27 +02:00
gui . dragging = true ;
2022-11-18 18:10:57 +01:00
gui . drag_data = control - > get_drag_data ( control - > get_global_transform_with_canvas ( ) . affine_inverse ( ) . xform ( mpos - gui . drag_accum ) ) ;
2017-05-20 17:38:03 +02:00
if ( gui . drag_data . get_type ( ) ! = Variant : : NIL ) {
2020-04-02 01:20:12 +02:00
gui . mouse_focus = nullptr ;
2020-03-20 03:32:09 +01:00
gui . forced_mouse_focus = false ;
2023-01-08 00:55:54 +01:00
gui . mouse_focus_mask . clear ( ) ;
2018-11-19 22:37:39 +01:00
break ;
2018-08-24 15:29:27 +02:00
} else {
2021-02-24 12:47:14 +01:00
Control * drag_preview = _gui_get_drag_preview ( ) ;
if ( drag_preview ) {
2018-11-19 22:37:39 +01:00
ERR_PRINT ( " Don't set a drag preview and return null data. Preview was deleted and drag request ignored. " ) ;
2021-02-24 12:47:14 +01:00
memdelete ( drag_preview ) ;
gui . drag_preview_id = ObjectID ( ) ;
2018-11-19 22:37:39 +01:00
}
2018-08-24 15:29:27 +02:00
gui . dragging = false ;
2017-01-24 03:12:08 +01:00
}
2020-05-14 16:41:43 +02:00
if ( control - > data . mouse_filter = = Control : : MOUSE_FILTER_STOP ) {
2017-01-24 03:12:08 +01:00
break ;
2020-05-14 16:41:43 +02:00
}
2017-01-24 03:12:08 +01:00
}
2020-10-01 09:17:33 +02:00
if ( ci - > is_set_as_top_level ( ) ) {
2017-05-20 17:38:03 +02:00
break ;
2020-05-14 16:41:43 +02:00
}
2017-01-24 03:12:08 +01:00
2017-05-20 17:38:03 +02:00
ci = ci - > get_parent_item ( ) ;
2016-05-11 16:46:08 +02:00
}
2016-01-17 02:41:10 +01:00
}
2017-05-20 17:38:03 +02:00
gui . drag_attempted = true ;
2022-11-08 19:02:47 +01:00
if ( gui . dragging ) {
2017-05-20 17:38:03 +02:00
_propagate_viewport_notification ( this , NOTIFICATION_DRAG_BEGIN ) ;
}
2016-01-17 02:41:10 +01:00
}
2017-05-20 17:38:03 +02:00
}
2016-01-17 02:41:10 +01:00
2021-04-24 14:03:38 +02:00
Control * over = nullptr ;
2022-03-26 17:01:19 +01:00
if ( gui . mouse_focus ) {
over = gui . mouse_focus ;
2023-01-06 21:48:20 +01:00
} else if ( gui . mouse_in_viewport ) {
over = gui_find_control ( mpos ) ;
2022-03-26 17:01:19 +01:00
}
2020-04-28 15:19:37 +02:00
DisplayServer : : CursorShape ds_cursor_shape = ( DisplayServer : : CursorShape ) Input : : get_singleton ( ) - > get_default_cursor_shape ( ) ;
2016-01-17 02:41:10 +01:00
2020-03-25 00:15:35 +01:00
if ( over ) {
Transform2D localizer = over - > get_global_transform_with_canvas ( ) . affine_inverse ( ) ;
Size2 pos = localizer . xform ( mpos ) ;
2021-12-29 14:22:22 +01:00
Vector2 velocity = localizer . basis_xform ( mm - > get_velocity ( ) ) ;
2020-03-25 00:15:35 +01:00
Vector2 rel = localizer . basis_xform ( mm - > get_relative ( ) ) ;
2016-01-17 02:41:10 +01:00
2021-09-10 16:58:33 +02:00
mm = mm - > xformed_by ( Transform2D ( ) ) ; // Make a copy.
2016-01-17 02:41:10 +01:00
2020-03-25 00:15:35 +01:00
mm - > set_global_position ( mpos ) ;
2021-12-29 14:22:22 +01:00
mm - > set_velocity ( velocity ) ;
2020-03-25 00:15:35 +01:00
mm - > set_relative ( rel ) ;
2016-01-17 02:41:10 +01:00
2023-09-24 07:18:17 +02:00
// Nothing pressed.
2023-01-08 00:55:54 +01:00
if ( mm - > get_button_mask ( ) . is_empty ( ) ) {
2020-03-25 00:15:35 +01:00
bool is_tooltip_shown = false ;
2020-03-20 21:51:53 +01:00
2020-03-25 00:15:35 +01:00
if ( gui . tooltip_popup ) {
2021-11-29 13:23:28 +01:00
if ( gui . tooltip_control ) {
2021-12-12 09:12:26 +01:00
String tooltip = _gui_get_tooltip ( over , gui . tooltip_control - > get_global_transform ( ) . xform_inv ( mpos ) ) ;
2022-02-15 16:29:03 +01:00
tooltip = tooltip . strip_edges ( ) ;
2023-09-24 07:18:17 +02:00
if ( tooltip . is_empty ( ) | | tooltip ! = gui . tooltip_text ) {
2020-03-25 00:15:35 +01:00
_gui_cancel_tooltip ( ) ;
2020-03-20 21:51:53 +01:00
} else {
2023-09-24 07:18:17 +02:00
is_tooltip_shown = true ;
2020-03-20 21:51:53 +01:00
}
2020-05-14 16:41:43 +02:00
} else {
2020-03-25 00:15:35 +01:00
_gui_cancel_tooltip ( ) ;
2020-05-14 16:41:43 +02:00
}
2020-03-25 00:15:35 +01:00
}
2021-11-29 13:23:28 +01:00
if ( ! is_tooltip_shown & & over - > can_process ( ) ) {
2021-02-27 00:37:20 +01:00
if ( gui . tooltip_timer . is_valid ( ) ) {
gui . tooltip_timer - > release_connections ( ) ;
gui . tooltip_timer = Ref < SceneTreeTimer > ( ) ;
}
2020-11-02 17:18:29 +01:00
gui . tooltip_control = over ;
gui . tooltip_pos = over - > get_screen_transform ( ) . xform ( pos ) ;
2021-02-27 00:37:20 +01:00
gui . tooltip_timer = get_tree ( ) - > create_timer ( gui . tooltip_delay ) ;
gui . tooltip_timer - > set_ignore_time_scale ( true ) ;
gui . tooltip_timer - > connect ( " timeout " , callable_mp ( this , & Viewport : : _gui_show_tooltip ) ) ;
2020-03-25 00:15:35 +01:00
}
2017-05-20 17:38:03 +02:00
}
2016-07-18 22:14:57 +02:00
2020-03-25 00:15:35 +01:00
mm - > set_position ( pos ) ;
Control : : CursorShape cursor_shape = Control : : CURSOR_ARROW ;
{
Control * c = over ;
Vector2 cpos = pos ;
while ( c ) {
2023-01-08 00:55:54 +01:00
if ( ! gui . mouse_focus_mask . is_empty ( ) | | c - > has_point ( cpos ) ) {
2020-07-02 19:15:03 +02:00
cursor_shape = c - > get_cursor_shape ( cpos ) ;
} else {
cursor_shape = Control : : CURSOR_ARROW ;
}
2020-03-25 00:15:35 +01:00
cpos = c - > get_transform ( ) . xform ( cpos ) ;
2020-05-14 16:41:43 +02:00
if ( cursor_shape ! = Control : : CURSOR_ARROW ) {
2020-03-25 00:15:35 +01:00
break ;
2020-05-14 16:41:43 +02:00
}
if ( c - > data . mouse_filter = = Control : : MOUSE_FILTER_STOP ) {
2020-03-25 00:15:35 +01:00
break ;
2020-05-14 16:41:43 +02:00
}
2020-10-01 09:17:33 +02:00
if ( c - > is_set_as_top_level ( ) ) {
2020-03-25 00:15:35 +01:00
break ;
2020-05-14 16:41:43 +02:00
}
2020-03-25 00:15:35 +01:00
c = c - > get_parent_control ( ) ;
}
}
ds_cursor_shape = ( DisplayServer : : CursorShape ) cursor_shape ;
2023-02-08 18:39:05 +01:00
bool stopped = over - > can_process ( ) & & _gui_call_input ( over , mm ) ;
2022-05-16 15:10:30 +02:00
if ( stopped ) {
set_input_as_handled ( ) ;
}
2017-05-20 17:38:03 +02:00
}
2016-01-17 02:41:10 +01:00
2022-11-08 19:02:47 +01:00
if ( gui . dragging ) {
2021-09-10 16:58:33 +02:00
// Handle drag & drop.
2016-01-17 02:41:10 +01:00
2021-02-24 12:47:14 +01:00
Control * drag_preview = _gui_get_drag_preview ( ) ;
if ( drag_preview ) {
drag_preview - > set_position ( mpos ) ;
2020-03-25 00:15:35 +01:00
}
2016-01-17 02:41:10 +01:00
2020-03-25 00:15:35 +01:00
gui . drag_mouse_over = over ;
gui . drag_mouse_over_pos = Vector2 ( ) ;
2021-09-10 16:58:33 +02:00
// Find the window this is above of.
// See if there is an embedder.
2020-03-25 00:15:35 +01:00
Viewport * embedder = nullptr ;
Vector2 viewport_pos ;
if ( is_embedding_subwindows ( ) ) {
embedder = this ;
viewport_pos = mpos ;
} else {
2021-09-10 16:58:33 +02:00
// Not an embedder, but may be a subwindow of an embedder.
2020-03-25 00:15:35 +01:00
Window * w = Object : : cast_to < Window > ( this ) ;
if ( w ) {
if ( w - > is_embedded ( ) ) {
2023-02-05 17:35:39 +01:00
embedder = w - > get_embedder ( ) ;
2020-03-25 00:15:35 +01:00
2022-10-01 08:40:11 +02:00
viewport_pos = get_final_transform ( ) . xform ( mpos ) + w - > get_position ( ) ; // To parent coords.
2020-03-25 00:15:35 +01:00
}
}
2018-06-07 17:46:14 +02:00
}
2020-03-25 00:15:35 +01:00
Viewport * viewport_under = nullptr ;
2016-01-17 02:41:10 +01:00
2020-03-25 00:15:35 +01:00
if ( embedder ) {
2021-09-10 16:58:33 +02:00
// Use embedder logic.
2016-01-17 02:41:10 +01:00
2020-03-25 00:15:35 +01:00
for ( int i = embedder - > gui . sub_windows . size ( ) - 1 ; i > = 0 ; i - - ) {
Window * sw = embedder - > gui . sub_windows [ i ] . window ;
Rect2 swrect = Rect2i ( sw - > get_position ( ) , sw - > get_size ( ) ) ;
if ( ! sw - > get_flag ( Window : : FLAG_BORDERLESS ) ) {
2023-09-12 15:01:42 +02:00
int title_height = sw - > theme_cache . title_height ;
2020-03-25 00:15:35 +01:00
swrect . position . y - = title_height ;
swrect . size . y + = title_height ;
}
if ( swrect . has_point ( viewport_pos ) ) {
viewport_under = sw ;
viewport_pos - = sw - > get_position ( ) ;
}
}
2016-01-17 02:41:10 +01:00
2020-03-25 00:15:35 +01:00
if ( ! viewport_under ) {
2021-09-10 16:58:33 +02:00
// Not in a subwindow, likely in embedder.
2020-03-25 00:15:35 +01:00
viewport_under = embedder ;
}
} else {
2021-09-10 16:58:33 +02:00
// Use DisplayServer logic.
2020-03-25 00:15:35 +01:00
Vector2i screen_mouse_pos = DisplayServer : : get_singleton ( ) - > mouse_get_position ( ) ;
DisplayServer : : WindowID window_id = DisplayServer : : get_singleton ( ) - > get_window_at_screen_position ( screen_mouse_pos ) ;
if ( window_id ! = DisplayServer : : INVALID_WINDOW_ID ) {
ObjectID object_under = DisplayServer : : get_singleton ( ) - > window_get_attached_instance_id ( window_id ) ;
2021-09-10 16:58:33 +02:00
if ( object_under ! = ObjectID ( ) ) { // Fetch window.
2020-03-25 00:15:35 +01:00
Window * w = Object : : cast_to < Window > ( ObjectDB : : get_instance ( object_under ) ) ;
if ( w ) {
viewport_under = w ;
2023-12-25 23:32:29 +01:00
viewport_pos = w - > get_final_transform ( ) . affine_inverse ( ) . xform ( screen_mouse_pos - w - > get_position ( ) ) ;
2020-03-25 00:15:35 +01:00
}
}
}
}
2016-01-17 02:41:10 +01:00
2020-03-25 00:15:35 +01:00
if ( viewport_under ) {
2022-03-31 00:43:52 +02:00
if ( viewport_under ! = this ) {
2022-10-01 08:40:11 +02:00
Transform2D ai = viewport_under - > get_final_transform ( ) . affine_inverse ( ) ;
2022-03-31 00:43:52 +02:00
viewport_pos = ai . xform ( viewport_pos ) ;
}
2021-09-10 16:58:33 +02:00
// Find control under at position.
2021-07-19 22:09:23 +02:00
gui . drag_mouse_over = viewport_under - > gui_find_control ( viewport_pos ) ;
2020-03-25 00:15:35 +01:00
if ( gui . drag_mouse_over ) {
Transform2D localizer = gui . drag_mouse_over - > get_global_transform_with_canvas ( ) . affine_inverse ( ) ;
gui . drag_mouse_over_pos = localizer . xform ( viewport_pos ) ;
2021-12-03 11:19:41 +01:00
bool can_drop = _gui_drop ( gui . drag_mouse_over , gui . drag_mouse_over_pos , true ) ;
2020-03-25 00:15:35 +01:00
2021-12-03 11:19:41 +01:00
if ( ! can_drop ) {
ds_cursor_shape = DisplayServer : : CURSOR_FORBIDDEN ;
} else {
ds_cursor_shape = DisplayServer : : CURSOR_CAN_DROP ;
2020-03-25 00:15:35 +01:00
}
}
2016-05-11 16:46:08 +02:00
2017-05-20 17:38:03 +02:00
} else {
2020-03-25 00:15:35 +01:00
gui . drag_mouse_over = nullptr ;
2016-01-17 02:41:10 +01:00
}
2017-05-20 17:38:03 +02:00
}
2020-03-25 00:15:35 +01:00
2023-07-23 02:14:41 +02:00
if ( DisplayServer : : get_singleton ( ) - > has_feature ( DisplayServer : : FEATURE_CURSOR_SHAPE ) & & ! Object : : cast_to < SubViewportContainer > ( over ) ) {
2022-08-23 11:14:07 +02:00
DisplayServer : : get_singleton ( ) - > cursor_set_shape ( ds_cursor_shape ) ;
}
2017-05-20 17:38:03 +02:00
}
2016-01-17 02:41:10 +01:00
2017-08-07 06:44:46 +02:00
Ref < InputEventScreenTouch > touch_event = p_event ;
if ( touch_event . is_valid ( ) ) {
Size2 pos = touch_event - > get_position ( ) ;
2022-11-14 01:09:03 +01:00
const int touch_index = touch_event - > get_index ( ) ;
2017-08-07 06:44:46 +02:00
if ( touch_event - > is_pressed ( ) ) {
2021-07-19 22:09:23 +02:00
Control * over = gui_find_control ( pos ) ;
2017-08-07 06:44:46 +02:00
if ( over ) {
2022-11-14 01:09:03 +01:00
gui . touch_focus [ touch_index ] = over - > get_instance_id ( ) ;
2022-05-16 15:10:30 +02:00
bool stopped = false ;
2017-08-07 06:44:46 +02:00
if ( over - > can_process ( ) ) {
2021-09-10 16:58:33 +02:00
touch_event = touch_event - > xformed_by ( Transform2D ( ) ) ; // Make a copy.
2022-12-05 10:41:32 +01:00
pos = over - > get_global_transform_with_canvas ( ) . affine_inverse ( ) . xform ( pos ) ;
2017-08-07 06:44:46 +02:00
touch_event - > set_position ( pos ) ;
2022-05-16 15:10:30 +02:00
stopped = _gui_call_input ( over , touch_event ) ;
}
if ( stopped ) {
set_input_as_handled ( ) ;
2017-08-07 06:44:46 +02:00
}
return ;
}
2022-11-14 01:09:03 +01:00
} else {
2022-05-16 15:10:30 +02:00
bool stopped = false ;
2022-11-14 01:09:03 +01:00
ObjectID control_id = gui . touch_focus [ touch_index ] ;
Control * over = control_id . is_valid ( ) ? Object : : cast_to < Control > ( ObjectDB : : get_instance ( control_id ) ) : nullptr ;
if ( over & & over - > can_process ( ) ) {
2021-09-10 16:58:33 +02:00
touch_event = touch_event - > xformed_by ( Transform2D ( ) ) ; // Make a copy.
2023-01-18 00:43:16 +01:00
pos = over - > get_global_transform_with_canvas ( ) . affine_inverse ( ) . xform ( pos ) ;
2022-11-14 01:09:03 +01:00
touch_event - > set_position ( pos ) ;
2017-08-07 06:44:46 +02:00
2022-11-14 01:09:03 +01:00
stopped = _gui_call_input ( over , touch_event ) ;
2022-05-16 15:10:30 +02:00
}
if ( stopped ) {
set_input_as_handled ( ) ;
2017-08-07 06:44:46 +02:00
}
2022-11-14 01:09:03 +01:00
gui . touch_focus . erase ( touch_index ) ;
2017-08-07 06:44:46 +02:00
return ;
}
}
2017-11-01 21:49:39 +01:00
Ref < InputEventGesture > gesture_event = p_event ;
if ( gesture_event . is_valid ( ) ) {
2018-03-04 22:19:10 +01:00
gui . key_event_accepted = false ;
2017-12-22 19:39:23 +01:00
_gui_cancel_tooltip ( ) ;
2017-11-01 21:49:39 +01:00
Size2 pos = gesture_event - > get_position ( ) ;
2021-07-19 22:09:23 +02:00
Control * over = gui_find_control ( pos ) ;
2017-11-01 21:49:39 +01:00
if ( over ) {
2022-05-16 15:10:30 +02:00
bool stopped = false ;
2017-11-01 21:49:39 +01:00
if ( over - > can_process ( ) ) {
2021-09-10 16:58:33 +02:00
gesture_event = gesture_event - > xformed_by ( Transform2D ( ) ) ; // Make a copy.
2022-12-05 10:41:32 +01:00
pos = over - > get_global_transform_with_canvas ( ) . affine_inverse ( ) . xform ( pos ) ;
2017-11-01 21:49:39 +01:00
gesture_event - > set_position ( pos ) ;
2022-05-16 15:10:30 +02:00
stopped = _gui_call_input ( over , gesture_event ) ;
}
if ( stopped ) {
set_input_as_handled ( ) ;
2017-11-01 21:49:39 +01:00
}
return ;
}
}
2017-08-07 06:44:46 +02:00
Ref < InputEventScreenDrag > drag_event = p_event ;
if ( drag_event . is_valid ( ) ) {
2022-11-14 01:09:03 +01:00
const int drag_event_index = drag_event - > get_index ( ) ;
ObjectID control_id = gui . touch_focus [ drag_event_index ] ;
Control * over = control_id . is_valid ( ) ? Object : : cast_to < Control > ( ObjectDB : : get_instance ( control_id ) ) : nullptr ;
2017-08-07 06:44:46 +02:00
if ( ! over ) {
2021-07-19 22:09:23 +02:00
over = gui_find_control ( drag_event - > get_position ( ) ) ;
2017-08-07 06:44:46 +02:00
}
if ( over ) {
2022-05-16 15:10:30 +02:00
bool stopped = false ;
2017-08-07 06:44:46 +02:00
if ( over - > can_process ( ) ) {
Transform2D localizer = over - > get_global_transform_with_canvas ( ) . affine_inverse ( ) ;
Size2 pos = localizer . xform ( drag_event - > get_position ( ) ) ;
2021-12-29 14:22:22 +01:00
Vector2 velocity = localizer . basis_xform ( drag_event - > get_velocity ( ) ) ;
2017-08-07 06:44:46 +02:00
Vector2 rel = localizer . basis_xform ( drag_event - > get_relative ( ) ) ;
2021-09-10 16:58:33 +02:00
drag_event = drag_event - > xformed_by ( Transform2D ( ) ) ; // Make a copy.
2017-08-07 06:44:46 +02:00
2021-12-29 14:22:22 +01:00
drag_event - > set_velocity ( velocity ) ;
2017-08-07 06:44:46 +02:00
drag_event - > set_relative ( rel ) ;
drag_event - > set_position ( pos ) ;
2022-05-16 15:10:30 +02:00
stopped = _gui_call_input ( over , drag_event ) ;
2017-08-07 06:44:46 +02:00
}
2022-05-16 15:10:30 +02:00
if ( stopped ) {
set_input_as_handled ( ) ;
}
2017-08-07 06:44:46 +02:00
return ;
}
}
2017-05-20 17:38:03 +02:00
if ( mm . is_null ( ) & & mb . is_null ( ) & & p_event - > is_action_type ( ) ) {
2022-11-08 19:02:47 +01:00
if ( gui . dragging & & p_event - > is_action_pressed ( " ui_cancel " ) & & Input : : get_singleton ( ) - > is_action_just_pressed ( " ui_cancel " ) ) {
_perform_drop ( ) ;
set_input_as_handled ( ) ;
return ;
}
2023-08-07 10:52:28 +02:00
if ( p_event - > is_action_pressed ( " ui_cancel " ) ) {
// Cancel tooltip timer or hide tooltip when pressing Escape (this is standard behavior in most applications).
_gui_cancel_tooltip ( ) ;
if ( gui . tooltip_popup ) {
// If a tooltip was hidden, prevent other actions associated with `ui_cancel` from occurring.
// For instance, this prevents the node from being deselected when pressing Escape
// to hide a documentation tooltip in the inspector.
set_input_as_handled ( ) ;
return ;
}
}
2017-05-20 17:38:03 +02:00
if ( gui . key_focus & & ! gui . key_focus - > is_visible_in_tree ( ) ) {
gui . key_focus - > release_focus ( ) ;
}
2016-07-01 15:42:33 +02:00
2017-05-20 17:38:03 +02:00
if ( gui . key_focus ) {
gui . key_event_accepted = false ;
if ( gui . key_focus - > can_process ( ) ) {
2021-08-22 17:37:22 +02:00
gui . key_focus - > _call_gui_input ( p_event ) ;
2017-05-20 17:38:03 +02:00
}
2016-01-17 02:41:10 +01:00
2017-05-20 17:38:03 +02:00
if ( gui . key_event_accepted ) {
2018-11-15 17:54:26 +01:00
set_input_as_handled ( ) ;
2017-05-20 17:38:03 +02:00
return ;
2016-01-17 02:41:10 +01:00
}
2017-05-20 17:38:03 +02:00
}
2016-01-17 02:41:10 +01:00
2021-09-10 16:58:33 +02:00
Control * from = gui . key_focus ? gui . key_focus : nullptr ;
2016-01-17 02:41:10 +01:00
2017-05-20 17:38:03 +02:00
if ( from & & p_event - > is_pressed ( ) ) {
2020-04-02 01:20:12 +02:00
Control * next = nullptr ;
2016-01-17 02:41:10 +01:00
2022-03-27 11:41:29 +02:00
Ref < InputEventJoypadMotion > joypadmotion_event = p_event ;
if ( joypadmotion_event . is_valid ( ) ) {
Input * input = Input : : get_singleton ( ) ;
2016-01-17 02:41:10 +01:00
2022-03-27 11:41:29 +02:00
if ( p_event - > is_action_pressed ( " ui_focus_next " ) & & input - > is_action_just_pressed ( " ui_focus_next " ) ) {
next = from - > find_next_valid_focus ( ) ;
}
2016-01-17 02:41:10 +01:00
2022-03-27 11:41:29 +02:00
if ( p_event - > is_action_pressed ( " ui_focus_prev " ) & & input - > is_action_just_pressed ( " ui_focus_prev " ) ) {
next = from - > find_prev_valid_focus ( ) ;
}
2016-01-17 02:41:10 +01:00
2022-03-27 11:41:29 +02:00
if ( p_event - > is_action_pressed ( " ui_up " ) & & input - > is_action_just_pressed ( " ui_up " ) ) {
next = from - > _get_focus_neighbor ( SIDE_TOP ) ;
}
2016-01-17 02:41:10 +01:00
2022-03-27 11:41:29 +02:00
if ( p_event - > is_action_pressed ( " ui_left " ) & & input - > is_action_just_pressed ( " ui_left " ) ) {
next = from - > _get_focus_neighbor ( SIDE_LEFT ) ;
}
2016-01-17 02:41:10 +01:00
2022-03-27 11:41:29 +02:00
if ( p_event - > is_action_pressed ( " ui_right " ) & & input - > is_action_just_pressed ( " ui_right " ) ) {
next = from - > _get_focus_neighbor ( SIDE_RIGHT ) ;
}
2016-01-17 02:41:10 +01:00
2022-03-27 11:41:29 +02:00
if ( p_event - > is_action_pressed ( " ui_down " ) & & input - > is_action_just_pressed ( " ui_down " ) ) {
next = from - > _get_focus_neighbor ( SIDE_BOTTOM ) ;
}
} else {
if ( p_event - > is_action_pressed ( " ui_focus_next " , true , true ) ) {
next = from - > find_next_valid_focus ( ) ;
}
if ( p_event - > is_action_pressed ( " ui_focus_prev " , true , true ) ) {
next = from - > find_prev_valid_focus ( ) ;
}
if ( p_event - > is_action_pressed ( " ui_up " , true , true ) ) {
next = from - > _get_focus_neighbor ( SIDE_TOP ) ;
}
if ( p_event - > is_action_pressed ( " ui_left " , true , true ) ) {
next = from - > _get_focus_neighbor ( SIDE_LEFT ) ;
}
if ( p_event - > is_action_pressed ( " ui_right " , true , true ) ) {
next = from - > _get_focus_neighbor ( SIDE_RIGHT ) ;
}
if ( p_event - > is_action_pressed ( " ui_down " , true , true ) ) {
next = from - > _get_focus_neighbor ( SIDE_BOTTOM ) ;
}
}
2017-05-20 17:38:03 +02:00
if ( next ) {
next - > grab_focus ( ) ;
2018-11-15 17:54:26 +01:00
set_input_as_handled ( ) ;
2017-05-20 17:38:03 +02:00
}
}
2016-01-17 02:41:10 +01:00
}
}
2022-11-08 19:02:47 +01:00
void Viewport : : _perform_drop ( Control * p_control , Point2 p_pos ) {
// Without any arguments, simply cancel Drag and Drop.
if ( p_control ) {
gui . drag_successful = _gui_drop ( p_control , p_pos , false ) ;
} else {
gui . drag_successful = false ;
}
Control * drag_preview = _gui_get_drag_preview ( ) ;
if ( drag_preview ) {
memdelete ( drag_preview ) ;
gui . drag_preview_id = ObjectID ( ) ;
}
gui . drag_data = Variant ( ) ;
gui . dragging = false ;
gui . drag_mouse_over = nullptr ;
_propagate_viewport_notification ( this , NOTIFICATION_DRAG_END ) ;
2022-09-29 23:45:51 +02:00
// Display the new cursor shape instantly.
update_mouse_cursor_state ( ) ;
2022-11-08 19:02:47 +01:00
}
2022-03-13 23:54:13 +01:00
void Viewport : : _gui_cleanup_internal_state ( Ref < InputEvent > p_event ) {
ERR_FAIL_COND ( p_event . is_null ( ) ) ;
Ref < InputEventMouseButton > mb = p_event ;
if ( mb . is_valid ( ) ) {
if ( ! mb - > is_pressed ( ) ) {
2023-01-08 00:55:54 +01:00
gui . mouse_focus_mask . clear_flag ( mouse_button_to_mask ( mb - > get_button_index ( ) ) ) ; // Remove from mask.
2022-03-13 23:54:13 +01:00
}
}
}
2016-01-17 02:41:10 +01:00
List < Control * > : : Element * Viewport : : _gui_add_root_control ( Control * p_control ) {
gui . roots_order_dirty = true ;
return gui . roots . push_back ( p_control ) ;
}
2022-04-01 21:18:16 +02:00
void Viewport : : gui_set_root_order_dirty ( ) {
2023-05-12 13:53:15 +02:00
ERR_MAIN_THREAD_GUARD ;
2016-01-17 02:41:10 +01:00
gui . roots_order_dirty = true ;
}
2016-01-20 00:27:27 +01:00
void Viewport : : _gui_force_drag ( Control * p_base , const Variant & p_data , Control * p_control ) {
2019-08-08 22:11:48 +02:00
ERR_FAIL_COND_MSG ( p_data . get_type ( ) = = Variant : : NIL , " Drag data must be a value. " ) ;
2016-07-01 15:34:38 +02:00
2018-08-24 15:29:27 +02:00
gui . dragging = true ;
2016-01-17 02:41:10 +01:00
gui . drag_data = p_data ;
2020-04-02 01:20:12 +02:00
gui . mouse_focus = nullptr ;
2024-05-02 00:10:29 +02:00
gui . mouse_focus_mask . clear ( ) ;
2016-01-17 02:41:10 +01:00
if ( p_control ) {
2016-01-20 00:27:27 +01:00
_gui_set_drag_preview ( p_base , p_control ) ;
2016-01-17 02:41:10 +01:00
}
2021-12-03 11:19:41 +01:00
_propagate_viewport_notification ( this , NOTIFICATION_DRAG_BEGIN ) ;
2016-01-17 02:41:10 +01:00
}
2016-01-20 00:27:27 +01:00
void Viewport : : _gui_set_drag_preview ( Control * p_base , Control * p_control ) {
2016-01-17 02:41:10 +01:00
ERR_FAIL_NULL ( p_control ) ;
ERR_FAIL_COND ( p_control - > is_inside_tree ( ) ) ;
2020-04-02 01:20:12 +02:00
ERR_FAIL_COND ( p_control - > get_parent ( ) ! = nullptr ) ;
2016-01-17 02:41:10 +01:00
2021-02-24 12:47:14 +01:00
Control * drag_preview = _gui_get_drag_preview ( ) ;
if ( drag_preview ) {
memdelete ( drag_preview ) ;
2016-01-17 02:41:10 +01:00
}
2020-10-01 09:17:33 +02:00
p_control - > set_as_top_level ( true ) ;
2017-03-29 17:29:38 +02:00
p_control - > set_position ( gui . last_mouse_pos ) ;
2021-09-10 16:58:33 +02:00
p_base - > get_root_parent_control ( ) - > add_child ( p_control ) ; // Add as child of viewport.
2022-04-10 20:52:55 +02:00
p_control - > move_to_front ( ) ;
2018-05-08 07:52:38 +02:00
2021-02-24 12:47:14 +01:00
gui . drag_preview_id = p_control - > get_instance_id ( ) ;
}
Control * Viewport : : _gui_get_drag_preview ( ) {
if ( gui . drag_preview_id . is_null ( ) ) {
return nullptr ;
} else {
Control * drag_preview = Object : : cast_to < Control > ( ObjectDB : : get_instance ( gui . drag_preview_id ) ) ;
if ( ! drag_preview ) {
ERR_PRINT ( " Don't free the control set as drag preview. " ) ;
gui . drag_preview_id = ObjectID ( ) ;
}
return drag_preview ;
}
2016-01-17 02:41:10 +01:00
}
void Viewport : : _gui_remove_root_control ( List < Control * > : : Element * RI ) {
gui . roots . erase ( RI ) ;
}
void Viewport : : _gui_unfocus_control ( Control * p_control ) {
if ( gui . key_focus = = p_control ) {
gui . key_focus - > release_focus ( ) ;
}
}
2020-09-09 03:08:21 +02:00
void Viewport : : _gui_hide_control ( Control * p_control ) {
2016-01-17 02:41:10 +01:00
if ( gui . mouse_focus = = p_control ) {
2018-11-28 13:31:17 +01:00
_drop_mouse_focus ( ) ;
2016-01-17 02:41:10 +01:00
}
2020-05-14 16:41:43 +02:00
if ( gui . key_focus = = p_control ) {
2022-02-01 15:07:22 +01:00
gui_release_focus ( ) ;
2020-05-14 16:41:43 +02:00
}
2024-05-06 16:43:04 +02:00
if ( gui . mouse_over = = p_control | | gui . mouse_over_hierarchy . has ( p_control ) ) {
2023-10-31 18:55:34 +01:00
_drop_mouse_over ( p_control - > get_parent_control ( ) ) ;
2020-05-14 16:41:43 +02:00
}
if ( gui . drag_mouse_over = = p_control ) {
2020-04-02 01:20:12 +02:00
gui . drag_mouse_over = nullptr ;
2020-05-14 16:41:43 +02:00
}
2020-11-02 17:18:29 +01:00
if ( gui . tooltip_control = = p_control ) {
2016-01-25 14:30:03 +01:00
_gui_cancel_tooltip ( ) ;
2020-05-14 16:41:43 +02:00
}
2016-01-17 02:41:10 +01:00
}
void Viewport : : _gui_remove_control ( Control * p_control ) {
2018-11-28 13:31:17 +01:00
if ( gui . mouse_focus = = p_control ) {
2020-04-02 01:20:12 +02:00
gui . mouse_focus = nullptr ;
2020-03-20 03:32:09 +01:00
gui . forced_mouse_focus = false ;
2023-01-08 00:55:54 +01:00
gui . mouse_focus_mask . clear ( ) ;
2018-11-28 13:31:17 +01:00
}
2020-05-14 16:41:43 +02:00
if ( gui . key_focus = = p_control ) {
2020-04-02 01:20:12 +02:00
gui . key_focus = nullptr ;
2020-05-14 16:41:43 +02:00
}
2024-05-06 16:43:04 +02:00
if ( gui . mouse_over = = p_control | | gui . mouse_over_hierarchy . has ( p_control ) ) {
2023-10-31 18:55:34 +01:00
_drop_mouse_over ( p_control - > get_parent_control ( ) ) ;
2020-05-14 16:41:43 +02:00
}
if ( gui . drag_mouse_over = = p_control ) {
2020-04-02 01:20:12 +02:00
gui . drag_mouse_over = nullptr ;
2020-05-14 16:41:43 +02:00
}
2020-11-02 17:18:29 +01:00
if ( gui . tooltip_control = = p_control ) {
gui . tooltip_control = nullptr ;
2020-05-14 16:41:43 +02:00
}
2016-01-17 02:41:10 +01:00
}
2023-10-31 18:55:34 +01:00
void Viewport : : canvas_item_top_level_changed ( ) {
_gui_update_mouse_over ( ) ;
}
void Viewport : : _gui_update_mouse_over ( ) {
if ( gui . mouse_over = = nullptr | | gui . mouse_over_hierarchy . is_empty ( ) ) {
return ;
}
2023-11-24 04:38:34 +01:00
if ( gui . sending_mouse_enter_exit_notifications ) {
// If notifications are already being sent, delay call to next frame.
if ( get_tree ( ) & & ! get_tree ( ) - > is_connected ( SNAME ( " process_frame " ) , callable_mp ( this , & Viewport : : _gui_update_mouse_over ) ) ) {
get_tree ( ) - > connect ( SNAME ( " process_frame " ) , callable_mp ( this , & Viewport : : _gui_update_mouse_over ) , CONNECT_ONE_SHOT ) ;
}
return ;
}
2023-10-31 18:55:34 +01:00
// Rebuild the mouse over hierarchy.
LocalVector < Control * > new_mouse_over_hierarchy ;
LocalVector < Control * > needs_enter ;
LocalVector < int > needs_exit ;
CanvasItem * ancestor = gui . mouse_over ;
bool removing = false ;
bool reached_top = false ;
while ( ancestor ) {
Control * ancestor_control = Object : : cast_to < Control > ( ancestor ) ;
if ( ancestor_control ) {
int found = gui . mouse_over_hierarchy . find ( ancestor_control ) ;
if ( found > = 0 ) {
// Remove the node if the propagation chain has been broken or it is now MOUSE_FILTER_IGNORE.
if ( removing | | ancestor_control - > get_mouse_filter ( ) = = Control : : MOUSE_FILTER_IGNORE ) {
needs_exit . push_back ( found ) ;
}
}
if ( found = = 0 ) {
if ( removing ) {
// Stop if the chain has been broken and the top of the hierarchy has been reached.
break ;
}
reached_top = true ;
}
if ( ! removing & & ancestor_control - > get_mouse_filter ( ) ! = Control : : MOUSE_FILTER_IGNORE ) {
new_mouse_over_hierarchy . push_back ( ancestor_control ) ;
// Add the node if it was not found and it is now not MOUSE_FILTER_IGNORE.
if ( found < 0 ) {
needs_enter . push_back ( ancestor_control ) ;
}
}
if ( ancestor_control - > get_mouse_filter ( ) = = Control : : MOUSE_FILTER_STOP ) {
// MOUSE_FILTER_STOP breaks the propagation chain.
if ( reached_top ) {
break ;
}
removing = true ;
}
}
if ( ancestor - > is_set_as_top_level ( ) ) {
// Top level breaks the propagation chain.
if ( reached_top ) {
break ;
} else {
removing = true ;
ancestor = Object : : cast_to < CanvasItem > ( ancestor - > get_parent ( ) ) ;
continue ;
}
}
ancestor = ancestor - > get_parent_item ( ) ;
}
if ( needs_exit . is_empty ( ) & & needs_enter . is_empty ( ) ) {
return ;
}
2023-11-24 04:38:34 +01:00
gui . sending_mouse_enter_exit_notifications = true ;
2023-10-31 18:55:34 +01:00
// Send Mouse Exit Self notification.
if ( gui . mouse_over & & ! needs_exit . is_empty ( ) & & needs_exit [ 0 ] = = ( int ) gui . mouse_over_hierarchy . size ( ) - 1 ) {
gui . mouse_over - > notification ( Control : : NOTIFICATION_MOUSE_EXIT_SELF ) ;
gui . mouse_over = nullptr ;
}
// Send Mouse Exit notifications.
for ( int exit_control_index : needs_exit ) {
gui . mouse_over_hierarchy [ exit_control_index ] - > notification ( Control : : NOTIFICATION_MOUSE_EXIT ) ;
}
// Update the mouse over hierarchy.
gui . mouse_over_hierarchy . resize ( new_mouse_over_hierarchy . size ( ) ) ;
for ( int i = 0 ; i < ( int ) new_mouse_over_hierarchy . size ( ) ; i + + ) {
gui . mouse_over_hierarchy [ i ] = new_mouse_over_hierarchy [ new_mouse_over_hierarchy . size ( ) - 1 - i ] ;
}
// Send Mouse Enter notifications.
for ( int i = needs_enter . size ( ) - 1 ; i > = 0 ; i - - ) {
needs_enter [ i ] - > notification ( Control : : NOTIFICATION_MOUSE_ENTER ) ;
}
2023-11-24 04:38:34 +01:00
gui . sending_mouse_enter_exit_notifications = false ;
2023-10-31 18:55:34 +01:00
}
2020-07-01 15:59:42 +02:00
Window * Viewport : : get_base_window ( ) const {
2023-05-12 13:53:15 +02:00
ERR_READ_THREAD_GUARD_V ( nullptr ) ;
2021-06-13 05:36:32 +02:00
ERR_FAIL_COND_V ( ! is_inside_tree ( ) , nullptr ) ;
2020-07-01 15:59:42 +02:00
Viewport * v = const_cast < Viewport * > ( this ) ;
Window * w = Object : : cast_to < Window > ( v ) ;
while ( ! w ) {
v = v - > get_parent_viewport ( ) ;
w = Object : : cast_to < Window > ( v ) ;
}
return w ;
}
2023-08-16 03:06:15 +02:00
2020-07-01 15:59:42 +02:00
void Viewport : : _gui_remove_focus_for_window ( Node * p_window ) {
if ( get_base_window ( ) = = p_window ) {
2022-02-01 15:07:22 +01:00
gui_release_focus ( ) ;
2016-01-17 02:41:10 +01:00
}
}
bool Viewport : : _gui_control_has_focus ( const Control * p_control ) {
return gui . key_focus = = p_control ;
}
void Viewport : : _gui_control_grab_focus ( Control * p_control ) {
2020-05-14 16:41:43 +02:00
if ( gui . key_focus & & gui . key_focus = = p_control ) {
2021-09-10 16:58:33 +02:00
// No need for change.
2016-01-17 02:41:10 +01:00
return ;
2020-05-14 16:41:43 +02:00
}
2021-08-12 23:40:13 +02:00
get_tree ( ) - > call_group ( " _viewports " , " _gui_remove_focus_for_window " , ( Node * ) get_base_window ( ) ) ;
2023-06-23 01:47:05 +02:00
if ( p_control - > is_inside_tree ( ) & & p_control - > get_viewport ( ) = = this ) {
gui . key_focus = p_control ;
emit_signal ( SNAME ( " gui_focus_changed " ) , p_control ) ;
p_control - > notification ( Control : : NOTIFICATION_FOCUS_ENTER ) ;
p_control - > queue_redraw ( ) ;
}
2016-01-17 02:41:10 +01:00
}
void Viewport : : _gui_accept_event ( ) {
gui . key_event_accepted = true ;
2020-05-14 16:41:43 +02:00
if ( is_inside_tree ( ) ) {
2018-11-15 17:54:26 +01:00
set_input_as_handled ( ) ;
2020-05-14 16:41:43 +02:00
}
2016-01-17 02:41:10 +01:00
}
2018-11-28 13:31:17 +01:00
void Viewport : : _drop_mouse_focus ( ) {
Control * c = gui . mouse_focus ;
2023-01-08 00:55:54 +01:00
BitField < MouseButtonMask > mask = gui . mouse_focus_mask ;
2020-04-02 01:20:12 +02:00
gui . mouse_focus = nullptr ;
2020-03-20 03:32:09 +01:00
gui . forced_mouse_focus = false ;
2023-01-08 00:55:54 +01:00
gui . mouse_focus_mask . clear ( ) ;
2018-11-28 13:31:17 +01:00
for ( int i = 0 ; i < 3 ; i + + ) {
2021-08-13 23:31:57 +02:00
if ( ( int ) mask & ( 1 < < i ) ) {
2018-11-28 13:31:17 +01:00
Ref < InputEventMouseButton > mb ;
2021-06-18 00:03:09 +02:00
mb . instantiate ( ) ;
2018-11-28 13:31:17 +01:00
mb - > set_position ( c - > get_local_mouse_position ( ) ) ;
2018-11-28 17:09:56 +01:00
mb - > set_global_position ( c - > get_local_mouse_position ( ) ) ;
2021-03-25 21:56:12 +01:00
mb - > set_button_index ( MouseButton ( i + 1 ) ) ;
2018-11-28 13:31:17 +01:00
mb - > set_pressed ( false ) ;
2023-02-04 23:16:54 +01:00
mb - > set_device ( InputEvent : : DEVICE_ID_INTERNAL ) ;
2021-08-22 17:37:22 +02:00
c - > _call_gui_input ( mb ) ;
2018-11-28 13:31:17 +01:00
}
}
}
2021-02-06 21:14:35 +01:00
void Viewport : : _drop_physics_mouseover ( bool p_paused_only ) {
2021-03-26 18:39:05 +01:00
_cleanup_mouseover_colliders ( true , p_paused_only ) ;
2021-07-04 03:43:23 +02:00
# ifndef _3D_DISABLED
2021-03-26 18:39:05 +01:00
if ( physics_object_over . is_valid ( ) ) {
CollisionObject3D * co = Object : : cast_to < CollisionObject3D > ( ObjectDB : : get_instance ( physics_object_over ) ) ;
if ( co ) {
2021-10-20 18:02:05 +02:00
if ( ! co - > is_inside_tree ( ) ) {
physics_object_over = ObjectID ( ) ;
physics_object_capture = ObjectID ( ) ;
} else if ( ! ( p_paused_only & & co - > can_process ( ) ) ) {
2021-03-26 18:39:05 +01:00
co - > _mouse_exit ( ) ;
physics_object_over = ObjectID ( ) ;
physics_object_capture = ObjectID ( ) ;
}
}
}
2021-07-04 03:43:23 +02:00
# endif // _3D_DISABLED
2021-03-26 18:39:05 +01:00
}
2016-01-17 02:41:10 +01:00
void Viewport : : _gui_grab_click_focus ( Control * p_control ) {
2018-03-27 23:41:27 +02:00
gui . mouse_click_grabber = p_control ;
2023-12-18 15:46:56 +01:00
callable_mp ( this , & Viewport : : _post_gui_grab_click_focus ) . call_deferred ( ) ;
2018-03-27 23:41:27 +02:00
}
void Viewport : : _post_gui_grab_click_focus ( ) {
Control * focus_grabber = gui . mouse_click_grabber ;
if ( ! focus_grabber ) {
2021-09-10 16:58:33 +02:00
// Redundant grab requests were made.
2018-03-27 23:41:27 +02:00
return ;
}
2020-04-02 01:20:12 +02:00
gui . mouse_click_grabber = nullptr ;
2018-03-27 23:41:27 +02:00
2016-01-17 02:41:10 +01:00
if ( gui . mouse_focus ) {
2020-05-14 16:41:43 +02:00
if ( gui . mouse_focus = = focus_grabber ) {
2016-01-17 02:41:10 +01:00
return ;
2020-05-14 16:41:43 +02:00
}
2016-01-17 02:41:10 +01:00
2023-01-08 00:55:54 +01:00
BitField < MouseButtonMask > mask = gui . mouse_focus_mask ;
2016-02-03 13:31:18 +01:00
Point2 click = gui . mouse_focus - > get_global_transform_with_canvas ( ) . affine_inverse ( ) . xform ( gui . last_mouse_pos ) ;
2018-11-28 13:31:17 +01:00
for ( int i = 0 ; i < 3 ; i + + ) {
2021-08-13 23:31:57 +02:00
if ( ( int ) mask & ( 1 < < i ) ) {
2018-11-28 13:31:17 +01:00
Ref < InputEventMouseButton > mb ;
2021-06-18 00:03:09 +02:00
mb . instantiate ( ) ;
2018-11-28 13:31:17 +01:00
2021-09-10 16:58:33 +02:00
// Send unclick.
2018-11-28 13:31:17 +01:00
mb - > set_position ( click ) ;
2021-03-25 21:56:12 +01:00
mb - > set_button_index ( MouseButton ( i + 1 ) ) ;
2018-11-28 13:31:17 +01:00
mb - > set_pressed ( false ) ;
2023-02-04 23:16:54 +01:00
mb - > set_device ( InputEvent : : DEVICE_ID_INTERNAL ) ;
2021-08-22 17:37:22 +02:00
gui . mouse_focus - > _call_gui_input ( mb ) ;
2018-11-28 13:31:17 +01:00
}
}
2016-01-17 02:41:10 +01:00
2018-03-27 23:41:27 +02:00
gui . mouse_focus = focus_grabber ;
2016-02-03 13:31:18 +01:00
click = gui . mouse_focus - > get_global_transform_with_canvas ( ) . affine_inverse ( ) . xform ( gui . last_mouse_pos ) ;
2018-11-28 13:31:17 +01:00
for ( int i = 0 ; i < 3 ; i + + ) {
2021-08-13 23:31:57 +02:00
if ( ( int ) mask & ( 1 < < i ) ) {
2018-11-28 13:31:17 +01:00
Ref < InputEventMouseButton > mb ;
2021-06-18 00:03:09 +02:00
mb . instantiate ( ) ;
2018-11-28 13:31:17 +01:00
2021-09-10 16:58:33 +02:00
// Send click.
2018-11-28 13:31:17 +01:00
mb - > set_position ( click ) ;
2021-03-25 21:56:12 +01:00
mb - > set_button_index ( MouseButton ( i + 1 ) ) ;
2018-11-28 13:31:17 +01:00
mb - > set_pressed ( true ) ;
2023-02-04 23:16:54 +01:00
mb - > set_device ( InputEvent : : DEVICE_ID_INTERNAL ) ;
2023-12-18 15:46:56 +01:00
callable_mp ( gui . mouse_focus , & Control : : _call_gui_input ) . call_deferred ( mb ) ;
2018-11-28 13:31:17 +01:00
}
}
2016-01-17 02:41:10 +01:00
}
}
///////////////////////////////
2021-08-22 17:37:22 +02:00
void Viewport : : push_text_input ( const String & p_text ) {
2023-05-12 13:53:15 +02:00
ERR_MAIN_THREAD_GUARD ;
2020-03-14 17:06:39 +01:00
if ( gui . subwindow_focused ) {
2021-08-22 17:37:22 +02:00
gui . subwindow_focused - > push_text_input ( p_text ) ;
2020-03-14 17:06:39 +01:00
return ;
}
2020-03-04 17:36:09 +01:00
if ( gui . key_focus ) {
gui . key_focus - > call ( " set_text " , p_text ) ;
}
}
2020-05-14 14:29:06 +02:00
2020-03-14 17:06:39 +01:00
Viewport : : SubWindowResize Viewport : : _sub_window_get_resize_margin ( Window * p_subwindow , const Point2 & p_point ) {
2022-01-17 21:17:53 +01:00
if ( p_subwindow - > get_flag ( Window : : FLAG_BORDERLESS ) | | p_subwindow - > get_flag ( Window : : FLAG_RESIZE_DISABLED ) ) {
2020-03-14 17:06:39 +01:00
return SUB_WINDOW_RESIZE_DISABLED ;
}
Rect2i r = Rect2i ( p_subwindow - > get_position ( ) , p_subwindow - > get_size ( ) ) ;
2023-09-12 15:01:42 +02:00
int title_height = p_subwindow - > theme_cache . title_height ;
2020-03-14 17:06:39 +01:00
r . position . y - = title_height ;
r . size . y + = title_height ;
if ( r . has_point ( p_point ) ) {
2021-09-10 16:58:33 +02:00
return SUB_WINDOW_RESIZE_DISABLED ; // It's inside, so no resize.
2020-03-14 17:06:39 +01:00
}
int dist_x = p_point . x < r . position . x ? ( p_point . x - r . position . x ) : ( p_point . x > ( r . position . x + r . size . x ) ? ( p_point . x - ( r . position . x + r . size . x ) ) : 0 ) ;
int dist_y = p_point . y < r . position . y ? ( p_point . y - r . position . y ) : ( p_point . y > ( r . position . y + r . size . y ) ? ( p_point . y - ( r . position . y + r . size . y ) ) : 0 ) ;
2023-09-12 15:01:42 +02:00
int limit = p_subwindow - > theme_cache . resize_margin ;
2020-03-14 17:06:39 +01:00
if ( ABS ( dist_x ) > limit ) {
return SUB_WINDOW_RESIZE_DISABLED ;
}
if ( ABS ( dist_y ) > limit ) {
return SUB_WINDOW_RESIZE_DISABLED ;
}
if ( dist_x < 0 & & dist_y < 0 ) {
return SUB_WINDOW_RESIZE_TOP_LEFT ;
}
if ( dist_x = = 0 & & dist_y < 0 ) {
return SUB_WINDOW_RESIZE_TOP ;
}
if ( dist_x > 0 & & dist_y < 0 ) {
return SUB_WINDOW_RESIZE_TOP_RIGHT ;
}
if ( dist_x < 0 & & dist_y = = 0 ) {
return SUB_WINDOW_RESIZE_LEFT ;
}
if ( dist_x > 0 & & dist_y = = 0 ) {
return SUB_WINDOW_RESIZE_RIGHT ;
}
if ( dist_x < 0 & & dist_y > 0 ) {
return SUB_WINDOW_RESIZE_BOTTOM_LEFT ;
}
if ( dist_x = = 0 & & dist_y > 0 ) {
return SUB_WINDOW_RESIZE_BOTTOM ;
}
if ( dist_x > 0 & & dist_y > 0 ) {
return SUB_WINDOW_RESIZE_BOTTOM_RIGHT ;
}
return SUB_WINDOW_RESIZE_DISABLED ;
}
2020-05-14 14:29:06 +02:00
2020-03-14 17:06:39 +01:00
bool Viewport : : _sub_windows_forward_input ( const Ref < InputEvent > & p_event ) {
if ( gui . subwindow_drag ! = SUB_WINDOW_DRAG_DISABLED ) {
2023-09-28 11:40:18 +02:00
ERR_FAIL_NULL_V ( gui . currently_dragged_subwindow , false ) ;
2020-03-14 17:06:39 +01:00
Ref < InputEventMouseButton > mb = p_event ;
2021-08-13 23:31:57 +02:00
if ( mb . is_valid ( ) & & ! mb - > is_pressed ( ) & & mb - > get_button_index ( ) = = MouseButton : : LEFT ) {
2020-03-14 17:06:39 +01:00
if ( gui . subwindow_drag = = SUB_WINDOW_DRAG_CLOSE ) {
if ( gui . subwindow_drag_close_rect . has_point ( mb - > get_position ( ) ) ) {
2021-09-10 16:58:33 +02:00
// Close window.
2023-06-04 19:09:54 +02:00
gui . currently_dragged_subwindow - > _event_callback ( DisplayServer : : WINDOW_EVENT_CLOSE_REQUEST ) ;
2020-03-14 17:06:39 +01:00
}
}
gui . subwindow_drag = SUB_WINDOW_DRAG_DISABLED ;
2023-06-04 19:09:54 +02:00
if ( gui . currently_dragged_subwindow ! = nullptr ) { // May have been erased.
_sub_window_update ( gui . currently_dragged_subwindow ) ;
gui . currently_dragged_subwindow = nullptr ;
2020-03-14 17:06:39 +01:00
}
}
Ref < InputEventMouseMotion > mm = p_event ;
if ( mm . is_valid ( ) ) {
if ( gui . subwindow_drag = = SUB_WINDOW_DRAG_MOVE ) {
Vector2 diff = mm - > get_position ( ) - gui . subwindow_drag_from ;
2023-06-04 19:09:54 +02:00
Rect2i new_rect ( gui . subwindow_drag_pos + diff , gui . currently_dragged_subwindow - > get_size ( ) ) ;
2020-07-01 17:39:42 +02:00
2023-06-04 19:09:54 +02:00
if ( gui . currently_dragged_subwindow - > is_clamped_to_embedder ( ) ) {
new_rect = gui . currently_dragged_subwindow - > fit_rect_in_parent ( new_rect , get_visible_rect ( ) ) ;
2020-07-01 17:39:42 +02:00
}
2023-06-04 19:09:54 +02:00
gui . currently_dragged_subwindow - > _rect_changed_callback ( new_rect ) ;
2023-05-07 16:14:57 +02:00
if ( DisplayServer : : get_singleton ( ) - > has_feature ( DisplayServer : : FEATURE_CURSOR_SHAPE ) ) {
DisplayServer : : get_singleton ( ) - > cursor_set_shape ( DisplayServer : : CURSOR_MOVE ) ;
}
2020-03-14 17:06:39 +01:00
}
if ( gui . subwindow_drag = = SUB_WINDOW_DRAG_CLOSE ) {
gui . subwindow_drag_close_inside = gui . subwindow_drag_close_rect . has_point ( mm - > get_position ( ) ) ;
}
if ( gui . subwindow_drag = = SUB_WINDOW_DRAG_RESIZE ) {
Vector2i diff = mm - > get_position ( ) - gui . subwindow_drag_from ;
2023-06-04 19:09:54 +02:00
Size2i min_size = gui . currently_dragged_subwindow - > get_min_size ( ) ;
Size2i min_size_clamped = gui . currently_dragged_subwindow - > get_clamped_minimum_size ( ) ;
2022-08-04 22:11:32 +02:00
2024-03-03 14:37:52 +01:00
min_size_clamped = min_size_clamped . maxi ( 1 ) ;
2020-03-14 17:06:39 +01:00
Rect2i r = gui . subwindow_resize_from_rect ;
2022-06-18 12:52:30 +02:00
Size2i limit = r . size - min_size_clamped ;
2020-03-14 17:06:39 +01:00
switch ( gui . subwindow_resize_mode ) {
case SUB_WINDOW_RESIZE_TOP_LEFT : {
diff . x = MIN ( diff . x , limit . x ) ;
diff . y = MIN ( diff . y , limit . y ) ;
r . position + = diff ;
r . size - = diff ;
} break ;
case SUB_WINDOW_RESIZE_TOP : {
diff . x = 0 ;
diff . y = MIN ( diff . y , limit . y ) ;
r . position + = diff ;
r . size - = diff ;
} break ;
case SUB_WINDOW_RESIZE_TOP_RIGHT : {
diff . x = MAX ( diff . x , - limit . x ) ;
diff . y = MIN ( diff . y , limit . y ) ;
r . position . y + = diff . y ;
r . size . y - = diff . y ;
r . size . x + = diff . x ;
} break ;
case SUB_WINDOW_RESIZE_LEFT : {
diff . x = MIN ( diff . x , limit . x ) ;
diff . y = 0 ;
r . position + = diff ;
r . size - = diff ;
} break ;
case SUB_WINDOW_RESIZE_RIGHT : {
diff . x = MAX ( diff . x , - limit . x ) ;
r . size . x + = diff . x ;
} break ;
case SUB_WINDOW_RESIZE_BOTTOM_LEFT : {
diff . x = MIN ( diff . x , limit . x ) ;
diff . y = MAX ( diff . y , - limit . y ) ;
r . position . x + = diff . x ;
r . size . x - = diff . x ;
r . size . y + = diff . y ;
} break ;
case SUB_WINDOW_RESIZE_BOTTOM : {
diff . y = MAX ( diff . y , - limit . y ) ;
r . size . y + = diff . y ;
} break ;
case SUB_WINDOW_RESIZE_BOTTOM_RIGHT : {
diff . x = MAX ( diff . x , - limit . x ) ;
diff . y = MAX ( diff . y , - limit . y ) ;
r . size + = diff ;
} break ;
default : {
}
}
2023-06-04 19:09:54 +02:00
Size2i max_size = gui . currently_dragged_subwindow - > get_max_size ( ) ;
2022-08-04 22:11:32 +02:00
if ( ( max_size . x > 0 | | max_size . y > 0 ) & & ( max_size . x > = min_size . x & & max_size . y > = min_size . y ) ) {
2024-03-03 14:37:52 +01:00
max_size = max_size . maxi ( 1 ) ;
2022-08-04 22:11:32 +02:00
if ( r . size . x > max_size . x ) {
r . size . x = max_size . x ;
}
if ( r . size . y > max_size . y ) {
r . size . y = max_size . y ;
}
}
2023-06-04 19:09:54 +02:00
gui . currently_dragged_subwindow - > _rect_changed_callback ( r ) ;
2020-03-14 17:06:39 +01:00
}
2023-06-04 19:09:54 +02:00
if ( gui . currently_dragged_subwindow ) { // May have been erased.
_sub_window_update ( gui . currently_dragged_subwindow ) ;
2020-03-14 17:06:39 +01:00
}
}
2021-09-10 16:58:33 +02:00
return true ; // Handled.
2020-03-14 17:06:39 +01:00
}
Ref < InputEventMouseButton > mb = p_event ;
2021-09-10 16:58:33 +02:00
// If the event is a mouse button, we need to check whether another window was clicked.
2020-03-14 17:06:39 +01:00
2021-08-13 23:31:57 +02:00
if ( mb . is_valid ( ) & & mb - > is_pressed ( ) & & mb - > get_button_index ( ) = = MouseButton : : LEFT ) {
2023-06-04 19:09:54 +02:00
Window * click_on_window = nullptr ;
2020-03-14 17:06:39 +01:00
for ( int i = gui . sub_windows . size ( ) - 1 ; i > = 0 ; i - - ) {
2021-11-30 00:36:47 +01:00
SubWindow sw = gui . sub_windows . write [ i ] ;
2020-03-14 17:06:39 +01:00
2021-09-10 16:58:33 +02:00
// Clicked inside window?
2020-03-14 17:06:39 +01:00
Rect2i r = Rect2i ( sw . window - > get_position ( ) , sw . window - > get_size ( ) ) ;
if ( ! sw . window - > get_flag ( Window : : FLAG_BORDERLESS ) ) {
2021-09-10 16:58:33 +02:00
// Check top bar.
2023-09-12 15:01:42 +02:00
int title_height = sw . window - > theme_cache . title_height ;
2020-03-14 17:06:39 +01:00
Rect2i title_bar = r ;
title_bar . position . y - = title_height ;
title_bar . size . y = title_height ;
2023-05-28 21:46:16 +02:00
if ( title_bar . size . y > 0 & & title_bar . has_point ( mb - > get_position ( ) ) ) {
2023-06-04 19:09:54 +02:00
click_on_window = sw . window ;
2020-03-14 17:06:39 +01:00
2023-09-12 15:01:42 +02:00
int close_h_ofs = sw . window - > theme_cache . close_h_offset ;
int close_v_ofs = sw . window - > theme_cache . close_v_offset ;
Ref < Texture2D > close_icon = sw . window - > theme_cache . close ;
2020-03-14 17:06:39 +01:00
Rect2 close_rect ;
2022-08-04 22:11:32 +02:00
close_rect . position = Vector2 ( r . position . x + r . size . x - close_h_ofs , r . position . y - close_v_ofs ) ;
2020-03-14 17:06:39 +01:00
close_rect . size = close_icon - > get_size ( ) ;
if ( gui . subwindow_focused ! = sw . window ) {
2021-09-10 16:58:33 +02:00
// Refocus.
2020-03-14 17:06:39 +01:00
_sub_window_grab_focus ( sw . window ) ;
}
if ( close_rect . has_point ( mb - > get_position ( ) ) ) {
gui . subwindow_drag = SUB_WINDOW_DRAG_CLOSE ;
2021-09-10 16:58:33 +02:00
gui . subwindow_drag_close_inside = true ; // Starts inside.
2020-03-14 17:06:39 +01:00
gui . subwindow_drag_close_rect = close_rect ;
} else {
gui . subwindow_drag = SUB_WINDOW_DRAG_MOVE ;
}
gui . subwindow_drag_from = mb - > get_position ( ) ;
gui . subwindow_drag_pos = sw . window - > get_position ( ) ;
_sub_window_update ( sw . window ) ;
} else {
2020-03-25 00:15:35 +01:00
gui . subwindow_resize_mode = _sub_window_get_resize_margin ( sw . window , mb - > get_position ( ) ) ;
2020-03-14 17:06:39 +01:00
if ( gui . subwindow_resize_mode ! = SUB_WINDOW_RESIZE_DISABLED ) {
2022-11-04 22:24:00 +01:00
if ( gui . subwindow_focused ! = sw . window ) {
// Refocus.
_sub_window_grab_focus ( sw . window ) ;
}
2020-03-14 17:06:39 +01:00
gui . subwindow_resize_from_rect = r ;
gui . subwindow_drag_from = mb - > get_position ( ) ;
gui . subwindow_drag = SUB_WINDOW_DRAG_RESIZE ;
2023-06-04 19:09:54 +02:00
click_on_window = sw . window ;
2020-03-14 17:06:39 +01:00
}
}
}
if ( ! click_on_window & & r . has_point ( mb - > get_position ( ) ) ) {
2021-09-10 16:58:33 +02:00
// Clicked, see if it needs to fetch focus.
2020-03-14 17:06:39 +01:00
if ( gui . subwindow_focused ! = sw . window ) {
2021-09-10 16:58:33 +02:00
// Refocus.
2020-03-14 17:06:39 +01:00
_sub_window_grab_focus ( sw . window ) ;
}
2023-06-04 19:09:54 +02:00
click_on_window = sw . window ;
2020-03-14 17:06:39 +01:00
}
if ( click_on_window ) {
break ;
}
}
2023-06-04 19:09:54 +02:00
gui . currently_dragged_subwindow = click_on_window ;
2020-03-14 17:06:39 +01:00
if ( ! click_on_window & & gui . subwindow_focused ) {
2021-09-10 16:58:33 +02:00
// No window found and clicked, remove focus.
2020-03-14 17:06:39 +01:00
_sub_window_grab_focus ( nullptr ) ;
}
}
if ( gui . subwindow_focused ) {
Ref < InputEventMouseMotion > mm = p_event ;
if ( mm . is_valid ( ) ) {
SubWindowResize resize = _sub_window_get_resize_margin ( gui . subwindow_focused , mm - > get_position ( ) ) ;
if ( resize ! = SUB_WINDOW_RESIZE_DISABLED ) {
DisplayServer : : CursorShape shapes [ SUB_WINDOW_RESIZE_MAX ] = {
DisplayServer : : CURSOR_ARROW ,
DisplayServer : : CURSOR_FDIAGSIZE ,
DisplayServer : : CURSOR_VSIZE ,
DisplayServer : : CURSOR_BDIAGSIZE ,
DisplayServer : : CURSOR_HSIZE ,
DisplayServer : : CURSOR_HSIZE ,
DisplayServer : : CURSOR_BDIAGSIZE ,
DisplayServer : : CURSOR_VSIZE ,
DisplayServer : : CURSOR_FDIAGSIZE
} ;
2022-08-23 11:14:07 +02:00
if ( DisplayServer : : get_singleton ( ) - > has_feature ( DisplayServer : : FEATURE_CURSOR_SHAPE ) ) {
DisplayServer : : get_singleton ( ) - > cursor_set_shape ( shapes [ resize ] ) ;
}
2020-03-14 17:06:39 +01:00
2021-09-10 16:58:33 +02:00
return true ; // Reserved for showing the resize cursor.
2020-03-14 17:06:39 +01:00
}
}
}
if ( gui . subwindow_drag ! = SUB_WINDOW_DRAG_DISABLED ) {
2021-09-10 16:58:33 +02:00
return true ; // Dragging, don't pass the event.
2020-03-14 17:06:39 +01:00
}
if ( ! gui . subwindow_focused ) {
return false ;
}
Transform2D window_ofs ;
window_ofs . set_origin ( - gui . subwindow_focused - > get_position ( ) ) ;
Ref < InputEvent > ev = p_event - > xformed_by ( window_ofs ) ;
gui . subwindow_focused - > _window_input ( ev ) ;
return true ;
}
2023-01-06 21:48:20 +01:00
void Viewport : : _update_mouse_over ( ) {
// Update gui.mouse_over and gui.subwindow_over in all Viewports.
2023-08-06 13:07:28 +02:00
// Send necessary mouse_enter/mouse_exit signals and the MOUSE_ENTER/MOUSE_EXIT notifications for every Viewport in the SceneTree.
2023-01-06 21:48:20 +01:00
if ( is_attached_in_viewport ( ) ) {
// Execute this function only, when it is processed by a native Window or a SubViewport, that has no SubViewportContainer as parent.
return ;
}
if ( get_tree ( ) - > get_root ( ) - > is_embedding_subwindows ( ) | | is_sub_viewport ( ) ) {
// Use embedder logic for calculating mouse position.
_update_mouse_over ( gui . last_mouse_pos ) ;
} else {
// Native Window: Use DisplayServer logic for calculating mouse position.
Window * receiving_window = get_tree ( ) - > get_root ( ) - > gui . windowmanager_window_over ;
if ( ! receiving_window ) {
return ;
}
Vector2 pos = DisplayServer : : get_singleton ( ) - > mouse_get_position ( ) - receiving_window - > get_position ( ) ;
pos = receiving_window - > get_final_transform ( ) . affine_inverse ( ) . xform ( pos ) ;
receiving_window - > _update_mouse_over ( pos ) ;
}
}
void Viewport : : _update_mouse_over ( Vector2 p_pos ) {
// Look for embedded windows at mouse position.
if ( is_embedding_subwindows ( ) ) {
for ( int i = gui . sub_windows . size ( ) - 1 ; i > = 0 ; i - - ) {
Window * sw = gui . sub_windows [ i ] . window ;
Rect2 swrect = Rect2 ( sw - > get_position ( ) , sw - > get_size ( ) ) ;
Rect2 swrect_border = swrect ;
if ( ! sw - > get_flag ( Window : : FLAG_BORDERLESS ) ) {
2023-09-12 15:01:42 +02:00
int title_height = sw - > theme_cache . title_height ;
int margin = sw - > theme_cache . resize_margin ;
2023-01-06 21:48:20 +01:00
swrect_border . position . y - = title_height + margin ;
swrect_border . size . y + = title_height + margin * 2 ;
swrect_border . position . x - = margin ;
swrect_border . size . x + = margin * 2 ;
}
if ( swrect_border . has_point ( p_pos ) ) {
if ( gui . mouse_over ) {
_drop_mouse_over ( ) ;
} else if ( ! gui . subwindow_over ) {
_drop_physics_mouseover ( ) ;
}
if ( swrect . has_point ( p_pos ) ) {
if ( sw ! = gui . subwindow_over ) {
if ( gui . subwindow_over ) {
gui . subwindow_over - > _mouse_leave_viewport ( ) ;
}
gui . subwindow_over = sw ;
}
if ( ! sw - > is_input_disabled ( ) ) {
sw - > _update_mouse_over ( sw - > get_final_transform ( ) . affine_inverse ( ) . xform ( p_pos - sw - > get_position ( ) ) ) ;
}
} else {
if ( gui . subwindow_over ) {
gui . subwindow_over - > _mouse_leave_viewport ( ) ;
gui . subwindow_over = nullptr ;
}
}
return ;
}
}
if ( gui . subwindow_over ) {
// Take care of moving mouse out of any embedded Window.
gui . subwindow_over - > _mouse_leave_viewport ( ) ;
gui . subwindow_over = nullptr ;
}
}
// Look for Controls at mouse position.
Control * over = gui_find_control ( p_pos ) ;
bool notify_embedded_viewports = false ;
2023-10-31 18:55:34 +01:00
if ( over ! = gui . mouse_over | | ( ! over & & ! gui . mouse_over_hierarchy . is_empty ( ) ) ) {
// Find the common ancestor of `gui.mouse_over` and `over`.
Control * common_ancestor = nullptr ;
LocalVector < Control * > over_ancestors ;
if ( over ) {
// Get all ancestors that the mouse is currently over and need an enter signal.
CanvasItem * ancestor = over ;
while ( ancestor ) {
Control * ancestor_control = Object : : cast_to < Control > ( ancestor ) ;
if ( ancestor_control ) {
if ( ancestor_control - > get_mouse_filter ( ) ! = Control : : MOUSE_FILTER_IGNORE ) {
int found = gui . mouse_over_hierarchy . find ( ancestor_control ) ;
if ( found > = 0 ) {
common_ancestor = gui . mouse_over_hierarchy [ found ] ;
break ;
}
over_ancestors . push_back ( ancestor_control ) ;
}
if ( ancestor_control - > get_mouse_filter ( ) = = Control : : MOUSE_FILTER_STOP ) {
// MOUSE_FILTER_STOP breaks the propagation chain.
break ;
}
}
if ( ancestor - > is_set_as_top_level ( ) ) {
// Top level breaks the propagation chain.
break ;
}
ancestor = ancestor - > get_parent_item ( ) ;
}
}
if ( gui . mouse_over | | ! gui . mouse_over_hierarchy . is_empty ( ) ) {
// Send Mouse Exit Self and Mouse Exit notifications.
_drop_mouse_over ( common_ancestor ) ;
2023-01-06 21:48:20 +01:00
} else {
_drop_physics_mouseover ( ) ;
}
if ( over ) {
2023-10-31 18:55:34 +01:00
gui . mouse_over = over ;
gui . mouse_over_hierarchy . reserve ( gui . mouse_over_hierarchy . size ( ) + over_ancestors . size ( ) ) ;
2023-11-24 04:38:34 +01:00
gui . sending_mouse_enter_exit_notifications = true ;
2023-10-31 18:55:34 +01:00
// Send Mouse Enter notifications to parents first.
for ( int i = over_ancestors . size ( ) - 1 ; i > = 0 ; i - - ) {
gui . mouse_over_hierarchy . push_back ( over_ancestors [ i ] ) ;
2023-11-24 04:38:34 +01:00
over_ancestors [ i ] - > notification ( Control : : NOTIFICATION_MOUSE_ENTER ) ;
2023-10-31 18:55:34 +01:00
}
// Send Mouse Enter Self notification.
2023-11-23 23:25:00 +01:00
if ( gui . mouse_over ) {
gui . mouse_over - > notification ( Control : : NOTIFICATION_MOUSE_ENTER_SELF ) ;
}
2023-10-31 18:55:34 +01:00
2023-11-24 04:38:34 +01:00
gui . sending_mouse_enter_exit_notifications = false ;
2023-01-06 21:48:20 +01:00
notify_embedded_viewports = true ;
}
}
if ( over ) {
SubViewportContainer * c = Object : : cast_to < SubViewportContainer > ( over ) ;
if ( ! c ) {
return ;
}
Vector2 pos = c - > get_global_transform_with_canvas ( ) . affine_inverse ( ) . xform ( p_pos ) ;
if ( c - > is_stretch_enabled ( ) ) {
pos / = c - > get_stretch_shrink ( ) ;
}
for ( int i = 0 ; i < c - > get_child_count ( ) ; i + + ) {
SubViewport * v = Object : : cast_to < SubViewport > ( c - > get_child ( i ) ) ;
if ( ! v | | v - > is_input_disabled ( ) ) {
continue ;
}
if ( notify_embedded_viewports ) {
v - > notification ( NOTIFICATION_VP_MOUSE_ENTER ) ;
}
v - > _update_mouse_over ( v - > get_final_transform ( ) . affine_inverse ( ) . xform ( pos ) ) ;
}
}
}
void Viewport : : _mouse_leave_viewport ( ) {
if ( ! is_inside_tree ( ) | | is_input_disabled ( ) ) {
return ;
}
if ( gui . subwindow_over ) {
gui . subwindow_over - > _mouse_leave_viewport ( ) ;
gui . subwindow_over = nullptr ;
} else if ( gui . mouse_over ) {
_drop_mouse_over ( ) ;
}
notification ( NOTIFICATION_VP_MOUSE_EXIT ) ;
}
2023-10-31 18:55:34 +01:00
void Viewport : : _drop_mouse_over ( Control * p_until_control ) {
2023-11-24 04:38:34 +01:00
if ( gui . sending_mouse_enter_exit_notifications ) {
// If notifications are already being sent, defer call.
callable_mp ( this , & Viewport : : _drop_mouse_over ) . call_deferred ( p_until_control ) ;
return ;
}
2023-01-06 21:48:20 +01:00
_gui_cancel_tooltip ( ) ;
SubViewportContainer * c = Object : : cast_to < SubViewportContainer > ( gui . mouse_over ) ;
if ( c ) {
for ( int i = 0 ; i < c - > get_child_count ( ) ; i + + ) {
SubViewport * v = Object : : cast_to < SubViewport > ( c - > get_child ( i ) ) ;
if ( ! v ) {
continue ;
}
v - > _mouse_leave_viewport ( ) ;
}
}
2023-11-24 04:38:34 +01:00
gui . sending_mouse_enter_exit_notifications = true ;
2023-10-31 18:55:34 +01:00
if ( gui . mouse_over & & gui . mouse_over - > is_inside_tree ( ) ) {
gui . mouse_over - > notification ( Control : : NOTIFICATION_MOUSE_EXIT_SELF ) ;
2023-01-06 21:48:20 +01:00
}
gui . mouse_over = nullptr ;
2023-10-31 18:55:34 +01:00
// Send Mouse Exit notifications to children first. Don't send to p_until_control or above.
int notification_until = p_until_control ? gui . mouse_over_hierarchy . find ( p_until_control ) + 1 : 0 ;
for ( int i = gui . mouse_over_hierarchy . size ( ) - 1 ; i > = notification_until ; i - - ) {
if ( gui . mouse_over_hierarchy [ i ] - > is_inside_tree ( ) ) {
gui . mouse_over_hierarchy [ i ] - > notification ( Control : : NOTIFICATION_MOUSE_EXIT ) ;
}
}
gui . mouse_over_hierarchy . resize ( notification_until ) ;
2023-11-24 04:38:34 +01:00
gui . sending_mouse_enter_exit_notifications = false ;
2023-01-06 21:48:20 +01:00
}
2021-08-22 17:37:22 +02:00
void Viewport : : push_input ( const Ref < InputEvent > & p_event , bool p_local_coords ) {
2023-05-12 13:53:15 +02:00
ERR_MAIN_THREAD_GUARD ;
2014-11-06 01:20:42 +01:00
ERR_FAIL_COND ( ! is_inside_tree ( ) ) ;
2023-05-14 16:04:12 +02:00
ERR_FAIL_COND ( p_event . is_null ( ) ) ;
2016-01-18 23:49:11 +01:00
2020-05-14 16:41:43 +02:00
if ( disable_input ) {
2020-03-04 17:36:09 +01:00
return ;
2020-05-14 16:41:43 +02:00
}
2020-03-04 17:36:09 +01:00
2021-06-19 00:02:50 +02:00
if ( Engine : : get_singleton ( ) - > is_editor_hint ( ) & & get_tree ( ) - > get_edited_scene_root ( ) & & get_tree ( ) - > get_edited_scene_root ( ) - > is_ancestor_of ( this ) ) {
2020-03-04 17:36:09 +01:00
return ;
}
2018-11-15 17:54:26 +01:00
local_input_handled = false ;
2023-06-01 15:26:47 +02:00
if ( ! handle_input_locally ) {
Viewport * vp = this ;
while ( true ) {
if ( Object : : cast_to < Window > ( vp ) | | ! vp - > get_parent ( ) ) {
break ;
}
vp = vp - > get_parent ( ) - > get_viewport ( ) ;
}
vp - > local_input_handled = false ;
}
2018-11-15 17:54:26 +01:00
2020-03-04 17:36:09 +01:00
Ref < InputEvent > ev ;
if ( ! p_local_coords ) {
ev = _make_input_local ( p_event ) ;
} else {
ev = p_event ;
}
2022-10-14 10:29:28 +02:00
Ref < InputEventMouse > me = ev ;
if ( me . is_valid ( ) ) {
gui . last_mouse_pos = me - > get_position ( ) ;
2023-01-06 21:48:20 +01:00
_update_mouse_over ( ) ;
2022-10-14 10:29:28 +02:00
}
2022-03-13 18:45:09 +01:00
if ( is_embedding_subwindows ( ) & & _sub_windows_forward_input ( ev ) ) {
2020-03-14 17:06:39 +01:00
set_input_as_handled ( ) ;
return ;
}
2020-07-01 14:27:43 +02:00
if ( ! _can_consume_input_events ( ) ) {
return ;
}
2018-11-15 17:54:26 +01:00
if ( ! is_input_handled ( ) ) {
2023-06-02 09:47:13 +02:00
ERR_FAIL_COND ( ! is_inside_tree ( ) ) ;
2021-08-22 17:37:22 +02:00
get_tree ( ) - > _call_input_pause ( input_group , SceneTree : : CALL_INPUT_TYPE_INPUT , ev , this ) ; //not a bug, must happen before GUI, order is _input -> gui input -> _unhandled input
2017-10-16 14:13:33 +02:00
}
2018-11-15 17:54:26 +01:00
if ( ! is_input_handled ( ) ) {
2023-06-02 09:47:13 +02:00
ERR_FAIL_COND ( ! is_inside_tree ( ) ) ;
2020-03-04 17:36:09 +01:00
_gui_input_event ( ev ) ;
2022-03-13 23:54:13 +01:00
} else {
// Cleanup internal GUI state after accepting event during _input().
_gui_cleanup_internal_state ( ev ) ;
2017-10-16 14:13:33 +02:00
}
2020-07-01 15:59:42 +02:00
2022-03-31 11:53:47 +02:00
if ( ! is_input_handled ( ) ) {
2023-05-10 21:51:50 +02:00
_push_unhandled_input_internal ( ev ) ;
2022-03-31 11:53:47 +02:00
}
2020-07-01 15:59:42 +02:00
event_count + + ;
2014-04-10 05:18:27 +02:00
}
2023-05-10 21:51:50 +02:00
# ifndef DISABLE_DEPRECATED
2021-08-22 17:37:22 +02:00
void Viewport : : push_unhandled_input ( const Ref < InputEvent > & p_event , bool p_local_coords ) {
2023-05-12 13:53:15 +02:00
ERR_MAIN_THREAD_GUARD ;
2023-06-06 10:27:29 +02:00
WARN_DEPRECATED_MSG ( R " *(The " push_unhandled_input ( ) " method is deprecated, use " push_input ( ) " instead.)* " ) ;
2014-11-06 01:20:42 +01:00
ERR_FAIL_COND ( ! is_inside_tree ( ) ) ;
2023-06-06 10:27:29 +02:00
ERR_FAIL_COND ( p_event . is_null ( ) ) ;
2023-05-10 21:51:50 +02:00
2021-05-29 15:28:16 +02:00
local_input_handled = false ;
2014-04-10 05:18:27 +02:00
2020-07-01 14:27:43 +02:00
if ( disable_input | | ! _can_consume_input_events ( ) ) {
2020-03-04 17:36:09 +01:00
return ;
2020-05-14 16:41:43 +02:00
}
2020-03-04 17:36:09 +01:00
2021-06-19 00:02:50 +02:00
if ( Engine : : get_singleton ( ) - > is_editor_hint ( ) & & get_tree ( ) - > get_edited_scene_root ( ) & & get_tree ( ) - > get_edited_scene_root ( ) - > is_ancestor_of ( this ) ) {
2020-03-04 17:36:09 +01:00
return ;
}
Ref < InputEvent > ev ;
if ( ! p_local_coords ) {
ev = _make_input_local ( p_event ) ;
} else {
ev = p_event ;
}
2023-05-10 21:51:50 +02:00
_push_unhandled_input_internal ( ev ) ;
}
# endif // DISABLE_DEPRECATED
void Viewport : : _push_unhandled_input_internal ( const Ref < InputEvent > & p_event ) {
2022-01-11 14:59:52 +01:00
// Shortcut Input.
2023-05-10 21:51:50 +02:00
if ( Object : : cast_to < InputEventKey > ( * p_event ) ! = nullptr | | Object : : cast_to < InputEventShortcut > ( * p_event ) ! = nullptr | | Object : : cast_to < InputEventJoypadButton > ( * p_event ) ! = nullptr ) {
2023-06-02 09:47:13 +02:00
ERR_FAIL_COND ( ! is_inside_tree ( ) ) ;
2023-05-10 21:51:50 +02:00
get_tree ( ) - > _call_input_pause ( shortcut_input_group , SceneTree : : CALL_INPUT_TYPE_SHORTCUT_INPUT , p_event , this ) ;
2022-01-11 14:59:52 +01:00
}
// Unhandled key Input - Used for performance reasons - This is called a lot less than _unhandled_input since it ignores MouseMotion, and to handle Unicode input with Alt / Ctrl modifiers after handling shortcuts.
2023-05-10 21:51:50 +02:00
if ( ! is_input_handled ( ) & & ( Object : : cast_to < InputEventKey > ( * p_event ) ! = nullptr ) ) {
2023-06-02 09:47:13 +02:00
ERR_FAIL_COND ( ! is_inside_tree ( ) ) ;
2023-05-10 21:51:50 +02:00
get_tree ( ) - > _call_input_pause ( unhandled_key_input_group , SceneTree : : CALL_INPUT_TYPE_UNHANDLED_KEY_INPUT , p_event , this ) ;
2014-04-10 05:18:27 +02:00
}
2014-09-15 16:33:30 +02:00
2023-07-09 19:23:19 +02:00
// Unhandled Input.
if ( ! is_input_handled ( ) ) {
ERR_FAIL_COND ( ! is_inside_tree ( ) ) ;
get_tree ( ) - > _call_input_pause ( unhandled_input_group , SceneTree : : CALL_INPUT_TYPE_UNHANDLED_INPUT , p_event , this ) ;
}
2020-03-04 17:36:09 +01:00
if ( physics_object_picking & & ! is_input_handled ( ) ) {
2020-04-28 15:19:37 +02:00
if ( Input : : get_singleton ( ) - > get_mouse_mode ( ) ! = Input : : MOUSE_MODE_CAPTURED & &
2023-06-08 21:04:38 +02:00
( Object : : cast_to < InputEventMouse > ( * p_event ) | |
2023-05-10 21:51:50 +02:00
Object : : cast_to < InputEventScreenDrag > ( * p_event ) | |
2023-06-08 21:04:38 +02:00
Object : : cast_to < InputEventScreenTouch > ( * p_event )
2018-11-15 17:54:26 +01:00
2023-06-08 21:04:38 +02:00
) ) {
2023-05-10 21:51:50 +02:00
physics_picking_events . push_back ( p_event ) ;
2023-05-29 00:29:44 +02:00
set_input_as_handled ( ) ;
2014-09-15 16:33:30 +02:00
}
}
2014-04-10 05:18:27 +02:00
}
2014-09-15 16:33:30 +02:00
void Viewport : : set_physics_object_picking ( bool p_enable ) {
2023-05-12 13:53:15 +02:00
ERR_MAIN_THREAD_GUARD ;
2014-09-15 16:33:30 +02:00
physics_object_picking = p_enable ;
2021-07-19 19:25:15 +02:00
if ( physics_object_picking ) {
add_to_group ( " _picking_viewports " ) ;
} else {
2014-09-15 16:33:30 +02:00
physics_picking_events . clear ( ) ;
2021-07-19 19:25:15 +02:00
if ( is_in_group ( " _picking_viewports " ) ) {
remove_from_group ( " _picking_viewports " ) ;
}
2018-03-01 14:44:45 +01:00
}
}
bool Viewport : : get_physics_object_picking ( ) {
2023-05-12 13:53:15 +02:00
ERR_READ_THREAD_GUARD_V ( false ) ;
2018-03-01 14:44:45 +01:00
return physics_object_picking ;
2014-09-15 16:33:30 +02:00
}
2022-11-10 22:55:57 +01:00
void Viewport : : set_physics_object_picking_sort ( bool p_enable ) {
2023-05-12 13:53:15 +02:00
ERR_MAIN_THREAD_GUARD ;
2022-11-10 22:55:57 +01:00
physics_object_picking_sort = p_enable ;
}
bool Viewport : : get_physics_object_picking_sort ( ) {
2023-05-12 13:53:15 +02:00
ERR_READ_THREAD_GUARD_V ( false ) ;
2022-11-10 22:55:57 +01:00
return physics_object_picking_sort ;
}
2023-04-04 19:04:49 +02:00
void Viewport : : set_physics_object_picking_first_only ( bool p_enable ) {
physics_object_picking_first_only = p_enable ;
}
bool Viewport : : get_physics_object_picking_first_only ( ) {
return physics_object_picking_first_only ;
}
2014-10-28 02:54:32 +01:00
Vector2 Viewport : : get_camera_coords ( const Vector2 & p_viewport_coords ) const {
2023-05-12 13:53:15 +02:00
ERR_READ_THREAD_GUARD_V ( Vector2 ( ) ) ;
2022-10-01 08:40:11 +02:00
Transform2D xf = stretch_transform * global_canvas_transform ;
2014-10-28 02:54:32 +01:00
return xf . xform ( p_viewport_coords ) ;
}
Vector2 Viewport : : get_camera_rect_size ( ) const {
2023-05-12 13:53:15 +02:00
ERR_READ_THREAD_GUARD_V ( Vector2 ( ) ) ;
2016-10-27 16:50:26 +02:00
return size ;
2014-10-28 02:54:32 +01:00
}
2016-01-17 02:41:10 +01:00
void Viewport : : set_disable_input ( bool p_disable ) {
2023-05-12 13:53:15 +02:00
ERR_MAIN_THREAD_GUARD ;
2022-03-13 12:43:32 +01:00
if ( p_disable = = disable_input ) {
return ;
}
if ( p_disable ) {
_drop_mouse_focus ( ) ;
2023-01-06 21:48:20 +01:00
_mouse_leave_viewport ( ) ;
2022-03-13 12:43:32 +01:00
_gui_cancel_tooltip ( ) ;
}
2016-01-17 02:41:10 +01:00
disable_input = p_disable ;
}
bool Viewport : : is_input_disabled ( ) const {
2023-05-12 13:53:15 +02:00
ERR_READ_THREAD_GUARD_V ( false ) ;
2016-01-17 02:41:10 +01:00
return disable_input ;
}
2014-02-10 02:10:30 +01:00
2016-05-11 16:46:08 +02:00
Variant Viewport : : gui_get_drag_data ( ) const {
2023-05-12 13:53:15 +02:00
ERR_READ_THREAD_GUARD_V ( Variant ( ) ) ;
2016-05-11 16:46:08 +02:00
return gui . drag_data ;
}
2016-05-17 23:27:15 +02:00
2024-02-17 19:03:21 +01:00
PackedStringArray Viewport : : get_configuration_warnings ( ) const {
ERR_MAIN_THREAD_GUARD_V ( PackedStringArray ( ) ) ;
PackedStringArray warnings = Node : : get_configuration_warnings ( ) ;
2020-05-14 22:59:27 +02:00
2021-10-01 16:36:28 +02:00
if ( size . x < = 1 | | size . y < = 1 ) {
warnings . push_back ( RTR ( " The Viewport size must be greater than or equal to 2 pixels on both dimensions to render anything. " ) ) ;
2020-03-17 21:33:36 +01:00
}
2020-10-29 11:01:28 +01:00
return warnings ;
2016-05-17 23:27:15 +02:00
}
2016-10-03 21:33:42 +02:00
void Viewport : : gui_reset_canvas_sort_index ( ) {
2023-05-12 13:53:15 +02:00
ERR_MAIN_THREAD_GUARD ;
2016-10-03 21:33:42 +02:00
gui . canvas_sort_index = 0 ;
}
2020-05-14 14:29:06 +02:00
2016-10-03 21:33:42 +02:00
int Viewport : : gui_get_canvas_sort_index ( ) {
2023-05-12 13:53:15 +02:00
ERR_MAIN_THREAD_GUARD_V ( 0 ) ;
2016-10-03 21:33:42 +02:00
return gui . canvas_sort_index + + ;
}
2022-02-01 15:07:22 +01:00
void Viewport : : gui_release_focus ( ) {
2023-05-12 13:53:15 +02:00
ERR_MAIN_THREAD_GUARD ;
2022-02-01 15:07:22 +01:00
if ( gui . key_focus ) {
Control * f = gui . key_focus ;
gui . key_focus = nullptr ;
f - > notification ( Control : : NOTIFICATION_FOCUS_EXIT , true ) ;
2022-08-13 23:21:24 +02:00
f - > queue_redraw ( ) ;
2022-02-01 15:07:22 +01:00
}
}
2023-06-02 16:57:10 +02:00
Control * Viewport : : gui_get_focus_owner ( ) const {
2023-05-12 13:53:15 +02:00
ERR_READ_THREAD_GUARD_V ( nullptr ) ;
2022-02-01 15:07:22 +01:00
return gui . key_focus ;
}
2023-12-18 14:50:21 +01:00
Control * Viewport : : gui_get_hovered_control ( ) const {
ERR_READ_THREAD_GUARD_V ( nullptr ) ;
return gui . mouse_over ;
}
2022-08-13 01:02:32 +02:00
void Viewport : : set_msaa_2d ( MSAA p_msaa ) {
2023-05-12 13:53:15 +02:00
ERR_MAIN_THREAD_GUARD ;
2020-04-12 06:49:10 +02:00
ERR_FAIL_INDEX ( p_msaa , MSAA_MAX ) ;
2022-08-13 01:02:32 +02:00
if ( msaa_2d = = p_msaa ) {
2017-01-02 02:16:52 +01:00
return ;
2020-05-14 16:41:43 +02:00
}
2022-08-13 01:02:32 +02:00
msaa_2d = p_msaa ;
RS : : get_singleton ( ) - > viewport_set_msaa_2d ( viewport , RS : : ViewportMSAA ( p_msaa ) ) ;
2017-01-02 02:16:52 +01:00
}
2022-08-13 01:02:32 +02:00
Viewport : : MSAA Viewport : : get_msaa_2d ( ) const {
2023-05-12 13:53:15 +02:00
ERR_READ_THREAD_GUARD_V ( MSAA_DISABLED ) ;
2022-08-13 01:02:32 +02:00
return msaa_2d ;
}
void Viewport : : set_msaa_3d ( MSAA p_msaa ) {
2023-05-12 13:53:15 +02:00
ERR_MAIN_THREAD_GUARD ;
2022-08-13 01:02:32 +02:00
ERR_FAIL_INDEX ( p_msaa , MSAA_MAX ) ;
if ( msaa_3d = = p_msaa ) {
return ;
}
msaa_3d = p_msaa ;
RS : : get_singleton ( ) - > viewport_set_msaa_3d ( viewport , RS : : ViewportMSAA ( p_msaa ) ) ;
}
Viewport : : MSAA Viewport : : get_msaa_3d ( ) const {
2023-05-12 13:53:15 +02:00
ERR_READ_THREAD_GUARD_V ( MSAA_DISABLED ) ;
2022-08-13 01:02:32 +02:00
return msaa_3d ;
2017-01-02 02:16:52 +01:00
}
2020-04-12 06:49:10 +02:00
void Viewport : : set_screen_space_aa ( ScreenSpaceAA p_screen_space_aa ) {
2023-05-12 13:53:15 +02:00
ERR_MAIN_THREAD_GUARD ;
2020-04-12 06:49:10 +02:00
ERR_FAIL_INDEX ( p_screen_space_aa , SCREEN_SPACE_AA_MAX ) ;
2020-05-14 16:41:43 +02:00
if ( screen_space_aa = = p_screen_space_aa ) {
2020-04-12 06:49:10 +02:00
return ;
2020-05-14 16:41:43 +02:00
}
2020-04-12 06:49:10 +02:00
screen_space_aa = p_screen_space_aa ;
RS : : get_singleton ( ) - > viewport_set_screen_space_aa ( viewport , RS : : ViewportScreenSpaceAA ( p_screen_space_aa ) ) ;
}
Viewport : : ScreenSpaceAA Viewport : : get_screen_space_aa ( ) const {
2023-05-12 13:53:15 +02:00
ERR_READ_THREAD_GUARD_V ( SCREEN_SPACE_AA_DISABLED ) ;
2020-04-12 06:49:10 +02:00
return screen_space_aa ;
}
2020-05-14 14:29:06 +02:00
2022-04-04 16:10:22 +02:00
void Viewport : : set_use_taa ( bool p_use_taa ) {
2023-05-12 13:53:15 +02:00
ERR_MAIN_THREAD_GUARD ;
2022-04-04 16:10:22 +02:00
if ( use_taa = = p_use_taa ) {
return ;
}
use_taa = p_use_taa ;
RS : : get_singleton ( ) - > viewport_set_use_taa ( viewport , p_use_taa ) ;
}
bool Viewport : : is_using_taa ( ) const {
2023-05-12 13:53:15 +02:00
ERR_READ_THREAD_GUARD_V ( false ) ;
2022-04-04 16:10:22 +02:00
return use_taa ;
}
2020-04-20 23:34:47 +02:00
void Viewport : : set_use_debanding ( bool p_use_debanding ) {
2023-05-12 13:53:15 +02:00
ERR_MAIN_THREAD_GUARD ;
2021-04-05 14:09:59 +02:00
if ( use_debanding = = p_use_debanding ) {
2020-04-20 23:34:47 +02:00
return ;
2021-04-05 14:09:59 +02:00
}
2020-04-20 23:34:47 +02:00
use_debanding = p_use_debanding ;
RS : : get_singleton ( ) - > viewport_set_use_debanding ( viewport , p_use_debanding ) ;
}
bool Viewport : : is_using_debanding ( ) const {
2023-05-12 13:53:15 +02:00
ERR_READ_THREAD_GUARD_V ( false ) ;
2020-04-20 23:34:47 +02:00
return use_debanding ;
}
2021-12-29 00:10:41 +01:00
void Viewport : : set_mesh_lod_threshold ( float p_pixels ) {
2023-05-12 13:53:15 +02:00
ERR_MAIN_THREAD_GUARD ;
2021-12-29 00:10:41 +01:00
mesh_lod_threshold = p_pixels ;
RS : : get_singleton ( ) - > viewport_set_mesh_lod_threshold ( viewport , mesh_lod_threshold ) ;
2020-12-17 19:56:59 +01:00
}
2021-08-02 19:31:51 +02:00
2021-12-29 00:10:41 +01:00
float Viewport : : get_mesh_lod_threshold ( ) const {
2023-05-12 13:53:15 +02:00
ERR_READ_THREAD_GUARD_V ( 0 ) ;
2021-12-29 00:10:41 +01:00
return mesh_lod_threshold ;
2020-12-17 19:56:59 +01:00
}
2021-04-20 18:40:24 +02:00
void Viewport : : set_use_occlusion_culling ( bool p_use_occlusion_culling ) {
2023-05-12 13:53:15 +02:00
ERR_MAIN_THREAD_GUARD ;
2021-04-20 18:40:24 +02:00
if ( use_occlusion_culling = = p_use_occlusion_culling ) {
return ;
}
use_occlusion_culling = p_use_occlusion_culling ;
RS : : get_singleton ( ) - > viewport_set_use_occlusion_culling ( viewport , p_use_occlusion_culling ) ;
notify_property_list_changed ( ) ;
}
bool Viewport : : is_using_occlusion_culling ( ) const {
2023-05-12 13:53:15 +02:00
ERR_READ_THREAD_GUARD_V ( false ) ;
2021-04-20 18:40:24 +02:00
return use_occlusion_culling ;
}
2017-06-11 20:52:03 +02:00
void Viewport : : set_debug_draw ( DebugDraw p_debug_draw ) {
2023-05-12 13:53:15 +02:00
ERR_MAIN_THREAD_GUARD ;
2017-06-11 20:52:03 +02:00
debug_draw = p_debug_draw ;
2020-03-27 19:21:27 +01:00
RS : : get_singleton ( ) - > viewport_set_debug_draw ( viewport , RS : : ViewportDebugDraw ( p_debug_draw ) ) ;
2017-06-11 20:52:03 +02:00
}
Viewport : : DebugDraw Viewport : : get_debug_draw ( ) const {
2023-05-12 13:53:15 +02:00
ERR_READ_THREAD_GUARD_V ( DEBUG_DRAW_DISABLED ) ;
2017-06-11 20:52:03 +02:00
return debug_draw ;
}
2021-07-03 01:14:19 +02:00
int Viewport : : get_render_info ( RenderInfoType p_type , RenderInfo p_info ) {
2023-05-12 13:53:15 +02:00
ERR_READ_THREAD_GUARD_V ( 0 ) ;
2021-07-03 01:14:19 +02:00
return RS : : get_singleton ( ) - > viewport_get_render_info ( viewport , RS : : ViewportRenderInfoType ( p_type ) , RS : : ViewportRenderInfo ( p_info ) ) ;
2017-06-11 20:52:03 +02:00
}
2017-09-07 16:22:07 +02:00
void Viewport : : set_snap_controls_to_pixels ( bool p_enable ) {
2023-05-12 13:53:15 +02:00
ERR_MAIN_THREAD_GUARD ;
2017-09-07 08:57:09 +02:00
snap_controls_to_pixels = p_enable ;
2017-09-07 16:22:07 +02:00
}
bool Viewport : : is_snap_controls_to_pixels_enabled ( ) const {
2023-05-12 13:53:15 +02:00
ERR_READ_THREAD_GUARD_V ( false ) ;
2017-09-07 16:22:07 +02:00
return snap_controls_to_pixels ;
}
2020-10-29 22:09:16 +01:00
void Viewport : : set_snap_2d_transforms_to_pixel ( bool p_enable ) {
2023-05-12 13:53:15 +02:00
ERR_MAIN_THREAD_GUARD ;
2020-10-29 22:09:16 +01:00
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 {
2023-05-12 13:53:15 +02:00
ERR_READ_THREAD_GUARD_V ( false ) ;
2020-10-29 22:09:16 +01:00
return snap_2d_transforms_to_pixel ;
}
void Viewport : : set_snap_2d_vertices_to_pixel ( bool p_enable ) {
2023-05-12 13:53:15 +02:00
ERR_MAIN_THREAD_GUARD ;
2020-10-29 22:09:16 +01:00
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 {
2023-05-12 13:53:15 +02:00
ERR_READ_THREAD_GUARD_V ( false ) ;
2020-10-29 22:09:16 +01:00
return snap_2d_vertices_to_pixel ;
}
2018-08-24 15:29:27 +02:00
bool Viewport : : gui_is_dragging ( ) const {
2023-05-12 13:53:15 +02:00
ERR_READ_THREAD_GUARD_V ( false ) ;
2018-08-24 15:29:27 +02:00
return gui . dragging ;
}
2018-11-15 17:54:26 +01:00
2021-10-28 09:07:18 +02:00
bool Viewport : : gui_is_drag_successful ( ) const {
2023-05-12 13:53:15 +02:00
ERR_READ_THREAD_GUARD_V ( false ) ;
2021-10-28 09:07:18 +02:00
return gui . drag_successful ;
}
2024-01-23 00:26:16 +01:00
void Viewport : : gui_cancel_drag ( ) {
ERR_MAIN_THREAD_GUARD ;
if ( gui_is_dragging ( ) ) {
_perform_drop ( ) ;
}
}
2018-11-15 17:54:26 +01:00
void Viewport : : set_input_as_handled ( ) {
2023-05-12 13:53:15 +02:00
ERR_MAIN_THREAD_GUARD ;
2021-10-10 12:10:28 +02:00
if ( ! handle_input_locally ) {
2018-11-15 17:54:26 +01:00
ERR_FAIL_COND ( ! is_inside_tree ( ) ) ;
2020-03-04 17:36:09 +01:00
Viewport * vp = this ;
while ( true ) {
if ( Object : : cast_to < Window > ( vp ) ) {
break ;
}
if ( ! vp - > get_parent ( ) ) {
break ;
}
vp = vp - > get_parent ( ) - > get_viewport ( ) ;
}
2021-10-10 12:10:28 +02:00
if ( vp ! = this ) {
vp - > set_input_as_handled ( ) ;
return ;
}
2018-11-15 17:54:26 +01:00
}
2021-10-10 12:10:28 +02:00
local_input_handled = true ;
2018-11-15 17:54:26 +01:00
}
bool Viewport : : is_input_handled ( ) const {
2023-05-12 13:53:15 +02:00
ERR_READ_THREAD_GUARD_V ( false ) ;
2021-10-10 12:10:28 +02:00
if ( ! handle_input_locally ) {
2021-06-13 05:36:32 +02:00
ERR_FAIL_COND_V ( ! is_inside_tree ( ) , false ) ;
2021-10-10 12:10:28 +02:00
const Viewport * vp = this ;
2020-03-04 17:36:09 +01:00
while ( true ) {
if ( Object : : cast_to < Window > ( vp ) ) {
break ;
}
if ( ! vp - > get_parent ( ) ) {
break ;
}
vp = vp - > get_parent ( ) - > get_viewport ( ) ;
}
2021-10-10 12:10:28 +02:00
if ( vp ! = this ) {
return vp - > is_input_handled ( ) ;
}
2018-11-15 17:54:26 +01:00
}
2021-10-10 12:10:28 +02:00
return local_input_handled ;
2018-11-15 17:54:26 +01:00
}
void Viewport : : set_handle_input_locally ( bool p_enable ) {
2023-05-12 13:53:15 +02:00
ERR_MAIN_THREAD_GUARD ;
2018-11-15 17:54:26 +01:00
handle_input_locally = p_enable ;
}
bool Viewport : : is_handling_input_locally ( ) const {
2023-05-12 13:53:15 +02:00
ERR_READ_THREAD_GUARD_V ( false ) ;
2018-11-15 17:54:26 +01:00
return handle_input_locally ;
}
2019-06-25 03:24:07 +02:00
void Viewport : : set_default_canvas_item_texture_filter ( DefaultCanvasItemTextureFilter p_filter ) {
2023-05-12 13:53:15 +02:00
ERR_MAIN_THREAD_GUARD ;
2020-10-24 17:15:43 +02:00
ERR_FAIL_INDEX ( p_filter , DEFAULT_CANVAS_ITEM_TEXTURE_FILTER_MAX ) ;
2019-06-25 03:24:07 +02:00
if ( default_canvas_item_texture_filter = = p_filter ) {
return ;
}
default_canvas_item_texture_filter = p_filter ;
2020-10-24 17:15:43 +02:00
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 : {
}
}
2019-06-25 03:24:07 +02:00
}
Viewport : : DefaultCanvasItemTextureFilter Viewport : : get_default_canvas_item_texture_filter ( ) const {
2023-05-12 13:53:15 +02:00
ERR_READ_THREAD_GUARD_V ( DEFAULT_CANVAS_ITEM_TEXTURE_FILTER_NEAREST ) ;
2019-06-25 03:24:07 +02:00
return default_canvas_item_texture_filter ;
}
void Viewport : : set_default_canvas_item_texture_repeat ( DefaultCanvasItemTextureRepeat p_repeat ) {
2023-05-12 13:53:15 +02:00
ERR_MAIN_THREAD_GUARD ;
2020-10-24 17:15:43 +02:00
ERR_FAIL_INDEX ( p_repeat , DEFAULT_CANVAS_ITEM_TEXTURE_REPEAT_MAX ) ;
2019-06-25 03:24:07 +02:00
if ( default_canvas_item_texture_repeat = = p_repeat ) {
return ;
}
2020-10-24 17:15:43 +02:00
default_canvas_item_texture_repeat = p_repeat ;
2019-06-25 03:24:07 +02:00
2020-10-24 17:15:43 +02:00
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 : {
}
2019-06-25 03:24:07 +02:00
}
}
2020-10-24 17:15:43 +02:00
Viewport : : DefaultCanvasItemTextureRepeat Viewport : : get_default_canvas_item_texture_repeat ( ) const {
2023-05-12 13:53:15 +02:00
ERR_READ_THREAD_GUARD_V ( DEFAULT_CANVAS_ITEM_TEXTURE_REPEAT_DISABLED ) ;
2020-10-24 17:15:43 +02:00
return default_canvas_item_texture_repeat ;
2019-06-25 03:24:07 +02:00
}
2022-02-11 12:33:54 +01:00
void Viewport : : set_vrs_mode ( Viewport : : VRSMode p_vrs_mode ) {
2023-05-12 13:53:15 +02:00
ERR_MAIN_THREAD_GUARD ;
2022-02-11 12:33:54 +01:00
// Note, set this even if not supported on this hardware, it will only be used if it is but we want to save the value as set by the user.
vrs_mode = p_vrs_mode ;
switch ( p_vrs_mode ) {
case VRS_TEXTURE : {
RS : : get_singleton ( ) - > viewport_set_vrs_mode ( viewport , RS : : VIEWPORT_VRS_TEXTURE ) ;
} break ;
case VRS_XR : {
RS : : get_singleton ( ) - > viewport_set_vrs_mode ( viewport , RS : : VIEWPORT_VRS_XR ) ;
} break ;
default : {
RS : : get_singleton ( ) - > viewport_set_vrs_mode ( viewport , RS : : VIEWPORT_VRS_DISABLED ) ;
} break ;
}
notify_property_list_changed ( ) ;
}
Viewport : : VRSMode Viewport : : get_vrs_mode ( ) const {
2023-05-12 13:53:15 +02:00
ERR_READ_THREAD_GUARD_V ( VRS_DISABLED ) ;
2022-02-11 12:33:54 +01:00
return vrs_mode ;
}
2024-03-26 02:57:26 +01:00
void Viewport : : set_vrs_update_mode ( VRSUpdateMode p_vrs_update_mode ) {
ERR_MAIN_THREAD_GUARD ;
vrs_update_mode = p_vrs_update_mode ;
switch ( p_vrs_update_mode ) {
case VRS_UPDATE_ONCE : {
RS : : get_singleton ( ) - > viewport_set_vrs_update_mode ( viewport , RS : : VIEWPORT_VRS_UPDATE_ONCE ) ;
} break ;
case VRS_UPDATE_ALWAYS : {
RS : : get_singleton ( ) - > viewport_set_vrs_update_mode ( viewport , RS : : VIEWPORT_VRS_UPDATE_ALWAYS ) ;
} break ;
default : {
RS : : get_singleton ( ) - > viewport_set_vrs_update_mode ( viewport , RS : : VIEWPORT_VRS_UPDATE_DISABLED ) ;
} break ;
}
}
Viewport : : VRSUpdateMode Viewport : : get_vrs_update_mode ( ) const {
ERR_READ_THREAD_GUARD_V ( VRS_UPDATE_DISABLED ) ;
return vrs_update_mode ;
}
2022-02-11 12:33:54 +01:00
void Viewport : : set_vrs_texture ( Ref < Texture2D > p_texture ) {
2023-05-12 13:53:15 +02:00
ERR_MAIN_THREAD_GUARD ;
2022-02-11 12:33:54 +01:00
vrs_texture = p_texture ;
// TODO need to add something here in case the RID changes
RID tex = p_texture . is_valid ( ) ? p_texture - > get_rid ( ) : RID ( ) ;
RS : : get_singleton ( ) - > viewport_set_vrs_texture ( viewport , tex ) ;
}
Ref < Texture2D > Viewport : : get_vrs_texture ( ) const {
2023-05-12 13:53:15 +02:00
ERR_READ_THREAD_GUARD_V ( Ref < Texture2D > ( ) ) ;
2022-02-11 12:33:54 +01:00
return vrs_texture ;
}
2020-03-03 14:36:29 +01:00
DisplayServer : : WindowID Viewport : : get_window_id ( ) const {
2023-05-12 13:53:15 +02:00
ERR_READ_THREAD_GUARD_V ( DisplayServer : : INVALID_WINDOW_ID ) ;
2020-03-03 14:36:29 +01:00
return DisplayServer : : MAIN_WINDOW_ID ;
}
2020-03-04 02:51:12 +01:00
Viewport * Viewport : : get_parent_viewport ( ) const {
2023-05-12 13:53:15 +02:00
ERR_READ_THREAD_GUARD_V ( nullptr ) ;
2020-03-04 02:51:12 +01:00
ERR_FAIL_COND_V ( ! is_inside_tree ( ) , nullptr ) ;
if ( ! get_parent ( ) ) {
return nullptr ; //root viewport
}
return get_parent ( ) - > get_viewport ( ) ;
}
2014-02-10 02:10:30 +01:00
2022-03-13 16:18:44 +01:00
void Viewport : : set_embedding_subwindows ( bool p_embed ) {
2023-05-12 13:53:15 +02:00
ERR_THREAD_GUARD ;
2023-12-16 01:33:12 +01:00
if ( gui . embed_subwindows_hint = = p_embed ) {
return ;
}
bool allow_change = true ;
if ( ! is_inside_tree ( ) ) {
// Change can happen since no child window is displayed.
} else if ( gui . embed_subwindows_hint ) {
if ( ! gui . sub_windows . is_empty ( ) ) {
// Prevent change when this viewport has embedded windows.
allow_change = false ;
}
} else {
Viewport * vp = this ;
while ( true ) {
if ( ! vp - > get_parent ( ) ) {
// Root window reached.
break ;
}
vp = vp - > get_parent ( ) - > get_viewport ( ) ;
if ( vp - > is_embedding_subwindows ( ) ) {
for ( int i = 0 ; i < vp - > gui . sub_windows . size ( ) ; i + + ) {
if ( is_ancestor_of ( vp - > gui . sub_windows [ i ] . window ) ) {
// Prevent change when this viewport has child windows that are displayed in an ancestor viewport.
allow_change = false ;
break ;
}
}
}
}
if ( allow_change ) {
Vector < int > wl = DisplayServer : : get_singleton ( ) - > get_window_list ( ) ;
for ( int index = 0 ; index < wl . size ( ) ; index + + ) {
DisplayServer : : WindowID wid = wl [ index ] ;
if ( wid = = DisplayServer : : INVALID_WINDOW_ID ) {
continue ;
}
ObjectID woid = DisplayServer : : get_singleton ( ) - > window_get_attached_instance_id ( wid ) ;
if ( woid . is_null ( ) ) {
continue ;
}
Window * w = Object : : cast_to < Window > ( ObjectDB : : get_instance ( woid ) ) ;
if ( w & & is_ancestor_of ( w ) ) {
// Prevent change when this viewport has child windows that are displayed as native windows.
allow_change = false ;
break ;
}
}
}
}
if ( allow_change ) {
gui . embed_subwindows_hint = p_embed ;
} else {
WARN_PRINT ( " Can't change \" gui_embed_subwindows \" while a child window is displayed. Consider hiding all child windows before changing this value. " ) ;
}
2020-03-04 02:51:12 +01:00
}
2020-05-14 14:29:06 +02:00
2020-03-04 02:51:12 +01:00
bool Viewport : : is_embedding_subwindows ( ) const {
2023-05-12 13:53:15 +02:00
ERR_READ_THREAD_GUARD_V ( false ) ;
2020-03-04 02:51:12 +01:00
return gui . embed_subwindows_hint ;
}
2023-08-16 03:06:15 +02:00
TypedArray < Window > Viewport : : get_embedded_subwindows ( ) const {
TypedArray < Window > windows ;
for ( int i = 0 ; i < gui . sub_windows . size ( ) ; i + + ) {
windows . append ( gui . sub_windows [ i ] . window ) ;
}
return windows ;
}
2023-06-20 15:50:44 +02:00
void Viewport : : subwindow_set_popup_safe_rect ( Window * p_window , const Rect2i & p_rect ) {
int index = _sub_window_find ( p_window ) ;
ERR_FAIL_COND ( index = = - 1 ) ;
2023-08-01 14:44:45 +02:00
gui . sub_windows . write [ index ] . parent_safe_rect = p_rect ;
2023-06-20 15:50:44 +02:00
}
Rect2i Viewport : : subwindow_get_popup_safe_rect ( Window * p_window ) const {
int index = _sub_window_find ( p_window ) ;
2023-07-26 20:15:18 +02:00
// FIXME: Re-enable ERR_FAIL_COND after rewriting embedded window popup closing.
// Currently it is expected, that index == -1 can happen.
if ( index = = - 1 ) {
return Rect2i ( ) ;
}
// ERR_FAIL_COND_V(index == -1, Rect2i());
2023-06-20 15:50:44 +02:00
return gui . sub_windows [ index ] . parent_safe_rect ;
}
2020-03-20 03:32:09 +01:00
void Viewport : : pass_mouse_focus_to ( Viewport * p_viewport , Control * p_control ) {
2023-05-12 13:53:15 +02:00
ERR_MAIN_THREAD_GUARD ;
2020-03-20 03:32:09 +01:00
ERR_FAIL_NULL ( p_viewport ) ;
ERR_FAIL_NULL ( p_control ) ;
if ( gui . mouse_focus ) {
p_viewport - > gui . mouse_focus = p_control ;
p_viewport - > gui . mouse_focus_mask = gui . mouse_focus_mask ;
p_viewport - > gui . key_focus = p_control ;
p_viewport - > gui . forced_mouse_focus = true ;
gui . mouse_focus = nullptr ;
gui . forced_mouse_focus = false ;
2023-01-08 00:55:54 +01:00
gui . mouse_focus_mask . clear ( ) ;
2020-03-20 03:32:09 +01:00
}
}
2020-11-26 13:50:21 +01:00
void Viewport : : set_sdf_oversize ( SDFOversize p_sdf_oversize ) {
2023-05-12 13:53:15 +02:00
ERR_MAIN_THREAD_GUARD ;
2020-11-26 13:50:21 +01:00
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 ) ) ;
}
2021-08-02 19:31:51 +02:00
2020-11-26 13:50:21 +01:00
Viewport : : SDFOversize Viewport : : get_sdf_oversize ( ) const {
2023-05-12 13:53:15 +02:00
ERR_READ_THREAD_GUARD_V ( SDF_OVERSIZE_100_PERCENT ) ;
2020-11-26 13:50:21 +01:00
return sdf_oversize ;
}
void Viewport : : set_sdf_scale ( SDFScale p_sdf_scale ) {
2023-05-12 13:53:15 +02:00
ERR_MAIN_THREAD_GUARD ;
2020-11-26 13:50:21 +01:00
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 ) ) ;
}
2021-08-02 19:31:51 +02:00
2020-11-26 13:50:21 +01:00
Viewport : : SDFScale Viewport : : get_sdf_scale ( ) const {
2023-05-12 13:53:15 +02:00
ERR_READ_THREAD_GUARD_V ( SDF_SCALE_100_PERCENT ) ;
2020-11-26 13:50:21 +01:00
return sdf_scale ;
}
2022-03-28 11:01:29 +02:00
Transform2D Viewport : : get_screen_transform ( ) const {
2023-05-12 13:53:15 +02:00
ERR_READ_THREAD_GUARD_V ( Transform2D ( ) ) ;
2023-01-20 22:33:05 +01:00
return get_screen_transform_internal ( ) ;
}
Transform2D Viewport : : get_screen_transform_internal ( bool p_absolute_position ) const {
2023-05-12 13:53:15 +02:00
ERR_READ_THREAD_GUARD_V ( Transform2D ( ) ) ;
2022-10-01 08:40:11 +02:00
return get_final_transform ( ) ;
2022-03-28 11:01:29 +02:00
}
2022-09-29 23:45:51 +02:00
void Viewport : : update_mouse_cursor_state ( ) {
// Updates need to happen in Window, because SubViewportContainers might be hidden behind other Controls.
Window * base_window = get_base_window ( ) ;
if ( base_window ) {
base_window - > update_mouse_cursor_state ( ) ;
}
}
2021-09-02 20:07:04 +02:00
void Viewport : : set_canvas_cull_mask ( uint32_t p_canvas_cull_mask ) {
2023-05-12 13:53:15 +02:00
ERR_MAIN_THREAD_GUARD ;
2021-09-02 20:07:04 +02:00
canvas_cull_mask = p_canvas_cull_mask ;
RenderingServer : : get_singleton ( ) - > viewport_set_canvas_cull_mask ( viewport , canvas_cull_mask ) ;
}
uint32_t Viewport : : get_canvas_cull_mask ( ) const {
2023-05-12 13:53:15 +02:00
ERR_READ_THREAD_GUARD_V ( 0 ) ;
2021-09-02 20:07:04 +02:00
return canvas_cull_mask ;
}
void Viewport : : set_canvas_cull_mask_bit ( uint32_t p_layer , bool p_enable ) {
2023-05-12 13:53:15 +02:00
ERR_MAIN_THREAD_GUARD ;
2022-11-02 22:36:01 +01:00
ERR_FAIL_UNSIGNED_INDEX ( p_layer , 32 ) ;
2021-09-02 20:07:04 +02:00
if ( p_enable ) {
set_canvas_cull_mask ( canvas_cull_mask | ( 1 < < p_layer ) ) ;
} else {
set_canvas_cull_mask ( canvas_cull_mask & ( ~ ( 1 < < p_layer ) ) ) ;
}
}
bool Viewport : : get_canvas_cull_mask_bit ( uint32_t p_layer ) const {
2023-05-12 13:53:15 +02:00
ERR_READ_THREAD_GUARD_V ( false ) ;
2022-11-02 22:36:01 +01:00
ERR_FAIL_UNSIGNED_INDEX_V ( p_layer , 32 , false ) ;
2021-09-02 20:07:04 +02:00
return ( canvas_cull_mask & ( 1 < < p_layer ) ) ;
}
2023-07-08 05:57:31 +02:00
void Viewport : : _update_audio_listener_2d ( ) {
if ( AudioServer : : get_singleton ( ) ) {
AudioServer : : get_singleton ( ) - > notify_listener_changed ( ) ;
}
}
void Viewport : : _audio_listener_2d_set ( AudioListener2D * p_audio_listener ) {
if ( audio_listener_2d = = p_audio_listener ) {
return ;
} else if ( audio_listener_2d ) {
audio_listener_2d - > clear_current ( ) ;
}
audio_listener_2d = p_audio_listener ;
}
void Viewport : : _audio_listener_2d_remove ( AudioListener2D * p_audio_listener ) {
if ( audio_listener_2d = = p_audio_listener ) {
audio_listener_2d = nullptr ;
}
}
void Viewport : : _camera_2d_set ( Camera2D * p_camera_2d ) {
camera_2d = p_camera_2d ;
}
void Viewport : : _cleanup_mouseover_colliders ( bool p_clean_all_frames , bool p_paused_only , uint64_t p_frame_reference ) {
List < ObjectID > to_erase ;
List < ObjectID > to_mouse_exit ;
for ( const KeyValue < ObjectID , uint64_t > & E : physics_2d_mouseover ) {
if ( ! p_clean_all_frames & & E . value = = p_frame_reference ) {
continue ;
}
Object * o = ObjectDB : : get_instance ( E . key ) ;
if ( o ) {
CollisionObject2D * co = Object : : cast_to < CollisionObject2D > ( o ) ;
if ( co & & co - > is_inside_tree ( ) ) {
if ( p_clean_all_frames & & p_paused_only & & co - > can_process ( ) ) {
continue ;
}
to_mouse_exit . push_back ( E . key ) ;
}
}
to_erase . push_back ( E . key ) ;
}
while ( to_erase . size ( ) ) {
physics_2d_mouseover . erase ( to_erase . front ( ) - > get ( ) ) ;
to_erase . pop_front ( ) ;
}
// Per-shape.
List < Pair < ObjectID , int > > shapes_to_erase ;
List < Pair < ObjectID , int > > shapes_to_mouse_exit ;
for ( KeyValue < Pair < ObjectID , int > , uint64_t > & E : physics_2d_shape_mouseover ) {
if ( ! p_clean_all_frames & & E . value = = p_frame_reference ) {
continue ;
}
Object * o = ObjectDB : : get_instance ( E . key . first ) ;
if ( o ) {
CollisionObject2D * co = Object : : cast_to < CollisionObject2D > ( o ) ;
if ( co & & co - > is_inside_tree ( ) ) {
if ( p_clean_all_frames & & p_paused_only & & co - > can_process ( ) ) {
continue ;
}
shapes_to_mouse_exit . push_back ( E . key ) ;
}
}
shapes_to_erase . push_back ( E . key ) ;
}
while ( shapes_to_erase . size ( ) ) {
physics_2d_shape_mouseover . erase ( shapes_to_erase . front ( ) - > get ( ) ) ;
shapes_to_erase . pop_front ( ) ;
}
while ( to_mouse_exit . size ( ) ) {
Object * o = ObjectDB : : get_instance ( to_mouse_exit . front ( ) - > get ( ) ) ;
CollisionObject2D * co = Object : : cast_to < CollisionObject2D > ( o ) ;
co - > _mouse_exit ( ) ;
to_mouse_exit . pop_front ( ) ;
}
while ( shapes_to_mouse_exit . size ( ) ) {
Pair < ObjectID , int > e = shapes_to_mouse_exit . front ( ) - > get ( ) ;
Object * o = ObjectDB : : get_instance ( e . first ) ;
CollisionObject2D * co = Object : : cast_to < CollisionObject2D > ( o ) ;
co - > _mouse_shape_exit ( e . second ) ;
shapes_to_mouse_exit . pop_front ( ) ;
}
}
AudioListener2D * Viewport : : get_audio_listener_2d ( ) const {
ERR_READ_THREAD_GUARD_V ( nullptr ) ;
return audio_listener_2d ;
}
void Viewport : : set_as_audio_listener_2d ( bool p_enable ) {
ERR_MAIN_THREAD_GUARD ;
if ( p_enable = = is_audio_listener_2d_enabled ) {
return ;
}
is_audio_listener_2d_enabled = p_enable ;
_update_audio_listener_2d ( ) ;
}
bool Viewport : : is_audio_listener_2d ( ) const {
ERR_READ_THREAD_GUARD_V ( false ) ;
return is_audio_listener_2d_enabled ;
}
Camera2D * Viewport : : get_camera_2d ( ) const {
ERR_READ_THREAD_GUARD_V ( nullptr ) ;
return camera_2d ;
}
void Viewport : : assign_next_enabled_camera_2d ( const StringName & p_camera_group ) {
ERR_MAIN_THREAD_GUARD ;
List < Node * > camera_list ;
get_tree ( ) - > get_nodes_in_group ( p_camera_group , & camera_list ) ;
Camera2D * new_camera = nullptr ;
for ( Node * E : camera_list ) {
Camera2D * cam = Object : : cast_to < Camera2D > ( E ) ;
if ( ! cam ) {
continue ; // Non-camera node (e.g. ParallaxBackground).
}
if ( cam - > is_enabled ( ) ) {
new_camera = cam ;
break ;
}
}
_camera_2d_set ( new_camera ) ;
if ( ! camera_2d ) {
set_canvas_transform ( Transform2D ( ) ) ;
}
}
2021-07-04 03:43:23 +02:00
# ifndef _3D_DISABLED
2021-09-16 21:28:20 +02:00
AudioListener3D * Viewport : : get_audio_listener_3d ( ) const {
2023-05-12 13:53:15 +02:00
ERR_READ_THREAD_GUARD_V ( nullptr ) ;
2021-09-16 21:28:20 +02:00
return audio_listener_3d ;
2021-08-02 19:31:51 +02:00
}
2014-02-10 02:10:30 +01:00
2021-08-02 19:31:51 +02:00
void Viewport : : set_as_audio_listener_3d ( bool p_enable ) {
2023-05-12 13:53:15 +02:00
ERR_MAIN_THREAD_GUARD ;
2021-09-16 21:28:20 +02:00
if ( p_enable = = is_audio_listener_3d_enabled ) {
2021-08-02 19:31:51 +02:00
return ;
}
2014-02-10 02:10:30 +01:00
2021-09-16 21:28:20 +02:00
is_audio_listener_3d_enabled = p_enable ;
_update_audio_listener_3d ( ) ;
2021-08-02 19:31:51 +02:00
}
2014-02-10 02:10:30 +01:00
2021-08-02 19:31:51 +02:00
bool Viewport : : is_audio_listener_3d ( ) const {
2023-05-12 13:53:15 +02:00
ERR_READ_THREAD_GUARD_V ( false ) ;
2021-09-16 21:28:20 +02:00
return is_audio_listener_3d_enabled ;
2021-08-02 19:31:51 +02:00
}
2014-08-14 15:31:38 +02:00
2021-09-16 21:28:20 +02:00
void Viewport : : _update_audio_listener_3d ( ) {
2021-09-01 17:44:47 +02:00
if ( AudioServer : : get_singleton ( ) ) {
AudioServer : : get_singleton ( ) - > notify_listener_changed ( ) ;
}
2021-08-02 19:31:51 +02:00
}
2020-04-12 06:49:10 +02:00
2021-08-02 19:31:51 +02:00
void Viewport : : _listener_transform_3d_changed_notify ( ) {
}
2020-04-20 23:34:47 +02:00
2021-09-16 21:28:20 +02:00
void Viewport : : _audio_listener_3d_set ( AudioListener3D * p_listener ) {
if ( audio_listener_3d = = p_listener ) {
2021-08-02 19:31:51 +02:00
return ;
}
2021-04-20 18:40:24 +02:00
2021-09-16 21:28:20 +02:00
audio_listener_3d = p_listener ;
2017-06-11 20:52:03 +02:00
2021-09-16 21:28:20 +02:00
_update_audio_listener_3d ( ) ;
2021-08-02 19:31:51 +02:00
_listener_transform_3d_changed_notify ( ) ;
}
2017-06-11 20:52:03 +02:00
2021-09-16 21:28:20 +02:00
bool Viewport : : _audio_listener_3d_add ( AudioListener3D * p_listener ) {
audio_listener_3d_set . insert ( p_listener ) ;
return audio_listener_3d_set . size ( ) = = 1 ;
2021-08-02 19:31:51 +02:00
}
2021-04-29 03:23:24 +02:00
2021-09-16 21:28:20 +02:00
void Viewport : : _audio_listener_3d_remove ( AudioListener3D * p_listener ) {
audio_listener_3d_set . erase ( p_listener ) ;
if ( audio_listener_3d = = p_listener ) {
audio_listener_3d = nullptr ;
2021-08-02 19:31:51 +02:00
}
}
2014-02-26 14:08:17 +01:00
2021-09-16 21:28:20 +02:00
void Viewport : : _audio_listener_3d_make_next_current ( AudioListener3D * p_exclude ) {
if ( audio_listener_3d_set . size ( ) > 0 ) {
2022-05-19 01:43:40 +02:00
for ( AudioListener3D * E : audio_listener_3d_set ) {
if ( p_exclude = = E ) {
2021-08-02 19:31:51 +02:00
continue ;
}
2022-05-19 01:43:40 +02:00
if ( ! E - > is_inside_tree ( ) ) {
2021-08-02 19:31:51 +02:00
continue ;
}
2021-09-16 21:28:20 +02:00
if ( audio_listener_3d ! = nullptr ) {
2021-08-02 19:31:51 +02:00
return ;
}
2014-09-15 16:33:30 +02:00
2022-05-19 01:43:40 +02:00
E - > make_current ( ) ;
2021-08-02 19:31:51 +02:00
}
} else {
2021-09-10 16:58:33 +02:00
// Attempt to reset listener to the camera position.
2021-08-02 19:31:51 +02:00
if ( camera_3d ! = nullptr ) {
2021-09-16 21:28:20 +02:00
_update_audio_listener_3d ( ) ;
2021-08-02 19:31:51 +02:00
_camera_3d_transform_changed_notify ( ) ;
}
}
}
2014-02-26 14:08:17 +01:00
2021-08-02 19:31:51 +02:00
void Viewport : : _collision_object_3d_input_event ( CollisionObject3D * p_object , Camera3D * p_camera , const Ref < InputEvent > & p_input_event , const Vector3 & p_pos , const Vector3 & p_normal , int p_shape ) {
Transform3D object_transform = p_object - > get_global_transform ( ) ;
Transform3D camera_transform = p_camera - > get_global_transform ( ) ;
ObjectID id = p_object - > get_instance_id ( ) ;
2014-04-15 03:43:44 +02:00
2021-09-10 16:58:33 +02:00
// Avoid sending the fake event unnecessarily if nothing really changed in the context.
2021-08-02 19:31:51 +02:00
if ( object_transform = = physics_last_object_transform & & camera_transform = = physics_last_camera_transform & & physics_last_id = = id ) {
Ref < InputEventMouseMotion > mm = p_input_event ;
if ( mm . is_valid ( ) & & mm - > get_device ( ) = = InputEvent : : DEVICE_ID_INTERNAL ) {
2021-09-10 16:58:33 +02:00
return ; // Discarded.
2021-08-02 19:31:51 +02:00
}
}
2021-08-22 17:37:22 +02:00
p_object - > _input_event_call ( camera_3d , p_input_event , p_pos , p_normal , p_shape ) ;
2021-08-02 19:31:51 +02:00
physics_last_object_transform = object_transform ;
physics_last_camera_transform = camera_transform ;
physics_last_id = id ;
}
2014-02-26 14:08:17 +01:00
2021-08-02 19:31:51 +02:00
Camera3D * Viewport : : get_camera_3d ( ) const {
2023-05-12 13:53:15 +02:00
ERR_READ_THREAD_GUARD_V ( nullptr ) ;
2021-08-02 19:31:51 +02:00
return camera_3d ;
}
2014-02-26 14:08:17 +01:00
2021-08-02 19:31:51 +02:00
void Viewport : : _camera_3d_transform_changed_notify ( ) {
}
2014-02-26 14:08:17 +01:00
2021-08-02 19:31:51 +02:00
void Viewport : : _camera_3d_set ( Camera3D * p_camera ) {
if ( camera_3d = = p_camera ) {
return ;
}
if ( camera_3d ) {
camera_3d - > notification ( Camera3D : : NOTIFICATION_LOST_CURRENT ) ;
}
camera_3d = p_camera ;
if ( ! camera_3d_override ) {
if ( camera_3d ) {
RenderingServer : : get_singleton ( ) - > viewport_attach_camera ( viewport , camera_3d - > get_camera ( ) ) ;
} else {
RenderingServer : : get_singleton ( ) - > viewport_attach_camera ( viewport , RID ( ) ) ;
}
}
if ( camera_3d ) {
camera_3d - > notification ( Camera3D : : NOTIFICATION_BECAME_CURRENT ) ;
}
2021-09-16 21:28:20 +02:00
_update_audio_listener_3d ( ) ;
2021-08-02 19:31:51 +02:00
_camera_3d_transform_changed_notify ( ) ;
}
bool Viewport : : _camera_3d_add ( Camera3D * p_camera ) {
camera_3d_set . insert ( p_camera ) ;
return camera_3d_set . size ( ) = = 1 ;
}
void Viewport : : _camera_3d_remove ( Camera3D * p_camera ) {
camera_3d_set . erase ( p_camera ) ;
if ( camera_3d = = p_camera ) {
camera_3d - > notification ( Camera3D : : NOTIFICATION_LOST_CURRENT ) ;
camera_3d = nullptr ;
}
}
void Viewport : : _camera_3d_make_next_current ( Camera3D * p_exclude ) {
2022-05-19 01:43:40 +02:00
for ( Camera3D * E : camera_3d_set ) {
if ( p_exclude = = E ) {
2021-08-02 19:31:51 +02:00
continue ;
}
2022-05-19 01:43:40 +02:00
if ( ! E - > is_inside_tree ( ) ) {
2021-08-02 19:31:51 +02:00
continue ;
}
if ( camera_3d ! = nullptr ) {
return ;
}
2022-05-19 01:43:40 +02:00
E - > make_current ( ) ;
2021-08-02 19:31:51 +02:00
}
}
void Viewport : : enable_camera_3d_override ( bool p_enable ) {
2023-05-12 13:53:15 +02:00
ERR_MAIN_THREAD_GUARD ;
2021-08-02 19:31:51 +02:00
if ( p_enable = = camera_3d_override ) {
return ;
}
if ( p_enable ) {
camera_3d_override . rid = RenderingServer : : get_singleton ( ) - > camera_create ( ) ;
} else {
RenderingServer : : get_singleton ( ) - > free ( camera_3d_override . rid ) ;
camera_3d_override . rid = RID ( ) ;
}
if ( p_enable ) {
RenderingServer : : get_singleton ( ) - > viewport_attach_camera ( viewport , camera_3d_override . rid ) ;
} else if ( camera_3d ) {
RenderingServer : : get_singleton ( ) - > viewport_attach_camera ( viewport , camera_3d - > get_camera ( ) ) ;
} else {
RenderingServer : : get_singleton ( ) - > viewport_attach_camera ( viewport , RID ( ) ) ;
}
}
void Viewport : : set_camera_3d_override_perspective ( real_t p_fovy_degrees , real_t p_z_near , real_t p_z_far ) {
2023-05-12 13:53:15 +02:00
ERR_MAIN_THREAD_GUARD ;
2021-08-02 19:31:51 +02:00
if ( camera_3d_override ) {
if ( camera_3d_override . fov = = p_fovy_degrees & & camera_3d_override . z_near = = p_z_near & &
camera_3d_override . z_far = = p_z_far & & camera_3d_override . projection = = Camera3DOverrideData : : PROJECTION_PERSPECTIVE ) {
return ;
}
camera_3d_override . fov = p_fovy_degrees ;
camera_3d_override . z_near = p_z_near ;
camera_3d_override . z_far = p_z_far ;
camera_3d_override . projection = Camera3DOverrideData : : PROJECTION_PERSPECTIVE ;
RenderingServer : : get_singleton ( ) - > camera_set_perspective ( camera_3d_override . rid , camera_3d_override . fov , camera_3d_override . z_near , camera_3d_override . z_far ) ;
}
}
void Viewport : : set_camera_3d_override_orthogonal ( real_t p_size , real_t p_z_near , real_t p_z_far ) {
2023-05-12 13:53:15 +02:00
ERR_MAIN_THREAD_GUARD ;
2021-08-02 19:31:51 +02:00
if ( camera_3d_override ) {
if ( camera_3d_override . size = = p_size & & camera_3d_override . z_near = = p_z_near & &
camera_3d_override . z_far = = p_z_far & & camera_3d_override . projection = = Camera3DOverrideData : : PROJECTION_ORTHOGONAL ) {
return ;
}
camera_3d_override . size = p_size ;
camera_3d_override . z_near = p_z_near ;
camera_3d_override . z_far = p_z_far ;
camera_3d_override . projection = Camera3DOverrideData : : PROJECTION_ORTHOGONAL ;
RenderingServer : : get_singleton ( ) - > camera_set_orthogonal ( camera_3d_override . rid , camera_3d_override . size , camera_3d_override . z_near , camera_3d_override . z_far ) ;
}
}
void Viewport : : set_disable_3d ( bool p_disable ) {
2023-05-12 13:53:15 +02:00
ERR_MAIN_THREAD_GUARD ;
2021-08-02 19:31:51 +02:00
disable_3d = p_disable ;
RenderingServer : : get_singleton ( ) - > viewport_set_disable_3d ( viewport , disable_3d ) ;
}
bool Viewport : : is_3d_disabled ( ) const {
2023-05-12 13:53:15 +02:00
ERR_READ_THREAD_GUARD_V ( false ) ;
2021-08-02 19:31:51 +02:00
return disable_3d ;
}
bool Viewport : : is_camera_3d_override_enabled ( ) const {
2023-05-12 13:53:15 +02:00
ERR_READ_THREAD_GUARD_V ( false ) ;
2021-08-02 19:31:51 +02:00
return camera_3d_override ;
}
void Viewport : : set_camera_3d_override_transform ( const Transform3D & p_transform ) {
2023-05-12 13:53:15 +02:00
ERR_MAIN_THREAD_GUARD ;
2021-08-02 19:31:51 +02:00
if ( camera_3d_override ) {
camera_3d_override . transform = p_transform ;
RenderingServer : : get_singleton ( ) - > camera_set_transform ( camera_3d_override . rid , p_transform ) ;
}
}
Transform3D Viewport : : get_camera_3d_override_transform ( ) const {
2023-05-12 13:53:15 +02:00
ERR_READ_THREAD_GUARD_V ( Transform3D ( ) ) ;
2021-08-02 19:31:51 +02:00
if ( camera_3d_override ) {
return camera_3d_override . transform ;
}
return Transform3D ( ) ;
}
Ref < World3D > Viewport : : get_world_3d ( ) const {
2023-05-12 13:53:15 +02:00
ERR_READ_THREAD_GUARD_V ( Ref < World3D > ( ) ) ;
2021-08-02 19:31:51 +02:00
return world_3d ;
}
Ref < World3D > Viewport : : find_world_3d ( ) const {
2023-05-12 13:53:15 +02:00
ERR_READ_THREAD_GUARD_V ( Ref < World3D > ( ) ) ;
2021-08-02 19:31:51 +02:00
if ( own_world_3d . is_valid ( ) ) {
return own_world_3d ;
} else if ( world_3d . is_valid ( ) ) {
return world_3d ;
} else if ( parent ) {
return parent - > find_world_3d ( ) ;
} else {
return Ref < World3D > ( ) ;
}
}
void Viewport : : set_world_3d ( const Ref < World3D > & p_world_3d ) {
2023-05-12 13:53:15 +02:00
ERR_MAIN_THREAD_GUARD ;
2021-08-02 19:31:51 +02:00
if ( world_3d = = p_world_3d ) {
return ;
}
if ( is_inside_tree ( ) ) {
_propagate_exit_world_3d ( this ) ;
}
if ( own_world_3d . is_valid ( ) & & world_3d . is_valid ( ) ) {
2023-07-03 21:29:37 +02:00
world_3d - > disconnect_changed ( callable_mp ( this , & Viewport : : _own_world_3d_changed ) ) ;
2021-08-02 19:31:51 +02:00
}
world_3d = p_world_3d ;
if ( own_world_3d . is_valid ( ) ) {
if ( world_3d . is_valid ( ) ) {
own_world_3d = world_3d - > duplicate ( ) ;
2023-07-03 21:29:37 +02:00
world_3d - > connect_changed ( callable_mp ( this , & Viewport : : _own_world_3d_changed ) ) ;
2021-08-02 19:31:51 +02:00
} else {
own_world_3d = Ref < World3D > ( memnew ( World3D ) ) ;
}
}
if ( is_inside_tree ( ) ) {
_propagate_enter_world_3d ( this ) ;
}
if ( is_inside_tree ( ) ) {
RenderingServer : : get_singleton ( ) - > viewport_set_scenario ( viewport , find_world_3d ( ) - > get_scenario ( ) ) ;
}
2021-09-16 21:28:20 +02:00
_update_audio_listener_3d ( ) ;
2021-08-02 19:31:51 +02:00
}
void Viewport : : _own_world_3d_changed ( ) {
ERR_FAIL_COND ( world_3d . is_null ( ) ) ;
ERR_FAIL_COND ( own_world_3d . is_null ( ) ) ;
if ( is_inside_tree ( ) ) {
_propagate_exit_world_3d ( this ) ;
}
own_world_3d = world_3d - > duplicate ( ) ;
if ( is_inside_tree ( ) ) {
_propagate_enter_world_3d ( this ) ;
}
if ( is_inside_tree ( ) ) {
RenderingServer : : get_singleton ( ) - > viewport_set_scenario ( viewport , find_world_3d ( ) - > get_scenario ( ) ) ;
}
2021-09-16 21:28:20 +02:00
_update_audio_listener_3d ( ) ;
2021-08-02 19:31:51 +02:00
}
2022-06-06 15:34:40 +02:00
void Viewport : : set_use_own_world_3d ( bool p_use_own_world_3d ) {
2023-05-12 13:53:15 +02:00
ERR_MAIN_THREAD_GUARD ;
2022-06-06 15:34:40 +02:00
if ( p_use_own_world_3d = = own_world_3d . is_valid ( ) ) {
2021-08-02 19:31:51 +02:00
return ;
}
if ( is_inside_tree ( ) ) {
_propagate_exit_world_3d ( this ) ;
}
2022-06-06 15:34:40 +02:00
if ( p_use_own_world_3d ) {
2021-08-02 19:31:51 +02:00
if ( world_3d . is_valid ( ) ) {
own_world_3d = world_3d - > duplicate ( ) ;
2023-07-03 21:29:37 +02:00
world_3d - > connect_changed ( callable_mp ( this , & Viewport : : _own_world_3d_changed ) ) ;
2021-08-02 19:31:51 +02:00
} else {
own_world_3d = Ref < World3D > ( memnew ( World3D ) ) ;
}
2022-06-06 15:34:40 +02:00
} else {
own_world_3d = Ref < World3D > ( ) ;
if ( world_3d . is_valid ( ) ) {
2023-07-03 21:29:37 +02:00
world_3d - > disconnect_changed ( callable_mp ( this , & Viewport : : _own_world_3d_changed ) ) ;
2022-06-06 15:34:40 +02:00
}
2021-08-02 19:31:51 +02:00
}
if ( is_inside_tree ( ) ) {
_propagate_enter_world_3d ( this ) ;
}
if ( is_inside_tree ( ) ) {
RenderingServer : : get_singleton ( ) - > viewport_set_scenario ( viewport , find_world_3d ( ) - > get_scenario ( ) ) ;
}
2021-09-16 21:28:20 +02:00
_update_audio_listener_3d ( ) ;
2021-08-02 19:31:51 +02:00
}
bool Viewport : : is_using_own_world_3d ( ) const {
2023-05-12 13:53:15 +02:00
ERR_READ_THREAD_GUARD_V ( false ) ;
2021-08-02 19:31:51 +02:00
return own_world_3d . is_valid ( ) ;
}
void Viewport : : _propagate_enter_world_3d ( Node * p_node ) {
if ( p_node ! = this ) {
if ( ! p_node - > is_inside_tree ( ) ) { //may not have entered scene yet
return ;
}
if ( Object : : cast_to < Node3D > ( p_node ) | | Object : : cast_to < WorldEnvironment > ( p_node ) ) {
p_node - > notification ( Node3D : : NOTIFICATION_ENTER_WORLD ) ;
} else {
Viewport * v = Object : : cast_to < Viewport > ( p_node ) ;
if ( v ) {
if ( v - > world_3d . is_valid ( ) | | v - > own_world_3d . is_valid ( ) ) {
return ;
}
}
}
}
for ( int i = 0 ; i < p_node - > get_child_count ( ) ; i + + ) {
_propagate_enter_world_3d ( p_node - > get_child ( i ) ) ;
}
}
void Viewport : : _propagate_exit_world_3d ( Node * p_node ) {
if ( p_node ! = this ) {
if ( ! p_node - > is_inside_tree ( ) ) { //may have exited scene already
return ;
}
if ( Object : : cast_to < Node3D > ( p_node ) | | Object : : cast_to < WorldEnvironment > ( p_node ) ) {
p_node - > notification ( Node3D : : NOTIFICATION_EXIT_WORLD ) ;
} else {
Viewport * v = Object : : cast_to < Viewport > ( p_node ) ;
if ( v ) {
if ( v - > world_3d . is_valid ( ) | | v - > own_world_3d . is_valid ( ) ) {
return ;
}
}
}
}
for ( int i = 0 ; i < p_node - > get_child_count ( ) ; i + + ) {
_propagate_exit_world_3d ( p_node - > get_child ( i ) ) ;
}
}
void Viewport : : set_use_xr ( bool p_use_xr ) {
2023-05-12 13:53:15 +02:00
ERR_MAIN_THREAD_GUARD ;
2022-08-16 23:54:55 +02:00
if ( use_xr ! = p_use_xr ) {
use_xr = p_use_xr ;
2021-08-02 19:31:51 +02:00
2022-08-16 23:54:55 +02:00
RS : : get_singleton ( ) - > viewport_set_use_xr ( viewport , use_xr ) ;
if ( ! use_xr ) {
// Set viewport to previous size when exiting XR.
if ( size_allocated ) {
RS : : get_singleton ( ) - > viewport_set_size ( viewport , size . width , size . height ) ;
} else {
RS : : get_singleton ( ) - > viewport_set_size ( viewport , 0 , 0 ) ;
}
2024-03-25 14:07:28 +01:00
// Reset render target override textures.
RID rt = RS : : get_singleton ( ) - > viewport_get_render_target ( viewport ) ;
RSG : : texture_storage - > render_target_set_override ( rt , RID ( ) , RID ( ) , RID ( ) ) ;
2022-08-16 23:54:55 +02:00
}
}
2021-08-02 19:31:51 +02:00
}
bool Viewport : : is_using_xr ( ) {
2023-05-12 13:53:15 +02:00
ERR_READ_THREAD_GUARD_V ( false ) ;
2021-08-02 19:31:51 +02:00
return use_xr ;
}
2021-08-19 03:52:06 +02:00
2021-11-23 22:16:03 +01:00
void Viewport : : set_scaling_3d_mode ( Scaling3DMode p_scaling_3d_mode ) {
2023-05-12 13:53:15 +02:00
ERR_MAIN_THREAD_GUARD ;
2021-11-23 22:16:03 +01:00
if ( scaling_3d_mode = = p_scaling_3d_mode ) {
return ;
}
scaling_3d_mode = p_scaling_3d_mode ;
RS : : get_singleton ( ) - > viewport_set_scaling_3d_mode ( viewport , ( RS : : ViewportScaling3DMode ) ( int ) p_scaling_3d_mode ) ;
}
Viewport : : Scaling3DMode Viewport : : get_scaling_3d_mode ( ) const {
2023-05-12 13:53:15 +02:00
ERR_READ_THREAD_GUARD_V ( SCALING_3D_MODE_BILINEAR ) ;
2021-11-23 22:16:03 +01:00
return scaling_3d_mode ;
}
void Viewport : : set_scaling_3d_scale ( float p_scaling_3d_scale ) {
2023-05-12 13:53:15 +02:00
ERR_MAIN_THREAD_GUARD ;
2021-08-29 14:44:09 +02:00
// Clamp to reasonable values that are actually useful.
// Values above 2.0 don't serve a practical purpose since the viewport
// isn't displayed with mipmaps.
2021-11-23 22:16:03 +01:00
scaling_3d_scale = CLAMP ( p_scaling_3d_scale , 0.1 , 2.0 ) ;
RS : : get_singleton ( ) - > viewport_set_scaling_3d_scale ( viewport , scaling_3d_scale ) ;
}
float Viewport : : get_scaling_3d_scale ( ) const {
2023-05-12 13:53:15 +02:00
ERR_READ_THREAD_GUARD_V ( 0 ) ;
2021-11-23 22:16:03 +01:00
return scaling_3d_scale ;
}
void Viewport : : set_fsr_sharpness ( float p_fsr_sharpness ) {
2023-05-12 13:53:15 +02:00
ERR_MAIN_THREAD_GUARD ;
2021-11-23 22:16:03 +01:00
if ( fsr_sharpness = = p_fsr_sharpness ) {
return ;
}
if ( p_fsr_sharpness < 0.0f ) {
p_fsr_sharpness = 0.0f ;
}
2021-08-19 03:52:06 +02:00
2021-11-23 22:16:03 +01:00
fsr_sharpness = p_fsr_sharpness ;
RS : : get_singleton ( ) - > viewport_set_fsr_sharpness ( viewport , p_fsr_sharpness ) ;
2021-08-19 03:52:06 +02:00
}
2021-11-23 22:16:03 +01:00
float Viewport : : get_fsr_sharpness ( ) const {
2023-05-12 13:53:15 +02:00
ERR_READ_THREAD_GUARD_V ( 0 ) ;
2021-11-23 22:16:03 +01:00
return fsr_sharpness ;
}
2022-06-12 01:49:59 +02:00
void Viewport : : set_texture_mipmap_bias ( float p_texture_mipmap_bias ) {
2023-05-12 13:53:15 +02:00
ERR_MAIN_THREAD_GUARD ;
2022-06-12 01:49:59 +02:00
if ( texture_mipmap_bias = = p_texture_mipmap_bias ) {
2021-11-23 22:16:03 +01:00
return ;
}
2022-06-12 01:49:59 +02:00
texture_mipmap_bias = p_texture_mipmap_bias ;
RS : : get_singleton ( ) - > viewport_set_texture_mipmap_bias ( viewport , p_texture_mipmap_bias ) ;
2021-11-23 22:16:03 +01:00
}
2022-06-12 01:49:59 +02:00
float Viewport : : get_texture_mipmap_bias ( ) const {
2023-05-12 13:53:15 +02:00
ERR_READ_THREAD_GUARD_V ( 0 ) ;
2022-06-12 01:49:59 +02:00
return texture_mipmap_bias ;
2021-08-19 03:52:06 +02:00
}
2021-07-04 03:43:23 +02:00
# endif // _3D_DISABLED
2021-08-02 19:31:51 +02:00
2022-01-25 04:01:59 +01:00
void Viewport : : _propagate_world_2d_changed ( Node * p_node ) {
if ( p_node ! = this ) {
if ( Object : : cast_to < CanvasItem > ( p_node ) ) {
p_node - > notification ( CanvasItem : : NOTIFICATION_WORLD_2D_CHANGED ) ;
} else {
Viewport * v = Object : : cast_to < Viewport > ( p_node ) ;
if ( v ) {
if ( v - > world_2d . is_valid ( ) ) {
return ;
}
}
}
}
for ( int i = 0 ; i < p_node - > get_child_count ( ) ; + + i ) {
_propagate_world_2d_changed ( p_node - > get_child ( i ) ) ;
}
}
2021-08-02 19:31:51 +02:00
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 ) ;
ClassDB : : bind_method ( D_METHOD ( " find_world_2d " ) , & Viewport : : find_world_2d ) ;
ClassDB : : bind_method ( D_METHOD ( " set_canvas_transform " , " xform " ) , & Viewport : : set_canvas_transform ) ;
ClassDB : : bind_method ( D_METHOD ( " get_canvas_transform " ) , & Viewport : : get_canvas_transform ) ;
ClassDB : : bind_method ( D_METHOD ( " set_global_canvas_transform " , " xform " ) , & Viewport : : set_global_canvas_transform ) ;
ClassDB : : bind_method ( D_METHOD ( " get_global_canvas_transform " ) , & Viewport : : get_global_canvas_transform ) ;
ClassDB : : bind_method ( D_METHOD ( " get_final_transform " ) , & Viewport : : get_final_transform ) ;
2022-10-15 21:02:58 +02:00
ClassDB : : bind_method ( D_METHOD ( " get_screen_transform " ) , & Viewport : : get_screen_transform ) ;
2021-08-02 19:31:51 +02:00
ClassDB : : bind_method ( D_METHOD ( " get_visible_rect " ) , & Viewport : : get_visible_rect ) ;
ClassDB : : bind_method ( D_METHOD ( " set_transparent_background " , " enable " ) , & Viewport : : set_transparent_background ) ;
ClassDB : : bind_method ( D_METHOD ( " has_transparent_background " ) , & Viewport : : has_transparent_background ) ;
2023-08-03 14:10:01 +02:00
ClassDB : : bind_method ( D_METHOD ( " set_use_hdr_2d " , " enable " ) , & Viewport : : set_use_hdr_2d ) ;
ClassDB : : bind_method ( D_METHOD ( " is_using_hdr_2d " ) , & Viewport : : is_using_hdr_2d ) ;
2021-08-02 19:31:51 +02:00
2022-08-13 01:02:32 +02:00
ClassDB : : bind_method ( D_METHOD ( " set_msaa_2d " , " msaa " ) , & Viewport : : set_msaa_2d ) ;
ClassDB : : bind_method ( D_METHOD ( " get_msaa_2d " ) , & Viewport : : get_msaa_2d ) ;
ClassDB : : bind_method ( D_METHOD ( " set_msaa_3d " , " msaa " ) , & Viewport : : set_msaa_3d ) ;
ClassDB : : bind_method ( D_METHOD ( " get_msaa_3d " ) , & Viewport : : get_msaa_3d ) ;
2021-08-02 19:31:51 +02:00
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 ) ;
2022-04-04 16:10:22 +02:00
ClassDB : : bind_method ( D_METHOD ( " set_use_taa " , " enable " ) , & Viewport : : set_use_taa ) ;
ClassDB : : bind_method ( D_METHOD ( " is_using_taa " ) , & Viewport : : is_using_taa ) ;
2021-08-02 19:31:51 +02:00
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_use_occlusion_culling " , " enable " ) , & Viewport : : set_use_occlusion_culling ) ;
ClassDB : : bind_method ( D_METHOD ( " is_using_occlusion_culling " ) , & Viewport : : is_using_occlusion_culling ) ;
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 ) ;
ClassDB : : bind_method ( D_METHOD ( " get_render_info " , " type " , " info " ) , & Viewport : : get_render_info ) ;
ClassDB : : bind_method ( D_METHOD ( " get_texture " ) , & Viewport : : get_texture ) ;
ClassDB : : bind_method ( D_METHOD ( " set_physics_object_picking " , " enable " ) , & Viewport : : set_physics_object_picking ) ;
ClassDB : : bind_method ( D_METHOD ( " get_physics_object_picking " ) , & Viewport : : get_physics_object_picking ) ;
2022-11-10 22:55:57 +01:00
ClassDB : : bind_method ( D_METHOD ( " set_physics_object_picking_sort " , " enable " ) , & Viewport : : set_physics_object_picking_sort ) ;
ClassDB : : bind_method ( D_METHOD ( " get_physics_object_picking_sort " ) , & Viewport : : get_physics_object_picking_sort ) ;
2023-04-04 19:04:49 +02:00
ClassDB : : bind_method ( D_METHOD ( " set_physics_object_picking_first_only " , " enable " ) , & Viewport : : set_physics_object_picking_first_only ) ;
ClassDB : : bind_method ( D_METHOD ( " get_physics_object_picking_first_only " ) , & Viewport : : get_physics_object_picking_first_only ) ;
2021-08-02 19:31:51 +02:00
ClassDB : : bind_method ( D_METHOD ( " get_viewport_rid " ) , & Viewport : : get_viewport_rid ) ;
2021-08-22 17:37:22 +02:00
ClassDB : : bind_method ( D_METHOD ( " push_text_input " , " text " ) , & Viewport : : push_text_input ) ;
ClassDB : : bind_method ( D_METHOD ( " push_input " , " event " , " in_local_coords " ) , & Viewport : : push_input , DEFVAL ( false ) ) ;
2023-05-10 21:51:50 +02:00
# ifndef DISABLE_DEPRECATED
2021-08-22 17:37:22 +02:00
ClassDB : : bind_method ( D_METHOD ( " push_unhandled_input " , " event " , " in_local_coords " ) , & Viewport : : push_unhandled_input , DEFVAL ( false ) ) ;
2023-05-10 21:51:50 +02:00
# endif // DISABLE_DEPRECATED
2021-08-02 19:31:51 +02:00
2017-03-29 17:29:38 +02:00
ClassDB : : bind_method ( D_METHOD ( " get_mouse_position " ) , & Viewport : : get_mouse_position ) ;
2022-03-27 11:17:36 +02:00
ClassDB : : bind_method ( D_METHOD ( " warp_mouse " , " position " ) , & Viewport : : warp_mouse ) ;
2022-09-29 23:45:51 +02:00
ClassDB : : bind_method ( D_METHOD ( " update_mouse_cursor_state " ) , & Viewport : : update_mouse_cursor_state ) ;
2014-02-26 14:08:17 +01:00
2017-08-09 13:19:41 +02:00
ClassDB : : bind_method ( D_METHOD ( " gui_get_drag_data " ) , & Viewport : : gui_get_drag_data ) ;
2018-08-24 15:29:27 +02:00
ClassDB : : bind_method ( D_METHOD ( " gui_is_dragging " ) , & Viewport : : gui_is_dragging ) ;
2021-10-28 09:07:18 +02:00
ClassDB : : bind_method ( D_METHOD ( " gui_is_drag_successful " ) , & Viewport : : gui_is_drag_successful ) ;
2016-01-17 02:41:10 +01:00
2022-02-01 15:07:22 +01:00
ClassDB : : bind_method ( D_METHOD ( " gui_release_focus " ) , & Viewport : : gui_release_focus ) ;
ClassDB : : bind_method ( D_METHOD ( " gui_get_focus_owner " ) , & Viewport : : gui_get_focus_owner ) ;
2023-12-18 14:50:21 +01:00
ClassDB : : bind_method ( D_METHOD ( " gui_get_hovered_control " ) , & Viewport : : gui_get_hovered_control ) ;
2022-02-01 15:07:22 +01:00
2017-02-13 12:47:24 +01:00
ClassDB : : bind_method ( D_METHOD ( " set_disable_input " , " disable " ) , & Viewport : : set_disable_input ) ;
ClassDB : : bind_method ( D_METHOD ( " is_input_disabled " ) , & Viewport : : is_input_disabled ) ;
2016-01-17 02:41:10 +01:00
2020-07-01 15:59:42 +02:00
ClassDB : : bind_method ( D_METHOD ( " _gui_remove_focus_for_window " ) , & Viewport : : _gui_remove_focus_for_window ) ;
2016-01-17 02:41:10 +01:00
2022-05-01 01:40:30 +02:00
ClassDB : : bind_method ( D_METHOD ( " set_positional_shadow_atlas_size " , " size " ) , & Viewport : : set_positional_shadow_atlas_size ) ;
ClassDB : : bind_method ( D_METHOD ( " get_positional_shadow_atlas_size " ) , & Viewport : : get_positional_shadow_atlas_size ) ;
2016-11-10 03:55:06 +01:00
2022-05-01 01:40:30 +02:00
ClassDB : : bind_method ( D_METHOD ( " set_positional_shadow_atlas_16_bits " , " enable " ) , & Viewport : : set_positional_shadow_atlas_16_bits ) ;
ClassDB : : bind_method ( D_METHOD ( " get_positional_shadow_atlas_16_bits " ) , & Viewport : : get_positional_shadow_atlas_16_bits ) ;
2021-01-24 20:00:20 +01:00
2017-09-07 16:22:07 +02:00
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 ) ;
2020-10-29 22:09:16 +01:00
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 ) ;
2022-05-01 01:40:30 +02:00
ClassDB : : bind_method ( D_METHOD ( " set_positional_shadow_atlas_quadrant_subdiv " , " quadrant " , " subdiv " ) , & Viewport : : set_positional_shadow_atlas_quadrant_subdiv ) ;
ClassDB : : bind_method ( D_METHOD ( " get_positional_shadow_atlas_quadrant_subdiv " , " quadrant " ) , & Viewport : : get_positional_shadow_atlas_quadrant_subdiv ) ;
2016-11-10 03:55:06 +01:00
2018-11-15 17:54:26 +01:00
ClassDB : : bind_method ( D_METHOD ( " set_input_as_handled " ) , & Viewport : : set_input_as_handled ) ;
ClassDB : : bind_method ( D_METHOD ( " is_input_handled " ) , & Viewport : : is_input_handled ) ;
ClassDB : : bind_method ( D_METHOD ( " set_handle_input_locally " , " enable " ) , & Viewport : : set_handle_input_locally ) ;
ClassDB : : bind_method ( D_METHOD ( " is_handling_input_locally " ) , & Viewport : : is_handling_input_locally ) ;
2019-06-25 03:24:07 +02:00
ClassDB : : bind_method ( D_METHOD ( " set_default_canvas_item_texture_filter " , " mode " ) , & Viewport : : set_default_canvas_item_texture_filter ) ;
ClassDB : : bind_method ( D_METHOD ( " get_default_canvas_item_texture_filter " ) , & Viewport : : get_default_canvas_item_texture_filter ) ;
2022-03-13 16:18:44 +01:00
ClassDB : : bind_method ( D_METHOD ( " set_embedding_subwindows " , " enable " ) , & Viewport : : set_embedding_subwindows ) ;
2020-03-04 02:51:12 +01:00
ClassDB : : bind_method ( D_METHOD ( " is_embedding_subwindows " ) , & Viewport : : is_embedding_subwindows ) ;
2023-08-16 03:06:15 +02:00
ClassDB : : bind_method ( D_METHOD ( " get_embedded_subwindows " ) , & Viewport : : get_embedded_subwindows ) ;
2020-03-04 02:51:12 +01:00
2021-09-02 20:07:04 +02:00
ClassDB : : bind_method ( D_METHOD ( " set_canvas_cull_mask " , " mask " ) , & Viewport : : set_canvas_cull_mask ) ;
ClassDB : : bind_method ( D_METHOD ( " get_canvas_cull_mask " ) , & Viewport : : get_canvas_cull_mask ) ;
ClassDB : : bind_method ( D_METHOD ( " set_canvas_cull_mask_bit " , " layer " , " enable " ) , & Viewport : : set_canvas_cull_mask_bit ) ;
ClassDB : : bind_method ( D_METHOD ( " get_canvas_cull_mask_bit " , " layer " ) , & Viewport : : get_canvas_cull_mask_bit ) ;
2019-06-25 03:24:07 +02:00
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 ) ;
2020-11-26 13:50:21 +01:00
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 ) ;
2021-12-29 00:10:41 +01:00
ClassDB : : bind_method ( D_METHOD ( " set_mesh_lod_threshold " , " pixels " ) , & Viewport : : set_mesh_lod_threshold ) ;
ClassDB : : bind_method ( D_METHOD ( " get_mesh_lod_threshold " ) , & Viewport : : get_mesh_lod_threshold ) ;
2020-12-17 19:56:59 +01:00
2021-02-06 21:14:35 +01:00
ClassDB : : bind_method ( D_METHOD ( " _process_picking " ) , & Viewport : : _process_picking ) ;
2023-07-08 05:57:31 +02:00
ClassDB : : bind_method ( D_METHOD ( " set_as_audio_listener_2d " , " enable " ) , & Viewport : : set_as_audio_listener_2d ) ;
ClassDB : : bind_method ( D_METHOD ( " is_audio_listener_2d " ) , & Viewport : : is_audio_listener_2d ) ;
ClassDB : : bind_method ( D_METHOD ( " get_camera_2d " ) , & Viewport : : get_camera_2d ) ;
2021-07-04 03:43:23 +02:00
# ifndef _3D_DISABLED
2021-08-02 19:31:51 +02:00
ClassDB : : bind_method ( D_METHOD ( " set_world_3d " , " world_3d " ) , & Viewport : : set_world_3d ) ;
ClassDB : : bind_method ( D_METHOD ( " get_world_3d " ) , & Viewport : : get_world_3d ) ;
ClassDB : : bind_method ( D_METHOD ( " find_world_3d " ) , & Viewport : : find_world_3d ) ;
ClassDB : : bind_method ( D_METHOD ( " set_use_own_world_3d " , " enable " ) , & Viewport : : set_use_own_world_3d ) ;
ClassDB : : bind_method ( D_METHOD ( " is_using_own_world_3d " ) , & Viewport : : is_using_own_world_3d ) ;
ClassDB : : bind_method ( D_METHOD ( " get_camera_3d " ) , & Viewport : : get_camera_3d ) ;
ClassDB : : bind_method ( D_METHOD ( " set_as_audio_listener_3d " , " enable " ) , & Viewport : : set_as_audio_listener_3d ) ;
ClassDB : : bind_method ( D_METHOD ( " is_audio_listener_3d " ) , & Viewport : : is_audio_listener_3d ) ;
ClassDB : : bind_method ( D_METHOD ( " set_disable_3d " , " disable " ) , & Viewport : : set_disable_3d ) ;
ClassDB : : bind_method ( D_METHOD ( " is_3d_disabled " ) , & Viewport : : is_3d_disabled ) ;
ClassDB : : bind_method ( D_METHOD ( " set_use_xr " , " use " ) , & Viewport : : set_use_xr ) ;
ClassDB : : bind_method ( D_METHOD ( " is_using_xr " ) , & Viewport : : is_using_xr ) ;
2021-11-23 22:16:03 +01:00
ClassDB : : bind_method ( D_METHOD ( " set_scaling_3d_mode " , " scaling_3d_mode " ) , & Viewport : : set_scaling_3d_mode ) ;
ClassDB : : bind_method ( D_METHOD ( " get_scaling_3d_mode " ) , & Viewport : : get_scaling_3d_mode ) ;
ClassDB : : bind_method ( D_METHOD ( " set_scaling_3d_scale " , " scale " ) , & Viewport : : set_scaling_3d_scale ) ;
ClassDB : : bind_method ( D_METHOD ( " get_scaling_3d_scale " ) , & Viewport : : get_scaling_3d_scale ) ;
ClassDB : : bind_method ( D_METHOD ( " set_fsr_sharpness " , " fsr_sharpness " ) , & Viewport : : set_fsr_sharpness ) ;
ClassDB : : bind_method ( D_METHOD ( " get_fsr_sharpness " ) , & Viewport : : get_fsr_sharpness ) ;
2022-06-12 01:49:59 +02:00
ClassDB : : bind_method ( D_METHOD ( " set_texture_mipmap_bias " , " texture_mipmap_bias " ) , & Viewport : : set_texture_mipmap_bias ) ;
ClassDB : : bind_method ( D_METHOD ( " get_texture_mipmap_bias " ) , & Viewport : : get_texture_mipmap_bias ) ;
2021-08-19 03:52:06 +02:00
2022-02-11 12:33:54 +01:00
ClassDB : : bind_method ( D_METHOD ( " set_vrs_mode " , " mode " ) , & Viewport : : set_vrs_mode ) ;
ClassDB : : bind_method ( D_METHOD ( " get_vrs_mode " ) , & Viewport : : get_vrs_mode ) ;
2024-03-26 02:57:26 +01:00
ClassDB : : bind_method ( D_METHOD ( " set_vrs_update_mode " , " mode " ) , & Viewport : : set_vrs_update_mode ) ;
ClassDB : : bind_method ( D_METHOD ( " get_vrs_update_mode " ) , & Viewport : : get_vrs_update_mode ) ;
2022-02-11 12:33:54 +01:00
ClassDB : : bind_method ( D_METHOD ( " set_vrs_texture " , " texture " ) , & Viewport : : set_vrs_texture ) ;
ClassDB : : bind_method ( D_METHOD ( " get_vrs_texture " ) , & Viewport : : get_vrs_texture ) ;
2021-08-02 19:31:51 +02:00
ADD_PROPERTY ( PropertyInfo ( Variant : : BOOL , " disable_3d " ) , " set_disable_3d " , " is_3d_disabled " ) ;
2021-04-29 03:23:24 +02:00
ADD_PROPERTY ( PropertyInfo ( Variant : : BOOL , " use_xr " ) , " set_use_xr " , " is_using_xr " ) ;
2020-04-18 11:00:51 +02:00
ADD_PROPERTY ( PropertyInfo ( Variant : : BOOL , " own_world_3d " ) , " set_use_own_world_3d " , " is_using_own_world_3d " ) ;
2020-05-04 16:55:01 +02:00
ADD_PROPERTY ( PropertyInfo ( Variant : : OBJECT , " world_3d " , PROPERTY_HINT_RESOURCE_TYPE , " World3D " ) , " set_world_3d " , " get_world_3d " ) ;
2021-07-04 03:43:23 +02:00
# endif // _3D_DISABLED
2021-06-18 01:10:18 +02:00
ADD_PROPERTY ( PropertyInfo ( Variant : : OBJECT , " world_2d " , PROPERTY_HINT_RESOURCE_TYPE , " World2D " , PROPERTY_USAGE_NONE ) , " set_world_2d " , " get_world_2d " ) ;
2017-02-12 01:11:37 +01:00
ADD_PROPERTY ( PropertyInfo ( Variant : : BOOL , " transparent_bg " ) , " set_transparent_background " , " has_transparent_background " ) ;
2018-11-15 17:54:26 +01:00
ADD_PROPERTY ( PropertyInfo ( Variant : : BOOL , " handle_input_locally " ) , " set_handle_input_locally " , " is_handling_input_locally " ) ;
2020-10-29 22:09:16 +01:00
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 " ) ;
2017-01-04 05:16:14 +01:00
ADD_GROUP ( " Rendering " , " " ) ;
2022-08-13 01:02:32 +02:00
ADD_PROPERTY ( PropertyInfo ( Variant : : INT , " msaa_2d " , PROPERTY_HINT_ENUM , String : : utf8 ( " Disabled (Fastest),2× (Average),4× (Slow),8× (Slowest) " ) ) , " set_msaa_2d " , " get_msaa_2d " ) ;
ADD_PROPERTY ( PropertyInfo ( Variant : : INT , " msaa_3d " , PROPERTY_HINT_ENUM , String : : utf8 ( " Disabled (Fastest),2× (Average),4× (Slow),8× (Slowest) " ) ) , " set_msaa_3d " , " get_msaa_3d " ) ;
2021-05-22 04:30:58 +02:00
ADD_PROPERTY ( PropertyInfo ( Variant : : INT , " screen_space_aa " , PROPERTY_HINT_ENUM , " Disabled (Fastest),FXAA (Fast) " ) , " set_screen_space_aa " , " get_screen_space_aa " ) ;
2022-04-04 16:10:22 +02:00
ADD_PROPERTY ( PropertyInfo ( Variant : : BOOL , " use_taa " ) , " set_use_taa " , " is_using_taa " ) ;
2020-04-20 23:34:47 +02:00
ADD_PROPERTY ( PropertyInfo ( Variant : : BOOL , " use_debanding " ) , " set_use_debanding " , " is_using_debanding " ) ;
2021-04-20 18:40:24 +02:00
ADD_PROPERTY ( PropertyInfo ( Variant : : BOOL , " use_occlusion_culling " ) , " set_use_occlusion_culling " , " is_using_occlusion_culling " ) ;
2021-12-29 00:10:41 +01:00
ADD_PROPERTY ( PropertyInfo ( Variant : : FLOAT , " mesh_lod_threshold " , PROPERTY_HINT_RANGE , " 0,1024,0.1 " ) , " set_mesh_lod_threshold " , " get_mesh_lod_threshold " ) ;
2024-02-24 08:13:39 +01:00
ADD_PROPERTY ( PropertyInfo ( Variant : : INT , " debug_draw " , PROPERTY_HINT_ENUM , " Disabled,Unshaded,Lighting,Overdraw,Wireframe,Normal Buffer,VoxelGI Albedo,VoxelGI Lighting,VoxelGI Emission,Shadow Atlas,Directional Shadow Map,Scene Luminance,SSAO,SSIL,Directional Shadow Splits,Decal Atlas,SDFGI Cascades,SDFGI Probes,VoxelGI/SDFGI Buffer,Disable Mesh LOD,OmniLight3D Cluster,SpotLight3D Cluster,Decal Cluster,ReflectionProbe Cluster,Occlusion Culling Buffer,Motion Vectors,Internal Buffer " ) , " set_debug_draw " , " get_debug_draw " ) ;
2023-08-03 14:10:01 +02:00
ADD_PROPERTY ( PropertyInfo ( Variant : : BOOL , " use_hdr_2d " ) , " set_use_hdr_2d " , " is_using_hdr_2d " ) ;
2021-11-23 22:16:03 +01:00
# ifndef _3D_DISABLED
ADD_GROUP ( " Scaling 3D " , " " ) ;
2023-09-22 23:38:02 +02:00
ADD_PROPERTY ( PropertyInfo ( Variant : : INT , " scaling_3d_mode " , PROPERTY_HINT_ENUM , " Bilinear (Fastest),FSR 1.0 (Fast),FSR 2.2 (Slow) " ) , " set_scaling_3d_mode " , " get_scaling_3d_mode " ) ;
2021-11-23 22:16:03 +01:00
ADD_PROPERTY ( PropertyInfo ( Variant : : FLOAT , " scaling_3d_scale " , PROPERTY_HINT_RANGE , " 0.25,2.0,0.01 " ) , " set_scaling_3d_scale " , " get_scaling_3d_scale " ) ;
2022-06-12 01:49:59 +02:00
ADD_PROPERTY ( PropertyInfo ( Variant : : FLOAT , " texture_mipmap_bias " , PROPERTY_HINT_RANGE , " -2,2,0.001 " ) , " set_texture_mipmap_bias " , " get_texture_mipmap_bias " ) ;
2021-11-23 22:16:03 +01:00
ADD_PROPERTY ( PropertyInfo ( Variant : : FLOAT , " fsr_sharpness " , PROPERTY_HINT_RANGE , " 0,2,0.1 " ) , " set_fsr_sharpness " , " get_fsr_sharpness " ) ;
2022-02-11 12:33:54 +01:00
ADD_GROUP ( " Variable Rate Shading " , " vrs_ " ) ;
ADD_PROPERTY ( PropertyInfo ( Variant : : INT , " vrs_mode " , PROPERTY_HINT_ENUM , " Disabled,Texture,Depth buffer,XR " ) , " set_vrs_mode " , " get_vrs_mode " ) ;
2024-03-26 02:57:26 +01:00
ADD_PROPERTY ( PropertyInfo ( Variant : : INT , " vrs_update_mode " , PROPERTY_HINT_ENUM , " Disabled,Once,Always " ) , " set_vrs_update_mode " , " get_vrs_update_mode " ) ;
2022-02-11 12:33:54 +01:00
ADD_PROPERTY ( PropertyInfo ( Variant : : OBJECT , " vrs_texture " , PROPERTY_HINT_RESOURCE_TYPE , " Texture2D " ) , " set_vrs_texture " , " get_vrs_texture " ) ;
2024-02-23 12:52:06 +01:00
# endif
2019-06-25 03:24:07 +02:00
ADD_GROUP ( " Canvas Items " , " canvas_item_ " ) ;
2020-02-29 18:04:28 +01:00
ADD_PROPERTY ( PropertyInfo ( Variant : : INT , " canvas_item_default_texture_filter " , PROPERTY_HINT_ENUM , " Nearest,Linear,Linear Mipmap,Nearest Mipmap " ) , " set_default_canvas_item_texture_filter " , " get_default_canvas_item_texture_filter " ) ;
2019-06-25 03:24:07 +02:00
ADD_PROPERTY ( PropertyInfo ( Variant : : INT , " canvas_item_default_texture_repeat " , PROPERTY_HINT_ENUM , " Disabled,Enabled,Mirror " ) , " set_default_canvas_item_texture_repeat " , " get_default_canvas_item_texture_repeat " ) ;
2017-01-04 05:16:14 +01:00
ADD_GROUP ( " Audio Listener " , " audio_listener_ " ) ;
2017-02-12 01:11:37 +01:00
ADD_PROPERTY ( PropertyInfo ( Variant : : BOOL , " audio_listener_enable_2d " ) , " set_as_audio_listener_2d " , " is_audio_listener_2d " ) ;
2022-04-15 21:27:39 +02:00
# ifndef _3D_DISABLED
ADD_PROPERTY ( PropertyInfo ( Variant : : BOOL , " audio_listener_enable_3d " ) , " set_as_audio_listener_3d " , " is_audio_listener_3d " ) ;
2023-07-08 05:57:31 +02:00
# endif // _3D_DISABLED
2017-01-04 05:16:14 +01:00
ADD_GROUP ( " Physics " , " physics_ " ) ;
2017-02-12 01:11:37 +01:00
ADD_PROPERTY ( PropertyInfo ( Variant : : BOOL , " physics_object_picking " ) , " set_physics_object_picking " , " get_physics_object_picking " ) ;
2022-11-10 22:55:57 +01:00
ADD_PROPERTY ( PropertyInfo ( Variant : : BOOL , " physics_object_picking_sort " ) , " set_physics_object_picking_sort " , " get_physics_object_picking_sort " ) ;
2023-04-04 19:04:49 +02:00
ADD_PROPERTY ( PropertyInfo ( Variant : : BOOL , " physics_object_picking_first_only " ) , " set_physics_object_picking_first_only " , " get_physics_object_picking_first_only " ) ;
2017-01-04 05:16:14 +01:00
ADD_GROUP ( " GUI " , " gui_ " ) ;
2017-02-12 01:11:37 +01:00
ADD_PROPERTY ( PropertyInfo ( Variant : : BOOL , " gui_disable_input " ) , " set_disable_input " , " is_input_disabled " ) ;
2017-09-07 16:22:07 +02:00
ADD_PROPERTY ( PropertyInfo ( Variant : : BOOL , " gui_snap_controls_to_pixels " ) , " set_snap_controls_to_pixels " , " is_snap_controls_to_pixels_enabled " ) ;
2022-03-13 16:18:44 +01:00
ADD_PROPERTY ( PropertyInfo ( Variant : : BOOL , " gui_embed_subwindows " ) , " set_embedding_subwindows " , " is_embedding_subwindows " ) ;
2020-11-26 13:50:21 +01:00
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 " ) ;
2022-05-01 01:40:30 +02:00
ADD_GROUP ( " Positional Shadow Atlas " , " positional_shadow_atlas_ " ) ;
ADD_PROPERTY ( PropertyInfo ( Variant : : INT , " positional_shadow_atlas_size " ) , " set_positional_shadow_atlas_size " , " get_positional_shadow_atlas_size " ) ;
ADD_PROPERTY ( PropertyInfo ( Variant : : BOOL , " positional_shadow_atlas_16_bits " ) , " set_positional_shadow_atlas_16_bits " , " get_positional_shadow_atlas_16_bits " ) ;
ADD_PROPERTYI ( PropertyInfo ( Variant : : INT , " positional_shadow_atlas_quad_0 " , PROPERTY_HINT_ENUM , " Disabled,1 Shadow,4 Shadows,16 Shadows,64 Shadows,256 Shadows,1024 Shadows " ) , " set_positional_shadow_atlas_quadrant_subdiv " , " get_positional_shadow_atlas_quadrant_subdiv " , 0 ) ;
ADD_PROPERTYI ( PropertyInfo ( Variant : : INT , " positional_shadow_atlas_quad_1 " , PROPERTY_HINT_ENUM , " Disabled,1 Shadow,4 Shadows,16 Shadows,64 Shadows,256 Shadows,1024 Shadows " ) , " set_positional_shadow_atlas_quadrant_subdiv " , " get_positional_shadow_atlas_quadrant_subdiv " , 1 ) ;
ADD_PROPERTYI ( PropertyInfo ( Variant : : INT , " positional_shadow_atlas_quad_2 " , PROPERTY_HINT_ENUM , " Disabled,1 Shadow,4 Shadows,16 Shadows,64 Shadows,256 Shadows,1024 Shadows " ) , " set_positional_shadow_atlas_quadrant_subdiv " , " get_positional_shadow_atlas_quadrant_subdiv " , 2 ) ;
ADD_PROPERTYI ( PropertyInfo ( Variant : : INT , " positional_shadow_atlas_quad_3 " , PROPERTY_HINT_ENUM , " Disabled,1 Shadow,4 Shadows,16 Shadows,64 Shadows,256 Shadows,1024 Shadows " ) , " set_positional_shadow_atlas_quadrant_subdiv " , " get_positional_shadow_atlas_quadrant_subdiv " , 3 ) ;
2021-06-18 01:10:18 +02:00
ADD_PROPERTY ( PropertyInfo ( Variant : : TRANSFORM2D , " canvas_transform " , PROPERTY_HINT_NONE , " " , PROPERTY_USAGE_NONE ) , " set_canvas_transform " , " get_canvas_transform " ) ;
ADD_PROPERTY ( PropertyInfo ( Variant : : TRANSFORM2D , " global_canvas_transform " , PROPERTY_HINT_NONE , " " , PROPERTY_USAGE_NONE ) , " set_global_canvas_transform " , " get_global_canvas_transform " ) ;
2021-09-02 20:07:04 +02:00
ADD_PROPERTY ( PropertyInfo ( Variant : : INT , " canvas_cull_mask " , PROPERTY_HINT_LAYERS_2D_RENDER ) , " set_canvas_cull_mask " , " get_canvas_cull_mask " ) ;
2014-02-10 02:10:30 +01:00
ADD_SIGNAL ( MethodInfo ( " size_changed " ) ) ;
2019-12-11 14:29:36 +01:00
ADD_SIGNAL ( MethodInfo ( " gui_focus_changed " , PropertyInfo ( Variant : : OBJECT , " node " , PROPERTY_HINT_RESOURCE_TYPE , " Control " ) ) ) ;
2014-02-26 14:08:17 +01:00
2017-08-20 17:45:01 +02:00
BIND_ENUM_CONSTANT ( SHADOW_ATLAS_QUADRANT_SUBDIV_DISABLED ) ;
BIND_ENUM_CONSTANT ( SHADOW_ATLAS_QUADRANT_SUBDIV_1 ) ;
BIND_ENUM_CONSTANT ( SHADOW_ATLAS_QUADRANT_SUBDIV_4 ) ;
BIND_ENUM_CONSTANT ( SHADOW_ATLAS_QUADRANT_SUBDIV_16 ) ;
BIND_ENUM_CONSTANT ( SHADOW_ATLAS_QUADRANT_SUBDIV_64 ) ;
BIND_ENUM_CONSTANT ( SHADOW_ATLAS_QUADRANT_SUBDIV_256 ) ;
BIND_ENUM_CONSTANT ( SHADOW_ATLAS_QUADRANT_SUBDIV_1024 ) ;
BIND_ENUM_CONSTANT ( SHADOW_ATLAS_QUADRANT_SUBDIV_MAX ) ;
2021-11-23 22:16:03 +01:00
BIND_ENUM_CONSTANT ( SCALING_3D_MODE_BILINEAR ) ;
BIND_ENUM_CONSTANT ( SCALING_3D_MODE_FSR ) ;
2023-09-22 23:38:02 +02:00
BIND_ENUM_CONSTANT ( SCALING_3D_MODE_FSR2 ) ;
2021-11-23 22:16:03 +01:00
BIND_ENUM_CONSTANT ( SCALING_3D_MODE_MAX ) ;
2020-04-20 11:48:00 +02:00
BIND_ENUM_CONSTANT ( MSAA_DISABLED ) ;
BIND_ENUM_CONSTANT ( MSAA_2X ) ;
BIND_ENUM_CONSTANT ( MSAA_4X ) ;
BIND_ENUM_CONSTANT ( MSAA_8X ) ;
BIND_ENUM_CONSTANT ( MSAA_MAX ) ;
BIND_ENUM_CONSTANT ( SCREEN_SPACE_AA_DISABLED ) ;
BIND_ENUM_CONSTANT ( SCREEN_SPACE_AA_FXAA ) ;
BIND_ENUM_CONSTANT ( SCREEN_SPACE_AA_MAX ) ;
2017-08-20 17:45:01 +02:00
BIND_ENUM_CONSTANT ( RENDER_INFO_OBJECTS_IN_FRAME ) ;
2021-07-03 01:14:19 +02:00
BIND_ENUM_CONSTANT ( RENDER_INFO_PRIMITIVES_IN_FRAME ) ;
2017-08-20 17:45:01 +02:00
BIND_ENUM_CONSTANT ( RENDER_INFO_DRAW_CALLS_IN_FRAME ) ;
BIND_ENUM_CONSTANT ( RENDER_INFO_MAX ) ;
2021-07-03 01:14:19 +02:00
BIND_ENUM_CONSTANT ( RENDER_INFO_TYPE_VISIBLE ) ;
BIND_ENUM_CONSTANT ( RENDER_INFO_TYPE_SHADOW ) ;
2024-03-23 14:02:59 +01:00
BIND_ENUM_CONSTANT ( RENDER_INFO_TYPE_CANVAS ) ;
2021-07-03 01:14:19 +02:00
BIND_ENUM_CONSTANT ( RENDER_INFO_TYPE_MAX ) ;
2017-08-20 17:45:01 +02:00
BIND_ENUM_CONSTANT ( DEBUG_DRAW_DISABLED ) ;
BIND_ENUM_CONSTANT ( DEBUG_DRAW_UNSHADED ) ;
2020-04-20 11:48:00 +02:00
BIND_ENUM_CONSTANT ( DEBUG_DRAW_LIGHTING ) ;
2017-08-20 17:45:01 +02:00
BIND_ENUM_CONSTANT ( DEBUG_DRAW_OVERDRAW ) ;
BIND_ENUM_CONSTANT ( DEBUG_DRAW_WIREFRAME ) ;
2020-04-20 11:48:00 +02:00
BIND_ENUM_CONSTANT ( DEBUG_DRAW_NORMAL_BUFFER ) ;
2021-06-05 00:47:26 +02:00
BIND_ENUM_CONSTANT ( DEBUG_DRAW_VOXEL_GI_ALBEDO ) ;
BIND_ENUM_CONSTANT ( DEBUG_DRAW_VOXEL_GI_LIGHTING ) ;
BIND_ENUM_CONSTANT ( DEBUG_DRAW_VOXEL_GI_EMISSION ) ;
2020-01-12 02:26:52 +01:00
BIND_ENUM_CONSTANT ( DEBUG_DRAW_SHADOW_ATLAS ) ;
BIND_ENUM_CONSTANT ( DEBUG_DRAW_DIRECTIONAL_SHADOW_ATLAS ) ;
BIND_ENUM_CONSTANT ( DEBUG_DRAW_SCENE_LUMINANCE ) ;
2020-01-25 11:18:55 +01:00
BIND_ENUM_CONSTANT ( DEBUG_DRAW_SSAO ) ;
2021-08-03 09:07:32 +02:00
BIND_ENUM_CONSTANT ( DEBUG_DRAW_SSIL ) ;
2020-04-08 03:51:52 +02:00
BIND_ENUM_CONSTANT ( DEBUG_DRAW_PSSM_SPLITS ) ;
2020-04-14 05:05:21 +02:00
BIND_ENUM_CONSTANT ( DEBUG_DRAW_DECAL_ATLAS ) ;
2020-06-25 15:33:28 +02:00
BIND_ENUM_CONSTANT ( DEBUG_DRAW_SDFGI ) ;
BIND_ENUM_CONSTANT ( DEBUG_DRAW_SDFGI_PROBES ) ;
BIND_ENUM_CONSTANT ( DEBUG_DRAW_GI_BUFFER ) ;
2020-12-17 19:56:59 +01:00
BIND_ENUM_CONSTANT ( DEBUG_DRAW_DISABLE_LOD ) ;
2021-01-17 17:25:38 +01:00
BIND_ENUM_CONSTANT ( DEBUG_DRAW_CLUSTER_OMNI_LIGHTS ) ;
BIND_ENUM_CONSTANT ( DEBUG_DRAW_CLUSTER_SPOT_LIGHTS ) ;
BIND_ENUM_CONSTANT ( DEBUG_DRAW_CLUSTER_DECALS ) ;
BIND_ENUM_CONSTANT ( DEBUG_DRAW_CLUSTER_REFLECTION_PROBES ) ;
2021-04-20 18:40:24 +02:00
BIND_ENUM_CONSTANT ( DEBUG_DRAW_OCCLUDERS )
2022-04-04 16:10:22 +02:00
BIND_ENUM_CONSTANT ( DEBUG_DRAW_MOTION_VECTORS )
2023-09-22 23:38:02 +02:00
BIND_ENUM_CONSTANT ( DEBUG_DRAW_INTERNAL_BUFFER ) ;
2020-01-12 02:26:52 +01:00
2019-06-25 03:24:07 +02:00
BIND_ENUM_CONSTANT ( DEFAULT_CANVAS_ITEM_TEXTURE_FILTER_NEAREST ) ;
BIND_ENUM_CONSTANT ( DEFAULT_CANVAS_ITEM_TEXTURE_FILTER_LINEAR ) ;
BIND_ENUM_CONSTANT ( DEFAULT_CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS ) ;
2020-02-20 00:31:43 +01:00
BIND_ENUM_CONSTANT ( DEFAULT_CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS ) ;
2019-06-25 03:24:07 +02:00
BIND_ENUM_CONSTANT ( DEFAULT_CANVAS_ITEM_TEXTURE_FILTER_MAX ) ;
2020-04-20 11:48:00 +02:00
2019-06-25 03:24:07 +02:00
BIND_ENUM_CONSTANT ( DEFAULT_CANVAS_ITEM_TEXTURE_REPEAT_DISABLED ) ;
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 ) ;
2020-11-26 13:50:21 +01:00
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 ) ;
2022-02-11 12:33:54 +01:00
BIND_ENUM_CONSTANT ( VRS_DISABLED ) ;
BIND_ENUM_CONSTANT ( VRS_TEXTURE ) ;
BIND_ENUM_CONSTANT ( VRS_XR ) ;
BIND_ENUM_CONSTANT ( VRS_MAX ) ;
2024-03-26 02:57:26 +01:00
BIND_ENUM_CONSTANT ( VRS_UPDATE_DISABLED ) ;
BIND_ENUM_CONSTANT ( VRS_UPDATE_ONCE ) ;
BIND_ENUM_CONSTANT ( VRS_UPDATE_ALWAYS ) ;
BIND_ENUM_CONSTANT ( VRS_UPDATE_MAX ) ;
2022-02-11 12:33:54 +01:00
}
2022-08-12 22:57:11 +02:00
void Viewport : : _validate_property ( PropertyInfo & p_property ) const {
if ( vrs_mode ! = VRS_TEXTURE & & ( p_property . name = = " vrs_texture " ) ) {
p_property . usage = PROPERTY_USAGE_NO_EDITOR ;
2022-02-11 12:33:54 +01:00
}
2024-03-26 02:57:26 +01:00
if ( vrs_mode = = VRS_DISABLED & & ( p_property . name = = " vrs_update_mode " ) ) {
p_property . usage = PROPERTY_USAGE_NO_EDITOR ;
}
2014-02-10 02:10:30 +01:00
}
Viewport : : Viewport ( ) {
world_2d = Ref < World2D > ( memnew ( World2D ) ) ;
2023-05-03 22:57:15 +02:00
world_2d - > register_viewport ( this ) ;
2014-02-10 02:10:30 +01:00
2020-03-27 19:21:27 +01:00
viewport = RenderingServer : : get_singleton ( ) - > viewport_create ( ) ;
texture_rid = RenderingServer : : get_singleton ( ) - > viewport_get_texture ( viewport ) ;
2017-01-10 22:02:19 +01:00
2021-06-18 00:03:09 +02:00
default_texture . instantiate ( ) ;
2017-01-10 22:02:19 +01:00
default_texture - > vp = const_cast < Viewport * > ( this ) ;
viewport_textures . insert ( default_texture . ptr ( ) ) ;
2020-03-27 19:21:27 +01:00
default_texture - > proxy = RS : : get_singleton ( ) - > texture_proxy_create ( texture_rid ) ;
2017-01-10 22:02:19 +01:00
2021-09-10 16:58:33 +02:00
canvas_layers . insert ( nullptr ) ; // This eases picking code (interpreted as the canvas of the Viewport).
2020-03-04 02:51:12 +01:00
2022-05-01 01:40:30 +02:00
set_positional_shadow_atlas_size ( positional_shadow_atlas_size ) ;
2021-01-24 20:00:20 +01:00
2016-11-10 03:55:06 +01:00
for ( int i = 0 ; i < 4 ; i + + ) {
2022-05-01 01:40:30 +02:00
positional_shadow_atlas_quadrant_subdiv [ i ] = SHADOW_ATLAS_QUADRANT_SUBDIV_MAX ;
2016-11-10 03:55:06 +01:00
}
2022-05-01 01:40:30 +02:00
set_positional_shadow_atlas_quadrant_subdiv ( 0 , SHADOW_ATLAS_QUADRANT_SUBDIV_4 ) ;
set_positional_shadow_atlas_quadrant_subdiv ( 1 , SHADOW_ATLAS_QUADRANT_SUBDIV_4 ) ;
set_positional_shadow_atlas_quadrant_subdiv ( 2 , SHADOW_ATLAS_QUADRANT_SUBDIV_16 ) ;
set_positional_shadow_atlas_quadrant_subdiv ( 3 , SHADOW_ATLAS_QUADRANT_SUBDIV_64 ) ;
2014-04-15 03:43:44 +02:00
2021-12-29 00:10:41 +01:00
set_mesh_lod_threshold ( mesh_lod_threshold ) ;
2020-12-17 19:56:59 +01:00
2017-08-07 12:17:31 +02:00
String id = itos ( get_instance_id ( ) ) ;
2014-04-10 05:18:27 +02:00
input_group = " _vp_input " + id ;
unhandled_input_group = " _vp_unhandled_input " + id ;
2022-01-11 14:59:52 +01:00
shortcut_input_group = " _vp_shortcut_input " + id ;
2014-04-10 05:18:27 +02:00
unhandled_key_input_group = " _vp_unhandled_key_input " + id ;
2014-02-10 02:10:30 +01:00
2020-11-02 17:18:29 +01:00
// Window tooltip.
2023-12-02 18:55:27 +01:00
gui . tooltip_delay = GLOBAL_GET ( " gui/timers/tooltip_delay_sec " ) ;
2016-01-18 23:49:11 +01:00
2021-08-19 03:52:06 +02:00
# ifndef _3D_DISABLED
2022-09-29 11:53:28 +02:00
set_scaling_3d_mode ( ( Viewport : : Scaling3DMode ) ( int ) GLOBAL_GET ( " rendering/scaling_3d/mode " ) ) ;
2021-11-23 22:16:03 +01:00
set_scaling_3d_scale ( GLOBAL_GET ( " rendering/scaling_3d/scale " ) ) ;
2022-09-29 11:53:28 +02:00
set_fsr_sharpness ( ( float ) GLOBAL_GET ( " rendering/scaling_3d/fsr_sharpness " ) ) ;
set_texture_mipmap_bias ( ( float ) GLOBAL_GET ( " rendering/textures/default_filters/texture_mipmap_bias " ) ) ;
2021-08-19 03:52:06 +02:00
# endif // _3D_DISABLED
2021-09-10 16:58:33 +02:00
set_sdf_oversize ( sdf_oversize ) ; // Set to server.
2014-02-10 02:10:30 +01:00
}
Viewport : : ~ Viewport ( ) {
2021-09-10 16:58:33 +02:00
// Erase itself from viewport textures.
2022-05-19 01:43:40 +02:00
for ( ViewportTexture * E : viewport_textures ) {
E - > vp = nullptr ;
2017-01-10 05:04:31 +01:00
}
2022-12-12 18:42:37 +01:00
ERR_FAIL_NULL ( RenderingServer : : get_singleton ( ) ) ;
2020-03-27 19:21:27 +01:00
RenderingServer : : get_singleton ( ) - > free ( viewport ) ;
2014-02-10 02:10:30 +01:00
}
2020-03-04 02:51:12 +01:00
/////////////////////////////////
void SubViewport : : set_size ( const Size2i & p_size ) {
2023-05-12 13:53:15 +02:00
ERR_MAIN_THREAD_GUARD ;
2022-10-04 21:53:18 +02:00
_internal_set_size ( p_size ) ;
}
2020-11-21 22:32:26 +01:00
2022-10-04 21:53:18 +02:00
void SubViewport : : set_size_force ( const Size2i & p_size ) {
2023-05-12 13:53:15 +02:00
ERR_MAIN_THREAD_GUARD ;
2022-10-04 21:53:18 +02:00
// Use only for setting the size from the parent SubViewportContainer with enabled stretch mode.
// Don't expose function to scripting.
_internal_set_size ( p_size , true ) ;
}
void SubViewport : : _internal_set_size ( const Size2i & p_size , bool p_force ) {
2020-11-21 22:32:26 +01:00
SubViewportContainer * c = Object : : cast_to < SubViewportContainer > ( get_parent ( ) ) ;
2022-10-04 21:53:18 +02:00
if ( ! p_force & & c & & c - > is_stretch_enabled ( ) ) {
# ifdef DEBUG_ENABLED
WARN_PRINT ( " Can't change the size of a `SubViewport` with a `SubViewportContainer` parent that has `stretch` enabled. Set `SubViewportContainer.stretch` to `false` to allow changing the size manually. " ) ;
# endif // DEBUG_ENABLED
return ;
}
2023-02-02 19:00:07 +01:00
_set_size ( p_size , _get_size_2d_override ( ) , true ) ;
2022-10-04 21:53:18 +02:00
2020-11-21 22:32:26 +01:00
if ( c ) {
c - > update_minimum_size ( ) ;
}
2020-03-04 02:51:12 +01:00
}
2020-05-14 14:29:06 +02:00
2020-03-04 02:51:12 +01:00
Size2i SubViewport : : get_size ( ) const {
2023-05-12 13:53:15 +02:00
ERR_READ_THREAD_GUARD_V ( Size2 ( ) ) ;
2020-03-04 02:51:12 +01:00
return _get_size ( ) ;
}
2020-04-01 05:47:58 +02:00
void SubViewport : : set_size_2d_override ( const Size2i & p_size ) {
2023-05-12 13:53:15 +02:00
ERR_MAIN_THREAD_GUARD ;
2023-02-02 19:00:07 +01:00
_set_size ( _get_size ( ) , p_size , true ) ;
2020-04-01 05:47:58 +02:00
}
2020-05-14 14:29:06 +02:00
2020-04-01 05:47:58 +02:00
Size2i SubViewport : : get_size_2d_override ( ) const {
2023-05-12 13:53:15 +02:00
ERR_READ_THREAD_GUARD_V ( Size2i ( ) ) ;
2020-04-01 05:47:58 +02:00
return _get_size_2d_override ( ) ;
}
void SubViewport : : set_size_2d_override_stretch ( bool p_enable ) {
2023-05-12 13:53:15 +02:00
ERR_MAIN_THREAD_GUARD ;
2020-04-01 05:47:58 +02:00
if ( p_enable = = size_2d_override_stretch ) {
return ;
}
size_2d_override_stretch = p_enable ;
2023-02-02 19:00:07 +01:00
_set_size ( _get_size ( ) , _get_size_2d_override ( ) , true ) ;
2020-04-01 05:47:58 +02:00
}
2020-05-14 14:29:06 +02:00
2020-04-01 05:47:58 +02:00
bool SubViewport : : is_size_2d_override_stretch_enabled ( ) const {
2023-05-12 13:53:15 +02:00
ERR_READ_THREAD_GUARD_V ( false ) ;
2020-04-01 05:47:58 +02:00
return size_2d_override_stretch ;
}
2020-03-04 02:51:12 +01:00
void SubViewport : : set_update_mode ( UpdateMode p_mode ) {
2023-05-12 13:53:15 +02:00
ERR_MAIN_THREAD_GUARD ;
2020-03-04 02:51:12 +01:00
update_mode = p_mode ;
2020-03-27 19:21:27 +01:00
RS : : get_singleton ( ) - > viewport_set_update_mode ( get_viewport_rid ( ) , RS : : ViewportUpdateMode ( p_mode ) ) ;
2020-03-04 02:51:12 +01:00
}
2020-05-14 14:29:06 +02:00
2020-03-04 02:51:12 +01:00
SubViewport : : UpdateMode SubViewport : : get_update_mode ( ) const {
2023-05-12 13:53:15 +02:00
ERR_READ_THREAD_GUARD_V ( UPDATE_DISABLED ) ;
2020-03-04 02:51:12 +01:00
return update_mode ;
}
void SubViewport : : set_clear_mode ( ClearMode p_mode ) {
2023-05-12 13:53:15 +02:00
ERR_MAIN_THREAD_GUARD ;
2020-03-04 02:51:12 +01:00
clear_mode = p_mode ;
2020-03-27 19:21:27 +01:00
RS : : get_singleton ( ) - > viewport_set_clear_mode ( get_viewport_rid ( ) , RS : : ViewportClearMode ( p_mode ) ) ;
2020-03-04 02:51:12 +01:00
}
2020-05-14 14:29:06 +02:00
2020-03-04 02:51:12 +01:00
SubViewport : : ClearMode SubViewport : : get_clear_mode ( ) const {
2023-05-12 13:53:15 +02:00
ERR_READ_THREAD_GUARD_V ( CLEAR_MODE_ALWAYS ) ;
2020-03-04 02:51:12 +01:00
return clear_mode ;
}
DisplayServer : : WindowID SubViewport : : get_window_id ( ) const {
2023-05-12 13:53:15 +02:00
ERR_READ_THREAD_GUARD_V ( DisplayServer : : INVALID_WINDOW_ID ) ;
2020-03-04 02:51:12 +01:00
return DisplayServer : : INVALID_WINDOW_ID ;
}
2023-01-20 22:33:05 +01:00
Transform2D SubViewport : : get_screen_transform_internal ( bool p_absolute_position ) const {
2023-05-12 13:53:15 +02:00
ERR_READ_THREAD_GUARD_V ( Transform2D ( ) ) ;
2022-11-14 18:21:06 +01:00
Transform2D container_transform ;
2022-03-28 11:01:29 +02:00
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 ( ) ) ) ;
}
2023-01-20 22:33:05 +01:00
container_transform = c - > get_viewport ( ) - > get_screen_transform_internal ( p_absolute_position ) * c - > get_global_transform_with_canvas ( ) * container_transform ;
2022-03-28 11:01:29 +02:00
} else {
WARN_PRINT_ONCE ( " SubViewport is not a child of a SubViewportContainer. get_screen_transform doesn't return the actual screen position. " ) ;
}
2023-02-02 19:28:14 +01:00
return container_transform * get_final_transform ( ) ;
2022-03-28 11:01:29 +02:00
}
2022-11-13 21:38:29 +01:00
Transform2D SubViewport : : get_popup_base_transform ( ) const {
2023-05-12 13:53:15 +02:00
ERR_READ_THREAD_GUARD_V ( Transform2D ( ) ) ;
2022-11-13 21:38:29 +01:00
if ( is_embedding_subwindows ( ) ) {
return Transform2D ( ) ;
}
SubViewportContainer * c = Object : : cast_to < SubViewportContainer > ( get_parent ( ) ) ;
if ( ! c ) {
2023-02-02 19:28:14 +01:00
return get_final_transform ( ) ;
2022-11-13 21:38:29 +01:00
}
Transform2D container_transform ;
if ( c - > is_stretch_enabled ( ) ) {
container_transform . scale ( Vector2 ( c - > get_stretch_shrink ( ) , c - > get_stretch_shrink ( ) ) ) ;
}
2023-02-02 19:28:14 +01:00
return c - > get_screen_transform ( ) * container_transform * get_final_transform ( ) ;
2022-11-13 21:38:29 +01:00
}
2023-06-06 20:42:41 +02:00
bool SubViewport : : is_directly_attached_to_screen ( ) const {
// SubViewports, that are used as Textures are not considered to be directly attached to screen.
return Object : : cast_to < SubViewportContainer > ( get_parent ( ) ) & & get_parent ( ) - > get_viewport ( ) & & get_parent ( ) - > get_viewport ( ) - > is_directly_attached_to_screen ( ) ;
}
2023-01-06 21:48:20 +01:00
bool SubViewport : : is_attached_in_viewport ( ) const {
return Object : : cast_to < SubViewportContainer > ( get_parent ( ) ) ;
}
2020-03-14 17:06:39 +01:00
void SubViewport : : _notification ( int p_what ) {
2023-05-12 13:53:15 +02:00
ERR_MAIN_THREAD_GUARD ;
2022-02-15 18:06:48 +01:00
switch ( p_what ) {
case NOTIFICATION_ENTER_TREE : {
RS : : get_singleton ( ) - > viewport_set_active ( get_viewport_rid ( ) , true ) ;
2023-02-13 00:34:16 +01:00
SubViewportContainer * parent_svc = Object : : cast_to < SubViewportContainer > ( get_parent ( ) ) ;
if ( parent_svc ) {
parent_svc - > recalc_force_viewport_sizes ( ) ;
}
2022-02-15 18:06:48 +01:00
} break ;
case NOTIFICATION_EXIT_TREE : {
RS : : get_singleton ( ) - > viewport_set_active ( get_viewport_rid ( ) , false ) ;
} break ;
2020-03-14 17:06:39 +01:00
}
}
2020-03-04 02:51:12 +01:00
void SubViewport : : _bind_methods ( ) {
ClassDB : : bind_method ( D_METHOD ( " set_size " , " size " ) , & SubViewport : : set_size ) ;
ClassDB : : bind_method ( D_METHOD ( " get_size " ) , & SubViewport : : get_size ) ;
2020-04-01 05:47:58 +02:00
ClassDB : : bind_method ( D_METHOD ( " set_size_2d_override " , " size " ) , & SubViewport : : set_size_2d_override ) ;
ClassDB : : bind_method ( D_METHOD ( " get_size_2d_override " ) , & SubViewport : : get_size_2d_override ) ;
ClassDB : : bind_method ( D_METHOD ( " set_size_2d_override_stretch " , " enable " ) , & SubViewport : : set_size_2d_override_stretch ) ;
ClassDB : : bind_method ( D_METHOD ( " is_size_2d_override_stretch_enabled " ) , & SubViewport : : is_size_2d_override_stretch_enabled ) ;
2020-03-04 02:51:12 +01:00
ClassDB : : bind_method ( D_METHOD ( " set_update_mode " , " mode " ) , & SubViewport : : set_update_mode ) ;
ClassDB : : bind_method ( D_METHOD ( " get_update_mode " ) , & SubViewport : : get_update_mode ) ;
ClassDB : : bind_method ( D_METHOD ( " set_clear_mode " , " mode " ) , & SubViewport : : set_clear_mode ) ;
ClassDB : : bind_method ( D_METHOD ( " get_clear_mode " ) , & SubViewport : : get_clear_mode ) ;
2022-05-20 07:24:41 +02:00
ADD_PROPERTY ( PropertyInfo ( Variant : : VECTOR2I , " size " , PROPERTY_HINT_NONE , " suffix:px " ) , " set_size " , " get_size " ) ;
ADD_PROPERTY ( PropertyInfo ( Variant : : VECTOR2I , " size_2d_override " , PROPERTY_HINT_NONE , " suffix:px " ) , " set_size_2d_override " , " get_size_2d_override " ) ;
2020-04-01 05:47:58 +02:00
ADD_PROPERTY ( PropertyInfo ( Variant : : BOOL , " size_2d_override_stretch " ) , " set_size_2d_override_stretch " , " is_size_2d_override_stretch_enabled " ) ;
2020-03-04 02:51:12 +01:00
ADD_GROUP ( " Render Target " , " render_target_ " ) ;
ADD_PROPERTY ( PropertyInfo ( Variant : : INT , " render_target_clear_mode " , PROPERTY_HINT_ENUM , " Always,Never,Next Frame " ) , " set_clear_mode " , " get_clear_mode " ) ;
2021-10-29 04:42:01 +02:00
ADD_PROPERTY ( PropertyInfo ( Variant : : INT , " render_target_update_mode " , PROPERTY_HINT_ENUM , " Disabled,Once,When Visible,When Parent Visible,Always " ) , " set_update_mode " , " get_update_mode " ) ;
2020-03-04 02:51:12 +01:00
2020-04-20 11:48:00 +02:00
BIND_ENUM_CONSTANT ( CLEAR_MODE_ALWAYS ) ;
BIND_ENUM_CONSTANT ( CLEAR_MODE_NEVER ) ;
2020-12-10 13:19:04 +01:00
BIND_ENUM_CONSTANT ( CLEAR_MODE_ONCE ) ;
2020-04-20 11:48:00 +02:00
2020-03-04 02:51:12 +01:00
BIND_ENUM_CONSTANT ( UPDATE_DISABLED ) ;
BIND_ENUM_CONSTANT ( UPDATE_ONCE ) ;
BIND_ENUM_CONSTANT ( UPDATE_WHEN_VISIBLE ) ;
2020-03-14 17:06:39 +01:00
BIND_ENUM_CONSTANT ( UPDATE_WHEN_PARENT_VISIBLE ) ;
2020-03-04 02:51:12 +01:00
BIND_ENUM_CONSTANT ( UPDATE_ALWAYS ) ;
}
2023-02-13 00:34:16 +01:00
void SubViewport : : _validate_property ( PropertyInfo & p_property ) const {
if ( p_property . name = = " size " ) {
SubViewportContainer * parent_svc = Object : : cast_to < SubViewportContainer > ( get_parent ( ) ) ;
if ( parent_svc & & parent_svc - > is_stretch_enabled ( ) ) {
p_property . usage = PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_READ_ONLY ;
} else {
p_property . usage = PROPERTY_USAGE_DEFAULT ;
}
}
}
2022-11-07 09:23:32 +01:00
SubViewport : : SubViewport ( ) {
RS : : get_singleton ( ) - > viewport_set_size ( get_viewport_rid ( ) , get_size ( ) . width , get_size ( ) . height ) ;
}
2020-03-04 02:51:12 +01:00
2021-02-09 18:24:36 +01:00
SubViewport : : ~ SubViewport ( ) { }