2014-02-10 01:10:30 +00:00
/*************************************************************************/
/* viewport.cpp */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
2017-08-27 12:16:55 +00:00
/* https://godotengine.org */
2014-02-10 01:10:30 +00:00
/*************************************************************************/
2021-01-01 19:13:46 +00:00
/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
2014-02-10 01:10:30 +00:00
/* */
/* 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-04 23:50:27 +00:00
2014-02-10 01:10:30 +00:00
# include "viewport.h"
2017-08-27 19:07:15 +00:00
2019-11-29 06:41:25 +00:00
# include "core/core_string_names.h"
2020-02-27 02:30:20 +00:00
# include "core/debugger/engine_debugger.h"
2021-08-22 15:37:22 +00:00
# include "core/object/message_queue.h"
2020-09-03 11:22:16 +00:00
# include "core/string/translation.h"
2021-08-12 23:05:59 +00:00
# include "core/templates/pair.h"
2020-04-28 15:04:07 +00:00
# include "scene/2d/camera_2d.h"
2017-08-27 19:07:15 +00:00
# include "scene/2d/collision_object_2d.h"
2020-12-31 20:34:09 +00:00
# include "scene/2d/listener_2d.cpp"
2021-07-04 01:43:23 +00:00
# ifndef _3D_DISABLED
2020-03-26 21:49:16 +00:00
# include "scene/3d/camera_3d.h"
# include "scene/3d/collision_object_3d.h"
# include "scene/3d/listener_3d.h"
2019-02-12 16:18:13 +00:00
# include "scene/3d/world_environment.h"
2021-07-04 01:43:23 +00:00
# endif // _3D_DISABLED
2017-03-05 15:44:50 +00:00
# include "scene/gui/control.h"
2016-01-17 01:41:10 +00:00
# include "scene/gui/label.h"
2021-08-12 23:05:59 +00:00
# include "scene/gui/popup.h"
2021-08-20 09:49:19 +00:00
# include "scene/gui/popup_menu.h"
2018-08-24 22:03:26 +00:00
# include "scene/main/canvas_layer.h"
2020-03-04 16:36:09 +00:00
# include "scene/main/window.h"
2017-08-27 19:07:15 +00:00
# include "scene/resources/mesh.h"
2021-08-12 23:05:59 +00:00
# include "scene/resources/text_line.h"
# include "scene/resources/world_2d.h"
2016-01-17 01:41:10 +00:00
# include "scene/scene_string_names.h"
2021-08-27 17:28:23 +00:00
# include "servers/audio_server.h"
2016-01-17 01:41:10 +00:00
2017-01-10 04:04:31 +00:00
void ViewportTexture : : setup_local_to_scene ( ) {
if ( vp ) {
vp - > viewport_textures . erase ( this ) ;
}
2020-04-01 23:20:12 +00:00
vp = nullptr ;
2017-01-10 04:04:31 +00:00
Node * local_scene = get_local_scene ( ) ;
if ( ! local_scene ) {
return ;
}
Node * vpn = local_scene - > get_node ( path ) ;
2019-08-08 20:11:48 +00:00
ERR_FAIL_COND_MSG ( ! vpn , " ViewportTexture: Path to node is invalid. " ) ;
2017-01-10 04:04:31 +00:00
2017-08-24 20:58:51 +00:00
vp = Object : : cast_to < Viewport > ( vpn ) ;
2017-01-10 04:04:31 +00:00
2019-08-08 20:11:48 +00:00
ERR_FAIL_COND_MSG ( ! vp , " ViewportTexture: Path to node does not point to a viewport. " ) ;
2017-01-10 04:04:31 +00:00
vp - > viewport_textures . insert ( this ) ;
2017-12-04 18:55:20 +00:00
2019-06-24 19:13:06 +00:00
if ( proxy_ph . is_valid ( ) ) {
2020-03-27 18:21:27 +00:00
RS : : get_singleton ( ) - > texture_proxy_update ( proxy , vp - > texture_rid ) ;
RS : : get_singleton ( ) - > free ( proxy_ph ) ;
2019-06-24 19:13:06 +00:00
} else {
2021-09-10 14:58:33 +00:00
ERR_FAIL_COND ( proxy . is_valid ( ) ) ; // Should be invalid.
2020-03-27 18:21:27 +00:00
proxy = RS : : get_singleton ( ) - > texture_proxy_create ( vp - > texture_rid ) ;
2019-06-24 19:13:06 +00:00
}
2017-01-10 04:04:31 +00:00
}
2017-03-05 15:44:50 +00:00
void ViewportTexture : : set_viewport_path_in_scene ( const NodePath & p_path ) {
2020-05-14 14:41:43 +00:00
if ( path = = p_path ) {
2017-01-10 04:04:31 +00:00
return ;
2020-05-14 14:41:43 +00:00
}
2017-01-10 04:04:31 +00:00
2017-03-05 15:44:50 +00:00
path = p_path ;
2017-01-10 04:04:31 +00:00
if ( get_local_scene ( ) ) {
setup_local_to_scene ( ) ;
}
}
NodePath ViewportTexture : : get_viewport_path_in_scene ( ) const {
return path ;
}
2016-10-05 04:26:35 +00:00
int ViewportTexture : : get_width ( ) const {
2019-09-25 08:28:50 +00:00
ERR_FAIL_COND_V_MSG ( ! vp , 0 , " Viewport Texture must be set to use it. " ) ;
2016-10-03 19:33:42 +00:00
return vp - > size . width ;
2014-02-10 01:10:30 +00:00
}
2020-05-14 12:29:06 +00:00
2017-03-05 15:44:50 +00:00
int ViewportTexture : : get_height ( ) const {
2019-09-25 08:28:50 +00:00
ERR_FAIL_COND_V_MSG ( ! vp , 0 , " Viewport Texture must be set to use it. " ) ;
2016-10-03 19:33:42 +00:00
return vp - > size . height ;
2014-02-10 01:10:30 +00:00
}
2020-05-14 12:29:06 +00:00
2017-03-05 15:44:50 +00:00
Size2 ViewportTexture : : get_size ( ) const {
2019-09-25 08:28:50 +00:00
ERR_FAIL_COND_V_MSG ( ! vp , Size2 ( ) , " Viewport Texture must be set to use it. " ) ;
2016-10-03 19:33:42 +00:00
return vp - > size ;
2014-02-10 01:10:30 +00:00
}
2020-05-14 12:29:06 +00:00
2017-03-05 15:44:50 +00:00
RID ViewportTexture : : get_rid ( ) const {
2019-06-24 19:13:06 +00:00
if ( proxy . is_null ( ) ) {
2020-03-27 18:21:27 +00:00
proxy_ph = RS : : get_singleton ( ) - > texture_2d_placeholder_create ( ) ;
proxy = RS : : get_singleton ( ) - > texture_proxy_create ( proxy_ph ) ;
2019-06-24 19:13:06 +00:00
}
2017-12-04 18:55:20 +00:00
return proxy ;
2014-02-10 01:10:30 +00:00
}
2017-03-05 15:44:50 +00:00
bool ViewportTexture : : has_alpha ( ) const {
2014-02-10 01:10:30 +00:00
return false ;
}
2020-05-14 12:29:06 +00:00
2021-03-28 11:32:17 +00:00
Ref < Image > ViewportTexture : : get_image ( ) const {
2019-09-25 08:28:50 +00:00
ERR_FAIL_COND_V_MSG ( ! vp , Ref < Image > ( ) , " Viewport Texture must be set to use it. " ) ;
2020-03-27 18:21:27 +00:00
return RS : : get_singleton ( ) - > texture_2d_get ( vp - > texture_rid ) ;
2017-01-10 04:04:31 +00:00
}
void ViewportTexture : : _bind_methods ( ) {
2017-03-05 15:44:50 +00: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 04:04:31 +00:00
2020-03-04 01:51:12 +00:00
ADD_PROPERTY ( PropertyInfo ( Variant : : NODE_PATH , " viewport_path " , PROPERTY_HINT_NODE_PATH_VALID_TYPES , " SubViewport " , PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_NODE_PATH_FROM_SCENE_ROOT ) , " set_viewport_path_in_scene " , " get_viewport_path_in_scene " ) ;
2017-01-10 04:04:31 +00:00
}
2017-03-05 15:44:50 +00:00
ViewportTexture : : ViewportTexture ( ) {
2017-01-10 04:04:31 +00:00
set_local_to_scene ( true ) ;
2014-02-10 01:10:30 +00:00
}
2017-03-05 15:44:50 +00:00
ViewportTexture : : ~ ViewportTexture ( ) {
2017-01-10 04:04:31 +00:00
if ( vp ) {
vp - > viewport_textures . erase ( this ) ;
}
2017-12-04 18:55:20 +00:00
2019-06-24 19:13:06 +00:00
if ( proxy_ph . is_valid ( ) ) {
2020-03-27 18:21:27 +00:00
RS : : get_singleton ( ) - > free ( proxy_ph ) ;
2019-06-24 19:13:06 +00:00
}
2019-07-29 21:19:31 +00:00
if ( proxy . is_valid ( ) ) {
2020-03-27 18:21:27 +00:00
RS : : get_singleton ( ) - > free ( proxy ) ;
2019-07-29 21:19:31 +00:00
}
2014-02-10 01:10:30 +00:00
}
2016-01-17 01:41:10 +00:00
/////////////////////////////////////
2020-11-02 16:18:29 +00:00
// Aliases used to provide custom styles to tooltips in the default
// theme and editor theme.
// TooltipPanel is also used for custom tooltips, while TooltipLabel
// is only relevant for default tooltips.
2020-03-20 20:51:53 +00:00
class TooltipPanel : public PopupPanel {
GDCLASS ( TooltipPanel , PopupPanel ) ;
2019-03-19 18:35:57 +00:00
2016-01-17 01:41:10 +00:00
public :
2020-05-12 15:01:17 +00:00
TooltipPanel ( ) { }
2016-01-17 01:41:10 +00:00
} ;
class TooltipLabel : public Label {
2019-03-19 18:35:57 +00:00
GDCLASS ( TooltipLabel , Label ) ;
2016-01-17 01:41:10 +00:00
public :
2020-05-12 15:01:17 +00:00
TooltipLabel ( ) { }
2016-01-17 01:41:10 +00:00
} ;
2020-11-02 16:18:29 +00:00
/////////////////////////////////////
2020-03-14 16:06:39 +00:00
void Viewport : : _sub_window_update_order ( ) {
for ( int i = 0 ; i < gui . sub_windows . size ( ) ; i + + ) {
2020-03-27 18:21:27 +00:00
RS : : get_singleton ( ) - > canvas_item_set_draw_index ( gui . sub_windows [ i ] . canvas_item , i ) ;
2020-03-14 16:06:39 +00: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 18:21:27 +00: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 16:06:39 +00:00
}
SubWindow sw ;
2020-03-27 18:21:27 +00: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 16:06:39 +00:00
sw . window = p_window ;
gui . sub_windows . push_back ( sw ) ;
_sub_window_grab_focus ( p_window ) ;
2020-03-27 18:21:27 +00:00
RenderingServer : : get_singleton ( ) - > viewport_set_parent_viewport ( p_window - > viewport , viewport ) ;
2020-03-14 16:06:39 +00:00
}
void Viewport : : _sub_window_update ( Window * p_window ) {
int index = - 1 ;
for ( int i = 0 ; i < gui . sub_windows . size ( ) ; i + + ) {
if ( gui . sub_windows [ i ] . window = = p_window ) {
index = i ;
break ;
}
}
ERR_FAIL_COND ( index = = - 1 ) ;
const SubWindow & sw = gui . sub_windows [ index ] ;
Transform2D pos ;
pos . set_origin ( p_window - > get_position ( ) ) ;
2020-03-27 18:21:27 +00:00
RS : : get_singleton ( ) - > canvas_item_clear ( sw . canvas_item ) ;
2020-03-14 16:06:39 +00:00
Rect2i r = Rect2i ( p_window - > get_position ( ) , sw . window - > get_size ( ) ) ;
if ( ! p_window - > get_flag ( Window : : FLAG_BORDERLESS ) ) {
2021-07-28 02:32:03 +00:00
Ref < StyleBox > panel = p_window - > get_theme_stylebox ( SNAME ( " embedded_border " ) ) ;
2020-03-14 16:06:39 +00:00
panel - > draw ( sw . canvas_item , r ) ;
// Draw the title bar text.
2021-07-17 21:22:52 +00:00
Ref < Font > title_font = p_window - > get_theme_font ( SNAME ( " title_font " ) ) ;
int font_size = p_window - > get_theme_font_size ( SNAME ( " title_font_size " ) ) ;
Color title_color = p_window - > get_theme_color ( SNAME ( " title_color " ) ) ;
int title_height = p_window - > get_theme_constant ( SNAME ( " title_height " ) ) ;
int close_h_ofs = p_window - > get_theme_constant ( SNAME ( " close_h_ofs " ) ) ;
int close_v_ofs = p_window - > get_theme_constant ( SNAME ( " close_v_ofs " ) ) ;
2020-03-14 16:06:39 +00:00
2021-05-27 17:31:33 +00:00
TextLine title_text = TextLine ( p_window - > atr ( p_window - > get_title ( ) ) , title_font , font_size , Dictionary ( ) , TranslationServer : : get_singleton ( ) - > get_tool_locale ( ) ) ;
2020-09-03 11:22:16 +00: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 ;
2021-07-17 21:22:52 +00:00
Color font_outline_color = p_window - > get_theme_color ( SNAME ( " title_outline_modulate " ) ) ;
int outline_size = p_window - > get_theme_constant ( SNAME ( " title_outline_size " ) ) ;
2020-12-25 21:45:28 +00: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 11:22:16 +00:00
title_text . draw ( sw . canvas_item , r . position + Point2 ( x , y ) , title_color ) ;
2020-03-14 16:06:39 +00:00
2021-07-28 02:32:03 +00:00
bool pressed = gui . subwindow_focused = = sw . window & & gui . subwindow_drag = = SUB_WINDOW_DRAG_CLOSE & & gui . subwindow_drag_close_inside ;
Ref < Texture2D > close_icon = p_window - > get_theme_icon ( pressed ? " close_pressed " : " close " ) ;
2020-03-14 16:06:39 +00:00
close_icon - > draw ( sw . canvas_item , r . position + Vector2 ( r . size . width - close_h_ofs , - close_v_ofs ) ) ;
}
2020-03-27 18:21:27 +00:00
RS : : get_singleton ( ) - > canvas_item_add_texture_rect ( sw . canvas_item , r , sw . window - > get_texture ( ) - > get_rid ( ) ) ;
2020-03-14 16:06:39 +00:00
}
void Viewport : : _sub_window_grab_focus ( Window * p_window ) {
if ( p_window = = nullptr ) {
2021-09-10 14:58:33 +00:00
// Release current focus.
2020-03-14 16:06:39 +00: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 20:51:53 +00:00
2020-03-14 16:06:39 +00:00
int index = - 1 ;
for ( int i = 0 ; i < gui . sub_windows . size ( ) ; i + + ) {
if ( gui . sub_windows [ i ] . window = = p_window ) {
index = i ;
break ;
}
}
ERR_FAIL_COND ( index = = - 1 ) ;
2020-03-20 20:51:53 +00:00
if ( p_window - > get_flag ( Window : : FLAG_NO_FOCUS ) ) {
2021-09-10 14:58:33 +00:00
// Can only move to foreground, but no focus granted.
2020-03-20 20:51:53 +00:00
SubWindow sw = gui . sub_windows [ index ] ;
gui . sub_windows . remove ( index ) ;
gui . sub_windows . push_back ( sw ) ;
index = gui . sub_windows . size ( ) - 1 ;
_sub_window_update_order ( ) ;
2021-09-10 14:58:33 +00:00
return ;
2020-03-20 20:51:53 +00:00
}
2020-03-14 16:06:39 +00:00
if ( gui . subwindow_focused ) {
if ( gui . subwindow_focused = = p_window ) {
2021-09-10 14:58:33 +00:00
return ; // Nothing to do.
2020-03-14 16:06:39 +00: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 14:58:33 +00:00
{ // Move to foreground.
2020-03-14 16:06:39 +00:00
SubWindow sw = gui . sub_windows [ index ] ;
gui . sub_windows . remove ( index ) ;
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 ) {
for ( int i = 0 ; i < gui . sub_windows . size ( ) ; i + + ) {
if ( gui . sub_windows [ i ] . window = = p_window ) {
2020-03-27 18:21:27 +00:00
RS : : get_singleton ( ) - > free ( gui . sub_windows [ i ] . canvas_item ) ;
2020-03-14 16:06:39 +00:00
gui . sub_windows . remove ( i ) ;
break ;
}
}
if ( gui . sub_windows . size ( ) = = 0 ) {
2020-03-27 18:21:27 +00:00
RS : : get_singleton ( ) - > free ( subwindow_canvas ) ;
2020-03-14 16:06:39 +00:00
subwindow_canvas = RID ( ) ;
}
if ( gui . subwindow_focused = = p_window ) {
Window * parent_visible = p_window - > get_parent_visible_window ( ) ;
gui . subwindow_drag = SUB_WINDOW_DRAG_DISABLED ;
gui . subwindow_focused - > _event_callback ( DisplayServer : : WINDOW_EVENT_FOCUS_OUT ) ;
if ( parent_visible & & parent_visible ! = this ) {
gui . subwindow_focused = parent_visible ;
gui . subwindow_focused - > _event_callback ( DisplayServer : : WINDOW_EVENT_FOCUS_IN ) ;
} else {
gui . subwindow_focused = nullptr ;
Window * this_window = Object : : cast_to < Window > ( this ) ;
if ( this_window ) {
this_window - > _event_callback ( DisplayServer : : WINDOW_EVENT_FOCUS_IN ) ;
}
}
}
2020-03-27 18:21:27 +00:00
RenderingServer : : get_singleton ( ) - > viewport_set_parent_viewport ( p_window - > viewport , p_window - > parent ? p_window - > parent - > viewport : RID ( ) ) ;
2020-03-14 16:06:39 +00:00
}
2014-02-10 01:10:30 +00:00
void Viewport : : _notification ( int p_what ) {
2017-03-05 15:44:50 +00:00
switch ( p_what ) {
2014-11-06 00:20:42 +00:00
case NOTIFICATION_ENTER_TREE : {
2020-03-14 16:06:39 +00:00
gui . embedding_subwindows = gui . embed_subwindows_hint ;
2016-01-18 22:49:11 +00:00
if ( get_parent ( ) ) {
2016-10-05 04:26:35 +00:00
parent = get_parent ( ) - > get_viewport ( ) ;
2020-03-27 18:21:27 +00:00
RenderingServer : : get_singleton ( ) - > viewport_set_parent_viewport ( viewport , parent - > get_viewport_rid ( ) ) ;
2016-10-05 04:26:35 +00:00
} else {
2020-04-01 23:20:12 +00:00
parent = nullptr ;
2014-02-10 01:10:30 +00:00
}
2017-03-05 15:44:50 +00:00
current_canvas = find_world_2d ( ) - > get_canvas ( ) ;
2020-03-27 18:21:27 +00:00
RenderingServer : : get_singleton ( ) - > viewport_attach_canvas ( viewport , current_canvas ) ;
2014-02-10 01:10:30 +00:00
_update_listener_2d ( ) ;
2021-07-04 01:43:23 +00:00
# ifndef _3D_DISABLED
2021-08-02 17:31:51 +00:00
RenderingServer : : get_singleton ( ) - > viewport_set_scenario ( viewport , find_world_3d ( ) - > get_scenario ( ) ) ;
_update_listener_3d ( ) ;
2021-07-04 01:43:23 +00:00
# endif // _3D_DISABLED
2014-02-10 01:10:30 +00:00
2015-09-20 20:29:36 +00:00
add_to_group ( " _viewports " ) ;
2015-09-20 16:03:46 +00:00
if ( get_tree ( ) - > is_debugging_collisions_hint ( ) ) {
2020-03-27 18:21:27 +00: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 ( ) ;
RenderingServer : : get_singleton ( ) - > canvas_item_set_parent ( contact_2d_debug , find_world_2d ( ) - > get_canvas ( ) ) ;
2021-07-04 01:43:23 +00:00
# ifndef _3D_DISABLED
2020-04-18 09:00:51 +00:00
PhysicsServer3D : : get_singleton ( ) - > space_set_debug_contacts ( find_world_3d ( ) - > get_space ( ) , get_tree ( ) - > get_collision_debug_contact_count ( ) ) ;
2020-03-27 18:21:27 +00:00
contact_3d_debug_multimesh = RenderingServer : : get_singleton ( ) - > multimesh_create ( ) ;
2021-02-09 16:19:03 +00:00
RenderingServer : : get_singleton ( ) - > multimesh_allocate_data ( contact_3d_debug_multimesh , get_tree ( ) - > get_collision_debug_contact_count ( ) , RS : : MULTIMESH_TRANSFORM_3D , true ) ;
2020-03-27 18:21:27 +00: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 09:00:51 +00:00
RenderingServer : : get_singleton ( ) - > instance_set_scenario ( contact_3d_debug_instance , find_world_3d ( ) - > get_scenario ( ) ) ;
2020-03-27 18:21:27 +00:00
//RenderingServer::get_singleton()->instance_geometry_set_flag(contact_3d_debug_instance, RS::INSTANCE_FLAG_VISIBLE_IN_ALL_ROOMS, true);
2021-07-04 01:43:23 +00:00
# endif // _3D_DISABLED
2015-09-20 16:03:46 +00:00
}
2014-02-10 01:10:30 +00:00
} break ;
case NOTIFICATION_READY : {
2021-07-04 01:43:23 +00:00
# ifndef _3D_DISABLED
2021-08-02 17:31:51 +00:00
if ( listener_3d_set . size ( ) & & ! listener_3d ) {
2020-04-01 23:20:12 +00:00
Listener3D * first = nullptr ;
2021-08-02 17:31:51 +00:00
for ( Set < Listener3D * > : : Element * E = listener_3d_set . front ( ) ; E ; E = E - > next ( ) ) {
2020-04-01 23:20:12 +00:00
if ( first = = nullptr | | first - > is_greater_than ( E - > get ( ) ) ) {
2017-03-05 15:44:50 +00:00
first = E - > get ( ) ;
2016-03-20 02:10:04 +00:00
}
}
2020-05-14 14:41:43 +00:00
if ( first ) {
2016-03-20 02:10:04 +00:00
first - > make_current ( ) ;
2020-05-14 14:41:43 +00:00
}
2016-03-20 02:10:04 +00:00
}
2021-08-02 17:31:51 +00:00
if ( camera_3d_set . size ( ) & & ! camera_3d ) {
2021-09-10 14:58:33 +00:00
// There are cameras but no current camera, pick first in tree and make it current.
2020-04-01 23:20:12 +00:00
Camera3D * first = nullptr ;
2021-08-02 17:31:51 +00:00
for ( Set < Camera3D * > : : Element * E = camera_3d_set . front ( ) ; E ; E = E - > next ( ) ) {
2020-04-01 23:20:12 +00:00
if ( first = = nullptr | | first - > is_greater_than ( E - > get ( ) ) ) {
2017-03-05 15:44:50 +00:00
first = E - > get ( ) ;
2014-02-10 01:10:30 +00:00
}
}
2020-05-14 14:41:43 +00:00
if ( first ) {
2014-02-10 01:10:30 +00:00
first - > make_current ( ) ;
2020-05-14 14:41:43 +00:00
}
2014-02-10 01:10:30 +00:00
}
2021-07-04 01:43:23 +00:00
# endif // _3D_DISABLED
2014-02-10 01:10:30 +00:00
} break ;
2014-11-06 00:20:42 +00:00
case NOTIFICATION_EXIT_TREE : {
2016-01-25 13:30:03 +00:00
_gui_cancel_tooltip ( ) ;
2014-02-10 01:10:30 +00:00
2020-03-27 18:21:27 +00:00
RenderingServer : : get_singleton ( ) - > viewport_set_scenario ( viewport , RID ( ) ) ;
RenderingServer : : get_singleton ( ) - > viewport_remove_canvas ( viewport , current_canvas ) ;
2015-09-20 16:03:46 +00:00
if ( contact_2d_debug . is_valid ( ) ) {
2020-03-27 18:21:27 +00:00
RenderingServer : : get_singleton ( ) - > free ( contact_2d_debug ) ;
2017-03-05 15:44:50 +00:00
contact_2d_debug = RID ( ) ;
2015-09-20 16:03:46 +00:00
}
if ( contact_3d_debug_multimesh . is_valid ( ) ) {
2020-03-27 18:21:27 +00:00
RenderingServer : : get_singleton ( ) - > free ( contact_3d_debug_multimesh ) ;
RenderingServer : : get_singleton ( ) - > free ( contact_3d_debug_instance ) ;
2017-03-05 15:44:50 +00:00
contact_3d_debug_instance = RID ( ) ;
contact_3d_debug_multimesh = RID ( ) ;
2015-09-20 16:03:46 +00:00
}
2014-02-10 01:10:30 +00:00
remove_from_group ( " _viewports " ) ;
2021-07-19 17:25:15 +00:00
set_physics_process_internal ( false ) ;
2016-10-05 04:26:35 +00:00
2020-03-27 18:21:27 +00:00
RS : : get_singleton ( ) - > viewport_set_active ( viewport , false ) ;
RenderingServer : : get_singleton ( ) - > viewport_set_parent_viewport ( viewport , RID ( ) ) ;
2018-03-01 13:44:45 +00:00
} break ;
case NOTIFICATION_INTERNAL_PHYSICS_PROCESS : {
2015-09-20 16:03:46 +00:00
if ( get_tree ( ) - > is_debugging_collisions_hint ( ) & & contact_2d_debug . is_valid ( ) ) {
2020-03-27 18:21:27 +00: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 16:03:46 +00:00
2020-03-27 18:21:27 +00: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 16:03:46 +00:00
Color ccol = get_tree ( ) - > get_debug_collision_contact_color ( ) ;
2017-03-05 15:44:50 +00:00
for ( int i = 0 ; i < point_count ; i + + ) {
2020-03-27 18:21:27 +00:00
RenderingServer : : get_singleton ( ) - > canvas_item_add_rect ( contact_2d_debug , Rect2 ( points [ i ] - Vector2 ( 2 , 2 ) , Vector2 ( 5 , 5 ) ) , ccol ) ;
2015-09-20 16:03:46 +00:00
}
}
2021-07-04 01:43:23 +00:00
# ifndef _3D_DISABLED
2015-09-20 16:03:46 +00:00
if ( get_tree ( ) - > is_debugging_collisions_hint ( ) & & contact_3d_debug_multimesh . is_valid ( ) ) {
2020-04-18 09:00:51 +00: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 16:03:46 +00:00
2020-03-27 18:21:27 +00:00
RS : : get_singleton ( ) - > multimesh_set_visible_instances ( contact_3d_debug_multimesh , point_count ) ;
2021-02-10 01:36:38 +00:00
for ( int i = 0 ; i < point_count ; i + + ) {
2020-10-17 05:08:21 +00:00
Transform3D point_transform ;
2021-02-10 01:36:38 +00:00
point_transform . origin = points [ i ] ;
RS : : get_singleton ( ) - > multimesh_instance_set_transform ( contact_3d_debug_multimesh , i , point_transform ) ;
}
2015-09-20 16:03:46 +00:00
}
2021-07-04 01:43:23 +00:00
# endif // _3D_DISABLED
2021-02-06 20:14:35 +00:00
} break ;
case NOTIFICATION_WM_MOUSE_EXIT : {
_drop_physics_mouseover ( ) ;
// Unlike on loss of focus (NOTIFICATION_WM_WINDOW_FOCUS_OUT), do not
// drop the gui mouseover here, as a scrollbar may be dragged while the
// mouse is outside the window (without the window having lost focus).
// See bug #39634
} break ;
case NOTIFICATION_WM_WINDOW_FOCUS_OUT : {
_drop_physics_mouseover ( ) ;
if ( gui . mouse_focus & & ! gui . forced_mouse_focus ) {
_drop_mouse_focus ( ) ;
}
} break ;
}
}
void Viewport : : _process_picking ( ) {
if ( ! is_inside_tree ( ) ) {
return ;
}
if ( ! physics_object_picking ) {
return ;
}
if ( to_screen_rect ! = Rect2i ( ) & & Input : : get_singleton ( ) - > get_mouse_mode ( ) = = Input : : MOUSE_MODE_CAPTURED ) {
return ;
}
_drop_physics_mouseover ( true ) ;
2015-09-20 16:03:46 +00:00
2021-02-06 20:14:35 +00:00
PhysicsDirectSpaceState2D * ss2d = PhysicsServer2D : : get_singleton ( ) - > space_get_direct_state ( find_world_2d ( ) - > get_space ( ) ) ;
if ( physics_has_last_mousepos ) {
2021-09-10 14:58:33 +00:00
// If no mouse event exists, create a motion one. This is necessary because objects or camera may have moved.
// 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.
2021-02-06 20:14:35 +00:00
bool has_mouse_event = false ;
2021-07-26 15:50:35 +00:00
for ( const Ref < InputEvent > & m : physics_picking_events ) {
2021-02-06 20:14:35 +00:00
if ( m . is_valid ( ) ) {
has_mouse_event = true ;
break ;
}
}
2018-11-15 16:54:26 +00:00
2021-02-06 20:14:35 +00:00
if ( ! has_mouse_event ) {
Ref < InputEventMouseMotion > mm ;
2021-06-17 22:03:09 +00:00
mm . instantiate ( ) ;
2018-11-15 16:54:26 +00:00
2021-02-06 20:14:35 +00:00
mm - > set_device ( InputEvent : : DEVICE_ID_INTERNAL ) ;
mm - > set_global_position ( physics_last_mousepos ) ;
mm - > set_position ( physics_last_mousepos ) ;
2021-04-24 20:33:50 +00:00
mm - > set_alt_pressed ( physics_last_mouse_state . alt ) ;
mm - > set_shift_pressed ( physics_last_mouse_state . shift ) ;
mm - > set_ctrl_pressed ( physics_last_mouse_state . control ) ;
mm - > set_meta_pressed ( physics_last_mouse_state . meta ) ;
2021-02-06 20:14:35 +00:00
mm - > set_button_mask ( physics_last_mouse_state . mouse_mask ) ;
physics_picking_events . push_back ( mm ) ;
}
}
2014-09-15 14:33:30 +00:00
2021-02-06 20:14:35 +00:00
while ( physics_picking_events . size ( ) ) {
Ref < InputEvent > ev = physics_picking_events . front ( ) - > get ( ) ;
physics_picking_events . pop_front ( ) ;
2017-05-20 15:38:03 +00:00
2021-02-06 20:14:35 +00:00
Vector2 pos ;
bool is_mouse = false ;
2017-05-20 15:38:03 +00:00
2021-02-06 20:14:35 +00:00
Ref < InputEventMouseMotion > mm = ev ;
2019-03-05 21:31:02 +00:00
2021-02-06 20:14:35 +00:00
if ( mm . is_valid ( ) ) {
pos = mm - > get_position ( ) ;
is_mouse = true ;
2017-05-20 15:38:03 +00:00
2021-02-06 20:14:35 +00:00
physics_has_last_mousepos = true ;
physics_last_mousepos = pos ;
2021-04-24 20:33:50 +00:00
physics_last_mouse_state . alt = mm - > is_alt_pressed ( ) ;
physics_last_mouse_state . shift = mm - > is_shift_pressed ( ) ;
physics_last_mouse_state . control = mm - > is_ctrl_pressed ( ) ;
physics_last_mouse_state . meta = mm - > is_meta_pressed ( ) ;
2021-02-06 20:14:35 +00:00
physics_last_mouse_state . mouse_mask = mm - > get_button_mask ( ) ;
}
2017-05-20 15:38:03 +00:00
2021-02-06 20:14:35 +00:00
Ref < InputEventMouseButton > mb = ev ;
2019-03-05 21:31:02 +00:00
2021-02-06 20:14:35 +00:00
if ( mb . is_valid ( ) ) {
pos = mb - > get_position ( ) ;
is_mouse = true ;
2018-11-15 16:54:26 +00:00
2021-02-06 20:14:35 +00:00
physics_has_last_mousepos = true ;
physics_last_mousepos = pos ;
2021-04-24 20:33:50 +00:00
physics_last_mouse_state . alt = mb - > is_alt_pressed ( ) ;
physics_last_mouse_state . shift = mb - > is_shift_pressed ( ) ;
physics_last_mouse_state . control = mb - > is_ctrl_pressed ( ) ;
physics_last_mouse_state . meta = mb - > is_meta_pressed ( ) ;
2019-03-05 21:31:02 +00:00
2021-02-06 20:14:35 +00:00
if ( mb - > is_pressed ( ) ) {
2021-03-25 20:56:12 +00:00
physics_last_mouse_state . mouse_mask | = ( MouseButton ) ( 1 < < ( mb - > get_button_index ( ) - 1 ) ) ;
2021-02-06 20:14:35 +00:00
} else {
2021-03-25 20:56:12 +00:00
physics_last_mouse_state . mouse_mask & = ( MouseButton ) ~ ( 1 < < ( mb - > get_button_index ( ) - 1 ) ) ;
2018-11-15 16:54:26 +00:00
2021-02-06 20:14:35 +00:00
// If touch mouse raised, assume we don't know last mouse pos until new events come
if ( mb - > get_device ( ) = = InputEvent : : DEVICE_ID_TOUCH_MOUSE ) {
physics_has_last_mousepos = false ;
}
}
}
2017-05-20 15:38:03 +00:00
2021-02-06 20:14:35 +00:00
Ref < InputEventKey > k = ev ;
if ( k . is_valid ( ) ) {
2021-09-10 14:58:33 +00:00
// Only for mask.
2021-04-24 20:33:50 +00:00
physics_last_mouse_state . alt = k - > is_alt_pressed ( ) ;
physics_last_mouse_state . shift = k - > is_shift_pressed ( ) ;
physics_last_mouse_state . control = k - > is_ctrl_pressed ( ) ;
physics_last_mouse_state . meta = k - > is_meta_pressed ( ) ;
2021-02-06 20:14:35 +00:00
continue ;
}
2017-05-20 15:38:03 +00:00
2021-02-06 20:14:35 +00:00
Ref < InputEventScreenDrag > sd = ev ;
2017-05-20 15:38:03 +00:00
2021-02-06 20:14:35 +00:00
if ( sd . is_valid ( ) ) {
pos = sd - > get_position ( ) ;
}
2017-05-20 15:38:03 +00:00
2021-02-06 20:14:35 +00:00
Ref < InputEventScreenTouch > st = ev ;
2014-09-15 14:33:30 +00:00
2021-02-06 20:14:35 +00:00
if ( st . is_valid ( ) ) {
pos = st - > get_position ( ) ;
}
2015-03-22 04:46:18 +00:00
2021-02-06 20:14:35 +00:00
if ( ss2d ) {
2021-09-10 14:58:33 +00:00
// Send to 2D.
2015-03-22 04:46:18 +00:00
2021-02-06 20:14:35 +00:00
uint64_t frame = get_tree ( ) - > get_frame ( ) ;
2018-08-24 22:03:26 +00:00
2021-02-06 20:14:35 +00:00
PhysicsDirectSpaceState2D : : ShapeResult res [ 64 ] ;
for ( Set < CanvasLayer * > : : Element * E = canvas_layers . front ( ) ; E ; E = E - > next ( ) ) {
Transform2D canvas_transform ;
ObjectID canvas_layer_id ;
if ( E - > get ( ) ) {
2021-09-10 14:58:33 +00:00
// A descendant CanvasLayer.
2021-02-06 20:14:35 +00:00
canvas_transform = E - > get ( ) - > get_transform ( ) ;
canvas_layer_id = E - > get ( ) - > get_instance_id ( ) ;
} else {
2021-09-10 14:58:33 +00:00
// This Viewport's builtin canvas.
2021-02-06 20:14:35 +00:00
canvas_transform = get_canvas_transform ( ) ;
canvas_layer_id = ObjectID ( ) ;
}
Vector2 point = canvas_transform . affine_inverse ( ) . xform ( pos ) ;
int rc = ss2d - > intersect_point_on_canvas ( point , canvas_layer_id , res , 64 , Set < RID > ( ) , 0xFFFFFFFF , true , true , true ) ;
for ( int i = 0 ; i < rc ; i + + ) {
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 ) {
Map < ObjectID , uint64_t > : : Element * F = physics_2d_mouseover . find ( res [ i ] . collider_id ) ;
if ( ! F ) {
physics_2d_mouseover . insert ( res [ i ] . collider_id , frame ) ;
co - > _mouse_enter ( ) ;
} else {
F - > get ( ) = frame ;
2021-09-10 14:58:33 +00:00
// It was already hovered, so don't send the event if it's faked.
2021-02-06 20:14:35 +00:00
if ( mm . is_valid ( ) & & mm - > get_device ( ) = = InputEvent : : DEVICE_ID_INTERNAL ) {
send_event = false ;
2018-08-24 22:03:26 +00:00
}
2015-03-22 04:46:18 +00:00
}
2021-03-26 17:39:05 +00:00
Map < Pair < ObjectID , int > , uint64_t , PairSort < ObjectID , int > > : : Element * SF = physics_2d_shape_mouseover . find ( Pair ( res [ i ] . collider_id , res [ i ] . shape ) ) ;
if ( ! SF ) {
physics_2d_shape_mouseover . insert ( Pair ( res [ i ] . collider_id , res [ i ] . shape ) , frame ) ;
co - > _mouse_shape_enter ( res [ i ] . shape ) ;
} else {
SF - > get ( ) = frame ;
}
2015-03-22 04:46:18 +00:00
}
2021-02-06 20:14:35 +00:00
if ( send_event ) {
2021-08-22 15:37:22 +00:00
co - > _input_event_call ( this , ev , res [ i ] . shape ) ;
2015-03-22 04:46:18 +00:00
}
2021-02-06 20:14:35 +00:00
}
}
}
}
2015-03-22 04:46:18 +00:00
2021-02-06 20:14:35 +00:00
if ( is_mouse ) {
2021-03-26 17:39:05 +00:00
_cleanup_mouseover_colliders ( false , false , frame ) ;
2021-02-06 20:14:35 +00:00
}
}
2015-03-22 04:46:18 +00:00
2021-07-04 01:43:23 +00:00
# ifndef _3D_DISABLED
Vector2 last_pos ( 1e20 , 1e20 ) ;
CollisionObject3D * last_object = nullptr ;
ObjectID last_id ;
PhysicsDirectSpaceState3D : : RayResult result ;
2021-02-06 20:14:35 +00:00
bool captured = false ;
if ( physics_object_capture . is_valid ( ) ) {
CollisionObject3D * co = Object : : cast_to < CollisionObject3D > ( ObjectDB : : get_instance ( physics_object_capture ) ) ;
2020-04-28 15:04:07 +00:00
if ( co & & camera_3d ) {
2021-08-02 17:31:51 +00:00
_collision_object_3d_input_event ( co , camera_3d , ev , Vector3 ( ) , Vector3 ( ) , 0 ) ;
2021-02-06 20:14:35 +00:00
captured = true ;
if ( mb . is_valid ( ) & & mb - > get_button_index ( ) = = 1 & & ! mb - > is_pressed ( ) ) {
physics_object_capture = ObjectID ( ) ;
}
2017-08-24 20:58:51 +00:00
2021-02-06 20:14:35 +00:00
} else {
physics_object_capture = ObjectID ( ) ;
}
}
if ( captured ) {
2021-09-10 14:58:33 +00:00
// None.
2021-02-06 20:14:35 +00:00
} else if ( pos = = last_pos ) {
if ( last_id . is_valid ( ) ) {
if ( ObjectDB : : get_instance ( last_id ) & & last_object ) {
2021-09-10 14:58:33 +00:00
// Good, exists.
2021-08-02 17:31:51 +00:00
_collision_object_3d_input_event ( last_object , camera_3d , ev , result . position , result . normal , result . shape ) ;
2021-02-06 20:14:35 +00:00
if ( last_object - > get_capture_input_on_drag ( ) & & mb . is_valid ( ) & & mb - > get_button_index ( ) = = 1 & & mb - > is_pressed ( ) ) {
physics_object_capture = last_id ;
}
}
}
} else {
2020-04-28 15:04:07 +00:00
if ( camera_3d ) {
Vector3 from = camera_3d - > project_ray_origin ( pos ) ;
Vector3 dir = camera_3d - > project_ray_normal ( pos ) ;
2021-02-06 20:14:35 +00:00
PhysicsDirectSpaceState3D * space = PhysicsServer3D : : get_singleton ( ) - > space_get_direct_state ( find_world_3d ( ) - > get_space ( ) ) ;
if ( space ) {
bool col = space - > intersect_ray ( from , from + dir * 10000 , result , Set < RID > ( ) , 0xFFFFFFFF , true , true , true ) ;
ObjectID new_collider ;
if ( col ) {
CollisionObject3D * co = Object : : cast_to < CollisionObject3D > ( result . collider ) ;
2021-08-02 17:31:51 +00:00
if ( co & & co - > can_process ( ) ) {
_collision_object_3d_input_event ( co , camera_3d , ev , result . position , result . normal , result . shape ) ;
2021-02-06 20:14:35 +00:00
last_object = co ;
last_id = result . collider_id ;
new_collider = last_id ;
if ( co - > get_capture_input_on_drag ( ) & & mb . is_valid ( ) & & mb - > get_button_index ( ) = = 1 & & mb - > is_pressed ( ) ) {
physics_object_capture = last_id ;
}
2014-09-15 14:33:30 +00:00
}
}
2021-02-06 20:14:35 +00:00
if ( is_mouse & & new_collider ! = physics_object_over ) {
if ( physics_object_over . is_valid ( ) ) {
CollisionObject3D * co = Object : : cast_to < CollisionObject3D > ( ObjectDB : : get_instance ( physics_object_over ) ) ;
if ( co ) {
co - > _mouse_exit ( ) ;
2014-09-15 14:33:30 +00:00
}
}
2021-02-06 20:14:35 +00:00
if ( new_collider . is_valid ( ) ) {
CollisionObject3D * co = Object : : cast_to < CollisionObject3D > ( ObjectDB : : get_instance ( new_collider ) ) ;
if ( co ) {
co - > _mouse_enter ( ) ;
2014-09-15 14:33:30 +00:00
}
2019-03-05 21:31:02 +00:00
}
2021-02-06 20:14:35 +00:00
physics_object_over = new_collider ;
2014-09-15 14:33:30 +00:00
}
2015-03-22 04:46:18 +00:00
}
2020-08-06 13:05:43 +00:00
2021-02-06 20:14:35 +00:00
last_pos = pos ;
2018-01-05 18:39:10 +00:00
}
2021-02-06 20:14:35 +00:00
}
2021-07-04 01:43:23 +00:00
# endif // _3D_DISABLED
2014-02-10 01:10:30 +00:00
}
}
2017-01-14 14:07:57 +00:00
RID Viewport : : get_viewport_rid ( ) const {
2016-03-08 23:00:52 +00:00
return viewport ;
2014-02-10 01:10:30 +00:00
}
2019-01-26 17:56:22 +00:00
void Viewport : : update_canvas_items ( ) {
2020-05-14 14:41:43 +00:00
if ( ! is_inside_tree ( ) ) {
2019-01-26 17:56:22 +00:00
return ;
2020-05-14 14:41:43 +00:00
}
2019-01-26 17:56:22 +00:00
_update_canvas_items ( this ) ;
}
2020-04-01 03:47:58 +00:00
void Viewport : : _set_size ( const Size2i & p_size , const Size2i & p_size_2d_override , const Rect2i & p_to_screen_rect , const Transform2D & p_stretch_transform , bool p_allocated ) {
2020-05-14 14:41:43 +00:00
if ( size = = p_size & & size_allocated = = p_allocated & & stretch_transform = = p_stretch_transform & & p_size_2d_override = = size_2d_override & & to_screen_rect ! = p_to_screen_rect ) {
2014-02-10 01:10:30 +00:00
return ;
2020-05-14 14:41:43 +00:00
}
2020-04-01 03:47:58 +00:00
2020-03-04 01:51:12 +00:00
size = p_size ;
size_allocated = p_allocated ;
2020-04-01 03:47:58 +00:00
size_2d_override = p_size_2d_override ;
2020-03-04 01:51:12 +00:00
stretch_transform = p_stretch_transform ;
to_screen_rect = p_to_screen_rect ;
if ( p_allocated ) {
2020-03-27 18:21:27 +00:00
RS : : get_singleton ( ) - > viewport_set_size ( viewport , size . width , size . height ) ;
2020-03-04 01:51:12 +00:00
} else {
2020-03-27 18:21:27 +00:00
RS : : get_singleton ( ) - > viewport_set_size ( viewport , 0 , 0 ) ;
2020-03-04 01:51:12 +00:00
}
_update_global_transform ( ) ;
2014-10-28 01:54:32 +00:00
2020-03-04 01:51:12 +00:00
update_canvas_items ( ) ;
2014-02-10 01:10:30 +00:00
2021-07-17 21:22:52 +00:00
emit_signal ( SNAME ( " size_changed " ) ) ;
2014-02-10 01:10:30 +00:00
}
2020-03-04 01:51:12 +00:00
Size2i Viewport : : _get_size ( ) const {
return size ;
}
2020-05-14 12:29:06 +00:00
2020-04-01 03:47:58 +00:00
Size2i Viewport : : _get_size_2d_override ( ) const {
return size_2d_override ;
}
2020-05-14 12:29:06 +00:00
2020-03-04 01:51:12 +00:00
bool Viewport : : _is_size_allocated ( ) const {
return size_allocated ;
}
2014-02-10 01:10:30 +00:00
Rect2 Viewport : : get_visible_rect ( ) const {
Rect2 r ;
2016-03-08 23:00:52 +00:00
2017-03-05 15:44:50 +00:00
if ( size = = Size2 ( ) ) {
2020-03-03 13:36:29 +00:00
r = Rect2 ( Point2 ( ) , DisplayServer : : get_singleton ( ) - > window_get_size ( ) ) ;
2014-02-10 01:10:30 +00:00
} else {
2017-03-05 15:44:50 +00:00
r = Rect2 ( Point2 ( ) , size ) ;
2014-02-10 01:10:30 +00:00
}
2020-04-01 03:47:58 +00:00
if ( size_2d_override ! = Size2i ( ) ) {
r . size = size_2d_override ;
2014-02-10 01:10:30 +00:00
}
return r ;
}
void Viewport : : _update_listener_2d ( ) {
2021-08-27 17:28:23 +00:00
AudioServer : : get_singleton ( ) - > notify_listener_changed ( ) ;
2014-02-10 01:10:30 +00:00
}
void Viewport : : set_as_audio_listener_2d ( bool p_enable ) {
2020-05-14 14:41:43 +00:00
if ( p_enable = = audio_listener_2d ) {
2014-02-10 01:10:30 +00:00
return ;
2020-05-14 14:41:43 +00:00
}
2014-02-10 01:10:30 +00:00
2017-03-05 15:44:50 +00:00
audio_listener_2d = p_enable ;
2014-02-10 01:10:30 +00:00
_update_listener_2d ( ) ;
}
bool Viewport : : is_audio_listener_2d ( ) const {
2017-03-05 15:44:50 +00:00
return audio_listener_2d ;
2014-02-10 01:10:30 +00:00
}
2020-12-31 20:34:09 +00:00
Listener2D * Viewport : : get_listener_2d ( ) const {
return listener_2d ;
}
2019-04-06 20:55:01 +00:00
void Viewport : : enable_canvas_transform_override ( bool p_enable ) {
if ( override_canvas_transform = = p_enable ) {
return ;
}
override_canvas_transform = p_enable ;
if ( p_enable ) {
2020-03-27 18:21:27 +00:00
RenderingServer : : get_singleton ( ) - > viewport_set_canvas_transform ( viewport , find_world_2d ( ) - > get_canvas ( ) , canvas_transform_override ) ;
2019-04-06 20:55:01 +00:00
} else {
2020-03-27 18:21:27 +00:00
RenderingServer : : get_singleton ( ) - > viewport_set_canvas_transform ( viewport , find_world_2d ( ) - > get_canvas ( ) , canvas_transform ) ;
2019-04-06 20:55:01 +00:00
}
}
bool Viewport : : is_canvas_transform_override_enbled ( ) const {
return override_canvas_transform ;
}
void Viewport : : set_canvas_transform_override ( const Transform2D & p_transform ) {
if ( canvas_transform_override = = p_transform ) {
return ;
}
canvas_transform_override = p_transform ;
if ( override_canvas_transform ) {
2020-03-27 18:21:27 +00:00
RenderingServer : : get_singleton ( ) - > viewport_set_canvas_transform ( viewport , find_world_2d ( ) - > get_canvas ( ) , canvas_transform_override ) ;
2019-04-06 20:55:01 +00:00
}
}
Transform2D Viewport : : get_canvas_transform_override ( ) const {
return canvas_transform_override ;
}
2017-03-05 15:44:50 +00:00
void Viewport : : set_canvas_transform ( const Transform2D & p_transform ) {
canvas_transform = p_transform ;
2019-04-06 20:55:01 +00:00
if ( ! override_canvas_transform ) {
2020-03-27 18:21:27 +00:00
RenderingServer : : get_singleton ( ) - > viewport_set_canvas_transform ( viewport , find_world_2d ( ) - > get_canvas ( ) , canvas_transform ) ;
2019-04-06 20:55:01 +00:00
}
2014-02-10 01:10:30 +00:00
}
2017-03-05 15:44:50 +00:00
Transform2D Viewport : : get_canvas_transform ( ) const {
2014-02-10 01:10:30 +00:00
return canvas_transform ;
}
void Viewport : : _update_global_transform ( ) {
2017-01-11 03:52:51 +00:00
Transform2D sxform = stretch_transform * global_canvas_transform ;
2014-02-10 01:10:30 +00:00
2020-03-27 18:21:27 +00:00
RenderingServer : : get_singleton ( ) - > viewport_set_global_canvas_transform ( viewport , sxform ) ;
2014-02-10 01:10:30 +00:00
}
2017-03-05 15:44:50 +00:00
void Viewport : : set_global_canvas_transform ( const Transform2D & p_transform ) {
global_canvas_transform = p_transform ;
2014-02-10 01:10:30 +00:00
_update_global_transform ( ) ;
}
2017-03-05 15:44:50 +00:00
Transform2D Viewport : : get_global_canvas_transform ( ) const {
2014-02-10 01:10:30 +00:00
return global_canvas_transform ;
}
2020-04-28 15:04:07 +00:00
void Viewport : : _camera_2d_set ( Camera2D * p_camera_2d ) {
camera_2d = p_camera_2d ;
}
2020-12-31 20:34:09 +00:00
void Viewport : : _listener_2d_set ( Listener2D * p_listener ) {
if ( listener_2d = = p_listener ) {
return ;
} else if ( listener_2d ) {
listener_2d - > clear_current ( ) ;
}
listener_2d = p_listener ;
}
void Viewport : : _listener_2d_remove ( Listener2D * p_listener ) {
if ( listener_2d = = p_listener ) {
listener_2d = nullptr ;
}
}
2018-08-24 22:03:26 +00: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 01:10:30 +00:00
void Viewport : : set_transparent_background ( bool p_enable ) {
2017-03-05 15:44:50 +00:00
transparent_bg = p_enable ;
2020-03-27 18:21:27 +00:00
RS : : get_singleton ( ) - > viewport_set_transparent_background ( viewport , p_enable ) ;
2014-02-10 01:10:30 +00:00
}
bool Viewport : : has_transparent_background ( ) const {
return transparent_bg ;
}
2017-03-05 15:44:50 +00:00
void Viewport : : set_world_2d ( const Ref < World2D > & p_world_2d ) {
2020-05-14 14:41:43 +00:00
if ( world_2d = = p_world_2d ) {
2016-07-13 18:51:38 +00:00
return ;
2020-05-14 14:41:43 +00:00
}
2016-07-13 18:51:38 +00:00
2017-03-05 15:44:50 +00:00
if ( parent & & parent - > find_world_2d ( ) = = p_world_2d ) {
2021-08-02 17:31:51 +00:00
WARN_PRINT ( " Unable to use parent world_2d as world_2d " ) ;
2016-07-13 18:51:38 +00:00
return ;
}
if ( is_inside_tree ( ) ) {
2020-03-27 18:21:27 +00:00
RenderingServer : : get_singleton ( ) - > viewport_remove_canvas ( viewport , current_canvas ) ;
2016-07-13 18:51:38 +00:00
}
2020-05-14 14:41:43 +00:00
if ( p_world_2d . is_valid ( ) ) {
2017-03-05 15:44:50 +00:00
world_2d = p_world_2d ;
2020-05-14 14:41:43 +00:00
} else {
2021-03-15 11:45:28 +00:00
WARN_PRINT ( " Invalid world_2d " ) ;
2017-03-05 15:44:50 +00:00
world_2d = Ref < World2D > ( memnew ( World2D ) ) ;
2016-07-13 18:51:38 +00:00
}
2014-02-10 01:10:30 +00:00
_update_listener_2d ( ) ;
2016-07-13 18:51:38 +00:00
if ( is_inside_tree ( ) ) {
2017-03-05 15:44:50 +00:00
current_canvas = find_world_2d ( ) - > get_canvas ( ) ;
2020-03-27 18:21:27 +00:00
RenderingServer : : get_singleton ( ) - > viewport_attach_canvas ( viewport , current_canvas ) ;
2014-02-10 01:10:30 +00:00
}
}
2017-03-05 15:44:50 +00:00
Ref < World2D > Viewport : : find_world_2d ( ) const {
2020-05-14 14:41:43 +00:00
if ( world_2d . is_valid ( ) ) {
2014-02-10 01:10:30 +00:00
return world_2d ;
2020-05-14 14:41:43 +00:00
} else if ( parent ) {
2014-02-10 01:10:30 +00:00
return parent - > find_world_2d ( ) ;
2020-05-14 14:41:43 +00:00
} else {
2014-02-10 01:10:30 +00:00
return Ref < World2D > ( ) ;
2020-05-14 14:41:43 +00:00
}
2014-02-10 01:10:30 +00:00
}
2017-03-05 15:44:50 +00:00
void Viewport : : _propagate_viewport_notification ( Node * p_node , int p_what ) {
2016-05-11 14:46:08 +00:00
p_node - > notification ( p_what ) ;
2017-03-05 15:44:50 +00:00
for ( int i = 0 ; i < p_node - > get_child_count ( ) ; i + + ) {
2016-05-11 14:46:08 +00:00
Node * c = p_node - > get_child ( i ) ;
2020-05-14 14:41:43 +00:00
if ( Object : : cast_to < Viewport > ( c ) ) {
2016-05-11 14:46:08 +00:00
continue ;
2020-05-14 14:41:43 +00:00
}
2017-03-05 15:44:50 +00:00
_propagate_viewport_notification ( c , p_what ) ;
2016-05-11 14:46:08 +00:00
}
}
2014-02-10 01:10:30 +00:00
2021-08-02 17:31:51 +00:00
Ref < World2D > Viewport : : get_world_2d ( ) const {
return world_2d ;
}
Camera2D * Viewport : : get_camera_2d ( ) const {
return camera_2d ;
}
Transform2D Viewport : : get_final_transform ( ) const {
return stretch_transform * global_canvas_transform ;
}
void Viewport : : _update_canvas_items ( Node * p_node ) {
2017-03-05 15:44:50 +00:00
if ( p_node ! = this ) {
2021-08-02 17:31:51 +00:00
Viewport * vp = Object : : cast_to < Viewport > ( p_node ) ;
if ( vp ) {
2014-02-10 01:10:30 +00:00
return ;
2020-05-14 14:41:43 +00:00
}
2014-02-10 01:10:30 +00:00
2021-08-02 17:31:51 +00:00
CanvasItem * ci = Object : : cast_to < CanvasItem > ( p_node ) ;
if ( ci ) {
ci - > update ( ) ;
2014-02-10 01:10:30 +00:00
}
2020-05-14 14:41:43 +00:00
}
2014-02-10 01:10:30 +00:00
2021-08-02 17:31:51 +00:00
int cc = p_node - > get_child_count ( ) ;
2014-02-10 01:10:30 +00:00
2021-08-02 17:31:51 +00:00
for ( int i = 0 ; i < cc ; i + + ) {
_update_canvas_items ( p_node - > get_child ( i ) ) ;
2019-11-29 06:41:25 +00:00
}
2021-08-02 17:31:51 +00:00
}
2019-11-29 06:41:25 +00:00
2021-08-02 17:31:51 +00:00
Ref < ViewportTexture > Viewport : : get_texture ( ) const {
return default_texture ;
}
2014-02-10 01:10:30 +00:00
2021-08-02 17:31:51 +00:00
void Viewport : : set_shadow_atlas_size ( int p_size ) {
shadow_atlas_size = p_size ;
RS : : get_singleton ( ) - > viewport_set_shadow_atlas_size ( viewport , p_size , shadow_atlas_16_bits ) ;
}
2019-11-29 06:41:25 +00:00
2021-08-02 17:31:51 +00:00
int Viewport : : get_shadow_atlas_size ( ) const {
return shadow_atlas_size ;
}
2014-02-10 01:10:30 +00:00
2021-08-02 17:31:51 +00:00
void Viewport : : set_shadow_atlas_16_bits ( bool p_16_bits ) {
if ( shadow_atlas_16_bits = = p_16_bits ) {
return ;
2014-02-10 01:10:30 +00:00
}
2021-08-02 17:31:51 +00:00
shadow_atlas_16_bits = p_16_bits ;
RS : : get_singleton ( ) - > viewport_set_shadow_atlas_size ( viewport , shadow_atlas_size , shadow_atlas_16_bits ) ;
2014-02-10 01:10:30 +00:00
}
2021-08-02 17:31:51 +00:00
bool Viewport : : get_shadow_atlas_16_bits ( ) const {
return shadow_atlas_16_bits ;
2021-01-24 19:00:20 +00:00
}
2017-03-05 15:44:50 +00:00
void Viewport : : set_shadow_atlas_quadrant_subdiv ( int p_quadrant , ShadowAtlasQuadrantSubdiv p_subdiv ) {
ERR_FAIL_INDEX ( p_quadrant , 4 ) ;
ERR_FAIL_INDEX ( p_subdiv , SHADOW_ATLAS_QUADRANT_SUBDIV_MAX ) ;
2014-05-14 04:22:15 +00:00
2020-05-14 14:41:43 +00:00
if ( shadow_atlas_quadrant_subdiv [ p_quadrant ] = = p_subdiv ) {
2016-11-10 02:55:06 +00:00
return ;
2020-05-14 14:41:43 +00:00
}
2014-05-14 04:22:15 +00:00
2017-03-05 15:44:50 +00:00
shadow_atlas_quadrant_subdiv [ p_quadrant ] = p_subdiv ;
static const int subdiv [ SHADOW_ATLAS_QUADRANT_SUBDIV_MAX ] = { 0 , 1 , 4 , 16 , 64 , 256 , 1024 } ;
2014-08-14 13:31:38 +00:00
2020-03-27 18:21:27 +00:00
RS : : get_singleton ( ) - > viewport_set_shadow_atlas_quadrant_subdivision ( viewport , p_quadrant , subdiv [ p_subdiv ] ) ;
2014-08-14 13:31:38 +00:00
}
2020-05-14 12:29:06 +00:00
2017-03-05 15:44:50 +00:00
Viewport : : ShadowAtlasQuadrantSubdiv Viewport : : get_shadow_atlas_quadrant_subdiv ( int p_quadrant ) const {
ERR_FAIL_INDEX_V ( p_quadrant , 4 , SHADOW_ATLAS_QUADRANT_SUBDIV_DISABLED ) ;
2016-11-10 02:55:06 +00:00
return shadow_atlas_quadrant_subdiv [ p_quadrant ] ;
}
2017-01-11 03:52:51 +00:00
Transform2D Viewport : : _get_input_pre_xform ( ) const {
Transform2D pre_xf ;
2014-04-18 14:43:54 +00:00
2020-03-12 12:37:40 +00:00
if ( to_screen_rect . size . x ! = 0 & & to_screen_rect . size . y ! = 0 ) {
2017-06-03 22:25:13 +00:00
pre_xf . elements [ 2 ] = - to_screen_rect . position ;
2017-03-05 15:44:50 +00:00
pre_xf . scale ( size / to_screen_rect . size ) ;
2014-04-18 14:43:54 +00:00
}
return pre_xf ;
}
2017-05-20 15:38:03 +00:00
Ref < InputEvent > Viewport : : _make_input_local ( const Ref < InputEvent > & ev ) {
Transform2D ai = get_final_transform ( ) . affine_inverse ( ) * _get_input_pre_xform ( ) ;
2014-04-10 03:18:27 +00:00
2020-03-14 16:06:39 +00:00
return ev - > xformed_by ( ai ) ;
2014-04-10 03:18:27 +00:00
}
2017-03-29 15:29:38 +00:00
Vector2 Viewport : : get_mouse_position ( ) const {
2020-03-14 16:06:39 +00:00
return gui . last_mouse_pos ;
2015-05-12 11:17:09 +00:00
}
2017-03-05 15:44:50 +00:00
void Viewport : : warp_mouse ( const Vector2 & p_pos ) {
2015-02-14 22:22:06 +00:00
Vector2 gpos = ( get_final_transform ( ) . affine_inverse ( ) * _get_input_pre_xform ( ) ) . affine_inverse ( ) . xform ( p_pos ) ;
2020-04-28 13:19:37 +00:00
Input : : get_singleton ( ) - > warp_mouse_position ( gpos ) ;
2015-02-14 22:22:06 +00:00
}
2016-01-17 01:41:10 +00:00
void Viewport : : _gui_sort_roots ( ) {
2020-05-14 14:41:43 +00:00
if ( ! gui . roots_order_dirty ) {
2016-01-17 01:41:10 +00:00
return ;
2020-05-14 14:41:43 +00:00
}
2016-01-17 01:41:10 +00:00
gui . roots . sort_custom < Control : : CComparator > ( ) ;
2017-03-05 15:44:50 +00:00
gui . roots_order_dirty = false ;
2016-01-17 01:41:10 +00:00
}
void Viewport : : _gui_cancel_tooltip ( ) {
2020-11-02 16:18:29 +00:00
gui . tooltip_control = nullptr ;
2021-02-26 23:37:20 +00:00
if ( gui . tooltip_timer . is_valid ( ) ) {
gui . tooltip_timer - > release_connections ( ) ;
gui . tooltip_timer = Ref < SceneTreeTimer > ( ) ;
}
2016-01-25 13:30:03 +00:00
if ( gui . tooltip_popup ) {
gui . tooltip_popup - > queue_delete ( ) ;
2020-04-01 23:20:12 +00:00
gui . tooltip_popup = nullptr ;
gui . tooltip_label = nullptr ;
2016-01-25 13:30:03 +00:00
}
2016-01-17 01:41:10 +00:00
}
2020-11-02 16:18:29 +00:00
String Viewport : : _gui_get_tooltip ( Control * p_control , const Vector2 & p_pos , Control * * r_tooltip_owner ) {
2018-06-07 15:46:14 +00:00
Vector2 pos = p_pos ;
String tooltip ;
while ( p_control ) {
tooltip = p_control - > get_tooltip ( pos ) ;
2021-09-10 14:58:33 +00:00
// Temporary solution for PopupMenus.
2021-08-20 09:49:19 +00:00
PopupMenu * menu = Object : : cast_to < PopupMenu > ( this ) ;
if ( menu ) {
tooltip = menu - > get_tooltip ( pos ) ;
}
2020-11-02 16:18:29 +00:00
if ( r_tooltip_owner ) {
* r_tooltip_owner = p_control ;
2018-07-20 21:14:33 +00:00
}
2020-11-02 16:18:29 +00:00
// If we found a tooltip, we stop here.
2020-12-15 12:04:21 +00:00
if ( ! tooltip . is_empty ( ) ) {
2018-06-07 15:46:14 +00:00
break ;
2020-05-14 14:41:43 +00:00
}
2020-11-02 16:18:29 +00:00
// Otherwise, we check parent controls unless some conditions prevent it.
2018-06-07 15:46:14 +00:00
2020-05-14 14:41:43 +00:00
if ( p_control - > data . mouse_filter = = Control : : MOUSE_FILTER_STOP ) {
2018-06-07 15:46:14 +00:00
break ;
2020-05-14 14:41:43 +00:00
}
2020-10-01 07:17:33 +00:00
if ( p_control - > is_set_as_top_level ( ) ) {
2018-06-07 15:46:14 +00:00
break ;
2020-05-14 14:41:43 +00:00
}
2018-06-07 15:46:14 +00:00
2020-11-02 16:18:29 +00:00
// Transform cursor pos for parent control.
pos = p_control - > get_transform ( ) . xform ( pos ) ;
2018-06-07 15:46:14 +00:00
p_control = p_control - > get_parent_control ( ) ;
}
return tooltip ;
}
2016-01-17 01:41:10 +00:00
void Viewport : : _gui_show_tooltip ( ) {
2020-11-02 16:18:29 +00:00
if ( ! gui . tooltip_control ) {
2016-01-17 01:41:10 +00:00
return ;
}
2020-11-02 16:18:29 +00:00
// Get the Control under cursor and the relevant tooltip text, if any.
Control * tooltip_owner = nullptr ;
String tooltip_text = _gui_get_tooltip (
gui . tooltip_control ,
gui . tooltip_control - > get_global_transform ( ) . xform_inv ( gui . last_mouse_pos ) ,
& tooltip_owner ) ;
2021-01-05 14:14:27 +00:00
tooltip_text = tooltip_text . strip_edges ( ) ;
2020-12-15 12:04:21 +00:00
if ( tooltip_text . is_empty ( ) ) {
2020-11-02 16:18:29 +00:00
return ; // Nothing to show.
2020-05-14 14:41:43 +00:00
}
2016-01-17 01:41:10 +00:00
2020-11-02 16:18:29 +00:00
// Remove previous popup if we change something.
2016-01-25 13:30:03 +00:00
if ( gui . tooltip_popup ) {
memdelete ( gui . tooltip_popup ) ;
2020-04-01 23:20:12 +00:00
gui . tooltip_popup = nullptr ;
gui . tooltip_label = nullptr ;
2016-01-25 13:30:03 +00:00
}
2016-01-17 01:41:10 +00:00
2020-11-02 16:18:29 +00:00
if ( ! tooltip_owner ) {
2017-08-21 01:48:03 +00:00
return ;
}
2021-04-25 14:53:50 +00:00
// Popup window which houses the tooltip content.
TooltipPanel * panel = memnew ( TooltipPanel ) ;
2020-11-02 16:18:29 +00: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.
Control * base_tooltip = tooltip_owner - > make_custom_tooltip ( tooltip_text ) ;
2018-07-20 21:14:33 +00:00
2020-11-02 16:18:29 +00:00
// If no custom tooltip is given, use a default implementation.
2020-03-20 20:51:53 +00:00
if ( ! base_tooltip ) {
2018-07-20 21:14:33 +00:00
gui . tooltip_label = memnew ( TooltipLabel ) ;
2021-05-27 17:31:33 +00:00
gui . tooltip_label - > set_auto_translate ( gui . tooltip_control - > is_auto_translating ( ) ) ;
2020-11-02 16:18:29 +00:00
gui . tooltip_label - > set_text ( tooltip_text ) ;
2020-03-20 20:51:53 +00:00
base_tooltip = gui . tooltip_label ;
2021-04-25 14:53:50 +00:00
panel - > connect ( " mouse_entered " , callable_mp ( this , & Viewport : : _gui_cancel_tooltip ) ) ;
2018-07-20 21:14:33 +00:00
}
2016-01-25 13:30:03 +00:00
2020-12-22 16:24:29 +00:00
base_tooltip - > set_anchors_and_offsets_preset ( Control : : PRESET_WIDE ) ;
2020-03-20 20:51:53 +00:00
panel - > set_transient ( false ) ;
panel - > set_flag ( Window : : FLAG_NO_FOCUS , true ) ;
panel - > set_wrap_controls ( true ) ;
panel - > add_child ( base_tooltip ) ;
gui . tooltip_popup = panel ;
2020-11-02 16:18:29 +00:00
tooltip_owner - > add_child ( gui . tooltip_popup ) ;
2016-01-17 01:41:10 +00:00
2019-03-02 11:11:42 +00:00
Point2 tooltip_offset = ProjectSettings : : get_singleton ( ) - > get ( " display/mouse_cursor/tooltip_position_offset " ) ;
2020-03-20 20:51:53 +00:00
Rect2 r ( gui . tooltip_pos + tooltip_offset , gui . tooltip_popup - > get_contents_minimum_size ( ) ) ;
2020-08-20 12:08:28 +00:00
Window * window = gui . tooltip_popup - > get_parent_visible_window ( ) ;
Rect2i vr = window - > get_usable_parent_rect ( ) ;
2020-03-20 20:51:53 +00:00
2020-05-14 14:41:43 +00:00
if ( r . size . x + r . position . x > vr . size . x + vr . position . x ) {
2020-03-20 20:51:53 +00:00
r . position . x = vr . position . x + vr . size . x - r . size . x ;
2020-05-14 14:41:43 +00:00
} else if ( r . position . x < vr . position . x ) {
2020-03-20 20:51:53 +00:00
r . position . x = vr . position . x ;
2020-05-14 14:41:43 +00:00
}
2020-03-20 20:51:53 +00:00
2020-05-14 14:41:43 +00:00
if ( r . size . y + r . position . y > vr . size . y + vr . position . y ) {
2020-03-20 20:51:53 +00:00
r . position . y = vr . position . y + vr . size . y - r . size . y ;
2020-05-14 14:41:43 +00:00
} else if ( r . position . y < vr . position . y ) {
2020-03-20 20:51:53 +00:00
r . position . y = vr . position . y ;
2020-05-14 14:41:43 +00:00
}
2020-03-20 20:51:53 +00:00
2020-08-20 12:08:28 +00:00
gui . tooltip_popup - > set_current_screen ( window - > get_current_screen ( ) ) ;
2020-03-20 20:51:53 +00:00
gui . tooltip_popup - > set_position ( r . position ) ;
2016-01-17 01:41:10 +00:00
gui . tooltip_popup - > set_size ( r . size ) ;
gui . tooltip_popup - > show ( ) ;
2020-03-20 20:51:53 +00:00
gui . tooltip_popup - > child_controls_changed ( ) ;
2016-01-17 01:41:10 +00:00
}
2017-05-20 15:38:03 +00:00
void Viewport : : _gui_call_input ( Control * p_control , const Ref < InputEvent > & p_input ) {
Ref < InputEvent > ev = p_input ;
2016-06-27 12:59:43 +00:00
2021-09-10 14:58:33 +00:00
// Mouse wheel events can't be stopped.
2017-05-20 15:38:03 +00:00
Ref < InputEventMouseButton > mb = p_input ;
bool cant_stop_me_now = ( mb . is_valid ( ) & &
2021-01-08 03:37:37 +00:00
( mb - > get_button_index ( ) = = MOUSE_BUTTON_WHEEL_DOWN | |
mb - > get_button_index ( ) = = MOUSE_BUTTON_WHEEL_UP | |
mb - > get_button_index ( ) = = MOUSE_BUTTON_WHEEL_LEFT | |
mb - > get_button_index ( ) = = MOUSE_BUTTON_WHEEL_RIGHT ) ) ;
2018-05-18 16:47:39 +00:00
Ref < InputEventPanGesture > pn = p_input ;
cant_stop_me_now = pn . is_valid ( ) | | cant_stop_me_now ;
2017-05-20 15:38:03 +00:00
2020-04-01 23:20:12 +00:00
bool ismouse = ev . is_valid ( ) | | Object : : cast_to < InputEventMouseMotion > ( * p_input ) ! = nullptr ;
2016-06-20 20:16:52 +00:00
2017-03-05 15:44:50 +00:00
CanvasItem * ci = p_control ;
while ( ci ) {
2017-08-24 20:58:51 +00:00
Control * control = Object : : cast_to < Control > ( ci ) ;
2016-06-07 05:39:40 +00:00
if ( control ) {
2018-11-16 16:46:42 +00:00
if ( control - > data . mouse_filter ! = Control : : MOUSE_FILTER_IGNORE ) {
2021-08-22 15:37:22 +00:00
control - > _call_gui_input ( ev ) ;
2018-11-16 16:46:42 +00:00
}
2018-06-07 15:46:14 +00:00
2020-10-01 07:17:33 +00:00
if ( ! control - > is_inside_tree ( ) | | control - > is_set_as_top_level ( ) ) {
2016-06-07 05:39:40 +00:00
break ;
2020-05-14 14:41:43 +00:00
}
if ( gui . key_event_accepted ) {
2016-06-07 05:39:40 +00:00
break ;
2020-05-14 14:41:43 +00:00
}
if ( ! cant_stop_me_now & & control - > data . mouse_filter = = Control : : MOUSE_FILTER_STOP & & ismouse ) {
2016-06-07 05:39:40 +00:00
break ;
2020-05-14 14:41:43 +00:00
}
2016-06-07 05:39:40 +00:00
}
2020-10-01 07:17:33 +00:00
if ( ci - > is_set_as_top_level ( ) ) {
2016-06-07 05:39:40 +00:00
break ;
2020-05-14 14:41:43 +00:00
}
2016-06-07 05:39:40 +00:00
2021-09-10 14:58:33 +00:00
ev = ev - > xformed_by ( ci - > get_transform ( ) ) ; // Transform event upwards.
2017-03-05 15:44:50 +00:00
ci = ci - > get_parent_item ( ) ;
2016-01-17 01:41:10 +00:00
}
}
2019-01-18 20:53:36 +00: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 14:41:43 +00:00
if ( ! control - > is_inside_tree ( ) ) {
2019-01-18 20:53:36 +00:00
break ;
2020-05-14 14:41:43 +00:00
}
2019-01-18 20:53:36 +00:00
2020-10-01 07:17:33 +00:00
if ( ! control - > is_inside_tree ( ) | | control - > is_set_as_top_level ( ) ) {
2019-01-18 20:53:36 +00:00
break ;
2020-05-14 14:41:43 +00:00
}
if ( control - > data . mouse_filter = = Control : : MOUSE_FILTER_STOP ) {
2019-01-18 20:53:36 +00:00
break ;
2020-05-14 14:41:43 +00:00
}
2019-01-18 20:53:36 +00:00
}
2020-10-01 07:17:33 +00:00
if ( ci - > is_set_as_top_level ( ) ) {
2019-01-18 20:53:36 +00:00
break ;
2020-05-14 14:41:43 +00:00
}
2019-01-18 20:53:36 +00:00
ci = ci - > get_parent_item ( ) ;
}
}
2020-05-14 12:29:06 +00:00
2021-07-19 20:09:23 +00:00
Control * Viewport : : gui_find_control ( const Point2 & p_global ) {
2021-09-10 14:58:33 +00:00
// Handle subwindows.
2016-01-25 13:39:55 +00:00
_gui_sort_roots ( ) ;
2017-03-05 15:44:50 +00:00
for ( List < Control * > : : Element * E = gui . roots . back ( ) ; E ; E = E - > prev ( ) ) {
2016-01-17 01:41:10 +00:00
Control * sw = E - > get ( ) ;
2020-05-14 14:41:43 +00:00
if ( ! sw - > is_visible_in_tree ( ) ) {
2016-01-17 01:41:10 +00:00
continue ;
2020-05-14 14:41:43 +00:00
}
2016-01-17 01:41:10 +00:00
2017-01-11 03:52:51 +00:00
Transform2D xform ;
2016-01-17 01:41:10 +00:00
CanvasItem * pci = sw - > get_parent_item ( ) ;
2020-05-14 14:41:43 +00:00
if ( pci ) {
2017-03-05 15:44:50 +00:00
xform = pci - > get_global_transform_with_canvas ( ) ;
2020-05-14 14:41:43 +00:00
} else {
2017-03-05 15:44:50 +00:00
xform = sw - > get_canvas_transform ( ) ;
2020-05-14 14:41:43 +00:00
}
2016-01-17 01:41:10 +00:00
2017-03-05 15:44:50 +00:00
Control * ret = _gui_find_control_at_pos ( sw , p_global , xform , gui . focus_inv_xform ) ;
2020-05-14 14:41:43 +00:00
if ( ret ) {
2016-01-17 01:41:10 +00:00
return ret ;
2020-05-14 14:41:43 +00:00
}
2016-01-17 01:41:10 +00:00
}
2020-04-01 23:20:12 +00:00
return nullptr ;
2016-01-17 01:41:10 +00:00
}
2017-03-05 15:44:50 +00:00
Control * Viewport : : _gui_find_control_at_pos ( CanvasItem * p_node , const Point2 & p_global , const Transform2D & p_xform , Transform2D & r_inv_xform ) {
2020-05-14 14:41:43 +00:00
if ( Object : : cast_to < Viewport > ( p_node ) ) {
2020-04-01 23:20:12 +00:00
return nullptr ;
2020-05-14 14:41:43 +00:00
}
2016-01-17 01:41:10 +00:00
2017-01-13 13:45:50 +00:00
if ( ! p_node - > is_visible ( ) ) {
2021-09-10 14:58:33 +00:00
return nullptr ; // Canvas item hidden, discard.
2016-01-17 01:41:10 +00:00
}
2017-01-11 03:52:51 +00:00
Transform2D matrix = p_xform * p_node - > get_transform ( ) ;
2016-10-08 10:33:10 +00:00
// matrix.basis_determinant() == 0.0f implies that node does not exist on scene
2020-05-14 14:41:43 +00:00
if ( matrix . basis_determinant ( ) = = 0.0f ) {
2020-04-01 23:20:12 +00:00
return nullptr ;
2020-05-14 14:41:43 +00:00
}
2016-01-17 01:41:10 +00:00
2018-08-24 07:35:07 +00:00
Control * c = Object : : cast_to < Control > ( p_node ) ;
2021-06-25 13:46:37 +00:00
if ( ! c | | ! c - > is_clipping_contents ( ) | | c - > has_point ( matrix . affine_inverse ( ) . xform ( p_global ) ) ) {
2017-03-05 15:44:50 +00:00
for ( int i = p_node - > get_child_count ( ) - 1 ; i > = 0 ; i - - ) {
2017-08-24 20:58:51 +00:00
CanvasItem * ci = Object : : cast_to < CanvasItem > ( p_node - > get_child ( i ) ) ;
2020-10-01 07:17:33 +00:00
if ( ! ci | | ci - > is_set_as_top_level ( ) ) {
2016-01-17 01:41:10 +00:00
continue ;
2020-05-14 14:41:43 +00:00
}
2016-01-17 01:41:10 +00:00
2017-03-05 15:44:50 +00:00
Control * ret = _gui_find_control_at_pos ( ci , p_global , matrix , r_inv_xform ) ;
2020-05-14 14:41:43 +00:00
if ( ret ) {
2016-01-17 01:41:10 +00:00
return ret ;
2020-05-14 14:41:43 +00:00
}
2016-01-17 01:41:10 +00:00
}
}
2021-02-24 11:47:14 +00:00
if ( ! c | | c - > data . mouse_filter = = Control : : MOUSE_FILTER_IGNORE ) {
2020-04-01 23:20:12 +00:00
return nullptr ;
2020-05-14 14:41:43 +00:00
}
2016-01-17 01:41:10 +00:00
matrix . affine_invert ( ) ;
2021-02-24 11:47:14 +00:00
if ( ! c - > has_point ( matrix . xform ( p_global ) ) ) {
return nullptr ;
}
2016-01-17 01:41:10 +00:00
2021-02-24 11:47:14 +00:00
Control * drag_preview = _gui_get_drag_preview ( ) ;
2021-06-18 22:02:50 +00:00
if ( ! drag_preview | | ( c ! = drag_preview & & ! drag_preview - > is_ancestor_of ( c ) ) ) {
2017-03-05 15:44:50 +00:00
r_inv_xform = matrix ;
2016-01-17 01:41:10 +00:00
return c ;
2020-05-14 14:41:43 +00:00
}
2021-02-24 11:47:14 +00:00
return nullptr ;
2016-01-17 01:41:10 +00:00
}
2017-03-05 15:44:50 +00:00
bool Viewport : : _gui_drop ( Control * p_at_control , Point2 p_at_pos , bool p_just_check ) {
2021-09-10 14:58:33 +00: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 02:12:08 +00:00
}
2021-09-10 14:58:33 +00:00
return true ;
2017-01-24 02:12:08 +00:00
}
2021-09-10 14:58:33 +00:00
if ( control - > data . mouse_filter = = Control : : MOUSE_FILTER_STOP ) {
2017-01-24 02:12:08 +00:00
break ;
2020-05-14 14:41:43 +00:00
}
2021-09-10 14:58:33 +00:00
}
p_at_pos = ci - > get_transform ( ) . xform ( p_at_pos ) ;
2017-01-24 02:12:08 +00:00
2021-09-10 14:58:33 +00:00
if ( ci - > is_set_as_top_level ( ) ) {
break ;
2017-01-24 02:12:08 +00:00
}
2021-09-10 14:58:33 +00:00
ci = ci - > get_parent_item ( ) ;
2017-01-24 02:12:08 +00:00
}
return false ;
}
2017-05-20 15:38:03 +00:00
void Viewport : : _gui_input_event ( Ref < InputEvent > p_event ) {
2019-11-07 09:37:44 +00:00
ERR_FAIL_COND ( p_event . is_null ( ) ) ;
2019-06-22 12:52:51 +00:00
2017-05-20 15:38:03 +00:00
Ref < InputEventMouseButton > mb = p_event ;
if ( mb . is_valid ( ) ) {
gui . key_event_accepted = false ;
2016-01-17 01:41:10 +00:00
2020-08-06 13:44:05 +00:00
Control * over = nullptr ;
2017-06-03 08:54:24 +00:00
Point2 mpos = mb - > get_position ( ) ;
2021-04-25 12:44:02 +00:00
gui . last_mouse_pos = mpos ;
2017-05-20 15:38:03 +00:00
if ( mb - > is_pressed ( ) ) {
Size2 pos = mpos ;
2018-11-28 12:31:17 +00:00
if ( gui . mouse_focus_mask ) {
2021-09-10 14:58:33 +00:00
// Do not steal mouse focus and stuff while a focus mask exists.
gui . mouse_focus_mask | = 1 < < ( mb - > get_button_index ( ) - 1 ) ; // Add the button to the mask.
2017-05-20 15:38:03 +00:00
} else {
2021-07-19 20:09:23 +00:00
gui . mouse_focus = gui_find_control ( pos ) ;
2018-10-26 19:23:47 +00:00
gui . last_mouse_focus = gui . mouse_focus ;
2016-01-17 01:41:10 +00:00
2017-05-20 15:38:03 +00:00
if ( ! gui . mouse_focus ) {
2019-03-04 13:26:48 +00:00
gui . mouse_focus_mask = 0 ;
2017-05-20 15:38:03 +00:00
return ;
}
2016-01-17 01:41:10 +00:00
2019-03-04 13:26:48 +00:00
gui . mouse_focus_mask = 1 < < ( mb - > get_button_index ( ) - 1 ) ;
2021-01-08 03:37:37 +00:00
if ( mb - > get_button_index ( ) = = MOUSE_BUTTON_LEFT ) {
2017-05-20 15:38:03 +00:00
gui . drag_accum = Vector2 ( ) ;
gui . drag_attempted = false ;
2016-01-17 01:41:10 +00:00
}
2017-05-20 15:38:03 +00:00
}
2021-09-10 14:58:33 +00:00
mb = mb - > xformed_by ( Transform2D ( ) ) ; // Make a copy of the event.
2017-05-20 15:38:03 +00:00
2017-06-03 08:54:24 +00:00
mb - > set_global_position ( pos ) ;
2016-01-17 01:41:10 +00:00
2017-05-20 15:38:03 +00:00
pos = gui . focus_inv_xform . xform ( pos ) ;
2016-01-17 01:41:10 +00:00
2017-06-03 08:54:24 +00:00
mb - > set_position ( pos ) ;
2016-01-17 01:41:10 +00:00
# ifdef DEBUG_ENABLED
2020-02-27 02:30:20 +00:00
if ( EngineDebugger : : get_singleton ( ) & & gui . mouse_focus ) {
2017-05-20 15:38:03 +00:00
Array arr ;
arr . push_back ( gui . mouse_focus - > get_path ( ) ) ;
arr . push_back ( gui . mouse_focus - > get_class ( ) ) ;
2020-02-27 02:30:20 +00:00
EngineDebugger : : get_singleton ( ) - > send_message ( " scene:click_ctrl " , arr ) ;
2017-05-20 15:38:03 +00:00
}
2016-01-17 01:41:10 +00:00
# endif
2021-09-10 14:58:33 +00:00
if ( mb - > get_button_index ( ) = = MOUSE_BUTTON_LEFT ) { // Assign focus.
2017-05-20 15:38:03 +00:00
CanvasItem * ci = gui . mouse_focus ;
while ( ci ) {
2017-08-24 20:58:51 +00:00
Control * control = Object : : cast_to < Control > ( ci ) ;
2017-05-20 15:38:03 +00:00
if ( control ) {
if ( control - > get_focus_mode ( ) ! = Control : : FOCUS_NONE ) {
if ( control ! = gui . key_focus ) {
control - > grab_focus ( ) ;
2017-01-21 22:00:25 +00:00
}
2017-05-20 15:38:03 +00:00
break ;
2017-01-21 22:00:25 +00:00
}
2020-05-14 14:41:43 +00:00
if ( control - > data . mouse_filter = = Control : : MOUSE_FILTER_STOP ) {
2017-01-21 22:00:25 +00:00
break ;
2020-05-14 14:41:43 +00:00
}
2017-01-21 22:00:25 +00:00
}
2016-01-17 01:41:10 +00:00
2020-10-01 07:17:33 +00:00
if ( ci - > is_set_as_top_level ( ) ) {
2017-05-20 15:38:03 +00:00
break ;
2020-05-14 14:41:43 +00:00
}
2016-01-17 01:41:10 +00:00
2017-05-20 15:38:03 +00:00
ci = ci - > get_parent_item ( ) ;
}
}
2016-01-17 01:41:10 +00:00
2018-12-01 13:25:43 +00:00
if ( gui . mouse_focus & & gui . mouse_focus - > can_process ( ) ) {
2017-05-20 15:38:03 +00:00
_gui_call_input ( gui . mouse_focus , mb ) ;
}
2016-07-01 13:34:38 +00:00
2018-11-15 16:54:26 +00:00
set_input_as_handled ( ) ;
2016-07-01 13:34:38 +00:00
2021-01-08 03:37:37 +00:00
if ( gui . drag_data . get_type ( ) ! = Variant : : NIL & & mb - > get_button_index ( ) = = MOUSE_BUTTON_LEFT ) {
2021-09-10 14:58:33 +00:00
// Alternate drop use (when using force_drag(), as proposed by #5342).
2017-05-20 15:38:03 +00:00
if ( gui . mouse_focus ) {
_gui_drop ( gui . mouse_focus , pos , false ) ;
2016-07-01 13:34:38 +00:00
}
2017-05-20 15:38:03 +00:00
gui . drag_data = Variant ( ) ;
2018-08-24 13:29:27 +00:00
gui . dragging = false ;
2016-01-17 01:41:10 +00:00
2021-02-24 11:47:14 +00:00
Control * drag_preview = _gui_get_drag_preview ( ) ;
if ( drag_preview ) {
memdelete ( drag_preview ) ;
gui . drag_preview_id = ObjectID ( ) ;
2017-05-20 15:38:03 +00:00
}
_propagate_viewport_notification ( this , NOTIFICATION_DRAG_END ) ;
2021-09-10 14:58:33 +00:00
// Change mouse accordingly.
2017-05-20 15:38:03 +00:00
}
2016-01-17 01:41:10 +00:00
2017-05-20 15:38:03 +00:00
_gui_cancel_tooltip ( ) ;
} else {
2021-01-08 03:37:37 +00:00
if ( gui . drag_data . get_type ( ) ! = Variant : : NIL & & mb - > get_button_index ( ) = = MOUSE_BUTTON_LEFT ) {
2020-03-24 23:15:35 +00:00
if ( gui . drag_mouse_over ) {
_gui_drop ( gui . drag_mouse_over , gui . drag_mouse_over_pos , false ) ;
2016-07-01 13:34:38 +00:00
}
2021-02-24 11:47:14 +00:00
Control * drag_preview = _gui_get_drag_preview ( ) ;
if ( drag_preview ) {
memdelete ( drag_preview ) ;
gui . drag_preview_id = ObjectID ( ) ;
2016-01-17 01:41:10 +00:00
}
2017-05-20 15:38:03 +00:00
gui . drag_data = Variant ( ) ;
2018-08-24 13:29:27 +00:00
gui . dragging = false ;
2020-03-24 23:15:35 +00:00
gui . drag_mouse_over = nullptr ;
2017-05-20 15:38:03 +00:00
_propagate_viewport_notification ( this , NOTIFICATION_DRAG_END ) ;
2021-09-10 14:58:33 +00:00
// Change mouse accordingly.
2017-05-20 15:38:03 +00:00
}
2016-01-17 01:41:10 +00:00
2021-09-10 14:58:33 +00:00
gui . mouse_focus_mask & = ~ ( 1 < < ( mb - > get_button_index ( ) - 1 ) ) ; // Remove from mask.
2018-11-28 12:31:17 +00:00
2017-05-20 15:38:03 +00:00
if ( ! gui . mouse_focus ) {
2021-09-10 14:58:33 +00:00
// Release event is only sent if a mouse focus (previously pressed button) exists.
2017-05-20 15:38:03 +00:00
return ;
}
2016-01-17 01:41:10 +00:00
2017-05-20 15:38:03 +00:00
Size2 pos = mpos ;
2016-01-17 01:41:10 +00:00
2021-09-10 14:58:33 +00:00
mb = mb - > xformed_by ( Transform2D ( ) ) ; // Make a copy.
2017-06-03 08:54:24 +00:00
mb - > set_global_position ( pos ) ;
2017-05-20 15:38:03 +00:00
pos = gui . focus_inv_xform . xform ( pos ) ;
2017-06-03 08:54:24 +00:00
mb - > set_position ( pos ) ;
2016-01-17 01:41:10 +00:00
2017-12-21 14:03:17 +00:00
Control * mouse_focus = gui . mouse_focus ;
2016-01-17 01:41:10 +00:00
2021-09-10 14:58:33 +00: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.
2018-11-28 12:31:17 +00:00
if ( gui . mouse_focus_mask = = 0 ) {
2020-04-01 23:20:12 +00:00
gui . mouse_focus = nullptr ;
2020-03-20 02:32:09 +00:00
gui . forced_mouse_focus = false ;
2017-05-20 15:38:03 +00:00
}
2016-01-17 01:41:10 +00:00
2018-12-03 00:38:54 +00:00
if ( mouse_focus & & mouse_focus - > can_process ( ) ) {
2017-12-21 14:03:17 +00:00
_gui_call_input ( mouse_focus , mb ) ;
}
2020-08-06 13:44:05 +00:00
// In case the mouse was released after for example dragging a scrollbar,
// check whether the current control is different from the stored one. If
// it is different, rather than wait for it to be updated the next time the
// mouse is moved, notify the control so that it can e.g. drop the highlight.
// This code is duplicated from the mm.is_valid()-case further below.
if ( gui . mouse_focus ) {
over = gui . mouse_focus ;
} else {
2021-07-19 20:09:23 +00:00
over = gui_find_control ( mpos ) ;
2020-08-06 13:44:05 +00:00
}
if ( gui . mouse_focus_mask = = 0 & & over ! = gui . mouse_over ) {
if ( gui . mouse_over ) {
_gui_call_notification ( gui . mouse_over , Control : : NOTIFICATION_MOUSE_EXIT ) ;
}
_gui_cancel_tooltip ( ) ;
if ( over ) {
_gui_call_notification ( over , Control : : NOTIFICATION_MOUSE_ENTER ) ;
}
}
gui . mouse_over = over ;
2018-11-15 16:54:26 +00:00
set_input_as_handled ( ) ;
2017-05-20 15:38:03 +00:00
}
}
2016-01-17 01:41:10 +00:00
2017-05-20 15:38:03 +00:00
Ref < InputEventMouseMotion > mm = p_event ;
if ( mm . is_valid ( ) ) {
gui . key_event_accepted = false ;
2017-06-03 08:54:24 +00:00
Point2 mpos = mm - > get_position ( ) ;
2017-01-24 02:12:08 +00:00
2017-05-20 15:38:03 +00:00
gui . last_mouse_pos = mpos ;
2017-01-24 02:12:08 +00:00
2020-04-01 23:20:12 +00:00
Control * over = nullptr ;
2017-01-24 02:12:08 +00:00
2021-09-10 14:58:33 +00:00
// Drag & drop.
2021-01-08 03:37:37 +00:00
if ( ! gui . drag_attempted & & gui . mouse_focus & & mm - > get_button_mask ( ) & MOUSE_BUTTON_MASK_LEFT ) {
2017-05-20 15:38:03 +00:00
gui . drag_accum + = mm - > get_relative ( ) ;
float len = gui . drag_accum . length ( ) ;
if ( len > 10 ) {
2021-09-10 14:58:33 +00:00
{ // Attempt grab, try parent controls too.
2017-05-20 15:38:03 +00:00
CanvasItem * ci = gui . mouse_focus ;
while ( ci ) {
2017-08-24 20:58:51 +00:00
Control * control = Object : : cast_to < Control > ( ci ) ;
2017-05-20 15:38:03 +00:00
if ( control ) {
2018-08-24 13:29:27 +00:00
gui . dragging = true ;
2017-05-20 15:38:03 +00:00
gui . drag_data = control - > get_drag_data ( control - > get_global_transform_with_canvas ( ) . affine_inverse ( ) . xform ( mpos ) - gui . drag_accum ) ;
if ( gui . drag_data . get_type ( ) ! = Variant : : NIL ) {
2020-04-01 23:20:12 +00:00
gui . mouse_focus = nullptr ;
2020-03-20 02:32:09 +00:00
gui . forced_mouse_focus = false ;
2018-11-28 12:31:17 +00:00
gui . mouse_focus_mask = 0 ;
2018-11-19 21:37:39 +00:00
break ;
2018-08-24 13:29:27 +00:00
} else {
2021-02-24 11:47:14 +00:00
Control * drag_preview = _gui_get_drag_preview ( ) ;
if ( drag_preview ) {
2018-11-19 21:37:39 +00:00
ERR_PRINT ( " Don't set a drag preview and return null data. Preview was deleted and drag request ignored. " ) ;
2021-02-24 11:47:14 +00:00
memdelete ( drag_preview ) ;
gui . drag_preview_id = ObjectID ( ) ;
2018-11-19 21:37:39 +00:00
}
2018-08-24 13:29:27 +00:00
gui . dragging = false ;
2017-01-24 02:12:08 +00:00
}
2020-05-14 14:41:43 +00:00
if ( control - > data . mouse_filter = = Control : : MOUSE_FILTER_STOP ) {
2017-01-24 02:12:08 +00:00
break ;
2020-05-14 14:41:43 +00:00
}
2017-01-24 02:12:08 +00:00
}
2020-10-01 07:17:33 +00:00
if ( ci - > is_set_as_top_level ( ) ) {
2017-05-20 15:38:03 +00:00
break ;
2020-05-14 14:41:43 +00:00
}
2017-01-24 02:12:08 +00:00
2017-05-20 15:38:03 +00:00
ci = ci - > get_parent_item ( ) ;
2016-05-11 14:46:08 +00:00
}
2016-01-17 01:41:10 +00:00
}
2017-05-20 15:38:03 +00:00
gui . drag_attempted = true ;
if ( gui . drag_data . get_type ( ) ! = Variant : : NIL ) {
_propagate_viewport_notification ( this , NOTIFICATION_DRAG_BEGIN ) ;
}
2016-01-17 01:41:10 +00:00
}
2017-05-20 15:38:03 +00:00
}
2016-01-17 01:41:10 +00:00
2020-08-06 13:44:05 +00:00
// These sections of code are reused in the mb.is_valid() case further up
// for the purpose of notifying controls about potential changes in focus
// when the mousebutton is released.
2017-05-20 15:38:03 +00:00
if ( gui . mouse_focus ) {
over = gui . mouse_focus ;
} else {
2021-07-19 20:09:23 +00:00
over = gui_find_control ( mpos ) ;
2017-05-20 15:38:03 +00:00
}
2016-01-17 01:41:10 +00:00
2017-05-20 15:38:03 +00:00
if ( over ! = gui . mouse_over ) {
2019-01-18 20:53:36 +00:00
if ( gui . mouse_over ) {
_gui_call_notification ( gui . mouse_over , Control : : NOTIFICATION_MOUSE_EXIT ) ;
}
2016-05-21 13:29:25 +00:00
2017-05-20 15:38:03 +00:00
_gui_cancel_tooltip ( ) ;
2016-01-17 01:41:10 +00:00
2019-01-18 20:53:36 +00:00
if ( over ) {
_gui_call_notification ( over , Control : : NOTIFICATION_MOUSE_ENTER ) ;
}
2017-05-20 15:38:03 +00:00
}
2016-01-17 01:41:10 +00:00
2017-05-20 15:38:03 +00:00
gui . mouse_over = over ;
2016-01-17 01:41:10 +00:00
2020-04-28 13:19:37 +00:00
DisplayServer : : CursorShape ds_cursor_shape = ( DisplayServer : : CursorShape ) Input : : get_singleton ( ) - > get_default_cursor_shape ( ) ;
2016-01-17 01:41:10 +00:00
2020-03-24 23:15:35 +00:00
if ( over ) {
Transform2D localizer = over - > get_global_transform_with_canvas ( ) . affine_inverse ( ) ;
Size2 pos = localizer . xform ( mpos ) ;
Vector2 speed = localizer . basis_xform ( mm - > get_speed ( ) ) ;
Vector2 rel = localizer . basis_xform ( mm - > get_relative ( ) ) ;
2016-01-17 01:41:10 +00:00
2021-09-10 14:58:33 +00:00
mm = mm - > xformed_by ( Transform2D ( ) ) ; // Make a copy.
2016-01-17 01:41:10 +00:00
2020-03-24 23:15:35 +00:00
mm - > set_global_position ( mpos ) ;
mm - > set_speed ( speed ) ;
mm - > set_relative ( rel ) ;
2016-01-17 01:41:10 +00:00
2020-03-24 23:15:35 +00:00
if ( mm - > get_button_mask ( ) = = 0 ) {
2021-09-10 14:58:33 +00:00
// Nothing pressed.
2016-07-19 04:27:12 +00:00
2020-03-24 23:15:35 +00:00
bool can_tooltip = true ;
2017-05-20 15:38:03 +00:00
2020-03-24 23:15:35 +00:00
bool is_tooltip_shown = false ;
2020-03-20 20:51:53 +00:00
2020-03-24 23:15:35 +00:00
if ( gui . tooltip_popup ) {
2020-11-02 16:18:29 +00:00
if ( can_tooltip & & gui . tooltip_control ) {
String tooltip = _gui_get_tooltip ( over , gui . tooltip_control - > get_global_transform ( ) . xform_inv ( mpos ) ) ;
2020-03-20 20:51:53 +00:00
2020-05-14 14:41:43 +00:00
if ( tooltip . length ( ) = = 0 ) {
2020-03-24 23:15:35 +00:00
_gui_cancel_tooltip ( ) ;
2020-05-14 14:41:43 +00:00
} else if ( gui . tooltip_label ) {
2020-03-24 23:15:35 +00:00
if ( tooltip = = gui . tooltip_label - > get_text ( ) ) {
2020-03-20 20:51:53 +00:00
is_tooltip_shown = true ;
}
} else {
2020-03-24 23:15:35 +00:00
Variant t = gui . tooltip_popup - > call ( " get_tooltip_text " ) ;
if ( t . get_type ( ) = = Variant : : STRING ) {
if ( tooltip = = String ( t ) ) {
is_tooltip_shown = true ;
}
} else {
2021-09-10 14:58:33 +00:00
is_tooltip_shown = true ; // Nothing to compare against, likely using custom control, so if it changes there is nothing we can do.
2020-03-24 23:15:35 +00:00
}
2020-03-20 20:51:53 +00:00
}
2020-05-14 14:41:43 +00:00
} else {
2020-03-24 23:15:35 +00:00
_gui_cancel_tooltip ( ) ;
2020-05-14 14:41:43 +00:00
}
2020-03-24 23:15:35 +00:00
}
if ( can_tooltip & & ! is_tooltip_shown ) {
2021-02-26 23:37:20 +00:00
if ( gui . tooltip_timer . is_valid ( ) ) {
gui . tooltip_timer - > release_connections ( ) ;
gui . tooltip_timer = Ref < SceneTreeTimer > ( ) ;
}
2020-11-02 16:18:29 +00:00
gui . tooltip_control = over ;
gui . tooltip_pos = over - > get_screen_transform ( ) . xform ( pos ) ;
2021-02-26 23:37:20 +00: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-24 23:15:35 +00:00
}
2017-05-20 15:38:03 +00:00
}
2016-07-18 20:14:57 +00:00
2020-03-24 23:15:35 +00:00
mm - > set_position ( pos ) ;
Control : : CursorShape cursor_shape = Control : : CURSOR_ARROW ;
{
Control * c = over ;
Vector2 cpos = pos ;
while ( c ) {
2020-07-02 17:15:03 +00:00
if ( gui . mouse_focus_mask ! = 0 | | c - > has_point ( cpos ) ) {
cursor_shape = c - > get_cursor_shape ( cpos ) ;
} else {
cursor_shape = Control : : CURSOR_ARROW ;
}
2020-03-24 23:15:35 +00:00
cpos = c - > get_transform ( ) . xform ( cpos ) ;
2020-05-14 14:41:43 +00:00
if ( cursor_shape ! = Control : : CURSOR_ARROW ) {
2020-03-24 23:15:35 +00:00
break ;
2020-05-14 14:41:43 +00:00
}
if ( c - > data . mouse_filter = = Control : : MOUSE_FILTER_STOP ) {
2020-03-24 23:15:35 +00:00
break ;
2020-05-14 14:41:43 +00:00
}
2020-10-01 07:17:33 +00:00
if ( c - > is_set_as_top_level ( ) ) {
2020-03-24 23:15:35 +00:00
break ;
2020-05-14 14:41:43 +00:00
}
2020-03-24 23:15:35 +00:00
c = c - > get_parent_control ( ) ;
}
}
ds_cursor_shape = ( DisplayServer : : CursorShape ) cursor_shape ;
if ( over & & over - > can_process ( ) ) {
_gui_call_input ( over , mm ) ;
2016-01-17 01:41:10 +00:00
}
2020-03-24 23:15:35 +00:00
set_input_as_handled ( ) ;
2017-05-20 15:38:03 +00:00
}
2016-01-17 01:41:10 +00:00
2020-03-24 23:15:35 +00:00
if ( gui . drag_data . get_type ( ) ! = Variant : : NIL ) {
2021-09-10 14:58:33 +00:00
// Handle drag & drop.
2016-01-17 01:41:10 +00:00
2021-02-24 11:47:14 +00:00
Control * drag_preview = _gui_get_drag_preview ( ) ;
if ( drag_preview ) {
drag_preview - > set_position ( mpos ) ;
2020-03-24 23:15:35 +00:00
}
2016-01-17 01:41:10 +00:00
2020-03-24 23:15:35 +00:00
gui . drag_mouse_over = over ;
gui . drag_mouse_over_pos = Vector2 ( ) ;
2021-09-10 14:58:33 +00:00
// Find the window this is above of.
// See if there is an embedder.
2020-03-24 23:15:35 +00:00
Viewport * embedder = nullptr ;
Vector2 viewport_pos ;
if ( is_embedding_subwindows ( ) ) {
embedder = this ;
viewport_pos = mpos ;
} else {
2021-09-10 14:58:33 +00:00
// Not an embedder, but may be a subwindow of an embedder.
2020-03-24 23:15:35 +00:00
Window * w = Object : : cast_to < Window > ( this ) ;
if ( w ) {
if ( w - > is_embedded ( ) ) {
embedder = w - > _get_embedder ( ) ;
Transform2D ai = ( get_final_transform ( ) . affine_inverse ( ) * _get_input_pre_xform ( ) ) . affine_inverse ( ) ;
2021-09-10 14:58:33 +00:00
viewport_pos = ai . xform ( mpos ) + w - > get_position ( ) ; // To parent coords.
2020-03-24 23:15:35 +00:00
}
}
2018-06-07 15:46:14 +00:00
}
2020-03-24 23:15:35 +00:00
Viewport * viewport_under = nullptr ;
2016-01-17 01:41:10 +00:00
2020-03-24 23:15:35 +00:00
if ( embedder ) {
2021-09-10 14:58:33 +00:00
// Use embedder logic.
2016-01-17 01:41:10 +00:00
2020-03-24 23:15:35 +00: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 ) ) {
2021-07-17 21:22:52 +00:00
int title_height = sw - > get_theme_constant ( SNAME ( " title_height " ) ) ;
2020-03-24 23:15:35 +00: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 01:41:10 +00:00
2020-03-24 23:15:35 +00:00
if ( ! viewport_under ) {
2021-09-10 14:58:33 +00:00
// Not in a subwindow, likely in embedder.
2020-03-24 23:15:35 +00:00
viewport_under = embedder ;
}
} else {
2021-09-10 14:58:33 +00:00
// Use DisplayServer logic.
2020-03-24 23:15:35 +00: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 14:58:33 +00:00
if ( object_under ! = ObjectID ( ) ) { // Fetch window.
2020-03-24 23:15:35 +00:00
Window * w = Object : : cast_to < Window > ( ObjectDB : : get_instance ( object_under ) ) ;
if ( w ) {
viewport_under = w ;
viewport_pos = screen_mouse_pos - w - > get_position ( ) ;
}
}
}
}
2016-01-17 01:41:10 +00:00
2020-03-24 23:15:35 +00:00
if ( viewport_under ) {
Transform2D ai = ( viewport_under - > get_final_transform ( ) . affine_inverse ( ) * viewport_under - > _get_input_pre_xform ( ) ) ;
viewport_pos = ai . xform ( viewport_pos ) ;
2021-09-10 14:58:33 +00:00
// Find control under at position.
2021-07-19 20:09:23 +00:00
gui . drag_mouse_over = viewport_under - > gui_find_control ( viewport_pos ) ;
2020-03-24 23:15:35 +00: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-01-08 03:37:37 +00:00
if ( mm - > get_button_mask ( ) & MOUSE_BUTTON_MASK_LEFT ) {
2020-03-24 23:15:35 +00:00
bool can_drop = _gui_drop ( gui . drag_mouse_over , gui . drag_mouse_over_pos , true ) ;
if ( ! can_drop ) {
ds_cursor_shape = DisplayServer : : CURSOR_FORBIDDEN ;
} else {
ds_cursor_shape = DisplayServer : : CURSOR_CAN_DROP ;
}
}
}
2016-05-11 14:46:08 +00:00
2017-05-20 15:38:03 +00:00
} else {
2020-03-24 23:15:35 +00:00
gui . drag_mouse_over = nullptr ;
2016-01-17 01:41:10 +00:00
}
2017-05-20 15:38:03 +00:00
}
2020-03-24 23:15:35 +00:00
DisplayServer : : get_singleton ( ) - > cursor_set_shape ( ds_cursor_shape ) ;
2017-05-20 15:38:03 +00:00
}
2016-01-17 01:41:10 +00:00
2017-08-07 04:44:46 +00:00
Ref < InputEventScreenTouch > touch_event = p_event ;
if ( touch_event . is_valid ( ) ) {
Size2 pos = touch_event - > get_position ( ) ;
if ( touch_event - > is_pressed ( ) ) {
2021-07-19 20:09:23 +00:00
Control * over = gui_find_control ( pos ) ;
2017-08-07 04:44:46 +00:00
if ( over ) {
if ( over - > can_process ( ) ) {
2021-09-10 14:58:33 +00:00
touch_event = touch_event - > xformed_by ( Transform2D ( ) ) ; // Make a copy.
2017-08-07 04:44:46 +00:00
if ( over = = gui . mouse_focus ) {
pos = gui . focus_inv_xform . xform ( pos ) ;
} else {
pos = over - > get_global_transform_with_canvas ( ) . affine_inverse ( ) . xform ( pos ) ;
}
touch_event - > set_position ( pos ) ;
_gui_call_input ( over , touch_event ) ;
}
2018-11-15 16:54:26 +00:00
set_input_as_handled ( ) ;
2017-08-07 04:44:46 +00:00
return ;
}
2018-10-26 19:23:47 +00:00
} else if ( touch_event - > get_index ( ) = = 0 & & gui . last_mouse_focus ) {
if ( gui . last_mouse_focus - > can_process ( ) ) {
2021-09-10 14:58:33 +00:00
touch_event = touch_event - > xformed_by ( Transform2D ( ) ) ; // Make a copy.
2017-08-07 04:44:46 +00:00
touch_event - > set_position ( gui . focus_inv_xform . xform ( pos ) ) ;
2018-10-26 19:23:47 +00:00
_gui_call_input ( gui . last_mouse_focus , touch_event ) ;
2017-08-07 04:44:46 +00:00
}
2018-11-15 16:54:26 +00:00
set_input_as_handled ( ) ;
2017-08-07 04:44:46 +00:00
return ;
}
}
2017-11-01 20:49:39 +00:00
Ref < InputEventGesture > gesture_event = p_event ;
if ( gesture_event . is_valid ( ) ) {
2018-03-04 21:19:10 +00:00
gui . key_event_accepted = false ;
2017-12-22 18:39:23 +00:00
_gui_cancel_tooltip ( ) ;
2017-11-01 20:49:39 +00:00
Size2 pos = gesture_event - > get_position ( ) ;
2021-07-19 20:09:23 +00:00
Control * over = gui_find_control ( pos ) ;
2017-11-01 20:49:39 +00:00
if ( over ) {
if ( over - > can_process ( ) ) {
2021-09-10 14:58:33 +00:00
gesture_event = gesture_event - > xformed_by ( Transform2D ( ) ) ; // Make a copy.
2017-11-01 20:49:39 +00:00
if ( over = = gui . mouse_focus ) {
pos = gui . focus_inv_xform . xform ( pos ) ;
} else {
pos = over - > get_global_transform_with_canvas ( ) . affine_inverse ( ) . xform ( pos ) ;
}
gesture_event - > set_position ( pos ) ;
_gui_call_input ( over , gesture_event ) ;
}
2018-11-15 16:54:26 +00:00
set_input_as_handled ( ) ;
2017-11-01 20:49:39 +00:00
return ;
}
}
2017-08-07 04:44:46 +00:00
Ref < InputEventScreenDrag > drag_event = p_event ;
if ( drag_event . is_valid ( ) ) {
Control * over = gui . mouse_focus ;
if ( ! over ) {
2021-07-19 20:09:23 +00:00
over = gui_find_control ( drag_event - > get_position ( ) ) ;
2017-08-07 04:44:46 +00:00
}
if ( over ) {
if ( over - > can_process ( ) ) {
Transform2D localizer = over - > get_global_transform_with_canvas ( ) . affine_inverse ( ) ;
Size2 pos = localizer . xform ( drag_event - > get_position ( ) ) ;
Vector2 speed = localizer . basis_xform ( drag_event - > get_speed ( ) ) ;
Vector2 rel = localizer . basis_xform ( drag_event - > get_relative ( ) ) ;
2021-09-10 14:58:33 +00:00
drag_event = drag_event - > xformed_by ( Transform2D ( ) ) ; // Make a copy.
2017-08-07 04:44:46 +00:00
drag_event - > set_speed ( speed ) ;
drag_event - > set_relative ( rel ) ;
drag_event - > set_position ( pos ) ;
_gui_call_input ( over , drag_event ) ;
}
2018-11-15 16:54:26 +00:00
set_input_as_handled ( ) ;
2017-08-07 04:44:46 +00:00
return ;
}
}
2017-05-20 15:38:03 +00:00
if ( mm . is_null ( ) & & mb . is_null ( ) & & p_event - > is_action_type ( ) ) {
if ( gui . key_focus & & ! gui . key_focus - > is_visible_in_tree ( ) ) {
gui . key_focus - > release_focus ( ) ;
}
2016-07-01 13:42:33 +00:00
2017-05-20 15:38:03 +00:00
if ( gui . key_focus ) {
gui . key_event_accepted = false ;
if ( gui . key_focus - > can_process ( ) ) {
2021-08-22 15:37:22 +00:00
gui . key_focus - > _call_gui_input ( p_event ) ;
2017-05-20 15:38:03 +00:00
}
2016-01-17 01:41:10 +00:00
2017-05-20 15:38:03 +00:00
if ( gui . key_event_accepted ) {
2018-11-15 16:54:26 +00:00
set_input_as_handled ( ) ;
2017-05-20 15:38:03 +00:00
return ;
2016-01-17 01:41:10 +00:00
}
2017-05-20 15:38:03 +00:00
}
2016-01-17 01:41:10 +00:00
2021-09-10 14:58:33 +00:00
Control * from = gui . key_focus ? gui . key_focus : nullptr ;
2016-01-17 01:41:10 +00:00
2021-09-10 14:58:33 +00:00
// Keyboard focus.
2017-07-15 12:35:29 +00:00
Ref < InputEventKey > k = p_event ;
2021-09-10 14:58:33 +00:00
// Need to check for mods, otherwise any combination of alt/ctrl/shift+<up/down/left/right/etc> is handled here when it shouldn't be.
2021-04-24 20:33:50 +00:00
bool mods = k . is_valid ( ) & & ( k - > is_ctrl_pressed ( ) | | k - > is_alt_pressed ( ) | | k - > is_shift_pressed ( ) | | k - > is_meta_pressed ( ) ) ;
2017-07-15 12:35:29 +00:00
2017-05-20 15:38:03 +00:00
if ( from & & p_event - > is_pressed ( ) ) {
2020-04-01 23:20:12 +00:00
Control * next = nullptr ;
2016-01-17 01:41:10 +00:00
2021-01-27 03:47:35 +00:00
if ( p_event - > is_action_pressed ( " ui_focus_next " , true ) ) {
2017-05-20 15:38:03 +00:00
next = from - > find_next_valid_focus ( ) ;
}
2016-01-17 01:41:10 +00:00
2021-01-27 03:47:35 +00:00
if ( p_event - > is_action_pressed ( " ui_focus_prev " , true ) ) {
2017-05-20 15:38:03 +00:00
next = from - > find_prev_valid_focus ( ) ;
}
2016-01-17 01:41:10 +00:00
2021-01-27 03:47:35 +00:00
if ( ! mods & & p_event - > is_action_pressed ( " ui_up " , true ) ) {
2020-12-22 16:24:29 +00:00
next = from - > _get_focus_neighbor ( SIDE_TOP ) ;
2017-05-20 15:38:03 +00:00
}
2016-01-17 01:41:10 +00:00
2021-01-27 03:47:35 +00:00
if ( ! mods & & p_event - > is_action_pressed ( " ui_left " , true ) ) {
2020-12-22 16:24:29 +00:00
next = from - > _get_focus_neighbor ( SIDE_LEFT ) ;
2017-05-20 15:38:03 +00:00
}
2016-01-17 01:41:10 +00:00
2021-01-27 03:47:35 +00:00
if ( ! mods & & p_event - > is_action_pressed ( " ui_right " , true ) ) {
2020-12-22 16:24:29 +00:00
next = from - > _get_focus_neighbor ( SIDE_RIGHT ) ;
2017-05-20 15:38:03 +00:00
}
2016-01-17 01:41:10 +00:00
2021-01-27 03:47:35 +00:00
if ( ! mods & & p_event - > is_action_pressed ( " ui_down " , true ) ) {
2020-12-22 16:24:29 +00:00
next = from - > _get_focus_neighbor ( SIDE_BOTTOM ) ;
2016-01-17 01:41:10 +00:00
}
2017-05-20 15:38:03 +00:00
if ( next ) {
next - > grab_focus ( ) ;
2018-11-15 16:54:26 +00:00
set_input_as_handled ( ) ;
2017-05-20 15:38:03 +00:00
}
}
2016-01-17 01:41:10 +00:00
}
}
2017-03-05 15:44:50 +00:00
List < Control * > : : Element * Viewport : : _gui_add_root_control ( Control * p_control ) {
gui . roots_order_dirty = true ;
2016-01-17 01:41:10 +00:00
return gui . roots . push_back ( p_control ) ;
}
void Viewport : : _gui_set_root_order_dirty ( ) {
2017-03-05 15:44:50 +00:00
gui . roots_order_dirty = true ;
2016-01-17 01:41:10 +00:00
}
2017-03-05 15:44:50 +00:00
void Viewport : : _gui_force_drag ( Control * p_base , const Variant & p_data , Control * p_control ) {
2019-08-08 20:11:48 +00:00
ERR_FAIL_COND_MSG ( p_data . get_type ( ) = = Variant : : NIL , " Drag data must be a value. " ) ;
2016-07-01 13:34:38 +00:00
2018-08-24 13:29:27 +00:00
gui . dragging = true ;
2017-03-05 15:44:50 +00:00
gui . drag_data = p_data ;
2020-04-01 23:20:12 +00:00
gui . mouse_focus = nullptr ;
2016-01-17 01:41:10 +00:00
if ( p_control ) {
2017-03-05 15:44:50 +00:00
_gui_set_drag_preview ( p_base , p_control ) ;
2016-01-17 01:41:10 +00:00
}
}
2016-01-19 23:27:27 +00:00
void Viewport : : _gui_set_drag_preview ( Control * p_base , Control * p_control ) {
2016-01-17 01:41:10 +00:00
ERR_FAIL_NULL ( p_control ) ;
2017-08-24 20:58:51 +00:00
ERR_FAIL_COND ( ! Object : : cast_to < Control > ( ( Object * ) p_control ) ) ;
2016-01-17 01:41:10 +00:00
ERR_FAIL_COND ( p_control - > is_inside_tree ( ) ) ;
2020-04-01 23:20:12 +00:00
ERR_FAIL_COND ( p_control - > get_parent ( ) ! = nullptr ) ;
2016-01-17 01:41:10 +00:00
2021-02-24 11:47:14 +00:00
Control * drag_preview = _gui_get_drag_preview ( ) ;
if ( drag_preview ) {
memdelete ( drag_preview ) ;
2016-01-17 01:41:10 +00:00
}
2020-10-01 07:17:33 +00:00
p_control - > set_as_top_level ( true ) ;
2017-03-29 15:29:38 +00:00
p_control - > set_position ( gui . last_mouse_pos ) ;
2021-09-10 14:58:33 +00:00
p_base - > get_root_parent_control ( ) - > add_child ( p_control ) ; // Add as child of viewport.
2016-01-17 01:41:10 +00:00
p_control - > raise ( ) ;
2018-05-08 05:52:38 +00:00
2021-02-24 11:47:14 +00: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 01:41:10 +00:00
}
2017-03-05 15:44:50 +00:00
void Viewport : : _gui_remove_root_control ( List < Control * > : : Element * RI ) {
2016-01-17 01:41:10 +00:00
gui . roots . erase ( RI ) ;
}
void Viewport : : _gui_unfocus_control ( Control * p_control ) {
2017-03-05 15:44:50 +00:00
if ( gui . key_focus = = p_control ) {
2016-01-17 01:41:10 +00:00
gui . key_focus - > release_focus ( ) ;
}
}
2020-09-09 01:08:21 +00:00
void Viewport : : _gui_hide_control ( Control * p_control ) {
2016-01-17 01:41:10 +00:00
if ( gui . mouse_focus = = p_control ) {
2018-11-28 12:31:17 +00:00
_drop_mouse_focus ( ) ;
2016-01-17 01:41:10 +00:00
}
2020-05-14 14:41:43 +00:00
if ( gui . key_focus = = p_control ) {
2017-12-26 19:58:53 +00:00
_gui_remove_focus ( ) ;
2020-05-14 14:41:43 +00:00
}
if ( gui . mouse_over = = p_control ) {
2020-04-01 23:20:12 +00:00
gui . mouse_over = nullptr ;
2020-05-14 14:41:43 +00:00
}
if ( gui . drag_mouse_over = = p_control ) {
2020-04-01 23:20:12 +00:00
gui . drag_mouse_over = nullptr ;
2020-05-14 14:41:43 +00:00
}
2020-11-02 16:18:29 +00:00
if ( gui . tooltip_control = = p_control ) {
2016-01-25 13:30:03 +00:00
_gui_cancel_tooltip ( ) ;
2020-05-14 14:41:43 +00:00
}
2016-01-17 01:41:10 +00:00
}
void Viewport : : _gui_remove_control ( Control * p_control ) {
2018-11-28 12:31:17 +00:00
if ( gui . mouse_focus = = p_control ) {
2020-04-01 23:20:12 +00:00
gui . mouse_focus = nullptr ;
2020-03-20 02:32:09 +00:00
gui . forced_mouse_focus = false ;
2018-11-28 12:31:17 +00:00
gui . mouse_focus_mask = 0 ;
}
2019-02-15 01:16:56 +00:00
if ( gui . last_mouse_focus = = p_control ) {
2020-04-01 23:20:12 +00:00
gui . last_mouse_focus = nullptr ;
2019-02-15 01:16:56 +00:00
}
2020-05-14 14:41:43 +00:00
if ( gui . key_focus = = p_control ) {
2020-04-01 23:20:12 +00:00
gui . key_focus = nullptr ;
2020-05-14 14:41:43 +00:00
}
if ( gui . mouse_over = = p_control ) {
2020-04-01 23:20:12 +00:00
gui . mouse_over = nullptr ;
2020-05-14 14:41:43 +00:00
}
if ( gui . drag_mouse_over = = p_control ) {
2020-04-01 23:20:12 +00:00
gui . drag_mouse_over = nullptr ;
2020-05-14 14:41:43 +00:00
}
2020-11-02 16:18:29 +00:00
if ( gui . tooltip_control = = p_control ) {
gui . tooltip_control = nullptr ;
2020-05-14 14:41:43 +00:00
}
2016-01-17 01:41:10 +00:00
}
2020-07-01 13:59:42 +00:00
Window * Viewport : : get_base_window ( ) const {
2021-06-13 03:36:32 +00:00
ERR_FAIL_COND_V ( ! is_inside_tree ( ) , nullptr ) ;
2020-07-01 13:59:42 +00: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 ;
}
void Viewport : : _gui_remove_focus_for_window ( Node * p_window ) {
if ( get_base_window ( ) = = p_window ) {
_gui_remove_focus ( ) ;
}
}
2016-01-17 01:41:10 +00:00
void Viewport : : _gui_remove_focus ( ) {
if ( gui . key_focus ) {
2017-03-05 15:44:50 +00:00
Node * f = gui . key_focus ;
2020-04-01 23:20:12 +00:00
gui . key_focus = nullptr ;
2017-03-05 15:44:50 +00:00
f - > notification ( Control : : NOTIFICATION_FOCUS_EXIT , true ) ;
2016-01-17 01:41:10 +00:00
}
}
2017-03-05 15:44:50 +00:00
bool Viewport : : _gui_control_has_focus ( const Control * p_control ) {
return gui . key_focus = = p_control ;
2016-01-17 01:41:10 +00:00
}
2017-03-05 15:44:50 +00:00
void Viewport : : _gui_control_grab_focus ( Control * p_control ) {
2020-05-14 14:41:43 +00:00
if ( gui . key_focus & & gui . key_focus = = p_control ) {
2021-09-10 14:58:33 +00:00
// No need for change.
2016-01-17 01:41:10 +00:00
return ;
2020-05-14 14:41:43 +00:00
}
2020-07-01 13:59:42 +00:00
get_tree ( ) - > call_group_flags ( SceneTree : : GROUP_CALL_REALTIME , " _viewports " , " _gui_remove_focus_for_window " , ( Node * ) get_base_window ( ) ) ;
2017-03-05 15:44:50 +00:00
gui . key_focus = p_control ;
2021-07-17 21:22:52 +00:00
emit_signal ( SNAME ( " gui_focus_changed " ) , p_control ) ;
2016-01-17 01:41:10 +00:00
p_control - > notification ( Control : : NOTIFICATION_FOCUS_ENTER ) ;
p_control - > update ( ) ;
}
void Viewport : : _gui_accept_event ( ) {
2017-03-05 15:44:50 +00:00
gui . key_event_accepted = true ;
2020-05-14 14:41:43 +00:00
if ( is_inside_tree ( ) ) {
2018-11-15 16:54:26 +00:00
set_input_as_handled ( ) ;
2020-05-14 14:41:43 +00:00
}
2016-01-17 01:41:10 +00:00
}
2018-11-28 12:31:17 +00:00
void Viewport : : _drop_mouse_focus ( ) {
Control * c = gui . mouse_focus ;
int mask = gui . mouse_focus_mask ;
2020-04-01 23:20:12 +00:00
gui . mouse_focus = nullptr ;
2020-03-20 02:32:09 +00:00
gui . forced_mouse_focus = false ;
2018-11-28 12:31:17 +00:00
gui . mouse_focus_mask = 0 ;
for ( int i = 0 ; i < 3 ; i + + ) {
if ( mask & ( 1 < < i ) ) {
Ref < InputEventMouseButton > mb ;
2021-06-17 22:03:09 +00:00
mb . instantiate ( ) ;
2018-11-28 12:31:17 +00:00
mb - > set_position ( c - > get_local_mouse_position ( ) ) ;
2018-11-28 16:09:56 +00:00
mb - > set_global_position ( c - > get_local_mouse_position ( ) ) ;
2021-03-25 20:56:12 +00:00
mb - > set_button_index ( MouseButton ( i + 1 ) ) ;
2018-11-28 12:31:17 +00:00
mb - > set_pressed ( false ) ;
2021-08-22 15:37:22 +00:00
c - > _call_gui_input ( mb ) ;
2018-11-28 12:31:17 +00:00
}
}
}
2021-02-06 20:14:35 +00:00
void Viewport : : _drop_physics_mouseover ( bool p_paused_only ) {
2019-03-11 00:18:21 +00:00
physics_has_last_mousepos = false ;
2021-03-26 17:39:05 +00:00
_cleanup_mouseover_colliders ( true , p_paused_only ) ;
2021-07-04 01:43:23 +00:00
# ifndef _3D_DISABLED
2021-03-26 17:39:05 +00:00
if ( physics_object_over . is_valid ( ) ) {
CollisionObject3D * co = Object : : cast_to < CollisionObject3D > ( ObjectDB : : get_instance ( physics_object_over ) ) ;
if ( co ) {
if ( ! ( p_paused_only & & co - > can_process ( ) ) ) {
co - > _mouse_exit ( ) ;
physics_object_over = ObjectID ( ) ;
physics_object_capture = ObjectID ( ) ;
}
}
}
2021-07-04 01:43:23 +00:00
# endif // _3D_DISABLED
2021-03-26 17:39:05 +00:00
}
void Viewport : : _cleanup_mouseover_colliders ( bool p_clean_all_frames , bool p_paused_only , uint64_t p_frame_reference ) {
2021-02-06 20:14:35 +00:00
List < Map < ObjectID , uint64_t > : : Element * > to_erase ;
for ( Map < ObjectID , uint64_t > : : Element * E = physics_2d_mouseover . front ( ) ; E ; E = E - > next ( ) ) {
2021-03-26 17:39:05 +00:00
if ( ! p_clean_all_frames & & E - > get ( ) = = p_frame_reference ) {
continue ;
}
2021-02-06 20:14:35 +00:00
Object * o = ObjectDB : : get_instance ( E - > key ( ) ) ;
2019-03-11 00:18:21 +00:00
if ( o ) {
CollisionObject2D * co = Object : : cast_to < CollisionObject2D > ( o ) ;
2021-02-06 20:14:35 +00:00
if ( co ) {
2021-03-26 17:39:05 +00:00
if ( p_clean_all_frames & & p_paused_only & & co - > can_process ( ) ) {
2021-02-06 20:14:35 +00:00
continue ;
}
co - > _mouse_exit ( ) ;
}
2019-03-11 00:18:21 +00:00
}
2021-03-26 17:39:05 +00:00
to_erase . push_back ( E ) ;
2021-02-06 20:14:35 +00:00
}
while ( to_erase . size ( ) ) {
physics_2d_mouseover . erase ( to_erase . front ( ) - > get ( ) ) ;
to_erase . pop_front ( ) ;
2019-03-11 00:18:21 +00:00
}
2021-09-10 14:58:33 +00:00
// Per-shape.
2021-03-26 17:39:05 +00:00
List < Map < Pair < ObjectID , int > , uint64_t , PairSort < ObjectID , int > > : : Element * > shapes_to_erase ;
for ( Map < Pair < ObjectID , int > , uint64_t , PairSort < ObjectID , int > > : : Element * E = physics_2d_shape_mouseover . front ( ) ; E ; E = E - > next ( ) ) {
if ( ! p_clean_all_frames & & E - > get ( ) = = p_frame_reference ) {
continue ;
}
Object * o = ObjectDB : : get_instance ( E - > key ( ) . first ) ;
if ( o ) {
CollisionObject2D * co = Object : : cast_to < CollisionObject2D > ( o ) ;
if ( co ) {
if ( p_clean_all_frames & & p_paused_only & & co - > can_process ( ) ) {
continue ;
}
co - > _mouse_shape_exit ( E - > key ( ) . second ) ;
2021-02-06 20:14:35 +00:00
}
2019-03-11 00:18:21 +00:00
}
2021-03-26 17:39:05 +00:00
shapes_to_erase . push_back ( E ) ;
}
while ( shapes_to_erase . size ( ) ) {
physics_2d_shape_mouseover . erase ( shapes_to_erase . front ( ) - > get ( ) ) ;
shapes_to_erase . pop_front ( ) ;
2019-03-11 00:18:21 +00:00
}
}
2016-01-17 01:41:10 +00:00
Control * Viewport : : _gui_get_focus_owner ( ) {
return gui . key_focus ;
}
void Viewport : : _gui_grab_click_focus ( Control * p_control ) {
2018-03-27 21:41:27 +00:00
gui . mouse_click_grabber = p_control ;
2021-07-17 21:22:52 +00:00
call_deferred ( SNAME ( " _post_gui_grab_click_focus " ) ) ;
2018-03-27 21:41:27 +00:00
}
void Viewport : : _post_gui_grab_click_focus ( ) {
Control * focus_grabber = gui . mouse_click_grabber ;
if ( ! focus_grabber ) {
2021-09-10 14:58:33 +00:00
// Redundant grab requests were made.
2018-03-27 21:41:27 +00:00
return ;
}
2020-04-01 23:20:12 +00:00
gui . mouse_click_grabber = nullptr ;
2018-03-27 21:41:27 +00:00
2016-01-17 01:41:10 +00:00
if ( gui . mouse_focus ) {
2020-05-14 14:41:43 +00:00
if ( gui . mouse_focus = = focus_grabber ) {
2016-01-17 01:41:10 +00:00
return ;
2020-05-14 14:41:43 +00:00
}
2016-01-17 01:41:10 +00:00
2018-11-28 12:31:17 +00:00
int mask = gui . mouse_focus_mask ;
2017-03-05 15:44:50 +00:00
Point2 click = gui . mouse_focus - > get_global_transform_with_canvas ( ) . affine_inverse ( ) . xform ( gui . last_mouse_pos ) ;
2018-11-28 12:31:17 +00:00
for ( int i = 0 ; i < 3 ; i + + ) {
if ( mask & ( 1 < < i ) ) {
Ref < InputEventMouseButton > mb ;
2021-06-17 22:03:09 +00:00
mb . instantiate ( ) ;
2018-11-28 12:31:17 +00:00
2021-09-10 14:58:33 +00:00
// Send unclick.
2018-11-28 12:31:17 +00:00
mb - > set_position ( click ) ;
2021-03-25 20:56:12 +00:00
mb - > set_button_index ( MouseButton ( i + 1 ) ) ;
2018-11-28 12:31:17 +00:00
mb - > set_pressed ( false ) ;
2021-08-22 15:37:22 +00:00
gui . mouse_focus - > _call_gui_input ( mb ) ;
2018-11-28 12:31:17 +00:00
}
}
2016-01-17 01:41:10 +00:00
2018-03-27 21:41:27 +00:00
gui . mouse_focus = focus_grabber ;
2017-03-05 15:44:50 +00:00
gui . focus_inv_xform = gui . mouse_focus - > get_global_transform_with_canvas ( ) . affine_inverse ( ) ;
click = gui . mouse_focus - > get_global_transform_with_canvas ( ) . affine_inverse ( ) . xform ( gui . last_mouse_pos ) ;
2018-11-28 12:31:17 +00:00
for ( int i = 0 ; i < 3 ; i + + ) {
if ( mask & ( 1 < < i ) ) {
Ref < InputEventMouseButton > mb ;
2021-06-17 22:03:09 +00:00
mb . instantiate ( ) ;
2018-11-28 12:31:17 +00:00
2021-09-10 14:58:33 +00:00
// Send click.
2018-11-28 12:31:17 +00:00
mb - > set_position ( click ) ;
2021-03-25 20:56:12 +00:00
mb - > set_button_index ( MouseButton ( i + 1 ) ) ;
2018-11-28 12:31:17 +00:00
mb - > set_pressed ( true ) ;
2021-08-22 15:37:22 +00:00
MessageQueue : : get_singleton ( ) - > push_callable ( callable_mp ( gui . mouse_focus , & Control : : _call_gui_input ) , mb ) ;
2018-11-28 12:31:17 +00:00
}
}
2016-01-17 01:41:10 +00:00
}
}
///////////////////////////////
2021-08-22 15:37:22 +00:00
void Viewport : : push_text_input ( const String & p_text ) {
2020-03-14 16:06:39 +00:00
if ( gui . subwindow_focused ) {
2021-08-22 15:37:22 +00:00
gui . subwindow_focused - > push_text_input ( p_text ) ;
2020-03-14 16:06:39 +00:00
return ;
}
2020-03-04 16:36:09 +00:00
if ( gui . key_focus ) {
gui . key_focus - > call ( " set_text " , p_text ) ;
}
}
2020-05-14 12:29:06 +00:00
2020-03-14 16:06:39 +00:00
Viewport : : SubWindowResize Viewport : : _sub_window_get_resize_margin ( Window * p_subwindow , const Point2 & p_point ) {
if ( p_subwindow - > get_flag ( Window : : FLAG_BORDERLESS ) ) {
return SUB_WINDOW_RESIZE_DISABLED ;
}
Rect2i r = Rect2i ( p_subwindow - > get_position ( ) , p_subwindow - > get_size ( ) ) ;
2021-07-17 21:22:52 +00:00
int title_height = p_subwindow - > get_theme_constant ( SNAME ( " title_height " ) ) ;
2020-03-14 16:06:39 +00:00
r . position . y - = title_height ;
r . size . y + = title_height ;
if ( r . has_point ( p_point ) ) {
2021-09-10 14:58:33 +00:00
return SUB_WINDOW_RESIZE_DISABLED ; // It's inside, so no resize.
2020-03-14 16:06:39 +00: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 ) ;
2021-07-17 21:22:52 +00:00
int limit = p_subwindow - > get_theme_constant ( SNAME ( " resize_margin " ) ) ;
2020-03-14 16:06:39 +00: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 12:29:06 +00:00
2020-03-14 16:06:39 +00:00
bool Viewport : : _sub_windows_forward_input ( const Ref < InputEvent > & p_event ) {
if ( gui . subwindow_drag ! = SUB_WINDOW_DRAG_DISABLED ) {
ERR_FAIL_COND_V ( gui . subwindow_focused = = nullptr , false ) ;
Ref < InputEventMouseButton > mb = p_event ;
2021-01-08 03:37:37 +00:00
if ( mb . is_valid ( ) & & ! mb - > is_pressed ( ) & & mb - > get_button_index ( ) = = MOUSE_BUTTON_LEFT ) {
2020-03-14 16:06:39 +00:00
if ( gui . subwindow_drag = = SUB_WINDOW_DRAG_CLOSE ) {
if ( gui . subwindow_drag_close_rect . has_point ( mb - > get_position ( ) ) ) {
2021-09-10 14:58:33 +00:00
// Close window.
2020-03-14 16:06:39 +00:00
gui . subwindow_focused - > _event_callback ( DisplayServer : : WINDOW_EVENT_CLOSE_REQUEST ) ;
}
}
gui . subwindow_drag = SUB_WINDOW_DRAG_DISABLED ;
2021-09-10 14:58:33 +00:00
if ( gui . subwindow_focused ! = nullptr ) { // May have been erased.
2020-03-14 16:06:39 +00:00
_sub_window_update ( gui . subwindow_focused ) ;
}
}
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 ;
Rect2i new_rect ( gui . subwindow_drag_pos + diff , gui . subwindow_focused - > get_size ( ) ) ;
2020-07-01 15:39:42 +00:00
if ( gui . subwindow_focused - > is_clamped_to_embedder ( ) ) {
Size2i limit = get_visible_rect ( ) . size ;
if ( new_rect . position . x + new_rect . size . x > limit . x ) {
new_rect . position . x = limit . x - new_rect . size . x ;
}
if ( new_rect . position . y + new_rect . size . y > limit . y ) {
new_rect . position . y = limit . y - new_rect . size . y ;
}
if ( new_rect . position . x < 0 ) {
new_rect . position . x = 0 ;
}
2021-07-17 21:22:52 +00:00
int title_height = gui . subwindow_focused - > get_flag ( Window : : FLAG_BORDERLESS ) ? 0 : gui . subwindow_focused - > get_theme_constant ( SNAME ( " title_height " ) ) ;
2020-07-01 15:39:42 +00:00
if ( new_rect . position . y < title_height ) {
new_rect . position . y = title_height ;
}
}
2020-03-14 16:06:39 +00:00
gui . subwindow_focused - > _rect_changed_callback ( new_rect ) ;
}
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 ;
Size2i min_size = gui . subwindow_focused - > get_min_size ( ) ;
if ( gui . subwindow_focused - > is_wrapping_controls ( ) ) {
Size2i cms = gui . subwindow_focused - > get_contents_minimum_size ( ) ;
min_size . x = MAX ( cms . x , min_size . x ) ;
min_size . y = MAX ( cms . y , min_size . y ) ;
}
min_size . x = MAX ( min_size . x , 1 ) ;
min_size . y = MAX ( min_size . y , 1 ) ;
Rect2i r = gui . subwindow_resize_from_rect ;
Size2i limit = r . size - min_size ;
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 : {
}
}
gui . subwindow_focused - > _rect_changed_callback ( r ) ;
}
2021-09-10 14:58:33 +00:00
if ( gui . subwindow_focused ) { // May have been erased.
2020-03-14 16:06:39 +00:00
_sub_window_update ( gui . subwindow_focused ) ;
}
}
2021-09-10 14:58:33 +00:00
return true ; // Handled.
2020-03-14 16:06:39 +00:00
}
Ref < InputEventMouseButton > mb = p_event ;
2021-09-10 14:58:33 +00:00
// If the event is a mouse button, we need to check whether another window was clicked.
2020-03-14 16:06:39 +00:00
2021-01-08 03:37:37 +00:00
if ( mb . is_valid ( ) & & mb - > is_pressed ( ) & & mb - > get_button_index ( ) = = MOUSE_BUTTON_LEFT ) {
2020-03-14 16:06:39 +00:00
bool click_on_window = false ;
for ( int i = gui . sub_windows . size ( ) - 1 ; i > = 0 ; i - - ) {
SubWindow & sw = gui . sub_windows . write [ i ] ;
2021-09-10 14:58:33 +00:00
// Clicked inside window?
2020-03-14 16:06:39 +00:00
Rect2i r = Rect2i ( sw . window - > get_position ( ) , sw . window - > get_size ( ) ) ;
if ( ! sw . window - > get_flag ( Window : : FLAG_BORDERLESS ) ) {
2021-09-10 14:58:33 +00:00
// Check top bar.
2021-07-17 21:22:52 +00:00
int title_height = sw . window - > get_theme_constant ( SNAME ( " title_height " ) ) ;
2020-03-14 16:06:39 +00:00
Rect2i title_bar = r ;
title_bar . position . y - = title_height ;
title_bar . size . y = title_height ;
if ( title_bar . has_point ( mb - > get_position ( ) ) ) {
click_on_window = true ;
2021-07-17 21:22:52 +00:00
int close_h_ofs = sw . window - > get_theme_constant ( SNAME ( " close_h_ofs " ) ) ;
int close_v_ofs = sw . window - > get_theme_constant ( SNAME ( " close_v_ofs " ) ) ;
Ref < Texture2D > close_icon = sw . window - > get_theme_icon ( SNAME ( " close " ) ) ;
2020-03-14 16:06:39 +00:00
Rect2 close_rect ;
close_rect . position = Vector2 ( r . position . x + r . size . x - close_v_ofs , r . position . y - close_h_ofs ) ;
close_rect . size = close_icon - > get_size ( ) ;
if ( gui . subwindow_focused ! = sw . window ) {
2021-09-10 14:58:33 +00:00
// Refocus.
2020-03-14 16:06:39 +00: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 14:58:33 +00:00
gui . subwindow_drag_close_inside = true ; // Starts inside.
2020-03-14 16:06:39 +00: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-24 23:15:35 +00:00
gui . subwindow_resize_mode = _sub_window_get_resize_margin ( sw . window , mb - > get_position ( ) ) ;
2020-03-14 16:06:39 +00:00
if ( gui . subwindow_resize_mode ! = SUB_WINDOW_RESIZE_DISABLED ) {
gui . subwindow_resize_from_rect = r ;
gui . subwindow_drag_from = mb - > get_position ( ) ;
gui . subwindow_drag = SUB_WINDOW_DRAG_RESIZE ;
click_on_window = true ;
}
}
}
if ( ! click_on_window & & r . has_point ( mb - > get_position ( ) ) ) {
2021-09-10 14:58:33 +00:00
// Clicked, see if it needs to fetch focus.
2020-03-14 16:06:39 +00:00
if ( gui . subwindow_focused ! = sw . window ) {
2021-09-10 14:58:33 +00:00
// Refocus.
2020-03-14 16:06:39 +00:00
_sub_window_grab_focus ( sw . window ) ;
}
click_on_window = true ;
}
if ( click_on_window ) {
break ;
}
}
if ( ! click_on_window & & gui . subwindow_focused ) {
2021-09-10 14:58:33 +00:00
// No window found and clicked, remove focus.
2020-03-14 16:06:39 +00: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
} ;
DisplayServer : : get_singleton ( ) - > cursor_set_shape ( shapes [ resize ] ) ;
2021-09-10 14:58:33 +00:00
return true ; // Reserved for showing the resize cursor.
2020-03-14 16:06:39 +00:00
}
}
}
if ( gui . subwindow_drag ! = SUB_WINDOW_DRAG_DISABLED ) {
2021-09-10 14:58:33 +00:00
return true ; // Dragging, don't pass the event.
2020-03-14 16:06:39 +00: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 ;
}
2021-08-22 15:37:22 +00:00
void Viewport : : push_input ( const Ref < InputEvent > & p_event , bool p_local_coords ) {
2014-11-06 00:20:42 +00:00
ERR_FAIL_COND ( ! is_inside_tree ( ) ) ;
2016-01-18 22:49:11 +00:00
2020-05-14 14:41:43 +00:00
if ( disable_input ) {
2020-03-04 16:36:09 +00:00
return ;
2020-05-14 14:41:43 +00:00
}
2020-03-04 16:36:09 +00:00
2021-06-18 22:02:50 +00: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 16:36:09 +00:00
return ;
}
2018-11-15 16:54:26 +00:00
local_input_handled = false ;
2020-03-04 16:36:09 +00:00
Ref < InputEvent > ev ;
if ( ! p_local_coords ) {
ev = _make_input_local ( p_event ) ;
} else {
ev = p_event ;
}
2020-03-14 16:06:39 +00:00
if ( is_embedding_subwindows ( ) & & _sub_windows_forward_input ( p_event ) ) {
set_input_as_handled ( ) ;
return ;
}
2020-07-01 12:27:43 +00:00
if ( ! _can_consume_input_events ( ) ) {
return ;
}
2018-11-15 16:54:26 +00:00
if ( ! is_input_handled ( ) ) {
2021-08-22 15:37:22 +00: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 12:13:33 +00:00
}
2018-11-15 16:54:26 +00:00
if ( ! is_input_handled ( ) ) {
2020-03-04 16:36:09 +00:00
_gui_input_event ( ev ) ;
2017-10-16 12:13:33 +00:00
}
2020-07-01 13:59:42 +00:00
event_count + + ;
2014-04-10 03:18:27 +00:00
}
2021-08-22 15:37:22 +00:00
void Viewport : : push_unhandled_input ( const Ref < InputEvent > & p_event , bool p_local_coords ) {
2021-04-05 06:52:21 +00:00
ERR_FAIL_COND ( p_event . is_null ( ) ) ;
2014-11-06 00:20:42 +00:00
ERR_FAIL_COND ( ! is_inside_tree ( ) ) ;
2021-05-29 13:28:16 +00:00
local_input_handled = false ;
2014-04-10 03:18:27 +00:00
2020-07-01 12:27:43 +00:00
if ( disable_input | | ! _can_consume_input_events ( ) ) {
2020-03-04 16:36:09 +00:00
return ;
2020-05-14 14:41:43 +00:00
}
2020-03-04 16:36:09 +00:00
2021-06-18 22:02:50 +00: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 16:36:09 +00:00
return ;
}
Ref < InputEvent > ev ;
if ( ! p_local_coords ) {
ev = _make_input_local ( p_event ) ;
} else {
ev = p_event ;
}
2021-09-10 14:58:33 +00:00
// Unhandled Input.
2021-08-22 15:37:22 +00:00
get_tree ( ) - > _call_input_pause ( unhandled_input_group , SceneTree : : CALL_INPUT_TYPE_UNHANDLED_INPUT , ev , this ) ;
2020-09-17 01:40:00 +00:00
2021-09-10 14:58:33 +00:00
// Unhandled key Input - used for performance reasons - This is called a lot less than _unhandled_input since it ignores MouseMotion, etc.
2021-05-29 13:28:16 +00:00
if ( ! is_input_handled ( ) & & ( Object : : cast_to < InputEventKey > ( * ev ) ! = nullptr | | Object : : cast_to < InputEventShortcut > ( * ev ) ! = nullptr ) ) {
2021-08-22 15:37:22 +00:00
get_tree ( ) - > _call_input_pause ( unhandled_key_input_group , SceneTree : : CALL_INPUT_TYPE_UNHANDLED_KEY_INPUT , ev , this ) ;
2014-04-10 03:18:27 +00:00
}
2014-09-15 14:33:30 +00:00
2020-03-04 16:36:09 +00:00
if ( physics_object_picking & & ! is_input_handled ( ) ) {
2020-04-28 13:19:37 +00:00
if ( Input : : get_singleton ( ) - > get_mouse_mode ( ) ! = Input : : MOUSE_MODE_CAPTURED & &
2020-03-04 16:36:09 +00:00
( Object : : cast_to < InputEventMouseButton > ( * ev ) | |
Object : : cast_to < InputEventMouseMotion > ( * ev ) | |
Object : : cast_to < InputEventScreenDrag > ( * ev ) | |
Object : : cast_to < InputEventScreenTouch > ( * ev ) | |
2021-09-10 14:58:33 +00:00
Object : : cast_to < InputEventKey > ( * ev ) // To remember state.
2018-11-15 16:54:26 +00:00
) ) {
2020-03-04 16:36:09 +00:00
physics_picking_events . push_back ( ev ) ;
2014-09-15 14:33:30 +00:00
}
}
2014-04-10 03:18:27 +00:00
}
2014-09-15 14:33:30 +00:00
void Viewport : : set_physics_object_picking ( bool p_enable ) {
2017-03-05 15:44:50 +00:00
physics_object_picking = p_enable ;
2021-07-19 17:25:15 +00:00
if ( physics_object_picking ) {
add_to_group ( " _picking_viewports " ) ;
} else {
2014-09-15 14:33:30 +00:00
physics_picking_events . clear ( ) ;
2021-07-19 17:25:15 +00:00
if ( is_in_group ( " _picking_viewports " ) ) {
remove_from_group ( " _picking_viewports " ) ;
}
2018-03-01 13:44:45 +00:00
}
}
bool Viewport : : get_physics_object_picking ( ) {
return physics_object_picking ;
2014-09-15 14:33:30 +00:00
}
2014-10-28 01:54:32 +00:00
Vector2 Viewport : : get_camera_coords ( const Vector2 & p_viewport_coords ) const {
2017-01-11 03:52:51 +00:00
Transform2D xf = get_final_transform ( ) ;
2014-10-28 01:54:32 +00:00
return xf . xform ( p_viewport_coords ) ;
}
Vector2 Viewport : : get_camera_rect_size ( ) const {
2016-10-27 14:50:26 +00:00
return size ;
2014-10-28 01:54:32 +00:00
}
2016-01-17 01:41:10 +00:00
void Viewport : : set_disable_input ( bool p_disable ) {
2017-03-05 15:44:50 +00:00
disable_input = p_disable ;
2016-01-17 01:41:10 +00:00
}
bool Viewport : : is_input_disabled ( ) const {
return disable_input ;
}
2014-02-10 01:10:30 +00:00
2016-05-11 14:46:08 +00:00
Variant Viewport : : gui_get_drag_data ( ) const {
return gui . drag_data ;
}
2016-05-17 21:27:15 +00:00
2020-10-29 10:01:28 +00:00
TypedArray < String > Viewport : : get_configuration_warnings ( ) const {
TypedArray < String > warnings = Node : : get_configuration_warnings ( ) ;
2020-05-14 20:59:27 +00:00
2020-03-17 20:33:36 +00:00
if ( size . x = = 0 | | size . y = = 0 ) {
2020-10-29 10:01:28 +00:00
warnings . push_back ( TTR ( " Viewport size must be greater than 0 to render anything. " ) ) ;
2020-03-17 20:33:36 +00:00
}
2020-10-29 10:01:28 +00:00
return warnings ;
2016-05-17 21:27:15 +00:00
}
2017-03-05 15:44:50 +00:00
void Viewport : : gui_reset_canvas_sort_index ( ) {
gui . canvas_sort_index = 0 ;
2016-10-03 19:33:42 +00:00
}
2020-05-14 12:29:06 +00:00
2016-10-03 19:33:42 +00:00
int Viewport : : gui_get_canvas_sort_index ( ) {
return gui . canvas_sort_index + + ;
}
2017-01-02 01:16:52 +00:00
void Viewport : : set_msaa ( MSAA p_msaa ) {
2020-04-12 04:49:10 +00:00
ERR_FAIL_INDEX ( p_msaa , MSAA_MAX ) ;
2020-05-14 14:41:43 +00:00
if ( msaa = = p_msaa ) {
2017-01-02 01:16:52 +00:00
return ;
2020-05-14 14:41:43 +00:00
}
2017-03-05 15:44:50 +00:00
msaa = p_msaa ;
2020-03-27 18:21:27 +00:00
RS : : get_singleton ( ) - > viewport_set_msaa ( viewport , RS : : ViewportMSAA ( p_msaa ) ) ;
2017-01-02 01:16:52 +00:00
}
Viewport : : MSAA Viewport : : get_msaa ( ) const {
return msaa ;
}
2020-04-12 04:49:10 +00:00
void Viewport : : set_screen_space_aa ( ScreenSpaceAA p_screen_space_aa ) {
ERR_FAIL_INDEX ( p_screen_space_aa , SCREEN_SPACE_AA_MAX ) ;
2020-05-14 14:41:43 +00:00
if ( screen_space_aa = = p_screen_space_aa ) {
2020-04-12 04:49:10 +00:00
return ;
2020-05-14 14:41:43 +00:00
}
2020-04-12 04:49:10 +00: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 {
return screen_space_aa ;
}
2020-05-14 12:29:06 +00:00
2020-04-20 21:34:47 +00:00
void Viewport : : set_use_debanding ( bool p_use_debanding ) {
2021-04-05 12:09:59 +00:00
if ( use_debanding = = p_use_debanding ) {
2020-04-20 21:34:47 +00:00
return ;
2021-04-05 12:09:59 +00:00
}
2020-04-20 21:34:47 +00:00
use_debanding = p_use_debanding ;
RS : : get_singleton ( ) - > viewport_set_use_debanding ( viewport , p_use_debanding ) ;
}
bool Viewport : : is_using_debanding ( ) const {
return use_debanding ;
}
2020-12-17 18:56:59 +00:00
void Viewport : : set_lod_threshold ( float p_pixels ) {
lod_threshold = p_pixels ;
RS : : get_singleton ( ) - > viewport_set_lod_threshold ( viewport , lod_threshold ) ;
}
2021-08-02 17:31:51 +00:00
2020-12-17 18:56:59 +00:00
float Viewport : : get_lod_threshold ( ) const {
return lod_threshold ;
}
2021-04-20 16:40:24 +00:00
void Viewport : : set_use_occlusion_culling ( bool p_use_occlusion_culling ) {
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 {
return use_occlusion_culling ;
}
2017-06-11 18:52:03 +00:00
void Viewport : : set_debug_draw ( DebugDraw p_debug_draw ) {
debug_draw = p_debug_draw ;
2020-03-27 18:21:27 +00:00
RS : : get_singleton ( ) - > viewport_set_debug_draw ( viewport , RS : : ViewportDebugDraw ( p_debug_draw ) ) ;
2017-06-11 18:52:03 +00:00
}
Viewport : : DebugDraw Viewport : : get_debug_draw ( ) const {
return debug_draw ;
}
2021-07-02 23:14:19 +00:00
int Viewport : : get_render_info ( RenderInfoType p_type , RenderInfo p_info ) {
return RS : : get_singleton ( ) - > viewport_get_render_info ( viewport , RS : : ViewportRenderInfoType ( p_type ) , RS : : ViewportRenderInfo ( p_info ) ) ;
2017-06-11 18:52:03 +00:00
}
2017-09-07 14:22:07 +00:00
void Viewport : : set_snap_controls_to_pixels ( bool p_enable ) {
2017-09-07 06:57:09 +00:00
snap_controls_to_pixels = p_enable ;
2017-09-07 14:22:07 +00:00
}
bool Viewport : : is_snap_controls_to_pixels_enabled ( ) const {
return snap_controls_to_pixels ;
}
2020-10-29 21:09:16 +00:00
void Viewport : : set_snap_2d_transforms_to_pixel ( bool p_enable ) {
snap_2d_transforms_to_pixel = p_enable ;
RS : : get_singleton ( ) - > viewport_set_snap_2d_transforms_to_pixel ( viewport , snap_2d_transforms_to_pixel ) ;
}
bool Viewport : : is_snap_2d_transforms_to_pixel_enabled ( ) const {
return snap_2d_transforms_to_pixel ;
}
void Viewport : : set_snap_2d_vertices_to_pixel ( bool p_enable ) {
snap_2d_vertices_to_pixel = p_enable ;
RS : : get_singleton ( ) - > viewport_set_snap_2d_vertices_to_pixel ( viewport , snap_2d_vertices_to_pixel ) ;
}
bool Viewport : : is_snap_2d_vertices_to_pixel_enabled ( ) const {
return snap_2d_vertices_to_pixel ;
}
2018-08-24 13:29:27 +00:00
bool Viewport : : gui_is_dragging ( ) const {
return gui . dragging ;
}
2018-11-15 16:54:26 +00:00
void Viewport : : set_input_as_handled ( ) {
2019-06-07 15:21:12 +00:00
_drop_physics_mouseover ( ) ;
2018-11-15 16:54:26 +00:00
if ( handle_input_locally ) {
local_input_handled = true ;
} else {
ERR_FAIL_COND ( ! is_inside_tree ( ) ) ;
2020-03-04 16:36:09 +00:00
Viewport * vp = this ;
while ( true ) {
if ( Object : : cast_to < Window > ( vp ) ) {
break ;
}
if ( ! vp - > get_parent ( ) ) {
break ;
}
vp = vp - > get_parent ( ) - > get_viewport ( ) ;
}
vp - > set_input_as_handled ( ) ;
2018-11-15 16:54:26 +00:00
}
}
bool Viewport : : is_input_handled ( ) const {
if ( handle_input_locally ) {
return local_input_handled ;
} else {
2020-03-04 16:36:09 +00:00
const Viewport * vp = this ;
2021-06-13 03:36:32 +00:00
ERR_FAIL_COND_V ( ! is_inside_tree ( ) , false ) ;
2020-03-04 16:36:09 +00:00
while ( true ) {
if ( Object : : cast_to < Window > ( vp ) ) {
break ;
}
if ( ! vp - > get_parent ( ) ) {
break ;
}
vp = vp - > get_parent ( ) - > get_viewport ( ) ;
}
return vp - > is_input_handled ( ) ;
2018-11-15 16:54:26 +00:00
}
}
void Viewport : : set_handle_input_locally ( bool p_enable ) {
handle_input_locally = p_enable ;
}
bool Viewport : : is_handling_input_locally ( ) const {
return handle_input_locally ;
}
2019-06-25 01:24:07 +00:00
void Viewport : : set_default_canvas_item_texture_filter ( DefaultCanvasItemTextureFilter p_filter ) {
2020-10-24 15:15:43 +00:00
ERR_FAIL_INDEX ( p_filter , DEFAULT_CANVAS_ITEM_TEXTURE_FILTER_MAX ) ;
2019-06-25 01:24:07 +00:00
if ( default_canvas_item_texture_filter = = p_filter ) {
return ;
}
default_canvas_item_texture_filter = p_filter ;
2020-10-24 15:15:43 +00: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 01:24:07 +00:00
}
Viewport : : DefaultCanvasItemTextureFilter Viewport : : get_default_canvas_item_texture_filter ( ) const {
return default_canvas_item_texture_filter ;
}
void Viewport : : set_default_canvas_item_texture_repeat ( DefaultCanvasItemTextureRepeat p_repeat ) {
2020-10-24 15:15:43 +00:00
ERR_FAIL_INDEX ( p_repeat , DEFAULT_CANVAS_ITEM_TEXTURE_REPEAT_MAX ) ;
2019-06-25 01:24:07 +00:00
if ( default_canvas_item_texture_repeat = = p_repeat ) {
return ;
}
2020-10-24 15:15:43 +00:00
default_canvas_item_texture_repeat = p_repeat ;
2019-06-25 01:24:07 +00:00
2020-10-24 15:15:43 +00: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 01:24:07 +00:00
}
}
2020-10-24 15:15:43 +00:00
Viewport : : DefaultCanvasItemTextureRepeat Viewport : : get_default_canvas_item_texture_repeat ( ) const {
return default_canvas_item_texture_repeat ;
2019-06-25 01:24:07 +00:00
}
2020-03-03 13:36:29 +00:00
DisplayServer : : WindowID Viewport : : get_window_id ( ) const {
return DisplayServer : : MAIN_WINDOW_ID ;
}
2020-03-04 01:51:12 +00:00
Viewport * Viewport : : get_parent_viewport ( ) const {
ERR_FAIL_COND_V ( ! is_inside_tree ( ) , nullptr ) ;
if ( ! get_parent ( ) ) {
return nullptr ; //root viewport
}
return get_parent ( ) - > get_viewport ( ) ;
}
2014-02-10 01:10:30 +00:00
2020-03-04 01:51:12 +00:00
void Viewport : : set_embed_subwindows_hint ( bool p_embed ) {
gui . embed_subwindows_hint = p_embed ;
}
2020-05-14 12:29:06 +00:00
2020-03-04 01:51:12 +00:00
bool Viewport : : get_embed_subwindows_hint ( ) const {
return gui . embed_subwindows_hint ;
}
2020-05-14 12:29:06 +00:00
2020-03-04 01:51:12 +00:00
bool Viewport : : is_embedding_subwindows ( ) const {
return gui . embed_subwindows_hint ;
}
2020-03-20 02:32:09 +00:00
void Viewport : : pass_mouse_focus_to ( Viewport * p_viewport , Control * p_control ) {
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 ;
gui . mouse_focus_mask = 0 ;
}
}
2020-11-26 12:50:21 +00:00
void Viewport : : set_sdf_oversize ( SDFOversize p_sdf_oversize ) {
ERR_FAIL_INDEX ( p_sdf_oversize , SDF_OVERSIZE_MAX ) ;
sdf_oversize = p_sdf_oversize ;
RS : : get_singleton ( ) - > viewport_set_sdf_oversize_and_scale ( viewport , RS : : ViewportSDFOversize ( sdf_oversize ) , RS : : ViewportSDFScale ( sdf_scale ) ) ;
}
2021-08-02 17:31:51 +00:00
2020-11-26 12:50:21 +00:00
Viewport : : SDFOversize Viewport : : get_sdf_oversize ( ) const {
return sdf_oversize ;
}
void Viewport : : set_sdf_scale ( SDFScale p_sdf_scale ) {
ERR_FAIL_INDEX ( p_sdf_scale , SDF_SCALE_MAX ) ;
sdf_scale = p_sdf_scale ;
RS : : get_singleton ( ) - > viewport_set_sdf_oversize_and_scale ( viewport , RS : : ViewportSDFOversize ( sdf_oversize ) , RS : : ViewportSDFScale ( sdf_scale ) ) ;
}
2021-08-02 17:31:51 +00:00
2020-11-26 12:50:21 +00:00
Viewport : : SDFScale Viewport : : get_sdf_scale ( ) const {
return sdf_scale ;
}
2021-07-04 01:43:23 +00:00
# ifndef _3D_DISABLED
2021-08-02 17:31:51 +00:00
Listener3D * Viewport : : get_listener_3d ( ) const {
return listener_3d ;
}
2014-02-10 01:10:30 +00:00
2021-08-02 17:31:51 +00:00
void Viewport : : set_as_audio_listener_3d ( bool p_enable ) {
if ( p_enable = = audio_listener_3d ) {
return ;
}
2014-02-10 01:10:30 +00:00
2021-08-02 17:31:51 +00:00
audio_listener_3d = p_enable ;
_update_listener_3d ( ) ;
}
2014-02-10 01:10:30 +00:00
2021-08-02 17:31:51 +00:00
bool Viewport : : is_audio_listener_3d ( ) const {
return audio_listener_3d ;
}
2014-08-14 13:31:38 +00:00
2021-08-02 17:31:51 +00:00
void Viewport : : _update_listener_3d ( ) {
2021-08-27 17:28:23 +00:00
AudioServer : : get_singleton ( ) - > notify_listener_changed ( ) ;
2021-08-02 17:31:51 +00:00
}
2020-04-12 04:49:10 +00:00
2021-08-02 17:31:51 +00:00
void Viewport : : _listener_transform_3d_changed_notify ( ) {
}
2020-04-20 21:34:47 +00:00
2021-08-02 17:31:51 +00:00
void Viewport : : _listener_3d_set ( Listener3D * p_listener ) {
if ( listener_3d = = p_listener ) {
return ;
}
2021-04-20 16:40:24 +00:00
2021-08-02 17:31:51 +00:00
listener_3d = p_listener ;
2017-06-11 18:52:03 +00:00
2021-08-02 17:31:51 +00:00
_update_listener_3d ( ) ;
_listener_transform_3d_changed_notify ( ) ;
}
2017-06-11 18:52:03 +00:00
2021-08-02 17:31:51 +00:00
bool Viewport : : _listener_3d_add ( Listener3D * p_listener ) {
listener_3d_set . insert ( p_listener ) ;
return listener_3d_set . size ( ) = = 1 ;
}
2021-04-29 01:23:24 +00:00
2021-08-02 17:31:51 +00:00
void Viewport : : _listener_3d_remove ( Listener3D * p_listener ) {
listener_3d_set . erase ( p_listener ) ;
if ( listener_3d = = p_listener ) {
listener_3d = nullptr ;
}
}
2014-02-26 13:08:17 +00:00
2021-08-02 17:31:51 +00:00
void Viewport : : _listener_3d_make_next_current ( Listener3D * p_exclude ) {
if ( listener_3d_set . size ( ) > 0 ) {
for ( Set < Listener3D * > : : Element * E = listener_3d_set . front ( ) ; E ; E = E - > next ( ) ) {
if ( p_exclude = = E - > get ( ) ) {
continue ;
}
if ( ! E - > get ( ) - > is_inside_tree ( ) ) {
continue ;
}
if ( listener_3d ! = nullptr ) {
return ;
}
2014-09-15 14:33:30 +00:00
2021-08-02 17:31:51 +00:00
E - > get ( ) - > make_current ( ) ;
}
} else {
2021-09-10 14:58:33 +00:00
// Attempt to reset listener to the camera position.
2021-08-02 17:31:51 +00:00
if ( camera_3d ! = nullptr ) {
_update_listener_3d ( ) ;
_camera_3d_transform_changed_notify ( ) ;
}
}
}
2014-02-26 13:08:17 +00:00
2021-08-02 17:31:51 +00: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 01:43:44 +00:00
2021-09-10 14:58:33 +00:00
// Avoid sending the fake event unnecessarily if nothing really changed in the context.
2021-08-02 17:31:51 +00: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 14:58:33 +00:00
return ; // Discarded.
2021-08-02 17:31:51 +00:00
}
}
2021-08-22 15:37:22 +00:00
p_object - > _input_event_call ( camera_3d , p_input_event , p_pos , p_normal , p_shape ) ;
2021-08-02 17:31:51 +00:00
physics_last_object_transform = object_transform ;
physics_last_camera_transform = camera_transform ;
physics_last_id = id ;
}
2014-02-26 13:08:17 +00:00
2021-08-02 17:31:51 +00:00
Camera3D * Viewport : : get_camera_3d ( ) const {
return camera_3d ;
}
2014-02-26 13:08:17 +00:00
2021-08-02 17:31:51 +00:00
void Viewport : : _camera_3d_transform_changed_notify ( ) {
}
2014-02-26 13:08:17 +00:00
2021-08-02 17:31:51 +00: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 ) ;
}
_update_listener_3d ( ) ;
_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 ) {
for ( Set < Camera3D * > : : Element * E = camera_3d_set . front ( ) ; E ; E = E - > next ( ) ) {
if ( p_exclude = = E - > get ( ) ) {
continue ;
}
if ( ! E - > get ( ) - > is_inside_tree ( ) ) {
continue ;
}
if ( camera_3d ! = nullptr ) {
return ;
}
E - > get ( ) - > make_current ( ) ;
}
}
void Viewport : : enable_camera_3d_override ( bool p_enable ) {
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 ) {
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 ) {
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 ) {
disable_3d = p_disable ;
RenderingServer : : get_singleton ( ) - > viewport_set_disable_3d ( viewport , disable_3d ) ;
}
bool Viewport : : is_3d_disabled ( ) const {
return disable_3d ;
}
bool Viewport : : is_camera_3d_override_enabled ( ) const {
return camera_3d_override ;
}
void Viewport : : set_camera_3d_override_transform ( const Transform3D & p_transform ) {
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 {
if ( camera_3d_override ) {
return camera_3d_override . transform ;
}
return Transform3D ( ) ;
}
Ref < World3D > Viewport : : get_world_3d ( ) const {
return world_3d ;
}
Ref < World3D > Viewport : : find_world_3d ( ) const {
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 ) {
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 ( ) ) {
world_3d - > disconnect ( CoreStringNames : : get_singleton ( ) - > changed , callable_mp ( this , & Viewport : : _own_world_3d_changed ) ) ;
}
world_3d = p_world_3d ;
if ( own_world_3d . is_valid ( ) ) {
if ( world_3d . is_valid ( ) ) {
own_world_3d = world_3d - > duplicate ( ) ;
world_3d - > connect ( CoreStringNames : : get_singleton ( ) - > changed , callable_mp ( this , & Viewport : : _own_world_3d_changed ) ) ;
} 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 ( ) ) ;
}
_update_listener_3d ( ) ;
}
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 ( ) ) ;
}
_update_listener_3d ( ) ;
}
void Viewport : : set_use_own_world_3d ( bool p_world_3d ) {
if ( p_world_3d = = own_world_3d . is_valid ( ) ) {
return ;
}
if ( is_inside_tree ( ) ) {
_propagate_exit_world_3d ( this ) ;
}
if ( ! p_world_3d ) {
own_world_3d = Ref < World3D > ( ) ;
if ( world_3d . is_valid ( ) ) {
world_3d - > disconnect ( CoreStringNames : : get_singleton ( ) - > changed , callable_mp ( this , & Viewport : : _own_world_3d_changed ) ) ;
}
} else {
if ( world_3d . is_valid ( ) ) {
own_world_3d = world_3d - > duplicate ( ) ;
world_3d - > connect ( CoreStringNames : : get_singleton ( ) - > changed , callable_mp ( this , & Viewport : : _own_world_3d_changed ) ) ;
} 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 ( ) ) ;
}
_update_listener_3d ( ) ;
}
bool Viewport : : is_using_own_world_3d ( ) const {
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 ) {
use_xr = p_use_xr ;
RS : : get_singleton ( ) - > viewport_set_use_xr ( viewport , use_xr ) ;
}
bool Viewport : : is_using_xr ( ) {
return use_xr ;
}
2021-08-19 01:52:06 +00:00
void Viewport : : set_scale_3d ( const Scale3D p_scale_3d ) {
scale_3d = p_scale_3d ;
RS : : get_singleton ( ) - > viewport_set_scale_3d ( viewport , RS : : ViewportScale3D ( scale_3d ) ) ;
}
Viewport : : Scale3D Viewport : : get_scale_3d ( ) const {
return scale_3d ;
}
2021-07-04 01:43:23 +00:00
# endif // _3D_DISABLED
2021-08-02 17:31:51 +00: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 ) ;
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 ) ;
ClassDB : : bind_method ( D_METHOD ( " set_msaa " , " msaa " ) , & Viewport : : set_msaa ) ;
ClassDB : : bind_method ( D_METHOD ( " get_msaa " ) , & Viewport : : get_msaa ) ;
ClassDB : : bind_method ( D_METHOD ( " set_screen_space_aa " , " screen_space_aa " ) , & Viewport : : set_screen_space_aa ) ;
ClassDB : : bind_method ( D_METHOD ( " get_screen_space_aa " ) , & Viewport : : get_screen_space_aa ) ;
ClassDB : : bind_method ( D_METHOD ( " set_use_debanding " , " enable " ) , & Viewport : : set_use_debanding ) ;
ClassDB : : bind_method ( D_METHOD ( " is_using_debanding " ) , & Viewport : : is_using_debanding ) ;
ClassDB : : bind_method ( D_METHOD ( " set_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 ) ;
ClassDB : : bind_method ( D_METHOD ( " get_viewport_rid " ) , & Viewport : : get_viewport_rid ) ;
2021-08-22 15:37:22 +00: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 ) ) ;
ClassDB : : bind_method ( D_METHOD ( " push_unhandled_input " , " event " , " in_local_coords " ) , & Viewport : : push_unhandled_input , DEFVAL ( false ) ) ;
2021-08-02 17:31:51 +00:00
ClassDB : : bind_method ( D_METHOD ( " get_camera_2d " ) , & Viewport : : get_camera_2d ) ;
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 ) ;
2021-06-29 16:36:32 +00:00
2017-03-29 15:29:38 +00:00
ClassDB : : bind_method ( D_METHOD ( " get_mouse_position " ) , & Viewport : : get_mouse_position ) ;
2017-09-10 13:37:49 +00:00
ClassDB : : bind_method ( D_METHOD ( " warp_mouse " , " to_position " ) , & Viewport : : warp_mouse ) ;
2014-02-26 13:08:17 +00:00
2017-08-09 11:19:41 +00:00
ClassDB : : bind_method ( D_METHOD ( " gui_get_drag_data " ) , & Viewport : : gui_get_drag_data ) ;
2018-08-24 13:29:27 +00:00
ClassDB : : bind_method ( D_METHOD ( " gui_is_dragging " ) , & Viewport : : gui_is_dragging ) ;
2016-01-17 01:41:10 +00:00
2017-03-05 15:44:50 +00:00
ClassDB : : bind_method ( D_METHOD ( " set_disable_input " , " disable " ) , & Viewport : : set_disable_input ) ;
2017-02-13 11:47:24 +00:00
ClassDB : : bind_method ( D_METHOD ( " is_input_disabled " ) , & Viewport : : is_input_disabled ) ;
2016-01-17 01:41:10 +00:00
2020-07-01 13:59:42 +00:00
ClassDB : : bind_method ( D_METHOD ( " _gui_remove_focus_for_window " ) , & Viewport : : _gui_remove_focus_for_window ) ;
2018-03-27 21:41:27 +00:00
ClassDB : : bind_method ( D_METHOD ( " _post_gui_grab_click_focus " ) , & Viewport : : _post_gui_grab_click_focus ) ;
2016-01-17 01:41:10 +00:00
2017-03-05 15:44:50 +00:00
ClassDB : : bind_method ( D_METHOD ( " set_shadow_atlas_size " , " size " ) , & Viewport : : set_shadow_atlas_size ) ;
2017-02-13 11:47:24 +00:00
ClassDB : : bind_method ( D_METHOD ( " get_shadow_atlas_size " ) , & Viewport : : get_shadow_atlas_size ) ;
2016-11-10 02:55:06 +00:00
2021-01-24 19:00:20 +00:00
ClassDB : : bind_method ( D_METHOD ( " set_shadow_atlas_16_bits " , " enable " ) , & Viewport : : set_shadow_atlas_16_bits ) ;
ClassDB : : bind_method ( D_METHOD ( " get_shadow_atlas_16_bits " ) , & Viewport : : get_shadow_atlas_16_bits ) ;
2017-09-07 14:22:07 +00: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 21:09:16 +00: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 ) ;
2017-03-05 15:44:50 +00:00
ClassDB : : bind_method ( D_METHOD ( " set_shadow_atlas_quadrant_subdiv " , " quadrant " , " subdiv " ) , & Viewport : : set_shadow_atlas_quadrant_subdiv ) ;
ClassDB : : bind_method ( D_METHOD ( " get_shadow_atlas_quadrant_subdiv " , " quadrant " ) , & Viewport : : get_shadow_atlas_quadrant_subdiv ) ;
2016-11-10 02:55:06 +00:00
2018-11-15 16:54:26 +00: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 01:24:07 +00: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 ) ;
2020-03-04 01:51:12 +00:00
ClassDB : : bind_method ( D_METHOD ( " set_embed_subwindows_hint " , " enable " ) , & Viewport : : set_embed_subwindows_hint ) ;
ClassDB : : bind_method ( D_METHOD ( " get_embed_subwindows_hint " ) , & Viewport : : get_embed_subwindows_hint ) ;
ClassDB : : bind_method ( D_METHOD ( " is_embedding_subwindows " ) , & Viewport : : is_embedding_subwindows ) ;
2019-06-25 01:24:07 +00: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 12:50:21 +00: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 ) ;
2020-12-17 18:56:59 +00:00
ClassDB : : bind_method ( D_METHOD ( " set_lod_threshold " , " pixels " ) , & Viewport : : set_lod_threshold ) ;
ClassDB : : bind_method ( D_METHOD ( " get_lod_threshold " ) , & Viewport : : get_lod_threshold ) ;
2021-02-06 20:14:35 +00:00
ClassDB : : bind_method ( D_METHOD ( " _process_picking " ) , & Viewport : : _process_picking ) ;
2021-07-04 01:43:23 +00:00
# ifndef _3D_DISABLED
2021-08-02 17:31:51 +00: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-08-19 01:52:06 +00:00
ClassDB : : bind_method ( D_METHOD ( " set_scale_3d " , " scale " ) , & Viewport : : set_scale_3d ) ;
ClassDB : : bind_method ( D_METHOD ( " get_scale_3d " ) , & Viewport : : get_scale_3d ) ;
2021-08-02 17:31:51 +00:00
ADD_PROPERTY ( PropertyInfo ( Variant : : BOOL , " disable_3d " ) , " set_disable_3d " , " is_3d_disabled " ) ;
2021-04-29 01:23:24 +00:00
ADD_PROPERTY ( PropertyInfo ( Variant : : BOOL , " use_xr " ) , " set_use_xr " , " is_using_xr " ) ;
2021-08-19 01:52:06 +00:00
ADD_PROPERTY ( PropertyInfo ( Variant : : INT , " scale_3d " , PROPERTY_HINT_ENUM , String : : utf8 ( " Disabled,75%,50%,33%,25% " ) ) , " set_scale_3d " , " get_scale_3d " ) ;
2021-08-02 17:31:51 +00:00
ADD_PROPERTY ( PropertyInfo ( Variant : : BOOL , " audio_listener_enable_3d " ) , " set_as_audio_listener_3d " , " is_audio_listener_3d " ) ;
2020-04-18 09:00:51 +00:00
ADD_PROPERTY ( PropertyInfo ( Variant : : BOOL , " own_world_3d " ) , " set_use_own_world_3d " , " is_using_own_world_3d " ) ;
2020-05-04 14:55:01 +00:00
ADD_PROPERTY ( PropertyInfo ( Variant : : OBJECT , " world_3d " , PROPERTY_HINT_RESOURCE_TYPE , " World3D " ) , " set_world_3d " , " get_world_3d " ) ;
2021-07-04 01:43:23 +00:00
# endif // _3D_DISABLED
2021-06-17 23:10:18 +00:00
ADD_PROPERTY ( PropertyInfo ( Variant : : OBJECT , " world_2d " , PROPERTY_HINT_RESOURCE_TYPE , " World2D " , PROPERTY_USAGE_NONE ) , " set_world_2d " , " get_world_2d " ) ;
2017-03-05 15:44:50 +00:00
ADD_PROPERTY ( PropertyInfo ( Variant : : BOOL , " transparent_bg " ) , " set_transparent_background " , " has_transparent_background " ) ;
2018-11-15 16:54:26 +00:00
ADD_PROPERTY ( PropertyInfo ( Variant : : BOOL , " handle_input_locally " ) , " set_handle_input_locally " , " is_handling_input_locally " ) ;
2020-10-29 21:09:16 +00: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-03-05 15:44:50 +00:00
ADD_GROUP ( " Rendering " , " " ) ;
2021-08-12 19:45:33 +00:00
ADD_PROPERTY ( PropertyInfo ( Variant : : INT , " msaa " , PROPERTY_HINT_ENUM , String : : utf8 ( " Disabled (Fastest),2× (Fast),4× (Average),8× (Slow),16× (Slower) " ) ) , " set_msaa " , " get_msaa " ) ;
2021-05-22 02:30:58 +00:00
ADD_PROPERTY ( PropertyInfo ( Variant : : INT , " screen_space_aa " , PROPERTY_HINT_ENUM , " Disabled (Fastest),FXAA (Fast) " ) , " set_screen_space_aa " , " get_screen_space_aa " ) ;
2020-04-20 21:34:47 +00:00
ADD_PROPERTY ( PropertyInfo ( Variant : : BOOL , " use_debanding " ) , " set_use_debanding " , " is_using_debanding " ) ;
2021-04-20 16:40:24 +00:00
ADD_PROPERTY ( PropertyInfo ( Variant : : BOOL , " use_occlusion_culling " ) , " set_use_occlusion_culling " , " is_using_occlusion_culling " ) ;
2020-12-17 18:56:59 +00:00
ADD_PROPERTY ( PropertyInfo ( Variant : : FLOAT , " lod_threshold " , PROPERTY_HINT_RANGE , " 0,1024,0.1 " ) , " set_lod_threshold " , " get_lod_threshold " ) ;
2017-06-11 18:52:03 +00:00
ADD_PROPERTY ( PropertyInfo ( Variant : : INT , " debug_draw " , PROPERTY_HINT_ENUM , " Disabled,Unshaded,Overdraw,Wireframe " ) , " set_debug_draw " , " get_debug_draw " ) ;
2019-06-25 01:24:07 +00:00
ADD_GROUP ( " Canvas Items " , " canvas_item_ " ) ;
2020-02-29 17:04:28 +00: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 01:24:07 +00: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-03-05 15:44:50 +00:00
ADD_GROUP ( " Audio Listener " , " audio_listener_ " ) ;
ADD_PROPERTY ( PropertyInfo ( Variant : : BOOL , " audio_listener_enable_2d " ) , " set_as_audio_listener_2d " , " is_audio_listener_2d " ) ;
ADD_GROUP ( " Physics " , " physics_ " ) ;
ADD_PROPERTY ( PropertyInfo ( Variant : : BOOL , " physics_object_picking " ) , " set_physics_object_picking " , " get_physics_object_picking " ) ;
ADD_GROUP ( " GUI " , " gui_ " ) ;
ADD_PROPERTY ( PropertyInfo ( Variant : : BOOL , " gui_disable_input " ) , " set_disable_input " , " is_input_disabled " ) ;
2017-09-07 14:22:07 +00:00
ADD_PROPERTY ( PropertyInfo ( Variant : : BOOL , " gui_snap_controls_to_pixels " ) , " set_snap_controls_to_pixels " , " is_snap_controls_to_pixels_enabled " ) ;
2020-03-04 01:51:12 +00:00
ADD_PROPERTY ( PropertyInfo ( Variant : : BOOL , " gui_embed_subwindows " ) , " set_embed_subwindows_hint " , " get_embed_subwindows_hint " ) ;
2020-11-26 12:50:21 +00: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 " ) ;
2017-03-05 15:44:50 +00:00
ADD_GROUP ( " Shadow Atlas " , " shadow_atlas_ " ) ;
ADD_PROPERTY ( PropertyInfo ( Variant : : INT , " shadow_atlas_size " ) , " set_shadow_atlas_size " , " get_shadow_atlas_size " ) ;
2021-01-24 19:00:20 +00:00
ADD_PROPERTY ( PropertyInfo ( Variant : : BOOL , " shadow_atlas_16_bits " ) , " set_shadow_atlas_16_bits " , " get_shadow_atlas_16_bits " ) ;
2017-03-05 15:44:50 +00:00
ADD_PROPERTYI ( PropertyInfo ( Variant : : INT , " shadow_atlas_quad_0 " , PROPERTY_HINT_ENUM , " Disabled,1 Shadow,4 Shadows,16 Shadows,64 Shadows,256 Shadows,1024 Shadows " ) , " set_shadow_atlas_quadrant_subdiv " , " get_shadow_atlas_quadrant_subdiv " , 0 ) ;
ADD_PROPERTYI ( PropertyInfo ( Variant : : INT , " shadow_atlas_quad_1 " , PROPERTY_HINT_ENUM , " Disabled,1 Shadow,4 Shadows,16 Shadows,64 Shadows,256 Shadows,1024 Shadows " ) , " set_shadow_atlas_quadrant_subdiv " , " get_shadow_atlas_quadrant_subdiv " , 1 ) ;
ADD_PROPERTYI ( PropertyInfo ( Variant : : INT , " shadow_atlas_quad_2 " , PROPERTY_HINT_ENUM , " Disabled,1 Shadow,4 Shadows,16 Shadows,64 Shadows,256 Shadows,1024 Shadows " ) , " set_shadow_atlas_quadrant_subdiv " , " get_shadow_atlas_quadrant_subdiv " , 2 ) ;
ADD_PROPERTYI ( PropertyInfo ( Variant : : INT , " shadow_atlas_quad_3 " , PROPERTY_HINT_ENUM , " Disabled,1 Shadow,4 Shadows,16 Shadows,64 Shadows,256 Shadows,1024 Shadows " ) , " set_shadow_atlas_quadrant_subdiv " , " get_shadow_atlas_quadrant_subdiv " , 3 ) ;
2021-06-17 23:10:18 +00: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 " ) ;
2014-02-10 01:10:30 +00:00
ADD_SIGNAL ( MethodInfo ( " size_changed " ) ) ;
2019-12-11 13:29:36 +00:00
ADD_SIGNAL ( MethodInfo ( " gui_focus_changed " , PropertyInfo ( Variant : : OBJECT , " node " , PROPERTY_HINT_RESOURCE_TYPE , " Control " ) ) ) ;
2014-02-26 13:08:17 +00:00
2021-08-19 01:52:06 +00:00
BIND_ENUM_CONSTANT ( SCALE_3D_DISABLED ) ;
BIND_ENUM_CONSTANT ( SCALE_3D_75_PERCENT ) ;
BIND_ENUM_CONSTANT ( SCALE_3D_50_PERCENT ) ;
BIND_ENUM_CONSTANT ( SCALE_3D_33_PERCENT ) ;
BIND_ENUM_CONSTANT ( SCALE_3D_25_PERCENT ) ;
2017-08-20 15:45:01 +00: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 ) ;
2020-04-20 09:48:00 +00: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_16X ) ;
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 15:45:01 +00:00
BIND_ENUM_CONSTANT ( RENDER_INFO_OBJECTS_IN_FRAME ) ;
2021-07-02 23:14:19 +00:00
BIND_ENUM_CONSTANT ( RENDER_INFO_PRIMITIVES_IN_FRAME ) ;
2017-08-20 15:45:01 +00:00
BIND_ENUM_CONSTANT ( RENDER_INFO_DRAW_CALLS_IN_FRAME ) ;
BIND_ENUM_CONSTANT ( RENDER_INFO_MAX ) ;
2021-07-02 23:14:19 +00:00
BIND_ENUM_CONSTANT ( RENDER_INFO_TYPE_VISIBLE ) ;
BIND_ENUM_CONSTANT ( RENDER_INFO_TYPE_SHADOW ) ;
BIND_ENUM_CONSTANT ( RENDER_INFO_TYPE_MAX ) ;
2017-08-20 15:45:01 +00:00
BIND_ENUM_CONSTANT ( DEBUG_DRAW_DISABLED ) ;
BIND_ENUM_CONSTANT ( DEBUG_DRAW_UNSHADED ) ;
2020-04-20 09:48:00 +00:00
BIND_ENUM_CONSTANT ( DEBUG_DRAW_LIGHTING ) ;
2017-08-20 15:45:01 +00:00
BIND_ENUM_CONSTANT ( DEBUG_DRAW_OVERDRAW ) ;
BIND_ENUM_CONSTANT ( DEBUG_DRAW_WIREFRAME ) ;
2020-04-20 09:48:00 +00:00
BIND_ENUM_CONSTANT ( DEBUG_DRAW_NORMAL_BUFFER ) ;
2021-06-04 22:47:26 +00: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 01:26:52 +00: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 10:18:55 +00:00
BIND_ENUM_CONSTANT ( DEBUG_DRAW_SSAO ) ;
2020-04-08 01:51:52 +00:00
BIND_ENUM_CONSTANT ( DEBUG_DRAW_PSSM_SPLITS ) ;
2020-04-14 03:05:21 +00:00
BIND_ENUM_CONSTANT ( DEBUG_DRAW_DECAL_ATLAS ) ;
2020-06-25 13:33:28 +00:00
BIND_ENUM_CONSTANT ( DEBUG_DRAW_SDFGI ) ;
BIND_ENUM_CONSTANT ( DEBUG_DRAW_SDFGI_PROBES ) ;
BIND_ENUM_CONSTANT ( DEBUG_DRAW_GI_BUFFER ) ;
2020-12-17 18:56:59 +00:00
BIND_ENUM_CONSTANT ( DEBUG_DRAW_DISABLE_LOD ) ;
2021-01-17 16:25:38 +00: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 16:40:24 +00:00
BIND_ENUM_CONSTANT ( DEBUG_DRAW_OCCLUDERS )
2020-01-12 01:26:52 +00:00
2019-06-25 01:24:07 +00: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-19 23:31:43 +00:00
BIND_ENUM_CONSTANT ( DEFAULT_CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS ) ;
2019-06-25 01:24:07 +00:00
BIND_ENUM_CONSTANT ( DEFAULT_CANVAS_ITEM_TEXTURE_FILTER_MAX ) ;
2020-04-20 09:48:00 +00:00
2019-06-25 01:24:07 +00: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 12:50:21 +00: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 ) ;
2014-02-10 01:10:30 +00:00
}
Viewport : : Viewport ( ) {
2017-03-05 15:44:50 +00:00
world_2d = Ref < World2D > ( memnew ( World2D ) ) ;
2014-02-10 01:10:30 +00:00
2020-03-27 18:21:27 +00:00
viewport = RenderingServer : : get_singleton ( ) - > viewport_create ( ) ;
texture_rid = RenderingServer : : get_singleton ( ) - > viewport_get_texture ( viewport ) ;
2017-01-10 21:02:19 +00:00
2021-06-17 22:03:09 +00:00
default_texture . instantiate ( ) ;
2017-03-05 15:44:50 +00:00
default_texture - > vp = const_cast < Viewport * > ( this ) ;
2017-01-10 21:02:19 +00:00
viewport_textures . insert ( default_texture . ptr ( ) ) ;
2020-03-27 18:21:27 +00:00
default_texture - > proxy = RS : : get_singleton ( ) - > texture_proxy_create ( texture_rid ) ;
2017-01-10 21:02:19 +00:00
2021-09-10 14:58:33 +00:00
canvas_layers . insert ( nullptr ) ; // This eases picking code (interpreted as the canvas of the Viewport).
2020-03-04 01:51:12 +00:00
2021-01-24 19:00:20 +00:00
set_shadow_atlas_size ( shadow_atlas_size ) ;
2017-03-05 15:44:50 +00:00
for ( int i = 0 ; i < 4 ; i + + ) {
shadow_atlas_quadrant_subdiv [ i ] = SHADOW_ATLAS_QUADRANT_SUBDIV_MAX ;
2016-11-10 02:55:06 +00:00
}
2017-03-05 15:44:50 +00:00
set_shadow_atlas_quadrant_subdiv ( 0 , SHADOW_ATLAS_QUADRANT_SUBDIV_4 ) ;
set_shadow_atlas_quadrant_subdiv ( 1 , SHADOW_ATLAS_QUADRANT_SUBDIV_4 ) ;
set_shadow_atlas_quadrant_subdiv ( 2 , SHADOW_ATLAS_QUADRANT_SUBDIV_16 ) ;
set_shadow_atlas_quadrant_subdiv ( 3 , SHADOW_ATLAS_QUADRANT_SUBDIV_64 ) ;
2014-04-15 01:43:44 +00:00
2020-12-17 18:56:59 +00:00
set_lod_threshold ( lod_threshold ) ;
2017-08-07 10:17:31 +00:00
String id = itos ( get_instance_id ( ) ) ;
2017-03-05 15:44:50 +00:00
input_group = " _vp_input " + id ;
gui_input_group = " _vp_gui_input " + id ;
unhandled_input_group = " _vp_unhandled_input " + id ;
unhandled_key_input_group = " _vp_unhandled_key_input " + id ;
2014-02-10 01:10:30 +00:00
2020-11-02 16:18:29 +00:00
// Window tooltip.
2019-04-10 17:45:29 +00:00
gui . tooltip_delay = GLOBAL_DEF ( " gui/timers/tooltip_delay_sec " , 0.5 ) ;
Variant: Added 64-bit packed arrays, renamed Variant::REAL to FLOAT.
- Renames PackedIntArray to PackedInt32Array.
- Renames PackedFloatArray to PackedFloat32Array.
- Adds PackedInt64Array and PackedFloat64Array.
- Renames Variant::REAL to Variant::FLOAT for consistency.
Packed arrays are for storing large amount of data and creating stuff like
meshes, buffers. textures, etc. Forcing them to be 64 is a huge waste of
memory. That said, many users requested the ability to have 64 bits packed
arrays for their games, so this is just an optional added type.
For Variant, the float datatype is always 64 bits, and exposed as `float`.
We still have `real_t` which is the datatype that can change from 32 to 64
bits depending on a compile flag (not entirely working right now, but that's
the idea). It affects math related datatypes and code only.
Neither Variant nor PackedArray make use of real_t, which is only intended
for math precision, so the term is removed from there to keep only float.
2020-02-24 18:20:53 +00:00
ProjectSettings : : get_singleton ( ) - > set_custom_property_info ( " gui/timers/tooltip_delay_sec " , PropertyInfo ( Variant : : FLOAT , " gui/timers/tooltip_delay_sec " , PROPERTY_HINT_RANGE , " 0,5,0.01,or_greater " ) ) ; // No negative numbers
2016-01-18 22:49:11 +00:00
2021-08-19 01:52:06 +00:00
# ifndef _3D_DISABLED
int scale = GLOBAL_GET ( " rendering/3d/viewport/scale " ) ;
set_scale_3d ( ( Scale3D ) scale ) ;
# endif // _3D_DISABLED
2021-09-10 14:58:33 +00:00
set_sdf_oversize ( sdf_oversize ) ; // Set to server.
2014-02-10 01:10:30 +00:00
}
Viewport : : ~ Viewport ( ) {
2021-09-10 14:58:33 +00:00
// Erase itself from viewport textures.
2017-03-05 15:44:50 +00:00
for ( Set < ViewportTexture * > : : Element * E = viewport_textures . front ( ) ; E ; E = E - > next ( ) ) {
2020-04-01 23:20:12 +00:00
E - > get ( ) - > vp = nullptr ;
2017-01-10 04:04:31 +00:00
}
2020-03-27 18:21:27 +00:00
RenderingServer : : get_singleton ( ) - > free ( viewport ) ;
2014-02-10 01:10:30 +00:00
}
2020-03-04 01:51:12 +00:00
/////////////////////////////////
void SubViewport : : set_size ( const Size2i & p_size ) {
2020-04-01 03:47:58 +00:00
_set_size ( p_size , _get_size_2d_override ( ) , Rect2i ( ) , _stretch_transform ( ) , true ) ;
2020-03-04 01:51:12 +00:00
}
2020-05-14 12:29:06 +00:00
2020-03-04 01:51:12 +00:00
Size2i SubViewport : : get_size ( ) const {
return _get_size ( ) ;
}
2020-04-01 03:47:58 +00:00
void SubViewport : : set_size_2d_override ( const Size2i & p_size ) {
_set_size ( _get_size ( ) , p_size , Rect2i ( ) , _stretch_transform ( ) , true ) ;
}
2020-05-14 12:29:06 +00:00
2020-04-01 03:47:58 +00:00
Size2i SubViewport : : get_size_2d_override ( ) const {
return _get_size_2d_override ( ) ;
}
void SubViewport : : set_size_2d_override_stretch ( bool p_enable ) {
if ( p_enable = = size_2d_override_stretch ) {
return ;
}
size_2d_override_stretch = p_enable ;
_set_size ( _get_size ( ) , _get_size_2d_override ( ) , Rect2i ( ) , _stretch_transform ( ) , true ) ;
}
2020-05-14 12:29:06 +00:00
2020-04-01 03:47:58 +00:00
bool SubViewport : : is_size_2d_override_stretch_enabled ( ) const {
return size_2d_override_stretch ;
}
2020-03-04 01:51:12 +00:00
void SubViewport : : set_update_mode ( UpdateMode p_mode ) {
update_mode = p_mode ;
2020-03-27 18:21:27 +00:00
RS : : get_singleton ( ) - > viewport_set_update_mode ( get_viewport_rid ( ) , RS : : ViewportUpdateMode ( p_mode ) ) ;
2020-03-04 01:51:12 +00:00
}
2020-05-14 12:29:06 +00:00
2020-03-04 01:51:12 +00:00
SubViewport : : UpdateMode SubViewport : : get_update_mode ( ) const {
return update_mode ;
}
void SubViewport : : set_clear_mode ( ClearMode p_mode ) {
clear_mode = p_mode ;
2020-03-27 18:21:27 +00:00
RS : : get_singleton ( ) - > viewport_set_clear_mode ( get_viewport_rid ( ) , RS : : ViewportClearMode ( p_mode ) ) ;
2020-03-04 01:51:12 +00:00
}
2020-05-14 12:29:06 +00:00
2020-03-04 01:51:12 +00:00
SubViewport : : ClearMode SubViewport : : get_clear_mode ( ) const {
return clear_mode ;
}
DisplayServer : : WindowID SubViewport : : get_window_id ( ) const {
return DisplayServer : : INVALID_WINDOW_ID ;
}
2020-04-01 03:47:58 +00:00
Transform2D SubViewport : : _stretch_transform ( ) {
Transform2D transform = Transform2D ( ) ;
Size2i view_size_2d_override = _get_size_2d_override ( ) ;
if ( size_2d_override_stretch & & view_size_2d_override . width > 0 & & view_size_2d_override . height > 0 ) {
Size2 scale = _get_size ( ) / view_size_2d_override ;
transform . scale ( scale ) ;
}
return transform ;
}
2020-03-14 16:06:39 +00:00
void SubViewport : : _notification ( int p_what ) {
if ( p_what = = NOTIFICATION_ENTER_TREE ) {
2020-03-27 18:21:27 +00:00
RS : : get_singleton ( ) - > viewport_set_active ( get_viewport_rid ( ) , true ) ;
2020-03-14 16:06:39 +00:00
}
if ( p_what = = NOTIFICATION_EXIT_TREE ) {
2020-03-27 18:21:27 +00:00
RS : : get_singleton ( ) - > viewport_set_active ( get_viewport_rid ( ) , false ) ;
2020-03-14 16:06:39 +00:00
}
}
2020-03-04 01:51:12 +00: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 03:47:58 +00: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 01:51:12 +00: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 ) ;
2020-04-01 03:47:58 +00:00
ADD_PROPERTY ( PropertyInfo ( Variant : : VECTOR2 , " size " ) , " set_size " , " get_size " ) ;
ADD_PROPERTY ( PropertyInfo ( Variant : : VECTOR2 , " size_2d_override " ) , " set_size_2d_override " , " get_size_2d_override " ) ;
ADD_PROPERTY ( PropertyInfo ( Variant : : BOOL , " size_2d_override_stretch " ) , " set_size_2d_override_stretch " , " is_size_2d_override_stretch_enabled " ) ;
2020-03-04 01:51:12 +00: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 " ) ;
ADD_PROPERTY ( PropertyInfo ( Variant : : INT , " render_target_update_mode " , PROPERTY_HINT_ENUM , " Disabled,Once,When Visible,Always " ) , " set_update_mode " , " get_update_mode " ) ;
2020-04-20 09:48:00 +00:00
BIND_ENUM_CONSTANT ( CLEAR_MODE_ALWAYS ) ;
BIND_ENUM_CONSTANT ( CLEAR_MODE_NEVER ) ;
2020-12-10 12:19:04 +00:00
BIND_ENUM_CONSTANT ( CLEAR_MODE_ONCE ) ;
2020-04-20 09:48:00 +00:00
2020-03-04 01:51:12 +00:00
BIND_ENUM_CONSTANT ( UPDATE_DISABLED ) ;
BIND_ENUM_CONSTANT ( UPDATE_ONCE ) ;
BIND_ENUM_CONSTANT ( UPDATE_WHEN_VISIBLE ) ;
2020-03-14 16:06:39 +00:00
BIND_ENUM_CONSTANT ( UPDATE_WHEN_PARENT_VISIBLE ) ;
2020-03-04 01:51:12 +00:00
BIND_ENUM_CONSTANT ( UPDATE_ALWAYS ) ;
}
2021-02-09 17:24:36 +00:00
SubViewport : : SubViewport ( ) { }
2020-03-04 01:51:12 +00:00
2021-02-09 17:24:36 +00:00
SubViewport : : ~ SubViewport ( ) { }