2014-02-10 02:10:30 +01:00
/*************************************************************************/
/* viewport.cpp */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
2017-08-27 14:16:55 +02:00
/* https://godotengine.org */
2014-02-10 02:10:30 +01:00
/*************************************************************************/
2020-01-01 11:16:22 +01:00
/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */
/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */
2014-02-10 02:10:30 +01: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-05 00:50:27 +01:00
2014-02-10 02:10:30 +01:00
# include "viewport.h"
2017-08-27 21:07:15 +02:00
2019-11-29 07:41:25 +01:00
# include "core/core_string_names.h"
2020-02-27 03:30:20 +01:00
# include "core/debugger/engine_debugger.h"
2020-04-28 15:19:37 +02:00
# include "core/input/input.h"
2018-09-11 18:13:45 +02:00
# include "core/os/os.h"
# include "core/project_settings.h"
2017-08-27 21:07:15 +02:00
# include "scene/2d/collision_object_2d.h"
2020-03-26 22:49:16 +01:00
# include "scene/3d/camera_3d.h"
# include "scene/3d/collision_object_3d.h"
# include "scene/3d/listener_3d.h"
# include "scene/3d/node_3d.h"
2019-02-12 17:18:13 +01:00
# include "scene/3d/world_environment.h"
2017-03-05 16:44:50 +01:00
# include "scene/gui/control.h"
2016-01-17 02:41:10 +01:00
# include "scene/gui/label.h"
2018-06-23 04:51:47 +02:00
# include "scene/gui/menu_button.h"
# include "scene/gui/panel.h"
2018-07-20 23:14:33 +02:00
# include "scene/gui/panel_container.h"
2018-06-23 04:51:47 +02:00
# include "scene/gui/popup_menu.h"
2018-08-25 00:03:26 +02:00
# include "scene/main/canvas_layer.h"
2016-01-17 02:41:10 +01:00
# include "scene/main/timer.h"
2020-03-04 17:36:09 +01:00
# include "scene/main/window.h"
2017-08-27 21:07:15 +02:00
# include "scene/resources/mesh.h"
2016-01-17 02:41:10 +01:00
# include "scene/scene_string_names.h"
2020-03-03 14:36:29 +01:00
# include "servers/display_server.h"
2020-03-27 19:21:27 +01:00
# include "servers/physics_server_2d.h"
2016-01-17 02:41:10 +01:00
2017-01-10 05:04:31 +01:00
void ViewportTexture : : setup_local_to_scene ( ) {
if ( vp ) {
vp - > viewport_textures . erase ( this ) ;
}
2020-04-02 01:20:12 +02:00
vp = nullptr ;
2017-01-10 05:04:31 +01:00
Node * local_scene = get_local_scene ( ) ;
if ( ! local_scene ) {
return ;
}
Node * vpn = local_scene - > get_node ( path ) ;
2019-08-08 22:11:48 +02:00
ERR_FAIL_COND_MSG ( ! vpn , " ViewportTexture: Path to node is invalid. " ) ;
2017-01-10 05:04:31 +01:00
2017-08-24 22:58:51 +02:00
vp = Object : : cast_to < Viewport > ( vpn ) ;
2017-01-10 05:04:31 +01:00
2019-08-08 22:11:48 +02:00
ERR_FAIL_COND_MSG ( ! vp , " ViewportTexture: Path to node does not point to a viewport. " ) ;
2017-01-10 05:04:31 +01:00
vp - > viewport_textures . insert ( this ) ;
2017-12-04 19:55:20 +01:00
2019-06-24 21:13:06 +02:00
if ( proxy_ph . is_valid ( ) ) {
2020-03-27 19:21:27 +01:00
RS : : get_singleton ( ) - > texture_proxy_update ( proxy , vp - > texture_rid ) ;
RS : : get_singleton ( ) - > free ( proxy_ph ) ;
2019-06-24 21:13:06 +02:00
} else {
ERR_FAIL_COND ( proxy . is_valid ( ) ) ; //should be invalid
2020-03-27 19:21:27 +01:00
proxy = RS : : get_singleton ( ) - > texture_proxy_create ( vp - > texture_rid ) ;
2019-06-24 21:13:06 +02:00
}
2017-01-10 05:04:31 +01:00
}
2017-03-05 16:44:50 +01:00
void ViewportTexture : : set_viewport_path_in_scene ( const NodePath & p_path ) {
2020-05-14 16:41:43 +02:00
if ( path = = p_path ) {
2017-01-10 05:04:31 +01:00
return ;
2020-05-14 16:41:43 +02:00
}
2017-01-10 05:04:31 +01:00
2017-03-05 16:44:50 +01:00
path = p_path ;
2017-01-10 05:04:31 +01:00
if ( get_local_scene ( ) ) {
setup_local_to_scene ( ) ;
}
}
NodePath ViewportTexture : : get_viewport_path_in_scene ( ) const {
return path ;
}
2016-10-05 06:26:35 +02:00
int ViewportTexture : : get_width ( ) const {
2019-09-25 10:28:50 +02:00
ERR_FAIL_COND_V_MSG ( ! vp , 0 , " Viewport Texture must be set to use it. " ) ;
2016-10-03 21:33:42 +02:00
return vp - > size . width ;
2014-02-10 02:10:30 +01:00
}
2020-05-14 14:29:06 +02:00
2017-03-05 16:44:50 +01:00
int ViewportTexture : : get_height ( ) const {
2019-09-25 10:28:50 +02:00
ERR_FAIL_COND_V_MSG ( ! vp , 0 , " Viewport Texture must be set to use it. " ) ;
2016-10-03 21:33:42 +02:00
return vp - > size . height ;
2014-02-10 02:10:30 +01:00
}
2020-05-14 14:29:06 +02:00
2017-03-05 16:44:50 +01:00
Size2 ViewportTexture : : get_size ( ) const {
2019-09-25 10:28:50 +02:00
ERR_FAIL_COND_V_MSG ( ! vp , Size2 ( ) , " Viewport Texture must be set to use it. " ) ;
2016-10-03 21:33:42 +02:00
return vp - > size ;
2014-02-10 02:10:30 +01:00
}
2020-05-14 14:29:06 +02:00
2017-03-05 16:44:50 +01:00
RID ViewportTexture : : get_rid ( ) const {
2019-09-25 10:28:50 +02:00
//ERR_FAIL_COND_V_MSG(!vp, RID(), "Viewport Texture must be set to use it.");
2019-06-24 21:13:06 +02:00
if ( proxy . is_null ( ) ) {
2020-03-27 19:21:27 +01:00
proxy_ph = RS : : get_singleton ( ) - > texture_2d_placeholder_create ( ) ;
proxy = RS : : get_singleton ( ) - > texture_proxy_create ( proxy_ph ) ;
2019-06-24 21:13:06 +02:00
}
2017-12-04 19:55:20 +01:00
return proxy ;
2014-02-10 02:10:30 +01:00
}
2017-03-05 16:44:50 +01:00
bool ViewportTexture : : has_alpha ( ) const {
2014-02-10 02:10:30 +01:00
return false ;
}
2020-05-14 14:29:06 +02:00
2017-06-09 05:23:50 +02:00
Ref < Image > ViewportTexture : : get_data ( ) const {
2019-09-25 10:28:50 +02:00
ERR_FAIL_COND_V_MSG ( ! vp , Ref < Image > ( ) , " Viewport Texture must be set to use it. " ) ;
2020-03-27 19:21:27 +01:00
return RS : : get_singleton ( ) - > texture_2d_get ( vp - > texture_rid ) ;
2017-01-10 05:04:31 +01:00
}
void ViewportTexture : : _bind_methods ( ) {
2017-03-05 16:44:50 +01:00
ClassDB : : bind_method ( D_METHOD ( " set_viewport_path_in_scene " , " path " ) , & ViewportTexture : : set_viewport_path_in_scene ) ;
ClassDB : : bind_method ( D_METHOD ( " get_viewport_path_in_scene " ) , & ViewportTexture : : get_viewport_path_in_scene ) ;
2017-01-10 05:04:31 +01:00
2020-03-04 02:51:12 +01: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 05:04:31 +01:00
}
2017-03-05 16:44:50 +01:00
ViewportTexture : : ViewportTexture ( ) {
2020-04-02 01:20:12 +02:00
vp = nullptr ;
2017-01-10 05:04:31 +01:00
set_local_to_scene ( true ) ;
2014-02-10 02:10:30 +01:00
}
2017-03-05 16:44:50 +01:00
ViewportTexture : : ~ ViewportTexture ( ) {
2017-01-10 05:04:31 +01:00
if ( vp ) {
vp - > viewport_textures . erase ( this ) ;
}
2017-12-04 19:55:20 +01:00
2019-06-24 21:13:06 +02:00
if ( proxy_ph . is_valid ( ) ) {
2020-03-27 19:21:27 +01:00
RS : : get_singleton ( ) - > free ( proxy_ph ) ;
2019-06-24 21:13:06 +02:00
}
2019-07-29 23:19:31 +02:00
if ( proxy . is_valid ( ) ) {
2020-03-27 19:21:27 +01:00
RS : : get_singleton ( ) - > free ( proxy ) ;
2019-07-29 23:19:31 +02:00
}
2014-02-10 02:10:30 +01:00
}
2016-01-17 02:41:10 +01:00
/////////////////////////////////////
2020-03-20 21:51:53 +01:00
class TooltipPanel : public PopupPanel {
GDCLASS ( TooltipPanel , PopupPanel ) ;
2019-03-19 19:35:57 +01:00
2016-01-17 02:41:10 +01:00
public :
2020-05-12 17:01:17 +02:00
TooltipPanel ( ) { }
2016-01-17 02:41:10 +01:00
} ;
class TooltipLabel : public Label {
2019-03-19 19:35:57 +01:00
GDCLASS ( TooltipLabel , Label ) ;
2016-01-17 02:41:10 +01:00
public :
2020-05-12 17:01:17 +02:00
TooltipLabel ( ) { }
2016-01-17 02:41:10 +01:00
} ;
Viewport : : GUI : : GUI ( ) {
2020-03-04 02:51:12 +01:00
embed_subwindows_hint = false ;
2020-03-14 17:06:39 +01:00
embedding_subwindows = false ;
2020-03-04 02:51:12 +01:00
2018-08-24 15:29:27 +02:00
dragging = false ;
2020-04-02 01:20:12 +02:00
mouse_focus = nullptr ;
2020-03-20 03:32:09 +01:00
forced_mouse_focus = false ;
2020-04-02 01:20:12 +02:00
mouse_click_grabber = nullptr ;
2018-11-28 13:31:17 +01:00
mouse_focus_mask = 0 ;
2020-04-02 01:20:12 +02:00
key_focus = nullptr ;
mouse_over = nullptr ;
drag_mouse_over = nullptr ;
2016-01-17 02:41:10 +01:00
2020-04-02 01:20:12 +02:00
tooltip = nullptr ;
tooltip_popup = nullptr ;
tooltip_label = nullptr ;
2016-01-17 02:41:10 +01:00
}
2014-02-10 02:10:30 +01:00
2016-01-17 02:41:10 +01:00
/////////////////////////////////////
2018-03-01 14:44:45 +01:00
2014-02-10 02:10:30 +01:00
void Viewport : : update_worlds ( ) {
2020-05-14 16:41:43 +02:00
if ( ! is_inside_tree ( ) ) {
2014-02-10 02:10:30 +01:00
return ;
2020-05-14 16:41:43 +02:00
}
2014-02-10 02:10:30 +01:00
2017-03-06 02:28:58 +01:00
Rect2 abstracted_rect = Rect2 ( Vector2 ( ) , get_visible_rect ( ) . size ) ;
Rect2 xformed_rect = ( global_canvas_transform * canvas_transform ) . affine_inverse ( ) . xform ( abstracted_rect ) ;
2017-03-05 16:44:50 +01:00
find_world_2d ( ) - > _update_viewport ( this , xformed_rect ) ;
2014-02-10 02:10:30 +01:00
find_world_2d ( ) - > _update ( ) ;
2020-04-18 11:00:51 +02:00
find_world_3d ( ) - > _update ( get_tree ( ) - > get_frame ( ) ) ;
2014-02-10 02:10:30 +01:00
}
2020-03-26 22:49:16 +01:00
void Viewport : : _collision_object_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 ) {
2018-11-15 17:54:26 +01:00
Transform object_transform = p_object - > get_global_transform ( ) ;
Transform camera_transform = p_camera - > get_global_transform ( ) ;
ObjectID id = p_object - > get_instance_id ( ) ;
2019-03-09 22:03:27 +01:00
//avoid sending the fake event unnecessarily if nothing really changed in the context
if ( object_transform = = physics_last_object_transform & & camera_transform = = physics_last_camera_transform & & physics_last_id = = id ) {
2018-11-15 17:54:26 +01:00
Ref < InputEventMouseMotion > mm = p_input_event ;
2019-03-09 22:03:27 +01:00
if ( mm . is_valid ( ) & & mm - > get_device ( ) = = InputEvent : : DEVICE_ID_INTERNAL ) {
2018-11-15 17:54:26 +01:00
return ; //discarded
}
}
p_object - > _input_event ( camera , p_input_event , p_pos , p_normal , p_shape ) ;
physics_last_object_transform = object_transform ;
physics_last_camera_transform = camera_transform ;
physics_last_id = id ;
}
2020-03-14 17:06:39 +01:00
void Viewport : : _sub_window_update_order ( ) {
for ( int i = 0 ; i < gui . sub_windows . size ( ) ; i + + ) {
2020-03-27 19:21:27 +01:00
RS : : get_singleton ( ) - > canvas_item_set_draw_index ( gui . sub_windows [ i ] . canvas_item , i ) ;
2020-03-14 17:06:39 +01:00
}
}
void Viewport : : _sub_window_register ( Window * p_window ) {
ERR_FAIL_COND ( ! is_inside_tree ( ) ) ;
for ( int i = 0 ; i < gui . sub_windows . size ( ) ; i + + ) {
ERR_FAIL_COND ( gui . sub_windows [ i ] . window = = p_window ) ;
}
if ( gui . sub_windows . size ( ) = = 0 ) {
2020-03-27 19:21:27 +01:00
subwindow_canvas = RS : : get_singleton ( ) - > canvas_create ( ) ;
RS : : get_singleton ( ) - > viewport_attach_canvas ( viewport , subwindow_canvas ) ;
RS : : get_singleton ( ) - > viewport_set_canvas_stacking ( viewport , subwindow_canvas , SUBWINDOW_CANVAS_LAYER , 0 ) ;
2020-03-14 17:06:39 +01:00
}
SubWindow sw ;
2020-03-27 19:21:27 +01:00
sw . canvas_item = RS : : get_singleton ( ) - > canvas_item_create ( ) ;
RS : : get_singleton ( ) - > canvas_item_set_parent ( sw . canvas_item , subwindow_canvas ) ;
2020-03-14 17:06:39 +01:00
sw . window = p_window ;
gui . sub_windows . push_back ( sw ) ;
_sub_window_grab_focus ( p_window ) ;
2020-03-27 19:21:27 +01:00
RenderingServer : : get_singleton ( ) - > viewport_set_parent_viewport ( p_window - > viewport , viewport ) ;
2020-03-14 17:06:39 +01:00
}
void Viewport : : _sub_window_update ( Window * p_window ) {
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 19:21:27 +01:00
RS : : get_singleton ( ) - > canvas_item_clear ( sw . canvas_item ) ;
2020-03-14 17:06:39 +01:00
Rect2i r = Rect2i ( p_window - > get_position ( ) , sw . window - > get_size ( ) ) ;
if ( ! p_window - > get_flag ( Window : : FLAG_BORDERLESS ) ) {
Ref < StyleBox > panel = p_window - > get_theme_stylebox ( " panel_window " ) ;
panel - > draw ( sw . canvas_item , r ) ;
// Draw the title bar text.
Ref < Font > title_font = p_window - > get_theme_font ( " title_font " ) ;
Color title_color = p_window - > get_theme_color ( " title_color " ) ;
int title_height = p_window - > get_theme_constant ( " title_height " ) ;
int font_height = title_font - > get_height ( ) - title_font - > get_descent ( ) * 2 ;
int x = ( r . size . width - title_font - > get_string_size ( p_window - > get_title ( ) ) . x ) / 2 ;
int y = ( - title_height + font_height ) / 2 ;
int close_h_ofs = p_window - > get_theme_constant ( " close_h_ofs " ) ;
int close_v_ofs = p_window - > get_theme_constant ( " close_v_ofs " ) ;
title_font - > draw ( sw . canvas_item , r . position + Point2 ( x , y ) , p_window - > get_title ( ) , title_color , r . size . width - panel - > get_minimum_size ( ) . x - close_h_ofs ) ;
bool hl = 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 ( hl ? " close_highlight " : " close " ) ;
close_icon - > draw ( sw . canvas_item , r . position + Vector2 ( r . size . width - close_h_ofs , - close_v_ofs ) ) ;
}
2020-03-27 19:21:27 +01:00
RS : : get_singleton ( ) - > canvas_item_add_texture_rect ( sw . canvas_item , r , sw . window - > get_texture ( ) - > get_rid ( ) ) ;
2020-03-14 17:06:39 +01:00
}
void Viewport : : _sub_window_grab_focus ( Window * p_window ) {
if ( p_window = = nullptr ) {
//release current focus
if ( gui . subwindow_focused ) {
gui . subwindow_focused - > _event_callback ( DisplayServer : : WINDOW_EVENT_FOCUS_OUT ) ;
gui . subwindow_focused = nullptr ;
gui . subwindow_drag = SUB_WINDOW_DRAG_DISABLED ;
}
Window * this_window = Object : : cast_to < Window > ( this ) ;
if ( this_window ) {
this_window - > _event_callback ( DisplayServer : : WINDOW_EVENT_FOCUS_IN ) ;
}
return ;
}
2020-03-20 21:51:53 +01:00
2020-03-14 17:06:39 +01: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 21:51:53 +01:00
if ( p_window - > get_flag ( Window : : FLAG_NO_FOCUS ) ) {
//can only move to foreground, but no focus granted
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 ( ) ;
return ; //i guess not...
}
2020-03-14 17:06:39 +01:00
if ( gui . subwindow_focused ) {
if ( gui . subwindow_focused = = p_window ) {
return ; //nothing to do
}
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 ) ;
{ //move to foreground
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 19:21:27 +01:00
RS : : get_singleton ( ) - > free ( gui . sub_windows [ i ] . canvas_item ) ;
2020-03-14 17:06:39 +01:00
gui . sub_windows . remove ( i ) ;
break ;
}
}
if ( gui . sub_windows . size ( ) = = 0 ) {
2020-03-27 19:21:27 +01:00
RS : : get_singleton ( ) - > free ( subwindow_canvas ) ;
2020-03-14 17:06:39 +01:00
subwindow_canvas = RID ( ) ;
}
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 19:21:27 +01:00
RenderingServer : : get_singleton ( ) - > viewport_set_parent_viewport ( p_window - > viewport , p_window - > parent ? p_window - > parent - > viewport : RID ( ) ) ;
2020-03-14 17:06:39 +01:00
}
2020-04-18 11:00:51 +02:00
void Viewport : : _own_world_3d_changed ( ) {
ERR_FAIL_COND ( world_3d . is_null ( ) ) ;
ERR_FAIL_COND ( own_world_3d . is_null ( ) ) ;
2019-11-29 07:41:25 +01:00
if ( is_inside_tree ( ) ) {
_propagate_exit_world ( this ) ;
}
2020-04-18 11:00:51 +02:00
own_world_3d = world_3d - > duplicate ( ) ;
2019-11-29 07:41:25 +01:00
if ( is_inside_tree ( ) ) {
_propagate_enter_world ( this ) ;
}
if ( is_inside_tree ( ) ) {
2020-04-18 11:00:51 +02:00
RenderingServer : : get_singleton ( ) - > viewport_set_scenario ( viewport , find_world_3d ( ) - > get_scenario ( ) ) ;
2019-11-29 07:41:25 +01:00
}
_update_listener ( ) ;
}
2014-02-10 02:10:30 +01:00
void Viewport : : _notification ( int p_what ) {
2017-03-05 16:44:50 +01:00
switch ( p_what ) {
2014-11-06 01:20:42 +01:00
case NOTIFICATION_ENTER_TREE : {
2020-03-14 17:06:39 +01:00
gui . embedding_subwindows = gui . embed_subwindows_hint ;
2016-01-18 23:49:11 +01:00
if ( get_parent ( ) ) {
2016-10-05 06:26:35 +02:00
parent = get_parent ( ) - > get_viewport ( ) ;
2020-03-27 19:21:27 +01:00
RenderingServer : : get_singleton ( ) - > viewport_set_parent_viewport ( viewport , parent - > get_viewport_rid ( ) ) ;
2016-10-05 06:26:35 +02:00
} else {
2020-04-02 01:20:12 +02:00
parent = nullptr ;
2014-02-10 02:10:30 +01:00
}
2017-03-05 16:44:50 +01:00
current_canvas = find_world_2d ( ) - > get_canvas ( ) ;
2020-04-18 11:00:51 +02:00
RenderingServer : : get_singleton ( ) - > viewport_set_scenario ( viewport , find_world_3d ( ) - > get_scenario ( ) ) ;
2020-03-27 19:21:27 +01:00
RenderingServer : : get_singleton ( ) - > viewport_attach_canvas ( viewport , current_canvas ) ;
2014-02-10 02:10:30 +01:00
_update_listener ( ) ;
_update_listener_2d ( ) ;
2017-03-05 16:44:50 +01:00
find_world_2d ( ) - > _register_viewport ( this , Rect2 ( ) ) ;
2014-02-10 02:10:30 +01:00
2015-09-20 22:29:36 +02:00
add_to_group ( " _viewports " ) ;
2015-09-20 18:03:46 +02:00
if ( get_tree ( ) - > is_debugging_collisions_hint ( ) ) {
//2D
2020-03-27 19:21:27 +01:00
PhysicsServer2D : : get_singleton ( ) - > space_set_debug_contacts ( find_world_2d ( ) - > get_space ( ) , get_tree ( ) - > get_collision_debug_contact_count ( ) ) ;
contact_2d_debug = RenderingServer : : get_singleton ( ) - > canvas_item_create ( ) ;
RenderingServer : : get_singleton ( ) - > canvas_item_set_parent ( contact_2d_debug , find_world_2d ( ) - > get_canvas ( ) ) ;
2015-09-20 18:03:46 +02:00
//3D
2020-04-18 11:00:51 +02:00
PhysicsServer3D : : get_singleton ( ) - > space_set_debug_contacts ( find_world_3d ( ) - > get_space ( ) , get_tree ( ) - > get_collision_debug_contact_count ( ) ) ;
2020-03-27 19:21:27 +01:00
contact_3d_debug_multimesh = RenderingServer : : get_singleton ( ) - > multimesh_create ( ) ;
RenderingServer : : get_singleton ( ) - > multimesh_allocate ( contact_3d_debug_multimesh , get_tree ( ) - > get_collision_debug_contact_count ( ) , RS : : MULTIMESH_TRANSFORM_3D , true ) ;
RenderingServer : : get_singleton ( ) - > multimesh_set_visible_instances ( contact_3d_debug_multimesh , 0 ) ;
RenderingServer : : get_singleton ( ) - > multimesh_set_mesh ( contact_3d_debug_multimesh , get_tree ( ) - > get_debug_contact_mesh ( ) - > get_rid ( ) ) ;
contact_3d_debug_instance = RenderingServer : : get_singleton ( ) - > instance_create ( ) ;
RenderingServer : : get_singleton ( ) - > instance_set_base ( contact_3d_debug_instance , contact_3d_debug_multimesh ) ;
2020-04-18 11:00:51 +02:00
RenderingServer : : get_singleton ( ) - > instance_set_scenario ( contact_3d_debug_instance , find_world_3d ( ) - > get_scenario ( ) ) ;
2020-03-27 19:21:27 +01:00
//RenderingServer::get_singleton()->instance_geometry_set_flag(contact_3d_debug_instance, RS::INSTANCE_FLAG_VISIBLE_IN_ALL_ROOMS, true);
2015-09-20 18:03:46 +02:00
}
2014-02-10 02:10:30 +01:00
} break ;
case NOTIFICATION_READY : {
2014-07-03 10:06:23 +02:00
# ifndef _3D_DISABLED
2016-03-20 03:10:04 +01:00
if ( listeners . size ( ) & & ! listener ) {
2020-04-02 01:20:12 +02:00
Listener3D * first = nullptr ;
2020-03-26 22:49:16 +01:00
for ( Set < Listener3D * > : : Element * E = listeners . front ( ) ; E ; E = E - > next ( ) ) {
2020-04-02 01:20:12 +02:00
if ( first = = nullptr | | first - > is_greater_than ( E - > get ( ) ) ) {
2017-03-05 16:44:50 +01:00
first = E - > get ( ) ;
2016-03-20 03:10:04 +01:00
}
}
2020-05-14 16:41:43 +02:00
if ( first ) {
2016-03-20 03:10:04 +01:00
first - > make_current ( ) ;
2020-05-14 16:41:43 +02:00
}
2016-03-20 03:10:04 +01:00
}
2014-02-10 02:10:30 +01:00
if ( cameras . size ( ) & & ! camera ) {
//there are cameras but no current camera, pick first in tree and make it current
2020-04-02 01:20:12 +02:00
Camera3D * first = nullptr ;
2020-03-26 22:49:16 +01:00
for ( Set < Camera3D * > : : Element * E = cameras . front ( ) ; E ; E = E - > next ( ) ) {
2020-04-02 01:20:12 +02:00
if ( first = = nullptr | | first - > is_greater_than ( E - > get ( ) ) ) {
2017-03-05 16:44:50 +01:00
first = E - > get ( ) ;
2014-02-10 02:10:30 +01:00
}
}
2020-05-14 16:41:43 +02:00
if ( first ) {
2014-02-10 02:10:30 +01:00
first - > make_current ( ) ;
2020-05-14 16:41:43 +02:00
}
2014-02-10 02:10:30 +01:00
}
2014-07-03 10:06:23 +02:00
# endif
2018-03-01 14:44:45 +01:00
// Enable processing for tooltips, collision debugging, physics object picking, etc.
set_process_internal ( true ) ;
set_physics_process_internal ( true ) ;
2014-02-10 02:10:30 +01:00
} break ;
2014-11-06 01:20:42 +01:00
case NOTIFICATION_EXIT_TREE : {
2016-01-25 14:30:03 +01:00
_gui_cancel_tooltip ( ) ;
2020-05-14 16:41:43 +02:00
if ( world_2d . is_valid ( ) ) {
2014-02-10 02:10:30 +01:00
world_2d - > _remove_viewport ( this ) ;
2020-05-14 16:41:43 +02:00
}
2014-02-10 02:10:30 +01:00
2020-03-27 19:21:27 +01:00
RenderingServer : : get_singleton ( ) - > viewport_set_scenario ( viewport , RID ( ) ) ;
RenderingServer : : get_singleton ( ) - > viewport_remove_canvas ( viewport , current_canvas ) ;
2015-09-20 18:03:46 +02:00
if ( contact_2d_debug . is_valid ( ) ) {
2020-03-27 19:21:27 +01:00
RenderingServer : : get_singleton ( ) - > free ( contact_2d_debug ) ;
2017-03-05 16:44:50 +01:00
contact_2d_debug = RID ( ) ;
2015-09-20 18:03:46 +02:00
}
if ( contact_3d_debug_multimesh . is_valid ( ) ) {
2020-03-27 19:21:27 +01:00
RenderingServer : : get_singleton ( ) - > free ( contact_3d_debug_multimesh ) ;
RenderingServer : : get_singleton ( ) - > free ( contact_3d_debug_instance ) ;
2017-03-05 16:44:50 +01:00
contact_3d_debug_instance = RID ( ) ;
contact_3d_debug_multimesh = RID ( ) ;
2015-09-20 18:03:46 +02:00
}
2014-02-10 02:10:30 +01:00
remove_from_group ( " _viewports " ) ;
2016-10-05 06:26:35 +02:00
2020-03-27 19:21:27 +01:00
RS : : get_singleton ( ) - > viewport_set_active ( viewport , false ) ;
RenderingServer : : get_singleton ( ) - > viewport_set_parent_viewport ( viewport , RID ( ) ) ;
2014-02-10 02:10:30 +01:00
} break ;
2018-03-01 14:44:45 +01:00
case NOTIFICATION_INTERNAL_PROCESS : {
2017-03-05 16:44:50 +01:00
if ( gui . tooltip_timer > = 0 ) {
2018-03-01 14:44:45 +01:00
gui . tooltip_timer - = get_process_delta_time ( ) ;
2017-03-05 16:44:50 +01:00
if ( gui . tooltip_timer < 0 ) {
2016-01-25 14:30:03 +01:00
_gui_show_tooltip ( ) ;
}
}
2015-09-20 18:03:46 +02:00
2018-03-01 14:44:45 +01:00
} break ;
case NOTIFICATION_INTERNAL_PHYSICS_PROCESS : {
2015-09-20 18:03:46 +02:00
if ( get_tree ( ) - > is_debugging_collisions_hint ( ) & & contact_2d_debug . is_valid ( ) ) {
2020-03-27 19:21:27 +01:00
RenderingServer : : get_singleton ( ) - > canvas_item_clear ( contact_2d_debug ) ;
RenderingServer : : get_singleton ( ) - > canvas_item_set_draw_index ( contact_2d_debug , 0xFFFFF ) ; //very high index
2015-09-20 18:03:46 +02:00
2020-03-27 19:21:27 +01:00
Vector < Vector2 > points = PhysicsServer2D : : get_singleton ( ) - > space_get_contacts ( find_world_2d ( ) - > get_space ( ) ) ;
int point_count = PhysicsServer2D : : get_singleton ( ) - > space_get_contact_count ( find_world_2d ( ) - > get_space ( ) ) ;
2015-09-20 18:03:46 +02:00
Color ccol = get_tree ( ) - > get_debug_collision_contact_color ( ) ;
2017-03-05 16:44:50 +01:00
for ( int i = 0 ; i < point_count ; i + + ) {
2020-03-27 19:21:27 +01:00
RenderingServer : : get_singleton ( ) - > canvas_item_add_rect ( contact_2d_debug , Rect2 ( points [ i ] - Vector2 ( 2 , 2 ) , Vector2 ( 5 , 5 ) ) , ccol ) ;
2015-09-20 18:03:46 +02:00
}
}
if ( get_tree ( ) - > is_debugging_collisions_hint ( ) & & contact_3d_debug_multimesh . is_valid ( ) ) {
2020-04-18 11:00:51 +02:00
Vector < Vector3 > points = PhysicsServer3D : : get_singleton ( ) - > space_get_contacts ( find_world_3d ( ) - > get_space ( ) ) ;
int point_count = PhysicsServer3D : : get_singleton ( ) - > space_get_contact_count ( find_world_3d ( ) - > get_space ( ) ) ;
2015-09-20 18:03:46 +02:00
2020-03-27 19:21:27 +01:00
RS : : get_singleton ( ) - > multimesh_set_visible_instances ( contact_3d_debug_multimesh , point_count ) ;
2015-09-20 18:03:46 +02:00
}
2020-04-28 15:19:37 +02:00
if ( physics_object_picking & & ( to_screen_rect = = Rect2i ( ) | | Input : : get_singleton ( ) - > get_mouse_mode ( ) ! = Input : : MOUSE_MODE_CAPTURED ) ) {
2019-04-20 11:07:58 +02:00
# ifndef _3D_DISABLED
2017-03-05 16:44:50 +01:00
Vector2 last_pos ( 1e20 , 1e20 ) ;
2020-04-02 01:20:12 +02:00
CollisionObject3D * last_object = nullptr ;
2020-02-12 18:24:06 +01:00
ObjectID last_id ;
2019-04-20 11:07:58 +02:00
# endif
2020-03-27 19:21:27 +01:00
PhysicsDirectSpaceState3D : : RayResult result ;
PhysicsDirectSpaceState2D * ss2d = PhysicsServer2D : : get_singleton ( ) - > space_get_direct_state ( find_world_2d ( ) - > get_space ( ) ) ;
2014-09-15 16:33:30 +02:00
2019-03-05 22:31:02 +01:00
if ( physics_has_last_mousepos ) {
// if no mouse event exists, create a motion one. This is necessary because objects or camera may have moved.
2019-02-13 09:23:29 +01:00
// while this extra event is sent, it is checked if both camera and last object and last ID did not move. If nothing changed, the event is discarded to avoid flooding with unnecessary motion events every frame
2019-03-05 22:31:02 +01:00
bool has_mouse_event = false ;
2020-03-17 07:33:00 +01:00
for ( List < Ref < InputEvent > > : : Element * E = physics_picking_events . front ( ) ; E ; E = E - > next ( ) ) {
2019-03-05 22:31:02 +01:00
Ref < InputEventMouse > m = E - > get ( ) ;
if ( m . is_valid ( ) ) {
has_mouse_event = true ;
2018-11-15 17:54:26 +01:00
break ;
}
}
2019-03-05 22:31:02 +01:00
if ( ! has_mouse_event ) {
2018-11-15 17:54:26 +01:00
Ref < InputEventMouseMotion > mm ;
mm . instance ( ) ;
2020-03-20 03:32:09 +01:00
2019-03-09 22:03:27 +01:00
mm - > set_device ( InputEvent : : DEVICE_ID_INTERNAL ) ;
2018-11-15 17:54:26 +01:00
mm - > set_global_position ( physics_last_mousepos ) ;
mm - > set_position ( physics_last_mousepos ) ;
mm - > set_alt ( physics_last_mouse_state . alt ) ;
mm - > set_shift ( physics_last_mouse_state . shift ) ;
mm - > set_control ( physics_last_mouse_state . control ) ;
mm - > set_metakey ( physics_last_mouse_state . meta ) ;
mm - > set_button_mask ( physics_last_mouse_state . mouse_mask ) ;
physics_picking_events . push_back ( mm ) ;
}
}
2017-03-05 16:44:50 +01:00
while ( physics_picking_events . size ( ) ) {
2017-05-20 17:38:03 +02:00
Ref < InputEvent > ev = physics_picking_events . front ( ) - > get ( ) ;
2014-09-15 16:33:30 +02:00
physics_picking_events . pop_front ( ) ;
Vector2 pos ;
2019-03-05 22:31:02 +01:00
bool is_mouse = false ;
2017-05-20 17:38:03 +02:00
Ref < InputEventMouseMotion > mm = ev ;
if ( mm . is_valid ( ) ) {
2017-06-03 10:54:24 +02:00
pos = mm - > get_position ( ) ;
2019-03-05 22:31:02 +01:00
is_mouse = true ;
2018-12-18 08:11:13 +01:00
physics_has_last_mousepos = true ;
2017-05-20 17:38:03 +02:00
physics_last_mousepos = pos ;
2018-11-15 17:54:26 +01:00
physics_last_mouse_state . alt = mm - > get_alt ( ) ;
physics_last_mouse_state . shift = mm - > get_shift ( ) ;
physics_last_mouse_state . control = mm - > get_control ( ) ;
physics_last_mouse_state . meta = mm - > get_metakey ( ) ;
physics_last_mouse_state . mouse_mask = mm - > get_button_mask ( ) ;
2017-05-20 17:38:03 +02:00
}
Ref < InputEventMouseButton > mb = ev ;
if ( mb . is_valid ( ) ) {
2017-06-03 10:54:24 +02:00
pos = mb - > get_position ( ) ;
2019-03-05 22:31:02 +01:00
is_mouse = true ;
physics_has_last_mousepos = true ;
physics_last_mousepos = pos ;
2018-11-15 17:54:26 +01:00
physics_last_mouse_state . alt = mb - > get_alt ( ) ;
physics_last_mouse_state . shift = mb - > get_shift ( ) ;
physics_last_mouse_state . control = mb - > get_control ( ) ;
physics_last_mouse_state . meta = mb - > get_metakey ( ) ;
if ( mb - > is_pressed ( ) ) {
physics_last_mouse_state . mouse_mask | = ( 1 < < ( mb - > get_button_index ( ) - 1 ) ) ;
} else {
physics_last_mouse_state . mouse_mask & = ~ ( 1 < < ( mb - > get_button_index ( ) - 1 ) ) ;
2019-03-05 22:31:02 +01:00
// If touch mouse raised, assume we don't know last mouse pos until new events come
2019-03-09 22:03:27 +01:00
if ( mb - > get_device ( ) = = InputEvent : : DEVICE_ID_TOUCH_MOUSE ) {
2019-03-05 22:31:02 +01:00
physics_has_last_mousepos = false ;
}
2018-11-15 17:54:26 +01:00
}
}
Ref < InputEventKey > k = ev ;
if ( k . is_valid ( ) ) {
//only for mask
physics_last_mouse_state . alt = k - > get_alt ( ) ;
physics_last_mouse_state . shift = k - > get_shift ( ) ;
physics_last_mouse_state . control = k - > get_control ( ) ;
physics_last_mouse_state . meta = k - > get_metakey ( ) ;
continue ;
2017-05-20 17:38:03 +02:00
}
Ref < InputEventScreenDrag > sd = ev ;
if ( sd . is_valid ( ) ) {
2017-06-03 10:54:24 +02:00
pos = sd - > get_position ( ) ;
2017-05-20 17:38:03 +02:00
}
Ref < InputEventScreenTouch > st = ev ;
if ( st . is_valid ( ) ) {
2017-06-03 10:54:24 +02:00
pos = st - > get_position ( ) ;
2014-09-15 16:33:30 +02:00
}
2015-03-22 05:46:18 +01:00
if ( ss2d ) {
//send to 2D
uint64_t frame = get_tree ( ) - > get_frame ( ) ;
2020-03-27 19:21:27 +01:00
PhysicsDirectSpaceState2D : : ShapeResult res [ 64 ] ;
2018-08-25 00:03:26 +02:00
for ( Set < CanvasLayer * > : : Element * E = canvas_layers . front ( ) ; E ; E = E - > next ( ) ) {
Transform2D canvas_transform ;
ObjectID canvas_layer_id ;
if ( E - > get ( ) ) {
// A descendant CanvasLayer
canvas_transform = E - > get ( ) - > get_transform ( ) ;
canvas_layer_id = E - > get ( ) - > get_instance_id ( ) ;
} else {
// This Viewport's builtin canvas
canvas_transform = get_canvas_transform ( ) ;
2020-02-12 18:24:06 +01:00
canvas_layer_id = ObjectID ( ) ;
2018-08-25 00:03:26 +02:00
}
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 + + ) {
2020-02-12 18:24:06 +01:00
if ( res [ i ] . collider_id . is_valid ( ) & & res [ i ] . collider ) {
2018-08-25 00:03:26 +02:00
CollisionObject2D * co = Object : : cast_to < CollisionObject2D > ( res [ i ] . collider ) ;
if ( co ) {
2019-03-09 22:03:27 +01:00
bool send_event = true ;
2019-03-05 22:31:02 +01:00
if ( is_mouse ) {
Map < ObjectID , uint64_t > : : Element * F = physics_2d_mouseover . find ( res [ i ] . collider_id ) ;
2019-03-09 22:03:27 +01:00
2019-03-05 22:31:02 +01:00
if ( ! F ) {
2019-06-26 15:08:25 +02:00
physics_2d_mouseover . insert ( res [ i ] . collider_id , frame ) ;
2019-03-05 22:31:02 +01:00
co - > _mouse_enter ( ) ;
} else {
F - > get ( ) = frame ;
2019-03-09 22:03:27 +01:00
// It was already hovered, so don't send the event if it's faked
if ( mm . is_valid ( ) & & mm - > get_device ( ) = = InputEvent : : DEVICE_ID_INTERNAL ) {
send_event = false ;
}
2019-03-05 22:31:02 +01:00
}
2018-08-25 00:03:26 +02:00
}
2015-03-22 05:46:18 +01:00
2019-03-09 22:03:27 +01:00
if ( send_event ) {
co - > _input_event ( this , ev , res [ i ] . shape ) ;
}
2018-08-25 00:03:26 +02:00
}
2015-03-22 05:46:18 +01:00
}
}
}
2019-03-05 22:31:02 +01:00
if ( is_mouse ) {
List < Map < ObjectID , uint64_t > : : Element * > to_erase ;
2015-03-22 05:46:18 +01:00
2019-03-05 22:31:02 +01:00
for ( Map < ObjectID , uint64_t > : : Element * E = physics_2d_mouseover . front ( ) ; E ; E = E - > next ( ) ) {
if ( E - > get ( ) ! = frame ) {
Object * o = ObjectDB : : get_instance ( E - > key ( ) ) ;
if ( o ) {
CollisionObject2D * co = Object : : cast_to < CollisionObject2D > ( o ) ;
if ( co ) {
co - > _mouse_exit ( ) ;
}
2015-03-22 05:46:18 +01:00
}
2019-03-05 22:31:02 +01:00
to_erase . push_back ( E ) ;
2015-03-22 05:46:18 +01:00
}
}
2019-03-05 22:31:02 +01:00
while ( to_erase . size ( ) ) {
physics_2d_mouseover . erase ( to_erase . front ( ) - > get ( ) ) ;
to_erase . pop_front ( ) ;
}
2015-03-22 05:46:18 +01:00
}
}
# ifndef _3D_DISABLED
2017-03-05 16:44:50 +01:00
bool captured = false ;
2014-09-15 16:33:30 +02:00
2020-02-12 18:24:06 +01:00
if ( physics_object_capture . is_valid ( ) ) {
2020-03-26 22:49:16 +01:00
CollisionObject3D * co = Object : : cast_to < CollisionObject3D > ( ObjectDB : : get_instance ( physics_object_capture ) ) ;
2019-07-20 08:09:57 +02:00
if ( co & & camera ) {
2019-03-09 22:03:27 +01:00
_collision_object_input_event ( co , camera , ev , Vector3 ( ) , Vector3 ( ) , 0 ) ;
2017-08-24 22:58:51 +02:00
captured = true ;
if ( mb . is_valid ( ) & & mb - > get_button_index ( ) = = 1 & & ! mb - > is_pressed ( ) ) {
2020-02-12 18:24:06 +01:00
physics_object_capture = ObjectID ( ) ;
2014-09-15 16:33:30 +02:00
}
2017-08-24 22:58:51 +02:00
2014-09-15 16:33:30 +02:00
} else {
2020-02-12 18:24:06 +01:00
physics_object_capture = ObjectID ( ) ;
2014-09-15 16:33:30 +02:00
}
}
if ( captured ) {
//none
2017-03-05 16:44:50 +01:00
} else if ( pos = = last_pos ) {
2020-02-12 18:24:06 +01:00
if ( last_id . is_valid ( ) ) {
2017-09-01 22:33:39 +02:00
if ( ObjectDB : : get_instance ( last_id ) & & last_object ) {
2014-09-15 16:33:30 +02:00
//good, exists
2019-03-09 22:03:27 +01:00
_collision_object_input_event ( last_object , camera , ev , result . position , result . normal , result . shape ) ;
2017-05-20 17:38:03 +02:00
if ( last_object - > get_capture_input_on_drag ( ) & & mb . is_valid ( ) & & mb - > get_button_index ( ) = = 1 & & mb - > is_pressed ( ) ) {
2017-03-05 16:44:50 +01:00
physics_object_capture = last_id ;
2014-09-15 16:33:30 +02:00
}
}
}
} else {
if ( camera ) {
Vector3 from = camera - > project_ray_origin ( pos ) ;
Vector3 dir = camera - > project_ray_normal ( pos ) ;
2020-04-18 11:00:51 +02:00
PhysicsDirectSpaceState3D * space = PhysicsServer3D : : get_singleton ( ) - > space_get_direct_state ( find_world_3d ( ) - > get_space ( ) ) ;
2014-09-15 16:33:30 +02:00
if ( space ) {
2018-08-21 20:30:41 +02:00
bool col = space - > intersect_ray ( from , from + dir * 10000 , result , Set < RID > ( ) , 0xFFFFFFFF , true , true , true ) ;
2020-02-12 18:24:06 +01:00
ObjectID new_collider ;
2014-09-15 16:33:30 +02:00
if ( col ) {
2020-03-26 22:49:16 +01:00
CollisionObject3D * co = Object : : cast_to < CollisionObject3D > ( result . collider ) ;
2017-08-24 22:58:51 +02:00
if ( co ) {
2019-03-09 22:03:27 +01:00
_collision_object_input_event ( co , camera , ev , result . position , result . normal , result . shape ) ;
2017-08-24 22:58:51 +02: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 16:33:30 +02:00
}
}
}
2019-03-05 22:31:02 +01:00
if ( is_mouse & & new_collider ! = physics_object_over ) {
2020-02-12 18:24:06 +01:00
if ( physics_object_over . is_valid ( ) ) {
2020-03-26 22:49:16 +01:00
CollisionObject3D * co = Object : : cast_to < CollisionObject3D > ( ObjectDB : : get_instance ( physics_object_over ) ) ;
2019-03-05 22:31:02 +01:00
if ( co ) {
co - > _mouse_exit ( ) ;
}
}
2014-09-15 16:33:30 +02:00
2020-02-12 18:24:06 +01:00
if ( new_collider . is_valid ( ) ) {
2020-03-26 22:49:16 +01:00
CollisionObject3D * co = Object : : cast_to < CollisionObject3D > ( ObjectDB : : get_instance ( new_collider ) ) ;
2019-03-05 22:31:02 +01:00
if ( co ) {
co - > _mouse_enter ( ) ;
}
}
2014-09-15 16:33:30 +02:00
2019-03-05 22:31:02 +01:00
physics_object_over = new_collider ;
}
2014-09-15 16:33:30 +02:00
}
2019-03-05 22:31:02 +01:00
last_pos = pos ;
}
2014-09-15 16:33:30 +02:00
}
2014-11-02 15:31:01 +01:00
# endif
2015-03-22 05:46:18 +01:00
}
2014-09-15 16:33:30 +02:00
}
} break ;
2020-03-04 17:36:09 +01:00
case NOTIFICATION_WM_MOUSE_EXIT :
2020-06-30 01:47:18 +02:00
case NOTIFICATION_WM_WINDOW_FOCUS_OUT : {
2019-03-11 01:18:21 +01:00
_drop_physics_mouseover ( ) ;
2020-03-20 03:32:09 +01:00
if ( gui . mouse_focus & & ! gui . forced_mouse_focus ) {
2018-11-28 13:31:17 +01:00
_drop_mouse_focus ( ) ;
2018-01-05 19:39:10 +01:00
}
} break ;
2014-02-10 02:10:30 +01:00
}
}
2017-01-14 15:07:57 +01:00
RID Viewport : : get_viewport_rid ( ) const {
2016-03-09 00:00:52 +01:00
return viewport ;
2014-02-10 02:10:30 +01:00
}
2019-01-26 18:56:22 +01:00
void Viewport : : update_canvas_items ( ) {
2020-05-14 16:41:43 +02:00
if ( ! is_inside_tree ( ) ) {
2019-01-26 18:56:22 +01:00
return ;
2020-05-14 16:41:43 +02:00
}
2019-01-26 18:56:22 +01:00
_update_canvas_items ( this ) ;
}
2020-04-01 05:47:58 +02: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 16:41:43 +02: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 02:10:30 +01:00
return ;
2020-05-14 16:41:43 +02:00
}
2020-04-01 05:47:58 +02:00
2020-03-04 02:51:12 +01:00
size = p_size ;
size_allocated = p_allocated ;
2020-04-01 05:47:58 +02:00
size_2d_override = p_size_2d_override ;
2020-03-04 02:51:12 +01:00
stretch_transform = p_stretch_transform ;
to_screen_rect = p_to_screen_rect ;
if ( p_allocated ) {
2020-03-27 19:21:27 +01:00
RS : : get_singleton ( ) - > viewport_set_size ( viewport , size . width , size . height ) ;
2020-03-04 02:51:12 +01:00
} else {
2020-03-27 19:21:27 +01:00
RS : : get_singleton ( ) - > viewport_set_size ( viewport , 0 , 0 ) ;
2020-03-04 02:51:12 +01:00
}
_update_global_transform ( ) ;
2014-10-28 02:54:32 +01:00
2020-03-04 02:51:12 +01:00
update_canvas_items ( ) ;
2014-02-10 02:10:30 +01:00
2016-10-03 21:33:42 +02:00
emit_signal ( " size_changed " ) ;
2014-02-10 02:10:30 +01:00
}
2020-03-04 02:51:12 +01:00
Size2i Viewport : : _get_size ( ) const {
return size ;
}
2020-05-14 14:29:06 +02:00
2020-04-01 05:47:58 +02:00
Size2i Viewport : : _get_size_2d_override ( ) const {
return size_2d_override ;
}
2020-05-14 14:29:06 +02:00
2020-03-04 02:51:12 +01:00
bool Viewport : : _is_size_allocated ( ) const {
return size_allocated ;
}
2014-02-10 02:10:30 +01:00
Rect2 Viewport : : get_visible_rect ( ) const {
Rect2 r ;
2016-03-09 00:00:52 +01:00
2017-03-05 16:44:50 +01:00
if ( size = = Size2 ( ) ) {
2020-03-03 14:36:29 +01:00
r = Rect2 ( Point2 ( ) , DisplayServer : : get_singleton ( ) - > window_get_size ( ) ) ;
2014-02-10 02:10:30 +01:00
} else {
2017-03-05 16:44:50 +01:00
r = Rect2 ( Point2 ( ) , size ) ;
2014-02-10 02:10:30 +01:00
}
2020-04-01 05:47:58 +02:00
if ( size_2d_override ! = Size2i ( ) ) {
r . size = size_2d_override ;
2014-02-10 02:10:30 +01:00
}
return r ;
}
void Viewport : : _update_listener ( ) {
}
void Viewport : : _update_listener_2d ( ) {
2017-01-15 20:06:14 +01:00
/*
2017-08-24 22:58:51 +02:00
if ( is_inside_tree ( ) & & audio_listener & & ( ! get_parent ( ) | | ( Object : : cast_to < Control > ( get_parent ( ) ) & & Object : : cast_to < Control > ( get_parent ( ) ) - > is_visible_in_tree ( ) ) ) )
2016-03-20 03:10:04 +01:00
SpatialSound2DServer : : get_singleton ( ) - > listener_set_space ( internal_listener_2d , find_world_2d ( ) - > get_sound_space ( ) ) ;
2014-02-10 02:10:30 +01:00
else
2016-03-20 03:10:04 +01:00
SpatialSound2DServer : : get_singleton ( ) - > listener_set_space ( internal_listener_2d , RID ( ) ) ;
2017-01-15 20:06:14 +01:00
*/
2014-02-10 02:10:30 +01:00
}
void Viewport : : set_as_audio_listener ( bool p_enable ) {
2020-05-14 16:41:43 +02:00
if ( p_enable = = audio_listener ) {
2014-02-10 02:10:30 +01:00
return ;
2020-05-14 16:41:43 +02:00
}
2014-02-10 02:10:30 +01:00
2017-03-05 16:44:50 +01:00
audio_listener = p_enable ;
2014-02-10 02:10:30 +01:00
_update_listener ( ) ;
}
bool Viewport : : is_audio_listener ( ) const {
2017-03-05 16:44:50 +01:00
return audio_listener ;
2014-02-10 02:10:30 +01:00
}
void Viewport : : set_as_audio_listener_2d ( bool p_enable ) {
2020-05-14 16:41:43 +02:00
if ( p_enable = = audio_listener_2d ) {
2014-02-10 02:10:30 +01:00
return ;
2020-05-14 16:41:43 +02:00
}
2014-02-10 02:10:30 +01:00
2017-03-05 16:44:50 +01:00
audio_listener_2d = p_enable ;
2014-02-10 02:10:30 +01:00
_update_listener_2d ( ) ;
}
bool Viewport : : is_audio_listener_2d ( ) const {
2017-03-05 16:44:50 +01:00
return audio_listener_2d ;
2014-02-10 02:10:30 +01:00
}
2019-04-06 22:55:01 +02: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 19:21:27 +01:00
RenderingServer : : get_singleton ( ) - > viewport_set_canvas_transform ( viewport , find_world_2d ( ) - > get_canvas ( ) , canvas_transform_override ) ;
2019-04-06 22:55:01 +02:00
} else {
2020-03-27 19:21:27 +01:00
RenderingServer : : get_singleton ( ) - > viewport_set_canvas_transform ( viewport , find_world_2d ( ) - > get_canvas ( ) , canvas_transform ) ;
2019-04-06 22:55:01 +02:00
}
}
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 19:21:27 +01:00
RenderingServer : : get_singleton ( ) - > viewport_set_canvas_transform ( viewport , find_world_2d ( ) - > get_canvas ( ) , canvas_transform_override ) ;
2019-04-06 22:55:01 +02:00
}
}
Transform2D Viewport : : get_canvas_transform_override ( ) const {
return canvas_transform_override ;
}
2017-03-05 16:44:50 +01:00
void Viewport : : set_canvas_transform ( const Transform2D & p_transform ) {
canvas_transform = p_transform ;
2019-04-06 22:55:01 +02:00
if ( ! override_canvas_transform ) {
2020-03-27 19:21:27 +01:00
RenderingServer : : get_singleton ( ) - > viewport_set_canvas_transform ( viewport , find_world_2d ( ) - > get_canvas ( ) , canvas_transform ) ;
2019-04-06 22:55:01 +02:00
}
2014-02-10 02:10:30 +01:00
}
2017-03-05 16:44:50 +01:00
Transform2D Viewport : : get_canvas_transform ( ) const {
2014-02-10 02:10:30 +01:00
return canvas_transform ;
}
void Viewport : : _update_global_transform ( ) {
2017-01-11 04:52:51 +01:00
Transform2D sxform = stretch_transform * global_canvas_transform ;
2014-02-10 02:10:30 +01:00
2020-03-27 19:21:27 +01:00
RenderingServer : : get_singleton ( ) - > viewport_set_global_canvas_transform ( viewport , sxform ) ;
2014-02-10 02:10:30 +01:00
}
2017-03-05 16:44:50 +01:00
void Viewport : : set_global_canvas_transform ( const Transform2D & p_transform ) {
global_canvas_transform = p_transform ;
2014-02-10 02:10:30 +01:00
_update_global_transform ( ) ;
}
2017-03-05 16:44:50 +01:00
Transform2D Viewport : : get_global_canvas_transform ( ) const {
2014-02-10 02:10:30 +01:00
return global_canvas_transform ;
}
2016-03-20 03:10:04 +01:00
void Viewport : : _listener_transform_changed_notify ( ) {
}
2020-03-26 22:49:16 +01:00
void Viewport : : _listener_set ( Listener3D * p_listener ) {
2016-03-20 03:10:04 +01:00
# ifndef _3D_DISABLED
2020-05-14 16:41:43 +02:00
if ( listener = = p_listener ) {
2016-03-20 03:10:04 +01:00
return ;
2020-05-14 16:41:43 +02:00
}
2016-03-20 03:10:04 +01:00
listener = p_listener ;
_update_listener ( ) ;
_listener_transform_changed_notify ( ) ;
# endif
}
2020-03-26 22:49:16 +01:00
bool Viewport : : _listener_add ( Listener3D * p_listener ) {
2016-03-20 03:10:04 +01:00
listeners . insert ( p_listener ) ;
return listeners . size ( ) = = 1 ;
}
2020-03-26 22:49:16 +01:00
void Viewport : : _listener_remove ( Listener3D * p_listener ) {
2016-03-20 03:10:04 +01:00
listeners . erase ( p_listener ) ;
if ( listener = = p_listener ) {
2020-04-02 01:20:12 +02:00
listener = nullptr ;
2016-03-20 03:10:04 +01:00
}
}
# ifndef _3D_DISABLED
2020-03-26 22:49:16 +01:00
void Viewport : : _listener_make_next_current ( Listener3D * p_exclude ) {
2016-03-20 03:10:04 +01:00
if ( listeners . size ( ) > 0 ) {
2020-03-26 22:49:16 +01:00
for ( Set < Listener3D * > : : Element * E = listeners . front ( ) ; E ; E = E - > next ( ) ) {
2020-05-14 16:41:43 +02:00
if ( p_exclude = = E - > get ( ) ) {
2016-03-20 03:10:04 +01:00
continue ;
2020-05-14 16:41:43 +02:00
}
if ( ! E - > get ( ) - > is_inside_tree ( ) ) {
2016-03-20 03:10:04 +01:00
continue ;
2020-05-14 16:41:43 +02:00
}
if ( listener ! = nullptr ) {
2016-03-20 03:10:04 +01:00
return ;
2020-05-14 16:41:43 +02:00
}
2016-03-20 03:10:04 +01:00
E - > get ( ) - > make_current ( ) ;
}
2017-03-05 16:44:50 +01:00
} else {
2016-03-20 03:10:04 +01:00
// Attempt to reset listener to the camera position
2020-04-02 01:20:12 +02:00
if ( camera ! = nullptr ) {
2016-03-20 03:10:04 +01:00
_update_listener ( ) ;
_camera_transform_changed_notify ( ) ;
}
}
}
# endif
2014-02-10 02:10:30 +01:00
void Viewport : : _camera_transform_changed_notify ( ) {
# ifndef _3D_DISABLED
# endif
}
2020-03-26 22:49:16 +01:00
void Viewport : : _camera_set ( Camera3D * p_camera ) {
2014-02-10 02:10:30 +01:00
# ifndef _3D_DISABLED
2020-05-14 16:41:43 +02:00
if ( camera = = p_camera ) {
2014-02-10 02:10:30 +01:00
return ;
2020-05-14 16:41:43 +02:00
}
2014-02-10 02:10:30 +01:00
2019-03-10 04:59:52 +01:00
if ( camera ) {
2020-03-26 22:49:16 +01:00
camera - > notification ( Camera3D : : NOTIFICATION_LOST_CURRENT ) ;
2014-02-10 02:10:30 +01:00
}
2020-03-20 03:32:09 +01:00
2017-03-05 16:44:50 +01:00
camera = p_camera ;
2020-03-20 03:32:09 +01:00
2019-04-06 22:55:01 +02:00
if ( ! camera_override ) {
2020-05-14 16:41:43 +02:00
if ( camera ) {
2020-03-27 19:21:27 +01:00
RenderingServer : : get_singleton ( ) - > viewport_attach_camera ( viewport , camera - > get_camera ( ) ) ;
2020-05-14 16:41:43 +02:00
} else {
2020-03-27 19:21:27 +01:00
RenderingServer : : get_singleton ( ) - > viewport_attach_camera ( viewport , RID ( ) ) ;
2020-05-14 16:41:43 +02:00
}
2019-04-06 22:55:01 +02:00
}
2014-02-10 02:10:30 +01:00
2019-03-10 04:59:52 +01:00
if ( camera ) {
2020-03-26 22:49:16 +01:00
camera - > notification ( Camera3D : : NOTIFICATION_BECAME_CURRENT ) ;
2014-02-10 02:10:30 +01:00
}
_update_listener ( ) ;
_camera_transform_changed_notify ( ) ;
# endif
}
2020-03-26 22:49:16 +01:00
bool Viewport : : _camera_add ( Camera3D * p_camera ) {
2016-01-31 19:09:52 +01:00
cameras . insert ( p_camera ) ;
2017-03-05 16:44:50 +01:00
return cameras . size ( ) = = 1 ;
2016-01-31 19:09:52 +01:00
}
2020-03-26 22:49:16 +01:00
void Viewport : : _camera_remove ( Camera3D * p_camera ) {
2016-01-31 19:09:52 +01:00
cameras . erase ( p_camera ) ;
2017-03-05 16:44:50 +01:00
if ( camera = = p_camera ) {
2020-03-26 22:49:16 +01:00
camera - > notification ( Camera3D : : NOTIFICATION_LOST_CURRENT ) ;
2020-04-02 01:20:12 +02:00
camera = nullptr ;
2016-01-31 19:09:52 +01:00
}
}
2016-03-11 03:01:56 +01:00
# ifndef _3D_DISABLED
2020-03-26 22:49:16 +01:00
void Viewport : : _camera_make_next_current ( Camera3D * p_exclude ) {
for ( Set < Camera3D * > : : Element * E = cameras . front ( ) ; E ; E = E - > next ( ) ) {
2020-05-14 16:41:43 +02:00
if ( p_exclude = = E - > get ( ) ) {
2016-01-31 19:09:52 +01:00
continue ;
2020-05-14 16:41:43 +02:00
}
if ( ! E - > get ( ) - > is_inside_tree ( ) ) {
2016-01-31 19:09:52 +01:00
continue ;
2020-05-14 16:41:43 +02:00
}
if ( camera ! = nullptr ) {
2016-01-31 19:09:52 +01:00
return ;
2020-05-14 16:41:43 +02:00
}
2016-01-31 19:09:52 +01:00
E - > get ( ) - > make_current ( ) ;
}
}
2016-03-11 03:01:56 +01:00
# endif
2014-02-10 02:10:30 +01:00
2018-08-25 00:03:26 +02:00
void Viewport : : _canvas_layer_add ( CanvasLayer * p_canvas_layer ) {
canvas_layers . insert ( p_canvas_layer ) ;
}
void Viewport : : _canvas_layer_remove ( CanvasLayer * p_canvas_layer ) {
canvas_layers . erase ( p_canvas_layer ) ;
}
2014-02-10 02:10:30 +01:00
void Viewport : : set_transparent_background ( bool p_enable ) {
2017-03-05 16:44:50 +01:00
transparent_bg = p_enable ;
2020-03-27 19:21:27 +01:00
RS : : get_singleton ( ) - > viewport_set_transparent_background ( viewport , p_enable ) ;
2014-02-10 02:10:30 +01:00
}
bool Viewport : : has_transparent_background ( ) const {
return transparent_bg ;
}
2017-03-05 16:44:50 +01:00
void Viewport : : set_world_2d ( const Ref < World2D > & p_world_2d ) {
2020-05-14 16:41:43 +02:00
if ( world_2d = = p_world_2d ) {
2016-07-13 20:51:38 +02:00
return ;
2020-05-14 16:41:43 +02:00
}
2016-07-13 20:51:38 +02:00
2017-03-05 16:44:50 +01:00
if ( parent & & parent - > find_world_2d ( ) = = p_world_2d ) {
2020-04-18 11:00:51 +02:00
WARN_PRINT ( " Unable to use parent world_3d as world_2d " ) ;
2016-07-13 20:51:38 +02:00
return ;
}
if ( is_inside_tree ( ) ) {
find_world_2d ( ) - > _remove_viewport ( this ) ;
2020-03-27 19:21:27 +01:00
RenderingServer : : get_singleton ( ) - > viewport_remove_canvas ( viewport , current_canvas ) ;
2016-07-13 20:51:38 +02:00
}
2020-05-14 16:41:43 +02:00
if ( p_world_2d . is_valid ( ) ) {
2017-03-05 16:44:50 +01:00
world_2d = p_world_2d ;
2020-05-14 16:41:43 +02:00
} else {
2020-04-18 11:00:51 +02:00
WARN_PRINT ( " Invalid world_3d " ) ;
2017-03-05 16:44:50 +01:00
world_2d = Ref < World2D > ( memnew ( World2D ) ) ;
2016-07-13 20:51:38 +02:00
}
2014-02-10 02:10:30 +01:00
_update_listener_2d ( ) ;
2016-07-13 20:51:38 +02:00
if ( is_inside_tree ( ) ) {
2017-03-05 16:44:50 +01:00
current_canvas = find_world_2d ( ) - > get_canvas ( ) ;
2020-03-27 19:21:27 +01:00
RenderingServer : : get_singleton ( ) - > viewport_attach_canvas ( viewport , current_canvas ) ;
2017-03-05 16:44:50 +01:00
find_world_2d ( ) - > _register_viewport ( this , Rect2 ( ) ) ;
2014-02-10 02:10:30 +01:00
}
}
2017-03-05 16:44:50 +01:00
Ref < World2D > Viewport : : find_world_2d ( ) const {
2020-05-14 16:41:43 +02:00
if ( world_2d . is_valid ( ) ) {
2014-02-10 02:10:30 +01:00
return world_2d ;
2020-05-14 16:41:43 +02:00
} else if ( parent ) {
2014-02-10 02:10:30 +01:00
return parent - > find_world_2d ( ) ;
2020-05-14 16:41:43 +02:00
} else {
2014-02-10 02:10:30 +01:00
return Ref < World2D > ( ) ;
2020-05-14 16:41:43 +02:00
}
2014-02-10 02:10:30 +01:00
}
void Viewport : : _propagate_enter_world ( Node * p_node ) {
2017-03-05 16:44:50 +01:00
if ( p_node ! = this ) {
2020-05-14 16:41:43 +02:00
if ( ! p_node - > is_inside_tree ( ) ) { //may not have entered scene yet
2014-02-10 02:10:30 +01:00
return ;
2020-05-14 16:41:43 +02:00
}
2014-02-10 02:10:30 +01:00
2020-03-27 08:06:40 +01:00
# ifndef _3D_DISABLED
2020-03-26 22:49:16 +01:00
if ( Object : : cast_to < Node3D > ( p_node ) | | Object : : cast_to < WorldEnvironment > ( p_node ) ) {
p_node - > notification ( Node3D : : NOTIFICATION_ENTER_WORLD ) ;
2014-02-10 02:10:30 +01:00
} else {
2020-03-27 08:06:40 +01:00
# endif
2017-08-24 22:58:51 +02:00
Viewport * v = Object : : cast_to < Viewport > ( p_node ) ;
2014-02-10 02:10:30 +01:00
if ( v ) {
2020-05-14 16:41:43 +02:00
if ( v - > world_3d . is_valid ( ) | | v - > own_world_3d . is_valid ( ) ) {
2014-02-10 02:10:30 +01:00
return ;
2020-05-14 16:41:43 +02:00
}
2014-02-10 02:10:30 +01:00
}
2020-03-27 08:06:40 +01:00
# ifndef _3D_DISABLED
2014-02-10 02:10:30 +01:00
}
2020-03-27 08:06:40 +01:00
# endif
2014-02-10 02:10:30 +01:00
}
2017-03-05 16:44:50 +01:00
for ( int i = 0 ; i < p_node - > get_child_count ( ) ; i + + ) {
2014-02-10 02:10:30 +01:00
_propagate_enter_world ( p_node - > get_child ( i ) ) ;
}
}
2017-03-05 16:44:50 +01:00
void Viewport : : _propagate_viewport_notification ( Node * p_node , int p_what ) {
2016-05-11 16:46:08 +02:00
p_node - > notification ( p_what ) ;
2017-03-05 16:44:50 +01:00
for ( int i = 0 ; i < p_node - > get_child_count ( ) ; i + + ) {
2016-05-11 16:46:08 +02:00
Node * c = p_node - > get_child ( i ) ;
2020-05-14 16:41:43 +02:00
if ( Object : : cast_to < Viewport > ( c ) ) {
2016-05-11 16:46:08 +02:00
continue ;
2020-05-14 16:41:43 +02:00
}
2017-03-05 16:44:50 +01:00
_propagate_viewport_notification ( c , p_what ) ;
2016-05-11 16:46:08 +02:00
}
}
2014-02-10 02:10:30 +01:00
void Viewport : : _propagate_exit_world ( Node * p_node ) {
2017-03-05 16:44:50 +01:00
if ( p_node ! = this ) {
2020-05-14 16:41:43 +02:00
if ( ! p_node - > is_inside_tree ( ) ) { //may have exited scene already
2014-02-10 02:10:30 +01:00
return ;
2020-05-14 16:41:43 +02:00
}
2014-02-10 02:10:30 +01:00
2020-03-27 08:06:40 +01:00
# ifndef _3D_DISABLED
2020-03-26 22:49:16 +01:00
if ( Object : : cast_to < Node3D > ( p_node ) | | Object : : cast_to < WorldEnvironment > ( p_node ) ) {
p_node - > notification ( Node3D : : NOTIFICATION_EXIT_WORLD ) ;
2014-02-10 02:10:30 +01:00
} else {
2020-03-27 08:06:40 +01:00
# endif
2017-08-24 22:58:51 +02:00
Viewport * v = Object : : cast_to < Viewport > ( p_node ) ;
2014-02-10 02:10:30 +01:00
if ( v ) {
2020-05-14 16:41:43 +02:00
if ( v - > world_3d . is_valid ( ) | | v - > own_world_3d . is_valid ( ) ) {
2014-02-10 02:10:30 +01:00
return ;
2020-05-14 16:41:43 +02:00
}
2014-02-10 02:10:30 +01:00
}
2020-03-27 08:06:40 +01:00
# ifndef _3D_DISABLED
2014-02-10 02:10:30 +01:00
}
2020-03-27 08:06:40 +01:00
# endif
2014-02-10 02:10:30 +01:00
}
2017-03-05 16:44:50 +01:00
for ( int i = 0 ; i < p_node - > get_child_count ( ) ; i + + ) {
2014-02-10 02:10:30 +01:00
_propagate_exit_world ( p_node - > get_child ( i ) ) ;
}
}
2020-04-18 11:00:51 +02:00
void Viewport : : set_world_3d ( const Ref < World3D > & p_world_3d ) {
2020-05-14 16:41:43 +02:00
if ( world_3d = = p_world_3d ) {
2014-02-10 02:10:30 +01:00
return ;
2020-05-14 16:41:43 +02:00
}
2014-02-10 02:10:30 +01:00
2020-05-14 16:41:43 +02:00
if ( is_inside_tree ( ) ) {
2014-02-10 02:10:30 +01:00
_propagate_exit_world ( this ) ;
2020-05-14 16:41:43 +02:00
}
2014-02-10 02:10:30 +01:00
2020-04-18 11:00:51 +02:00
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 ) ) ;
2019-11-29 07:41:25 +01:00
}
2020-04-18 11:00:51 +02:00
world_3d = p_world_3d ;
2014-02-10 02:10:30 +01:00
2020-04-18 11:00:51 +02:00
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 ) ) ;
2019-11-29 07:41:25 +01:00
} else {
2020-04-18 11:00:51 +02:00
own_world_3d = Ref < World3D > ( memnew ( World3D ) ) ;
2019-11-29 07:41:25 +01:00
}
}
2020-05-14 16:41:43 +02:00
if ( is_inside_tree ( ) ) {
2014-02-10 02:10:30 +01:00
_propagate_enter_world ( this ) ;
2020-05-14 16:41:43 +02:00
}
2014-02-10 02:10:30 +01:00
2014-11-06 01:20:42 +01:00
if ( is_inside_tree ( ) ) {
2020-04-18 11:00:51 +02:00
RenderingServer : : get_singleton ( ) - > viewport_set_scenario ( viewport , find_world_3d ( ) - > get_scenario ( ) ) ;
2014-02-10 02:10:30 +01:00
}
_update_listener ( ) ;
}
2020-04-18 11:00:51 +02:00
Ref < World3D > Viewport : : get_world_3d ( ) const {
return world_3d ;
2014-02-10 02:10:30 +01:00
}
2017-03-05 16:44:50 +01:00
Ref < World2D > Viewport : : get_world_2d ( ) const {
2016-07-13 20:51:38 +02:00
return world_2d ;
}
2020-04-18 11:00:51 +02:00
Ref < World3D > Viewport : : find_world_3d ( ) const {
2020-05-14 16:41:43 +02:00
if ( own_world_3d . is_valid ( ) ) {
2020-04-18 11:00:51 +02:00
return own_world_3d ;
2020-05-14 16:41:43 +02:00
} else if ( world_3d . is_valid ( ) ) {
2020-04-18 11:00:51 +02:00
return world_3d ;
2020-05-14 16:41:43 +02:00
} else if ( parent ) {
2020-04-18 11:00:51 +02:00
return parent - > find_world_3d ( ) ;
2020-05-14 16:41:43 +02:00
} else {
2020-03-27 08:44:44 +01:00
return Ref < World3D > ( ) ;
2020-05-14 16:41:43 +02:00
}
2014-02-10 02:10:30 +01:00
}
2020-03-26 22:49:16 +01:00
Listener3D * Viewport : : get_listener ( ) const {
2016-03-20 03:10:04 +01:00
return listener ;
}
2020-03-26 22:49:16 +01:00
Camera3D * Viewport : : get_camera ( ) const {
2014-02-10 02:10:30 +01:00
return camera ;
}
2019-04-06 22:55:01 +02:00
void Viewport : : enable_camera_override ( bool p_enable ) {
# ifndef _3D_DISABLED
if ( p_enable = = camera_override ) {
return ;
}
if ( p_enable ) {
2020-03-27 19:21:27 +01:00
camera_override . rid = RenderingServer : : get_singleton ( ) - > camera_create ( ) ;
2019-04-06 22:55:01 +02:00
} else {
2020-03-27 19:21:27 +01:00
RenderingServer : : get_singleton ( ) - > free ( camera_override . rid ) ;
2019-04-06 22:55:01 +02:00
camera_override . rid = RID ( ) ;
}
if ( p_enable ) {
2020-03-27 19:21:27 +01:00
RenderingServer : : get_singleton ( ) - > viewport_attach_camera ( viewport , camera_override . rid ) ;
2019-04-06 22:55:01 +02:00
} else if ( camera ) {
2020-03-27 19:21:27 +01:00
RenderingServer : : get_singleton ( ) - > viewport_attach_camera ( viewport , camera - > get_camera ( ) ) ;
2019-04-06 22:55:01 +02:00
} else {
2020-03-27 19:21:27 +01:00
RenderingServer : : get_singleton ( ) - > viewport_attach_camera ( viewport , RID ( ) ) ;
2019-04-06 22:55:01 +02:00
}
# endif
}
bool Viewport : : is_camera_override_enabled ( ) const {
return camera_override ;
}
void Viewport : : set_camera_override_transform ( const Transform & p_transform ) {
if ( camera_override ) {
camera_override . transform = p_transform ;
2020-03-27 19:21:27 +01:00
RenderingServer : : get_singleton ( ) - > camera_set_transform ( camera_override . rid , p_transform ) ;
2019-04-06 22:55:01 +02:00
}
}
Transform Viewport : : get_camera_override_transform ( ) const {
if ( camera_override ) {
return camera_override . transform ;
}
return Transform ( ) ;
}
void Viewport : : set_camera_override_perspective ( float p_fovy_degrees , float p_z_near , float p_z_far ) {
if ( camera_override ) {
if ( camera_override . fov = = p_fovy_degrees & & camera_override . z_near = = p_z_near & &
2020-05-14 16:41:43 +02:00
camera_override . z_far = = p_z_far & & camera_override . projection = = CameraOverrideData : : PROJECTION_PERSPECTIVE ) {
2019-04-06 22:55:01 +02:00
return ;
2020-05-14 16:41:43 +02:00
}
2019-04-06 22:55:01 +02:00
camera_override . fov = p_fovy_degrees ;
camera_override . z_near = p_z_near ;
camera_override . z_far = p_z_far ;
camera_override . projection = CameraOverrideData : : PROJECTION_PERSPECTIVE ;
2020-03-27 19:21:27 +01:00
RenderingServer : : get_singleton ( ) - > camera_set_perspective ( camera_override . rid , camera_override . fov , camera_override . z_near , camera_override . z_far ) ;
2019-04-06 22:55:01 +02:00
}
}
void Viewport : : set_camera_override_orthogonal ( float p_size , float p_z_near , float p_z_far ) {
if ( camera_override ) {
if ( camera_override . size = = p_size & & camera_override . z_near = = p_z_near & &
2020-05-14 16:41:43 +02:00
camera_override . z_far = = p_z_far & & camera_override . projection = = CameraOverrideData : : PROJECTION_ORTHOGONAL ) {
2019-04-06 22:55:01 +02:00
return ;
2020-05-14 16:41:43 +02:00
}
2019-04-06 22:55:01 +02:00
camera_override . size = p_size ;
camera_override . z_near = p_z_near ;
camera_override . z_far = p_z_far ;
camera_override . projection = CameraOverrideData : : PROJECTION_ORTHOGONAL ;
2020-03-27 19:21:27 +01:00
RenderingServer : : get_singleton ( ) - > camera_set_orthogonal ( camera_override . rid , camera_override . size , camera_override . z_near , camera_override . z_far ) ;
2019-04-06 22:55:01 +02:00
}
}
2017-01-11 04:52:51 +01:00
Transform2D Viewport : : get_final_transform ( ) const {
2014-02-10 02:10:30 +01:00
return stretch_transform * global_canvas_transform ;
}
2019-01-26 18:56:22 +01:00
void Viewport : : _update_canvas_items ( Node * p_node ) {
if ( p_node ! = this ) {
Viewport * vp = Object : : cast_to < Viewport > ( p_node ) ;
2020-05-14 16:41:43 +02:00
if ( vp ) {
2019-01-26 18:56:22 +01:00
return ;
2020-05-14 16:41:43 +02:00
}
2019-01-26 18:56:22 +01:00
CanvasItem * ci = Object : : cast_to < CanvasItem > ( p_node ) ;
if ( ci ) {
ci - > update ( ) ;
}
}
int cc = p_node - > get_child_count ( ) ;
for ( int i = 0 ; i < cc ; i + + ) {
_update_canvas_items ( p_node - > get_child ( i ) ) ;
}
}
2016-10-05 06:26:35 +02:00
Ref < ViewportTexture > Viewport : : get_texture ( ) const {
2017-01-10 22:02:19 +01:00
return default_texture ;
2014-02-10 02:10:30 +01:00
}
2016-11-10 03:55:06 +01:00
void Viewport : : set_shadow_atlas_size ( int p_size ) {
2020-05-14 16:41:43 +02:00
if ( shadow_atlas_size = = p_size ) {
2016-12-22 14:00:15 +01:00
return ;
2020-05-14 16:41:43 +02:00
}
2015-02-21 10:35:06 +01:00
2017-03-05 16:44:50 +01:00
shadow_atlas_size = p_size ;
2020-03-27 19:21:27 +01:00
RS : : get_singleton ( ) - > viewport_set_shadow_atlas_size ( viewport , p_size ) ;
2015-02-21 10:35:06 +01:00
}
2014-04-10 05:18:27 +02:00
2017-03-05 16:44:50 +01:00
int Viewport : : get_shadow_atlas_size ( ) const {
2016-11-10 03:55:06 +01:00
return shadow_atlas_size ;
}
2016-07-13 20:51:38 +02:00
2017-03-05 16:44:50 +01: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 06:22:15 +02:00
2020-05-14 16:41:43 +02:00
if ( shadow_atlas_quadrant_subdiv [ p_quadrant ] = = p_subdiv ) {
2016-11-10 03:55:06 +01:00
return ;
2020-05-14 16:41:43 +02:00
}
2014-05-14 06:22:15 +02:00
2017-03-05 16:44:50 +01: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 15:31:38 +02:00
2020-03-27 19:21:27 +01:00
RS : : get_singleton ( ) - > viewport_set_shadow_atlas_quadrant_subdivision ( viewport , p_quadrant , subdiv [ p_subdiv ] ) ;
2014-08-14 15:31:38 +02:00
}
2020-05-14 14:29:06 +02:00
2017-03-05 16:44:50 +01: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 03:55:06 +01:00
return shadow_atlas_quadrant_subdiv [ p_quadrant ] ;
}
2017-01-11 04:52:51 +01:00
Transform2D Viewport : : _get_input_pre_xform ( ) const {
Transform2D pre_xf ;
2014-04-18 16:43:54 +02:00
2020-03-12 13:37:40 +01:00
if ( to_screen_rect . size . x ! = 0 & & to_screen_rect . size . y ! = 0 ) {
2017-06-04 00:25:13 +02:00
pre_xf . elements [ 2 ] = - to_screen_rect . position ;
2017-03-05 16:44:50 +01:00
pre_xf . scale ( size / to_screen_rect . size ) ;
2014-04-18 16:43:54 +02:00
}
return pre_xf ;
}
2017-05-20 17:38:03 +02: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 05:18:27 +02:00
2020-03-14 17:06:39 +01:00
return ev - > xformed_by ( ai ) ;
2014-04-10 05:18:27 +02:00
}
2017-03-29 17:29:38 +02:00
Vector2 Viewport : : get_mouse_position ( ) const {
2020-03-14 17:06:39 +01:00
return gui . last_mouse_pos ;
2015-05-12 13:17:09 +02:00
}
2017-03-05 16:44:50 +01:00
void Viewport : : warp_mouse ( const Vector2 & p_pos ) {
2015-02-14 23:22:06 +01:00
Vector2 gpos = ( get_final_transform ( ) . affine_inverse ( ) * _get_input_pre_xform ( ) ) . affine_inverse ( ) . xform ( p_pos ) ;
2020-04-28 15:19:37 +02:00
Input : : get_singleton ( ) - > warp_mouse_position ( gpos ) ;
2015-02-14 23:22:06 +01:00
}
2016-01-17 02:41:10 +01:00
void Viewport : : _gui_sort_roots ( ) {
2020-05-14 16:41:43 +02:00
if ( ! gui . roots_order_dirty ) {
2016-01-17 02:41:10 +01:00
return ;
2020-05-14 16:41:43 +02:00
}
2016-01-17 02:41:10 +01:00
gui . roots . sort_custom < Control : : CComparator > ( ) ;
2017-03-05 16:44:50 +01:00
gui . roots_order_dirty = false ;
2016-01-17 02:41:10 +01:00
}
void Viewport : : _gui_cancel_tooltip ( ) {
2020-04-02 01:20:12 +02:00
gui . tooltip = nullptr ;
2017-03-05 16:44:50 +01:00
gui . tooltip_timer = - 1 ;
2016-01-25 14:30:03 +01:00
if ( gui . tooltip_popup ) {
gui . tooltip_popup - > queue_delete ( ) ;
2020-04-02 01:20:12 +02:00
gui . tooltip_popup = nullptr ;
gui . tooltip_label = nullptr ;
2016-01-25 14:30:03 +01:00
}
2016-01-17 02:41:10 +01:00
}
2018-07-20 23:14:33 +02:00
String Viewport : : _gui_get_tooltip ( Control * p_control , const Vector2 & p_pos , Control * * r_which ) {
2018-06-07 17:46:14 +02:00
Vector2 pos = p_pos ;
String tooltip ;
while ( p_control ) {
tooltip = p_control - > get_tooltip ( pos ) ;
2018-07-20 23:14:33 +02:00
if ( r_which ) {
* r_which = p_control ;
}
2020-05-14 16:41:43 +02:00
if ( tooltip ! = String ( ) ) {
2018-06-07 17:46:14 +02:00
break ;
2020-05-14 16:41:43 +02:00
}
2018-06-07 17:46:14 +02:00
pos = p_control - > get_transform ( ) . xform ( pos ) ;
2020-05-14 16:41:43 +02:00
if ( p_control - > data . mouse_filter = = Control : : MOUSE_FILTER_STOP ) {
2018-06-07 17:46:14 +02:00
break ;
2020-05-14 16:41:43 +02:00
}
if ( p_control - > is_set_as_toplevel ( ) ) {
2018-06-07 17:46:14 +02:00
break ;
2020-05-14 16:41:43 +02:00
}
2018-06-07 17:46:14 +02:00
p_control = p_control - > get_parent_control ( ) ;
}
return tooltip ;
}
2016-01-17 02:41:10 +01:00
void Viewport : : _gui_show_tooltip ( ) {
if ( ! gui . tooltip ) {
return ;
}
2020-04-02 01:20:12 +02:00
Control * which = nullptr ;
2018-07-20 23:14:33 +02:00
String tooltip = _gui_get_tooltip ( gui . tooltip , gui . tooltip - > get_global_transform ( ) . xform_inv ( gui . tooltip_pos ) , & which ) ;
2019-07-09 16:01:38 +02:00
tooltip = tooltip . strip_edges ( ) ;
2020-05-14 16:41:43 +02:00
if ( tooltip . length ( ) = = 0 ) {
2016-01-17 02:41:10 +01:00
return ; // bye
2020-05-14 16:41:43 +02:00
}
2016-01-17 02:41:10 +01:00
2016-01-25 14:30:03 +01:00
if ( gui . tooltip_popup ) {
memdelete ( gui . tooltip_popup ) ;
2020-04-02 01:20:12 +02:00
gui . tooltip_popup = nullptr ;
gui . tooltip_label = nullptr ;
2016-01-25 14:30:03 +01:00
}
2016-01-17 02:41:10 +01:00
2018-07-20 23:14:33 +02:00
if ( ! which ) {
2017-08-21 03:48:03 +02:00
return ;
}
2019-06-20 16:59:48 +02:00
Control * rp = which ;
2016-01-25 14:30:03 +01:00
2020-03-20 21:51:53 +01:00
Control * base_tooltip = which - > make_custom_tooltip ( tooltip ) ;
2018-07-20 23:14:33 +02:00
2020-03-20 21:51:53 +01:00
if ( ! base_tooltip ) {
2018-07-20 23:14:33 +02:00
gui . tooltip_label = memnew ( TooltipLabel ) ;
2019-07-09 16:01:38 +02:00
gui . tooltip_label - > set_text ( tooltip ) ;
2020-03-20 21:51:53 +01:00
base_tooltip = gui . tooltip_label ;
2018-07-20 23:14:33 +02:00
}
2016-01-25 14:30:03 +01:00
2020-03-20 21:51:53 +01:00
base_tooltip - > set_anchors_and_margins_preset ( Control : : PRESET_WIDE ) ;
TooltipPanel * panel = memnew ( TooltipPanel ) ;
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 ;
2016-01-25 14:30:03 +01:00
rp - > add_child ( gui . tooltip_popup ) ;
2020-03-20 21:51:53 +01:00
//if (gui.tooltip) // Avoids crash when rapidly switching controls.
// gui.tooltip_popup->set_scale(gui.tooltip->get_global_transform().get_scale());
2016-01-17 02:41:10 +01:00
2019-03-02 12:11:42 +01:00
Point2 tooltip_offset = ProjectSettings : : get_singleton ( ) - > get ( " display/mouse_cursor/tooltip_position_offset " ) ;
2020-03-20 21:51:53 +01:00
Rect2 r ( gui . tooltip_pos + tooltip_offset , gui . tooltip_popup - > get_contents_minimum_size ( ) ) ;
Rect2i vr = gui . tooltip_popup - > get_parent_visible_window ( ) - > get_usable_parent_rect ( ) ;
2020-05-14 16:41:43 +02:00
if ( r . size . x + r . position . x > vr . size . x + vr . position . x ) {
2020-03-20 21:51:53 +01:00
r . position . x = vr . position . x + vr . size . x - r . size . x ;
2020-05-14 16:41:43 +02:00
} else if ( r . position . x < vr . position . x ) {
2020-03-20 21:51:53 +01:00
r . position . x = vr . position . x ;
2020-05-14 16:41:43 +02:00
}
2020-03-20 21:51:53 +01:00
2020-05-14 16:41:43 +02:00
if ( r . size . y + r . position . y > vr . size . y + vr . position . y ) {
2020-03-20 21:51:53 +01:00
r . position . y = vr . position . y + vr . size . y - r . size . y ;
2020-05-14 16:41:43 +02:00
} else if ( r . position . y < vr . position . y ) {
2020-03-20 21:51:53 +01:00
r . position . y = vr . position . y ;
2020-05-14 16:41:43 +02:00
}
2020-03-20 21:51:53 +01:00
gui . tooltip_popup - > set_position ( r . position ) ;
2016-01-17 02:41:10 +01:00
gui . tooltip_popup - > set_size ( r . size ) ;
gui . tooltip_popup - > show ( ) ;
2020-03-20 21:51:53 +01:00
gui . tooltip_popup - > child_controls_changed ( ) ;
2016-01-17 02:41:10 +01:00
}
2017-05-20 17:38:03 +02:00
void Viewport : : _gui_call_input ( Control * p_control , const Ref < InputEvent > & p_input ) {
2017-01-14 12:26:56 +01:00
//_block();
2016-01-17 02:41:10 +01:00
2017-05-20 17:38:03 +02:00
Ref < InputEvent > ev = p_input ;
2016-06-27 14:59:43 +02:00
2016-06-20 22:16:52 +02:00
//mouse wheel events can't be stopped
2017-05-20 17:38:03 +02:00
Ref < InputEventMouseButton > mb = p_input ;
bool cant_stop_me_now = ( mb . is_valid ( ) & &
( mb - > get_button_index ( ) = = BUTTON_WHEEL_DOWN | |
mb - > get_button_index ( ) = = BUTTON_WHEEL_UP | |
mb - > get_button_index ( ) = = BUTTON_WHEEL_LEFT | |
mb - > get_button_index ( ) = = BUTTON_WHEEL_RIGHT ) ) ;
2018-05-18 18:47:39 +02:00
Ref < InputEventPanGesture > pn = p_input ;
cant_stop_me_now = pn . is_valid ( ) | | cant_stop_me_now ;
2017-05-20 17:38:03 +02:00
2020-04-02 01:20:12 +02:00
bool ismouse = ev . is_valid ( ) | | Object : : cast_to < InputEventMouseMotion > ( * p_input ) ! = nullptr ;
2016-06-20 22:16:52 +02:00
2017-03-05 16:44:50 +01:00
CanvasItem * ci = p_control ;
while ( ci ) {
2017-08-24 22:58:51 +02:00
Control * control = Object : : cast_to < Control > ( ci ) ;
2016-06-07 07:39:40 +02:00
if ( control ) {
2018-11-16 17:46:42 +01:00
if ( control - > data . mouse_filter ! = Control : : MOUSE_FILTER_IGNORE ) {
control - > emit_signal ( SceneStringNames : : get_singleton ( ) - > gui_input , ev ) ; //signal should be first, so it's possible to override an event (and then accept it)
}
2020-05-14 16:41:43 +02:00
if ( gui . key_event_accepted ) {
2016-06-07 07:39:40 +02:00
break ;
2020-05-14 16:41:43 +02:00
}
if ( ! control - > is_inside_tree ( ) ) {
2016-06-07 07:39:40 +02:00
break ;
2020-05-14 16:41:43 +02:00
}
2018-11-16 17:46:42 +01:00
if ( control - > data . mouse_filter ! = Control : : MOUSE_FILTER_IGNORE ) {
2020-07-27 20:15:37 +02:00
// Call both script and native methods.
Callable : : CallError error ;
Variant event = ev ;
const Variant * args [ 1 ] = { & event } ;
if ( control - > get_script_instance ( ) ) {
control - > get_script_instance ( ) - > call ( SceneStringNames : : get_singleton ( ) - > _gui_input , args , 1 , error ) ;
}
MethodBind * method = ClassDB : : get_method ( control - > get_class_name ( ) , SceneStringNames : : get_singleton ( ) - > _gui_input ) ;
if ( method ) {
method - > call ( control , args , 1 , error ) ;
}
2018-11-16 17:46:42 +01:00
}
2018-06-07 17:46:14 +02:00
2020-05-14 16:41:43 +02:00
if ( ! control - > is_inside_tree ( ) | | control - > is_set_as_toplevel ( ) ) {
2016-06-07 07:39:40 +02:00
break ;
2020-05-14 16:41:43 +02:00
}
if ( gui . key_event_accepted ) {
2016-06-07 07:39:40 +02:00
break ;
2020-05-14 16:41:43 +02:00
}
if ( ! cant_stop_me_now & & control - > data . mouse_filter = = Control : : MOUSE_FILTER_STOP & & ismouse ) {
2016-06-07 07:39:40 +02:00
break ;
2020-05-14 16:41:43 +02:00
}
2016-06-07 07:39:40 +02:00
}
2020-05-14 16:41:43 +02:00
if ( ci - > is_set_as_toplevel ( ) ) {
2016-06-07 07:39:40 +02:00
break ;
2020-05-14 16:41:43 +02:00
}
2016-06-07 07:39:40 +02:00
2017-05-20 17:38:03 +02:00
ev = ev - > xformed_by ( ci - > get_transform ( ) ) ; //transform event upwards
2017-03-05 16:44:50 +01:00
ci = ci - > get_parent_item ( ) ;
2016-01-17 02:41:10 +01:00
}
//_unblock();
}
2019-01-18 21:53:36 +01:00
void Viewport : : _gui_call_notification ( Control * p_control , int p_what ) {
CanvasItem * ci = p_control ;
while ( ci ) {
Control * control = Object : : cast_to < Control > ( ci ) ;
if ( control ) {
if ( control - > data . mouse_filter ! = Control : : MOUSE_FILTER_IGNORE ) {
control - > notification ( p_what ) ;
}
2020-05-14 16:41:43 +02:00
if ( ! control - > is_inside_tree ( ) ) {
2019-01-18 21:53:36 +01:00
break ;
2020-05-14 16:41:43 +02:00
}
2019-01-18 21:53:36 +01:00
2020-05-14 16:41:43 +02:00
if ( ! control - > is_inside_tree ( ) | | control - > is_set_as_toplevel ( ) ) {
2019-01-18 21:53:36 +01:00
break ;
2020-05-14 16:41:43 +02:00
}
if ( control - > data . mouse_filter = = Control : : MOUSE_FILTER_STOP ) {
2019-01-18 21:53:36 +01:00
break ;
2020-05-14 16:41:43 +02:00
}
2019-01-18 21:53:36 +01:00
}
2020-05-14 16:41:43 +02:00
if ( ci - > is_set_as_toplevel ( ) ) {
2019-01-18 21:53:36 +01:00
break ;
2020-05-14 16:41:43 +02:00
}
2019-01-18 21:53:36 +01:00
ci = ci - > get_parent_item ( ) ;
}
//_unblock();
}
2020-05-14 14:29:06 +02:00
2017-03-05 16:44:50 +01:00
Control * Viewport : : _gui_find_control ( const Point2 & p_global ) {
2020-03-14 17:06:39 +01:00
//aca va subwindows
2016-01-25 14:39:55 +01:00
_gui_sort_roots ( ) ;
2017-03-05 16:44:50 +01:00
for ( List < Control * > : : Element * E = gui . roots . back ( ) ; E ; E = E - > prev ( ) ) {
2016-01-17 02:41:10 +01:00
Control * sw = E - > get ( ) ;
2020-05-14 16:41:43 +02:00
if ( ! sw - > is_visible_in_tree ( ) ) {
2016-01-17 02:41:10 +01:00
continue ;
2020-05-14 16:41:43 +02:00
}
2016-01-17 02:41:10 +01:00
2017-01-11 04:52:51 +01:00
Transform2D xform ;
2016-01-17 02:41:10 +01:00
CanvasItem * pci = sw - > get_parent_item ( ) ;
2020-05-14 16:41:43 +02:00
if ( pci ) {
2017-03-05 16:44:50 +01:00
xform = pci - > get_global_transform_with_canvas ( ) ;
2020-05-14 16:41:43 +02:00
} else {
2017-03-05 16:44:50 +01:00
xform = sw - > get_canvas_transform ( ) ;
2020-05-14 16:41:43 +02:00
}
2016-01-17 02:41:10 +01:00
2017-03-05 16:44:50 +01:00
Control * ret = _gui_find_control_at_pos ( sw , p_global , xform , gui . focus_inv_xform ) ;
2020-05-14 16:41:43 +02:00
if ( ret ) {
2016-01-17 02:41:10 +01:00
return ret ;
2020-05-14 16:41:43 +02:00
}
2016-01-17 02:41:10 +01:00
}
2020-04-02 01:20:12 +02:00
return nullptr ;
2016-01-17 02:41:10 +01:00
}
2017-03-05 16:44:50 +01: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 16:41:43 +02:00
if ( Object : : cast_to < Viewport > ( p_node ) ) {
2020-04-02 01:20:12 +02:00
return nullptr ;
2020-05-14 16:41:43 +02:00
}
2016-01-17 02:41:10 +01:00
2017-01-13 14:45:50 +01:00
if ( ! p_node - > is_visible ( ) ) {
2016-01-17 02:41:10 +01:00
//return _find_next_visible_control_at_pos(p_node,p_global,r_inv_xform);
2020-04-02 01:20:12 +02:00
return nullptr ; //canvas item hidden, discard
2016-01-17 02:41:10 +01:00
}
2017-01-11 04:52:51 +01:00
Transform2D matrix = p_xform * p_node - > get_transform ( ) ;
2016-10-08 12:33:10 +02:00
// matrix.basis_determinant() == 0.0f implies that node does not exist on scene
2020-05-14 16:41:43 +02:00
if ( matrix . basis_determinant ( ) = = 0.0f ) {
2020-04-02 01:20:12 +02:00
return nullptr ;
2020-05-14 16:41:43 +02:00
}
2016-01-17 02:41:10 +01:00
2018-08-24 09:35:07 +02:00
Control * c = Object : : cast_to < Control > ( p_node ) ;
2016-01-17 02:41:10 +01:00
if ( ! c | | ! c - > clips_input ( ) | | c - > has_point ( matrix . affine_inverse ( ) . xform ( p_global ) ) ) {
2017-03-05 16:44:50 +01:00
for ( int i = p_node - > get_child_count ( ) - 1 ; i > = 0 ; i - - ) {
2017-08-24 22:58:51 +02:00
CanvasItem * ci = Object : : cast_to < CanvasItem > ( p_node - > get_child ( i ) ) ;
2020-05-14 16:41:43 +02:00
if ( ! ci | | ci - > is_set_as_toplevel ( ) ) {
2016-01-17 02:41:10 +01:00
continue ;
2020-05-14 16:41:43 +02:00
}
2016-01-17 02:41:10 +01:00
2017-03-05 16:44:50 +01:00
Control * ret = _gui_find_control_at_pos ( ci , p_global , matrix , r_inv_xform ) ;
2020-05-14 16:41:43 +02:00
if ( ret ) {
2016-01-17 02:41:10 +01:00
return ret ;
2020-05-14 16:41:43 +02:00
}
2016-01-17 02:41:10 +01:00
}
}
2020-05-14 16:41:43 +02:00
if ( ! c ) {
2020-04-02 01:20:12 +02:00
return nullptr ;
2020-05-14 16:41:43 +02:00
}
2016-01-17 02:41:10 +01:00
matrix . affine_invert ( ) ;
//conditions for considering this as a valid control for return
2017-03-05 16:44:50 +01:00
if ( c - > data . mouse_filter ! = Control : : MOUSE_FILTER_IGNORE & & c - > has_point ( matrix . xform ( p_global ) ) & & ( ! gui . drag_preview | | ( c ! = gui . drag_preview & & ! gui . drag_preview - > is_a_parent_of ( c ) ) ) ) {
r_inv_xform = matrix ;
2016-01-17 02:41:10 +01:00
return c ;
2020-05-14 16:41:43 +02:00
} else {
2020-04-02 01:20:12 +02:00
return nullptr ;
2020-05-14 16:41:43 +02:00
}
2016-01-17 02:41:10 +01:00
}
2017-03-05 16:44:50 +01:00
bool Viewport : : _gui_drop ( Control * p_at_control , Point2 p_at_pos , bool p_just_check ) {
2017-01-24 03:12:08 +01:00
{ //attempt grab, try parent controls too
2017-03-05 16:44:50 +01:00
CanvasItem * ci = p_at_control ;
while ( ci ) {
2017-08-24 22:58:51 +02:00
Control * control = Object : : cast_to < Control > ( ci ) ;
2017-01-24 03:12:08 +01:00
if ( control ) {
2017-03-05 16:44:50 +01:00
if ( control - > can_drop_data ( p_at_pos , gui . drag_data ) ) {
2017-01-24 03:12:08 +01:00
if ( ! p_just_check ) {
2017-03-05 16:44:50 +01:00
control - > drop_data ( p_at_pos , gui . drag_data ) ;
2017-01-24 03:12:08 +01:00
}
return true ;
}
2020-05-14 16:41:43 +02:00
if ( control - > data . mouse_filter = = Control : : MOUSE_FILTER_STOP ) {
2017-01-24 03:12:08 +01:00
break ;
2020-05-14 16:41:43 +02:00
}
2017-01-24 03:12:08 +01:00
}
p_at_pos = ci - > get_transform ( ) . xform ( p_at_pos ) ;
2020-05-14 16:41:43 +02:00
if ( ci - > is_set_as_toplevel ( ) ) {
2017-01-24 03:12:08 +01:00
break ;
2020-05-14 16:41:43 +02:00
}
2017-01-24 03:12:08 +01:00
2017-03-05 16:44:50 +01:00
ci = ci - > get_parent_item ( ) ;
2017-01-24 03:12:08 +01:00
}
}
return false ;
}
2017-05-20 17:38:03 +02:00
void Viewport : : _gui_input_event ( Ref < InputEvent > p_event ) {
2019-11-07 10:37:44 +01:00
ERR_FAIL_COND ( p_event . is_null ( ) ) ;
2019-06-22 14:52:51 +02:00
2016-01-17 02:41:10 +01:00
//?
2017-01-14 12:26:56 +01:00
/*
if ( ! is_visible ( ) ) {
return ; //simple and plain
}
*/
2016-01-17 02:41:10 +01:00
2017-05-20 17:38:03 +02:00
Ref < InputEventMouseButton > mb = p_event ;
2016-01-17 02:41:10 +01:00
2017-05-20 17:38:03 +02:00
if ( mb . is_valid ( ) ) {
gui . key_event_accepted = false ;
2016-01-17 02:41:10 +01:00
2017-06-03 10:54:24 +02:00
Point2 mpos = mb - > get_position ( ) ;
2017-05-20 17:38:03 +02:00
if ( mb - > is_pressed ( ) ) {
Size2 pos = mpos ;
2018-11-28 13:31:17 +01:00
if ( gui . mouse_focus_mask ) {
//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 17:38:03 +02:00
} else {
2017-11-22 09:43:40 +01:00
bool is_handled = false ;
if ( is_handled ) {
2018-11-15 17:54:26 +01:00
set_input_as_handled ( ) ;
2017-11-22 09:43:40 +01:00
return ;
}
2017-05-20 17:38:03 +02:00
//Matrix32 parent_xform;
2016-01-17 02:41:10 +01:00
2017-05-20 17:38:03 +02:00
/*
if ( data . parent_canvas_item )
parent_xform = data . parent_canvas_item - > get_global_transform ( ) ;
*/
2016-01-17 02:41:10 +01:00
2017-05-20 17:38:03 +02:00
gui . mouse_focus = _gui_find_control ( pos ) ;
2018-10-26 21:23:47 +02:00
gui . last_mouse_focus = gui . mouse_focus ;
2016-01-17 02:41:10 +01:00
2017-05-20 17:38:03 +02:00
if ( ! gui . mouse_focus ) {
2019-03-04 14:26:48 +01:00
gui . mouse_focus_mask = 0 ;
2017-05-20 17:38:03 +02:00
return ;
}
2016-01-17 02:41:10 +01:00
2019-03-04 14:26:48 +01:00
gui . mouse_focus_mask = 1 < < ( mb - > get_button_index ( ) - 1 ) ;
2017-05-20 17:38:03 +02:00
if ( mb - > get_button_index ( ) = = BUTTON_LEFT ) {
gui . drag_accum = Vector2 ( ) ;
gui . drag_attempted = false ;
2016-01-17 02:41:10 +01:00
}
2017-05-20 17:38:03 +02:00
}
mb = mb - > xformed_by ( Transform2D ( ) ) ; // make a copy of the event
2017-06-03 10:54:24 +02:00
mb - > set_global_position ( pos ) ;
2016-01-17 02:41:10 +01:00
2017-05-20 17:38:03 +02:00
pos = gui . focus_inv_xform . xform ( pos ) ;
2016-01-17 02:41:10 +01:00
2017-06-03 10:54:24 +02:00
mb - > set_position ( pos ) ;
2016-01-17 02:41:10 +01:00
# ifdef DEBUG_ENABLED
2020-02-27 03:30:20 +01:00
if ( EngineDebugger : : get_singleton ( ) & & gui . mouse_focus ) {
2017-05-20 17:38:03 +02:00
Array arr ;
arr . push_back ( gui . mouse_focus - > get_path ( ) ) ;
arr . push_back ( gui . mouse_focus - > get_class ( ) ) ;
2020-02-27 03:30:20 +01:00
EngineDebugger : : get_singleton ( ) - > send_message ( " scene:click_ctrl " , arr ) ;
2017-05-20 17:38:03 +02:00
}
2016-01-17 02:41:10 +01:00
# endif
2017-05-20 17:38:03 +02:00
if ( mb - > get_button_index ( ) = = BUTTON_LEFT ) { //assign focus
CanvasItem * ci = gui . mouse_focus ;
while ( ci ) {
2017-08-24 22:58:51 +02:00
Control * control = Object : : cast_to < Control > ( ci ) ;
2017-05-20 17:38:03 +02:00
if ( control ) {
if ( control - > get_focus_mode ( ) ! = Control : : FOCUS_NONE ) {
if ( control ! = gui . key_focus ) {
control - > grab_focus ( ) ;
2017-01-21 23:00:25 +01:00
}
2017-05-20 17:38:03 +02:00
break ;
2017-01-21 23:00:25 +01:00
}
2020-05-14 16:41:43 +02:00
if ( control - > data . mouse_filter = = Control : : MOUSE_FILTER_STOP ) {
2017-01-21 23:00:25 +01:00
break ;
2020-05-14 16:41:43 +02:00
}
2017-01-21 23:00:25 +01:00
}
2016-01-17 02:41:10 +01:00
2020-05-14 16:41:43 +02:00
if ( ci - > is_set_as_toplevel ( ) ) {
2017-05-20 17:38:03 +02:00
break ;
2020-05-14 16:41:43 +02:00
}
2016-01-17 02:41:10 +01:00
2017-05-20 17:38:03 +02:00
ci = ci - > get_parent_item ( ) ;
}
}
2016-01-17 02:41:10 +01:00
2018-12-01 14:25:43 +01:00
if ( gui . mouse_focus & & gui . mouse_focus - > can_process ( ) ) {
2017-05-20 17:38:03 +02:00
_gui_call_input ( gui . mouse_focus , mb ) ;
}
2016-07-01 15:34:38 +02:00
2018-11-15 17:54:26 +01:00
set_input_as_handled ( ) ;
2016-07-01 15:34:38 +02:00
2017-05-20 17:38:03 +02:00
if ( gui . drag_data . get_type ( ) ! = Variant : : NIL & & mb - > get_button_index ( ) = = BUTTON_LEFT ) {
//alternate drop use (when using force_drag(), as proposed by #5342
if ( gui . mouse_focus ) {
_gui_drop ( gui . mouse_focus , pos , false ) ;
2016-07-01 15:34:38 +02:00
}
2017-05-20 17:38:03 +02:00
gui . drag_data = Variant ( ) ;
2018-08-24 15:29:27 +02:00
gui . dragging = false ;
2016-01-17 02:41:10 +01:00
2017-05-20 17:38:03 +02:00
if ( gui . drag_preview ) {
memdelete ( gui . drag_preview ) ;
2020-04-02 01:20:12 +02:00
gui . drag_preview = nullptr ;
2017-05-20 17:38:03 +02:00
}
_propagate_viewport_notification ( this , NOTIFICATION_DRAG_END ) ;
//change mouse accordingly
}
2016-01-17 02:41:10 +01:00
2017-05-20 17:38:03 +02:00
_gui_cancel_tooltip ( ) ;
//gui.tooltip_popup->hide();
2016-01-17 02:41:10 +01:00
2017-05-20 17:38:03 +02:00
} else {
if ( gui . drag_data . get_type ( ) ! = Variant : : NIL & & mb - > get_button_index ( ) = = BUTTON_LEFT ) {
2020-03-25 00:15:35 +01:00
if ( gui . drag_mouse_over ) {
_gui_drop ( gui . drag_mouse_over , gui . drag_mouse_over_pos , false ) ;
2016-07-01 15:34:38 +02:00
}
2017-05-20 17:38:03 +02:00
if ( gui . drag_preview & & mb - > get_button_index ( ) = = BUTTON_LEFT ) {
memdelete ( gui . drag_preview ) ;
2020-04-02 01:20:12 +02:00
gui . drag_preview = nullptr ;
2016-01-17 02:41:10 +01:00
}
2017-05-20 17:38:03 +02:00
gui . drag_data = Variant ( ) ;
2018-08-24 15:29:27 +02:00
gui . dragging = false ;
2020-03-25 00:15:35 +01:00
gui . drag_mouse_over = nullptr ;
2017-05-20 17:38:03 +02:00
_propagate_viewport_notification ( this , NOTIFICATION_DRAG_END ) ;
//change mouse accordingly
}
2016-01-17 02:41:10 +01:00
2018-11-28 13:31:17 +01:00
gui . mouse_focus_mask & = ~ ( 1 < < ( mb - > get_button_index ( ) - 1 ) ) ; //remove from mask
2017-05-20 17:38:03 +02:00
if ( ! gui . mouse_focus ) {
//release event is only sent if a mouse focus (previously pressed button) exists
return ;
}
2016-01-17 02:41:10 +01:00
2017-05-20 17:38:03 +02:00
Size2 pos = mpos ;
2016-01-17 02:41:10 +01:00
2017-05-20 17:38:03 +02:00
mb = mb - > xformed_by ( Transform2D ( ) ) ; //make a copy
2017-06-03 10:54:24 +02:00
mb - > set_global_position ( pos ) ;
2017-05-20 17:38:03 +02:00
pos = gui . focus_inv_xform . xform ( pos ) ;
2017-06-03 10:54:24 +02:00
mb - > set_position ( pos ) ;
2016-01-17 02:41:10 +01:00
2017-12-21 15:03:17 +01:00
Control * mouse_focus = gui . mouse_focus ;
2016-01-17 02:41:10 +01:00
2017-12-21 15:03:17 +01: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 13:31:17 +01:00
if ( gui . mouse_focus_mask = = 0 ) {
2020-04-02 01:20:12 +02:00
gui . mouse_focus = nullptr ;
2020-03-20 03:32:09 +01:00
gui . forced_mouse_focus = false ;
2017-05-20 17:38:03 +02:00
}
2016-01-17 02:41:10 +01:00
2018-12-03 01:38:54 +01:00
if ( mouse_focus & & mouse_focus - > can_process ( ) ) {
2017-12-21 15:03:17 +01:00
_gui_call_input ( mouse_focus , mb ) ;
}
2017-05-20 17:38:03 +02:00
/*if (gui.drag_data.get_type()!=Variant::NIL && mb->get_button_index()==BUTTON_LEFT) {
_propagate_viewport_notification ( this , NOTIFICATION_DRAG_END ) ;
gui . drag_data = Variant ( ) ; //always clear
} */
2016-01-17 02:41:10 +01:00
2018-11-15 17:54:26 +01:00
set_input_as_handled ( ) ;
2017-05-20 17:38:03 +02:00
}
}
2016-01-17 02:41:10 +01:00
2017-05-20 17:38:03 +02:00
Ref < InputEventMouseMotion > mm = p_event ;
2016-01-17 02:41:10 +01:00
2017-05-20 17:38:03 +02:00
if ( mm . is_valid ( ) ) {
gui . key_event_accepted = false ;
2017-06-03 10:54:24 +02:00
Point2 mpos = mm - > get_position ( ) ;
2017-01-24 03:12:08 +01:00
2017-05-20 17:38:03 +02:00
gui . last_mouse_pos = mpos ;
2017-01-24 03:12:08 +01:00
2020-04-02 01:20:12 +02:00
Control * over = nullptr ;
2017-01-24 03:12:08 +01:00
2017-05-20 17:38:03 +02:00
// D&D
if ( ! gui . drag_attempted & & gui . mouse_focus & & mm - > get_button_mask ( ) & BUTTON_MASK_LEFT ) {
gui . drag_accum + = mm - > get_relative ( ) ;
float len = gui . drag_accum . length ( ) ;
if ( len > 10 ) {
{ //attempt grab, try parent controls too
CanvasItem * ci = gui . mouse_focus ;
while ( ci ) {
2017-08-24 22:58:51 +02:00
Control * control = Object : : cast_to < Control > ( ci ) ;
2017-05-20 17:38:03 +02:00
if ( control ) {
2018-08-24 15:29:27 +02:00
gui . dragging = true ;
2017-05-20 17:38:03 +02: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-02 01:20:12 +02:00
gui . mouse_focus = nullptr ;
2020-03-20 03:32:09 +01:00
gui . forced_mouse_focus = false ;
2018-11-28 13:31:17 +01:00
gui . mouse_focus_mask = 0 ;
2018-11-19 22:37:39 +01:00
break ;
2018-08-24 15:29:27 +02:00
} else {
2020-04-02 01:20:12 +02:00
if ( gui . drag_preview ! = nullptr ) {
2018-11-19 22:37:39 +01:00
ERR_PRINT ( " Don't set a drag preview and return null data. Preview was deleted and drag request ignored. " ) ;
memdelete ( gui . drag_preview ) ;
2020-04-02 01:20:12 +02:00
gui . drag_preview = nullptr ;
2018-11-19 22:37:39 +01:00
}
2018-08-24 15:29:27 +02:00
gui . dragging = false ;
2017-01-24 03:12:08 +01:00
}
2020-05-14 16:41:43 +02:00
if ( control - > data . mouse_filter = = Control : : MOUSE_FILTER_STOP ) {
2017-01-24 03:12:08 +01:00
break ;
2020-05-14 16:41:43 +02:00
}
2017-01-24 03:12:08 +01:00
}
2020-05-14 16:41:43 +02:00
if ( ci - > is_set_as_toplevel ( ) ) {
2017-05-20 17:38:03 +02:00
break ;
2020-05-14 16:41:43 +02:00
}
2017-01-24 03:12:08 +01:00
2017-05-20 17:38:03 +02:00
ci = ci - > get_parent_item ( ) ;
2016-05-11 16:46:08 +02:00
}
2016-01-17 02:41:10 +01:00
}
2017-05-20 17:38:03 +02:00
gui . drag_attempted = true ;
if ( gui . drag_data . get_type ( ) ! = Variant : : NIL ) {
_propagate_viewport_notification ( this , NOTIFICATION_DRAG_BEGIN ) ;
}
2016-01-17 02:41:10 +01:00
}
2017-05-20 17:38:03 +02:00
}
2016-01-17 02:41:10 +01:00
2017-05-20 17:38:03 +02:00
if ( gui . mouse_focus ) {
over = gui . mouse_focus ;
//recompute focus_inv_xform again here
2016-01-17 02:41:10 +01:00
2017-05-20 17:38:03 +02:00
} else {
over = _gui_find_control ( mpos ) ;
}
2016-01-17 02:41:10 +01:00
2017-05-20 17:38:03 +02:00
if ( over ! = gui . mouse_over ) {
2019-01-18 21:53:36 +01:00
if ( gui . mouse_over ) {
_gui_call_notification ( gui . mouse_over , Control : : NOTIFICATION_MOUSE_EXIT ) ;
}
2016-05-21 15:29:25 +02:00
2017-05-20 17:38:03 +02:00
_gui_cancel_tooltip ( ) ;
2016-01-17 02:41:10 +01:00
2019-01-18 21:53:36 +01:00
if ( over ) {
_gui_call_notification ( over , Control : : NOTIFICATION_MOUSE_ENTER ) ;
}
2017-05-20 17:38:03 +02:00
}
2016-01-17 02:41:10 +01:00
2017-05-20 17:38:03 +02:00
gui . mouse_over = over ;
2016-01-17 02:41:10 +01:00
2020-04-28 15:19:37 +02:00
DisplayServer : : CursorShape ds_cursor_shape = ( DisplayServer : : CursorShape ) Input : : get_singleton ( ) - > get_default_cursor_shape ( ) ;
2016-01-17 02:41:10 +01:00
2020-03-25 00:15:35 +01:00
if ( over ) {
Transform2D localizer = over - > get_global_transform_with_canvas ( ) . affine_inverse ( ) ;
Size2 pos = localizer . xform ( mpos ) ;
Vector2 speed = localizer . basis_xform ( mm - > get_speed ( ) ) ;
Vector2 rel = localizer . basis_xform ( mm - > get_relative ( ) ) ;
2016-01-17 02:41:10 +01:00
2020-03-25 00:15:35 +01:00
mm = mm - > xformed_by ( Transform2D ( ) ) ; //make a copy
2016-01-17 02:41:10 +01:00
2020-03-25 00:15:35 +01:00
mm - > set_global_position ( mpos ) ;
mm - > set_speed ( speed ) ;
mm - > set_relative ( rel ) ;
2016-01-17 02:41:10 +01:00
2020-03-25 00:15:35 +01:00
if ( mm - > get_button_mask ( ) = = 0 ) {
//nothing pressed
2016-07-19 06:27:12 +02:00
2020-03-25 00:15:35 +01:00
bool can_tooltip = true ;
2017-05-20 17:38:03 +02:00
2020-03-25 00:15:35 +01:00
bool is_tooltip_shown = false ;
2020-03-20 21:51:53 +01:00
2020-03-25 00:15:35 +01:00
if ( gui . tooltip_popup ) {
if ( can_tooltip & & gui . tooltip ) {
String tooltip = _gui_get_tooltip ( over , gui . tooltip - > get_global_transform ( ) . xform_inv ( mpos ) ) ;
2020-03-20 21:51:53 +01:00
2020-05-14 16:41:43 +02:00
if ( tooltip . length ( ) = = 0 ) {
2020-03-25 00:15:35 +01:00
_gui_cancel_tooltip ( ) ;
2020-05-14 16:41:43 +02:00
} else if ( gui . tooltip_label ) {
2020-03-25 00:15:35 +01:00
if ( tooltip = = gui . tooltip_label - > get_text ( ) ) {
2020-03-20 21:51:53 +01:00
is_tooltip_shown = true ;
}
} else {
2020-03-25 00:15:35 +01: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 {
is_tooltip_shown = true ; //well, nothing to compare against, likely using custom control, so if it changes there is nothing we can do
}
2020-03-20 21:51:53 +01:00
}
2020-05-14 16:41:43 +02:00
} else {
2020-03-25 00:15:35 +01:00
_gui_cancel_tooltip ( ) ;
2020-05-14 16:41:43 +02:00
}
2020-03-25 00:15:35 +01:00
}
if ( can_tooltip & & ! is_tooltip_shown ) {
gui . tooltip = over ;
gui . tooltip_pos = over - > get_screen_transform ( ) . xform ( pos ) ; //(parent_xform * get_transform()).affine_inverse().xform(pos);
gui . tooltip_timer = gui . tooltip_delay ;
}
2017-05-20 17:38:03 +02:00
}
2016-07-18 22:14:57 +02:00
2020-03-25 00:15:35 +01:00
//pos = gui.focus_inv_xform.xform(pos);
2016-01-17 02:41:10 +01:00
2020-03-25 00:15:35 +01:00
mm - > set_position ( pos ) ;
Control : : CursorShape cursor_shape = Control : : CURSOR_ARROW ;
{
Control * c = over ;
Vector2 cpos = pos ;
while ( c ) {
2020-07-02 19:15:03 +02: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-25 00:15:35 +01:00
cpos = c - > get_transform ( ) . xform ( cpos ) ;
2020-05-14 16:41:43 +02:00
if ( cursor_shape ! = Control : : CURSOR_ARROW ) {
2020-03-25 00:15:35 +01:00
break ;
2020-05-14 16:41:43 +02:00
}
if ( c - > data . mouse_filter = = Control : : MOUSE_FILTER_STOP ) {
2020-03-25 00:15:35 +01:00
break ;
2020-05-14 16:41:43 +02:00
}
if ( c - > is_set_as_toplevel ( ) ) {
2020-03-25 00:15:35 +01:00
break ;
2020-05-14 16:41:43 +02:00
}
2020-03-25 00:15:35 +01:00
c = c - > get_parent_control ( ) ;
}
}
ds_cursor_shape = ( DisplayServer : : CursorShape ) cursor_shape ;
if ( over & & over - > can_process ( ) ) {
_gui_call_input ( over , mm ) ;
2016-01-17 02:41:10 +01:00
}
2020-03-25 00:15:35 +01:00
set_input_as_handled ( ) ;
2017-05-20 17:38:03 +02:00
}
2016-01-17 02:41:10 +01:00
2020-03-25 00:15:35 +01:00
if ( gui . drag_data . get_type ( ) ! = Variant : : NIL ) {
//handle dragandrop
2016-01-17 02:41:10 +01:00
2020-03-25 00:15:35 +01:00
if ( gui . drag_preview ) {
gui . drag_preview - > set_position ( mpos ) ;
}
2016-01-17 02:41:10 +01:00
2020-03-25 00:15:35 +01:00
gui . drag_mouse_over = over ;
gui . drag_mouse_over_pos = Vector2 ( ) ;
//find the window this is above of
//see if there is an embedder
Viewport * embedder = nullptr ;
Vector2 viewport_pos ;
if ( is_embedding_subwindows ( ) ) {
embedder = this ;
viewport_pos = mpos ;
} else {
//not an embeder, but may be a subwindow of an embedder
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 ( ) ;
viewport_pos = ai . xform ( mpos ) + w - > get_position ( ) ; //to parent coords
}
}
2018-06-07 17:46:14 +02:00
}
2020-03-25 00:15:35 +01:00
Viewport * viewport_under = nullptr ;
2016-01-17 02:41:10 +01:00
2020-03-25 00:15:35 +01:00
if ( embedder ) {
//use embedder logic
2016-01-17 02:41:10 +01:00
2020-03-25 00:15:35 +01:00
for ( int i = embedder - > gui . sub_windows . size ( ) - 1 ; i > = 0 ; i - - ) {
Window * sw = embedder - > gui . sub_windows [ i ] . window ;
Rect2 swrect = Rect2i ( sw - > get_position ( ) , sw - > get_size ( ) ) ;
if ( ! sw - > get_flag ( Window : : FLAG_BORDERLESS ) ) {
int title_height = sw - > get_theme_constant ( " title_height " ) ;
swrect . position . y - = title_height ;
swrect . size . y + = title_height ;
}
if ( swrect . has_point ( viewport_pos ) ) {
viewport_under = sw ;
viewport_pos - = sw - > get_position ( ) ;
}
}
2016-01-17 02:41:10 +01:00
2020-03-25 00:15:35 +01:00
if ( ! viewport_under ) {
//not in a subwindow, likely in embedder
viewport_under = embedder ;
}
} else {
//use displayserver logic
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 ) ;
if ( object_under ! = ObjectID ( ) ) { //fetch window
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 02:41:10 +01:00
2020-03-25 00:15:35 +01: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 ) ;
//find control under at pos
gui . drag_mouse_over = viewport_under - > _gui_find_control ( viewport_pos ) ;
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 ) ;
if ( mm - > get_button_mask ( ) & BUTTON_MASK_LEFT ) {
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 16:46:08 +02:00
2017-05-20 17:38:03 +02:00
} else {
2020-03-25 00:15:35 +01:00
gui . drag_mouse_over = nullptr ;
2016-01-17 02:41:10 +01:00
}
2017-05-20 17:38:03 +02:00
}
2020-03-25 00:15:35 +01:00
DisplayServer : : get_singleton ( ) - > cursor_set_shape ( ds_cursor_shape ) ;
2017-05-20 17:38:03 +02:00
}
2016-01-17 02:41:10 +01:00
2017-08-07 06:44:46 +02:00
Ref < InputEventScreenTouch > touch_event = p_event ;
if ( touch_event . is_valid ( ) ) {
Size2 pos = touch_event - > get_position ( ) ;
if ( touch_event - > is_pressed ( ) ) {
Control * over = _gui_find_control ( pos ) ;
if ( over ) {
if ( over - > can_process ( ) ) {
touch_event = touch_event - > xformed_by ( Transform2D ( ) ) ; //make a copy
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 17:54:26 +01:00
set_input_as_handled ( ) ;
2017-08-07 06:44:46 +02:00
return ;
}
2018-10-26 21:23:47 +02:00
} else if ( touch_event - > get_index ( ) = = 0 & & gui . last_mouse_focus ) {
if ( gui . last_mouse_focus - > can_process ( ) ) {
2017-08-07 06:44:46 +02:00
touch_event = touch_event - > xformed_by ( Transform2D ( ) ) ; //make a copy
touch_event - > set_position ( gui . focus_inv_xform . xform ( pos ) ) ;
2018-10-26 21:23:47 +02:00
_gui_call_input ( gui . last_mouse_focus , touch_event ) ;
2017-08-07 06:44:46 +02:00
}
2018-11-15 17:54:26 +01:00
set_input_as_handled ( ) ;
2017-08-07 06:44:46 +02:00
return ;
}
}
2017-11-01 21:49:39 +01:00
Ref < InputEventGesture > gesture_event = p_event ;
if ( gesture_event . is_valid ( ) ) {
2018-03-04 22:19:10 +01:00
gui . key_event_accepted = false ;
2017-12-22 19:39:23 +01:00
_gui_cancel_tooltip ( ) ;
2017-11-01 21:49:39 +01:00
Size2 pos = gesture_event - > get_position ( ) ;
Control * over = _gui_find_control ( pos ) ;
if ( over ) {
if ( over - > can_process ( ) ) {
gesture_event = gesture_event - > xformed_by ( Transform2D ( ) ) ; //make a copy
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 17:54:26 +01:00
set_input_as_handled ( ) ;
2017-11-01 21:49:39 +01:00
return ;
}
}
2017-08-07 06:44:46 +02:00
Ref < InputEventScreenDrag > drag_event = p_event ;
if ( drag_event . is_valid ( ) ) {
Control * over = gui . mouse_focus ;
if ( ! over ) {
over = _gui_find_control ( drag_event - > get_position ( ) ) ;
}
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 ( ) ) ;
drag_event = drag_event - > xformed_by ( Transform2D ( ) ) ; //make a copy
drag_event - > set_speed ( speed ) ;
drag_event - > set_relative ( rel ) ;
drag_event - > set_position ( pos ) ;
_gui_call_input ( over , drag_event ) ;
}
2018-11-15 17:54:26 +01:00
set_input_as_handled ( ) ;
2017-08-07 06:44:46 +02:00
return ;
}
}
2017-05-20 17:38:03 +02:00
if ( mm . is_null ( ) & & mb . is_null ( ) & & p_event - > is_action_type ( ) ) {
if ( gui . key_focus & & ! gui . key_focus - > is_visible_in_tree ( ) ) {
gui . key_focus - > release_focus ( ) ;
}
2016-07-01 15:42:33 +02:00
2017-05-20 17:38:03 +02:00
if ( gui . key_focus ) {
gui . key_event_accepted = false ;
if ( gui . key_focus - > can_process ( ) ) {
2020-07-24 19:13:58 +02:00
gui . key_focus - > call ( SceneStringNames : : get_singleton ( ) - > _gui_input , p_event ) ;
2020-05-14 16:41:43 +02:00
if ( gui . key_focus ) { //maybe lost it
2017-05-20 17:38:03 +02:00
gui . key_focus - > emit_signal ( SceneStringNames : : get_singleton ( ) - > gui_input , p_event ) ;
2020-05-14 16:41:43 +02:00
}
2017-05-20 17:38:03 +02:00
}
2016-01-17 02:41:10 +01:00
2017-05-20 17:38:03 +02:00
if ( gui . key_event_accepted ) {
2018-11-15 17:54:26 +01:00
set_input_as_handled ( ) ;
2017-05-20 17:38:03 +02:00
return ;
2016-01-17 02:41:10 +01:00
}
2017-05-20 17:38:03 +02:00
}
2016-01-17 02:41:10 +01:00
2020-04-02 01:20:12 +02:00
Control * from = gui . key_focus ? gui . key_focus : nullptr ; //hmm
2016-01-17 02:41:10 +01:00
2017-05-20 17:38:03 +02:00
//keyboard focus
//if (from && p_event->is_pressed() && !p_event->get_alt() && !p_event->get_metakey() && !p_event->key->get_command()) {
2016-01-17 02:41:10 +01:00
2017-07-15 14:35:29 +02:00
Ref < InputEventKey > k = p_event ;
//need to check for mods, otherwise any combination of alt/ctrl/shift+<up/down/left/righ/etc> is handled here when it shouldn't be.
bool mods = k . is_valid ( ) & & ( k - > get_control ( ) | | k - > get_alt ( ) | | k - > get_shift ( ) | | k - > get_metakey ( ) ) ;
2017-05-20 17:38:03 +02:00
if ( from & & p_event - > is_pressed ( ) ) {
2020-04-02 01:20:12 +02:00
Control * next = nullptr ;
2016-01-17 02:41:10 +01:00
2020-04-28 15:19:37 +02:00
Input * input = Input : : get_singleton ( ) ;
2019-09-02 04:36:32 +02:00
2019-12-18 08:30:03 +01:00
if ( p_event - > is_action_pressed ( " ui_focus_next " ) & & input - > is_action_just_pressed ( " ui_focus_next " ) ) {
2017-05-20 17:38:03 +02:00
next = from - > find_next_valid_focus ( ) ;
}
2016-01-17 02:41:10 +01:00
2019-12-18 08:30:03 +01:00
if ( p_event - > is_action_pressed ( " ui_focus_prev " ) & & input - > is_action_just_pressed ( " ui_focus_prev " ) ) {
2017-05-20 17:38:03 +02:00
next = from - > find_prev_valid_focus ( ) ;
}
2016-01-17 02:41:10 +01:00
2019-09-02 04:36:32 +02:00
if ( ! mods & & p_event - > is_action_pressed ( " ui_up " ) & & input - > is_action_just_pressed ( " ui_up " ) ) {
2017-05-20 17:38:03 +02:00
next = from - > _get_focus_neighbour ( MARGIN_TOP ) ;
}
2016-01-17 02:41:10 +01:00
2019-09-02 04:36:32 +02:00
if ( ! mods & & p_event - > is_action_pressed ( " ui_left " ) & & input - > is_action_just_pressed ( " ui_left " ) ) {
2017-05-20 17:38:03 +02:00
next = from - > _get_focus_neighbour ( MARGIN_LEFT ) ;
}
2016-01-17 02:41:10 +01:00
2019-09-02 04:36:32 +02:00
if ( ! mods & & p_event - > is_action_pressed ( " ui_right " ) & & input - > is_action_just_pressed ( " ui_right " ) ) {
2017-05-20 17:38:03 +02:00
next = from - > _get_focus_neighbour ( MARGIN_RIGHT ) ;
}
2016-01-17 02:41:10 +01:00
2019-09-02 04:36:32 +02:00
if ( ! mods & & p_event - > is_action_pressed ( " ui_down " ) & & input - > is_action_just_pressed ( " ui_down " ) ) {
2017-05-20 17:38:03 +02:00
next = from - > _get_focus_neighbour ( MARGIN_BOTTOM ) ;
2016-01-17 02:41:10 +01:00
}
2017-05-20 17:38:03 +02:00
if ( next ) {
next - > grab_focus ( ) ;
2018-11-15 17:54:26 +01:00
set_input_as_handled ( ) ;
2017-05-20 17:38:03 +02:00
}
}
2016-01-17 02:41:10 +01:00
}
}
2017-03-05 16:44:50 +01:00
List < Control * > : : Element * Viewport : : _gui_add_root_control ( Control * p_control ) {
gui . roots_order_dirty = true ;
2016-01-17 02:41:10 +01:00
return gui . roots . push_back ( p_control ) ;
}
void Viewport : : _gui_set_root_order_dirty ( ) {
2017-03-05 16:44:50 +01:00
gui . roots_order_dirty = true ;
2016-01-17 02:41:10 +01:00
}
2017-03-05 16:44:50 +01:00
void Viewport : : _gui_force_drag ( Control * p_base , const Variant & p_data , Control * p_control ) {
2019-08-08 22:11:48 +02:00
ERR_FAIL_COND_MSG ( p_data . get_type ( ) = = Variant : : NIL , " Drag data must be a value. " ) ;
2016-07-01 15:34:38 +02:00
2018-08-24 15:29:27 +02:00
gui . dragging = true ;
2017-03-05 16:44:50 +01:00
gui . drag_data = p_data ;
2020-04-02 01:20:12 +02:00
gui . mouse_focus = nullptr ;
2016-01-17 02:41:10 +01:00
if ( p_control ) {
2017-03-05 16:44:50 +01:00
_gui_set_drag_preview ( p_base , p_control ) ;
2016-01-17 02:41:10 +01:00
}
}
2016-01-20 00:27:27 +01:00
void Viewport : : _gui_set_drag_preview ( Control * p_base , Control * p_control ) {
2016-01-17 02:41:10 +01:00
ERR_FAIL_NULL ( p_control ) ;
2017-08-24 22:58:51 +02:00
ERR_FAIL_COND ( ! Object : : cast_to < Control > ( ( Object * ) p_control ) ) ;
2016-01-17 02:41:10 +01:00
ERR_FAIL_COND ( p_control - > is_inside_tree ( ) ) ;
2020-04-02 01:20:12 +02:00
ERR_FAIL_COND ( p_control - > get_parent ( ) ! = nullptr ) ;
2016-01-17 02:41:10 +01:00
if ( gui . drag_preview ) {
memdelete ( gui . drag_preview ) ;
}
p_control - > set_as_toplevel ( true ) ;
2017-03-29 17:29:38 +02:00
p_control - > set_position ( gui . last_mouse_pos ) ;
2016-01-20 00:27:27 +01:00
p_base - > get_root_parent_control ( ) - > add_child ( p_control ) ; //add as child of viewport
2016-01-17 02:41:10 +01:00
p_control - > raise ( ) ;
2018-05-08 07:52:38 +02:00
2017-03-05 16:44:50 +01:00
gui . drag_preview = p_control ;
2016-01-17 02:41:10 +01:00
}
2017-03-05 16:44:50 +01:00
void Viewport : : _gui_remove_root_control ( List < Control * > : : Element * RI ) {
2016-01-17 02:41:10 +01:00
gui . roots . erase ( RI ) ;
}
void Viewport : : _gui_unfocus_control ( Control * p_control ) {
2017-03-05 16:44:50 +01:00
if ( gui . key_focus = = p_control ) {
2016-01-17 02:41:10 +01:00
gui . key_focus - > release_focus ( ) ;
}
}
void Viewport : : _gui_hid_control ( Control * p_control ) {
if ( gui . mouse_focus = = p_control ) {
2018-11-28 13:31:17 +01:00
_drop_mouse_focus ( ) ;
2016-01-17 02:41:10 +01:00
}
2020-05-14 16:41:43 +02:00
if ( gui . key_focus = = p_control ) {
2017-12-26 20:58:53 +01:00
_gui_remove_focus ( ) ;
2020-05-14 16:41:43 +02:00
}
if ( gui . mouse_over = = p_control ) {
2020-04-02 01:20:12 +02:00
gui . mouse_over = nullptr ;
2020-05-14 16:41:43 +02:00
}
if ( gui . drag_mouse_over = = p_control ) {
2020-04-02 01:20:12 +02:00
gui . drag_mouse_over = nullptr ;
2020-05-14 16:41:43 +02:00
}
if ( gui . tooltip = = p_control ) {
2016-01-25 14:30:03 +01:00
_gui_cancel_tooltip ( ) ;
2020-05-14 16:41:43 +02:00
}
2016-01-17 02:41:10 +01:00
}
void Viewport : : _gui_remove_control ( Control * p_control ) {
2018-11-28 13:31:17 +01:00
if ( gui . mouse_focus = = p_control ) {
2020-04-02 01:20:12 +02:00
gui . mouse_focus = nullptr ;
2020-03-20 03:32:09 +01:00
gui . forced_mouse_focus = false ;
2018-11-28 13:31:17 +01:00
gui . mouse_focus_mask = 0 ;
}
2019-02-15 02:16:56 +01:00
if ( gui . last_mouse_focus = = p_control ) {
2020-04-02 01:20:12 +02:00
gui . last_mouse_focus = nullptr ;
2019-02-15 02:16:56 +01:00
}
2020-05-14 16:41:43 +02:00
if ( gui . key_focus = = p_control ) {
2020-04-02 01:20:12 +02:00
gui . key_focus = nullptr ;
2020-05-14 16:41:43 +02:00
}
if ( gui . mouse_over = = p_control ) {
2020-04-02 01:20:12 +02:00
gui . mouse_over = nullptr ;
2020-05-14 16:41:43 +02:00
}
if ( gui . drag_mouse_over = = p_control ) {
2020-04-02 01:20:12 +02:00
gui . drag_mouse_over = nullptr ;
2020-05-14 16:41:43 +02:00
}
if ( gui . tooltip = = p_control ) {
2020-04-02 01:20:12 +02:00
gui . tooltip = nullptr ;
2020-05-14 16:41:43 +02:00
}
2016-01-17 02:41:10 +01:00
}
2020-07-01 15:59:42 +02:00
Window * Viewport : : get_base_window ( ) const {
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 02:41:10 +01:00
void Viewport : : _gui_remove_focus ( ) {
if ( gui . key_focus ) {
2017-03-05 16:44:50 +01:00
Node * f = gui . key_focus ;
2020-04-02 01:20:12 +02:00
gui . key_focus = nullptr ;
2017-03-05 16:44:50 +01:00
f - > notification ( Control : : NOTIFICATION_FOCUS_EXIT , true ) ;
2016-01-17 02:41:10 +01:00
}
}
2017-03-05 16:44:50 +01:00
bool Viewport : : _gui_control_has_focus ( const Control * p_control ) {
return gui . key_focus = = p_control ;
2016-01-17 02:41:10 +01:00
}
2017-03-05 16:44:50 +01:00
void Viewport : : _gui_control_grab_focus ( Control * p_control ) {
2016-01-17 02:41:10 +01:00
//no need for change
2020-05-14 16:41:43 +02:00
if ( gui . key_focus & & gui . key_focus = = p_control ) {
2016-01-17 02:41:10 +01:00
return ;
2020-05-14 16:41:43 +02:00
}
2020-07-01 15:59:42 +02:00
get_tree ( ) - > call_group_flags ( SceneTree : : GROUP_CALL_REALTIME , " _viewports " , " _gui_remove_focus_for_window " , ( Node * ) get_base_window ( ) ) ;
2017-03-05 16:44:50 +01:00
gui . key_focus = p_control ;
2019-12-11 14:29:36 +01:00
emit_signal ( " gui_focus_changed " , p_control ) ;
2016-01-17 02:41:10 +01:00
p_control - > notification ( Control : : NOTIFICATION_FOCUS_ENTER ) ;
p_control - > update ( ) ;
}
void Viewport : : _gui_accept_event ( ) {
2017-03-05 16:44:50 +01:00
gui . key_event_accepted = true ;
2020-05-14 16:41:43 +02:00
if ( is_inside_tree ( ) ) {
2018-11-15 17:54:26 +01:00
set_input_as_handled ( ) ;
2020-05-14 16:41:43 +02:00
}
2016-01-17 02:41:10 +01:00
}
2018-11-28 13:31:17 +01:00
void Viewport : : _drop_mouse_focus ( ) {
Control * c = gui . mouse_focus ;
int mask = gui . mouse_focus_mask ;
2020-04-02 01:20:12 +02:00
gui . mouse_focus = nullptr ;
2020-03-20 03:32:09 +01:00
gui . forced_mouse_focus = false ;
2018-11-28 13:31:17 +01:00
gui . mouse_focus_mask = 0 ;
for ( int i = 0 ; i < 3 ; i + + ) {
if ( mask & ( 1 < < i ) ) {
Ref < InputEventMouseButton > mb ;
mb . instance ( ) ;
mb - > set_position ( c - > get_local_mouse_position ( ) ) ;
2018-11-28 17:09:56 +01:00
mb - > set_global_position ( c - > get_local_mouse_position ( ) ) ;
2018-11-28 13:31:17 +01:00
mb - > set_button_index ( i + 1 ) ;
mb - > set_pressed ( false ) ;
2020-07-24 19:13:58 +02:00
c - > call ( SceneStringNames : : get_singleton ( ) - > _gui_input , mb ) ;
2018-11-28 13:31:17 +01:00
}
}
}
2019-03-11 01:18:21 +01:00
void Viewport : : _drop_physics_mouseover ( ) {
physics_has_last_mousepos = false ;
while ( physics_2d_mouseover . size ( ) ) {
Object * o = ObjectDB : : get_instance ( physics_2d_mouseover . front ( ) - > key ( ) ) ;
if ( o ) {
CollisionObject2D * co = Object : : cast_to < CollisionObject2D > ( o ) ;
co - > _mouse_exit ( ) ;
}
physics_2d_mouseover . erase ( physics_2d_mouseover . front ( ) ) ;
}
# ifndef _3D_DISABLED
2020-02-12 18:24:06 +01:00
if ( physics_object_over . is_valid ( ) ) {
2020-03-26 22:49:16 +01:00
CollisionObject3D * co = Object : : cast_to < CollisionObject3D > ( ObjectDB : : get_instance ( physics_object_over ) ) ;
2019-03-11 01:18:21 +01:00
if ( co ) {
co - > _mouse_exit ( ) ;
}
}
2020-02-12 18:24:06 +01:00
physics_object_over = ObjectID ( ) ;
physics_object_capture = ObjectID ( ) ;
2019-03-11 01:18:21 +01:00
# endif
}
2016-01-17 02:41:10 +01:00
Control * Viewport : : _gui_get_focus_owner ( ) {
return gui . key_focus ;
}
void Viewport : : _gui_grab_click_focus ( Control * p_control ) {
2018-03-27 23:41:27 +02:00
gui . mouse_click_grabber = p_control ;
call_deferred ( " _post_gui_grab_click_focus " ) ;
}
void Viewport : : _post_gui_grab_click_focus ( ) {
Control * focus_grabber = gui . mouse_click_grabber ;
if ( ! focus_grabber ) {
// Redundant grab requests were made
return ;
}
2020-04-02 01:20:12 +02:00
gui . mouse_click_grabber = nullptr ;
2018-03-27 23:41:27 +02:00
2016-01-17 02:41:10 +01:00
if ( gui . mouse_focus ) {
2020-05-14 16:41:43 +02:00
if ( gui . mouse_focus = = focus_grabber ) {
2016-01-17 02:41:10 +01:00
return ;
2020-05-14 16:41:43 +02:00
}
2016-01-17 02:41:10 +01:00
2018-11-28 13:31:17 +01:00
int mask = gui . mouse_focus_mask ;
2017-03-05 16:44:50 +01:00
Point2 click = gui . mouse_focus - > get_global_transform_with_canvas ( ) . affine_inverse ( ) . xform ( gui . last_mouse_pos ) ;
2018-11-28 13:31:17 +01:00
for ( int i = 0 ; i < 3 ; i + + ) {
if ( mask & ( 1 < < i ) ) {
Ref < InputEventMouseButton > mb ;
mb . instance ( ) ;
//send unclic
mb - > set_position ( click ) ;
mb - > set_button_index ( i + 1 ) ;
mb - > set_pressed ( false ) ;
2020-07-24 19:13:58 +02:00
gui . mouse_focus - > call ( SceneStringNames : : get_singleton ( ) - > _gui_input , mb ) ;
2018-11-28 13:31:17 +01:00
}
}
2016-01-17 02:41:10 +01:00
2018-03-27 23:41:27 +02:00
gui . mouse_focus = focus_grabber ;
2017-03-05 16:44:50 +01: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 13:31:17 +01:00
for ( int i = 0 ; i < 3 ; i + + ) {
if ( mask & ( 1 < < i ) ) {
Ref < InputEventMouseButton > mb ;
mb . instance ( ) ;
//send clic
mb - > set_position ( click ) ;
mb - > set_button_index ( i + 1 ) ;
mb - > set_pressed ( true ) ;
gui . mouse_focus - > call_deferred ( SceneStringNames : : get_singleton ( ) - > _gui_input , mb ) ;
}
}
2016-01-17 02:41:10 +01:00
}
}
///////////////////////////////
2020-03-04 17:36:09 +01:00
void Viewport : : input_text ( const String & p_text ) {
2020-03-14 17:06:39 +01:00
if ( gui . subwindow_focused ) {
gui . subwindow_focused - > input_text ( p_text ) ;
return ;
}
2020-03-04 17:36:09 +01:00
if ( gui . key_focus ) {
gui . key_focus - > call ( " set_text " , p_text ) ;
}
}
2020-05-14 14:29:06 +02:00
2020-03-14 17:06:39 +01:00
Viewport : : SubWindowResize Viewport : : _sub_window_get_resize_margin ( Window * p_subwindow , const Point2 & p_point ) {
if ( p_subwindow - > get_flag ( Window : : FLAG_BORDERLESS ) ) {
return SUB_WINDOW_RESIZE_DISABLED ;
}
Rect2i r = Rect2i ( p_subwindow - > get_position ( ) , p_subwindow - > get_size ( ) ) ;
int title_height = p_subwindow - > get_theme_constant ( " title_height " ) ;
r . position . y - = title_height ;
r . size . y + = title_height ;
if ( r . has_point ( p_point ) ) {
return SUB_WINDOW_RESIZE_DISABLED ; //it's inside, so no resize
}
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 ) ;
int limit = p_subwindow - > get_theme_constant ( " resize_margin " ) ;
if ( ABS ( dist_x ) > limit ) {
return SUB_WINDOW_RESIZE_DISABLED ;
}
if ( ABS ( dist_y ) > limit ) {
return SUB_WINDOW_RESIZE_DISABLED ;
}
if ( dist_x < 0 & & dist_y < 0 ) {
return SUB_WINDOW_RESIZE_TOP_LEFT ;
}
if ( dist_x = = 0 & & dist_y < 0 ) {
return SUB_WINDOW_RESIZE_TOP ;
}
if ( dist_x > 0 & & dist_y < 0 ) {
return SUB_WINDOW_RESIZE_TOP_RIGHT ;
}
if ( dist_x < 0 & & dist_y = = 0 ) {
return SUB_WINDOW_RESIZE_LEFT ;
}
if ( dist_x > 0 & & dist_y = = 0 ) {
return SUB_WINDOW_RESIZE_RIGHT ;
}
if ( dist_x < 0 & & dist_y > 0 ) {
return SUB_WINDOW_RESIZE_BOTTOM_LEFT ;
}
if ( dist_x = = 0 & & dist_y > 0 ) {
return SUB_WINDOW_RESIZE_BOTTOM ;
}
if ( dist_x > 0 & & dist_y > 0 ) {
return SUB_WINDOW_RESIZE_BOTTOM_RIGHT ;
}
return SUB_WINDOW_RESIZE_DISABLED ;
}
2020-05-14 14:29:06 +02:00
2020-03-14 17:06:39 +01:00
bool Viewport : : _sub_windows_forward_input ( const Ref < InputEvent > & p_event ) {
if ( gui . subwindow_drag ! = SUB_WINDOW_DRAG_DISABLED ) {
ERR_FAIL_COND_V ( gui . subwindow_focused = = nullptr , false ) ;
Ref < InputEventMouseButton > mb = p_event ;
if ( mb . is_valid ( ) & & ! mb - > is_pressed ( ) & & mb - > get_button_index ( ) = = BUTTON_LEFT ) {
if ( gui . subwindow_drag = = SUB_WINDOW_DRAG_CLOSE ) {
if ( gui . subwindow_drag_close_rect . has_point ( mb - > get_position ( ) ) ) {
//close window
gui . subwindow_focused - > _event_callback ( DisplayServer : : WINDOW_EVENT_CLOSE_REQUEST ) ;
}
}
gui . subwindow_drag = SUB_WINDOW_DRAG_DISABLED ;
if ( gui . subwindow_focused ! = nullptr ) { //may have been erased
_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 17:39:42 +02: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 ;
}
int title_height = gui . subwindow_focused - > get_flag ( Window : : FLAG_BORDERLESS ) ? 0 : gui . subwindow_focused - > get_theme_constant ( " title_height " ) ;
if ( new_rect . position . y < title_height ) {
new_rect . position . y = title_height ;
}
}
2020-03-14 17:06:39 +01: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 ) ;
}
if ( gui . subwindow_focused ) { //may have been erased
_sub_window_update ( gui . subwindow_focused ) ;
}
}
return true ; //handled
}
Ref < InputEventMouseButton > mb = p_event ;
//if the event is a mouse button, we need to check whether another window was clicked
if ( mb . is_valid ( ) & & mb - > is_pressed ( ) & & mb - > get_button_index ( ) = = BUTTON_LEFT ) {
bool click_on_window = false ;
for ( int i = gui . sub_windows . size ( ) - 1 ; i > = 0 ; i - - ) {
SubWindow & sw = gui . sub_windows . write [ i ] ;
//clicked inside window?
Rect2i r = Rect2i ( sw . window - > get_position ( ) , sw . window - > get_size ( ) ) ;
if ( ! sw . window - > get_flag ( Window : : FLAG_BORDERLESS ) ) {
//check top bar
int title_height = sw . window - > get_theme_constant ( " title_height " ) ;
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 ;
int close_h_ofs = sw . window - > get_theme_constant ( " close_h_ofs " ) ;
int close_v_ofs = sw . window - > get_theme_constant ( " close_v_ofs " ) ;
Ref < Texture2D > close_icon = sw . window - > get_theme_icon ( " close " ) ;
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 ) {
//refocus
_sub_window_grab_focus ( sw . window ) ;
}
if ( close_rect . has_point ( mb - > get_position ( ) ) ) {
gui . subwindow_drag = SUB_WINDOW_DRAG_CLOSE ;
gui . subwindow_drag_close_inside = true ; //starts inside
gui . subwindow_drag_close_rect = close_rect ;
} else {
gui . subwindow_drag = SUB_WINDOW_DRAG_MOVE ;
}
gui . subwindow_drag_from = mb - > get_position ( ) ;
gui . subwindow_drag_pos = sw . window - > get_position ( ) ;
_sub_window_update ( sw . window ) ;
} else {
2020-03-25 00:15:35 +01:00
gui . subwindow_resize_mode = _sub_window_get_resize_margin ( sw . window , mb - > get_position ( ) ) ;
2020-03-14 17:06:39 +01:00
if ( gui . subwindow_resize_mode ! = SUB_WINDOW_RESIZE_DISABLED ) {
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 ( ) ) ) {
//clicked, see if it needs to fetch focus
if ( gui . subwindow_focused ! = sw . window ) {
//refocus
_sub_window_grab_focus ( sw . window ) ;
}
click_on_window = true ;
}
if ( click_on_window ) {
break ;
}
}
if ( ! click_on_window & & gui . subwindow_focused ) {
//no window found and clicked, remove focus
_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 ] ) ;
return true ; //reserved for showing the resize cursor
}
}
}
if ( gui . subwindow_drag ! = SUB_WINDOW_DRAG_DISABLED ) {
return true ; // dragging, don't pass the event
}
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 ;
}
2020-03-04 17:36:09 +01:00
void Viewport : : input ( const Ref < InputEvent > & p_event , bool p_local_coords ) {
2014-11-06 01:20:42 +01:00
ERR_FAIL_COND ( ! is_inside_tree ( ) ) ;
2016-01-18 23:49:11 +01:00
2020-05-14 16:41:43 +02:00
if ( disable_input ) {
2020-03-04 17:36:09 +01:00
return ;
2020-05-14 16:41:43 +02:00
}
2020-03-04 17:36:09 +01:00
if ( Engine : : get_singleton ( ) - > is_editor_hint ( ) & & get_tree ( ) - > get_edited_scene_root ( ) & & get_tree ( ) - > get_edited_scene_root ( ) - > is_a_parent_of ( this ) ) {
return ;
}
2018-11-15 17:54:26 +01:00
local_input_handled = false ;
2020-03-04 17:36:09 +01:00
Ref < InputEvent > ev ;
if ( ! p_local_coords ) {
ev = _make_input_local ( p_event ) ;
} else {
ev = p_event ;
}
2020-03-14 17:06:39 +01:00
if ( is_embedding_subwindows ( ) & & _sub_windows_forward_input ( p_event ) ) {
set_input_as_handled ( ) ;
return ;
}
2020-07-01 14:27:43 +02:00
if ( ! _can_consume_input_events ( ) ) {
return ;
}
2018-11-15 17:54:26 +01:00
if ( ! is_input_handled ( ) ) {
2020-03-04 17:36:09 +01:00
get_tree ( ) - > _call_input_pause ( input_group , " _input " , ev , this ) ; //not a bug, must happen before GUI, order is _input -> gui input -> _unhandled input
2017-10-16 14:13:33 +02:00
}
2018-11-15 17:54:26 +01:00
if ( ! is_input_handled ( ) ) {
2020-03-04 17:36:09 +01:00
_gui_input_event ( ev ) ;
2017-10-16 14:13:33 +02:00
}
2020-07-01 15:59:42 +02:00
event_count + + ;
2020-03-04 17:36:09 +01:00
//get_tree()->call_group(SceneTree::GROUP_CALL_REVERSE|SceneTree::GROUP_CALL_REALTIME|SceneTree::GROUP_CALL_MULIILEVEL,gui_input_group,"_gui_input",ev); //special one for GUI, as controls use their own process check
2014-04-10 05:18:27 +02:00
}
2020-03-04 17:36:09 +01:00
void Viewport : : unhandled_input ( const Ref < InputEvent > & p_event , bool p_local_coords ) {
2014-11-06 01:20:42 +01:00
ERR_FAIL_COND ( ! is_inside_tree ( ) ) ;
2014-04-10 05:18:27 +02:00
2020-07-01 14:27:43 +02:00
if ( disable_input | | ! _can_consume_input_events ( ) ) {
2020-03-04 17:36:09 +01:00
return ;
2020-05-14 16:41:43 +02:00
}
2020-03-04 17:36:09 +01:00
if ( Engine : : get_singleton ( ) - > is_editor_hint ( ) & & get_tree ( ) - > get_edited_scene_root ( ) & & get_tree ( ) - > get_edited_scene_root ( ) - > is_a_parent_of ( this ) ) {
return ;
}
Ref < InputEvent > ev ;
if ( ! p_local_coords ) {
ev = _make_input_local ( p_event ) ;
} else {
ev = p_event ;
}
get_tree ( ) - > _call_input_pause ( unhandled_input_group , " _unhandled_input " , ev , this ) ;
2020-04-02 01:20:12 +02:00
if ( ! is_input_handled ( ) & & Object : : cast_to < InputEventKey > ( * ev ) ! = nullptr ) {
2020-03-04 17:36:09 +01:00
get_tree ( ) - > _call_input_pause ( unhandled_key_input_group , " _unhandled_key_input " , ev , this ) ;
2014-04-10 05:18:27 +02:00
}
2014-09-15 16:33:30 +02:00
2020-03-04 17:36:09 +01:00
if ( physics_object_picking & & ! is_input_handled ( ) ) {
2020-04-28 15:19:37 +02:00
if ( Input : : get_singleton ( ) - > get_mouse_mode ( ) ! = Input : : MOUSE_MODE_CAPTURED & &
2020-03-04 17:36:09 +01:00
( Object : : cast_to < InputEventMouseButton > ( * ev ) | |
Object : : cast_to < InputEventMouseMotion > ( * ev ) | |
Object : : cast_to < InputEventScreenDrag > ( * ev ) | |
Object : : cast_to < InputEventScreenTouch > ( * ev ) | |
Object : : cast_to < InputEventKey > ( * ev ) //to remember state
2018-11-15 17:54:26 +01:00
) ) {
2020-03-04 17:36:09 +01:00
physics_picking_events . push_back ( ev ) ;
2014-09-15 16:33:30 +02:00
}
}
2014-04-10 05:18:27 +02:00
}
2020-04-18 11:00:51 +02:00
void Viewport : : set_use_own_world_3d ( bool p_world_3d ) {
2020-05-14 16:41:43 +02:00
if ( p_world_3d = = own_world_3d . is_valid ( ) ) {
2014-04-15 03:43:44 +02:00
return ;
2020-05-14 16:41:43 +02:00
}
2014-04-15 03:43:44 +02:00
2020-05-14 16:41:43 +02:00
if ( is_inside_tree ( ) ) {
2014-04-15 03:43:44 +02:00
_propagate_exit_world ( this ) ;
2020-05-14 16:41:43 +02:00
}
2014-04-15 03:43:44 +02:00
2020-04-18 11:00:51 +02:00
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 ) ) ;
2019-11-29 07:41:25 +01:00
}
} else {
2020-04-18 11:00:51 +02:00
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 ) ) ;
2019-11-29 07:41:25 +01:00
} else {
2020-04-18 11:00:51 +02:00
own_world_3d = Ref < World3D > ( memnew ( World3D ) ) ;
2019-11-29 07:41:25 +01:00
}
}
2014-04-15 03:43:44 +02:00
2020-05-14 16:41:43 +02:00
if ( is_inside_tree ( ) ) {
2014-04-15 03:43:44 +02:00
_propagate_enter_world ( this ) ;
2020-05-14 16:41:43 +02:00
}
2014-04-15 03:43:44 +02:00
2014-11-06 01:20:42 +01:00
if ( is_inside_tree ( ) ) {
2020-04-18 11:00:51 +02:00
RenderingServer : : get_singleton ( ) - > viewport_set_scenario ( viewport , find_world_3d ( ) - > get_scenario ( ) ) ;
2014-04-15 03:43:44 +02:00
}
_update_listener ( ) ;
}
2020-04-18 11:00:51 +02:00
bool Viewport : : is_using_own_world_3d ( ) const {
return own_world_3d . is_valid ( ) ;
2014-04-15 03:43:44 +02:00
}
2014-09-15 16:33:30 +02:00
void Viewport : : set_physics_object_picking ( bool p_enable ) {
2017-03-05 16:44:50 +01:00
physics_object_picking = p_enable ;
2018-03-01 14:44:45 +01:00
if ( ! physics_object_picking ) {
2014-09-15 16:33:30 +02:00
physics_picking_events . clear ( ) ;
2018-03-01 14:44:45 +01:00
}
}
bool Viewport : : get_physics_object_picking ( ) {
return physics_object_picking ;
2014-09-15 16:33:30 +02:00
}
2014-10-28 02:54:32 +01:00
Vector2 Viewport : : get_camera_coords ( const Vector2 & p_viewport_coords ) const {
2017-01-11 04:52:51 +01:00
Transform2D xf = get_final_transform ( ) ;
2014-10-28 02:54:32 +01:00
return xf . xform ( p_viewport_coords ) ;
}
Vector2 Viewport : : get_camera_rect_size ( ) const {
2016-10-27 16:50:26 +02:00
return size ;
2014-10-28 02:54:32 +01:00
}
2016-01-17 02:41:10 +01:00
void Viewport : : set_disable_input ( bool p_disable ) {
2017-03-05 16:44:50 +01:00
disable_input = p_disable ;
2016-01-17 02:41:10 +01:00
}
bool Viewport : : is_input_disabled ( ) const {
return disable_input ;
}
2014-02-10 02:10:30 +01:00
2016-05-11 16:46:08 +02:00
Variant Viewport : : gui_get_drag_data ( ) const {
return gui . drag_data ;
}
2016-05-17 23:27:15 +02:00
String Viewport : : get_configuration_warning ( ) const {
2017-08-24 22:58:51 +02:00
/*if (get_parent() && !Object::cast_to<Control>(get_parent()) && !render_target) {
2016-05-17 23:27:15 +02:00
2016-05-19 00:08:12 +02:00
return TTR ( " This viewport is not set as render target. If you intend for it to display its contents directly to the screen, make it a child of a Control so it can obtain a size. Otherwise, make it a RenderTarget and assign its internal texture to some node for display. " ) ;
2016-10-03 21:33:42 +02:00
} */
2016-05-17 23:27:15 +02:00
2020-03-17 21:33:36 +01:00
if ( size . x = = 0 | | size . y = = 0 ) {
2020-03-17 22:47:20 +01:00
return TTR ( " Viewport size must be greater than 0 to render anything. " ) ;
2020-03-17 21:33:36 +01:00
}
2016-05-17 23:27:15 +02:00
return String ( ) ;
}
2017-03-05 16:44:50 +01:00
void Viewport : : gui_reset_canvas_sort_index ( ) {
gui . canvas_sort_index = 0 ;
2016-10-03 21:33:42 +02:00
}
2020-05-14 14:29:06 +02:00
2016-10-03 21:33:42 +02:00
int Viewport : : gui_get_canvas_sort_index ( ) {
return gui . canvas_sort_index + + ;
}
2017-01-02 02:16:52 +01:00
void Viewport : : set_msaa ( MSAA p_msaa ) {
2020-04-12 06:49:10 +02:00
ERR_FAIL_INDEX ( p_msaa , MSAA_MAX ) ;
2020-05-14 16:41:43 +02:00
if ( msaa = = p_msaa ) {
2017-01-02 02:16:52 +01:00
return ;
2020-05-14 16:41:43 +02:00
}
2017-03-05 16:44:50 +01:00
msaa = p_msaa ;
2020-03-27 19:21:27 +01:00
RS : : get_singleton ( ) - > viewport_set_msaa ( viewport , RS : : ViewportMSAA ( p_msaa ) ) ;
2017-01-02 02:16:52 +01:00
}
Viewport : : MSAA Viewport : : get_msaa ( ) const {
return msaa ;
}
2020-04-12 06:49:10 +02: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 16:41:43 +02:00
if ( screen_space_aa = = p_screen_space_aa ) {
2020-04-12 06:49:10 +02:00
return ;
2020-05-14 16:41:43 +02:00
}
2020-04-12 06:49:10 +02:00
screen_space_aa = p_screen_space_aa ;
RS : : get_singleton ( ) - > viewport_set_screen_space_aa ( viewport , RS : : ViewportScreenSpaceAA ( p_screen_space_aa ) ) ;
}
Viewport : : ScreenSpaceAA Viewport : : get_screen_space_aa ( ) const {
return screen_space_aa ;
}
2020-05-14 14:29:06 +02:00
2017-06-11 20:52:03 +02:00
void Viewport : : set_debug_draw ( DebugDraw p_debug_draw ) {
debug_draw = p_debug_draw ;
2020-03-27 19:21:27 +01:00
RS : : get_singleton ( ) - > viewport_set_debug_draw ( viewport , RS : : ViewportDebugDraw ( p_debug_draw ) ) ;
2017-06-11 20:52:03 +02:00
}
Viewport : : DebugDraw Viewport : : get_debug_draw ( ) const {
return debug_draw ;
}
int Viewport : : get_render_info ( RenderInfo p_info ) {
2020-03-27 19:21:27 +01:00
return RS : : get_singleton ( ) - > viewport_get_render_info ( viewport , RS : : ViewportRenderInfo ( p_info ) ) ;
2017-06-11 20:52:03 +02:00
}
2017-09-07 16:22:07 +02:00
void Viewport : : set_snap_controls_to_pixels ( bool p_enable ) {
2017-09-07 08:57:09 +02:00
snap_controls_to_pixels = p_enable ;
2017-09-07 16:22:07 +02:00
}
bool Viewport : : is_snap_controls_to_pixels_enabled ( ) const {
return snap_controls_to_pixels ;
}
2018-08-24 15:29:27 +02:00
bool Viewport : : gui_is_dragging ( ) const {
return gui . dragging ;
}
2018-11-15 17:54:26 +01:00
void Viewport : : set_input_as_handled ( ) {
2019-06-07 17:21:12 +02:00
_drop_physics_mouseover ( ) ;
2018-11-15 17:54:26 +01:00
if ( handle_input_locally ) {
local_input_handled = true ;
} else {
ERR_FAIL_COND ( ! is_inside_tree ( ) ) ;
2020-03-04 17:36:09 +01:00
Viewport * vp = this ;
while ( true ) {
if ( Object : : cast_to < Window > ( vp ) ) {
break ;
}
if ( ! vp - > get_parent ( ) ) {
break ;
}
vp = vp - > get_parent ( ) - > get_viewport ( ) ;
}
vp - > set_input_as_handled ( ) ;
2018-11-15 17:54:26 +01:00
}
}
bool Viewport : : is_input_handled ( ) const {
if ( handle_input_locally ) {
return local_input_handled ;
} else {
2020-03-04 17:36:09 +01:00
const Viewport * vp = this ;
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 17:54:26 +01: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-03-03 02:12:01 +01:00
void Viewport : : _validate_property ( PropertyInfo & property ) const {
}
2019-06-25 03:24:07 +02:00
void Viewport : : set_default_canvas_item_texture_filter ( DefaultCanvasItemTextureFilter p_filter ) {
if ( default_canvas_item_texture_filter = = p_filter ) {
return ;
}
default_canvas_item_texture_filter = p_filter ;
_propagate_update_default_filter ( this ) ;
}
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 ) {
if ( default_canvas_item_texture_repeat = = p_repeat ) {
return ;
}
default_canvas_item_texture_repeat = p_repeat ;
_propagate_update_default_repeat ( this ) ;
}
2020-05-14 14:29:06 +02:00
2019-06-25 03:24:07 +02:00
Viewport : : DefaultCanvasItemTextureRepeat Viewport : : get_default_canvas_item_texture_repeat ( ) const {
return default_canvas_item_texture_repeat ;
}
void Viewport : : _propagate_update_default_filter ( Node * p_node ) {
CanvasItem * ci = Object : : cast_to < CanvasItem > ( p_node ) ;
if ( ci ) {
ci - > _update_texture_filter_changed ( false ) ;
}
for ( int i = 0 ; i < p_node - > get_child_count ( ) ; i + + ) {
_propagate_update_default_filter ( p_node - > get_child ( i ) ) ;
}
}
void Viewport : : _propagate_update_default_repeat ( Node * p_node ) {
CanvasItem * ci = Object : : cast_to < CanvasItem > ( p_node ) ;
if ( ci ) {
ci - > _update_texture_repeat_changed ( false ) ;
}
for ( int i = 0 ; i < p_node - > get_child_count ( ) ; i + + ) {
_propagate_update_default_repeat ( p_node - > get_child ( i ) ) ;
}
}
2020-03-03 14:36:29 +01:00
DisplayServer : : WindowID Viewport : : get_window_id ( ) const {
return DisplayServer : : MAIN_WINDOW_ID ;
}
2020-03-04 02:51:12 +01: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 02:10:30 +01:00
2020-03-04 02:51:12 +01:00
void Viewport : : set_embed_subwindows_hint ( bool p_embed ) {
gui . embed_subwindows_hint = p_embed ;
}
2020-05-14 14:29:06 +02:00
2020-03-04 02:51:12 +01:00
bool Viewport : : get_embed_subwindows_hint ( ) const {
return gui . embed_subwindows_hint ;
}
2020-05-14 14:29:06 +02:00
2020-03-04 02:51:12 +01:00
bool Viewport : : is_embedding_subwindows ( ) const {
return gui . embed_subwindows_hint ;
}
2020-03-20 03:32:09 +01: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-03-04 02:51:12 +01:00
void Viewport : : _bind_methods ( ) {
2017-08-09 13:19:41 +02:00
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 ) ;
2020-04-18 11:00:51 +02:00
ClassDB : : bind_method ( D_METHOD ( " set_world_3d " , " world_3d " ) , & Viewport : : set_world_3d ) ;
ClassDB : : bind_method ( D_METHOD ( " get_world_3d " ) , & Viewport : : get_world_3d ) ;
ClassDB : : bind_method ( D_METHOD ( " find_world_3d " ) , & Viewport : : find_world_3d ) ;
2014-02-10 02:10:30 +01:00
2017-03-05 16:44:50 +01:00
ClassDB : : bind_method ( D_METHOD ( " set_canvas_transform " , " xform " ) , & Viewport : : set_canvas_transform ) ;
2017-02-13 12:47:24 +01:00
ClassDB : : bind_method ( D_METHOD ( " get_canvas_transform " ) , & Viewport : : get_canvas_transform ) ;
2014-02-10 02:10:30 +01:00
2017-03-05 16:44:50 +01:00
ClassDB : : bind_method ( D_METHOD ( " set_global_canvas_transform " , " xform " ) , & Viewport : : set_global_canvas_transform ) ;
2017-02-13 12:47:24 +01:00
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 ) ;
2014-02-10 02:10:30 +01:00
2017-02-13 12:47:24 +01:00
ClassDB : : bind_method ( D_METHOD ( " get_visible_rect " ) , & Viewport : : get_visible_rect ) ;
2017-03-05 16:44:50 +01:00
ClassDB : : bind_method ( D_METHOD ( " set_transparent_background " , " enable " ) , & Viewport : : set_transparent_background ) ;
2017-02-13 12:47:24 +01:00
ClassDB : : bind_method ( D_METHOD ( " has_transparent_background " ) , & Viewport : : has_transparent_background ) ;
2014-02-10 02:10:30 +01:00
2017-03-05 16:44:50 +01:00
ClassDB : : bind_method ( D_METHOD ( " set_msaa " , " msaa " ) , & Viewport : : set_msaa ) ;
2017-02-13 12:47:24 +01:00
ClassDB : : bind_method ( D_METHOD ( " get_msaa " ) , & Viewport : : get_msaa ) ;
2014-08-14 15:31:38 +02:00
2020-04-12 06:49:10 +02:00
ClassDB : : bind_method ( D_METHOD ( " set_screen_space_aa " , " screen_space_aa " ) , & Viewport : : set_screen_space_aa ) ;
ClassDB : : bind_method ( D_METHOD ( " get_screen_space_aa " ) , & Viewport : : get_screen_space_aa ) ;
2017-06-11 20:52:03 +02:00
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 " , " info " ) , & Viewport : : get_render_info ) ;
2017-08-09 13:19:41 +02:00
ClassDB : : bind_method ( D_METHOD ( " get_texture " ) , & Viewport : : get_texture ) ;
2014-02-26 14:08:17 +01:00
2017-03-05 16:44:50 +01:00
ClassDB : : bind_method ( D_METHOD ( " set_physics_object_picking " , " enable " ) , & Viewport : : set_physics_object_picking ) ;
2017-02-13 12:47:24 +01:00
ClassDB : : bind_method ( D_METHOD ( " get_physics_object_picking " ) , & Viewport : : get_physics_object_picking ) ;
2014-09-15 16:33:30 +02:00
2017-02-13 12:47:24 +01:00
ClassDB : : bind_method ( D_METHOD ( " get_viewport_rid " ) , & Viewport : : get_viewport_rid ) ;
2020-03-04 17:36:09 +01:00
ClassDB : : bind_method ( D_METHOD ( " input_text " , " text " ) , & Viewport : : input_text ) ;
ClassDB : : bind_method ( D_METHOD ( " input " , " event " , " in_local_coords " ) , & Viewport : : input , DEFVAL ( false ) ) ;
ClassDB : : bind_method ( D_METHOD ( " unhandled_input " , " event " , " in_local_coords " ) , & Viewport : : unhandled_input , DEFVAL ( false ) ) ;
2014-02-26 14:08:17 +01:00
2017-02-13 12:47:24 +01:00
ClassDB : : bind_method ( D_METHOD ( " update_worlds " ) , & Viewport : : update_worlds ) ;
2014-02-10 02:10:30 +01:00
2020-04-18 11:00:51 +02:00
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 ) ;
2014-04-15 03:43:44 +02:00
2017-08-09 13:19:41 +02:00
ClassDB : : bind_method ( D_METHOD ( " get_camera " ) , & Viewport : : get_camera ) ;
2014-02-26 14:08:17 +01:00
2017-03-05 16:44:50 +01:00
ClassDB : : bind_method ( D_METHOD ( " set_as_audio_listener " , " enable " ) , & Viewport : : set_as_audio_listener ) ;
2017-08-09 13:54:55 +02:00
ClassDB : : bind_method ( D_METHOD ( " is_audio_listener " ) , & Viewport : : is_audio_listener ) ;
2014-02-26 14:08:17 +01:00
2017-03-05 16:44:50 +01:00
ClassDB : : bind_method ( D_METHOD ( " set_as_audio_listener_2d " , " enable " ) , & Viewport : : set_as_audio_listener_2d ) ;
2017-08-09 13:54:55 +02:00
ClassDB : : bind_method ( D_METHOD ( " is_audio_listener_2d " ) , & Viewport : : is_audio_listener_2d ) ;
2014-02-26 14:08:17 +01:00
2017-03-29 17:29:38 +02:00
ClassDB : : bind_method ( D_METHOD ( " get_mouse_position " ) , & Viewport : : get_mouse_position ) ;
2017-09-10 15:37:49 +02:00
ClassDB : : bind_method ( D_METHOD ( " warp_mouse " , " to_position " ) , & Viewport : : warp_mouse ) ;
2014-02-26 14:08:17 +01:00
2017-08-09 13:19:41 +02:00
ClassDB : : bind_method ( D_METHOD ( " gui_get_drag_data " ) , & Viewport : : gui_get_drag_data ) ;
2018-08-24 15:29:27 +02:00
ClassDB : : bind_method ( D_METHOD ( " gui_is_dragging " ) , & Viewport : : gui_is_dragging ) ;
2016-01-17 02:41:10 +01:00
2017-03-05 16:44:50 +01:00
ClassDB : : bind_method ( D_METHOD ( " set_disable_input " , " disable " ) , & Viewport : : set_disable_input ) ;
2017-02-13 12:47:24 +01:00
ClassDB : : bind_method ( D_METHOD ( " is_input_disabled " ) , & Viewport : : is_input_disabled ) ;
2016-01-17 02:41:10 +01:00
2020-07-01 15:59:42 +02:00
ClassDB : : bind_method ( D_METHOD ( " _gui_remove_focus_for_window " ) , & Viewport : : _gui_remove_focus_for_window ) ;
2018-03-27 23:41:27 +02:00
ClassDB : : bind_method ( D_METHOD ( " _post_gui_grab_click_focus " ) , & Viewport : : _post_gui_grab_click_focus ) ;
2016-01-17 02:41:10 +01:00
2017-03-05 16:44:50 +01:00
ClassDB : : bind_method ( D_METHOD ( " set_shadow_atlas_size " , " size " ) , & Viewport : : set_shadow_atlas_size ) ;
2017-02-13 12:47:24 +01:00
ClassDB : : bind_method ( D_METHOD ( " get_shadow_atlas_size " ) , & Viewport : : get_shadow_atlas_size ) ;
2016-11-10 03:55:06 +01:00
2017-09-07 16:22:07 +02:00
ClassDB : : bind_method ( D_METHOD ( " set_snap_controls_to_pixels " , " enabled " ) , & Viewport : : set_snap_controls_to_pixels ) ;
ClassDB : : bind_method ( D_METHOD ( " is_snap_controls_to_pixels_enabled " ) , & Viewport : : is_snap_controls_to_pixels_enabled ) ;
2017-03-05 16:44:50 +01: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 03:55:06 +01:00
2018-11-15 17:54:26 +01:00
ClassDB : : bind_method ( D_METHOD ( " set_input_as_handled " ) , & Viewport : : set_input_as_handled ) ;
ClassDB : : bind_method ( D_METHOD ( " is_input_handled " ) , & Viewport : : is_input_handled ) ;
ClassDB : : bind_method ( D_METHOD ( " set_handle_input_locally " , " enable " ) , & Viewport : : set_handle_input_locally ) ;
ClassDB : : bind_method ( D_METHOD ( " is_handling_input_locally " ) , & Viewport : : is_handling_input_locally ) ;
2019-06-25 03:24:07 +02:00
ClassDB : : bind_method ( D_METHOD ( " set_default_canvas_item_texture_filter " , " mode " ) , & Viewport : : set_default_canvas_item_texture_filter ) ;
ClassDB : : bind_method ( D_METHOD ( " get_default_canvas_item_texture_filter " ) , & Viewport : : get_default_canvas_item_texture_filter ) ;
2020-03-04 02:51:12 +01: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 03:24:07 +02:00
ClassDB : : bind_method ( D_METHOD ( " set_default_canvas_item_texture_repeat " , " mode " ) , & Viewport : : set_default_canvas_item_texture_repeat ) ;
ClassDB : : bind_method ( D_METHOD ( " get_default_canvas_item_texture_repeat " ) , & Viewport : : get_default_canvas_item_texture_repeat ) ;
2020-04-18 11:00:51 +02:00
ADD_PROPERTY ( PropertyInfo ( Variant : : BOOL , " own_world_3d " ) , " set_use_own_world_3d " , " is_using_own_world_3d " ) ;
2020-05-04 16:55:01 +02:00
ADD_PROPERTY ( PropertyInfo ( Variant : : OBJECT , " world_3d " , PROPERTY_HINT_RESOURCE_TYPE , " World3D " ) , " set_world_3d " , " get_world_3d " ) ;
2018-01-11 23:35:12 +01:00
ADD_PROPERTY ( PropertyInfo ( Variant : : OBJECT , " world_2d " , PROPERTY_HINT_RESOURCE_TYPE , " World2D " , 0 ) , " set_world_2d " , " get_world_2d " ) ;
2017-03-05 16:44:50 +01:00
ADD_PROPERTY ( PropertyInfo ( Variant : : BOOL , " transparent_bg " ) , " set_transparent_background " , " has_transparent_background " ) ;
2018-11-15 17:54:26 +01:00
ADD_PROPERTY ( PropertyInfo ( Variant : : BOOL , " handle_input_locally " ) , " set_handle_input_locally " , " is_handling_input_locally " ) ;
2017-03-05 16:44:50 +01:00
ADD_GROUP ( " Rendering " , " " ) ;
2019-11-19 19:02:11 +01:00
ADD_PROPERTY ( PropertyInfo ( Variant : : INT , " msaa " , PROPERTY_HINT_ENUM , " Disabled,2x,4x,8x,16x,AndroidVR 2x,AndroidVR 4x " ) , " set_msaa " , " get_msaa " ) ;
2020-04-12 06:49:10 +02:00
ADD_PROPERTY ( PropertyInfo ( Variant : : INT , " screen_space_aa " , PROPERTY_HINT_ENUM , " Disabled,FXAA " ) , " set_screen_space_aa " , " get_screen_space_aa " ) ;
2017-06-11 20:52:03 +02:00
ADD_PROPERTY ( PropertyInfo ( Variant : : INT , " debug_draw " , PROPERTY_HINT_ENUM , " Disabled,Unshaded,Overdraw,Wireframe " ) , " set_debug_draw " , " get_debug_draw " ) ;
2019-06-25 03:24:07 +02:00
ADD_GROUP ( " Canvas Items " , " canvas_item_ " ) ;
ADD_PROPERTY ( PropertyInfo ( Variant : : INT , " canvas_item_default_texture_filter " , PROPERTY_HINT_ENUM , " Nearest,Linear,MipmapLinear,MipmapNearest " ) , " set_default_canvas_item_texture_filter " , " get_default_canvas_item_texture_filter " ) ;
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 16:44:50 +01: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_PROPERTY ( PropertyInfo ( Variant : : BOOL , " audio_listener_enable_3d " ) , " set_as_audio_listener " , " is_audio_listener " ) ;
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 16:22:07 +02:00
ADD_PROPERTY ( PropertyInfo ( Variant : : BOOL , " gui_snap_controls_to_pixels " ) , " set_snap_controls_to_pixels " , " is_snap_controls_to_pixels_enabled " ) ;
2020-03-04 02:51:12 +01:00
ADD_PROPERTY ( PropertyInfo ( Variant : : BOOL , " gui_embed_subwindows " ) , " set_embed_subwindows_hint " , " get_embed_subwindows_hint " ) ;
2017-03-05 16:44:50 +01:00
ADD_GROUP ( " Shadow Atlas " , " shadow_atlas_ " ) ;
ADD_PROPERTY ( PropertyInfo ( Variant : : INT , " shadow_atlas_size " ) , " set_shadow_atlas_size " , " get_shadow_atlas_size " ) ;
ADD_PROPERTYI ( PropertyInfo ( Variant : : INT , " shadow_atlas_quad_0 " , PROPERTY_HINT_ENUM , " Disabled,1 Shadow,4 Shadows,16 Shadows,64 Shadows,256 Shadows,1024 Shadows " ) , " set_shadow_atlas_quadrant_subdiv " , " get_shadow_atlas_quadrant_subdiv " , 0 ) ;
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 ) ;
2018-01-11 23:35:12 +01:00
ADD_PROPERTY ( PropertyInfo ( Variant : : TRANSFORM2D , " canvas_transform " , PROPERTY_HINT_NONE , " " , 0 ) , " set_canvas_transform " , " get_canvas_transform " ) ;
ADD_PROPERTY ( PropertyInfo ( Variant : : TRANSFORM2D , " global_canvas_transform " , PROPERTY_HINT_NONE , " " , 0 ) , " set_global_canvas_transform " , " get_global_canvas_transform " ) ;
2014-02-10 02:10:30 +01:00
ADD_SIGNAL ( MethodInfo ( " size_changed " ) ) ;
2019-12-11 14:29:36 +01:00
ADD_SIGNAL ( MethodInfo ( " gui_focus_changed " , PropertyInfo ( Variant : : OBJECT , " node " , PROPERTY_HINT_RESOURCE_TYPE , " Control " ) ) ) ;
2014-02-26 14:08:17 +01:00
2017-08-20 17:45:01 +02:00
BIND_ENUM_CONSTANT ( SHADOW_ATLAS_QUADRANT_SUBDIV_DISABLED ) ;
BIND_ENUM_CONSTANT ( SHADOW_ATLAS_QUADRANT_SUBDIV_1 ) ;
BIND_ENUM_CONSTANT ( SHADOW_ATLAS_QUADRANT_SUBDIV_4 ) ;
BIND_ENUM_CONSTANT ( SHADOW_ATLAS_QUADRANT_SUBDIV_16 ) ;
BIND_ENUM_CONSTANT ( SHADOW_ATLAS_QUADRANT_SUBDIV_64 ) ;
BIND_ENUM_CONSTANT ( SHADOW_ATLAS_QUADRANT_SUBDIV_256 ) ;
BIND_ENUM_CONSTANT ( SHADOW_ATLAS_QUADRANT_SUBDIV_1024 ) ;
BIND_ENUM_CONSTANT ( SHADOW_ATLAS_QUADRANT_SUBDIV_MAX ) ;
2020-04-20 11:48:00 +02:00
BIND_ENUM_CONSTANT ( MSAA_DISABLED ) ;
BIND_ENUM_CONSTANT ( MSAA_2X ) ;
BIND_ENUM_CONSTANT ( MSAA_4X ) ;
BIND_ENUM_CONSTANT ( MSAA_8X ) ;
BIND_ENUM_CONSTANT ( MSAA_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 17:45:01 +02:00
BIND_ENUM_CONSTANT ( RENDER_INFO_OBJECTS_IN_FRAME ) ;
BIND_ENUM_CONSTANT ( RENDER_INFO_VERTICES_IN_FRAME ) ;
BIND_ENUM_CONSTANT ( RENDER_INFO_MATERIAL_CHANGES_IN_FRAME ) ;
BIND_ENUM_CONSTANT ( RENDER_INFO_SHADER_CHANGES_IN_FRAME ) ;
BIND_ENUM_CONSTANT ( RENDER_INFO_SURFACE_CHANGES_IN_FRAME ) ;
BIND_ENUM_CONSTANT ( RENDER_INFO_DRAW_CALLS_IN_FRAME ) ;
BIND_ENUM_CONSTANT ( RENDER_INFO_MAX ) ;
BIND_ENUM_CONSTANT ( DEBUG_DRAW_DISABLED ) ;
BIND_ENUM_CONSTANT ( DEBUG_DRAW_UNSHADED ) ;
2020-04-20 11:48:00 +02:00
BIND_ENUM_CONSTANT ( DEBUG_DRAW_LIGHTING ) ;
2017-08-20 17:45:01 +02:00
BIND_ENUM_CONSTANT ( DEBUG_DRAW_OVERDRAW ) ;
BIND_ENUM_CONSTANT ( DEBUG_DRAW_WIREFRAME ) ;
2020-04-20 11:48:00 +02:00
BIND_ENUM_CONSTANT ( DEBUG_DRAW_NORMAL_BUFFER ) ;
2020-01-12 02:26:52 +01:00
BIND_ENUM_CONSTANT ( DEBUG_DRAW_GI_PROBE_ALBEDO ) ;
BIND_ENUM_CONSTANT ( DEBUG_DRAW_GI_PROBE_LIGHTING ) ;
BIND_ENUM_CONSTANT ( DEBUG_DRAW_GI_PROBE_EMISSION ) ;
BIND_ENUM_CONSTANT ( DEBUG_DRAW_SHADOW_ATLAS ) ;
BIND_ENUM_CONSTANT ( DEBUG_DRAW_DIRECTIONAL_SHADOW_ATLAS ) ;
BIND_ENUM_CONSTANT ( DEBUG_DRAW_SCENE_LUMINANCE ) ;
2020-01-25 11:18:55 +01:00
BIND_ENUM_CONSTANT ( DEBUG_DRAW_SSAO ) ;
2020-04-08 03:51:52 +02:00
BIND_ENUM_CONSTANT ( DEBUG_DRAW_PSSM_SPLITS ) ;
2020-04-14 05:05:21 +02:00
BIND_ENUM_CONSTANT ( DEBUG_DRAW_DECAL_ATLAS ) ;
2020-06-25 15:33:28 +02:00
BIND_ENUM_CONSTANT ( DEBUG_DRAW_SDFGI ) ;
BIND_ENUM_CONSTANT ( DEBUG_DRAW_SDFGI_PROBES ) ;
BIND_ENUM_CONSTANT ( DEBUG_DRAW_GI_BUFFER ) ;
2020-01-12 02:26:52 +01:00
2019-06-25 03:24:07 +02:00
BIND_ENUM_CONSTANT ( DEFAULT_CANVAS_ITEM_TEXTURE_FILTER_NEAREST ) ;
BIND_ENUM_CONSTANT ( DEFAULT_CANVAS_ITEM_TEXTURE_FILTER_LINEAR ) ;
BIND_ENUM_CONSTANT ( DEFAULT_CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS ) ;
2020-02-20 00:31:43 +01:00
BIND_ENUM_CONSTANT ( DEFAULT_CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS ) ;
2019-06-25 03:24:07 +02:00
BIND_ENUM_CONSTANT ( DEFAULT_CANVAS_ITEM_TEXTURE_FILTER_MAX ) ;
2020-04-20 11:48:00 +02:00
2019-06-25 03:24:07 +02:00
BIND_ENUM_CONSTANT ( DEFAULT_CANVAS_ITEM_TEXTURE_REPEAT_DISABLED ) ;
BIND_ENUM_CONSTANT ( DEFAULT_CANVAS_ITEM_TEXTURE_REPEAT_ENABLED ) ;
BIND_ENUM_CONSTANT ( DEFAULT_CANVAS_ITEM_TEXTURE_REPEAT_MIRROR ) ;
BIND_ENUM_CONSTANT ( DEFAULT_CANVAS_ITEM_TEXTURE_REPEAT_MAX ) ;
2014-02-10 02:10:30 +01:00
}
Viewport : : Viewport ( ) {
2017-03-05 16:44:50 +01:00
world_2d = Ref < World2D > ( memnew ( World2D ) ) ;
2014-02-10 02:10:30 +01:00
2020-03-27 19:21:27 +01:00
viewport = RenderingServer : : get_singleton ( ) - > viewport_create ( ) ;
texture_rid = RenderingServer : : get_singleton ( ) - > viewport_get_texture ( viewport ) ;
2017-01-10 22:02:19 +01:00
default_texture . instance ( ) ;
2017-03-05 16:44:50 +01:00
default_texture - > vp = const_cast < Viewport * > ( this ) ;
2017-01-10 22:02:19 +01:00
viewport_textures . insert ( default_texture . ptr ( ) ) ;
2020-03-27 19:21:27 +01:00
default_texture - > proxy = RS : : get_singleton ( ) - > texture_proxy_create ( texture_rid ) ;
2017-01-10 22:02:19 +01:00
2017-03-05 16:44:50 +01:00
audio_listener = false ;
2017-01-15 20:06:14 +01:00
//internal_listener_2d = SpatialSound2DServer::get_singleton()->listener_create();
2017-03-05 16:44:50 +01:00
audio_listener_2d = false ;
transparent_bg = false ;
2020-04-02 01:20:12 +02:00
parent = nullptr ;
listener = nullptr ;
camera = nullptr ;
2019-04-06 22:55:01 +02:00
override_canvas_transform = false ;
2020-04-02 01:20:12 +02:00
canvas_layers . insert ( nullptr ) ; // This eases picking code (interpreted as the canvas of the Viewport)
2020-03-04 02:51:12 +01:00
2017-03-05 16:44:50 +01:00
gen_mipmaps = false ;
2016-10-03 21:33:42 +02:00
//clear=true;
2014-02-10 02:10:30 +01:00
2017-03-05 16:44:50 +01:00
physics_object_picking = false ;
2018-12-18 08:11:13 +01:00
physics_has_last_mousepos = false ;
physics_last_mousepos = Vector2 ( Math_INF , Math_INF ) ;
2014-09-15 16:33:30 +02:00
2017-03-05 16:44:50 +01:00
shadow_atlas_size = 0 ;
for ( int i = 0 ; i < 4 ; i + + ) {
shadow_atlas_quadrant_subdiv [ i ] = SHADOW_ATLAS_QUADRANT_SUBDIV_MAX ;
2016-11-10 03:55:06 +01:00
}
2017-03-05 16:44:50 +01: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 03:43:44 +02:00
2017-08-07 12:17:31 +02:00
String id = itos ( get_instance_id ( ) ) ;
2017-03-05 16:44:50 +01: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 02:10:30 +01:00
2017-03-05 16:44:50 +01:00
disable_input = false ;
2016-01-17 02:41:10 +01:00
//window tooltip
2016-01-25 14:30:03 +01:00
gui . tooltip_timer = - 1 ;
//gui.tooltip_timer->force_parent_owned();
2019-04-10 19:45:29 +02: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 19:20:53 +01: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 23:49:11 +01:00
2020-04-02 01:20:12 +02:00
gui . tooltip = nullptr ;
gui . tooltip_label = nullptr ;
gui . drag_preview = nullptr ;
2017-03-05 16:44:50 +01:00
gui . drag_attempted = false ;
gui . canvas_sort_index = 0 ;
2018-02-28 21:55:13 +01:00
gui . roots_order_dirty = false ;
2020-04-02 01:20:12 +02:00
gui . mouse_focus = nullptr ;
2020-03-20 03:32:09 +01:00
gui . forced_mouse_focus = false ;
2020-04-02 01:20:12 +02:00
gui . last_mouse_focus = nullptr ;
2020-03-14 17:06:39 +01:00
gui . subwindow_focused = nullptr ;
gui . subwindow_drag = SUB_WINDOW_DRAG_DISABLED ;
2015-09-20 18:03:46 +02:00
2017-03-05 16:44:50 +01:00
msaa = MSAA_DISABLED ;
2020-04-12 06:49:10 +02:00
screen_space_aa = SCREEN_SPACE_AA_DISABLED ;
2017-06-11 20:52:03 +02:00
debug_draw = DEBUG_DRAW_DISABLED ;
2017-09-07 16:22:07 +02:00
snap_controls_to_pixels = true ;
2018-11-15 17:54:26 +01:00
physics_last_mouse_state . alt = false ;
physics_last_mouse_state . control = false ;
physics_last_mouse_state . shift = false ;
physics_last_mouse_state . meta = false ;
physics_last_mouse_state . mouse_mask = 0 ;
local_input_handled = false ;
handle_input_locally = true ;
2019-06-25 03:24:07 +02:00
2020-03-04 02:51:12 +01:00
size_allocated = false ;
2019-06-25 03:24:07 +02:00
default_canvas_item_texture_filter = DEFAULT_CANVAS_ITEM_TEXTURE_FILTER_LINEAR ;
default_canvas_item_texture_repeat = DEFAULT_CANVAS_ITEM_TEXTURE_REPEAT_DISABLED ;
2014-02-10 02:10:30 +01:00
}
Viewport : : ~ Viewport ( ) {
2017-01-10 05:04:31 +01:00
//erase itself from viewport textures
2017-03-05 16:44:50 +01:00
for ( Set < ViewportTexture * > : : Element * E = viewport_textures . front ( ) ; E ; E = E - > next ( ) ) {
2020-04-02 01:20:12 +02:00
E - > get ( ) - > vp = nullptr ;
2017-01-10 05:04:31 +01:00
}
2020-03-27 19:21:27 +01:00
RenderingServer : : get_singleton ( ) - > free ( viewport ) ;
2014-02-10 02:10:30 +01:00
}
2020-03-04 02:51:12 +01:00
/////////////////////////////////
2020-04-08 16:47:36 +02:00
void SubViewport : : set_use_xr ( bool p_use_xr ) {
xr = p_use_xr ;
2020-03-04 02:51:12 +01:00
2020-04-08 16:47:36 +02:00
RS : : get_singleton ( ) - > viewport_set_use_xr ( get_viewport_rid ( ) , xr ) ;
2020-03-04 02:51:12 +01:00
}
2020-04-08 16:47:36 +02:00
bool SubViewport : : is_using_xr ( ) {
return xr ;
2020-03-04 02:51:12 +01:00
}
void SubViewport : : set_size ( const Size2i & p_size ) {
2020-04-01 05:47:58 +02:00
_set_size ( p_size , _get_size_2d_override ( ) , Rect2i ( ) , _stretch_transform ( ) , true ) ;
2020-03-04 02:51:12 +01:00
}
2020-05-14 14:29:06 +02:00
2020-03-04 02:51:12 +01:00
Size2i SubViewport : : get_size ( ) const {
return _get_size ( ) ;
}
2020-04-01 05:47:58 +02:00
void SubViewport : : set_size_2d_override ( const Size2i & p_size ) {
_set_size ( _get_size ( ) , p_size , Rect2i ( ) , _stretch_transform ( ) , true ) ;
}
2020-05-14 14:29:06 +02:00
2020-04-01 05:47:58 +02: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 14:29:06 +02:00
2020-04-01 05:47:58 +02:00
bool SubViewport : : is_size_2d_override_stretch_enabled ( ) const {
return size_2d_override_stretch ;
}
2020-03-04 02:51:12 +01:00
void SubViewport : : set_update_mode ( UpdateMode p_mode ) {
update_mode = p_mode ;
2020-03-27 19:21:27 +01:00
RS : : get_singleton ( ) - > viewport_set_update_mode ( get_viewport_rid ( ) , RS : : ViewportUpdateMode ( p_mode ) ) ;
2020-03-04 02:51:12 +01:00
}
2020-05-14 14:29:06 +02:00
2020-03-04 02:51:12 +01:00
SubViewport : : UpdateMode SubViewport : : get_update_mode ( ) const {
return update_mode ;
}
void SubViewport : : set_clear_mode ( ClearMode p_mode ) {
clear_mode = p_mode ;
2020-03-27 19:21:27 +01:00
RS : : get_singleton ( ) - > viewport_set_clear_mode ( get_viewport_rid ( ) , RS : : ViewportClearMode ( p_mode ) ) ;
2020-03-04 02:51:12 +01:00
}
2020-05-14 14:29:06 +02:00
2020-03-04 02:51:12 +01:00
SubViewport : : ClearMode SubViewport : : get_clear_mode ( ) const {
return clear_mode ;
}
DisplayServer : : WindowID SubViewport : : get_window_id ( ) const {
return DisplayServer : : INVALID_WINDOW_ID ;
}
2020-04-01 05:47:58 +02: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 17:06:39 +01:00
void SubViewport : : _notification ( int p_what ) {
if ( p_what = = NOTIFICATION_ENTER_TREE ) {
2020-03-27 19:21:27 +01:00
RS : : get_singleton ( ) - > viewport_set_active ( get_viewport_rid ( ) , true ) ;
2020-03-14 17:06:39 +01:00
}
if ( p_what = = NOTIFICATION_EXIT_TREE ) {
2020-03-27 19:21:27 +01:00
RS : : get_singleton ( ) - > viewport_set_active ( get_viewport_rid ( ) , false ) ;
2020-03-14 17:06:39 +01:00
}
}
2020-03-04 02:51:12 +01:00
void SubViewport : : _bind_methods ( ) {
2020-04-08 16:47:36 +02:00
ClassDB : : bind_method ( D_METHOD ( " set_use_xr " , " use " ) , & SubViewport : : set_use_xr ) ;
ClassDB : : bind_method ( D_METHOD ( " is_using_xr " ) , & SubViewport : : is_using_xr ) ;
2020-03-04 02:51:12 +01:00
ClassDB : : bind_method ( D_METHOD ( " set_size " , " size " ) , & SubViewport : : set_size ) ;
ClassDB : : bind_method ( D_METHOD ( " get_size " ) , & SubViewport : : get_size ) ;
2020-04-01 05:47:58 +02:00
ClassDB : : bind_method ( D_METHOD ( " set_size_2d_override " , " size " ) , & SubViewport : : set_size_2d_override ) ;
ClassDB : : bind_method ( D_METHOD ( " get_size_2d_override " ) , & SubViewport : : get_size_2d_override ) ;
ClassDB : : bind_method ( D_METHOD ( " set_size_2d_override_stretch " , " enable " ) , & SubViewport : : set_size_2d_override_stretch ) ;
ClassDB : : bind_method ( D_METHOD ( " is_size_2d_override_stretch_enabled " ) , & SubViewport : : is_size_2d_override_stretch_enabled ) ;
2020-03-04 02:51:12 +01:00
ClassDB : : bind_method ( D_METHOD ( " set_update_mode " , " mode " ) , & SubViewport : : set_update_mode ) ;
ClassDB : : bind_method ( D_METHOD ( " get_update_mode " ) , & SubViewport : : get_update_mode ) ;
ClassDB : : bind_method ( D_METHOD ( " set_clear_mode " , " mode " ) , & SubViewport : : set_clear_mode ) ;
ClassDB : : bind_method ( D_METHOD ( " get_clear_mode " ) , & SubViewport : : get_clear_mode ) ;
2020-04-08 16:47:36 +02:00
ADD_PROPERTY ( PropertyInfo ( Variant : : BOOL , " xr " ) , " set_use_xr " , " is_using_xr " ) ;
2020-04-01 05:47:58 +02: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 02:51:12 +01:00
ADD_GROUP ( " Render Target " , " render_target_ " ) ;
ADD_PROPERTY ( PropertyInfo ( Variant : : INT , " render_target_clear_mode " , PROPERTY_HINT_ENUM , " Always,Never,Next Frame " ) , " set_clear_mode " , " get_clear_mode " ) ;
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 11:48:00 +02:00
BIND_ENUM_CONSTANT ( CLEAR_MODE_ALWAYS ) ;
BIND_ENUM_CONSTANT ( CLEAR_MODE_NEVER ) ;
BIND_ENUM_CONSTANT ( CLEAR_MODE_ONLY_NEXT_FRAME ) ;
2020-03-04 02:51:12 +01:00
BIND_ENUM_CONSTANT ( UPDATE_DISABLED ) ;
BIND_ENUM_CONSTANT ( UPDATE_ONCE ) ;
BIND_ENUM_CONSTANT ( UPDATE_WHEN_VISIBLE ) ;
2020-03-14 17:06:39 +01:00
BIND_ENUM_CONSTANT ( UPDATE_WHEN_PARENT_VISIBLE ) ;
2020-03-04 02:51:12 +01:00
BIND_ENUM_CONSTANT ( UPDATE_ALWAYS ) ;
}
SubViewport : : SubViewport ( ) {
2020-04-08 16:47:36 +02:00
xr = false ;
2020-04-01 05:47:58 +02:00
size_2d_override_stretch = false ;
2020-03-04 02:51:12 +01:00
update_mode = UPDATE_WHEN_VISIBLE ;
clear_mode = CLEAR_MODE_ALWAYS ;
}
SubViewport : : ~ SubViewport ( ) {
}