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
/*************************************************************************/
2019-01-01 12:53:14 +01:00
/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */
/* Copyright (c) 2014-2019 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
2018-09-11 18:13:45 +02:00
# include "core/os/input.h"
# 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"
2014-02-10 02:10:30 +01:00
# include "scene/3d/camera.h"
2017-03-05 16:44:50 +01:00
# include "scene/3d/collision_object.h"
2016-03-20 03:10:04 +01:00
# include "scene/3d/listener.h"
2017-08-27 21:07:15 +02:00
# include "scene/3d/spatial.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"
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"
2017-08-27 21:07:15 +02:00
# include "servers/physics_2d_server.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 ) ;
}
2017-03-05 16:44:50 +01:00
vp = NULL ;
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 ) ;
ERR_EXPLAIN ( " ViewportTexture: Path to node is invalid " ) ;
ERR_FAIL_COND ( ! vpn ) ;
2017-08-24 22:58:51 +02:00
vp = Object : : cast_to < Viewport > ( vpn ) ;
2017-01-10 05:04:31 +01:00
ERR_EXPLAIN ( " ViewportTexture: Path to node does not point to a viewport " ) ;
ERR_FAIL_COND ( ! vp ) ;
vp - > viewport_textures . insert ( this ) ;
2017-12-04 19:55:20 +01:00
VS : : get_singleton ( ) - > texture_set_proxy ( proxy , vp - > texture_rid ) ;
2018-05-16 14:19:45 +02:00
vp - > texture_flags = flags ;
VS : : get_singleton ( ) - > texture_set_flags ( vp - > texture_rid , flags ) ;
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 ) {
2017-01-10 05:04:31 +01:00
2017-03-05 16:44:50 +01:00
if ( path = = p_path )
2017-01-10 05:04:31 +01:00
return ;
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 {
2014-02-10 02:10:30 +01:00
2017-03-05 16:44:50 +01:00
ERR_FAIL_COND_V ( ! vp , 0 ) ;
2016-10-03 21:33:42 +02:00
return vp - > size . width ;
2014-02-10 02:10:30 +01:00
}
2017-03-05 16:44:50 +01:00
int ViewportTexture : : get_height ( ) const {
2014-02-10 02:10:30 +01:00
2017-03-05 16:44:50 +01:00
ERR_FAIL_COND_V ( ! vp , 0 ) ;
2016-10-03 21:33:42 +02:00
return vp - > size . height ;
2014-02-10 02:10:30 +01:00
}
2017-03-05 16:44:50 +01:00
Size2 ViewportTexture : : get_size ( ) const {
2014-02-10 02:10:30 +01:00
2017-03-05 16:44:50 +01:00
ERR_FAIL_COND_V ( ! vp , Size2 ( ) ) ;
2016-10-03 21:33:42 +02:00
return vp - > size ;
2014-02-10 02:10:30 +01:00
}
2017-03-05 16:44:50 +01:00
RID ViewportTexture : : get_rid ( ) const {
2014-02-10 02:10:30 +01:00
2017-12-04 19:55:20 +01:00
//ERR_FAIL_COND_V(!vp, RID());
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 ;
}
2017-06-09 05:23:50 +02:00
Ref < Image > ViewportTexture : : get_data ( ) const {
2014-02-10 02:10:30 +01:00
2017-06-09 05:23:50 +02:00
ERR_FAIL_COND_V ( ! vp , Ref < Image > ( ) ) ;
return VS : : get_singleton ( ) - > texture_get_data ( vp - > texture_rid ) ;
}
2017-03-05 16:44:50 +01:00
void ViewportTexture : : set_flags ( uint32_t p_flags ) {
2018-05-16 14:19:45 +02:00
flags = p_flags ;
2016-10-05 06:26:35 +02:00
if ( ! vp )
return ;
2014-02-10 02:10:30 +01:00
2018-05-16 14:19:45 +02:00
vp - > texture_flags = flags ;
VS : : get_singleton ( ) - > texture_set_flags ( vp - > texture_rid , flags ) ;
2014-02-10 02:10:30 +01:00
}
2014-04-19 21:46:52 +02:00
2017-03-05 16:44:50 +01:00
uint32_t ViewportTexture : : get_flags ( ) const {
2014-02-10 02:10:30 +01:00
2018-05-16 14:19:45 +02:00
return flags ;
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
2019-01-14 19:46:56 +01:00
ADD_PROPERTY ( PropertyInfo ( Variant : : NODE_PATH , " viewport_path " , PROPERTY_HINT_NODE_PATH_VALID_TYPES , " Viewport " , PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_NODE_PATH_FROM_SCENE_ROOT ) , " set_viewport_path_in_scene " , " get_viewport_path_in_scene " ) ;
2017-01-10 05:04:31 +01:00
}
2017-03-05 16:44:50 +01:00
ViewportTexture : : ViewportTexture ( ) {
2017-01-10 05:04:31 +01:00
2017-03-05 16:44:50 +01:00
vp = NULL ;
2018-05-16 14:19:45 +02:00
flags = 0 ;
2017-01-10 05:04:31 +01:00
set_local_to_scene ( true ) ;
2017-12-04 19:55:20 +01:00
proxy = VS : : get_singleton ( ) - > texture_create ( ) ;
2014-02-10 02:10:30 +01:00
}
2017-03-05 16:44:50 +01:00
ViewportTexture : : ~ ViewportTexture ( ) {
2014-02-10 02:10:30 +01:00
2017-01-10 05:04:31 +01:00
if ( vp ) {
vp - > viewport_textures . erase ( this ) ;
}
2017-12-04 19:55:20 +01:00
VS : : get_singleton ( ) - > free ( proxy ) ;
2014-02-10 02:10:30 +01:00
}
2016-01-17 02:41:10 +01:00
/////////////////////////////////////
2018-07-20 23:14:33 +02:00
class TooltipPanel : public PanelContainer {
2016-01-17 02:41:10 +01:00
2018-07-20 23:14:33 +02:00
GDCLASS ( TooltipPanel , PanelContainer )
2016-01-17 02:41:10 +01:00
public :
2017-03-05 16:44:50 +01:00
TooltipPanel ( ) { } ;
2016-01-17 02:41:10 +01:00
} ;
class TooltipLabel : public Label {
2017-03-05 16:44:50 +01:00
GDCLASS ( TooltipLabel , Label )
2016-01-17 02:41:10 +01:00
public :
2017-03-05 16:44:50 +01:00
TooltipLabel ( ) { } ;
2016-01-17 02:41:10 +01:00
} ;
Viewport : : GUI : : GUI ( ) {
2018-08-24 15:29:27 +02:00
dragging = false ;
2017-03-05 16:44:50 +01:00
mouse_focus = NULL ;
2018-03-27 23:41:27 +02:00
mouse_click_grabber = NULL ;
2018-11-28 13:31:17 +01:00
mouse_focus_mask = 0 ;
2017-03-05 16:44:50 +01:00
key_focus = NULL ;
mouse_over = NULL ;
2016-01-17 02:41:10 +01:00
2017-03-05 16:44:50 +01:00
tooltip = NULL ;
tooltip_popup = NULL ;
tooltip_label = NULL ;
2017-12-28 10:01:22 +01:00
subwindow_visibility_dirty = false ;
2017-03-05 16:44:50 +01:00
subwindow_order_dirty = false ;
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_stretch_transform ( ) {
if ( size_override_stretch & & size_override ) {
2017-03-05 16:44:50 +01:00
stretch_transform = Transform2D ( ) ;
Size2 scale = size / ( size_override_size + size_override_margin * 2 ) ;
2014-04-15 03:43:44 +02:00
stretch_transform . scale ( scale ) ;
2017-03-05 16:44:50 +01:00
stretch_transform . elements [ 2 ] = size_override_margin * scale ;
2015-03-22 13:40:26 +01:00
2014-02-10 02:10:30 +01:00
} else {
2017-03-05 16:44:50 +01:00
stretch_transform = Transform2D ( ) ;
2014-02-10 02:10:30 +01:00
}
_update_global_transform ( ) ;
}
void Viewport : : update_worlds ( ) {
2014-11-06 01:20:42 +01:00
if ( ! is_inside_tree ( ) )
2014-02-10 02:10:30 +01:00
return ;
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 ( ) ;
2014-11-06 01:20:42 +01:00
find_world ( ) - > _update ( get_tree ( ) - > get_frame ( ) ) ;
2014-02-10 02:10:30 +01:00
}
2019-03-09 22:03:27 +01:00
void Viewport : : _collision_object_input_event ( CollisionObject * p_object , Camera * 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 ;
}
2014-02-10 02:10:30 +01:00
void Viewport : : _notification ( int p_what ) {
2016-03-09 00:00:52 +01:00
2017-03-05 16:44:50 +01:00
switch ( p_what ) {
2016-03-09 00:00:52 +01:00
2014-11-06 01:20:42 +01:00
case NOTIFICATION_ENTER_TREE : {
2014-02-10 02:10:30 +01:00
2016-01-18 23:49:11 +01:00
if ( get_parent ( ) ) {
2016-10-05 06:26:35 +02:00
parent = get_parent ( ) - > get_viewport ( ) ;
2017-03-05 16:44:50 +01:00
VisualServer : : get_singleton ( ) - > viewport_set_parent_viewport ( viewport , parent - > get_viewport_rid ( ) ) ;
2016-10-05 06:26:35 +02:00
} else {
2017-03-05 16:44:50 +01:00
parent = NULL ;
2014-02-10 02:10:30 +01:00
}
2017-03-05 16:44:50 +01:00
current_canvas = find_world_2d ( ) - > get_canvas ( ) ;
VisualServer : : get_singleton ( ) - > viewport_set_scenario ( viewport , find_world ( ) - > get_scenario ( ) ) ;
VisualServer : : 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
2017-03-05 16:44:50 +01:00
Physics2DServer : : get_singleton ( ) - > space_set_debug_contacts ( find_world_2d ( ) - > get_space ( ) , get_tree ( ) - > get_collision_debug_contact_count ( ) ) ;
contact_2d_debug = VisualServer : : get_singleton ( ) - > canvas_item_create ( ) ;
VisualServer : : get_singleton ( ) - > canvas_item_set_parent ( contact_2d_debug , find_world_2d ( ) - > get_canvas ( ) ) ;
2015-09-20 18:03:46 +02:00
//3D
2017-03-05 16:44:50 +01:00
PhysicsServer : : get_singleton ( ) - > space_set_debug_contacts ( find_world ( ) - > get_space ( ) , get_tree ( ) - > get_collision_debug_contact_count ( ) ) ;
contact_3d_debug_multimesh = VisualServer : : get_singleton ( ) - > multimesh_create ( ) ;
VisualServer : : get_singleton ( ) - > multimesh_allocate ( contact_3d_debug_multimesh , get_tree ( ) - > get_collision_debug_contact_count ( ) , VS : : MULTIMESH_TRANSFORM_3D , VS : : MULTIMESH_COLOR_8BIT ) ;
VisualServer : : get_singleton ( ) - > multimesh_set_visible_instances ( contact_3d_debug_multimesh , 0 ) ;
VisualServer : : get_singleton ( ) - > multimesh_set_mesh ( contact_3d_debug_multimesh , get_tree ( ) - > get_debug_contact_mesh ( ) - > get_rid ( ) ) ;
contact_3d_debug_instance = VisualServer : : get_singleton ( ) - > instance_create ( ) ;
VisualServer : : get_singleton ( ) - > instance_set_base ( contact_3d_debug_instance , contact_3d_debug_multimesh ) ;
VisualServer : : get_singleton ( ) - > instance_set_scenario ( contact_3d_debug_instance , find_world ( ) - > get_scenario ( ) ) ;
2017-08-26 05:40:45 +02:00
//VisualServer::get_singleton()->instance_geometry_set_flag(contact_3d_debug_instance, VS::INSTANCE_FLAG_VISIBLE_IN_ALL_ROOMS, true);
2015-09-20 18:03:46 +02:00
}
2014-02-10 02:10:30 +01:00
2017-03-05 16:44:50 +01:00
VS : : get_singleton ( ) - > viewport_set_active ( viewport , true ) ;
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 ) {
2017-03-05 16:44:50 +01:00
Listener * first = NULL ;
for ( Set < Listener * > : : Element * E = listeners . front ( ) ; E ; E = E - > next ( ) ) {
2016-03-20 03:10:04 +01:00
2017-03-05 16:44:50 +01:00
if ( first = = NULL | | first - > is_greater_than ( E - > get ( ) ) ) {
first = E - > get ( ) ;
2016-03-20 03:10:04 +01:00
}
}
if ( first )
first - > make_current ( ) ;
}
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
2017-03-05 16:44:50 +01:00
Camera * first = NULL ;
for ( Set < Camera * > : : Element * E = cameras . front ( ) ; E ; E = E - > next ( ) ) {
2014-02-10 02:10:30 +01:00
2017-03-05 16:44:50 +01:00
if ( first = = NULL | | first - > is_greater_than ( E - > get ( ) ) ) {
first = E - > get ( ) ;
2014-02-10 02:10:30 +01:00
}
}
if ( first )
first - > make_current ( ) ;
}
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 : {
2014-02-10 02:10:30 +01:00
2016-01-25 14:30:03 +01:00
_gui_cancel_tooltip ( ) ;
2014-02-10 02:10:30 +01:00
if ( world_2d . is_valid ( ) )
world_2d - > _remove_viewport ( this ) ;
2017-03-05 16:44:50 +01:00
VisualServer : : get_singleton ( ) - > viewport_set_scenario ( viewport , RID ( ) ) ;
// SpatialSoundServer::get_singleton()->listener_set_space(internal_listener, RID());
VisualServer : : get_singleton ( ) - > viewport_remove_canvas ( viewport , current_canvas ) ;
2015-09-20 18:03:46 +02:00
if ( contact_2d_debug . is_valid ( ) ) {
VisualServer : : 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 ( ) ) {
VisualServer : : get_singleton ( ) - > free ( contact_3d_debug_multimesh ) ;
VisualServer : : 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
2017-03-05 16:44:50 +01:00
VS : : get_singleton ( ) - > viewport_set_active ( viewport , false ) ;
2014-02-10 02:10:30 +01:00
} break ;
2018-03-01 14:44:45 +01:00
case NOTIFICATION_INTERNAL_PROCESS : {
2014-09-15 16:33:30 +02:00
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 ( ) ) {
VisualServer : : get_singleton ( ) - > canvas_item_clear ( contact_2d_debug ) ;
2017-03-05 16:44:50 +01:00
VisualServer : : get_singleton ( ) - > canvas_item_set_draw_index ( contact_2d_debug , 0xFFFFF ) ; //very high index
2015-09-20 18:03:46 +02:00
Vector < Vector2 > points = Physics2DServer : : get_singleton ( ) - > space_get_contacts ( find_world_2d ( ) - > get_space ( ) ) ;
int point_count = Physics2DServer : : get_singleton ( ) - > space_get_contact_count ( find_world_2d ( ) - > get_space ( ) ) ;
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 + + ) {
2015-09-20 18:03:46 +02:00
2017-03-05 16:44:50 +01:00
VisualServer : : 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 ( ) ) {
Vector < Vector3 > points = PhysicsServer : : get_singleton ( ) - > space_get_contacts ( find_world ( ) - > get_space ( ) ) ;
int point_count = PhysicsServer : : get_singleton ( ) - > space_get_contact_count ( find_world ( ) - > get_space ( ) ) ;
2017-03-05 16:44:50 +01:00
VS : : get_singleton ( ) - > multimesh_set_visible_instances ( contact_3d_debug_multimesh , point_count ) ;
2015-09-20 18:03:46 +02:00
}
2017-03-05 16:44:50 +01:00
if ( physics_object_picking & & ( to_screen_rect = = Rect2 ( ) | | Input : : get_singleton ( ) - > get_mouse_mode ( ) ! = Input : : MOUSE_MODE_CAPTURED ) ) {
2015-09-20 18:03:46 +02:00
2019-04-20 11:07:58 +02:00
# ifndef _3D_DISABLED
2017-03-05 16:44:50 +01:00
Vector2 last_pos ( 1e20 , 1e20 ) ;
2017-09-01 22:33:39 +02:00
CollisionObject * last_object = NULL ;
2017-03-05 16:44:50 +01:00
ObjectID last_id = 0 ;
2019-04-20 11:07:58 +02:00
# endif
2014-09-15 16:33:30 +02:00
PhysicsDirectSpaceState : : RayResult result ;
2017-03-05 16:44:50 +01:00
Physics2DDirectSpaceState * ss2d = Physics2DServer : : 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 ;
2018-11-15 17:54:26 +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 ( ) ;
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 ( ) ) {
2014-09-15 16:33:30 +02:00
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 ( ) ) {
2019-03-05 22:31:02 +01:00
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 ( ) ;
Physics2DDirectSpaceState : : 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 ( ) ;
canvas_layer_id = 0 ;
}
Vector2 point = canvas_transform . affine_inverse ( ) . xform ( pos ) ;
int rc = ss2d - > intersect_point_on_canvas ( point , canvas_layer_id , res , 64 , Set < RID > ( ) , 0xFFFFFFFF , true , true , true ) ;
for ( int i = 0 ; i < rc ; i + + ) {
if ( res [ i ] . collider_id & & res [ i ] . collider ) {
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 ) {
F = physics_2d_mouseover . insert ( res [ i ] . collider_id , frame ) ;
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 ) {
2015-03-22 05:46:18 +01:00
2019-03-05 22:31:02 +01:00
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
2017-03-05 16:44:50 +01:00
if ( physics_object_capture ! = 0 ) {
2014-09-15 16:33:30 +02:00
2017-08-24 22:58:51 +02:00
CollisionObject * co = Object : : cast_to < CollisionObject > ( ObjectDB : : get_instance ( physics_object_capture ) ) ;
if ( co ) {
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 ( ) ) {
2017-03-05 16:44:50 +01:00
physics_object_capture = 0 ;
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 {
2017-03-05 16:44:50 +01:00
physics_object_capture = 0 ;
2014-09-15 16:33:30 +02:00
}
}
if ( captured ) {
//none
2017-03-05 16:44:50 +01:00
} else if ( pos = = last_pos ) {
2014-09-15 16:33:30 +02:00
if ( last_id ) {
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 ) ;
PhysicsDirectSpaceState * space = PhysicsServer : : get_singleton ( ) - > space_get_direct_state ( find_world ( ) - > get_space ( ) ) ;
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 ) ;
2017-03-05 16:44:50 +01:00
ObjectID new_collider = 0 ;
2014-09-15 16:33:30 +02:00
if ( col ) {
2014-10-03 05:10:51 +02:00
2017-08-24 22:58:51 +02:00
CollisionObject * co = Object : : cast_to < CollisionObject > ( result . collider ) ;
if ( co ) {
2014-10-03 05:10:51 +02:00
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 ) {
2014-09-15 16:33:30 +02:00
2019-03-05 22:31:02 +01:00
if ( physics_object_over ) {
2014-09-15 16:33:30 +02:00
2019-03-05 22:31:02 +01:00
CollisionObject * co = Object : : cast_to < CollisionObject > ( ObjectDB : : get_instance ( physics_object_over ) ) ;
if ( co ) {
co - > _mouse_exit ( ) ;
}
}
2014-09-15 16:33:30 +02:00
2019-03-05 22:31:02 +01:00
if ( new_collider ) {
2014-09-15 16:33:30 +02:00
2019-03-05 22:31:02 +01:00
CollisionObject * co = Object : : cast_to < CollisionObject > ( ObjectDB : : get_instance ( new_collider ) ) ;
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 ;
2019-03-11 01:18:21 +01:00
case SceneTree : : NOTIFICATION_WM_MOUSE_EXIT :
2018-01-05 19:39:10 +01:00
case SceneTree : : NOTIFICATION_WM_FOCUS_OUT : {
2019-03-11 01:18:21 +01:00
_drop_physics_mouseover ( ) ;
2018-01-05 19:39:10 +01:00
if ( gui . mouse_focus ) {
//if mouse is being pressed, send a release event
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
}
2017-04-23 14:10:41 +02:00
void Viewport : : set_use_arvr ( bool p_use_arvr ) {
arvr = p_use_arvr ;
VS : : get_singleton ( ) - > viewport_set_use_arvr ( viewport , arvr ) ;
}
bool Viewport : : use_arvr ( ) {
return arvr ;
}
2019-01-26 18:56:22 +01:00
void Viewport : : update_canvas_items ( ) {
if ( ! is_inside_tree ( ) )
return ;
_update_canvas_items ( this ) ;
}
2016-10-03 21:33:42 +02:00
void Viewport : : set_size ( const Size2 & p_size ) {
2014-02-10 02:10:30 +01:00
2017-03-05 16:44:50 +01:00
if ( size = = p_size . floor ( ) )
2014-02-10 02:10:30 +01:00
return ;
2017-03-05 16:44:50 +01:00
size = p_size . floor ( ) ;
VS : : get_singleton ( ) - > viewport_set_size ( viewport , size . width , size . height ) ;
2014-10-28 02:54:32 +01:00
2014-02-10 02:10:30 +01:00
_update_stretch_transform ( ) ;
2016-10-03 21:33:42 +02:00
emit_signal ( " size_changed " ) ;
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 ( ) ) {
2018-10-17 08:46:50 +02:00
r = Rect2 ( Point2 ( ) , OS : : get_singleton ( ) - > get_window_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
}
if ( size_override ) {
2017-03-05 16:44:50 +01:00
r . size = size_override_size ;
2014-02-10 02:10:30 +01:00
}
return r ;
}
2016-10-03 21:33:42 +02:00
Size2 Viewport : : get_size ( ) const {
2016-03-09 00:00:52 +01:00
2016-10-03 21:33:42 +02:00
return size ;
2014-02-10 02:10:30 +01:00
}
void Viewport : : _update_listener ( ) {
2017-03-05 16:44:50 +01:00
/*
2017-08-24 22:58:51 +02:00
if ( is_inside_tree ( ) & & audio_listener & & ( camera | | 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
SpatialSoundServer : : get_singleton ( ) - > listener_set_space ( internal_listener , find_world ( ) - > get_sound_space ( ) ) ;
2014-02-10 02:10:30 +01:00
} else {
2016-03-20 03:10:04 +01:00
SpatialSoundServer : : get_singleton ( ) - > listener_set_space ( internal_listener , RID ( ) ) ;
2014-02-10 02:10:30 +01:00
}
2017-01-15 20:06:14 +01:00
*/
2014-02-10 02:10:30 +01:00
}
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 ) {
2017-03-05 16:44:50 +01:00
if ( p_enable = = audio_listener )
2014-02-10 02:10:30 +01:00
return ;
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 ) {
2017-03-05 16:44:50 +01:00
if ( p_enable = = audio_listener_2d )
2014-02-10 02:10:30 +01:00
return ;
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
}
2017-03-05 16:44:50 +01:00
void Viewport : : set_canvas_transform ( const Transform2D & p_transform ) {
2014-02-10 02:10:30 +01:00
2017-03-05 16:44:50 +01:00
canvas_transform = p_transform ;
VisualServer : : get_singleton ( ) - > viewport_set_canvas_transform ( viewport , find_world_2d ( ) - > get_canvas ( ) , canvas_transform ) ;
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
2017-03-05 16:44:50 +01:00
VisualServer : : 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 ) {
2014-02-10 02:10:30 +01:00
2017-03-05 16:44:50 +01:00
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 ( ) {
# ifndef _3D_DISABLED
2017-03-05 16:44:50 +01:00
//if (listener)
2017-01-15 20:06:14 +01:00
// SpatialSoundServer::get_singleton()->listener_set_transform(internal_listener, listener->get_listener_transform());
2016-03-20 03:10:04 +01:00
# endif
}
2017-03-05 16:44:50 +01:00
void Viewport : : _listener_set ( Listener * p_listener ) {
2016-03-20 03:10:04 +01:00
# ifndef _3D_DISABLED
if ( listener = = p_listener )
return ;
listener = p_listener ;
_update_listener ( ) ;
_listener_transform_changed_notify ( ) ;
# endif
}
2017-03-05 16:44:50 +01:00
bool Viewport : : _listener_add ( Listener * p_listener ) {
2016-03-20 03:10:04 +01:00
listeners . insert ( p_listener ) ;
return listeners . size ( ) = = 1 ;
}
2017-03-05 16:44:50 +01:00
void Viewport : : _listener_remove ( Listener * p_listener ) {
2016-03-20 03:10:04 +01:00
listeners . erase ( p_listener ) ;
if ( listener = = p_listener ) {
listener = NULL ;
}
}
# ifndef _3D_DISABLED
2017-03-05 16:44:50 +01:00
void Viewport : : _listener_make_next_current ( Listener * p_exclude ) {
2016-03-20 03:10:04 +01:00
if ( listeners . size ( ) > 0 ) {
2017-03-05 16:44:50 +01:00
for ( Set < Listener * > : : Element * E = listeners . front ( ) ; E ; E = E - > next ( ) ) {
2016-03-20 03:10:04 +01:00
if ( p_exclude = = E - > get ( ) )
continue ;
if ( ! E - > get ( ) - > is_inside_tree ( ) )
continue ;
if ( listener ! = NULL )
return ;
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
if ( camera ! = NULL ) {
_update_listener ( ) ;
_camera_transform_changed_notify ( ) ;
}
}
}
# endif
2014-02-10 02:10:30 +01:00
void Viewport : : _camera_transform_changed_notify ( ) {
# ifndef _3D_DISABLED
2017-03-05 16:44:50 +01:00
// If there is an active listener in the scene, it takes priority over the camera
2017-01-15 20:06:14 +01:00
// if (camera && !listener)
// SpatialSoundServer::get_singleton()->listener_set_transform(internal_listener, camera->get_camera_transform());
2014-02-10 02:10:30 +01:00
# endif
}
2017-03-05 16:44:50 +01:00
void Viewport : : _camera_set ( Camera * p_camera ) {
2014-02-10 02:10:30 +01:00
# ifndef _3D_DISABLED
2017-03-05 16:44:50 +01:00
if ( camera = = p_camera )
2014-02-10 02:10:30 +01:00
return ;
2019-03-10 04:59:52 +01:00
if ( camera ) {
2014-02-10 02:10:30 +01:00
camera - > notification ( Camera : : NOTIFICATION_LOST_CURRENT ) ;
}
2017-03-05 16:44:50 +01:00
camera = p_camera ;
2014-02-10 02:10:30 +01:00
if ( camera )
2017-03-05 16:44:50 +01:00
VisualServer : : get_singleton ( ) - > viewport_attach_camera ( viewport , camera - > get_camera ( ) ) ;
2014-02-10 02:10:30 +01:00
else
2017-03-05 16:44:50 +01:00
VisualServer : : get_singleton ( ) - > viewport_attach_camera ( viewport , RID ( ) ) ;
2014-02-10 02:10:30 +01:00
2019-03-10 04:59:52 +01:00
if ( camera ) {
2014-02-10 02:10:30 +01:00
camera - > notification ( Camera : : NOTIFICATION_BECAME_CURRENT ) ;
}
_update_listener ( ) ;
_camera_transform_changed_notify ( ) ;
# endif
}
2017-03-05 16:44:50 +01:00
bool Viewport : : _camera_add ( Camera * 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
}
2017-03-05 16:44:50 +01:00
void Viewport : : _camera_remove ( Camera * 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 ) {
2019-03-10 04:59:52 +01:00
camera - > notification ( Camera : : NOTIFICATION_LOST_CURRENT ) ;
2017-03-05 16:44:50 +01:00
camera = NULL ;
2016-01-31 19:09:52 +01:00
}
}
2016-03-11 03:01:56 +01:00
# ifndef _3D_DISABLED
2017-03-05 16:44:50 +01:00
void Viewport : : _camera_make_next_current ( Camera * p_exclude ) {
2016-01-31 19:09:52 +01:00
2017-03-05 16:44:50 +01:00
for ( Set < Camera * > : : Element * E = cameras . front ( ) ; E ; E = E - > next ( ) ) {
2016-01-31 19:09:52 +01:00
2017-03-05 16:44:50 +01:00
if ( p_exclude = = E - > get ( ) )
2016-01-31 19:09:52 +01:00
continue ;
if ( ! E - > get ( ) - > is_inside_tree ( ) )
continue ;
2017-03-05 16:44:50 +01:00
if ( camera ! = NULL )
2016-01-31 19:09:52 +01:00
return ;
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 ;
VS : : 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 ) {
if ( world_2d = = p_world_2d )
2016-07-13 20:51:38 +02:00
return ;
2017-03-05 16:44:50 +01:00
if ( parent & & parent - > find_world_2d ( ) = = p_world_2d ) {
2016-07-13 20:51:38 +02:00
WARN_PRINT ( " Unable to use parent world as world_2d " ) ;
return ;
}
if ( is_inside_tree ( ) ) {
find_world_2d ( ) - > _remove_viewport ( this ) ;
2017-03-05 16:44:50 +01:00
VisualServer : : get_singleton ( ) - > viewport_remove_canvas ( viewport , current_canvas ) ;
2016-07-13 20:51:38 +02:00
}
if ( p_world_2d . is_valid ( ) )
2017-03-05 16:44:50 +01:00
world_2d = p_world_2d ;
2016-07-13 20:51:38 +02:00
else {
WARN_PRINT ( " Invalid world " ) ;
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 ( ) ;
VisualServer : : get_singleton ( ) - > viewport_attach_canvas ( viewport , current_canvas ) ;
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 {
2014-02-10 02:10:30 +01:00
if ( world_2d . is_valid ( ) )
return world_2d ;
else if ( parent )
return parent - > find_world_2d ( ) ;
else
return Ref < World2D > ( ) ;
}
void Viewport : : _propagate_enter_world ( Node * p_node ) {
2017-03-05 16:44:50 +01:00
if ( p_node ! = this ) {
2014-02-10 02:10:30 +01:00
2014-11-06 01:20:42 +01:00
if ( ! p_node - > is_inside_tree ( ) ) //may not have entered scene yet
2014-02-10 02:10:30 +01:00
return ;
2017-08-24 22:58:51 +02:00
if ( Object : : cast_to < Spatial > ( p_node ) | | Object : : cast_to < WorldEnvironment > ( p_node ) ) {
2014-02-10 02:10:30 +01:00
2017-06-24 13:58:27 +02:00
p_node - > notification ( Spatial : : NOTIFICATION_ENTER_WORLD ) ;
2014-02-10 02:10:30 +01:00
} else {
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 ) {
2019-03-10 04:59:52 +01:00
if ( v - > world . is_valid ( ) | | v - > own_world . is_valid ( ) )
2014-02-10 02:10:30 +01:00
return ;
}
}
}
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 ) ;
2017-08-24 22:58:51 +02:00
if ( Object : : cast_to < Viewport > ( c ) )
2016-05-11 16:46:08 +02:00
continue ;
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 ) {
2014-02-10 02:10:30 +01:00
2014-11-06 01:20:42 +01:00
if ( ! p_node - > is_inside_tree ( ) ) //may have exited scene already
2014-02-10 02:10:30 +01:00
return ;
2017-08-24 22:58:51 +02:00
if ( Object : : cast_to < Spatial > ( p_node ) | | Object : : cast_to < WorldEnvironment > ( p_node ) ) {
2014-02-10 02:10:30 +01:00
2017-06-24 13:58:27 +02:00
p_node - > notification ( Spatial : : NOTIFICATION_EXIT_WORLD ) ;
2014-02-10 02:10:30 +01:00
} else {
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 ) {
2019-03-10 04:59:52 +01:00
if ( v - > world . is_valid ( ) | | v - > own_world . is_valid ( ) )
2014-02-10 02:10:30 +01:00
return ;
}
}
}
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 ) ) ;
}
}
2017-03-05 16:44:50 +01:00
void Viewport : : set_world ( const Ref < World > & p_world ) {
2014-02-10 02:10:30 +01:00
2017-03-05 16:44:50 +01:00
if ( world = = p_world )
2014-02-10 02:10:30 +01:00
return ;
2014-11-06 01:20:42 +01:00
if ( is_inside_tree ( ) )
2014-02-10 02:10:30 +01:00
_propagate_exit_world ( this ) ;
2017-03-05 16:44:50 +01:00
world = p_world ;
2014-02-10 02:10:30 +01:00
2014-11-06 01:20:42 +01:00
if ( is_inside_tree ( ) )
2014-02-10 02:10:30 +01:00
_propagate_enter_world ( this ) ;
2014-11-06 01:20:42 +01:00
if ( is_inside_tree ( ) ) {
2017-03-05 16:44:50 +01:00
VisualServer : : get_singleton ( ) - > viewport_set_scenario ( viewport , find_world ( ) - > get_scenario ( ) ) ;
2014-02-10 02:10:30 +01:00
}
_update_listener ( ) ;
}
2017-03-05 16:44:50 +01:00
Ref < World > Viewport : : get_world ( ) const {
2014-02-10 02:10:30 +01:00
return world ;
}
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 ;
}
2017-03-05 16:44:50 +01:00
Ref < World > Viewport : : find_world ( ) const {
2014-02-10 02:10:30 +01:00
2014-04-15 03:43:44 +02:00
if ( own_world . is_valid ( ) )
return own_world ;
else if ( world . is_valid ( ) )
2014-02-10 02:10:30 +01:00
return world ;
else if ( parent )
return parent - > find_world ( ) ;
else
return Ref < World > ( ) ;
}
2017-03-05 16:44:50 +01:00
Listener * Viewport : : get_listener ( ) const {
2016-03-20 03:10:04 +01:00
return listener ;
}
2017-03-05 16:44:50 +01:00
Camera * Viewport : : get_camera ( ) const {
2014-02-10 02:10:30 +01:00
return camera ;
}
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 ) ;
if ( vp )
return ;
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 ) ) ;
}
}
2017-03-05 16:44:50 +01:00
void Viewport : : set_size_override ( bool p_enable , const Size2 & p_size , const Vector2 & p_margin ) {
2014-02-10 02:10:30 +01:00
2017-03-05 16:44:50 +01:00
if ( size_override = = p_enable & & p_size = = size_override_size )
2014-02-10 02:10:30 +01:00
return ;
2017-03-05 16:44:50 +01:00
size_override = p_enable ;
if ( p_size . x > = 0 | | p_size . y > = 0 ) {
size_override_size = p_size ;
2014-02-10 02:10:30 +01:00
}
2017-03-05 16:44:50 +01:00
size_override_margin = p_margin ;
2018-01-18 22:37:45 +01:00
2014-02-10 02:10:30 +01:00
_update_stretch_transform ( ) ;
2017-06-12 21:18:17 +02:00
emit_signal ( " size_changed " ) ;
2014-02-10 02:10:30 +01:00
}
Size2 Viewport : : get_size_override ( ) const {
return size_override_size ;
}
bool Viewport : : is_size_override_enabled ( ) const {
return size_override ;
}
void Viewport : : set_size_override_stretch ( bool p_enable ) {
2017-03-05 16:44:50 +01:00
if ( p_enable = = size_override_stretch )
2014-02-10 02:10:30 +01:00
return ;
2017-03-05 16:44:50 +01:00
size_override_stretch = p_enable ;
2014-02-10 02:10:30 +01:00
_update_stretch_transform ( ) ;
}
bool Viewport : : is_size_override_stretch_enabled ( ) const {
2016-06-10 03:30:34 +02:00
return size_override_stretch ;
2014-02-10 02:10:30 +01:00
}
2017-03-05 16:44:50 +01:00
void Viewport : : set_update_mode ( UpdateMode p_mode ) {
2014-02-10 02:10:30 +01:00
2017-03-05 16:44:50 +01:00
update_mode = p_mode ;
VS : : get_singleton ( ) - > viewport_set_update_mode ( viewport , VS : : ViewportUpdateMode ( p_mode ) ) ;
2014-02-10 02:10:30 +01:00
}
2017-03-05 16:44:50 +01:00
Viewport : : UpdateMode Viewport : : get_update_mode ( ) const {
2014-02-10 02:10:30 +01:00
2016-10-03 21:33:42 +02:00
return update_mode ;
2014-02-10 02:10:30 +01:00
}
2016-10-05 06:26:35 +02:00
Ref < ViewportTexture > Viewport : : get_texture ( ) const {
2014-02-10 02:10:30 +01:00
2017-01-10 22:02:19 +01:00
return default_texture ;
2014-02-10 02:10:30 +01:00
}
2016-10-03 21:33:42 +02:00
void Viewport : : set_vflip ( bool p_enable ) {
2014-04-10 05:18:27 +02:00
2017-03-05 16:44:50 +01:00
vflip = p_enable ;
VisualServer : : get_singleton ( ) - > viewport_set_vflip ( viewport , p_enable ) ;
2014-04-10 05:18:27 +02:00
}
2017-03-05 16:44:50 +01:00
bool Viewport : : get_vflip ( ) const {
2014-04-10 05:18:27 +02:00
2016-10-03 21:33:42 +02:00
return vflip ;
2014-04-10 05:18:27 +02:00
}
2017-08-31 16:01:36 +02:00
void Viewport : : set_clear_mode ( ClearMode p_mode ) {
2015-02-21 10:35:06 +01:00
2017-08-31 16:01:36 +02:00
clear_mode = p_mode ;
VS : : get_singleton ( ) - > viewport_set_clear_mode ( viewport , VS : : ViewportClearMode ( p_mode ) ) ;
2015-02-21 10:35:06 +01:00
}
2017-08-31 16:01:36 +02:00
Viewport : : ClearMode Viewport : : get_clear_mode ( ) const {
2015-02-21 10:35:06 +01:00
2017-08-31 16:01:36 +02:00
return clear_mode ;
2015-02-21 10:35:06 +01:00
}
2016-11-10 03:55:06 +01:00
void Viewport : : set_shadow_atlas_size ( int p_size ) {
2017-03-05 16:44:50 +01:00
if ( shadow_atlas_size = = p_size )
2016-12-22 14:00:15 +01:00
return ;
2015-02-21 10:35:06 +01:00
2017-03-05 16:44:50 +01:00
shadow_atlas_size = p_size ;
VS : : 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 {
2014-05-14 06:22:15 +02:00
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 ) {
2014-05-14 06:22:15 +02:00
2017-03-05 16:44:50 +01:00
ERR_FAIL_INDEX ( p_quadrant , 4 ) ;
ERR_FAIL_INDEX ( p_subdiv , SHADOW_ATLAS_QUADRANT_SUBDIV_MAX ) ;
2014-05-14 06:22:15 +02:00
2017-03-05 16:44:50 +01:00
if ( shadow_atlas_quadrant_subdiv [ p_quadrant ] = = p_subdiv )
2016-11-10 03:55:06 +01:00
return ;
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
2017-03-05 16:44:50 +01:00
VS : : get_singleton ( ) - > viewport_set_shadow_atlas_quadrant_subdivision ( viewport , p_quadrant , subdiv [ p_subdiv ] ) ;
2014-08-14 15:31:38 +02:00
}
2017-03-05 16:44:50 +01:00
Viewport : : ShadowAtlasQuadrantSubdiv Viewport : : get_shadow_atlas_quadrant_subdiv ( int p_quadrant ) const {
2016-11-10 03:55:06 +01:00
2017-03-05 16:44:50 +01:00
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 {
2014-04-18 16:43:54 +02:00
2017-01-11 04:52:51 +01:00
Transform2D pre_xf ;
2014-04-18 16:43:54 +02:00
2017-03-05 16:44:50 +01:00
if ( to_screen_rect ! = Rect2 ( ) ) {
2015-03-22 13:40:26 +01:00
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 ;
}
2016-09-10 18:29:07 +02:00
Vector2 Viewport : : _get_window_offset ( ) const {
2017-12-09 22:15:57 +01:00
if ( get_parent ( ) & & get_parent ( ) - > has_method ( " get_global_position " ) ) {
return get_parent ( ) - > call ( " get_global_position " ) ;
2017-01-14 12:26:56 +01:00
}
2016-09-10 18:29:07 +02:00
return Vector2 ( ) ;
}
2017-05-20 17:38:03 +02:00
Ref < InputEvent > Viewport : : _make_input_local ( const Ref < InputEvent > & ev ) {
2014-04-10 05:18:27 +02:00
2017-05-20 17:38:03 +02:00
Vector2 vp_ofs = _get_window_offset ( ) ;
Transform2D ai = get_final_transform ( ) . affine_inverse ( ) * _get_input_pre_xform ( ) ;
2014-04-10 05:18:27 +02:00
2017-05-20 17:38:03 +02:00
return ev - > xformed_by ( ai , - vp_ofs ) ;
2014-04-10 05:18:27 +02:00
}
2017-03-05 16:44:50 +01:00
void Viewport : : _vp_input_text ( const String & p_text ) {
2016-01-17 02:41:10 +01:00
if ( gui . key_focus ) {
2017-03-05 16:44:50 +01:00
gui . key_focus - > call ( " set_text " , p_text ) ;
2016-01-17 02:41:10 +01:00
}
}
2014-04-10 05:18:27 +02:00
2017-05-20 17:38:03 +02:00
void Viewport : : _vp_input ( const Ref < InputEvent > & p_ev ) {
2014-04-10 05:18:27 +02:00
2016-01-17 02:41:10 +01:00
if ( disable_input )
return ;
2016-01-19 10:45:12 +01:00
# ifdef TOOLS_ENABLED
2017-08-19 01:02:56 +02: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 ) ) {
2016-01-18 23:49:11 +01:00
return ;
}
2016-01-19 10:45:12 +01:00
# endif
2016-01-18 23:49:11 +01:00
2017-03-05 16:44:50 +01:00
if ( to_screen_rect = = Rect2 ( ) )
2014-04-10 05:18:27 +02:00
return ; //if render target, can't get input events
//this one handles system input, p_ev are in system coordinates
//they are converted to viewport coordinates
2017-05-20 17:38:03 +02:00
Ref < InputEvent > ev = _make_input_local ( p_ev ) ;
2014-04-10 05:18:27 +02:00
input ( ev ) ;
}
2017-05-20 17:38:03 +02:00
void Viewport : : _vp_unhandled_input ( const Ref < InputEvent > & p_ev ) {
2014-04-10 05:18:27 +02:00
2016-01-18 23:49:11 +01:00
if ( disable_input )
return ;
2016-01-19 10:45:12 +01:00
# ifdef TOOLS_ENABLED
2017-08-19 01:02:56 +02: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 ) ) {
2016-01-18 23:49:11 +01:00
return ;
}
2016-01-19 10:45:12 +01:00
# endif
2016-01-18 23:49:11 +01:00
2017-01-14 12:26:56 +01:00
/*
if ( parent_control & & ! parent_control - > is_visible_in_tree ( ) )
return ;
*/
2014-09-15 16:33:30 +02:00
2017-03-05 16:44:50 +01:00
if ( to_screen_rect = = Rect2 ( ) )
2014-04-10 05:18:27 +02:00
return ; //if render target, can't get input events
//this one handles system input, p_ev are in system coordinates
//they are converted to viewport coordinates
2017-05-20 17:38:03 +02:00
Ref < InputEvent > ev = _make_input_local ( p_ev ) ;
2014-04-10 05:18:27 +02:00
unhandled_input ( ev ) ;
}
2017-03-29 17:29:38 +02:00
Vector2 Viewport : : get_mouse_position ( ) const {
2015-05-12 13:17:09 +02:00
2017-03-29 17:29:38 +02:00
return ( get_final_transform ( ) . affine_inverse ( ) * _get_input_pre_xform ( ) ) . xform ( Input : : get_singleton ( ) - > get_mouse_position ( ) - _get_window_offset ( ) ) ;
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 ) ;
2017-09-10 15:37:49 +02:00
Input : : get_singleton ( ) - > warp_mouse_position ( gpos ) ;
2015-02-14 23:22:06 +01:00
}
2017-12-28 10:01:22 +01:00
void Viewport : : _gui_prepare_subwindows ( ) {
if ( gui . subwindow_visibility_dirty ) {
gui . subwindows . clear ( ) ;
for ( List < Control * > : : Element * E = gui . all_known_subwindows . front ( ) ; E ; E = E - > next ( ) ) {
if ( E - > get ( ) - > is_visible_in_tree ( ) ) {
gui . subwindows . push_back ( E - > get ( ) ) ;
}
}
gui . subwindow_visibility_dirty = false ;
gui . subwindow_order_dirty = true ;
}
_gui_sort_subwindows ( ) ;
}
2016-01-17 02:41:10 +01:00
void Viewport : : _gui_sort_subwindows ( ) {
if ( ! gui . subwindow_order_dirty )
return ;
gui . modal_stack . sort_custom < Control : : CComparator > ( ) ;
gui . subwindows . sort_custom < Control : : CComparator > ( ) ;
2017-03-05 16:44:50 +01:00
gui . subwindow_order_dirty = false ;
2016-01-17 02:41:10 +01:00
}
void Viewport : : _gui_sort_modal_stack ( ) {
gui . modal_stack . sort_custom < Control : : CComparator > ( ) ;
}
void Viewport : : _gui_sort_roots ( ) {
if ( ! gui . roots_order_dirty )
return ;
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 ( ) {
2017-03-05 16:44:50 +01:00
gui . tooltip = NULL ;
gui . tooltip_timer = - 1 ;
2016-01-25 14:30:03 +01:00
if ( gui . tooltip_popup ) {
gui . tooltip_popup - > queue_delete ( ) ;
2017-03-05 16:44:50 +01:00
gui . tooltip_popup = NULL ;
2018-07-20 23:14:33 +02:00
gui . tooltip_label = NULL ;
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 ;
}
2018-06-07 17:46:14 +02:00
if ( tooltip ! = String ( ) )
break ;
pos = p_control - > get_transform ( ) . xform ( pos ) ;
if ( p_control - > data . mouse_filter = = Control : : MOUSE_FILTER_STOP )
break ;
if ( p_control - > is_set_as_toplevel ( ) )
break ;
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 ;
}
2018-07-20 23:14:33 +02:00
Control * which = NULL ;
String tooltip = _gui_get_tooltip ( gui . tooltip , gui . tooltip - > get_global_transform ( ) . xform_inv ( gui . tooltip_pos ) , & which ) ;
2017-03-05 16:44:50 +01:00
if ( tooltip . length ( ) = = 0 )
2016-01-17 02:41:10 +01:00
return ; // bye
2016-01-25 14:30:03 +01:00
if ( gui . tooltip_popup ) {
memdelete ( gui . tooltip_popup ) ;
2017-03-05 16:44:50 +01:00
gui . tooltip_popup = NULL ;
2018-07-20 23:14:33 +02:00
gui . tooltip_label = NULL ;
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 ;
}
2018-07-20 23:14:33 +02:00
Control * rp = which ; //->get_root_parent_control();
2016-01-25 14:30:03 +01:00
if ( ! rp )
2016-01-17 02:41:10 +01:00
return ;
2016-01-25 14:30:03 +01:00
2018-07-20 23:14:33 +02:00
gui . tooltip_popup = which - > make_custom_tooltip ( tooltip ) ;
if ( ! gui . tooltip_popup ) {
gui . tooltip_popup = memnew ( TooltipPanel ) ;
gui . tooltip_label = memnew ( TooltipLabel ) ;
gui . tooltip_popup - > add_child ( gui . tooltip_label ) ;
Ref < StyleBox > ttp = gui . tooltip_label - > get_stylebox ( " panel " , " TooltipPanel " ) ;
gui . tooltip_label - > set_anchor_and_margin ( MARGIN_LEFT , Control : : ANCHOR_BEGIN , ttp - > get_margin ( MARGIN_LEFT ) ) ;
gui . tooltip_label - > set_anchor_and_margin ( MARGIN_TOP , Control : : ANCHOR_BEGIN , ttp - > get_margin ( MARGIN_TOP ) ) ;
gui . tooltip_label - > set_anchor_and_margin ( MARGIN_RIGHT , Control : : ANCHOR_END , - ttp - > get_margin ( MARGIN_RIGHT ) ) ;
gui . tooltip_label - > set_anchor_and_margin ( MARGIN_BOTTOM , Control : : ANCHOR_END , - ttp - > get_margin ( MARGIN_BOTTOM ) ) ;
gui . tooltip_label - > set_text ( tooltip . strip_edges ( ) ) ;
}
2016-01-25 14:30:03 +01:00
rp - > add_child ( gui . tooltip_popup ) ;
gui . tooltip_popup - > force_parent_owned ( ) ;
gui . tooltip_popup - > set_as_toplevel ( true ) ;
2018-07-20 23:14:33 +02:00
//gui.tooltip_popup->hide();
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 " ) ;
Rect2 r ( gui . tooltip_pos + tooltip_offset , gui . tooltip_popup - > get_minimum_size ( ) ) ;
2018-07-20 23:14:33 +02:00
Rect2 vr = gui . tooltip_popup - > get_viewport_rect ( ) ;
2017-06-04 00:25:13 +02:00
if ( r . size . x + r . position . x > vr . size . x )
r . position . x = vr . size . x - r . size . x ;
else if ( r . position . x < 0 )
r . position . x = 0 ;
2016-01-17 02:41:10 +01:00
2017-06-04 00:25:13 +02:00
if ( r . size . y + r . position . y > vr . size . y )
r . position . y = vr . size . y - r . size . y ;
else if ( r . position . y < 0 )
r . position . y = 0 ;
2016-01-17 02:41:10 +01:00
2017-06-04 00:25:13 +02:00
gui . tooltip_popup - > set_global_position ( r . position ) ;
2016-01-17 02:41:10 +01:00
gui . tooltip_popup - > set_size ( r . size ) ;
gui . tooltip_popup - > raise ( ) ;
gui . tooltip_popup - > show ( ) ;
}
2017-05-20 17:38:03 +02:00
void Viewport : : _gui_call_input ( Control * p_control , const Ref < InputEvent > & p_input ) {
2016-01-17 02:41:10 +01:00
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
2017-08-24 22:58:51 +02:00
bool ismouse = ev . is_valid ( ) | | Object : : cast_to < InputEventMouseMotion > ( * p_input ) ! = NULL ;
2016-06-20 22:16:52 +02:00
2017-03-05 16:44:50 +01:00
CanvasItem * ci = p_control ;
while ( ci ) {
2016-06-07 07:39:40 +02:00
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-06-07 17:46:14 +02:00
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)
}
2016-06-07 07:39:40 +02:00
if ( gui . key_event_accepted )
break ;
if ( ! control - > is_inside_tree ( ) )
break ;
2018-11-16 17:46:42 +01:00
if ( control - > data . mouse_filter ! = Control : : MOUSE_FILTER_IGNORE ) {
control - > call_multilevel ( SceneStringNames : : get_singleton ( ) - > _gui_input , ev ) ;
}
2018-06-07 17:46:14 +02:00
2016-06-07 07:39:40 +02:00
if ( ! control - > is_inside_tree ( ) | | control - > is_set_as_toplevel ( ) )
break ;
if ( gui . key_event_accepted )
break ;
2017-05-20 17:38:03 +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 ;
}
if ( ci - > is_set_as_toplevel ( ) )
break ;
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 ) ;
}
if ( ! control - > is_inside_tree ( ) )
break ;
if ( ! control - > is_inside_tree ( ) | | control - > is_set_as_toplevel ( ) )
break ;
if ( control - > data . mouse_filter = = Control : : MOUSE_FILTER_STOP )
break ;
}
if ( ci - > is_set_as_toplevel ( ) )
break ;
ci = ci - > get_parent_item ( ) ;
}
//_unblock();
}
2017-03-05 16:44:50 +01:00
Control * Viewport : : _gui_find_control ( const Point2 & p_global ) {
2016-01-17 02:41:10 +01:00
2017-12-28 10:01:22 +01:00
_gui_prepare_subwindows ( ) ;
2016-01-17 02:41:10 +01:00
2017-03-05 16:44:50 +01:00
for ( List < Control * > : : Element * E = gui . subwindows . back ( ) ; E ; E = E - > prev ( ) ) {
2016-01-17 02:41:10 +01:00
Control * sw = E - > get ( ) ;
2017-01-13 14:45:50 +01:00
if ( ! sw - > is_visible_in_tree ( ) )
2016-01-17 02:41:10 +01:00
continue ;
2017-01-11 04:52:51 +01:00
Transform2D xform ;
2016-01-17 02:41:10 +01:00
CanvasItem * pci = sw - > get_parent_item ( ) ;
if ( pci )
2017-03-05 16:44:50 +01:00
xform = pci - > get_global_transform_with_canvas ( ) ;
2016-02-03 13:31:18 +01:00
else
2017-03-05 16:44:50 +01:00
xform = sw - > get_canvas_transform ( ) ;
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 ) ;
2016-01-17 02:41:10 +01:00
if ( ret )
return ret ;
}
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 ( ) ;
2017-01-13 14:45:50 +01:00
if ( ! sw - > is_visible_in_tree ( ) )
2016-01-17 02:41:10 +01:00
continue ;
2017-01-11 04:52:51 +01:00
Transform2D xform ;
2016-01-17 02:41:10 +01:00
CanvasItem * pci = sw - > get_parent_item ( ) ;
if ( pci )
2017-03-05 16:44:50 +01:00
xform = pci - > get_global_transform_with_canvas ( ) ;
2016-02-03 13:31:18 +01:00
else
2017-03-05 16:44:50 +01:00
xform = sw - > get_canvas_transform ( ) ;
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 ) ;
2016-01-17 02:41:10 +01:00
if ( ret )
return ret ;
}
return NULL ;
}
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 ) {
2016-01-17 02:41:10 +01:00
2017-08-24 22:58:51 +02:00
if ( Object : : cast_to < Viewport > ( p_node ) )
2016-01-17 02:41:10 +01:00
return NULL ;
//subwindows first!!
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);
return NULL ; //canvas item hidden, discard
}
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
2017-03-05 16:44:50 +01:00
if ( matrix . basis_determinant ( ) = = 0.0f )
2016-10-08 12:33:10 +02:00
return NULL ;
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 - - ) {
2016-01-17 02:41:10 +01:00
2017-03-05 16:44:50 +01:00
if ( p_node = = gui . tooltip_popup )
2016-01-17 02:41:10 +01:00
continue ;
2017-08-24 22:58:51 +02:00
CanvasItem * ci = Object : : cast_to < CanvasItem > ( p_node - > get_child ( i ) ) ;
2016-01-17 02:41:10 +01:00
if ( ! ci | | ci - > is_set_as_toplevel ( ) )
continue ;
2017-03-05 16:44:50 +01:00
Control * ret = _gui_find_control_at_pos ( ci , p_global , matrix , r_inv_xform ) ;
2016-01-17 02:41:10 +01:00
if ( ret )
return ret ;
}
}
if ( ! c )
return NULL ;
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 ;
} else
return NULL ;
}
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-01-24 03:12:08 +01:00
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 ;
}
2017-03-05 16:44:50 +01:00
if ( control - > data . mouse_filter = = Control : : MOUSE_FILTER_STOP )
2017-01-24 03:12:08 +01:00
break ;
}
p_at_pos = ci - > get_transform ( ) . xform ( p_at_pos ) ;
if ( ci - > is_set_as_toplevel ( ) )
break ;
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 ) {
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 ( ) ) {
2016-01-17 02:41:10 +01:00
2017-05-20 17:38:03 +02:00
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 ( ) ) {
2016-01-17 02:41:10 +01:00
2017-05-20 17:38:03 +02:00
Size2 pos = mpos ;
2018-11-28 13:31:17 +01:00
if ( gui . mouse_focus_mask ) {
2016-01-17 02:41:10 +01:00
2018-11-28 13:31:17 +01:00
//do not steal mouse focus and stuff while a focus mask exists
gui . mouse_focus_mask | = 1 < < ( mb - > get_button_index ( ) - 1 ) ; //add the button to the mask
2017-05-20 17:38:03 +02:00
} else {
2016-01-17 02:41:10 +01:00
2017-11-22 09:43:40 +01:00
bool is_handled = false ;
2017-05-20 17:38:03 +02:00
_gui_sort_modal_stack ( ) ;
while ( ! gui . modal_stack . empty ( ) ) {
2016-01-17 02:41:10 +01:00
2017-05-20 17:38:03 +02:00
Control * top = gui . modal_stack . back ( ) - > get ( ) ;
2019-02-12 21:10:08 +01:00
Vector2 pos2 = top - > get_global_transform_with_canvas ( ) . affine_inverse ( ) . xform ( mpos ) ;
if ( ! top - > has_point ( pos2 ) ) {
2016-01-17 02:41:10 +01:00
2017-05-20 17:38:03 +02:00
if ( top - > data . modal_exclusive | | top - > data . modal_frame = = Engine : : get_singleton ( ) - > get_frames_drawn ( ) ) {
//cancel event, sorry, modal exclusive EATS UP ALL
//alternative, you can't pop out a window the same frame it was made modal (fixes many issues)
2018-11-15 17:54:26 +01:00
set_input_as_handled ( ) ;
2017-12-19 13:55:01 +01:00
2017-05-20 17:38:03 +02:00
return ; // no one gets the event if exclusive NO ONE
2016-01-17 02:41:10 +01:00
}
2017-05-20 17:38:03 +02:00
top - > notification ( Control : : NOTIFICATION_MODAL_CLOSE ) ;
top - > _modal_stack_remove ( ) ;
top - > hide ( ) ;
2017-11-22 09:43:40 +01:00
if ( ! top - > pass_on_modal_close_click ( ) ) {
is_handled = true ;
}
2017-05-20 17:38:03 +02:00
} else {
break ;
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-11-22 09:43:40 +01:00
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
2018-12-03 01:38:54 +01:00
if ( ScriptDebugger : : get_singleton ( ) & & gui . mouse_focus ) {
2016-01-17 02:41:10 +01:00
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 ( ) ) ;
ScriptDebugger : : get_singleton ( ) - > send_message ( " click_ctrl " , arr ) ;
}
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-01-21 23:00:25 +01:00
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
}
2017-05-20 17:38:03 +02:00
if ( control - > data . mouse_filter = = Control : : MOUSE_FILTER_STOP )
2017-01-21 23:00:25 +01:00
break ;
}
2016-01-17 02:41:10 +01:00
2017-05-20 17:38:03 +02:00
if ( ci - > is_set_as_toplevel ( ) )
break ;
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 ) {
2016-07-01 15:34:38 +02:00
2017-05-20 17:38:03 +02:00
//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 ) ;
gui . drag_preview = NULL ;
}
_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 {
2017-01-24 03:12:08 +01:00
2017-05-20 17:38:03 +02:00
if ( gui . drag_data . get_type ( ) ! = Variant : : NIL & & mb - > get_button_index ( ) = = BUTTON_LEFT ) {
2016-01-17 02:41:10 +01:00
2017-05-20 17:38:03 +02:00
if ( gui . mouse_over ) {
Size2 pos = mpos ;
pos = gui . focus_inv_xform . xform ( pos ) ;
2016-07-01 15:34:38 +02:00
2017-05-20 17:38:03 +02:00
_gui_drop ( gui . 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 ) ;
gui . drag_preview = NULL ;
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 ;
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 ) {
2017-05-20 17:38:03 +02:00
gui . mouse_focus = NULL ;
}
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 ( ) ) {
2016-01-17 02:41:10 +01:00
2017-05-20 17:38:03 +02:00
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
2017-05-20 17:38:03 +02:00
Control * over = NULL ;
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 ) {
2017-01-24 03:12:08 +01:00
2017-05-20 17:38:03 +02:00
{ //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 ) {
gui . mouse_focus = NULL ;
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 {
2018-11-19 22:37:39 +01:00
if ( gui . drag_preview ! = NULL ) {
ERR_PRINT ( " Don't set a drag preview and return null data. Preview was deleted and drag request ignored. " ) ;
memdelete ( gui . drag_preview ) ;
gui . drag_preview = NULL ;
}
2018-08-24 15:29:27 +02:00
gui . dragging = false ;
2017-01-24 03:12:08 +01:00
}
2017-05-20 17:38:03 +02:00
if ( control - > data . mouse_filter = = Control : : MOUSE_FILTER_STOP )
2017-01-24 03:12:08 +01:00
break ;
}
2017-05-20 17:38:03 +02:00
if ( ci - > is_set_as_toplevel ( ) )
break ;
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 {
2016-01-17 02:41:10 +01:00
2017-05-20 17:38:03 +02:00
over = _gui_find_control ( mpos ) ;
}
2016-01-17 02:41:10 +01:00
2017-05-20 17:38:03 +02:00
if ( gui . drag_data . get_type ( ) = = Variant : : NIL & & over & & ! gui . modal_stack . empty ( ) ) {
2016-01-17 02:41:10 +01:00
2017-05-20 17:38:03 +02:00
Control * top = gui . modal_stack . back ( ) - > get ( ) ;
2018-06-23 04:51:47 +02:00
2017-05-20 17:38:03 +02:00
if ( over ! = top & & ! top - > is_a_parent_of ( over ) ) {
2018-06-23 04:51:47 +02:00
PopupMenu * popup_menu = Object : : cast_to < PopupMenu > ( top ) ;
2018-07-28 19:05:30 +02:00
MenuButton * popup_menu_parent = NULL ;
2018-06-23 04:51:47 +02:00
MenuButton * menu_button = Object : : cast_to < MenuButton > ( over ) ;
2018-09-11 06:44:19 +02:00
if ( popup_menu ) {
2018-06-23 04:51:47 +02:00
popup_menu_parent = Object : : cast_to < MenuButton > ( popup_menu - > get_parent ( ) ) ;
2018-09-11 06:44:19 +02:00
if ( ! popup_menu_parent ) {
// Go through the parents to see if there's a MenuButton at the end.
while ( Object : : cast_to < PopupMenu > ( popup_menu - > get_parent ( ) ) ) {
popup_menu = Object : : cast_to < PopupMenu > ( popup_menu - > get_parent ( ) ) ;
}
popup_menu_parent = Object : : cast_to < MenuButton > ( popup_menu - > get_parent ( ) ) ;
}
}
2018-06-23 04:51:47 +02:00
// If the mouse is over a menu button, this menu will open automatically
// if there is already a pop-up menu open at the same hierarchical level.
2018-07-30 00:26:43 +02:00
if ( popup_menu_parent & & menu_button & & popup_menu_parent - > is_switch_on_hover ( ) & &
! menu_button - > is_disabled ( ) & & menu_button - > is_switch_on_hover ( ) & &
( popup_menu_parent - > get_parent ( ) - > is_a_parent_of ( menu_button ) | |
2018-06-23 04:51:47 +02:00
menu_button - > get_parent ( ) - > is_a_parent_of ( popup_menu ) ) ) {
popup_menu - > notification ( Control : : NOTIFICATION_MODAL_CLOSE ) ;
popup_menu - > _modal_stack_remove ( ) ;
popup_menu - > hide ( ) ;
menu_button - > pressed ( ) ;
} else {
over = NULL ; //nothing can be found outside the modal stack
}
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 ( over ! = gui . mouse_over ) {
2016-01-17 02:41:10 +01:00
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
2017-05-20 17:38:03 +02:00
if ( gui . drag_preview ) {
gui . drag_preview - > set_position ( mpos ) ;
}
2016-01-17 02:41:10 +01:00
2017-05-20 17:38:03 +02:00
if ( ! over ) {
2018-04-09 22:48:24 +02:00
OS : : get_singleton ( ) - > set_cursor_shape ( ( OS : : CursorShape ) Input : : get_singleton ( ) - > get_default_cursor_shape ( ) ) ;
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
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
2017-05-20 17:38:03 +02:00
mm = mm - > xformed_by ( Transform2D ( ) ) ; //make a copy
2016-01-17 02:41:10 +01:00
2017-06-03 10:54:24 +02:00
mm - > set_global_position ( mpos ) ;
2017-05-20 17:38:03 +02:00
mm - > set_speed ( speed ) ;
mm - > set_relative ( rel ) ;
2016-01-17 02:41:10 +01:00
2017-05-20 17:38:03 +02:00
if ( mm - > get_button_mask ( ) = = 0 ) {
//nothing pressed
2016-01-17 02:41:10 +01:00
2017-05-20 17:38:03 +02:00
bool can_tooltip = true ;
2016-01-17 02:41:10 +01:00
2017-05-20 17:38:03 +02:00
if ( ! gui . modal_stack . empty ( ) ) {
if ( gui . modal_stack . back ( ) - > get ( ) ! = over & & ! gui . modal_stack . back ( ) - > get ( ) - > is_a_parent_of ( over ) )
can_tooltip = false ;
}
2016-01-17 02:41:10 +01:00
2017-05-20 17:38:03 +02:00
bool is_tooltip_shown = false ;
2016-07-19 06:27:12 +02:00
2017-05-20 17:38:03 +02:00
if ( gui . tooltip_popup ) {
2018-07-20 23:14:33 +02:00
if ( can_tooltip & & gui . tooltip ) {
2018-06-07 17:46:14 +02:00
String tooltip = _gui_get_tooltip ( over , gui . tooltip - > get_global_transform ( ) . xform_inv ( mpos ) ) ;
2017-05-20 17:38:03 +02:00
if ( tooltip . length ( ) = = 0 )
2016-07-19 06:27:12 +02:00
_gui_cancel_tooltip ( ) ;
2018-07-20 23:14:33 +02:00
else if ( gui . tooltip_label ) {
if ( tooltip = = gui . tooltip_label - > get_text ( ) ) {
is_tooltip_shown = true ;
}
} else if ( tooltip = = String ( gui . tooltip_popup - > call ( " get_tooltip_text " ) ) ) {
2017-05-20 17:38:03 +02:00
is_tooltip_shown = true ;
2018-07-20 23:14:33 +02:00
}
2017-05-20 17:38:03 +02:00
} else
_gui_cancel_tooltip ( ) ;
}
2016-07-18 22:14:57 +02:00
2017-05-20 17:38:03 +02:00
if ( can_tooltip & & ! is_tooltip_shown ) {
2016-01-17 02:41:10 +01:00
2017-05-20 17:38:03 +02:00
gui . tooltip = over ;
gui . tooltip_pos = mpos ; //(parent_xform * get_transform()).affine_inverse().xform(pos);
gui . tooltip_timer = gui . tooltip_delay ;
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
//pos = gui.focus_inv_xform.xform(pos);
2016-01-17 02:41:10 +01:00
2017-06-03 10:54:24 +02:00
mm - > set_position ( pos ) ;
2016-01-17 02:41:10 +01:00
2018-06-07 17:46:14 +02:00
Control : : CursorShape cursor_shape = Control : : CURSOR_ARROW ;
{
Control * c = over ;
Vector2 cpos = pos ;
while ( c ) {
2018-06-07 20:12:59 +02:00
cursor_shape = c - > get_cursor_shape ( cpos ) ;
2018-06-07 17:46:14 +02:00
cpos = c - > get_transform ( ) . xform ( cpos ) ;
if ( cursor_shape ! = Control : : CURSOR_ARROW )
break ;
if ( c - > data . mouse_filter = = Control : : MOUSE_FILTER_STOP )
break ;
if ( c - > is_set_as_toplevel ( ) )
break ;
c = c - > get_parent_control ( ) ;
}
}
2017-05-20 17:38:03 +02:00
OS : : get_singleton ( ) - > set_cursor_shape ( ( OS : : CursorShape ) cursor_shape ) ;
2016-01-17 02:41:10 +01:00
2018-12-03 01:38:54 +01:00
if ( over & & over - > can_process ( ) ) {
2017-05-20 17:38:03 +02:00
_gui_call_input ( over , mm ) ;
}
2016-01-17 02:41:10 +01:00
2018-11-15 17:54:26 +01:00
set_input_as_handled ( ) ;
2016-01-17 02:41:10 +01:00
2017-05-20 17:38:03 +02:00
if ( gui . drag_data . get_type ( ) ! = Variant : : NIL & & mm - > get_button_mask ( ) & BUTTON_MASK_LEFT ) {
2016-01-17 02:41:10 +01:00
2017-05-20 17:38:03 +02:00
bool can_drop = _gui_drop ( over , pos , true ) ;
2016-05-11 16:46:08 +02:00
2017-05-20 17:38:03 +02:00
if ( ! can_drop ) {
OS : : get_singleton ( ) - > set_cursor_shape ( OS : : CURSOR_FORBIDDEN ) ;
} else {
OS : : get_singleton ( ) - > set_cursor_shape ( OS : : CURSOR_CAN_DROP ) ;
2016-01-17 02:41:10 +01:00
}
2017-05-20 17:38:03 +02:00
//change mouse accordingly i guess
}
}
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 ( ! gui . modal_stack . empty ( ) ) {
Control * top = gui . modal_stack . back ( ) - > get ( ) ;
if ( over ! = top & & ! top - > is_a_parent_of ( over ) ) {
return ;
}
}
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 ) {
2017-08-07 06:44:46 +02:00
2018-10-26 21:23:47 +02:00
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 ( ! gui . modal_stack . empty ( ) ) {
Control * top = gui . modal_stack . back ( ) - > get ( ) ;
if ( over ! = top & & ! top - > is_a_parent_of ( over ) ) {
return ;
}
}
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 ( ) ) {
2016-01-17 02:41:10 +01:00
2017-05-20 17:38:03 +02:00
if ( gui . key_focus & & ! gui . key_focus - > is_visible_in_tree ( ) ) {
gui . key_focus - > release_focus ( ) ;
}
2016-07-01 15:42:33 +02:00
2017-05-20 17:38:03 +02:00
if ( gui . key_focus ) {
2016-01-17 02:41:10 +01:00
2017-05-20 17:38:03 +02:00
gui . key_event_accepted = false ;
if ( gui . key_focus - > can_process ( ) ) {
gui . key_focus - > call_multilevel ( SceneStringNames : : get_singleton ( ) - > _gui_input , p_event ) ;
if ( gui . key_focus ) //maybe lost it
gui . key_focus - > emit_signal ( SceneStringNames : : get_singleton ( ) - > gui_input , p_event ) ;
}
2016-01-17 02:41:10 +01:00
2017-05-20 17:38:03 +02:00
if ( gui . key_event_accepted ) {
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
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
2017-05-20 17:38:03 +02:00
if ( p_event - > is_pressed ( ) & & p_event - > is_action ( " ui_cancel " ) & & ! gui . modal_stack . empty ( ) ) {
2016-01-17 02:41:10 +01:00
2017-05-20 17:38:03 +02:00
_gui_sort_modal_stack ( ) ;
Control * top = gui . modal_stack . back ( ) - > get ( ) ;
if ( ! top - > data . modal_exclusive ) {
2016-01-17 02:41:10 +01:00
2017-05-20 17:38:03 +02:00
top - > notification ( Control : : NOTIFICATION_MODAL_CLOSE ) ;
top - > _modal_stack_remove ( ) ;
top - > hide ( ) ;
2018-01-06 07:50:15 +01:00
// Close modal, set input as handled
2018-11-15 17:54:26 +01:00
set_input_as_handled ( ) ;
2018-01-06 07:50:15 +01: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
2017-05-20 17:38:03 +02:00
Control * from = gui . key_focus ? gui . key_focus : NULL ; //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 ( ) ) {
Control * next = NULL ;
2016-01-17 02:41:10 +01:00
2019-03-09 21:09:20 +01:00
if ( p_event - > is_action_pressed ( " ui_focus_next " ) ) {
2016-01-17 02:41:10 +01:00
2017-05-20 17:38:03 +02:00
next = from - > find_next_valid_focus ( ) ;
}
2016-01-17 02:41:10 +01:00
2019-03-09 21:09:20 +01:00
if ( p_event - > is_action_pressed ( " ui_focus_prev " ) ) {
2016-01-17 02:41:10 +01:00
2017-05-20 17:38:03 +02:00
next = from - > find_prev_valid_focus ( ) ;
}
2016-01-17 02:41:10 +01:00
2019-03-09 21:09:20 +01:00
if ( ! mods & & p_event - > is_action_pressed ( " ui_up " ) ) {
2016-01-17 02:41:10 +01:00
2017-05-20 17:38:03 +02:00
next = from - > _get_focus_neighbour ( MARGIN_TOP ) ;
}
2016-01-17 02:41:10 +01:00
2019-03-09 21:09:20 +01:00
if ( ! mods & & p_event - > is_action_pressed ( " ui_left " ) ) {
2016-01-17 02:41:10 +01:00
2017-05-20 17:38:03 +02:00
next = from - > _get_focus_neighbour ( MARGIN_LEFT ) ;
}
2016-01-17 02:41:10 +01:00
2019-03-09 21:09:20 +01:00
if ( ! mods & & p_event - > is_action_pressed ( " ui_right " ) ) {
2016-01-17 02:41:10 +01:00
2017-05-20 17:38:03 +02:00
next = from - > _get_focus_neighbour ( MARGIN_RIGHT ) ;
}
2016-01-17 02:41:10 +01:00
2019-03-09 21:09:20 +01:00
if ( ! mods & & p_event - > is_action_pressed ( " ui_down " ) ) {
2016-01-17 02:41:10 +01:00
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 ) {
2016-01-17 02:41:10 +01:00
2017-03-05 16:44:50 +01:00
gui . roots_order_dirty = true ;
2016-01-17 02:41:10 +01:00
return gui . roots . push_back ( p_control ) ;
}
2017-03-05 16:44:50 +01:00
List < Control * > : : Element * Viewport : : _gui_add_subwindow_control ( Control * p_control ) {
2016-01-17 02:41:10 +01:00
2017-12-28 10:01:22 +01:00
p_control - > connect ( " visibility_changed " , this , " _subwindow_visibility_changed " ) ;
if ( p_control - > is_visible_in_tree ( ) ) {
gui . subwindow_order_dirty = true ;
gui . subwindows . push_back ( p_control ) ;
}
return gui . all_known_subwindows . push_back ( p_control ) ;
2016-01-17 02:41:10 +01:00
}
void Viewport : : _gui_set_subwindow_order_dirty ( ) {
2017-03-05 16:44:50 +01:00
gui . subwindow_order_dirty = true ;
2016-01-17 02:41:10 +01:00
}
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_remove_modal_control ( List < Control * > : : Element * MI ) {
2016-01-17 02:41:10 +01:00
gui . modal_stack . erase ( MI ) ;
}
2017-03-05 16:44:50 +01:00
void Viewport : : _gui_remove_from_modal_stack ( List < Control * > : : Element * MI , ObjectID p_prev_focus_owner ) {
2016-01-17 02:41:10 +01:00
//transfer the focus stack to the next
2017-03-05 16:44:50 +01:00
List < Control * > : : Element * next = MI - > next ( ) ;
2016-01-17 02:41:10 +01:00
gui . modal_stack . erase ( MI ) ;
2017-03-05 16:44:50 +01:00
MI = NULL ;
2016-01-17 02:41:10 +01:00
if ( p_prev_focus_owner ) {
// for previous window in stack, pass the focus so it feels more
// natural
if ( ! next ) { //top of stack
Object * pfo = ObjectDB : : get_instance ( p_prev_focus_owner ) ;
2017-08-24 22:58:51 +02:00
Control * pfoc = Object : : cast_to < Control > ( pfo ) ;
2016-01-17 02:41:10 +01:00
if ( ! pfoc )
return ;
2017-01-13 14:45:50 +01:00
if ( ! pfoc - > is_inside_tree ( ) | | ! pfoc - > is_visible_in_tree ( ) )
2016-01-17 02:41:10 +01:00
return ;
pfoc - > grab_focus ( ) ;
} else {
next - > get ( ) - > _modal_set_prev_focus_owner ( p_prev_focus_owner ) ;
}
}
}
2017-03-05 16:44:50 +01:00
void Viewport : : _gui_force_drag ( Control * p_base , const Variant & p_data , Control * p_control ) {
2016-01-17 02:41:10 +01:00
2016-07-01 15:34:38 +02:00
ERR_EXPLAIN ( " Drag data must be a value " ) ;
2017-03-05 16:44:50 +01:00
ERR_FAIL_COND ( p_data . get_type ( ) = = Variant : : NIL ) ;
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 ;
gui . mouse_focus = NULL ;
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 ( ) ) ;
2017-03-05 16:44:50 +01:00
ERR_FAIL_COND ( p_control - > get_parent ( ) ! = NULL ) ;
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 ) ;
}
2017-03-05 16:44:50 +01:00
void Viewport : : _gui_remove_subwindow_control ( List < Control * > : : Element * SI ) {
2016-01-17 02:41:10 +01:00
2017-12-28 10:01:22 +01:00
ERR_FAIL_COND ( ! SI ) ;
Control * control = SI - > get ( ) ;
control - > disconnect ( " visibility_changed " , this , " _subwindow_visibility_changed " ) ;
List < Control * > : : Element * E = gui . subwindows . find ( control ) ;
if ( E )
gui . subwindows . erase ( E ) ;
gui . all_known_subwindows . erase ( SI ) ;
2016-01-17 02:41:10 +01:00
}
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
}
/* ???
if ( data . window = = p_control ) {
window - > drag_data = Variant ( ) ;
if ( window - > drag_preview ) {
memdelete ( window - > drag_preview ) ;
window - > drag_preview = NULL ;
}
}
*/
if ( gui . key_focus = = p_control )
2017-12-26 20:58:53 +01:00
_gui_remove_focus ( ) ;
2016-01-17 02:41:10 +01:00
if ( gui . mouse_over = = p_control )
2017-03-05 16:44:50 +01:00
gui . mouse_over = NULL ;
2016-01-17 02:41:10 +01:00
if ( gui . tooltip = = p_control )
2016-01-25 14:30:03 +01:00
_gui_cancel_tooltip ( ) ;
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 ) {
2017-03-05 16:44:50 +01:00
gui . mouse_focus = NULL ;
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 ) {
gui . last_mouse_focus = NULL ;
}
2016-01-17 02:41:10 +01:00
if ( gui . key_focus = = p_control )
2017-03-05 16:44:50 +01:00
gui . key_focus = NULL ;
2016-01-17 02:41:10 +01:00
if ( gui . mouse_over = = p_control )
2017-03-05 16:44:50 +01:00
gui . mouse_over = NULL ;
2016-01-17 02:41:10 +01:00
if ( gui . tooltip = = p_control )
2017-03-05 16:44:50 +01:00
gui . tooltip = NULL ;
2016-01-25 14:30:03 +01:00
if ( gui . tooltip_popup = = p_control ) {
_gui_cancel_tooltip ( ) ;
}
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 ;
gui . key_focus = NULL ;
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_is_modal_on_top ( const Control * p_control ) {
2016-01-17 02:41:10 +01:00
2017-03-05 16:44:50 +01:00
return ( gui . modal_stack . size ( ) & & gui . modal_stack . back ( ) - > get ( ) = = p_control ) ;
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 ) {
2016-01-17 02:41:10 +01:00
2017-03-05 16:44:50 +01:00
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
2017-03-05 16:44:50 +01:00
if ( gui . key_focus & & gui . key_focus = = p_control )
2016-01-17 02:41:10 +01:00
return ;
2017-03-05 16:44:50 +01:00
get_tree ( ) - > call_group_flags ( SceneTree : : GROUP_CALL_REALTIME , " _viewports " , " _gui_remove_focus " ) ;
gui . key_focus = 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 ;
2016-01-17 02:41:10 +01:00
if ( is_inside_tree ( ) )
2018-11-15 17:54:26 +01:00
set_input_as_handled ( ) ;
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 ;
gui . mouse_focus = NULL ;
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 ) ;
c - > call_multilevel ( SceneStringNames : : get_singleton ( ) - > _gui_input , mb ) ;
}
}
}
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
if ( physics_object_over ) {
CollisionObject * co = Object : : cast_to < CollisionObject > ( ObjectDB : : get_instance ( physics_object_over ) ) ;
if ( co ) {
co - > _mouse_exit ( ) ;
}
}
physics_object_over = physics_object_capture = 0 ;
# endif
}
2017-03-05 16:44:50 +01:00
List < Control * > : : Element * Viewport : : _gui_show_modal ( Control * p_control ) {
2016-01-17 02:41:10 +01:00
gui . modal_stack . push_back ( p_control ) ;
if ( gui . key_focus )
2017-08-07 12:17:31 +02:00
p_control - > _modal_set_prev_focus_owner ( gui . key_focus - > get_instance_id ( ) ) ;
2016-01-17 02:41:10 +01:00
else
p_control - > _modal_set_prev_focus_owner ( 0 ) ;
2018-03-27 23:41:27 +02:00
if ( gui . mouse_focus & & ! p_control - > is_a_parent_of ( gui . mouse_focus ) & & ! gui . mouse_click_grabber ) {
2018-11-28 13:31:17 +01:00
_drop_mouse_focus ( ) ;
2017-12-19 13:55:01 +01:00
}
2016-01-17 02:41:10 +01:00
return gui . modal_stack . back ( ) ;
}
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 ;
}
gui . mouse_click_grabber = NULL ;
2016-01-17 02:41:10 +01:00
if ( gui . mouse_focus ) {
2018-03-27 23:41:27 +02:00
if ( gui . mouse_focus = = focus_grabber )
2016-01-17 02:41:10 +01:00
return ;
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 ) ;
gui . mouse_focus - > call_multilevel ( SceneStringNames : : get_singleton ( ) - > _gui_input , mb ) ;
}
}
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
}
}
///////////////////////////////
2017-05-20 17:38:03 +02:00
void Viewport : : input ( const Ref < InputEvent > & p_event ) {
2014-04-10 05:18:27 +02:00
2014-11-06 01:20:42 +01:00
ERR_FAIL_COND ( ! is_inside_tree ( ) ) ;
2016-01-18 23:49:11 +01:00
2018-11-15 17:54:26 +01:00
local_input_handled = false ;
if ( ! is_input_handled ( ) ) {
2017-10-16 14:13:33 +02:00
get_tree ( ) - > _call_input_pause ( input_group , " _input " , p_event ) ; //not a bug, must happen before GUI, order is _input -> gui input -> _unhandled input
}
2018-11-15 17:54:26 +01:00
if ( ! is_input_handled ( ) ) {
2017-10-16 14:13:33 +02:00
_gui_input_event ( p_event ) ;
}
2016-01-17 02:41:10 +01:00
//get_tree()->call_group(SceneTree::GROUP_CALL_REVERSE|SceneTree::GROUP_CALL_REALTIME|SceneTree::GROUP_CALL_MULIILEVEL,gui_input_group,"_gui_input",p_event); //special one for GUI, as controls use their own process check
2014-04-10 05:18:27 +02:00
}
2017-05-20 17:38:03 +02:00
void Viewport : : unhandled_input ( const Ref < InputEvent > & p_event ) {
2014-04-10 05:18:27 +02:00
2014-11-06 01:20:42 +01:00
ERR_FAIL_COND ( ! is_inside_tree ( ) ) ;
2014-04-10 05:18:27 +02:00
2017-03-05 16:44:50 +01:00
get_tree ( ) - > _call_input_pause ( unhandled_input_group , " _unhandled_input " , p_event ) ;
2014-04-10 05:18:27 +02:00
//call_group(GROUP_CALL_REVERSE|GROUP_CALL_REALTIME|GROUP_CALL_MULIILEVEL,"unhandled_input","_unhandled_input",ev);
2017-08-24 22:58:51 +02:00
if ( ! get_tree ( ) - > input_handled & & Object : : cast_to < InputEventKey > ( * p_event ) ! = NULL ) {
2017-03-05 16:44:50 +01:00
get_tree ( ) - > _call_input_pause ( unhandled_key_input_group , " _unhandled_key_input " , p_event ) ;
2014-04-10 05:18:27 +02:00
//call_group(GROUP_CALL_REVERSE|GROUP_CALL_REALTIME|GROUP_CALL_MULIILEVEL,"unhandled_key_input","_unhandled_key_input",ev);
}
2014-09-15 16:33:30 +02:00
2014-11-06 01:20:42 +01:00
if ( physics_object_picking & & ! get_tree ( ) - > input_handled ) {
2014-09-15 16:33:30 +02:00
2017-08-24 22:58:51 +02:00
if ( Input : : get_singleton ( ) - > get_mouse_mode ( ) ! = Input : : MOUSE_MODE_CAPTURED & &
( Object : : cast_to < InputEventMouseButton > ( * p_event ) | |
Object : : cast_to < InputEventMouseMotion > ( * p_event ) | |
Object : : cast_to < InputEventScreenDrag > ( * p_event ) | |
2018-11-15 17:54:26 +01:00
Object : : cast_to < InputEventScreenTouch > ( * p_event ) | |
Object : : cast_to < InputEventKey > ( * p_event ) //to remember state
) ) {
2014-09-15 16:33:30 +02:00
physics_picking_events . push_back ( p_event ) ;
}
}
2014-04-10 05:18:27 +02:00
}
2014-04-15 03:43:44 +02:00
void Viewport : : set_use_own_world ( bool p_world ) {
2017-03-05 16:44:50 +01:00
if ( p_world = = own_world . is_valid ( ) )
2014-04-15 03:43:44 +02:00
return ;
2014-11-06 01:20:42 +01:00
if ( is_inside_tree ( ) )
2014-04-15 03:43:44 +02:00
_propagate_exit_world ( this ) ;
if ( ! p_world )
2017-03-05 16:44:50 +01:00
own_world = Ref < World > ( ) ;
2014-04-15 03:43:44 +02:00
else
2017-03-05 16:44:50 +01:00
own_world = Ref < World > ( memnew ( World ) ) ;
2014-04-15 03:43:44 +02:00
2014-11-06 01:20:42 +01:00
if ( is_inside_tree ( ) )
2014-04-15 03:43:44 +02:00
_propagate_enter_world ( this ) ;
2014-11-06 01:20:42 +01:00
if ( is_inside_tree ( ) ) {
2017-03-05 16:44:50 +01:00
VisualServer : : get_singleton ( ) - > viewport_set_scenario ( viewport , find_world ( ) - > get_scenario ( ) ) ;
2014-04-15 03:43:44 +02:00
}
_update_listener ( ) ;
}
bool Viewport : : is_using_own_world ( ) const {
return own_world . is_valid ( ) ;
}
2017-03-05 16:44:50 +01:00
void Viewport : : set_attach_to_screen_rect ( const Rect2 & p_rect ) {
2014-04-15 03:43:44 +02:00
2017-03-05 16:44:50 +01:00
VS : : get_singleton ( ) - > viewport_attach_to_screen ( viewport , p_rect ) ;
to_screen_rect = p_rect ;
2014-04-15 03:43:44 +02:00
}
2017-03-05 16:44:50 +01:00
Rect2 Viewport : : get_attach_to_screen_rect ( ) const {
2014-04-15 03:43:44 +02:00
return to_screen_rect ;
}
2019-05-08 20:25:34 +02:00
void Viewport : : set_use_render_direct_to_screen ( bool p_render_direct_to_screen ) {
if ( p_render_direct_to_screen = = render_direct_to_screen )
return ;
render_direct_to_screen = p_render_direct_to_screen ;
VS : : get_singleton ( ) - > viewport_set_render_direct_to_screen ( viewport , p_render_direct_to_screen ) ;
}
bool Viewport : : is_using_render_direct_to_screen ( ) const {
return render_direct_to_screen ;
}
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
bool Viewport : : gui_has_modal_stack ( ) const {
return gui . modal_stack . size ( ) ;
}
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-10-05 06:26:35 +02:00
void Viewport : : set_disable_3d ( bool p_disable ) {
2017-03-05 16:44:50 +01:00
disable_3d = p_disable ;
VS : : get_singleton ( ) - > viewport_set_disable_3d ( viewport , p_disable ) ;
2016-10-05 06:26:35 +02:00
}
bool Viewport : : is_3d_disabled ( ) const {
return disable_3d ;
}
2018-04-30 14:30:11 +02:00
void Viewport : : set_keep_3d_linear ( bool p_keep_3d_linear ) {
keep_3d_linear = p_keep_3d_linear ;
VS : : get_singleton ( ) - > viewport_set_keep_3d_linear ( viewport , keep_3d_linear ) ;
}
bool Viewport : : get_keep_3d_linear ( ) const {
return keep_3d_linear ;
}
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
2016-06-28 01:14:59 +02:00
Control * Viewport : : get_modal_stack_top ( ) const {
2017-03-05 16:44:50 +01:00
return gui . modal_stack . size ( ) ? gui . modal_stack . back ( ) - > get ( ) : NULL ;
2016-06-28 01:14:59 +02:00
}
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
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
}
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 ) {
2017-03-05 16:44:50 +01:00
ERR_FAIL_INDEX ( p_msaa , 5 ) ;
if ( msaa = = p_msaa )
2017-01-02 02:16:52 +01:00
return ;
2017-03-05 16:44:50 +01:00
msaa = p_msaa ;
VS : : get_singleton ( ) - > viewport_set_msaa ( viewport , VS : : ViewportMSAA ( p_msaa ) ) ;
2017-01-02 02:16:52 +01:00
}
Viewport : : MSAA Viewport : : get_msaa ( ) const {
return msaa ;
}
void Viewport : : set_hdr ( bool p_hdr ) {
2017-03-05 16:44:50 +01:00
if ( hdr = = p_hdr )
2017-01-02 02:16:52 +01:00
return ;
2017-03-05 16:44:50 +01:00
hdr = p_hdr ;
VS : : get_singleton ( ) - > viewport_set_hdr ( viewport , p_hdr ) ;
2017-01-02 02:16:52 +01:00
}
2017-03-05 16:44:50 +01:00
bool Viewport : : get_hdr ( ) const {
2017-01-02 02:16:52 +01:00
return hdr ;
}
2017-06-09 05:23:50 +02:00
void Viewport : : set_usage ( Usage p_usage ) {
usage = p_usage ;
VS : : get_singleton ( ) - > viewport_set_usage ( viewport , VS : : ViewportUsage ( p_usage ) ) ;
}
Viewport : : Usage Viewport : : get_usage ( ) const {
return usage ;
}
2017-06-11 20:52:03 +02:00
void Viewport : : set_debug_draw ( DebugDraw p_debug_draw ) {
debug_draw = p_debug_draw ;
VS : : get_singleton ( ) - > viewport_set_debug_draw ( viewport , VS : : ViewportDebugDraw ( p_debug_draw ) ) ;
}
Viewport : : DebugDraw Viewport : : get_debug_draw ( ) const {
return debug_draw ;
}
int Viewport : : get_render_info ( RenderInfo p_info ) {
return VS : : get_singleton ( ) - > viewport_get_render_info ( viewport , VS : : ViewportRenderInfo ( p_info ) ) ;
}
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 ( ) ) ;
get_tree ( ) - > set_input_as_handled ( ) ;
}
}
bool Viewport : : is_input_handled ( ) const {
if ( handle_input_locally ) {
return local_input_handled ;
} else {
ERR_FAIL_COND_V ( ! is_inside_tree ( ) , false ) ;
return get_tree ( ) - > is_input_handled ( ) ;
}
}
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 {
if ( VisualServer : : get_singleton ( ) - > is_low_end ( ) & & property . name = = " hdr " ) {
property . usage = PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL ;
}
}
2014-02-10 02:10:30 +01:00
void Viewport : : _bind_methods ( ) {
2017-04-23 14:10:41 +02:00
ClassDB : : bind_method ( D_METHOD ( " set_use_arvr " , " use " ) , & Viewport : : set_use_arvr ) ;
ClassDB : : bind_method ( D_METHOD ( " use_arvr " ) , & Viewport : : use_arvr ) ;
2017-03-05 16:44:50 +01:00
ClassDB : : bind_method ( D_METHOD ( " set_size " , " size " ) , & Viewport : : set_size ) ;
2017-02-13 12:47:24 +01:00
ClassDB : : bind_method ( D_METHOD ( " get_size " ) , & Viewport : : get_size ) ;
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 ) ;
ClassDB : : bind_method ( D_METHOD ( " set_world " , " world " ) , & Viewport : : set_world ) ;
ClassDB : : bind_method ( D_METHOD ( " get_world " ) , & Viewport : : get_world ) ;
ClassDB : : bind_method ( D_METHOD ( " find_world " ) , & Viewport : : find_world ) ;
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-02-13 12:47:24 +01:00
ClassDB : : bind_method ( D_METHOD ( " _vp_input " ) , & Viewport : : _vp_input ) ;
2017-03-05 16:44:50 +01:00
ClassDB : : bind_method ( D_METHOD ( " _vp_input_text " , " text " ) , & Viewport : : _vp_input_text ) ;
2017-02-13 12:47:24 +01:00
ClassDB : : bind_method ( D_METHOD ( " _vp_unhandled_input " ) , & Viewport : : _vp_unhandled_input ) ;
2014-02-10 02:10:30 +01:00
2017-03-05 16:44:50 +01:00
ClassDB : : bind_method ( D_METHOD ( " set_size_override " , " enable " , " size " , " margin " ) , & Viewport : : set_size_override , DEFVAL ( Size2 ( - 1 , - 1 ) ) , DEFVAL ( Size2 ( 0 , 0 ) ) ) ;
2017-02-13 12:47:24 +01:00
ClassDB : : bind_method ( D_METHOD ( " get_size_override " ) , & Viewport : : get_size_override ) ;
ClassDB : : bind_method ( D_METHOD ( " is_size_override_enabled " ) , & Viewport : : is_size_override_enabled ) ;
2017-03-05 16:44:50 +01:00
ClassDB : : bind_method ( D_METHOD ( " set_size_override_stretch " , " enabled " ) , & Viewport : : set_size_override_stretch ) ;
2017-02-13 12:47:24 +01:00
ClassDB : : bind_method ( D_METHOD ( " is_size_override_stretch_enabled " ) , & Viewport : : is_size_override_stretch_enabled ) ;
2014-02-10 02:10:30 +01:00
2017-03-05 16:44:50 +01:00
ClassDB : : bind_method ( D_METHOD ( " set_vflip " , " enable " ) , & Viewport : : set_vflip ) ;
2017-02-13 12:47:24 +01:00
ClassDB : : bind_method ( D_METHOD ( " get_vflip " ) , & Viewport : : get_vflip ) ;
2016-03-09 00:00:52 +01:00
2017-08-31 16:01:36 +02:00
ClassDB : : bind_method ( D_METHOD ( " set_clear_mode " , " mode " ) , & Viewport : : set_clear_mode ) ;
ClassDB : : bind_method ( D_METHOD ( " get_clear_mode " ) , & Viewport : : get_clear_mode ) ;
2014-04-10 05:18:27 +02:00
2017-03-05 16:44:50 +01:00
ClassDB : : bind_method ( D_METHOD ( " set_update_mode " , " mode " ) , & Viewport : : set_update_mode ) ;
2017-02-13 12:47:24 +01:00
ClassDB : : bind_method ( D_METHOD ( " get_update_mode " ) , & Viewport : : get_update_mode ) ;
2014-05-14 06:22:15 +02: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
2017-03-05 16:44:50 +01:00
ClassDB : : bind_method ( D_METHOD ( " set_hdr " , " enable " ) , & Viewport : : set_hdr ) ;
2017-02-13 12:47:24 +01:00
ClassDB : : bind_method ( D_METHOD ( " get_hdr " ) , & Viewport : : get_hdr ) ;
2014-02-26 14:08:17 +01:00
2017-06-09 05:23:50 +02:00
ClassDB : : bind_method ( D_METHOD ( " set_usage " , " usage " ) , & Viewport : : set_usage ) ;
ClassDB : : bind_method ( D_METHOD ( " get_usage " ) , & Viewport : : get_usage ) ;
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 ) ;
2017-08-09 13:19:41 +02:00
ClassDB : : bind_method ( D_METHOD ( " input " , " local_event " ) , & Viewport : : input ) ;
ClassDB : : bind_method ( D_METHOD ( " unhandled_input " , " local_event " ) , & Viewport : : unhandled_input ) ;
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
2017-03-05 16:44:50 +01:00
ClassDB : : bind_method ( D_METHOD ( " set_use_own_world " , " enable " ) , & Viewport : : set_use_own_world ) ;
2017-02-13 12:47:24 +01:00
ClassDB : : bind_method ( D_METHOD ( " is_using_own_world " ) , & Viewport : : is_using_own_world ) ;
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 ) ;
2017-03-05 16:44:50 +01:00
ClassDB : : bind_method ( D_METHOD ( " set_attach_to_screen_rect " , " rect " ) , & Viewport : : set_attach_to_screen_rect ) ;
2019-05-08 20:25:34 +02:00
ClassDB : : bind_method ( D_METHOD ( " set_use_render_direct_to_screen " , " enable " ) , & Viewport : : set_use_render_direct_to_screen ) ;
ClassDB : : bind_method ( D_METHOD ( " is_using_render_direct_to_screen " ) , & Viewport : : is_using_render_direct_to_screen ) ;
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-02-13 12:47:24 +01:00
ClassDB : : bind_method ( D_METHOD ( " gui_has_modal_stack " ) , & Viewport : : gui_has_modal_stack ) ;
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
2018-09-14 21:35:52 +02:00
ClassDB : : bind_method ( D_METHOD ( " get_modal_stack_top " ) , & Viewport : : get_modal_stack_top ) ;
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
2017-03-05 16:44:50 +01:00
ClassDB : : bind_method ( D_METHOD ( " set_disable_3d " , " disable " ) , & Viewport : : set_disable_3d ) ;
2017-02-13 12:47:24 +01:00
ClassDB : : bind_method ( D_METHOD ( " is_3d_disabled " ) , & Viewport : : is_3d_disabled ) ;
2016-10-05 06:26:35 +02:00
2018-04-30 14:30:11 +02:00
ClassDB : : bind_method ( D_METHOD ( " set_keep_3d_linear " , " keep_3d_linear " ) , & Viewport : : set_keep_3d_linear ) ;
ClassDB : : bind_method ( D_METHOD ( " get_keep_3d_linear " ) , & Viewport : : get_keep_3d_linear ) ;
2017-02-13 12:47:24 +01:00
ClassDB : : bind_method ( D_METHOD ( " _gui_show_tooltip " ) , & Viewport : : _gui_show_tooltip ) ;
ClassDB : : bind_method ( D_METHOD ( " _gui_remove_focus " ) , & Viewport : : _gui_remove_focus ) ;
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 ) ;
2017-12-28 10:01:22 +01:00
ClassDB : : bind_method ( D_METHOD ( " _subwindow_visibility_changed " ) , & Viewport : : _subwindow_visibility_changed ) ;
2017-04-23 14:10:41 +02:00
ADD_PROPERTY ( PropertyInfo ( Variant : : BOOL , " arvr " ) , " set_use_arvr " , " use_arvr " ) ;
2017-08-27 07:03:19 +02:00
ADD_PROPERTY ( PropertyInfo ( Variant : : VECTOR2 , " size " ) , " set_size " , " get_size " ) ;
2017-03-05 16:44:50 +01:00
ADD_PROPERTY ( PropertyInfo ( Variant : : BOOL , " own_world " ) , " set_use_own_world " , " is_using_own_world " ) ;
ADD_PROPERTY ( PropertyInfo ( Variant : : OBJECT , " world " , PROPERTY_HINT_RESOURCE_TYPE , " World " ) , " set_world " , " get_world " ) ;
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 " , " " ) ;
ADD_PROPERTY ( PropertyInfo ( Variant : : INT , " msaa " , PROPERTY_HINT_ENUM , " Disabled,2x,4x,8x,16x " ) , " set_msaa " , " get_msaa " ) ;
ADD_PROPERTY ( PropertyInfo ( Variant : : BOOL , " hdr " ) , " set_hdr " , " get_hdr " ) ;
ADD_PROPERTY ( PropertyInfo ( Variant : : BOOL , " disable_3d " ) , " set_disable_3d " , " is_3d_disabled " ) ;
2018-04-30 14:30:11 +02:00
ADD_PROPERTY ( PropertyInfo ( Variant : : BOOL , " keep_3d_linear " ) , " set_keep_3d_linear " , " get_keep_3d_linear " ) ;
2017-06-09 05:23:50 +02:00
ADD_PROPERTY ( PropertyInfo ( Variant : : INT , " usage " , PROPERTY_HINT_ENUM , " 2D,2D No-Sampling,3D,3D No-Effects " ) , " set_usage " , " get_usage " ) ;
2019-05-08 20:25:34 +02:00
ADD_PROPERTY ( PropertyInfo ( Variant : : BOOL , " render_direct_to_screen " ) , " set_use_render_direct_to_screen " , " is_using_render_direct_to_screen " ) ;
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 " ) ;
2017-03-05 16:44:50 +01:00
ADD_GROUP ( " Render Target " , " render_target_ " ) ;
ADD_PROPERTY ( PropertyInfo ( Variant : : BOOL , " render_target_v_flip " ) , " set_vflip " , " get_vflip " ) ;
2017-10-19 13:13:44 +02:00
ADD_PROPERTY ( PropertyInfo ( Variant : : INT , " render_target_clear_mode " , PROPERTY_HINT_ENUM , " Always,Never,Next Frame " ) , " set_clear_mode " , " get_clear_mode " ) ;
2017-03-05 16:44:50 +01:00
ADD_PROPERTY ( PropertyInfo ( Variant : : INT , " render_target_update_mode " , PROPERTY_HINT_ENUM , " Disabled,Once,When Visible,Always " ) , " set_update_mode " , " get_update_mode " ) ;
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 " ) ;
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 " ) ) ;
2014-02-26 14:08:17 +01:00
2017-08-20 17:45:01 +02:00
BIND_ENUM_CONSTANT ( UPDATE_DISABLED ) ;
BIND_ENUM_CONSTANT ( UPDATE_ONCE ) ;
BIND_ENUM_CONSTANT ( UPDATE_WHEN_VISIBLE ) ;
BIND_ENUM_CONSTANT ( UPDATE_ALWAYS ) ;
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 ) ;
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 ) ;
BIND_ENUM_CONSTANT ( DEBUG_DRAW_OVERDRAW ) ;
BIND_ENUM_CONSTANT ( DEBUG_DRAW_WIREFRAME ) ;
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 ) ;
2017-09-12 21:09:06 +02:00
BIND_ENUM_CONSTANT ( USAGE_2D ) ;
BIND_ENUM_CONSTANT ( USAGE_2D_NO_SAMPLING ) ;
BIND_ENUM_CONSTANT ( USAGE_3D ) ;
BIND_ENUM_CONSTANT ( USAGE_3D_NO_EFFECTS ) ;
BIND_ENUM_CONSTANT ( CLEAR_MODE_ALWAYS ) ;
BIND_ENUM_CONSTANT ( CLEAR_MODE_NEVER ) ;
BIND_ENUM_CONSTANT ( CLEAR_MODE_ONLY_NEXT_FRAME ) ;
2014-02-10 02:10:30 +01:00
}
2017-12-28 10:01:22 +01:00
void Viewport : : _subwindow_visibility_changed ( ) {
// unfortunately, we don't know the sender, i.e. which subwindow changed;
// so we have to check them all.
gui . subwindow_visibility_dirty = true ;
}
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
viewport = VisualServer : : get_singleton ( ) - > viewport_create ( ) ;
2017-03-05 16:44:50 +01:00
texture_rid = VisualServer : : get_singleton ( ) - > viewport_get_texture ( viewport ) ;
texture_flags = 0 ;
2017-01-10 22:02:19 +01:00
2019-05-08 20:25:34 +02:00
render_direct_to_screen = false ;
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 ( ) ) ;
2017-12-04 19:55:20 +01:00
VS : : get_singleton ( ) - > texture_set_proxy ( default_texture - > proxy , texture_rid ) ;
2017-01-10 22:02:19 +01:00
2017-01-15 20:06:14 +01:00
//internal_listener = SpatialSoundServer::get_singleton()->listener_create();
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 ;
parent = NULL ;
listener = NULL ;
camera = NULL ;
2018-08-25 00:03:26 +02:00
canvas_layers . insert ( NULL ) ; // This eases picking code (interpreted as the canvas of the Viewport)
2017-04-23 14:10:41 +02:00
arvr = false ;
2017-03-05 16:44:50 +01:00
size_override = false ;
size_override_stretch = false ;
size_override_size = Size2 ( 1 , 1 ) ;
gen_mipmaps = false ;
vflip = false ;
2017-08-31 16:01:36 +02:00
2016-10-03 21:33:42 +02:00
//clear=true;
2017-03-05 16:44:50 +01:00
update_mode = UPDATE_WHEN_VISIBLE ;
2014-02-10 02:10:30 +01:00
2017-03-05 16:44:50 +01:00
physics_object_picking = false ;
physics_object_capture = 0 ;
physics_object_over = 0 ;
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 ;
disable_3d = false ;
2018-04-30 14:30:11 +02:00
keep_3d_linear = 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 ) ;
2018-10-05 18:43:53 +02:00
ProjectSettings : : get_singleton ( ) - > set_custom_property_info ( " gui/timers/tooltip_delay_sec " , PropertyInfo ( Variant : : REAL , " 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
2017-03-05 16:44:50 +01:00
gui . tooltip = NULL ;
gui . tooltip_label = NULL ;
gui . drag_preview = NULL ;
gui . drag_attempted = false ;
gui . canvas_sort_index = 0 ;
2018-02-28 21:55:13 +01:00
gui . roots_order_dirty = false ;
2019-02-22 21:42:29 +01:00
gui . mouse_focus = NULL ;
gui . last_mouse_focus = NULL ;
2015-09-20 18:03:46 +02:00
2017-03-05 16:44:50 +01:00
msaa = MSAA_DISABLED ;
2017-12-21 14:17:35 +01:00
hdr = true ;
2017-06-09 05:23:50 +02:00
usage = USAGE_3D ;
2017-06-11 20:52:03 +02:00
debug_draw = DEBUG_DRAW_DISABLED ;
2017-08-31 16:01:36 +02:00
clear_mode = CLEAR_MODE_ALWAYS ;
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 ;
physics_last_id = 0 ; //ensures first time there will be a check
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 ( ) ) {
E - > get ( ) - > vp = NULL ;
2017-01-10 05:04:31 +01:00
}
2017-03-05 16:44:50 +01:00
VisualServer : : get_singleton ( ) - > free ( viewport ) ;
2017-01-15 20:06:14 +01:00
//SpatialSoundServer::get_singleton()->free(internal_listener);
//SpatialSound2DServer::get_singleton()->free(internal_listener_2d);
2014-02-10 02:10:30 +01:00
}