2014-02-10 02:10:30 +01:00
/*************************************************************************/
2017-09-01 16:07:55 +02:00
/* scene_tree.cpp */
2014-02-10 02:10:30 +01:00
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
2017-08-27 14:16:55 +02:00
/* https://godotengine.org */
2014-02-10 02:10:30 +01:00
/*************************************************************************/
2020-01-01 11:16:22 +01:00
/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */
/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */
2014-02-10 02:10:30 +01:00
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
/* "Software"), to deal in the Software without restriction, including */
/* without limitation the rights to use, copy, modify, merge, publish, */
/* distribute, sublicense, and/or sell copies of the Software, and to */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions: */
/* */
/* The above copyright notice and this permission notice shall be */
/* included in all copies or substantial portions of the Software. */
/* */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
2018-01-05 00:50:27 +01:00
2017-06-27 03:58:03 +02:00
# include "scene_tree.h"
2014-02-10 02:10:30 +01:00
2020-02-27 03:30:20 +01:00
# include "core/debugger/engine_debugger.h"
2020-03-04 17:36:09 +01:00
# include "core/input/input_filter.h"
2018-09-11 18:13:45 +02:00
# include "core/io/marshalls.h"
# include "core/io/resource_loader.h"
# include "core/message_queue.h"
2019-03-09 03:05:59 +01:00
# include "core/os/dir_access.h"
2018-09-11 18:13:45 +02:00
# include "core/os/keyboard.h"
# include "core/os/os.h"
# include "core/print_string.h"
# include "core/project_settings.h"
2014-02-10 02:10:30 +01:00
# include "node.h"
2020-02-07 02:52:05 +01:00
# include "scene/debugger/scene_debugger.h"
2017-12-19 22:48:30 +01:00
# include "scene/resources/dynamic_font.h"
2015-09-20 18:03:46 +02:00
# include "scene/resources/material.h"
# include "scene/resources/mesh.h"
2017-03-05 16:44:50 +01:00
# include "scene/resources/packed_scene.h"
# include "scene/scene_string_names.h"
2020-03-03 14:36:29 +01:00
# include "servers/display_server.h"
2020-03-27 19:21:27 +01:00
# include "servers/navigation_server_3d.h"
# include "servers/physics_server_2d.h"
# include "servers/physics_server_3d.h"
2020-03-04 02:51:12 +01:00
# include "window.h"
2016-08-07 02:39:50 +02:00
2017-08-27 21:07:15 +02:00
# include <stdio.h>
2016-08-07 02:39:50 +02:00
void SceneTreeTimer : : _bind_methods ( ) {
2017-03-05 16:44:50 +01:00
ClassDB : : bind_method ( D_METHOD ( " set_time_left " , " time " ) , & SceneTreeTimer : : set_time_left ) ;
ClassDB : : bind_method ( D_METHOD ( " get_time_left " ) , & SceneTreeTimer : : get_time_left ) ;
2016-08-07 02:39:50 +02:00
Variant: Added 64-bit packed arrays, renamed Variant::REAL to FLOAT.
- Renames PackedIntArray to PackedInt32Array.
- Renames PackedFloatArray to PackedFloat32Array.
- Adds PackedInt64Array and PackedFloat64Array.
- Renames Variant::REAL to Variant::FLOAT for consistency.
Packed arrays are for storing large amount of data and creating stuff like
meshes, buffers. textures, etc. Forcing them to be 64 is a huge waste of
memory. That said, many users requested the ability to have 64 bits packed
arrays for their games, so this is just an optional added type.
For Variant, the float datatype is always 64 bits, and exposed as `float`.
We still have `real_t` which is the datatype that can change from 32 to 64
bits depending on a compile flag (not entirely working right now, but that's
the idea). It affects math related datatypes and code only.
Neither Variant nor PackedArray make use of real_t, which is only intended
for math precision, so the term is removed from there to keep only float.
2020-02-24 19:20:53 +01:00
ADD_PROPERTY ( PropertyInfo ( Variant : : FLOAT , " time_left " ) , " set_time_left " , " get_time_left " ) ;
2018-01-11 23:35:12 +01:00
2016-08-07 02:39:50 +02:00
ADD_SIGNAL ( MethodInfo ( " timeout " ) ) ;
}
void SceneTreeTimer : : set_time_left ( float p_time ) {
2017-03-05 16:44:50 +01:00
time_left = p_time ;
2016-08-07 02:39:50 +02:00
}
float SceneTreeTimer : : get_time_left ( ) const {
return time_left ;
}
2017-02-14 00:34:33 +01:00
void SceneTreeTimer : : set_pause_mode_process ( bool p_pause_mode_process ) {
2019-10-14 11:40:55 +02:00
process_pause = p_pause_mode_process ;
2017-02-14 00:34:33 +01:00
}
bool SceneTreeTimer : : is_pause_mode_process ( ) {
return process_pause ;
}
2016-08-07 02:39:50 +02:00
2019-10-19 18:45:17 +02:00
void SceneTreeTimer : : release_connections ( ) {
List < Connection > connections ;
get_all_signal_connections ( & connections ) ;
for ( List < Connection > : : Element * E = connections . front ( ) ; E ; E = E - > next ( ) ) {
Connection const & connection = E - > get ( ) ;
2020-02-21 23:26:13 +01:00
disconnect ( connection . signal . get_name ( ) , connection . callable ) ;
2019-10-19 18:45:17 +02:00
}
}
2016-08-07 02:39:50 +02:00
SceneTreeTimer : : SceneTreeTimer ( ) {
2017-03-05 16:44:50 +01:00
time_left = 0 ;
2017-02-14 00:34:33 +01:00
process_pause = true ;
2016-08-07 02:39:50 +02:00
}
2014-11-06 01:20:42 +01:00
void SceneTree : : tree_changed ( ) {
2014-02-10 02:10:30 +01:00
tree_version + + ;
emit_signal ( tree_changed_name ) ;
}
2017-10-19 02:30:27 +02:00
void SceneTree : : node_added ( Node * p_node ) {
emit_signal ( node_added_name , p_node ) ;
}
2014-11-06 01:20:42 +01:00
void SceneTree : : node_removed ( Node * p_node ) {
2014-02-10 02:10:30 +01:00
2017-03-05 16:44:50 +01:00
if ( current_scene = = p_node ) {
2020-04-02 01:20:12 +02:00
current_scene = nullptr ;
2015-05-17 21:33:35 +02:00
}
2017-03-05 16:44:50 +01:00
emit_signal ( node_removed_name , p_node ) ;
if ( call_lock > 0 )
2014-02-10 02:10:30 +01:00
call_skip . insert ( p_node ) ;
}
2019-05-24 15:27:22 +02:00
void SceneTree : : node_renamed ( Node * p_node ) {
emit_signal ( node_renamed_name , p_node ) ;
}
2017-03-05 16:44:50 +01:00
SceneTree : : Group * SceneTree : : add_to_group ( const StringName & p_group , Node * p_node ) {
2014-02-10 02:10:30 +01:00
2017-03-05 16:44:50 +01:00
Map < StringName , Group > : : Element * E = group_map . find ( p_group ) ;
2014-02-10 02:10:30 +01:00
if ( ! E ) {
2017-03-05 16:44:50 +01:00
E = group_map . insert ( p_group , Group ( ) ) ;
2014-02-10 02:10:30 +01:00
}
2019-08-08 22:11:48 +02:00
ERR_FAIL_COND_V_MSG ( E - > get ( ) . nodes . find ( p_node ) ! = - 1 , & E - > get ( ) , " Already in group: " + p_group + " . " ) ;
2014-02-10 02:10:30 +01:00
E - > get ( ) . nodes . push_back ( p_node ) ;
2016-06-08 03:08:12 +02:00
//E->get().last_tree_version=0;
2017-03-05 16:44:50 +01:00
E - > get ( ) . changed = true ;
2016-06-08 03:08:12 +02:00
return & E - > get ( ) ;
2014-02-10 02:10:30 +01:00
}
2017-03-05 16:44:50 +01:00
void SceneTree : : remove_from_group ( const StringName & p_group , Node * p_node ) {
2014-02-10 02:10:30 +01:00
2017-03-05 16:44:50 +01:00
Map < StringName , Group > : : Element * E = group_map . find ( p_group ) ;
2014-02-10 02:10:30 +01:00
ERR_FAIL_COND ( ! E ) ;
E - > get ( ) . nodes . erase ( p_node ) ;
if ( E - > get ( ) . nodes . empty ( ) )
group_map . erase ( E ) ;
}
2018-07-02 07:30:40 +02:00
void SceneTree : : make_group_changed ( const StringName & p_group ) {
Map < StringName , Group > : : Element * E = group_map . find ( p_group ) ;
if ( E )
E - > get ( ) . changed = true ;
}
2017-10-30 19:43:19 +01:00
void SceneTree : : flush_transform_notifications ( ) {
2014-02-10 02:10:30 +01:00
2017-03-05 16:44:50 +01:00
SelfList < Node > * n = xform_change_list . first ( ) ;
while ( n ) {
2014-02-10 02:10:30 +01:00
2017-03-05 16:44:50 +01:00
Node * node = n - > self ( ) ;
SelfList < Node > * nx = n - > next ( ) ;
2014-02-10 02:10:30 +01:00
xform_change_list . remove ( n ) ;
2017-03-05 16:44:50 +01:00
n = nx ;
2014-02-10 02:10:30 +01:00
node - > notification ( NOTIFICATION_TRANSFORM_CHANGED ) ;
}
}
2014-11-06 01:20:42 +01:00
void SceneTree : : _flush_ugc ( ) {
2014-02-10 02:10:30 +01:00
2017-03-05 16:44:50 +01:00
ugc_locked = true ;
2014-02-10 02:10:30 +01:00
while ( unique_group_calls . size ( ) ) {
2020-03-17 07:33:00 +01:00
Map < UGCall , Vector < Variant > > : : Element * E = unique_group_calls . front ( ) ;
2014-02-10 02:10:30 +01:00
Variant v [ VARIANT_ARG_MAX ] ;
2017-03-05 16:44:50 +01:00
for ( int i = 0 ; i < E - > get ( ) . size ( ) ; i + + )
v [ i ] = E - > get ( ) [ i ] ;
2014-02-10 02:10:30 +01:00
2017-03-05 16:44:50 +01:00
call_group_flags ( GROUP_CALL_REALTIME , E - > key ( ) . group , E - > key ( ) . call , v [ 0 ] , v [ 1 ] , v [ 2 ] , v [ 3 ] , v [ 4 ] ) ;
2014-02-10 02:10:30 +01:00
unique_group_calls . erase ( E ) ;
}
2017-03-05 16:44:50 +01:00
ugc_locked = false ;
2014-02-10 02:10:30 +01:00
}
2018-07-02 07:30:40 +02:00
void SceneTree : : _update_group_order ( Group & g , bool p_use_priority ) {
2014-02-10 02:10:30 +01:00
2016-06-08 03:08:12 +02:00
if ( ! g . changed )
2014-02-10 02:10:30 +01:00
return ;
if ( g . nodes . empty ( ) )
return ;
2018-07-25 03:11:03 +02:00
Node * * nodes = g . nodes . ptrw ( ) ;
2017-03-05 16:44:50 +01:00
int node_count = g . nodes . size ( ) ;
2016-06-08 03:08:12 +02:00
2018-07-02 07:30:40 +02:00
if ( p_use_priority ) {
SortArray < Node * , Node : : ComparatorWithPriority > node_sort ;
node_sort . sort ( nodes , node_count ) ;
} else {
SortArray < Node * , Node : : Comparator > node_sort ;
node_sort . sort ( nodes , node_count ) ;
}
2017-03-05 16:44:50 +01:00
g . changed = false ;
2014-02-10 02:10:30 +01:00
}
2017-03-05 16:44:50 +01:00
void SceneTree : : call_group_flags ( uint32_t p_call_flags , const StringName & p_group , const StringName & p_function , VARIANT_ARG_DECLARE ) {
2014-02-10 02:10:30 +01:00
2017-03-05 16:44:50 +01:00
Map < StringName , Group > : : Element * E = group_map . find ( p_group ) ;
2014-02-10 02:10:30 +01:00
if ( ! E )
return ;
2017-03-05 16:44:50 +01:00
Group & g = E - > get ( ) ;
2014-02-10 02:10:30 +01:00
if ( g . nodes . empty ( ) )
return ;
2017-03-05 16:44:50 +01:00
if ( p_call_flags & GROUP_CALL_UNIQUE & & ! ( p_call_flags & GROUP_CALL_REALTIME ) ) {
2014-02-10 02:10:30 +01:00
ERR_FAIL_COND ( ugc_locked ) ;
UGCall ug ;
2017-03-05 16:44:50 +01:00
ug . call = p_function ;
ug . group = p_group ;
2014-02-10 02:10:30 +01:00
if ( unique_group_calls . has ( ug ) )
return ;
VARIANT_ARGPTRS ;
Vector < Variant > args ;
2017-03-05 16:44:50 +01:00
for ( int i = 0 ; i < VARIANT_ARG_MAX ; i + + ) {
if ( argptr [ i ] - > get_type ( ) = = Variant : : NIL )
2014-02-10 02:10:30 +01:00
break ;
args . push_back ( * argptr [ i ] ) ;
}
2017-03-05 16:44:50 +01:00
unique_group_calls [ ug ] = args ;
2014-02-10 02:10:30 +01:00
return ;
}
2016-06-08 03:08:12 +02:00
_update_group_order ( g ) ;
2017-03-05 16:44:50 +01:00
Vector < Node * > nodes_copy = g . nodes ;
2018-07-25 03:11:03 +02:00
Node * * nodes = nodes_copy . ptrw ( ) ;
2017-03-05 16:44:50 +01:00
int node_count = nodes_copy . size ( ) ;
2014-02-10 02:10:30 +01:00
call_lock + + ;
2017-03-05 16:44:50 +01:00
if ( p_call_flags & GROUP_CALL_REVERSE ) {
2014-02-10 02:10:30 +01:00
2017-03-05 16:44:50 +01:00
for ( int i = node_count - 1 ; i > = 0 ; i - - ) {
2014-02-10 02:10:30 +01:00
if ( call_lock & & call_skip . has ( nodes [ i ] ) )
continue ;
2017-03-05 16:44:50 +01:00
if ( p_call_flags & GROUP_CALL_REALTIME ) {
if ( p_call_flags & GROUP_CALL_MULTILEVEL )
nodes [ i ] - > call_multilevel ( p_function , VARIANT_ARG_PASS ) ;
2014-02-10 02:10:30 +01:00
else
2017-03-05 16:44:50 +01:00
nodes [ i ] - > call ( p_function , VARIANT_ARG_PASS ) ;
2014-02-10 02:10:30 +01:00
} else
2017-03-05 16:44:50 +01:00
MessageQueue : : get_singleton ( ) - > push_call ( nodes [ i ] , p_function , VARIANT_ARG_PASS ) ;
2014-02-10 02:10:30 +01:00
}
} else {
2017-03-05 16:44:50 +01:00
for ( int i = 0 ; i < node_count ; i + + ) {
2014-02-10 02:10:30 +01:00
if ( call_lock & & call_skip . has ( nodes [ i ] ) )
continue ;
2017-03-05 16:44:50 +01:00
if ( p_call_flags & GROUP_CALL_REALTIME ) {
if ( p_call_flags & GROUP_CALL_MULTILEVEL )
nodes [ i ] - > call_multilevel ( p_function , VARIANT_ARG_PASS ) ;
2014-02-10 02:10:30 +01:00
else
2017-03-05 16:44:50 +01:00
nodes [ i ] - > call ( p_function , VARIANT_ARG_PASS ) ;
2014-02-10 02:10:30 +01:00
} else
2017-03-05 16:44:50 +01:00
MessageQueue : : get_singleton ( ) - > push_call ( nodes [ i ] , p_function , VARIANT_ARG_PASS ) ;
2014-02-10 02:10:30 +01:00
}
}
call_lock - - ;
2017-03-05 16:44:50 +01:00
if ( call_lock = = 0 )
2014-02-10 02:10:30 +01:00
call_skip . clear ( ) ;
}
2017-03-05 16:44:50 +01:00
void SceneTree : : notify_group_flags ( uint32_t p_call_flags , const StringName & p_group , int p_notification ) {
2014-02-10 02:10:30 +01:00
2017-03-05 16:44:50 +01:00
Map < StringName , Group > : : Element * E = group_map . find ( p_group ) ;
2014-02-10 02:10:30 +01:00
if ( ! E )
return ;
2017-03-05 16:44:50 +01:00
Group & g = E - > get ( ) ;
2014-02-10 02:10:30 +01:00
if ( g . nodes . empty ( ) )
return ;
_update_group_order ( g ) ;
2017-03-05 16:44:50 +01:00
Vector < Node * > nodes_copy = g . nodes ;
2018-07-25 03:11:03 +02:00
Node * * nodes = nodes_copy . ptrw ( ) ;
2017-03-05 16:44:50 +01:00
int node_count = nodes_copy . size ( ) ;
2014-02-10 02:10:30 +01:00
call_lock + + ;
2017-03-05 16:44:50 +01:00
if ( p_call_flags & GROUP_CALL_REVERSE ) {
2014-02-10 02:10:30 +01:00
2017-03-05 16:44:50 +01:00
for ( int i = node_count - 1 ; i > = 0 ; i - - ) {
2014-02-10 02:10:30 +01:00
if ( call_lock & & call_skip . has ( nodes [ i ] ) )
continue ;
2017-03-05 16:44:50 +01:00
if ( p_call_flags & GROUP_CALL_REALTIME )
2014-02-10 02:10:30 +01:00
nodes [ i ] - > notification ( p_notification ) ;
else
2017-03-05 16:44:50 +01:00
MessageQueue : : get_singleton ( ) - > push_notification ( nodes [ i ] , p_notification ) ;
2014-02-10 02:10:30 +01:00
}
} else {
2017-03-05 16:44:50 +01:00
for ( int i = 0 ; i < node_count ; i + + ) {
2014-02-10 02:10:30 +01:00
if ( call_lock & & call_skip . has ( nodes [ i ] ) )
continue ;
2017-03-05 16:44:50 +01:00
if ( p_call_flags & GROUP_CALL_REALTIME )
2014-02-10 02:10:30 +01:00
nodes [ i ] - > notification ( p_notification ) ;
else
2017-03-05 16:44:50 +01:00
MessageQueue : : get_singleton ( ) - > push_notification ( nodes [ i ] , p_notification ) ;
2014-02-10 02:10:30 +01:00
}
}
call_lock - - ;
2017-03-05 16:44:50 +01:00
if ( call_lock = = 0 )
2014-02-10 02:10:30 +01:00
call_skip . clear ( ) ;
}
2017-03-05 16:44:50 +01:00
void SceneTree : : set_group_flags ( uint32_t p_call_flags , const StringName & p_group , const String & p_name , const Variant & p_value ) {
2014-02-10 02:10:30 +01:00
2017-03-05 16:44:50 +01:00
Map < StringName , Group > : : Element * E = group_map . find ( p_group ) ;
2014-02-10 02:10:30 +01:00
if ( ! E )
return ;
2017-03-05 16:44:50 +01:00
Group & g = E - > get ( ) ;
2014-02-10 02:10:30 +01:00
if ( g . nodes . empty ( ) )
return ;
_update_group_order ( g ) ;
2017-03-05 16:44:50 +01:00
Vector < Node * > nodes_copy = g . nodes ;
2018-07-25 03:11:03 +02:00
Node * * nodes = nodes_copy . ptrw ( ) ;
2017-03-05 16:44:50 +01:00
int node_count = nodes_copy . size ( ) ;
2014-02-10 02:10:30 +01:00
call_lock + + ;
2017-03-05 16:44:50 +01:00
if ( p_call_flags & GROUP_CALL_REVERSE ) {
2014-02-10 02:10:30 +01:00
2017-03-05 16:44:50 +01:00
for ( int i = node_count - 1 ; i > = 0 ; i - - ) {
2014-02-10 02:10:30 +01:00
if ( call_lock & & call_skip . has ( nodes [ i ] ) )
continue ;
2017-03-05 16:44:50 +01:00
if ( p_call_flags & GROUP_CALL_REALTIME )
nodes [ i ] - > set ( p_name , p_value ) ;
2014-02-10 02:10:30 +01:00
else
2017-03-05 16:44:50 +01:00
MessageQueue : : get_singleton ( ) - > push_set ( nodes [ i ] , p_name , p_value ) ;
2014-02-10 02:10:30 +01:00
}
} else {
2017-03-05 16:44:50 +01:00
for ( int i = 0 ; i < node_count ; i + + ) {
2014-02-10 02:10:30 +01:00
if ( call_lock & & call_skip . has ( nodes [ i ] ) )
continue ;
2017-03-05 16:44:50 +01:00
if ( p_call_flags & GROUP_CALL_REALTIME )
nodes [ i ] - > set ( p_name , p_value ) ;
2014-02-10 02:10:30 +01:00
else
2017-03-05 16:44:50 +01:00
MessageQueue : : get_singleton ( ) - > push_set ( nodes [ i ] , p_name , p_value ) ;
2014-02-10 02:10:30 +01:00
}
}
call_lock - - ;
2017-03-05 16:44:50 +01:00
if ( call_lock = = 0 )
2014-02-10 02:10:30 +01:00
call_skip . clear ( ) ;
}
2017-03-05 16:44:50 +01:00
void SceneTree : : call_group ( const StringName & p_group , const StringName & p_function , VARIANT_ARG_DECLARE ) {
2019-04-07 06:19:52 +02:00
call_group_flags ( 0 , p_group , p_function , VARIANT_ARG_PASS ) ;
2017-01-14 14:03:53 +01:00
}
2017-03-05 16:44:50 +01:00
void SceneTree : : notify_group ( const StringName & p_group , int p_notification ) {
2017-01-14 14:03:53 +01:00
2017-03-05 16:44:50 +01:00
notify_group_flags ( 0 , p_group , p_notification ) ;
2017-01-14 14:03:53 +01:00
}
2017-03-05 16:44:50 +01:00
void SceneTree : : set_group ( const StringName & p_group , const String & p_name , const Variant & p_value ) {
2017-01-14 14:03:53 +01:00
2017-03-05 16:44:50 +01:00
set_group_flags ( 0 , p_group , p_name , p_value ) ;
2017-01-14 14:03:53 +01:00
}
2014-11-06 01:20:42 +01:00
void SceneTree : : init ( ) {
2017-03-05 16:44:50 +01:00
initialized = true ;
2014-11-06 01:20:42 +01:00
root - > _set_tree ( this ) ;
2014-02-10 02:10:30 +01:00
MainLoop : : init ( ) ;
}
2014-11-06 01:20:42 +01:00
bool SceneTree : : iteration ( float p_time ) {
2014-02-10 02:10:30 +01:00
root_lock + + ;
current_frame + + ;
2017-10-30 19:43:19 +01:00
flush_transform_notifications ( ) ;
2014-02-10 02:10:30 +01:00
MainLoop : : iteration ( p_time ) ;
2017-09-30 16:19:07 +02:00
physics_process_time = p_time ;
2014-09-15 16:33:30 +02:00
2017-09-30 16:19:07 +02:00
emit_signal ( " physics_frame " ) ;
2014-09-15 16:33:30 +02:00
2017-09-30 16:19:07 +02:00
_notify_group_pause ( " physics_process_internal " , Node : : NOTIFICATION_INTERNAL_PHYSICS_PROCESS ) ;
_notify_group_pause ( " physics_process " , Node : : NOTIFICATION_PHYSICS_PROCESS ) ;
2014-02-10 02:10:30 +01:00
_flush_ugc ( ) ;
2017-08-08 03:18:12 +02:00
MessageQueue : : get_singleton ( ) - > flush ( ) ; //small little hack
2017-10-30 19:43:19 +01:00
flush_transform_notifications ( ) ;
2017-03-05 16:44:50 +01:00
call_group_flags ( GROUP_CALL_REALTIME , " _viewports " , " update_worlds " ) ;
2014-02-10 02:10:30 +01:00
root_lock - - ;
_flush_delete_queue ( ) ;
2016-10-27 16:50:26 +02:00
_call_idle_callbacks ( ) ;
2014-02-10 02:10:30 +01:00
return _quit ;
}
2017-03-05 16:44:50 +01:00
bool SceneTree : : idle ( float p_time ) {
2014-02-10 02:10:30 +01:00
2017-01-14 12:26:56 +01:00
//print_line("ram: "+itos(OS::get_singleton()->get_static_memory_usage())+" sram: "+itos(OS::get_singleton()->get_dynamic_memory_usage()));
//print_line("node count: "+itos(get_node_count()));
2020-03-27 19:21:27 +01:00
//print_line("TEXTURE RAM: "+itos(RS::get_singleton()->get_render_info(RS::INFO_TEXTURE_MEM_USED)));
2014-02-10 02:10:30 +01:00
root_lock + + ;
MainLoop : : idle ( p_time ) ;
2017-03-05 16:44:50 +01:00
idle_process_time = p_time ;
2014-02-10 02:10:30 +01:00
2018-06-02 14:32:30 +02:00
if ( multiplayer_poll ) {
multiplayer - > poll ( ) ;
}
2016-08-14 23:49:50 +02:00
2014-09-15 16:33:30 +02:00
emit_signal ( " idle_frame " ) ;
2017-08-08 03:18:12 +02:00
MessageQueue : : get_singleton ( ) - > flush ( ) ; //small little hack
2017-10-30 19:43:19 +01:00
flush_transform_notifications ( ) ;
2014-02-10 02:10:30 +01:00
2017-03-05 16:44:50 +01:00
_notify_group_pause ( " idle_process_internal " , Node : : NOTIFICATION_INTERNAL_PROCESS ) ;
_notify_group_pause ( " idle_process " , Node : : NOTIFICATION_PROCESS ) ;
2014-02-10 02:10:30 +01:00
_flush_ugc ( ) ;
2017-08-08 03:18:12 +02:00
MessageQueue : : get_singleton ( ) - > flush ( ) ; //small little hack
2017-10-30 19:43:19 +01:00
flush_transform_notifications ( ) ; //transforms after world update, to avoid unnecessary enter/exit notifications
2017-03-05 16:44:50 +01:00
call_group_flags ( GROUP_CALL_REALTIME , " _viewports " , " update_worlds " ) ;
2014-02-10 02:10:30 +01:00
root_lock - - ;
_flush_delete_queue ( ) ;
2016-08-07 02:39:50 +02:00
//go through timers
2020-03-17 07:33:00 +01:00
List < Ref < SceneTreeTimer > > : : Element * L = timers . back ( ) ; //last element
2018-11-14 00:11:22 +01:00
2020-03-17 07:33:00 +01:00
for ( List < Ref < SceneTreeTimer > > : : Element * E = timers . front ( ) ; E ; ) {
2016-08-07 02:39:50 +02:00
2020-03-17 07:33:00 +01:00
List < Ref < SceneTreeTimer > > : : Element * N = E - > next ( ) ;
2017-02-14 00:34:33 +01:00
if ( pause & & ! E - > get ( ) - > is_pause_mode_process ( ) ) {
2018-11-14 00:11:22 +01:00
if ( E = = L ) {
break ; //break on last, so if new timers were added during list traversal, ignore them.
}
2017-03-05 16:44:50 +01:00
E = N ;
2017-02-14 00:34:33 +01:00
continue ;
}
2016-08-07 02:39:50 +02:00
float time_left = E - > get ( ) - > get_time_left ( ) ;
2017-03-05 16:44:50 +01:00
time_left - = p_time ;
2016-08-07 02:39:50 +02:00
E - > get ( ) - > set_time_left ( time_left ) ;
2017-03-05 16:44:50 +01:00
if ( time_left < 0 ) {
2016-08-07 02:39:50 +02:00
E - > get ( ) - > emit_signal ( " timeout " ) ;
timers . erase ( E ) ;
}
2018-11-14 00:11:22 +01:00
if ( E = = L ) {
break ; //break on last, so if new timers were added during list traversal, ignore them.
}
2017-03-05 16:44:50 +01:00
E = N ;
2016-08-07 02:39:50 +02:00
}
2019-07-29 12:33:38 +02:00
flush_transform_notifications ( ) ; //additional transforms after timers update
2016-10-27 16:50:26 +02:00
_call_idle_callbacks ( ) ;
2017-05-29 02:46:48 +02:00
# ifdef TOOLS_ENABLED
2017-08-19 01:02:56 +02:00
if ( Engine : : get_singleton ( ) - > is_editor_hint ( ) ) {
2017-05-29 02:46:48 +02:00
//simple hack to reload fallback environment if it changed from editor
2017-07-19 22:00:46 +02:00
String env_path = ProjectSettings : : get_singleton ( ) - > get ( " rendering/environment/default_environment " ) ;
2017-05-29 02:46:48 +02:00
env_path = env_path . strip_edges ( ) ; //user may have added a space or two
String cpath ;
Ref < Environment > fallback = get_root ( ) - > get_world ( ) - > get_fallback_environment ( ) ;
if ( fallback . is_valid ( ) ) {
cpath = fallback - > get_path ( ) ;
}
if ( cpath ! = env_path ) {
if ( env_path ! = String ( ) ) {
fallback = ResourceLoader : : load ( env_path ) ;
2017-08-31 13:55:20 +02:00
if ( fallback . is_null ( ) ) {
//could not load fallback, set as empty
ProjectSettings : : get_singleton ( ) - > set ( " rendering/environment/default_environment " , " " ) ;
}
2017-05-29 02:46:48 +02:00
} else {
fallback . unref ( ) ;
}
get_root ( ) - > get_world ( ) - > set_fallback_environment ( fallback ) ;
}
}
# endif
2014-02-10 02:10:30 +01:00
return _quit ;
}
2014-11-06 01:20:42 +01:00
void SceneTree : : finish ( ) {
2014-02-10 02:10:30 +01:00
_flush_delete_queue ( ) ;
_flush_ugc ( ) ;
2017-03-05 16:44:50 +01:00
initialized = false ;
2014-02-10 02:10:30 +01:00
MainLoop : : finish ( ) ;
if ( root ) {
2020-04-02 01:20:12 +02:00
root - > _set_tree ( nullptr ) ;
2018-09-07 20:31:19 +02:00
root - > _propagate_after_exit_tree ( ) ;
2014-02-10 02:10:30 +01:00
memdelete ( root ) ; //delete root
2020-04-02 01:20:12 +02:00
root = nullptr ;
2014-02-10 02:10:30 +01:00
}
2019-10-19 18:45:17 +02:00
// cleanup timers
2020-03-17 07:33:00 +01:00
for ( List < Ref < SceneTreeTimer > > : : Element * E = timers . front ( ) ; E ; E = E - > next ( ) ) {
2019-10-19 18:45:17 +02:00
E - > get ( ) - > release_connections ( ) ;
}
timers . clear ( ) ;
2014-02-10 02:10:30 +01:00
}
2019-12-29 16:39:24 +01:00
void SceneTree : : quit ( int p_exit_code ) {
if ( p_exit_code > = 0 ) {
// Override the exit code if a positive argument is given (the default is `-1`).
// This is a shorthand for calling `set_exit_code()` on the OS singleton then quitting.
OS : : get_singleton ( ) - > set_exit_code ( p_exit_code ) ;
}
2014-02-10 02:10:30 +01:00
2017-03-05 16:44:50 +01:00
_quit = true ;
2014-02-10 02:10:30 +01:00
}
2020-03-04 17:36:09 +01:00
void SceneTree : : _main_window_close ( ) {
2017-01-11 20:34:32 +01:00
2020-03-04 17:36:09 +01:00
if ( accept_quit ) {
_quit = true ;
}
}
void SceneTree : : _main_window_go_back ( ) {
if ( quit_on_go_back ) {
_quit = true ;
}
}
2014-02-10 02:10:30 +01:00
2020-03-04 17:36:09 +01:00
void SceneTree : : _main_window_focus_in ( ) {
InputFilter * id = InputFilter : : get_singleton ( ) ;
if ( id ) {
id - > ensure_touch_mouse_raised ( ) ;
}
}
2019-09-09 23:42:17 +02:00
2020-03-04 17:36:09 +01:00
void SceneTree : : _notification ( int p_notification ) {
2018-02-24 03:04:30 +01:00
2020-03-04 17:36:09 +01:00
switch ( p_notification ) {
2019-09-09 23:42:17 +02:00
2017-01-09 20:43:44 +01:00
case NOTIFICATION_TRANSLATION_CHANGED : {
2017-08-19 01:02:56 +02:00
if ( ! Engine : : get_singleton ( ) - > is_editor_hint ( ) ) {
2019-04-04 15:34:03 +02:00
get_root ( ) - > propagate_notification ( p_notification ) ;
2017-06-28 22:00:18 +02:00
}
2017-01-09 20:43:44 +01:00
} break ;
2019-09-09 23:42:17 +02:00
case NOTIFICATION_OS_MEMORY_WARNING :
case NOTIFICATION_OS_IME_UPDATE :
case NOTIFICATION_WM_ABOUT :
case NOTIFICATION_CRASH :
case NOTIFICATION_APP_RESUMED :
case NOTIFICATION_APP_PAUSED : {
2018-07-02 21:18:58 +02:00
get_root ( ) - > propagate_notification ( p_notification ) ;
} break ;
2014-02-10 02:10:30 +01:00
default :
break ;
} ;
} ;
2014-11-06 01:20:42 +01:00
void SceneTree : : set_auto_accept_quit ( bool p_enable ) {
2014-02-10 02:10:30 +01:00
2017-03-05 16:44:50 +01:00
accept_quit = p_enable ;
2014-02-10 02:10:30 +01:00
}
2017-01-11 20:34:32 +01:00
void SceneTree : : set_quit_on_go_back ( bool p_enable ) {
2017-03-05 16:44:50 +01:00
quit_on_go_back = p_enable ;
2017-01-11 20:34:32 +01:00
}
2017-04-07 16:17:16 +02:00
# ifdef TOOLS_ENABLED
2014-02-10 02:10:30 +01:00
2017-03-05 16:44:50 +01:00
bool SceneTree : : is_node_being_edited ( const Node * p_node ) const {
2017-04-07 16:17:16 +02:00
2017-09-24 17:10:17 +02:00
return Engine : : get_singleton ( ) - > is_editor_hint ( ) & & edited_scene_root & & ( edited_scene_root - > is_a_parent_of ( p_node ) | | edited_scene_root = = p_node ) ;
2014-02-10 02:10:30 +01:00
}
2017-04-07 16:17:16 +02:00
# endif
2014-02-10 02:10:30 +01:00
2017-04-07 16:17:16 +02:00
# ifdef DEBUG_ENABLED
2015-09-19 04:10:58 +02:00
void SceneTree : : set_debug_collisions_hint ( bool p_enabled ) {
2017-03-05 16:44:50 +01:00
debug_collisions_hint = p_enabled ;
2015-09-19 04:10:58 +02:00
}
bool SceneTree : : is_debugging_collisions_hint ( ) const {
return debug_collisions_hint ;
}
2015-09-20 18:03:46 +02:00
void SceneTree : : set_debug_navigation_hint ( bool p_enabled ) {
2017-03-05 16:44:50 +01:00
debug_navigation_hint = p_enabled ;
2015-09-20 18:03:46 +02:00
}
bool SceneTree : : is_debugging_navigation_hint ( ) const {
return debug_navigation_hint ;
}
2017-04-07 16:17:16 +02:00
# endif
2015-09-20 18:03:46 +02:00
2017-03-05 16:44:50 +01:00
void SceneTree : : set_debug_collisions_color ( const Color & p_color ) {
2015-09-20 18:03:46 +02:00
2017-03-05 16:44:50 +01:00
debug_collisions_color = p_color ;
2015-09-20 18:03:46 +02:00
}
Color SceneTree : : get_debug_collisions_color ( ) const {
return debug_collisions_color ;
}
2017-03-05 16:44:50 +01:00
void SceneTree : : set_debug_collision_contact_color ( const Color & p_color ) {
2015-09-20 18:03:46 +02:00
2017-03-05 16:44:50 +01:00
debug_collision_contact_color = p_color ;
2015-09-20 18:03:46 +02:00
}
Color SceneTree : : get_debug_collision_contact_color ( ) const {
return debug_collision_contact_color ;
}
2017-03-05 16:44:50 +01:00
void SceneTree : : set_debug_navigation_color ( const Color & p_color ) {
2015-09-20 18:03:46 +02:00
2017-03-05 16:44:50 +01:00
debug_navigation_color = p_color ;
2015-09-20 18:03:46 +02:00
}
Color SceneTree : : get_debug_navigation_color ( ) const {
return debug_navigation_color ;
}
2017-03-05 16:44:50 +01:00
void SceneTree : : set_debug_navigation_disabled_color ( const Color & p_color ) {
2015-09-20 18:03:46 +02:00
2017-03-05 16:44:50 +01:00
debug_navigation_disabled_color = p_color ;
2015-09-20 18:03:46 +02:00
}
Color SceneTree : : get_debug_navigation_disabled_color ( ) const {
return debug_navigation_disabled_color ;
}
Ref < Material > SceneTree : : get_debug_navigation_material ( ) {
if ( navigation_material . is_valid ( ) )
return navigation_material ;
2019-09-15 06:01:52 +02:00
Ref < StandardMaterial3D > line_material = Ref < StandardMaterial3D > ( memnew ( StandardMaterial3D ) ) ;
line_material - > set_shading_mode ( StandardMaterial3D : : SHADING_MODE_UNSHADED ) ;
line_material - > set_transparency ( StandardMaterial3D : : TRANSPARENCY_ALPHA ) ;
line_material - > set_flag ( StandardMaterial3D : : FLAG_SRGB_VERTEX_COLOR , true ) ;
line_material - > set_flag ( StandardMaterial3D : : FLAG_ALBEDO_FROM_VERTEX_COLOR , true ) ;
2017-08-15 22:21:05 +02:00
line_material - > set_albedo ( get_debug_navigation_color ( ) ) ;
2015-09-20 18:03:46 +02:00
2017-03-05 16:44:50 +01:00
navigation_material = line_material ;
2015-09-20 18:03:46 +02:00
return navigation_material ;
}
2017-03-05 16:44:50 +01:00
Ref < Material > SceneTree : : get_debug_navigation_disabled_material ( ) {
2015-09-20 18:03:46 +02:00
if ( navigation_disabled_material . is_valid ( ) )
return navigation_disabled_material ;
2019-09-15 06:01:52 +02:00
Ref < StandardMaterial3D > line_material = Ref < StandardMaterial3D > ( memnew ( StandardMaterial3D ) ) ;
line_material - > set_shading_mode ( StandardMaterial3D : : SHADING_MODE_UNSHADED ) ;
line_material - > set_transparency ( StandardMaterial3D : : TRANSPARENCY_ALPHA ) ;
line_material - > set_flag ( StandardMaterial3D : : FLAG_SRGB_VERTEX_COLOR , true ) ;
line_material - > set_flag ( StandardMaterial3D : : FLAG_ALBEDO_FROM_VERTEX_COLOR , true ) ;
2017-08-15 22:21:05 +02:00
line_material - > set_albedo ( get_debug_navigation_disabled_color ( ) ) ;
2015-09-20 18:03:46 +02:00
2017-03-05 16:44:50 +01:00
navigation_disabled_material = line_material ;
2015-09-20 18:03:46 +02:00
return navigation_disabled_material ;
}
Ref < Material > SceneTree : : get_debug_collision_material ( ) {
if ( collision_material . is_valid ( ) )
return collision_material ;
2019-09-15 06:01:52 +02:00
Ref < StandardMaterial3D > line_material = Ref < StandardMaterial3D > ( memnew ( StandardMaterial3D ) ) ;
line_material - > set_shading_mode ( StandardMaterial3D : : SHADING_MODE_UNSHADED ) ;
line_material - > set_transparency ( StandardMaterial3D : : TRANSPARENCY_ALPHA ) ;
line_material - > set_flag ( StandardMaterial3D : : FLAG_SRGB_VERTEX_COLOR , true ) ;
line_material - > set_flag ( StandardMaterial3D : : FLAG_ALBEDO_FROM_VERTEX_COLOR , true ) ;
2017-08-15 22:21:05 +02:00
line_material - > set_albedo ( get_debug_collisions_color ( ) ) ;
2015-09-20 18:03:46 +02:00
2017-03-05 16:44:50 +01:00
collision_material = line_material ;
2015-09-20 18:03:46 +02:00
return collision_material ;
}
2017-06-07 23:18:55 +02:00
Ref < ArrayMesh > SceneTree : : get_debug_contact_mesh ( ) {
2015-09-20 18:03:46 +02:00
if ( debug_contact_mesh . is_valid ( ) )
return debug_contact_mesh ;
2017-06-07 23:18:55 +02:00
debug_contact_mesh = Ref < ArrayMesh > ( memnew ( ArrayMesh ) ) ;
2015-09-20 18:03:46 +02:00
2019-09-15 06:01:52 +02:00
Ref < StandardMaterial3D > mat = Ref < StandardMaterial3D > ( memnew ( StandardMaterial3D ) ) ;
mat - > set_shading_mode ( StandardMaterial3D : : SHADING_MODE_UNSHADED ) ;
mat - > set_transparency ( StandardMaterial3D : : TRANSPARENCY_ALPHA ) ;
mat - > set_flag ( StandardMaterial3D : : FLAG_SRGB_VERTEX_COLOR , true ) ;
mat - > set_flag ( StandardMaterial3D : : FLAG_ALBEDO_FROM_VERTEX_COLOR , true ) ;
2017-08-15 22:21:05 +02:00
mat - > set_albedo ( get_debug_collision_contact_color ( ) ) ;
2015-09-20 18:03:46 +02:00
2017-03-05 16:44:50 +01:00
Vector3 diamond [ 6 ] = {
2015-09-20 18:03:46 +02:00
Vector3 ( - 1 , 0 , 0 ) ,
2017-03-05 16:44:50 +01:00
Vector3 ( 1 , 0 , 0 ) ,
Vector3 ( 0 , - 1 , 0 ) ,
Vector3 ( 0 , 1 , 0 ) ,
Vector3 ( 0 , 0 , - 1 ) ,
Vector3 ( 0 , 0 , 1 )
2015-09-20 18:03:46 +02:00
} ;
2017-12-06 21:36:34 +01:00
/* clang-format off */
2017-03-05 16:44:50 +01:00
int diamond_faces [ 8 * 3 ] = {
0 , 2 , 4 ,
0 , 3 , 4 ,
1 , 2 , 4 ,
1 , 3 , 4 ,
0 , 2 , 5 ,
0 , 3 , 5 ,
1 , 2 , 5 ,
1 , 3 , 5 ,
2015-09-20 18:03:46 +02:00
} ;
2017-12-06 21:36:34 +01:00
/* clang-format on */
2015-09-20 18:03:46 +02:00
2020-02-17 22:06:54 +01:00
Vector < int > indices ;
2017-03-05 16:44:50 +01:00
for ( int i = 0 ; i < 8 * 3 ; i + + )
2015-09-20 18:03:46 +02:00
indices . push_back ( diamond_faces [ i ] ) ;
2020-02-17 22:06:54 +01:00
Vector < Vector3 > vertices ;
2017-03-05 16:44:50 +01:00
for ( int i = 0 ; i < 6 ; i + + )
vertices . push_back ( diamond [ i ] * 0.1 ) ;
2015-09-20 18:03:46 +02:00
Array arr ;
arr . resize ( Mesh : : ARRAY_MAX ) ;
2017-03-05 16:44:50 +01:00
arr [ Mesh : : ARRAY_VERTEX ] = vertices ;
arr [ Mesh : : ARRAY_INDEX ] = indices ;
2015-09-20 18:03:46 +02:00
2017-03-05 16:44:50 +01:00
debug_contact_mesh - > add_surface_from_arrays ( Mesh : : PRIMITIVE_TRIANGLES , arr ) ;
debug_contact_mesh - > surface_set_material ( 0 , mat ) ;
2015-09-20 18:03:46 +02:00
return debug_contact_mesh ;
}
2014-11-06 01:20:42 +01:00
void SceneTree : : set_pause ( bool p_enabled ) {
2014-02-10 02:10:30 +01:00
2017-03-05 16:44:50 +01:00
if ( p_enabled = = pause )
2014-02-10 02:10:30 +01:00
return ;
2017-03-05 16:44:50 +01:00
pause = p_enabled ;
2020-03-27 19:21:27 +01:00
NavigationServer3D : : get_singleton ( ) - > set_active ( ! p_enabled ) ;
PhysicsServer3D : : get_singleton ( ) - > set_active ( ! p_enabled ) ;
PhysicsServer2D : : get_singleton ( ) - > set_active ( ! p_enabled ) ;
2014-02-10 02:10:30 +01:00
if ( get_root ( ) )
get_root ( ) - > propagate_notification ( p_enabled ? Node : : NOTIFICATION_PAUSED : Node : : NOTIFICATION_UNPAUSED ) ;
}
2014-11-06 01:20:42 +01:00
bool SceneTree : : is_paused ( ) const {
2014-02-10 02:10:30 +01:00
return pause ;
}
2020-03-04 17:36:09 +01:00
void SceneTree : : _notify_group_pause ( const StringName & p_group , int p_notification ) {
2014-02-10 02:10:30 +01:00
2017-03-05 16:44:50 +01:00
Map < StringName , Group > : : Element * E = group_map . find ( p_group ) ;
2014-02-10 02:10:30 +01:00
if ( ! E )
return ;
2017-03-05 16:44:50 +01:00
Group & g = E - > get ( ) ;
2014-02-10 02:10:30 +01:00
if ( g . nodes . empty ( ) )
return ;
2020-03-04 17:36:09 +01:00
_update_group_order ( g , p_notification = = Node : : NOTIFICATION_PROCESS | | p_notification = = Node : : NOTIFICATION_INTERNAL_PROCESS | | p_notification = = Node : : NOTIFICATION_PHYSICS_PROCESS | | p_notification = = Node : : NOTIFICATION_INTERNAL_PHYSICS_PROCESS ) ;
2014-02-10 02:10:30 +01:00
//copy, so copy on write happens in case something is removed from process while being called
//performance is not lost because only if something is added/removed the vector is copied.
2017-03-05 16:44:50 +01:00
Vector < Node * > nodes_copy = g . nodes ;
2014-02-10 02:10:30 +01:00
2017-03-05 16:44:50 +01:00
int node_count = nodes_copy . size ( ) ;
2018-07-25 03:11:03 +02:00
Node * * nodes = nodes_copy . ptrw ( ) ;
2014-02-10 02:10:30 +01:00
call_lock + + ;
2020-03-04 17:36:09 +01:00
for ( int i = 0 ; i < node_count ; i + + ) {
2014-02-10 02:10:30 +01:00
Node * n = nodes [ i ] ;
if ( call_lock & & call_skip . has ( n ) )
continue ;
if ( ! n - > can_process ( ) )
continue ;
2020-03-04 17:36:09 +01:00
if ( ! n - > can_process_notification ( p_notification ) )
continue ;
2014-02-10 02:10:30 +01:00
2020-03-04 17:36:09 +01:00
n - > notification ( p_notification ) ;
2014-02-10 02:10:30 +01:00
//ERR_FAIL_COND(node_count != g.nodes.size());
}
call_lock - - ;
2017-03-05 16:44:50 +01:00
if ( call_lock = = 0 )
2014-02-10 02:10:30 +01:00
call_skip . clear ( ) ;
}
2020-03-04 17:36:09 +01:00
/*
void SceneMainLoop : : _update_listener_2d ( ) {
if ( listener_2d . is_valid ( ) ) {
SpatialSound2DServer : : get_singleton ( ) - > listener_set_space ( listener_2d , world_2d - > get_sound_space ( ) ) ;
}
}
*/
void SceneTree : : _call_input_pause ( const StringName & p_group , const StringName & p_method , const Ref < InputEvent > & p_input , Viewport * p_viewport ) {
2014-02-10 02:10:30 +01:00
2017-03-05 16:44:50 +01:00
Map < StringName , Group > : : Element * E = group_map . find ( p_group ) ;
2014-02-10 02:10:30 +01:00
if ( ! E )
return ;
2017-03-05 16:44:50 +01:00
Group & g = E - > get ( ) ;
2014-02-10 02:10:30 +01:00
if ( g . nodes . empty ( ) )
return ;
2020-03-04 17:36:09 +01:00
_update_group_order ( g ) ;
2014-02-10 02:10:30 +01:00
//copy, so copy on write happens in case something is removed from process while being called
//performance is not lost because only if something is added/removed the vector is copied.
2017-03-05 16:44:50 +01:00
Vector < Node * > nodes_copy = g . nodes ;
2014-02-10 02:10:30 +01:00
2017-03-05 16:44:50 +01:00
int node_count = nodes_copy . size ( ) ;
2018-07-25 03:11:03 +02:00
Node * * nodes = nodes_copy . ptrw ( ) ;
2014-02-10 02:10:30 +01:00
2020-03-04 17:36:09 +01:00
Variant arg = p_input ;
const Variant * v [ 1 ] = { & arg } ;
2014-02-10 02:10:30 +01:00
call_lock + + ;
2020-03-04 17:36:09 +01:00
for ( int i = node_count - 1 ; i > = 0 ; i - - ) {
if ( p_viewport - > is_input_handled ( ) )
break ;
2014-02-10 02:10:30 +01:00
Node * n = nodes [ i ] ;
if ( call_lock & & call_skip . has ( n ) )
continue ;
if ( ! n - > can_process ( ) )
continue ;
2020-03-04 17:36:09 +01:00
n - > call_multilevel ( p_method , ( const Variant * * ) v , 1 ) ;
2014-02-10 02:10:30 +01:00
//ERR_FAIL_COND(node_count != g.nodes.size());
}
call_lock - - ;
2017-03-05 16:44:50 +01:00
if ( call_lock = = 0 )
2014-02-10 02:10:30 +01:00
call_skip . clear ( ) ;
}
2020-02-19 20:27:19 +01:00
Variant SceneTree : : _call_group_flags ( const Variant * * p_args , int p_argcount , Callable : : CallError & r_error ) {
2014-02-10 02:10:30 +01:00
2020-02-19 20:27:19 +01:00
r_error . error = Callable : : CallError : : CALL_OK ;
2014-02-10 02:10:30 +01:00
2017-03-05 16:44:50 +01:00
ERR_FAIL_COND_V ( p_argcount < 3 , Variant ( ) ) ;
ERR_FAIL_COND_V ( ! p_args [ 0 ] - > is_num ( ) , Variant ( ) ) ;
2020-02-20 22:58:05 +01:00
ERR_FAIL_COND_V ( p_args [ 1 ] - > get_type ( ) ! = Variant : : STRING_NAME & & p_args [ 1 ] - > get_type ( ) ! = Variant : : STRING , Variant ( ) ) ;
ERR_FAIL_COND_V ( p_args [ 2 ] - > get_type ( ) ! = Variant : : STRING_NAME & & p_args [ 2 ] - > get_type ( ) ! = Variant : : STRING , Variant ( ) ) ;
2014-02-10 02:10:30 +01:00
int flags = * p_args [ 0 ] ;
StringName group = * p_args [ 1 ] ;
StringName method = * p_args [ 2 ] ;
Variant v [ VARIANT_ARG_MAX ] ;
2017-03-05 16:44:50 +01:00
for ( int i = 0 ; i < MIN ( p_argcount - 3 , 5 ) ; i + + ) {
2014-02-10 02:10:30 +01:00
2017-03-05 16:44:50 +01:00
v [ i ] = * p_args [ i + 3 ] ;
2014-02-10 02:10:30 +01:00
}
2017-03-05 16:44:50 +01:00
call_group_flags ( flags , group , method , v [ 0 ] , v [ 1 ] , v [ 2 ] , v [ 3 ] , v [ 4 ] ) ;
2014-02-10 02:10:30 +01:00
return Variant ( ) ;
}
2020-02-19 20:27:19 +01:00
Variant SceneTree : : _call_group ( const Variant * * p_args , int p_argcount , Callable : : CallError & r_error ) {
2014-02-10 02:10:30 +01:00
2020-02-19 20:27:19 +01:00
r_error . error = Callable : : CallError : : CALL_OK ;
2017-01-14 14:03:53 +01:00
2017-03-05 16:44:50 +01:00
ERR_FAIL_COND_V ( p_argcount < 2 , Variant ( ) ) ;
2020-02-20 22:58:05 +01:00
ERR_FAIL_COND_V ( p_args [ 0 ] - > get_type ( ) ! = Variant : : STRING_NAME & & p_args [ 0 ] - > get_type ( ) ! = Variant : : STRING , Variant ( ) ) ;
ERR_FAIL_COND_V ( p_args [ 1 ] - > get_type ( ) ! = Variant : : STRING_NAME & & p_args [ 1 ] - > get_type ( ) ! = Variant : : STRING , Variant ( ) ) ;
2017-01-14 14:03:53 +01:00
StringName group = * p_args [ 0 ] ;
StringName method = * p_args [ 1 ] ;
Variant v [ VARIANT_ARG_MAX ] ;
2017-03-05 16:44:50 +01:00
for ( int i = 0 ; i < MIN ( p_argcount - 2 , 5 ) ; i + + ) {
2017-01-14 14:03:53 +01:00
2017-03-05 16:44:50 +01:00
v [ i ] = * p_args [ i + 2 ] ;
2017-01-14 14:03:53 +01:00
}
2017-03-05 16:44:50 +01:00
call_group_flags ( 0 , group , method , v [ 0 ] , v [ 1 ] , v [ 2 ] , v [ 3 ] , v [ 4 ] ) ;
2017-01-14 14:03:53 +01:00
return Variant ( ) ;
}
2014-11-06 01:20:42 +01:00
int64_t SceneTree : : get_frame ( ) const {
2014-02-10 02:10:30 +01:00
return current_frame ;
}
2017-12-26 13:48:50 +01:00
int64_t SceneTree : : get_event_count ( ) const {
return current_event ;
}
2014-02-10 02:10:30 +01:00
2017-03-05 16:44:50 +01:00
Array SceneTree : : _get_nodes_in_group ( const StringName & p_group ) {
2014-02-10 02:10:30 +01:00
Array ret ;
2017-03-05 16:44:50 +01:00
Map < StringName , Group > : : Element * E = group_map . find ( p_group ) ;
2014-02-10 02:10:30 +01:00
if ( ! E )
return ret ;
_update_group_order ( E - > get ( ) ) ; //update order just in case
int nc = E - > get ( ) . nodes . size ( ) ;
2017-03-05 16:44:50 +01:00
if ( nc = = 0 )
2014-02-10 02:10:30 +01:00
return ret ;
ret . resize ( nc ) ;
2017-11-25 04:07:54 +01:00
Node * * ptr = E - > get ( ) . nodes . ptrw ( ) ;
2017-03-05 16:44:50 +01:00
for ( int i = 0 ; i < nc ; i + + ) {
2014-02-10 02:10:30 +01:00
2017-03-05 16:44:50 +01:00
ret [ i ] = ptr [ i ] ;
2014-02-10 02:10:30 +01:00
}
return ret ;
}
2017-03-05 16:44:50 +01:00
bool SceneTree : : has_group ( const StringName & p_identifier ) const {
2016-01-02 21:18:45 +01:00
return group_map . has ( p_identifier ) ;
}
2017-03-05 16:44:50 +01:00
void SceneTree : : get_nodes_in_group ( const StringName & p_group , List < Node * > * p_list ) {
2014-02-10 02:10:30 +01:00
2017-03-05 16:44:50 +01:00
Map < StringName , Group > : : Element * E = group_map . find ( p_group ) ;
2014-02-10 02:10:30 +01:00
if ( ! E )
return ;
_update_group_order ( E - > get ( ) ) ; //update order just in case
int nc = E - > get ( ) . nodes . size ( ) ;
2017-03-05 16:44:50 +01:00
if ( nc = = 0 )
2014-02-10 02:10:30 +01:00
return ;
2017-11-25 04:07:54 +01:00
Node * * ptr = E - > get ( ) . nodes . ptrw ( ) ;
2017-03-05 16:44:50 +01:00
for ( int i = 0 ; i < nc ; i + + ) {
2014-02-10 02:10:30 +01:00
p_list - > push_back ( ptr [ i ] ) ;
}
}
2014-11-06 01:20:42 +01:00
void SceneTree : : _flush_delete_queue ( ) {
2014-02-10 02:10:30 +01:00
_THREAD_SAFE_METHOD_
2017-03-05 16:44:50 +01:00
while ( delete_queue . size ( ) ) {
2014-02-10 02:10:30 +01:00
2017-03-05 16:44:50 +01:00
Object * obj = ObjectDB : : get_instance ( delete_queue . front ( ) - > get ( ) ) ;
2014-02-10 02:10:30 +01:00
if ( obj ) {
2017-03-05 16:44:50 +01:00
memdelete ( obj ) ;
2014-02-10 02:10:30 +01:00
}
delete_queue . pop_front ( ) ;
}
}
2014-11-06 01:20:42 +01:00
void SceneTree : : queue_delete ( Object * p_object ) {
2014-02-10 02:10:30 +01:00
_THREAD_SAFE_METHOD_
ERR_FAIL_NULL ( p_object ) ;
2015-03-28 18:34:28 +01:00
p_object - > _is_queued_for_deletion = true ;
2017-08-07 12:17:31 +02:00
delete_queue . push_back ( p_object - > get_instance_id ( ) ) ;
2014-02-10 02:10:30 +01:00
}
2014-11-06 01:20:42 +01:00
int SceneTree : : get_node_count ( ) const {
2014-02-10 02:10:30 +01:00
return node_count ;
}
2014-11-06 01:20:42 +01:00
void SceneTree : : set_edited_scene_root ( Node * p_node ) {
2018-04-29 19:49:26 +02:00
# ifdef TOOLS_ENABLED
2017-03-05 16:44:50 +01:00
edited_scene_root = p_node ;
2018-04-29 19:49:26 +02:00
# endif
2014-10-12 07:13:22 +02:00
}
2014-11-06 01:20:42 +01:00
Node * SceneTree : : get_edited_scene_root ( ) const {
2014-10-12 07:13:22 +02:00
2018-04-29 19:49:26 +02:00
# ifdef TOOLS_ENABLED
2014-10-12 07:13:22 +02:00
return edited_scene_root ;
2018-04-29 19:49:26 +02:00
# else
2020-04-02 01:20:12 +02:00
return nullptr ;
2014-10-12 07:13:22 +02:00
# endif
2018-04-29 19:49:26 +02:00
}
2014-10-12 07:13:22 +02:00
2017-03-05 16:44:50 +01:00
void SceneTree : : set_current_scene ( Node * p_scene ) {
2015-05-17 21:33:35 +02:00
2017-03-05 16:44:50 +01:00
ERR_FAIL_COND ( p_scene & & p_scene - > get_parent ( ) ! = root ) ;
current_scene = p_scene ;
2015-05-17 21:33:35 +02:00
}
2017-03-05 16:44:50 +01:00
Node * SceneTree : : get_current_scene ( ) const {
2015-05-17 21:33:35 +02:00
return current_scene ;
}
2017-03-05 16:44:50 +01:00
void SceneTree : : _change_scene ( Node * p_to ) {
2015-05-17 21:33:35 +02:00
if ( current_scene ) {
2017-03-05 16:44:50 +01:00
memdelete ( current_scene ) ;
2020-04-02 01:20:12 +02:00
current_scene = nullptr ;
2015-05-17 21:33:35 +02:00
}
2020-01-19 22:06:26 +01:00
// If we're quitting, abort.
if ( unlikely ( _quit ) ) {
if ( p_to ) { // Prevent memory leak.
memdelete ( p_to ) ;
}
return ;
}
2015-05-17 21:33:35 +02:00
if ( p_to ) {
2017-03-05 16:44:50 +01:00
current_scene = p_to ;
2015-05-17 21:33:35 +02:00
root - > add_child ( p_to ) ;
}
}
2017-03-05 16:44:50 +01:00
Error SceneTree : : change_scene ( const String & p_path ) {
2015-05-17 21:33:35 +02:00
Ref < PackedScene > new_scene = ResourceLoader : : load ( p_path ) ;
if ( new_scene . is_null ( ) )
return ERR_CANT_OPEN ;
return change_scene_to ( new_scene ) ;
}
2020-01-19 22:06:26 +01:00
Error SceneTree : : change_scene_to ( const Ref < PackedScene > & p_scene ) {
2020-04-02 01:20:12 +02:00
Node * new_scene = nullptr ;
2015-05-17 21:33:35 +02:00
if ( p_scene . is_valid ( ) ) {
new_scene = p_scene - > instance ( ) ;
2017-03-05 16:44:50 +01:00
ERR_FAIL_COND_V ( ! new_scene , ERR_CANT_CREATE ) ;
2015-05-17 21:33:35 +02:00
}
2017-03-05 16:44:50 +01:00
call_deferred ( " _change_scene " , new_scene ) ;
2015-05-17 21:33:35 +02:00
return OK ;
}
2020-01-19 22:06:26 +01:00
Error SceneTree : : reload_current_scene ( ) {
2017-03-05 16:44:50 +01:00
ERR_FAIL_COND_V ( ! current_scene , ERR_UNCONFIGURED ) ;
2015-05-17 21:33:35 +02:00
String fname = current_scene - > get_filename ( ) ;
return change_scene ( fname ) ;
}
2017-03-05 16:44:50 +01:00
void SceneTree : : add_current_scene ( Node * p_current ) {
2015-05-17 21:33:35 +02:00
2017-03-05 16:44:50 +01:00
current_scene = p_current ;
2015-05-17 21:33:35 +02:00
root - > add_child ( p_current ) ;
}
2020-01-19 22:06:26 +01:00
2017-02-14 00:34:33 +01:00
Ref < SceneTreeTimer > SceneTree : : create_timer ( float p_delay_sec , bool p_process_pause ) {
2016-08-07 02:39:50 +02:00
Ref < SceneTreeTimer > stt ;
stt . instance ( ) ;
2017-02-14 00:34:33 +01:00
stt - > set_pause_mode_process ( p_process_pause ) ;
2016-08-07 02:39:50 +02:00
stt - > set_time_left ( p_delay_sec ) ;
timers . push_back ( stt ) ;
return stt ;
}
2016-08-19 21:48:08 +02:00
void SceneTree : : _network_peer_connected ( int p_id ) {
2016-08-14 23:49:50 +02:00
2017-03-05 16:44:50 +01:00
emit_signal ( " network_peer_connected " , p_id ) ;
2016-08-14 23:49:50 +02:00
}
2016-08-19 21:48:08 +02:00
void SceneTree : : _network_peer_disconnected ( int p_id ) {
2016-08-14 23:49:50 +02:00
2017-03-05 16:44:50 +01:00
emit_signal ( " network_peer_disconnected " , p_id ) ;
2016-08-14 23:49:50 +02:00
}
2016-08-19 21:48:08 +02:00
void SceneTree : : _connected_to_server ( ) {
emit_signal ( " connected_to_server " ) ;
}
void SceneTree : : _connection_failed ( ) {
emit_signal ( " connection_failed " ) ;
}
void SceneTree : : _server_disconnected ( ) {
emit_signal ( " server_disconnected " ) ;
}
2018-05-08 10:51:04 +02:00
Ref < MultiplayerAPI > SceneTree : : get_multiplayer ( ) const {
return multiplayer ;
2018-03-03 18:30:11 +01:00
}
2018-06-02 14:32:30 +02:00
void SceneTree : : set_multiplayer_poll_enabled ( bool p_enabled ) {
multiplayer_poll = p_enabled ;
}
bool SceneTree : : is_multiplayer_poll_enabled ( ) const {
return multiplayer_poll ;
}
2018-05-08 10:51:04 +02:00
void SceneTree : : set_multiplayer ( Ref < MultiplayerAPI > p_multiplayer ) {
ERR_FAIL_COND ( ! p_multiplayer . is_valid ( ) ) ;
2018-03-03 18:30:11 +01:00
2018-05-08 10:51:04 +02:00
if ( multiplayer . is_valid ( ) ) {
2020-02-21 18:28:45 +01:00
multiplayer - > disconnect ( " network_peer_connected " , callable_mp ( this , & SceneTree : : _network_peer_connected ) ) ;
multiplayer - > disconnect ( " network_peer_disconnected " , callable_mp ( this , & SceneTree : : _network_peer_disconnected ) ) ;
multiplayer - > disconnect ( " connected_to_server " , callable_mp ( this , & SceneTree : : _connected_to_server ) ) ;
multiplayer - > disconnect ( " connection_failed " , callable_mp ( this , & SceneTree : : _connection_failed ) ) ;
multiplayer - > disconnect ( " server_disconnected " , callable_mp ( this , & SceneTree : : _server_disconnected ) ) ;
2016-08-14 23:49:50 +02:00
}
2018-05-08 10:51:04 +02:00
multiplayer = p_multiplayer ;
multiplayer - > set_root_node ( root ) ;
2016-08-14 23:49:50 +02:00
2020-02-21 18:28:45 +01:00
multiplayer - > connect ( " network_peer_connected " , callable_mp ( this , & SceneTree : : _network_peer_connected ) ) ;
multiplayer - > connect ( " network_peer_disconnected " , callable_mp ( this , & SceneTree : : _network_peer_disconnected ) ) ;
multiplayer - > connect ( " connected_to_server " , callable_mp ( this , & SceneTree : : _connected_to_server ) ) ;
multiplayer - > connect ( " connection_failed " , callable_mp ( this , & SceneTree : : _connection_failed ) ) ;
multiplayer - > connect ( " server_disconnected " , callable_mp ( this , & SceneTree : : _server_disconnected ) ) ;
2018-03-03 18:30:11 +01:00
}
2016-08-14 23:49:50 +02:00
2018-03-03 18:30:11 +01:00
void SceneTree : : set_network_peer ( const Ref < NetworkedMultiplayerPeer > & p_network_peer ) {
2018-05-08 10:51:04 +02:00
multiplayer - > set_network_peer ( p_network_peer ) ;
2016-08-14 23:49:50 +02:00
}
2018-01-11 23:35:12 +01:00
Ref < NetworkedMultiplayerPeer > SceneTree : : get_network_peer ( ) const {
2018-05-08 10:51:04 +02:00
return multiplayer - > get_network_peer ( ) ;
2018-01-11 23:35:12 +01:00
}
2016-08-14 23:49:50 +02:00
bool SceneTree : : is_network_server ( ) const {
2018-05-08 10:51:04 +02:00
return multiplayer - > is_network_server ( ) ;
2016-08-14 23:49:50 +02:00
}
2017-03-04 11:35:44 +01:00
bool SceneTree : : has_network_peer ( ) const {
2018-05-08 10:51:04 +02:00
return multiplayer - > has_network_peer ( ) ;
2017-03-04 11:35:44 +01:00
}
2016-08-19 21:48:08 +02:00
int SceneTree : : get_network_unique_id ( ) const {
2018-05-08 10:51:04 +02:00
return multiplayer - > get_network_unique_id ( ) ;
2016-08-19 21:48:08 +02:00
}
2017-07-03 15:44:45 +02:00
Vector < int > SceneTree : : get_network_connected_peers ( ) const {
2018-05-08 10:51:04 +02:00
return multiplayer - > get_network_connected_peers ( ) ;
2017-07-03 15:44:45 +02:00
}
2017-08-23 10:43:25 +02:00
int SceneTree : : get_rpc_sender_id ( ) const {
2018-05-08 10:51:04 +02:00
return multiplayer - > get_rpc_sender_id ( ) ;
2017-08-23 10:43:25 +02:00
}
2016-08-19 21:48:08 +02:00
void SceneTree : : set_refuse_new_network_connections ( bool p_refuse ) {
2018-05-08 10:51:04 +02:00
multiplayer - > set_refuse_new_network_connections ( p_refuse ) ;
2016-08-19 21:48:08 +02:00
}
bool SceneTree : : is_refusing_new_network_connections ( ) const {
2018-05-08 10:51:04 +02:00
return multiplayer - > is_refusing_new_network_connections ( ) ;
2016-08-14 23:49:50 +02:00
}
2014-11-06 01:20:42 +01:00
void SceneTree : : _bind_methods ( ) {
2014-02-10 02:10:30 +01:00
2017-08-09 13:19:41 +02:00
ClassDB : : bind_method ( D_METHOD ( " get_root " ) , & SceneTree : : get_root ) ;
2017-03-05 16:44:50 +01:00
ClassDB : : bind_method ( D_METHOD ( " has_group " , " name " ) , & SceneTree : : has_group ) ;
2014-02-10 02:10:30 +01:00
2017-03-05 16:44:50 +01:00
ClassDB : : bind_method ( D_METHOD ( " set_auto_accept_quit " , " enabled " ) , & SceneTree : : set_auto_accept_quit ) ;
2017-12-30 13:15:17 +01:00
ClassDB : : bind_method ( D_METHOD ( " set_quit_on_go_back " , " enabled " ) , & SceneTree : : set_quit_on_go_back ) ;
2014-02-10 02:10:30 +01:00
2017-03-05 16:44:50 +01:00
ClassDB : : bind_method ( D_METHOD ( " set_debug_collisions_hint " , " enable " ) , & SceneTree : : set_debug_collisions_hint ) ;
ClassDB : : bind_method ( D_METHOD ( " is_debugging_collisions_hint " ) , & SceneTree : : is_debugging_collisions_hint ) ;
ClassDB : : bind_method ( D_METHOD ( " set_debug_navigation_hint " , " enable " ) , & SceneTree : : set_debug_navigation_hint ) ;
ClassDB : : bind_method ( D_METHOD ( " is_debugging_navigation_hint " ) , & SceneTree : : is_debugging_navigation_hint ) ;
2015-09-20 18:03:46 +02:00
2017-08-09 13:19:41 +02:00
ClassDB : : bind_method ( D_METHOD ( " set_edited_scene_root " , " scene " ) , & SceneTree : : set_edited_scene_root ) ;
ClassDB : : bind_method ( D_METHOD ( " get_edited_scene_root " ) , & SceneTree : : get_edited_scene_root ) ;
2014-02-10 02:10:30 +01:00
2017-03-05 16:44:50 +01:00
ClassDB : : bind_method ( D_METHOD ( " set_pause " , " enable " ) , & SceneTree : : set_pause ) ;
ClassDB : : bind_method ( D_METHOD ( " is_paused " ) , & SceneTree : : is_paused ) ;
2014-02-10 02:10:30 +01:00
2017-08-09 13:19:41 +02:00
ClassDB : : bind_method ( D_METHOD ( " create_timer " , " time_sec " , " pause_mode_process " ) , & SceneTree : : create_timer , DEFVAL ( true ) ) ;
2014-02-10 02:10:30 +01:00
2017-03-05 16:44:50 +01:00
ClassDB : : bind_method ( D_METHOD ( " get_node_count " ) , & SceneTree : : get_node_count ) ;
ClassDB : : bind_method ( D_METHOD ( " get_frame " ) , & SceneTree : : get_frame ) ;
2019-12-29 16:39:24 +01:00
ClassDB : : bind_method ( D_METHOD ( " quit " , " exit_code " ) , & SceneTree : : quit , DEFVAL ( - 1 ) ) ;
2014-02-10 02:10:30 +01:00
2017-03-05 16:44:50 +01:00
ClassDB : : bind_method ( D_METHOD ( " queue_delete " , " obj " ) , & SceneTree : : queue_delete ) ;
2015-05-17 21:33:35 +02:00
2014-02-10 02:10:30 +01:00
MethodInfo mi ;
2017-03-05 16:44:50 +01:00
mi . name = " call_group_flags " ;
mi . arguments . push_back ( PropertyInfo ( Variant : : INT , " flags " ) ) ;
2020-02-20 22:58:05 +01:00
mi . arguments . push_back ( PropertyInfo ( Variant : : STRING_NAME , " group " ) ) ;
mi . arguments . push_back ( PropertyInfo ( Variant : : STRING_NAME , " method " ) ) ;
2016-09-08 00:39:02 +02:00
2017-03-05 16:44:50 +01:00
ClassDB : : bind_vararg_method ( METHOD_FLAGS_DEFAULT , " call_group_flags " , & SceneTree : : _call_group_flags , mi ) ;
2017-01-14 14:03:53 +01:00
2017-03-05 16:44:50 +01:00
ClassDB : : bind_method ( D_METHOD ( " notify_group_flags " , " call_flags " , " group " , " notification " ) , & SceneTree : : notify_group_flags ) ;
ClassDB : : bind_method ( D_METHOD ( " set_group_flags " , " call_flags " , " group " , " property " , " value " ) , & SceneTree : : set_group_flags ) ;
2017-01-14 14:03:53 +01:00
MethodInfo mi2 ;
2017-03-05 16:44:50 +01:00
mi2 . name = " call_group " ;
2020-02-20 22:58:05 +01:00
mi2 . arguments . push_back ( PropertyInfo ( Variant : : STRING_NAME , " group " ) ) ;
mi2 . arguments . push_back ( PropertyInfo ( Variant : : STRING_NAME , " method " ) ) ;
2017-01-14 14:03:53 +01:00
2017-03-05 16:44:50 +01:00
ClassDB : : bind_vararg_method ( METHOD_FLAGS_DEFAULT , " call_group " , & SceneTree : : _call_group , mi2 ) ;
2014-02-10 02:10:30 +01:00
2017-08-09 13:54:55 +02:00
ClassDB : : bind_method ( D_METHOD ( " notify_group " , " group " , " notification " ) , & SceneTree : : notify_group ) ;
ClassDB : : bind_method ( D_METHOD ( " set_group " , " group " , " property " , " value " ) , & SceneTree : : set_group ) ;
2015-05-17 21:33:35 +02:00
2017-03-05 16:44:50 +01:00
ClassDB : : bind_method ( D_METHOD ( " get_nodes_in_group " , " group " ) , & SceneTree : : _get_nodes_in_group ) ;
2015-05-17 21:33:35 +02:00
2017-08-09 13:19:41 +02:00
ClassDB : : bind_method ( D_METHOD ( " set_current_scene " , " child_node " ) , & SceneTree : : set_current_scene ) ;
ClassDB : : bind_method ( D_METHOD ( " get_current_scene " ) , & SceneTree : : get_current_scene ) ;
2015-05-17 21:33:35 +02:00
2017-03-05 16:44:50 +01:00
ClassDB : : bind_method ( D_METHOD ( " change_scene " , " path " ) , & SceneTree : : change_scene ) ;
2017-08-09 13:19:41 +02:00
ClassDB : : bind_method ( D_METHOD ( " change_scene_to " , " packed_scene " ) , & SceneTree : : change_scene_to ) ;
2015-05-17 21:33:35 +02:00
2017-03-05 16:44:50 +01:00
ClassDB : : bind_method ( D_METHOD ( " reload_current_scene " ) , & SceneTree : : reload_current_scene ) ;
2016-08-14 23:49:50 +02:00
2017-03-05 16:44:50 +01:00
ClassDB : : bind_method ( D_METHOD ( " _change_scene " ) , & SceneTree : : _change_scene ) ;
2016-08-14 23:49:50 +02:00
2018-05-08 10:51:04 +02:00
ClassDB : : bind_method ( D_METHOD ( " set_multiplayer " , " multiplayer " ) , & SceneTree : : set_multiplayer ) ;
ClassDB : : bind_method ( D_METHOD ( " get_multiplayer " ) , & SceneTree : : get_multiplayer ) ;
2018-06-02 14:32:30 +02:00
ClassDB : : bind_method ( D_METHOD ( " set_multiplayer_poll_enabled " , " enabled " ) , & SceneTree : : set_multiplayer_poll_enabled ) ;
ClassDB : : bind_method ( D_METHOD ( " is_multiplayer_poll_enabled " ) , & SceneTree : : is_multiplayer_poll_enabled ) ;
2017-08-09 13:19:41 +02:00
ClassDB : : bind_method ( D_METHOD ( " set_network_peer " , " peer " ) , & SceneTree : : set_network_peer ) ;
2018-01-11 23:35:12 +01:00
ClassDB : : bind_method ( D_METHOD ( " get_network_peer " ) , & SceneTree : : get_network_peer ) ;
2017-03-05 16:44:50 +01:00
ClassDB : : bind_method ( D_METHOD ( " is_network_server " ) , & SceneTree : : is_network_server ) ;
ClassDB : : bind_method ( D_METHOD ( " has_network_peer " ) , & SceneTree : : has_network_peer ) ;
2017-07-03 15:44:45 +02:00
ClassDB : : bind_method ( D_METHOD ( " get_network_connected_peers " ) , & SceneTree : : get_network_connected_peers ) ;
2017-03-05 16:44:50 +01:00
ClassDB : : bind_method ( D_METHOD ( " get_network_unique_id " ) , & SceneTree : : get_network_unique_id ) ;
2017-08-23 10:43:25 +02:00
ClassDB : : bind_method ( D_METHOD ( " get_rpc_sender_id " ) , & SceneTree : : get_rpc_sender_id ) ;
2017-03-05 16:44:50 +01:00
ClassDB : : bind_method ( D_METHOD ( " set_refuse_new_network_connections " , " refuse " ) , & SceneTree : : set_refuse_new_network_connections ) ;
ClassDB : : bind_method ( D_METHOD ( " is_refusing_new_network_connections " ) , & SceneTree : : is_refusing_new_network_connections ) ;
2014-02-10 02:10:30 +01:00
2018-01-11 23:35:12 +01:00
ADD_PROPERTY ( PropertyInfo ( Variant : : BOOL , " debug_collisions_hint " ) , " set_debug_collisions_hint " , " is_debugging_collisions_hint " ) ;
ADD_PROPERTY ( PropertyInfo ( Variant : : BOOL , " debug_navigation_hint " ) , " set_debug_navigation_hint " , " is_debugging_navigation_hint " ) ;
ADD_PROPERTY ( PropertyInfo ( Variant : : BOOL , " paused " ) , " set_pause " , " is_paused " ) ;
ADD_PROPERTY ( PropertyInfo ( Variant : : BOOL , " refuse_new_network_connections " ) , " set_refuse_new_network_connections " , " is_refusing_new_network_connections " ) ;
2019-06-01 15:42:22 +02:00
ADD_PROPERTY_DEFAULT ( " refuse_new_network_connections " , false ) ;
2018-01-11 23:35:12 +01:00
ADD_PROPERTY ( PropertyInfo ( Variant : : OBJECT , " edited_scene_root " , PROPERTY_HINT_RESOURCE_TYPE , " Node " , 0 ) , " set_edited_scene_root " , " get_edited_scene_root " ) ;
ADD_PROPERTY ( PropertyInfo ( Variant : : OBJECT , " current_scene " , PROPERTY_HINT_RESOURCE_TYPE , " Node " , 0 ) , " set_current_scene " , " get_current_scene " ) ;
ADD_PROPERTY ( PropertyInfo ( Variant : : OBJECT , " network_peer " , PROPERTY_HINT_RESOURCE_TYPE , " NetworkedMultiplayerPeer " , 0 ) , " set_network_peer " , " get_network_peer " ) ;
ADD_PROPERTY ( PropertyInfo ( Variant : : OBJECT , " root " , PROPERTY_HINT_RESOURCE_TYPE , " Node " , 0 ) , " " , " get_root " ) ;
2018-05-08 10:51:04 +02:00
ADD_PROPERTY ( PropertyInfo ( Variant : : OBJECT , " multiplayer " , PROPERTY_HINT_RESOURCE_TYPE , " MultiplayerAPI " , 0 ) , " set_multiplayer " , " get_multiplayer " ) ;
2018-06-02 14:32:30 +02:00
ADD_PROPERTY ( PropertyInfo ( Variant : : BOOL , " multiplayer_poll " ) , " set_multiplayer_poll_enabled " , " is_multiplayer_poll_enabled " ) ;
2018-01-11 23:35:12 +01:00
2017-03-05 16:44:50 +01:00
ADD_SIGNAL ( MethodInfo ( " tree_changed " ) ) ;
2018-09-01 12:05:51 +02:00
ADD_SIGNAL ( MethodInfo ( " node_added " , PropertyInfo ( Variant : : OBJECT , " node " , PROPERTY_HINT_RESOURCE_TYPE , " Node " ) ) ) ;
ADD_SIGNAL ( MethodInfo ( " node_removed " , PropertyInfo ( Variant : : OBJECT , " node " , PROPERTY_HINT_RESOURCE_TYPE , " Node " ) ) ) ;
2019-05-24 15:27:22 +02:00
ADD_SIGNAL ( MethodInfo ( " node_renamed " , PropertyInfo ( Variant : : OBJECT , " node " , PROPERTY_HINT_RESOURCE_TYPE , " Node " ) ) ) ;
2018-09-01 12:05:51 +02:00
ADD_SIGNAL ( MethodInfo ( " node_configuration_warning_changed " , PropertyInfo ( Variant : : OBJECT , " node " , PROPERTY_HINT_RESOURCE_TYPE , " Node " ) ) ) ;
2015-06-12 18:53:18 +02:00
2017-03-05 16:44:50 +01:00
ADD_SIGNAL ( MethodInfo ( " idle_frame " ) ) ;
2017-09-30 16:19:07 +02:00
ADD_SIGNAL ( MethodInfo ( " physics_frame " ) ) ;
2016-05-27 19:18:40 +02:00
2020-02-17 22:06:54 +01:00
ADD_SIGNAL ( MethodInfo ( " files_dropped " , PropertyInfo ( Variant : : PACKED_STRING_ARRAY , " files " ) , PropertyInfo ( Variant : : INT , " screen " ) ) ) ;
2017-03-05 16:44:50 +01:00
ADD_SIGNAL ( MethodInfo ( " network_peer_connected " , PropertyInfo ( Variant : : INT , " id " ) ) ) ;
ADD_SIGNAL ( MethodInfo ( " network_peer_disconnected " , PropertyInfo ( Variant : : INT , " id " ) ) ) ;
ADD_SIGNAL ( MethodInfo ( " connected_to_server " ) ) ;
ADD_SIGNAL ( MethodInfo ( " connection_failed " ) ) ;
ADD_SIGNAL ( MethodInfo ( " server_disconnected " ) ) ;
2014-02-10 02:10:30 +01:00
2017-08-20 17:45:01 +02:00
BIND_ENUM_CONSTANT ( GROUP_CALL_DEFAULT ) ;
BIND_ENUM_CONSTANT ( GROUP_CALL_REVERSE ) ;
BIND_ENUM_CONSTANT ( GROUP_CALL_REALTIME ) ;
BIND_ENUM_CONSTANT ( GROUP_CALL_UNIQUE ) ;
2014-02-10 02:10:30 +01:00
}
2020-04-02 01:20:12 +02:00
SceneTree * SceneTree : : singleton = nullptr ;
2016-10-27 16:50:26 +02:00
SceneTree : : IdleCallback SceneTree : : idle_callbacks [ SceneTree : : MAX_IDLE_CALLBACKS ] ;
2017-03-05 16:44:50 +01:00
int SceneTree : : idle_callback_count = 0 ;
2016-10-27 16:50:26 +02:00
void SceneTree : : _call_idle_callbacks ( ) {
2017-03-05 16:44:50 +01:00
for ( int i = 0 ; i < idle_callback_count ; i + + ) {
2016-10-27 16:50:26 +02:00
idle_callbacks [ i ] ( ) ;
}
}
void SceneTree : : add_idle_callback ( IdleCallback p_callback ) {
2017-03-05 16:44:50 +01:00
ERR_FAIL_COND ( idle_callback_count > = MAX_IDLE_CALLBACKS ) ;
idle_callbacks [ idle_callback_count + + ] = p_callback ;
2016-10-27 16:50:26 +02:00
}
2019-03-09 03:05:59 +01:00
void SceneTree : : get_argument_options ( const StringName & p_function , int p_idx , List < String > * r_options ) const {
if ( p_function = = " change_scene " ) {
DirAccessRef dir_access = DirAccess : : create ( DirAccess : : ACCESS_RESOURCES ) ;
List < String > directories ;
directories . push_back ( dir_access - > get_current_dir ( ) ) ;
while ( ! directories . empty ( ) ) {
dir_access - > change_dir ( directories . back ( ) - > get ( ) ) ;
directories . pop_back ( ) ;
dir_access - > list_dir_begin ( ) ;
String filename = dir_access - > get_next ( ) ;
while ( filename ! = " " ) {
if ( filename = = " . " | | filename = = " .. " ) {
filename = dir_access - > get_next ( ) ;
continue ;
}
if ( dir_access - > dir_exists ( filename ) ) {
directories . push_back ( dir_access - > get_current_dir ( ) . plus_file ( filename ) ) ;
} else if ( filename . ends_with ( " .tscn " ) | | filename . ends_with ( " .scn " ) ) {
r_options - > push_back ( " \" " + dir_access - > get_current_dir ( ) . plus_file ( filename ) + " \" " ) ;
}
filename = dir_access - > get_next ( ) ;
}
}
}
}
2014-11-06 01:20:42 +01:00
SceneTree : : SceneTree ( ) {
2014-02-10 02:10:30 +01:00
2020-04-02 01:20:12 +02:00
if ( singleton = = nullptr ) singleton = this ;
2017-03-05 16:44:50 +01:00
_quit = false ;
2017-04-25 13:05:22 +02:00
accept_quit = true ;
quit_on_go_back = true ;
2017-03-05 16:44:50 +01:00
initialized = false ;
2017-04-07 16:17:16 +02:00
# ifdef DEBUG_ENABLED
2017-03-05 16:44:50 +01:00
debug_collisions_hint = false ;
debug_navigation_hint = false ;
2017-04-07 16:17:16 +02:00
# endif
2017-07-18 02:05:38 +02:00
debug_collisions_color = GLOBAL_DEF ( " debug/shapes/collision/shape_color " , Color ( 0.0 , 0.6 , 0.7 , 0.5 ) ) ;
debug_collision_contact_color = GLOBAL_DEF ( " debug/shapes/collision/contact_color " , Color ( 1.0 , 0.2 , 0.1 , 0.8 ) ) ;
debug_navigation_color = GLOBAL_DEF ( " debug/shapes/navigation/geometry_color " , Color ( 0.1 , 1.0 , 0.7 , 0.4 ) ) ;
debug_navigation_disabled_color = GLOBAL_DEF ( " debug/shapes/navigation/disabled_geometry_color " , Color ( 1.0 , 0.7 , 0.1 , 0.4 ) ) ;
collision_debug_contacts = GLOBAL_DEF ( " debug/shapes/collision/max_contacts_displayed " , 10000 ) ;
2018-10-05 18:43:53 +02:00
ProjectSettings : : get_singleton ( ) - > set_custom_property_info ( " debug/shapes/collision/max_contacts_displayed " , PropertyInfo ( Variant : : INT , " debug/shapes/collision/max_contacts_displayed " , PROPERTY_HINT_RANGE , " 0,20000,1 " ) ) ; // No negative
2017-03-05 16:44:50 +01:00
tree_version = 1 ;
2017-09-30 16:19:07 +02:00
physics_process_time = 1 ;
2017-03-05 16:44:50 +01:00
idle_process_time = 1 ;
2017-12-26 13:48:50 +01:00
2020-04-02 01:20:12 +02:00
root = nullptr ;
2019-07-02 16:23:54 +02:00
pause = false ;
2017-03-05 16:44:50 +01:00
current_frame = 0 ;
2017-12-26 13:48:50 +01:00
current_event = 0 ;
2017-03-05 16:44:50 +01:00
tree_changed_name = " tree_changed " ;
2017-10-19 02:30:27 +02:00
node_added_name = " node_added " ;
2017-03-05 16:44:50 +01:00
node_removed_name = " node_removed " ;
2019-05-24 15:27:22 +02:00
node_renamed_name = " node_renamed " ;
2017-03-05 16:44:50 +01:00
ugc_locked = false ;
call_lock = 0 ;
root_lock = 0 ;
node_count = 0 ;
2014-02-10 02:10:30 +01:00
//create with mainloop
2020-03-04 02:51:12 +01:00
root = memnew ( Window ) ;
2014-02-10 02:10:30 +01:00
root - > set_name ( " root " ) ;
2017-05-29 02:46:48 +02:00
if ( ! root - > get_world ( ) . is_valid ( ) )
2020-03-27 08:44:44 +01:00
root - > set_world ( Ref < World3D > ( memnew ( World3D ) ) ) ;
2017-05-29 02:46:48 +02:00
2018-03-03 18:30:11 +01:00
// Initialize network state
2018-06-02 14:32:30 +02:00
multiplayer_poll = true ;
2018-05-08 10:51:04 +02:00
set_multiplayer ( Ref < MultiplayerAPI > ( memnew ( MultiplayerAPI ) ) ) ;
2018-03-03 18:30:11 +01:00
2014-02-10 02:10:30 +01:00
//root->set_world_2d( Ref<World2D>( memnew( World2D )));
root - > set_as_audio_listener ( true ) ;
root - > set_as_audio_listener_2d ( true ) ;
2020-04-02 01:20:12 +02:00
current_scene = nullptr ;
2014-02-10 02:10:30 +01:00
2020-04-12 20:33:57 +02:00
int msaa_mode = GLOBAL_DEF ( " rendering/quality/screen_filters/msaa " , 0 ) ;
2020-04-17 01:05:25 +02:00
ProjectSettings : : get_singleton ( ) - > set_custom_property_info ( " rendering/quality/screen_filters/msaa " , PropertyInfo ( Variant : : INT , " rendering/quality/screen_filters/msaa " , PROPERTY_HINT_ENUM , " Disabled,2x,4x,8x,16x " ) ) ;
2017-01-02 02:16:52 +01:00
root - > set_msaa ( Viewport : : MSAA ( msaa_mode ) ) ;
2017-07-19 22:00:46 +02:00
2020-04-12 20:33:57 +02:00
int ssaa_mode = GLOBAL_DEF ( " rendering/quality/screen_filters/screen_space_aa " , 0 ) ;
ProjectSettings : : get_singleton ( ) - > set_custom_property_info ( " rendering/quality/screen_filters/screen_space_aa " , PropertyInfo ( Variant : : INT , " rendering/quality/screen_filters/screen_space_aa " , PROPERTY_HINT_ENUM , " Disabled,FXAA " ) ) ;
2020-04-12 06:49:10 +02:00
root - > set_screen_space_aa ( Viewport : : ScreenSpaceAA ( ssaa_mode ) ) ;
2017-05-29 02:46:48 +02:00
{ //load default fallback environment
//get possible extensions
List < String > exts ;
ResourceLoader : : get_recognized_extensions_for_type ( " Environment " , & exts ) ;
String ext_hint ;
for ( List < String > : : Element * E = exts . front ( ) ; E ; E = E - > next ( ) ) {
if ( ext_hint ! = String ( ) )
ext_hint + = " , " ;
ext_hint + = " *. " + E - > get ( ) ;
}
//get path
2017-07-18 02:05:38 +02:00
String env_path = GLOBAL_DEF ( " rendering/environment/default_environment " , " " ) ;
2017-05-29 02:46:48 +02:00
//setup property
2017-07-19 22:00:46 +02:00
ProjectSettings : : get_singleton ( ) - > set_custom_property_info ( " rendering/environment/default_environment " , PropertyInfo ( Variant : : STRING , " rendering/viewport/default_environment " , PROPERTY_HINT_FILE , ext_hint ) ) ;
2017-05-29 02:46:48 +02:00
env_path = env_path . strip_edges ( ) ;
if ( env_path ! = String ( ) ) {
Ref < Environment > env = ResourceLoader : : load ( env_path ) ;
if ( env . is_valid ( ) ) {
root - > get_world ( ) - > set_fallback_environment ( env ) ;
} else {
2017-08-19 01:02:56 +02:00
if ( Engine : : get_singleton ( ) - > is_editor_hint ( ) ) {
2017-05-29 02:46:48 +02:00
//file was erased, clear the field.
2017-07-19 22:00:46 +02:00
ProjectSettings : : get_singleton ( ) - > set ( " rendering/environment/default_environment " , " " ) ;
2017-05-29 02:46:48 +02:00
} else {
//file was erased, notify user.
2019-11-06 17:03:04 +01:00
ERR_PRINT ( RTR ( " Default Environment as specified in Project Settings (Rendering -> Environment -> Default Environment) could not be loaded. " ) ) ;
2017-05-29 02:46:48 +02:00
}
}
}
}
2017-03-05 16:44:50 +01:00
root - > set_physics_object_picking ( GLOBAL_DEF ( " physics/common/enable_object_picking " , true ) ) ;
2014-09-15 16:33:30 +02:00
2020-03-04 17:36:09 +01:00
root - > connect ( " close_requested " , callable_mp ( this , & SceneTree : : _main_window_close ) ) ;
root - > connect ( " go_back_requested " , callable_mp ( this , & SceneTree : : _main_window_go_back ) ) ;
root - > connect ( " focus_entered " , callable_mp ( this , & SceneTree : : _main_window_focus_in ) ) ;
2014-10-14 06:01:25 +02:00
# ifdef TOOLS_ENABLED
2020-04-02 01:20:12 +02:00
edited_scene_root = nullptr ;
2014-10-14 06:01:25 +02:00
# endif
2014-02-10 02:10:30 +01:00
}
2014-11-06 01:20:42 +01:00
SceneTree : : ~ SceneTree ( ) {
2019-06-01 15:42:22 +02:00
if ( root ) {
2020-04-02 01:20:12 +02:00
root - > _set_tree ( nullptr ) ;
2019-06-01 15:42:22 +02:00
root - > _propagate_after_exit_tree ( ) ;
memdelete ( root ) ;
}
2020-04-02 01:20:12 +02:00
if ( singleton = = this ) singleton = nullptr ;
2014-02-10 02:10:30 +01:00
}