2014-02-10 01:10:30 +00:00
/*************************************************************************/
2017-09-01 14:07:55 +00:00
/* scene_tree.cpp */
2014-02-10 01:10:30 +00:00
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
2017-08-27 12:16:55 +00:00
/* https://godotengine.org */
2014-02-10 01:10:30 +00:00
/*************************************************************************/
2022-01-03 20:27:34 +00:00
/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
2014-02-10 01:10:30 +00:00
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
/* "Software"), to deal in the Software without restriction, including */
/* without limitation the rights to use, copy, modify, merge, publish, */
/* distribute, sublicense, and/or sell copies of the Software, and to */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions: */
/* */
/* The above copyright notice and this permission notice shall be */
/* included in all copies or substantial portions of the Software. */
/* */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
2018-01-04 23:50:27 +00:00
2017-06-27 01:58:03 +00:00
# include "scene_tree.h"
2014-02-10 01:10:30 +00:00
2020-11-07 22:33:38 +00:00
# include "core/config/project_settings.h"
2020-02-27 02:30:20 +00:00
# include "core/debugger/engine_debugger.h"
2020-04-28 13:19:37 +00:00
# include "core/input/input.h"
2021-06-11 12:51:48 +00:00
# include "core/io/dir_access.h"
2022-02-11 11:33:54 +00:00
# include "core/io/image_loader.h"
2018-09-11 16:13:45 +00:00
# include "core/io/marshalls.h"
# include "core/io/resource_loader.h"
2020-11-07 22:33:38 +00:00
# include "core/object/message_queue.h"
2018-09-11 16:13:45 +00:00
# include "core/os/keyboard.h"
# include "core/os/os.h"
2020-11-07 22:33:38 +00:00
# include "core/string/print_string.h"
2014-02-10 01:10:30 +00:00
# include "node.h"
2020-09-05 01:05:30 +00:00
# include "scene/animation/tween.h"
2020-02-07 01:52:05 +00:00
# include "scene/debugger/scene_debugger.h"
2022-09-24 14:32:53 +00:00
# include "scene/gui/control.h"
2022-07-12 21:12:42 +00:00
# include "scene/main/multiplayer_api.h"
2022-02-12 01:46:22 +00:00
# include "scene/main/viewport.h"
2022-07-31 23:20:24 +00:00
# include "scene/resources/environment.h"
2020-09-03 11:22:16 +00:00
# include "scene/resources/font.h"
2015-09-20 16:03:46 +00:00
# include "scene/resources/material.h"
# include "scene/resources/mesh.h"
2017-03-05 15:44:50 +00:00
# include "scene/resources/packed_scene.h"
2022-02-12 01:46:22 +00:00
# include "scene/resources/world_2d.h"
# include "scene/resources/world_3d.h"
2017-03-05 15:44:50 +00:00
# include "scene/scene_string_names.h"
2020-03-03 13:36:29 +00:00
# include "servers/display_server.h"
2020-03-27 18:21:27 +00:00
# include "servers/navigation_server_3d.h"
# include "servers/physics_server_2d.h"
# include "servers/physics_server_3d.h"
2020-03-04 01:51:12 +00:00
# include "window.h"
2016-08-07 00:39:50 +00:00
2017-08-27 19:07:15 +00:00
# include <stdio.h>
2020-05-21 16:08:48 +00:00
# include <stdlib.h>
2017-08-27 19:07:15 +00:00
2016-08-07 00:39:50 +00:00
void SceneTreeTimer : : _bind_methods ( ) {
2017-03-05 15:44:50 +00: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 00:39:50 +00:00
2021-12-03 00:09:19 +00:00
ADD_PROPERTY ( PropertyInfo ( Variant : : FLOAT , " time_left " , PROPERTY_HINT_NONE , " suffix:s " ) , " set_time_left " , " get_time_left " ) ;
2018-01-11 22:35:12 +00:00
2016-08-07 00:39:50 +00:00
ADD_SIGNAL ( MethodInfo ( " timeout " ) ) ;
}
2021-05-21 05:23:35 +00:00
void SceneTreeTimer : : set_time_left ( double p_time ) {
2017-03-05 15:44:50 +00:00
time_left = p_time ;
2016-08-07 00:39:50 +00:00
}
2021-05-21 05:23:35 +00:00
double SceneTreeTimer : : get_time_left ( ) const {
2016-08-07 00:39:50 +00:00
return time_left ;
}
2021-02-19 12:57:41 +00:00
void SceneTreeTimer : : set_process_always ( bool p_process_always ) {
process_always = p_process_always ;
2017-02-13 23:34:33 +00:00
}
2021-02-19 12:57:41 +00:00
bool SceneTreeTimer : : is_process_always ( ) {
return process_always ;
2017-02-13 23:34:33 +00:00
}
2016-08-07 00:39:50 +00:00
2022-07-15 06:21:51 +00:00
void SceneTreeTimer : : set_process_in_physics ( bool p_process_in_physics ) {
process_in_physics = p_process_in_physics ;
}
bool SceneTreeTimer : : is_process_in_physics ( ) {
return process_in_physics ;
}
2021-02-26 23:37:20 +00:00
void SceneTreeTimer : : set_ignore_time_scale ( bool p_ignore ) {
ignore_time_scale = p_ignore ;
}
bool SceneTreeTimer : : is_ignore_time_scale ( ) {
return ignore_time_scale ;
}
2019-10-19 16:45:17 +00:00
void SceneTreeTimer : : release_connections ( ) {
2022-09-29 09:53:28 +00:00
List < Connection > signal_connections ;
get_all_signal_connections ( & signal_connections ) ;
2019-10-19 16:45:17 +00:00
2022-09-29 09:53:28 +00:00
for ( const Connection & connection : signal_connections ) {
2020-02-21 22:26:13 +00:00
disconnect ( connection . signal . get_name ( ) , connection . callable ) ;
2019-10-19 16:45:17 +00:00
}
}
2021-02-09 17:24:36 +00:00
SceneTreeTimer : : SceneTreeTimer ( ) { }
2016-08-07 00:39:50 +00:00
2014-11-06 00:20:42 +00:00
void SceneTree : : tree_changed ( ) {
2014-02-10 01:10:30 +00:00
tree_version + + ;
emit_signal ( tree_changed_name ) ;
}
2017-10-19 00:30:27 +00:00
void SceneTree : : node_added ( Node * p_node ) {
emit_signal ( node_added_name , p_node ) ;
}
2014-11-06 00:20:42 +00:00
void SceneTree : : node_removed ( Node * p_node ) {
2017-03-05 15:44:50 +00:00
if ( current_scene = = p_node ) {
2020-04-01 23:20:12 +00:00
current_scene = nullptr ;
2015-05-17 19:33:35 +00:00
}
2017-03-05 15:44:50 +00:00
emit_signal ( node_removed_name , p_node ) ;
2020-05-14 14:41:43 +00:00
if ( call_lock > 0 ) {
2022-11-27 12:42:24 +00:00
call_skip . insert ( p_node ) ;
2020-05-14 14:41:43 +00:00
}
2014-02-10 01:10:30 +00:00
}
2019-05-24 13:27:22 +00:00
void SceneTree : : node_renamed ( Node * p_node ) {
emit_signal ( node_renamed_name , p_node ) ;
}
2017-03-05 15:44:50 +00:00
SceneTree : : Group * SceneTree : : add_to_group ( const StringName & p_group , Node * p_node ) {
2022-05-13 13:04:37 +00:00
HashMap < StringName , Group > : : Iterator E = group_map . find ( p_group ) ;
2014-02-10 01:10:30 +00:00
if ( ! E ) {
2017-03-05 15:44:50 +00:00
E = group_map . insert ( p_group , Group ( ) ) ;
2014-02-10 01:10:30 +00:00
}
2022-05-13 13:04:37 +00:00
ERR_FAIL_COND_V_MSG ( E - > value . nodes . has ( p_node ) , & E - > value , " Already in group: " + p_group + " . " ) ;
E - > value . nodes . push_back ( p_node ) ;
//E->value.last_tree_version=0;
E - > value . changed = true ;
return & E - > value ;
2014-02-10 01:10:30 +00:00
}
2017-03-05 15:44:50 +00:00
void SceneTree : : remove_from_group ( const StringName & p_group , Node * p_node ) {
2022-05-13 13:04:37 +00:00
HashMap < StringName , Group > : : Iterator E = group_map . find ( p_group ) ;
2014-02-10 01:10:30 +00:00
ERR_FAIL_COND ( ! E ) ;
2022-05-13 13:04:37 +00:00
E - > value . nodes . erase ( p_node ) ;
if ( E - > value . nodes . is_empty ( ) ) {
group_map . remove ( E ) ;
2020-05-14 14:41:43 +00:00
}
2014-02-10 01:10:30 +00:00
}
2018-07-02 05:30:40 +00:00
void SceneTree : : make_group_changed ( const StringName & p_group ) {
2022-05-13 13:04:37 +00:00
HashMap < StringName , Group > : : Iterator E = group_map . find ( p_group ) ;
2020-05-14 14:41:43 +00:00
if ( E ) {
2022-05-13 13:04:37 +00:00
E - > value . changed = true ;
2020-05-14 14:41:43 +00:00
}
2018-07-02 05:30:40 +00:00
}
2017-10-30 18:43:19 +00:00
void SceneTree : : flush_transform_notifications ( ) {
2017-03-05 15:44:50 +00:00
SelfList < Node > * n = xform_change_list . first ( ) ;
while ( n ) {
Node * node = n - > self ( ) ;
SelfList < Node > * nx = n - > next ( ) ;
2014-02-10 01:10:30 +00:00
xform_change_list . remove ( n ) ;
2017-03-05 15:44:50 +00:00
n = nx ;
2014-02-10 01:10:30 +00:00
node - > notification ( NOTIFICATION_TRANSFORM_CHANGED ) ;
}
}
2014-11-06 00:20:42 +00:00
void SceneTree : : _flush_ugc ( ) {
2017-03-05 15:44:50 +00:00
ugc_locked = true ;
2014-02-10 01:10:30 +00:00
while ( unique_group_calls . size ( ) ) {
2022-05-13 13:04:37 +00:00
HashMap < UGCall , Vector < Variant > , UGCall > : : Iterator E = unique_group_calls . begin ( ) ;
2014-02-10 01:10:30 +00:00
2022-05-13 13:04:37 +00:00
const Variant * * argptrs = ( const Variant * * ) alloca ( E - > value . size ( ) * sizeof ( Variant * ) ) ;
2022-03-09 13:58:40 +00:00
2022-05-13 13:04:37 +00:00
for ( int i = 0 ; i < E - > value . size ( ) ; i + + ) {
argptrs [ i ] = & E - > value [ i ] ;
2020-05-14 14:41:43 +00:00
}
2014-02-10 01:10:30 +00:00
2022-05-13 13:04:37 +00:00
call_group_flagsp ( GROUP_CALL_DEFAULT , E - > key . group , E - > key . call , argptrs , E - > value . size ( ) ) ;
2014-02-10 01:10:30 +00:00
2022-05-13 13:04:37 +00:00
unique_group_calls . remove ( E ) ;
2014-02-10 01:10:30 +00:00
}
2017-03-05 15:44:50 +00:00
ugc_locked = false ;
2014-02-10 01:10:30 +00:00
}
2018-07-02 05:30:40 +00:00
void SceneTree : : _update_group_order ( Group & g , bool p_use_priority ) {
2020-05-14 14:41:43 +00:00
if ( ! g . changed ) {
2014-02-10 01:10:30 +00:00
return ;
2020-05-14 14:41:43 +00:00
}
2020-12-15 12:04:21 +00:00
if ( g . nodes . is_empty ( ) ) {
2014-02-10 01:10:30 +00:00
return ;
2020-05-14 14:41:43 +00:00
}
2014-02-10 01:10:30 +00:00
2022-09-29 09:53:28 +00:00
Node * * gr_nodes = g . nodes . ptrw ( ) ;
int gr_node_count = g . nodes . size ( ) ;
2016-06-08 01:08:12 +00:00
2018-07-02 05:30:40 +00:00
if ( p_use_priority ) {
SortArray < Node * , Node : : ComparatorWithPriority > node_sort ;
2022-09-29 09:53:28 +00:00
node_sort . sort ( gr_nodes , gr_node_count ) ;
2018-07-02 05:30:40 +00:00
} else {
SortArray < Node * , Node : : Comparator > node_sort ;
2022-09-29 09:53:28 +00:00
node_sort . sort ( gr_nodes , gr_node_count ) ;
2018-07-02 05:30:40 +00:00
}
2017-03-05 15:44:50 +00:00
g . changed = false ;
2014-02-10 01:10:30 +00:00
}
2022-03-09 13:58:40 +00:00
void SceneTree : : call_group_flagsp ( uint32_t p_call_flags , const StringName & p_group , const StringName & p_function , const Variant * * p_args , int p_argcount ) {
2022-05-13 13:04:37 +00:00
HashMap < StringName , Group > : : Iterator E = group_map . find ( p_group ) ;
2020-05-14 14:41:43 +00:00
if ( ! E ) {
2014-02-10 01:10:30 +00:00
return ;
2020-05-14 14:41:43 +00:00
}
2022-05-13 13:04:37 +00:00
Group & g = E - > value ;
2020-12-15 12:04:21 +00:00
if ( g . nodes . is_empty ( ) ) {
2014-02-10 01:10:30 +00:00
return ;
2020-05-14 14:41:43 +00:00
}
2014-02-10 01:10:30 +00:00
2021-08-12 21:40:13 +00:00
if ( p_call_flags & GROUP_CALL_UNIQUE & & p_call_flags & GROUP_CALL_DEFERRED ) {
2014-02-10 01:10:30 +00:00
ERR_FAIL_COND ( ugc_locked ) ;
UGCall ug ;
2017-03-05 15:44:50 +00:00
ug . call = p_function ;
ug . group = p_group ;
2014-02-10 01:10:30 +00:00
2020-05-14 14:41:43 +00:00
if ( unique_group_calls . has ( ug ) ) {
2014-02-10 01:10:30 +00:00
return ;
2020-05-14 14:41:43 +00:00
}
2014-02-10 01:10:30 +00:00
Vector < Variant > args ;
2022-03-09 13:58:40 +00:00
for ( int i = 0 ; i < p_argcount ; i + + ) {
args . push_back ( * p_args [ i ] ) ;
2014-02-10 01:10:30 +00:00
}
2017-03-05 15:44:50 +00:00
unique_group_calls [ ug ] = args ;
2014-02-10 01:10:30 +00:00
return ;
}
2016-06-08 01:08:12 +00:00
_update_group_order ( g ) ;
2017-03-05 15:44:50 +00:00
Vector < Node * > nodes_copy = g . nodes ;
2022-09-29 09:53:28 +00:00
Node * * gr_nodes = nodes_copy . ptrw ( ) ;
int gr_node_count = nodes_copy . size ( ) ;
2014-02-10 01:10:30 +00:00
call_lock + + ;
2017-03-05 15:44:50 +00:00
if ( p_call_flags & GROUP_CALL_REVERSE ) {
2022-09-29 09:53:28 +00:00
for ( int i = gr_node_count - 1 ; i > = 0 ; i - - ) {
2022-11-27 12:42:24 +00:00
if ( call_lock & & call_skip . has ( gr_nodes [ i ] ) ) {
2014-02-10 01:10:30 +00:00
continue ;
2020-05-14 14:41:43 +00:00
}
2014-02-10 01:10:30 +00:00
2021-08-12 21:40:13 +00:00
if ( ! ( p_call_flags & GROUP_CALL_DEFERRED ) ) {
2022-03-09 13:58:40 +00:00
Callable : : CallError ce ;
2022-09-29 09:53:28 +00:00
gr_nodes [ i ] - > callp ( p_function , p_args , p_argcount , ce ) ;
2020-05-14 14:41:43 +00:00
} else {
2022-09-29 09:53:28 +00:00
MessageQueue : : get_singleton ( ) - > push_callp ( gr_nodes [ i ] , p_function , p_args , p_argcount ) ;
2020-05-14 14:41:43 +00:00
}
2014-02-10 01:10:30 +00:00
}
} else {
2022-09-29 09:53:28 +00:00
for ( int i = 0 ; i < gr_node_count ; i + + ) {
2022-11-27 12:42:24 +00:00
if ( call_lock & & call_skip . has ( gr_nodes [ i ] ) ) {
2014-02-10 01:10:30 +00:00
continue ;
2020-05-14 14:41:43 +00:00
}
2014-02-10 01:10:30 +00:00
2021-08-12 21:40:13 +00:00
if ( ! ( p_call_flags & GROUP_CALL_DEFERRED ) ) {
2022-03-09 13:58:40 +00:00
Callable : : CallError ce ;
2022-09-29 09:53:28 +00:00
gr_nodes [ i ] - > callp ( p_function , p_args , p_argcount , ce ) ;
2020-05-14 14:41:43 +00:00
} else {
2022-09-29 09:53:28 +00:00
MessageQueue : : get_singleton ( ) - > push_callp ( gr_nodes [ i ] , p_function , p_args , p_argcount ) ;
2020-05-14 14:41:43 +00:00
}
2014-02-10 01:10:30 +00:00
}
}
call_lock - - ;
2020-05-14 14:41:43 +00:00
if ( call_lock = = 0 ) {
2014-02-10 01:10:30 +00:00
call_skip . clear ( ) ;
2020-05-14 14:41:43 +00:00
}
2014-02-10 01:10:30 +00:00
}
2017-03-05 15:44:50 +00:00
void SceneTree : : notify_group_flags ( uint32_t p_call_flags , const StringName & p_group , int p_notification ) {
2022-05-13 13:04:37 +00:00
HashMap < StringName , Group > : : Iterator E = group_map . find ( p_group ) ;
2020-05-14 14:41:43 +00:00
if ( ! E ) {
2014-02-10 01:10:30 +00:00
return ;
2020-05-14 14:41:43 +00:00
}
2022-05-13 13:04:37 +00:00
Group & g = E - > value ;
2020-12-15 12:04:21 +00:00
if ( g . nodes . is_empty ( ) ) {
2014-02-10 01:10:30 +00:00
return ;
2020-05-14 14:41:43 +00:00
}
2014-02-10 01:10:30 +00:00
_update_group_order ( g ) ;
2017-03-05 15:44:50 +00:00
Vector < Node * > nodes_copy = g . nodes ;
2022-09-29 09:53:28 +00:00
Node * * gr_nodes = nodes_copy . ptrw ( ) ;
int gr_node_count = nodes_copy . size ( ) ;
2014-02-10 01:10:30 +00:00
call_lock + + ;
2017-03-05 15:44:50 +00:00
if ( p_call_flags & GROUP_CALL_REVERSE ) {
2022-09-29 09:53:28 +00:00
for ( int i = gr_node_count - 1 ; i > = 0 ; i - - ) {
2022-11-27 12:42:24 +00:00
if ( call_lock & & call_skip . has ( gr_nodes [ i ] ) ) {
2014-02-10 01:10:30 +00:00
continue ;
2020-05-14 14:41:43 +00:00
}
2014-02-10 01:10:30 +00:00
2021-08-12 21:40:13 +00:00
if ( ! ( p_call_flags & GROUP_CALL_DEFERRED ) ) {
2022-09-29 09:53:28 +00:00
gr_nodes [ i ] - > notification ( p_notification ) ;
2020-05-14 14:41:43 +00:00
} else {
2022-09-29 09:53:28 +00:00
MessageQueue : : get_singleton ( ) - > push_notification ( gr_nodes [ i ] , p_notification ) ;
2020-05-14 14:41:43 +00:00
}
2014-02-10 01:10:30 +00:00
}
} else {
2022-09-29 09:53:28 +00:00
for ( int i = 0 ; i < gr_node_count ; i + + ) {
2022-11-27 12:42:24 +00:00
if ( call_lock & & call_skip . has ( gr_nodes [ i ] ) ) {
2014-02-10 01:10:30 +00:00
continue ;
2020-05-14 14:41:43 +00:00
}
2014-02-10 01:10:30 +00:00
2021-08-12 21:40:13 +00:00
if ( ! ( p_call_flags & GROUP_CALL_DEFERRED ) ) {
2022-09-29 09:53:28 +00:00
gr_nodes [ i ] - > notification ( p_notification ) ;
2020-05-14 14:41:43 +00:00
} else {
2022-09-29 09:53:28 +00:00
MessageQueue : : get_singleton ( ) - > push_notification ( gr_nodes [ i ] , p_notification ) ;
2020-05-14 14:41:43 +00:00
}
2014-02-10 01:10:30 +00:00
}
}
call_lock - - ;
2020-05-14 14:41:43 +00:00
if ( call_lock = = 0 ) {
2014-02-10 01:10:30 +00:00
call_skip . clear ( ) ;
2020-05-14 14:41:43 +00:00
}
2014-02-10 01:10:30 +00:00
}
2017-03-05 15:44:50 +00:00
void SceneTree : : set_group_flags ( uint32_t p_call_flags , const StringName & p_group , const String & p_name , const Variant & p_value ) {
2022-05-13 13:04:37 +00:00
HashMap < StringName , Group > : : Iterator E = group_map . find ( p_group ) ;
2020-05-14 14:41:43 +00:00
if ( ! E ) {
2014-02-10 01:10:30 +00:00
return ;
2020-05-14 14:41:43 +00:00
}
2022-05-13 13:04:37 +00:00
Group & g = E - > value ;
2020-12-15 12:04:21 +00:00
if ( g . nodes . is_empty ( ) ) {
2014-02-10 01:10:30 +00:00
return ;
2020-05-14 14:41:43 +00:00
}
2014-02-10 01:10:30 +00:00
_update_group_order ( g ) ;
2017-03-05 15:44:50 +00:00
Vector < Node * > nodes_copy = g . nodes ;
2022-09-29 09:53:28 +00:00
Node * * gr_nodes = nodes_copy . ptrw ( ) ;
int gr_node_count = nodes_copy . size ( ) ;
2014-02-10 01:10:30 +00:00
call_lock + + ;
2017-03-05 15:44:50 +00:00
if ( p_call_flags & GROUP_CALL_REVERSE ) {
2022-09-29 09:53:28 +00:00
for ( int i = gr_node_count - 1 ; i > = 0 ; i - - ) {
2022-11-27 12:42:24 +00:00
if ( call_lock & & call_skip . has ( gr_nodes [ i ] ) ) {
2014-02-10 01:10:30 +00:00
continue ;
2020-05-14 14:41:43 +00:00
}
2014-02-10 01:10:30 +00:00
2021-08-12 21:40:13 +00:00
if ( ! ( p_call_flags & GROUP_CALL_DEFERRED ) ) {
2022-09-29 09:53:28 +00:00
gr_nodes [ i ] - > set ( p_name , p_value ) ;
2020-05-14 14:41:43 +00:00
} else {
2022-09-29 09:53:28 +00:00
MessageQueue : : get_singleton ( ) - > push_set ( gr_nodes [ i ] , p_name , p_value ) ;
2020-05-14 14:41:43 +00:00
}
2014-02-10 01:10:30 +00:00
}
} else {
2022-09-29 09:53:28 +00:00
for ( int i = 0 ; i < gr_node_count ; i + + ) {
2022-11-27 12:42:24 +00:00
if ( call_lock & & call_skip . has ( gr_nodes [ i ] ) ) {
2014-02-10 01:10:30 +00:00
continue ;
2020-05-14 14:41:43 +00:00
}
2014-02-10 01:10:30 +00:00
2021-08-12 21:40:13 +00:00
if ( ! ( p_call_flags & GROUP_CALL_DEFERRED ) ) {
2022-09-29 09:53:28 +00:00
gr_nodes [ i ] - > set ( p_name , p_value ) ;
2020-05-14 14:41:43 +00:00
} else {
2022-09-29 09:53:28 +00:00
MessageQueue : : get_singleton ( ) - > push_set ( gr_nodes [ i ] , p_name , p_value ) ;
2020-05-14 14:41:43 +00:00
}
2014-02-10 01:10:30 +00:00
}
}
call_lock - - ;
2020-05-14 14:41:43 +00:00
if ( call_lock = = 0 ) {
2014-02-10 01:10:30 +00:00
call_skip . clear ( ) ;
2020-05-14 14:41:43 +00:00
}
2014-02-10 01:10:30 +00:00
}
2017-03-05 15:44:50 +00:00
void SceneTree : : notify_group ( const StringName & p_group , int p_notification ) {
2022-06-19 14:04:53 +00:00
notify_group_flags ( GROUP_CALL_DEFAULT , p_group , p_notification ) ;
2017-01-14 13:03:53 +00:00
}
2017-03-05 15:44:50 +00:00
void SceneTree : : set_group ( const StringName & p_group , const String & p_name , const Variant & p_value ) {
2021-08-12 21:40:13 +00:00
set_group_flags ( GROUP_CALL_DEFAULT , p_group , p_name , p_value ) ;
2017-01-14 13:03:53 +00:00
}
2020-12-22 09:50:29 +00:00
void SceneTree : : initialize ( ) {
2021-03-20 23:48:41 +00:00
ERR_FAIL_COND ( ! root ) ;
2017-03-05 15:44:50 +00:00
initialized = true ;
2014-11-06 00:20:42 +00:00
root - > _set_tree ( this ) ;
2020-12-22 09:50:29 +00:00
MainLoop : : initialize ( ) ;
2014-02-10 01:10:30 +00:00
}
2021-05-21 05:23:35 +00:00
bool SceneTree : : physics_process ( double p_time ) {
2014-02-10 01:10:30 +00:00
root_lock + + ;
current_frame + + ;
2017-10-30 18:43:19 +00:00
flush_transform_notifications ( ) ;
2014-02-10 01:10:30 +00:00
2020-12-22 09:50:29 +00:00
MainLoop : : physics_process ( p_time ) ;
2017-09-30 14:19:07 +00:00
physics_process_time = p_time ;
2014-09-15 14:33:30 +00:00
2021-07-17 21:22:52 +00:00
emit_signal ( SNAME ( " physics_frame " ) ) ;
2014-09-15 14:33:30 +00:00
2022-07-01 18:16:05 +00:00
_notify_group_pause ( SNAME ( " _physics_process_internal " ) , Node : : NOTIFICATION_INTERNAL_PHYSICS_PROCESS ) ;
2021-08-12 21:40:13 +00:00
call_group ( SNAME ( " _picking_viewports " ) , SNAME ( " _process_picking " ) ) ;
2022-07-01 18:16:05 +00:00
_notify_group_pause ( SNAME ( " _physics_process " ) , Node : : NOTIFICATION_PHYSICS_PROCESS ) ;
2014-02-10 01:10:30 +00:00
_flush_ugc ( ) ;
2017-08-08 01:18:12 +00:00
MessageQueue : : get_singleton ( ) - > flush ( ) ; //small little hack
2020-09-05 01:05:30 +00:00
2022-07-15 06:21:51 +00:00
process_timers ( p_time , true ) ; //go through timers
2020-09-05 01:05:30 +00:00
process_tweens ( p_time , true ) ;
2017-10-30 18:43:19 +00:00
flush_transform_notifications ( ) ;
2014-02-10 01:10:30 +00:00
root_lock - - ;
_flush_delete_queue ( ) ;
2016-10-27 14:50:26 +00:00
_call_idle_callbacks ( ) ;
2014-02-10 01:10:30 +00:00
return _quit ;
}
2021-05-21 05:23:35 +00:00
bool SceneTree : : process ( double p_time ) {
2014-02-10 01:10:30 +00:00
root_lock + + ;
2020-12-22 09:50:29 +00:00
MainLoop : : process ( p_time ) ;
2014-02-10 01:10:30 +00:00
2020-12-22 09:50:29 +00:00
process_time = p_time ;
2014-02-10 01:10:30 +00:00
2018-06-02 12:32:30 +00:00
if ( multiplayer_poll ) {
multiplayer - > poll ( ) ;
2022-05-08 08:09:19 +00:00
for ( KeyValue < NodePath , Ref < MultiplayerAPI > > & E : custom_multiplayers ) {
E . value - > poll ( ) ;
2022-02-05 00:43:47 +00:00
}
2018-06-02 12:32:30 +00:00
}
2016-08-14 21:49:50 +00:00
2021-07-17 21:22:52 +00:00
emit_signal ( SNAME ( " process_frame " ) ) ;
2014-09-15 14:33:30 +00:00
2017-08-08 01:18:12 +00:00
MessageQueue : : get_singleton ( ) - > flush ( ) ; //small little hack
2017-10-30 18:43:19 +00:00
flush_transform_notifications ( ) ;
2014-02-10 01:10:30 +00:00
2022-07-01 18:16:05 +00:00
_notify_group_pause ( SNAME ( " _process_internal " ) , Node : : NOTIFICATION_INTERNAL_PROCESS ) ;
_notify_group_pause ( SNAME ( " _process " ) , Node : : NOTIFICATION_PROCESS ) ;
2014-02-10 01:10:30 +00:00
_flush_ugc ( ) ;
2017-08-08 01:18:12 +00:00
MessageQueue : : get_singleton ( ) - > flush ( ) ; //small little hack
2017-10-30 18:43:19 +00:00
flush_transform_notifications ( ) ; //transforms after world update, to avoid unnecessary enter/exit notifications
2014-02-10 01:10:30 +00:00
root_lock - - ;
_flush_delete_queue ( ) ;
2022-07-15 06:21:51 +00:00
process_timers ( p_time , false ) ; //go through timers
2016-08-07 00:39:50 +00:00
2020-09-05 01:05:30 +00:00
process_tweens ( p_time , false ) ;
2019-07-29 10:33:38 +00:00
flush_transform_notifications ( ) ; //additional transforms after timers update
2016-10-27 14:50:26 +00:00
_call_idle_callbacks ( ) ;
2017-05-29 00:46:48 +00:00
# ifdef TOOLS_ENABLED
2021-07-04 01:43:23 +00:00
# ifndef _3D_DISABLED
2017-08-18 23:02:56 +00:00
if ( Engine : : get_singleton ( ) - > is_editor_hint ( ) ) {
2017-05-29 00:46:48 +00:00
//simple hack to reload fallback environment if it changed from editor
2022-10-18 14:43:37 +00:00
String env_path = GLOBAL_GET ( SNAME ( " rendering/environment/defaults/default_environment " ) ) ;
2017-05-29 00:46:48 +00:00
env_path = env_path . strip_edges ( ) ; //user may have added a space or two
String cpath ;
2020-04-18 09:00:51 +00:00
Ref < Environment > fallback = get_root ( ) - > get_world_3d ( ) - > get_fallback_environment ( ) ;
2017-05-29 00:46:48 +00:00
if ( fallback . is_valid ( ) ) {
cpath = fallback - > get_path ( ) ;
}
if ( cpath ! = env_path ) {
2021-12-09 09:42:46 +00:00
if ( ! env_path . is_empty ( ) ) {
2017-05-29 00:46:48 +00:00
fallback = ResourceLoader : : load ( env_path ) ;
2017-08-31 11:55:20 +00:00
if ( fallback . is_null ( ) ) {
//could not load fallback, set as empty
2021-02-17 16:44:49 +00:00
ProjectSettings : : get_singleton ( ) - > set ( " rendering/environment/defaults/default_environment " , " " ) ;
2017-08-31 11:55:20 +00:00
}
2017-05-29 00:46:48 +00:00
} else {
fallback . unref ( ) ;
}
2020-04-18 09:00:51 +00:00
get_root ( ) - > get_world_3d ( ) - > set_fallback_environment ( fallback ) ;
2017-05-29 00:46:48 +00:00
}
}
2021-07-04 01:43:23 +00:00
# endif // _3D_DISABLED
# endif // TOOLS_ENABLED
2017-05-29 00:46:48 +00:00
2014-02-10 01:10:30 +00:00
return _quit ;
}
2022-09-22 13:54:15 +00:00
void SceneTree : : process_timers ( double p_delta , bool p_physics_frame ) {
2022-07-15 06:21:51 +00:00
List < Ref < SceneTreeTimer > > : : Element * L = timers . back ( ) ; //last element
for ( List < Ref < SceneTreeTimer > > : : Element * E = timers . front ( ) ; E ; ) {
List < Ref < SceneTreeTimer > > : : Element * N = E - > next ( ) ;
if ( ( paused & & ! E - > get ( ) - > is_process_always ( ) ) | | ( E - > get ( ) - > is_process_in_physics ( ) ! = p_physics_frame ) ) {
if ( E = = L ) {
break ; //break on last, so if new timers were added during list traversal, ignore them.
}
E = N ;
continue ;
}
double time_left = E - > get ( ) - > get_time_left ( ) ;
if ( E - > get ( ) - > is_ignore_time_scale ( ) ) {
time_left - = Engine : : get_singleton ( ) - > get_process_step ( ) ;
} else {
time_left - = p_delta ;
}
E - > get ( ) - > set_time_left ( time_left ) ;
if ( time_left < = 0 ) {
E - > get ( ) - > emit_signal ( SNAME ( " timeout " ) ) ;
timers . erase ( E ) ;
}
if ( E = = L ) {
break ; //break on last, so if new timers were added during list traversal, ignore them.
}
E = N ;
}
}
2022-09-22 13:54:15 +00:00
void SceneTree : : process_tweens ( double p_delta , bool p_physics ) {
2020-09-05 01:05:30 +00:00
// This methods works similarly to how SceneTreeTimers are handled.
List < Ref < Tween > > : : Element * L = tweens . back ( ) ;
for ( List < Ref < Tween > > : : Element * E = tweens . front ( ) ; E ; ) {
List < Ref < Tween > > : : Element * N = E - > next ( ) ;
// Don't process if paused or process mode doesn't match.
2022-01-09 17:23:53 +00:00
if ( ! E - > get ( ) - > can_process ( paused ) | | ( p_physics = = ( E - > get ( ) - > get_process_mode ( ) = = Tween : : TWEEN_PROCESS_IDLE ) ) ) {
2020-09-05 01:05:30 +00:00
if ( E = = L ) {
break ;
}
E = N ;
continue ;
}
if ( ! E - > get ( ) - > step ( p_delta ) ) {
2021-08-05 11:05:14 +00:00
E - > get ( ) - > clear ( ) ;
2020-09-05 01:05:30 +00:00
tweens . erase ( E ) ;
}
if ( E = = L ) {
break ;
}
E = N ;
}
}
2020-12-22 09:50:29 +00:00
void SceneTree : : finalize ( ) {
2014-02-10 01:10:30 +00:00
_flush_delete_queue ( ) ;
_flush_ugc ( ) ;
2017-03-05 15:44:50 +00:00
initialized = false ;
2014-02-10 01:10:30 +00:00
2020-12-22 09:50:29 +00:00
MainLoop : : finalize ( ) ;
2014-02-10 01:10:30 +00:00
if ( root ) {
2020-04-01 23:20:12 +00:00
root - > _set_tree ( nullptr ) ;
2018-09-07 18:31:19 +00:00
root - > _propagate_after_exit_tree ( ) ;
2014-02-10 01:10:30 +00:00
memdelete ( root ) ; //delete root
2020-04-01 23:20:12 +00:00
root = nullptr ;
2014-02-10 01:10:30 +00:00
}
2019-10-19 16:45:17 +00:00
2021-10-08 14:37:03 +00:00
// In case deletion of some objects was queued when destructing the `root`.
// E.g. if `queue_free()` was called for some node outside the tree when handling NOTIFICATION_PREDELETE for some node in the tree.
_flush_delete_queue ( ) ;
// Cleanup timers.
2021-07-26 15:50:35 +00:00
for ( Ref < SceneTreeTimer > & timer : timers ) {
timer - > release_connections ( ) ;
2019-10-19 16:45:17 +00:00
}
timers . clear ( ) ;
2014-02-10 01:10:30 +00:00
}
2019-12-29 15:39:24 +00:00
void SceneTree : : quit ( int p_exit_code ) {
2020-06-04 20:03:45 +00:00
OS : : get_singleton ( ) - > set_exit_code ( p_exit_code ) ;
2017-03-05 15:44:50 +00:00
_quit = true ;
2014-02-10 01:10:30 +00:00
}
2020-03-04 16:36:09 +00:00
void SceneTree : : _main_window_close ( ) {
if ( accept_quit ) {
_quit = true ;
}
}
2020-05-14 12:29:06 +00:00
2020-03-04 16:36:09 +00:00
void SceneTree : : _main_window_go_back ( ) {
if ( quit_on_go_back ) {
_quit = true ;
}
}
2014-02-10 01:10:30 +00:00
2020-03-04 16:36:09 +00:00
void SceneTree : : _main_window_focus_in ( ) {
2020-04-28 13:19:37 +00:00
Input * id = Input : : get_singleton ( ) ;
2020-03-04 16:36:09 +00:00
if ( id ) {
id - > ensure_touch_mouse_raised ( ) ;
}
}
2019-09-09 21:42:17 +00:00
2020-03-04 16:36:09 +00:00
void SceneTree : : _notification ( int p_notification ) {
switch ( p_notification ) {
2017-01-09 19:43:44 +00:00
case NOTIFICATION_TRANSLATION_CHANGED : {
2017-08-18 23:02:56 +00:00
if ( ! Engine : : get_singleton ( ) - > is_editor_hint ( ) ) {
2019-04-04 13:34:03 +00:00
get_root ( ) - > propagate_notification ( p_notification ) ;
2017-06-28 20:00:18 +00:00
}
2017-01-09 19:43:44 +00:00
} break ;
2022-02-15 17:06:48 +00:00
2019-09-09 21:42:17 +00:00
case NOTIFICATION_OS_MEMORY_WARNING :
case NOTIFICATION_OS_IME_UPDATE :
case NOTIFICATION_WM_ABOUT :
case NOTIFICATION_CRASH :
2020-06-29 23:47:18 +00:00
case NOTIFICATION_APPLICATION_RESUMED :
case NOTIFICATION_APPLICATION_PAUSED :
case NOTIFICATION_APPLICATION_FOCUS_IN :
case NOTIFICATION_APPLICATION_FOCUS_OUT : {
2022-02-15 17:06:48 +00:00
// Pass these to nodes, since they are mirrored.
get_root ( ) - > propagate_notification ( p_notification ) ;
2018-07-02 19:18:58 +00:00
} break ;
2022-02-15 17:06:48 +00:00
}
}
2014-02-10 01:10:30 +00:00
2022-05-14 10:18:26 +00:00
bool SceneTree : : is_auto_accept_quit ( ) const {
return accept_quit ;
}
2014-11-06 00:20:42 +00:00
void SceneTree : : set_auto_accept_quit ( bool p_enable ) {
2017-03-05 15:44:50 +00:00
accept_quit = p_enable ;
2014-02-10 01:10:30 +00:00
}
2022-05-14 10:18:26 +00:00
bool SceneTree : : is_quit_on_go_back ( ) const {
return quit_on_go_back ;
}
2017-01-11 19:34:32 +00:00
void SceneTree : : set_quit_on_go_back ( bool p_enable ) {
2017-03-05 15:44:50 +00:00
quit_on_go_back = p_enable ;
2017-01-11 19:34:32 +00:00
}
2017-04-07 14:17:16 +00:00
# ifdef TOOLS_ENABLED
2014-02-10 01:10:30 +00:00
2017-03-05 15:44:50 +00:00
bool SceneTree : : is_node_being_edited ( const Node * p_node ) const {
2021-06-18 22:02:50 +00:00
return Engine : : get_singleton ( ) - > is_editor_hint ( ) & & edited_scene_root & & ( edited_scene_root - > is_ancestor_of ( p_node ) | | edited_scene_root = = p_node ) ;
2014-02-10 01:10:30 +00:00
}
2017-04-07 14:17:16 +00:00
# endif
2014-02-10 01:10:30 +00:00
2017-04-07 14:17:16 +00:00
# ifdef DEBUG_ENABLED
2015-09-19 02:10:58 +00:00
void SceneTree : : set_debug_collisions_hint ( bool p_enabled ) {
2017-03-05 15:44:50 +00:00
debug_collisions_hint = p_enabled ;
2015-09-19 02:10:58 +00:00
}
bool SceneTree : : is_debugging_collisions_hint ( ) const {
return debug_collisions_hint ;
}
2022-06-15 21:24:06 +00:00
void SceneTree : : set_debug_paths_hint ( bool p_enabled ) {
debug_paths_hint = p_enabled ;
}
bool SceneTree : : is_debugging_paths_hint ( ) const {
return debug_paths_hint ;
}
2015-09-20 16:03:46 +00:00
void SceneTree : : set_debug_navigation_hint ( bool p_enabled ) {
2017-03-05 15:44:50 +00:00
debug_navigation_hint = p_enabled ;
2015-09-20 16:03:46 +00:00
}
bool SceneTree : : is_debugging_navigation_hint ( ) const {
return debug_navigation_hint ;
}
2017-04-07 14:17:16 +00:00
# endif
2015-09-20 16:03:46 +00:00
2017-03-05 15:44:50 +00:00
void SceneTree : : set_debug_collisions_color ( const Color & p_color ) {
debug_collisions_color = p_color ;
2015-09-20 16:03:46 +00:00
}
Color SceneTree : : get_debug_collisions_color ( ) const {
return debug_collisions_color ;
}
2017-03-05 15:44:50 +00:00
void SceneTree : : set_debug_collision_contact_color ( const Color & p_color ) {
debug_collision_contact_color = p_color ;
2015-09-20 16:03:46 +00:00
}
Color SceneTree : : get_debug_collision_contact_color ( ) const {
return debug_collision_contact_color ;
}
2022-06-15 21:24:06 +00:00
void SceneTree : : set_debug_paths_color ( const Color & p_color ) {
debug_paths_color = p_color ;
}
Color SceneTree : : get_debug_paths_color ( ) const {
return debug_paths_color ;
}
void SceneTree : : set_debug_paths_width ( float p_width ) {
debug_paths_width = p_width ;
}
float SceneTree : : get_debug_paths_width ( ) const {
return debug_paths_width ;
}
Ref < Material > SceneTree : : get_debug_paths_material ( ) {
if ( debug_paths_material . is_valid ( ) ) {
return debug_paths_material ;
}
Ref < StandardMaterial3D > _debug_material = Ref < StandardMaterial3D > ( memnew ( StandardMaterial3D ) ) ;
_debug_material - > set_shading_mode ( StandardMaterial3D : : SHADING_MODE_UNSHADED ) ;
_debug_material - > set_transparency ( StandardMaterial3D : : TRANSPARENCY_ALPHA ) ;
_debug_material - > set_flag ( StandardMaterial3D : : FLAG_SRGB_VERTEX_COLOR , true ) ;
_debug_material - > set_flag ( StandardMaterial3D : : FLAG_ALBEDO_FROM_VERTEX_COLOR , true ) ;
_debug_material - > set_albedo ( get_debug_paths_color ( ) ) ;
debug_paths_material = _debug_material ;
return debug_paths_material ;
}
2015-09-20 16:03:46 +00:00
Ref < Material > SceneTree : : get_debug_collision_material ( ) {
2020-05-14 14:41:43 +00:00
if ( collision_material . is_valid ( ) ) {
2015-09-20 16:03:46 +00:00
return collision_material ;
2020-05-14 14:41:43 +00:00
}
2015-09-20 16:03:46 +00:00
2019-09-15 04:01:52 +00: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 20:21:05 +00:00
line_material - > set_albedo ( get_debug_collisions_color ( ) ) ;
2015-09-20 16:03:46 +00:00
2017-03-05 15:44:50 +00:00
collision_material = line_material ;
2015-09-20 16:03:46 +00:00
return collision_material ;
}
2017-06-07 21:18:55 +00:00
Ref < ArrayMesh > SceneTree : : get_debug_contact_mesh ( ) {
2020-05-14 14:41:43 +00:00
if ( debug_contact_mesh . is_valid ( ) ) {
2015-09-20 16:03:46 +00:00
return debug_contact_mesh ;
2020-05-14 14:41:43 +00:00
}
2015-09-20 16:03:46 +00:00
2017-06-07 21:18:55 +00:00
debug_contact_mesh = Ref < ArrayMesh > ( memnew ( ArrayMesh ) ) ;
2015-09-20 16:03:46 +00:00
2019-09-15 04:01:52 +00: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 20:21:05 +00:00
mat - > set_albedo ( get_debug_collision_contact_color ( ) ) ;
2015-09-20 16:03:46 +00:00
2017-03-05 15:44:50 +00:00
Vector3 diamond [ 6 ] = {
2015-09-20 16:03:46 +00:00
Vector3 ( - 1 , 0 , 0 ) ,
2017-03-05 15:44:50 +00:00
Vector3 ( 1 , 0 , 0 ) ,
Vector3 ( 0 , - 1 , 0 ) ,
Vector3 ( 0 , 1 , 0 ) ,
Vector3 ( 0 , 0 , - 1 ) ,
Vector3 ( 0 , 0 , 1 )
2015-09-20 16:03:46 +00:00
} ;
2017-12-06 20:36:34 +00:00
/* clang-format off */
2017-03-05 15:44:50 +00: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 16:03:46 +00:00
} ;
2017-12-06 20:36:34 +00:00
/* clang-format on */
2015-09-20 16:03:46 +00:00
2020-02-17 21:06:54 +00:00
Vector < int > indices ;
2020-05-14 14:41:43 +00:00
for ( int i = 0 ; i < 8 * 3 ; i + + ) {
2015-09-20 16:03:46 +00:00
indices . push_back ( diamond_faces [ i ] ) ;
2020-05-14 14:41:43 +00:00
}
2015-09-20 16:03:46 +00:00
2020-02-17 21:06:54 +00:00
Vector < Vector3 > vertices ;
2020-05-14 14:41:43 +00:00
for ( int i = 0 ; i < 6 ; i + + ) {
2017-03-05 15:44:50 +00:00
vertices . push_back ( diamond [ i ] * 0.1 ) ;
2020-05-14 14:41:43 +00:00
}
2015-09-20 16:03:46 +00:00
Array arr ;
arr . resize ( Mesh : : ARRAY_MAX ) ;
2017-03-05 15:44:50 +00:00
arr [ Mesh : : ARRAY_VERTEX ] = vertices ;
arr [ Mesh : : ARRAY_INDEX ] = indices ;
2015-09-20 16:03:46 +00:00
2017-03-05 15:44:50 +00:00
debug_contact_mesh - > add_surface_from_arrays ( Mesh : : PRIMITIVE_TRIANGLES , arr ) ;
debug_contact_mesh - > surface_set_material ( 0 , mat ) ;
2015-09-20 16:03:46 +00:00
return debug_contact_mesh ;
}
2014-11-06 00:20:42 +00:00
void SceneTree : : set_pause ( bool p_enabled ) {
2021-02-19 12:57:41 +00:00
if ( p_enabled = = paused ) {
2014-02-10 01:10:30 +00:00
return ;
2020-05-14 14:41:43 +00:00
}
2021-02-19 12:57:41 +00:00
paused = p_enabled ;
2020-03-27 18:21:27 +00:00
NavigationServer3D : : get_singleton ( ) - > set_active ( ! p_enabled ) ;
PhysicsServer3D : : get_singleton ( ) - > set_active ( ! p_enabled ) ;
PhysicsServer2D : : get_singleton ( ) - > set_active ( ! p_enabled ) ;
2020-05-14 14:41:43 +00:00
if ( get_root ( ) ) {
2021-02-18 18:52:29 +00:00
get_root ( ) - > _propagate_pause_notification ( p_enabled ) ;
2020-05-14 14:41:43 +00:00
}
2014-02-10 01:10:30 +00:00
}
2014-11-06 00:20:42 +00:00
bool SceneTree : : is_paused ( ) const {
2021-02-19 12:57:41 +00:00
return paused ;
2014-02-10 01:10:30 +00:00
}
2020-03-04 16:36:09 +00:00
void SceneTree : : _notify_group_pause ( const StringName & p_group , int p_notification ) {
2022-05-13 13:04:37 +00:00
HashMap < StringName , Group > : : Iterator E = group_map . find ( p_group ) ;
2020-05-14 14:41:43 +00:00
if ( ! E ) {
2014-02-10 01:10:30 +00:00
return ;
2020-05-14 14:41:43 +00:00
}
2022-05-13 13:04:37 +00:00
Group & g = E - > value ;
2020-12-15 12:04:21 +00:00
if ( g . nodes . is_empty ( ) ) {
2014-02-10 01:10:30 +00:00
return ;
2020-05-14 14:41:43 +00:00
}
2014-02-10 01:10:30 +00:00
2020-03-04 16:36:09 +00: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 01:10:30 +00: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 15:44:50 +00:00
Vector < Node * > nodes_copy = g . nodes ;
2014-02-10 01:10:30 +00:00
2022-09-29 09:53:28 +00:00
int gr_node_count = nodes_copy . size ( ) ;
Node * * gr_nodes = nodes_copy . ptrw ( ) ;
2014-02-10 01:10:30 +00:00
call_lock + + ;
2022-09-29 09:53:28 +00:00
for ( int i = 0 ; i < gr_node_count ; i + + ) {
Node * n = gr_nodes [ i ] ;
2022-11-27 12:42:24 +00:00
if ( call_lock & & call_skip . has ( n ) ) {
2014-02-10 01:10:30 +00:00
continue ;
2020-05-14 14:41:43 +00:00
}
2014-02-10 01:10:30 +00:00
2020-05-14 14:41:43 +00:00
if ( ! n - > can_process ( ) ) {
2014-02-10 01:10:30 +00:00
continue ;
2020-05-14 14:41:43 +00:00
}
if ( ! n - > can_process_notification ( p_notification ) ) {
2020-03-04 16:36:09 +00:00
continue ;
2020-05-14 14:41:43 +00:00
}
2014-02-10 01:10:30 +00:00
2020-03-04 16:36:09 +00:00
n - > notification ( p_notification ) ;
2022-09-29 09:53:28 +00:00
//ERR_FAIL_COND(gr_node_count != g.nodes.size());
2014-02-10 01:10:30 +00:00
}
call_lock - - ;
2020-05-14 14:41:43 +00:00
if ( call_lock = = 0 ) {
2014-02-10 01:10:30 +00:00
call_skip . clear ( ) ;
2020-05-14 14:41:43 +00:00
}
2014-02-10 01:10:30 +00:00
}
2021-08-22 15:37:22 +00:00
void SceneTree : : _call_input_pause ( const StringName & p_group , CallInputType p_call_type , const Ref < InputEvent > & p_input , Viewport * p_viewport ) {
2022-05-13 13:04:37 +00:00
HashMap < StringName , Group > : : Iterator E = group_map . find ( p_group ) ;
2020-05-14 14:41:43 +00:00
if ( ! E ) {
2014-02-10 01:10:30 +00:00
return ;
2020-05-14 14:41:43 +00:00
}
2022-05-13 13:04:37 +00:00
Group & g = E - > value ;
2020-12-15 12:04:21 +00:00
if ( g . nodes . is_empty ( ) ) {
2014-02-10 01:10:30 +00:00
return ;
2020-05-14 14:41:43 +00:00
}
2014-02-10 01:10:30 +00:00
2020-03-04 16:36:09 +00:00
_update_group_order ( g ) ;
2014-02-10 01:10:30 +00: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 15:44:50 +00:00
Vector < Node * > nodes_copy = g . nodes ;
2014-02-10 01:10:30 +00:00
2022-09-29 09:53:28 +00:00
int gr_node_count = nodes_copy . size ( ) ;
Node * * gr_nodes = nodes_copy . ptrw ( ) ;
2014-02-10 01:10:30 +00:00
call_lock + + ;
2022-10-27 02:37:55 +00:00
Vector < ObjectID > no_context_node_ids ; // Nodes may be deleted due to this shortcut input.
2022-09-24 14:32:53 +00:00
2022-09-29 09:53:28 +00:00
for ( int i = gr_node_count - 1 ; i > = 0 ; i - - ) {
2020-05-14 14:41:43 +00:00
if ( p_viewport - > is_input_handled ( ) ) {
2020-03-04 16:36:09 +00:00
break ;
2020-05-14 14:41:43 +00:00
}
2014-02-10 01:10:30 +00:00
2022-09-29 09:53:28 +00:00
Node * n = gr_nodes [ i ] ;
2022-11-27 12:42:24 +00:00
if ( call_lock & & call_skip . has ( n ) ) {
2014-02-10 01:10:30 +00:00
continue ;
2020-05-14 14:41:43 +00:00
}
2014-02-10 01:10:30 +00:00
2020-05-14 14:41:43 +00:00
if ( ! n - > can_process ( ) ) {
2014-02-10 01:10:30 +00:00
continue ;
2020-05-14 14:41:43 +00:00
}
2014-02-10 01:10:30 +00:00
2021-08-22 15:37:22 +00:00
switch ( p_call_type ) {
case CALL_INPUT_TYPE_INPUT :
n - > _call_input ( p_input ) ;
break ;
2022-09-24 14:32:53 +00:00
case CALL_INPUT_TYPE_SHORTCUT_INPUT : {
const Control * c = Object : : cast_to < Control > ( n ) ;
if ( c ) {
// If calling shortcut input on a control, ensure it respects the shortcut context.
// Shortcut context (based on focus) only makes sense for controls (UI), so don't need to worry about it for nodes
if ( c - > get_shortcut_context ( ) = = nullptr ) {
2022-10-27 02:37:55 +00:00
no_context_node_ids . append ( n - > get_instance_id ( ) ) ;
2022-09-24 14:32:53 +00:00
continue ;
}
if ( ! c - > is_focus_owner_in_shortcut_context ( ) ) {
continue ;
}
}
2022-01-11 13:59:52 +00:00
n - > _call_shortcut_input ( p_input ) ;
break ;
2022-09-24 14:32:53 +00:00
}
2021-08-22 15:37:22 +00:00
case CALL_INPUT_TYPE_UNHANDLED_INPUT :
n - > _call_unhandled_input ( p_input ) ;
break ;
case CALL_INPUT_TYPE_UNHANDLED_KEY_INPUT :
n - > _call_unhandled_key_input ( p_input ) ;
break ;
2020-08-03 11:39:04 +00:00
}
2014-02-10 01:10:30 +00:00
}
2022-10-27 02:37:55 +00:00
for ( const ObjectID & id : no_context_node_ids ) {
Node * n = Object : : cast_to < Node > ( ObjectDB : : get_instance ( id ) ) ;
if ( n ) {
n - > _call_shortcut_input ( p_input ) ;
}
2022-09-24 14:32:53 +00:00
}
2014-02-10 01:10:30 +00:00
call_lock - - ;
2020-05-14 14:41:43 +00:00
if ( call_lock = = 0 ) {
2014-02-10 01:10:30 +00:00
call_skip . clear ( ) ;
2020-05-14 14:41:43 +00:00
}
2014-02-10 01:10:30 +00:00
}
2020-05-14 12:29:06 +00:00
2022-02-22 11:15:43 +00:00
void SceneTree : : _call_group_flags ( const Variant * * p_args , int p_argcount , Callable : : CallError & r_error ) {
2020-02-19 19:27:19 +00:00
r_error . error = Callable : : CallError : : CALL_OK ;
2014-02-10 01:10:30 +00:00
2022-02-22 11:15:43 +00:00
ERR_FAIL_COND ( p_argcount < 3 ) ;
ERR_FAIL_COND ( ! p_args [ 0 ] - > is_num ( ) ) ;
ERR_FAIL_COND ( p_args [ 1 ] - > get_type ( ) ! = Variant : : STRING_NAME & & p_args [ 1 ] - > get_type ( ) ! = Variant : : STRING ) ;
ERR_FAIL_COND ( p_args [ 2 ] - > get_type ( ) ! = Variant : : STRING_NAME & & p_args [ 2 ] - > get_type ( ) ! = Variant : : STRING ) ;
2014-02-10 01:10:30 +00:00
int flags = * p_args [ 0 ] ;
StringName group = * p_args [ 1 ] ;
StringName method = * p_args [ 2 ] ;
2022-03-09 13:58:40 +00:00
call_group_flagsp ( flags , group , method , p_args + 3 , p_argcount - 3 ) ;
2014-02-10 01:10:30 +00:00
}
2022-02-22 11:15:43 +00:00
void SceneTree : : _call_group ( const Variant * * p_args , int p_argcount , Callable : : CallError & r_error ) {
2020-02-19 19:27:19 +00:00
r_error . error = Callable : : CallError : : CALL_OK ;
2017-01-14 13:03:53 +00:00
2022-02-22 11:15:43 +00:00
ERR_FAIL_COND ( p_argcount < 2 ) ;
ERR_FAIL_COND ( p_args [ 0 ] - > get_type ( ) ! = Variant : : STRING_NAME & & p_args [ 0 ] - > get_type ( ) ! = Variant : : STRING ) ;
ERR_FAIL_COND ( p_args [ 1 ] - > get_type ( ) ! = Variant : : STRING_NAME & & p_args [ 1 ] - > get_type ( ) ! = Variant : : STRING ) ;
2017-01-14 13:03:53 +00:00
StringName group = * p_args [ 0 ] ;
StringName method = * p_args [ 1 ] ;
2021-08-12 21:40:13 +00:00
call_group_flagsp ( GROUP_CALL_DEFAULT , group , method , p_args + 2 , p_argcount - 2 ) ;
2017-01-14 13:03:53 +00:00
}
2014-11-06 00:20:42 +00:00
int64_t SceneTree : : get_frame ( ) const {
2014-02-10 01:10:30 +00:00
return current_frame ;
}
2020-05-14 12:29:06 +00:00
2022-08-05 18:35:08 +00:00
TypedArray < Node > SceneTree : : _get_nodes_in_group ( const StringName & p_group ) {
TypedArray < Node > ret ;
2022-05-13 13:04:37 +00:00
HashMap < StringName , Group > : : Iterator E = group_map . find ( p_group ) ;
2020-05-14 14:41:43 +00:00
if ( ! E ) {
2014-02-10 01:10:30 +00:00
return ret ;
2020-05-14 14:41:43 +00:00
}
2014-02-10 01:10:30 +00:00
2022-05-13 13:04:37 +00:00
_update_group_order ( E - > value ) ; //update order just in case
int nc = E - > value . nodes . size ( ) ;
2020-05-14 14:41:43 +00:00
if ( nc = = 0 ) {
2014-02-10 01:10:30 +00:00
return ret ;
2020-05-14 14:41:43 +00:00
}
2014-02-10 01:10:30 +00:00
ret . resize ( nc ) ;
2022-05-13 13:04:37 +00:00
Node * * ptr = E - > value . nodes . ptrw ( ) ;
2017-03-05 15:44:50 +00:00
for ( int i = 0 ; i < nc ; i + + ) {
ret [ i ] = ptr [ i ] ;
2014-02-10 01:10:30 +00:00
}
return ret ;
}
2017-03-05 15:44:50 +00:00
bool SceneTree : : has_group ( const StringName & p_identifier ) const {
2016-01-02 20:18:45 +00:00
return group_map . has ( p_identifier ) ;
}
2020-05-14 12:29:06 +00:00
2021-02-22 13:54:12 +00:00
Node * SceneTree : : get_first_node_in_group ( const StringName & p_group ) {
2022-05-13 13:04:37 +00:00
HashMap < StringName , Group > : : Iterator E = group_map . find ( p_group ) ;
2021-02-22 13:54:12 +00:00
if ( ! E ) {
2022-04-29 14:14:48 +00:00
return nullptr ; // No group.
2021-02-22 13:54:12 +00:00
}
2022-05-13 13:04:37 +00:00
_update_group_order ( E - > value ) ; // Update order just in case.
2021-02-22 13:54:12 +00:00
2022-05-13 13:04:37 +00:00
if ( E - > value . nodes . is_empty ( ) ) {
2021-02-22 13:54:12 +00:00
return nullptr ;
}
2022-05-13 13:04:37 +00:00
return E - > value . nodes [ 0 ] ;
2021-02-22 13:54:12 +00:00
}
2017-03-05 15:44:50 +00:00
void SceneTree : : get_nodes_in_group ( const StringName & p_group , List < Node * > * p_list ) {
2022-05-13 13:04:37 +00:00
HashMap < StringName , Group > : : Iterator E = group_map . find ( p_group ) ;
2020-05-14 14:41:43 +00:00
if ( ! E ) {
2014-02-10 01:10:30 +00:00
return ;
2020-05-14 14:41:43 +00:00
}
2014-02-10 01:10:30 +00:00
2022-05-13 13:04:37 +00:00
_update_group_order ( E - > value ) ; //update order just in case
int nc = E - > value . nodes . size ( ) ;
2020-05-14 14:41:43 +00:00
if ( nc = = 0 ) {
2014-02-10 01:10:30 +00:00
return ;
2020-05-14 14:41:43 +00:00
}
2022-05-13 13:04:37 +00:00
Node * * ptr = E - > value . nodes . ptrw ( ) ;
2017-03-05 15:44:50 +00:00
for ( int i = 0 ; i < nc ; i + + ) {
2014-02-10 01:10:30 +00:00
p_list - > push_back ( ptr [ i ] ) ;
}
}
2014-11-06 00:20:42 +00:00
void SceneTree : : _flush_delete_queue ( ) {
2014-02-10 01:10:30 +00:00
_THREAD_SAFE_METHOD_
2017-03-05 15:44:50 +00:00
while ( delete_queue . size ( ) ) {
Object * obj = ObjectDB : : get_instance ( delete_queue . front ( ) - > get ( ) ) ;
2014-02-10 01:10:30 +00:00
if ( obj ) {
2017-03-05 15:44:50 +00:00
memdelete ( obj ) ;
2014-02-10 01:10:30 +00:00
}
delete_queue . pop_front ( ) ;
}
}
2014-11-06 00:20:42 +00:00
void SceneTree : : queue_delete ( Object * p_object ) {
2014-02-10 01:10:30 +00:00
_THREAD_SAFE_METHOD_
ERR_FAIL_NULL ( p_object ) ;
2015-03-28 17:34:28 +00:00
p_object - > _is_queued_for_deletion = true ;
2017-08-07 10:17:31 +00:00
delete_queue . push_back ( p_object - > get_instance_id ( ) ) ;
2014-02-10 01:10:30 +00:00
}
2014-11-06 00:20:42 +00:00
int SceneTree : : get_node_count ( ) const {
2014-02-10 01:10:30 +00:00
return node_count ;
}
2014-11-06 00:20:42 +00:00
void SceneTree : : set_edited_scene_root ( Node * p_node ) {
2018-04-29 17:49:26 +00:00
# ifdef TOOLS_ENABLED
2017-03-05 15:44:50 +00:00
edited_scene_root = p_node ;
2018-04-29 17:49:26 +00:00
# endif
2014-10-12 05:13:22 +00:00
}
2014-11-06 00:20:42 +00:00
Node * SceneTree : : get_edited_scene_root ( ) const {
2018-04-29 17:49:26 +00:00
# ifdef TOOLS_ENABLED
2014-10-12 05:13:22 +00:00
return edited_scene_root ;
2018-04-29 17:49:26 +00:00
# else
2020-04-01 23:20:12 +00:00
return nullptr ;
2014-10-12 05:13:22 +00:00
# endif
2018-04-29 17:49:26 +00:00
}
2014-10-12 05:13:22 +00:00
2017-03-05 15:44:50 +00:00
void SceneTree : : set_current_scene ( Node * p_scene ) {
ERR_FAIL_COND ( p_scene & & p_scene - > get_parent ( ) ! = root ) ;
current_scene = p_scene ;
2015-05-17 19:33:35 +00:00
}
2017-03-05 15:44:50 +00:00
Node * SceneTree : : get_current_scene ( ) const {
2015-05-17 19:33:35 +00:00
return current_scene ;
}
2017-03-05 15:44:50 +00:00
void SceneTree : : _change_scene ( Node * p_to ) {
2015-05-17 19:33:35 +00:00
if ( current_scene ) {
2017-03-05 15:44:50 +00:00
memdelete ( current_scene ) ;
2020-04-01 23:20:12 +00:00
current_scene = nullptr ;
2015-05-17 19:33:35 +00:00
}
2020-01-19 21:06:26 +00:00
// If we're quitting, abort.
if ( unlikely ( _quit ) ) {
if ( p_to ) { // Prevent memory leak.
memdelete ( p_to ) ;
}
return ;
}
2015-05-17 19:33:35 +00:00
if ( p_to ) {
2017-03-05 15:44:50 +00:00
current_scene = p_to ;
2015-05-17 19:33:35 +00:00
root - > add_child ( p_to ) ;
2022-03-10 17:44:28 +00:00
root - > update_mouse_cursor_shape ( ) ;
2015-05-17 19:33:35 +00:00
}
}
2022-07-28 21:25:57 +00:00
Error SceneTree : : change_scene_to_file ( const String & p_path ) {
2015-05-17 19:33:35 +00:00
Ref < PackedScene > new_scene = ResourceLoader : : load ( p_path ) ;
2020-05-14 14:41:43 +00:00
if ( new_scene . is_null ( ) ) {
2015-05-17 19:33:35 +00:00
return ERR_CANT_OPEN ;
2020-05-14 14:41:43 +00:00
}
2015-05-17 19:33:35 +00:00
2022-07-28 21:25:57 +00:00
return change_scene_to_packed ( new_scene ) ;
2015-05-17 19:33:35 +00:00
}
2022-07-28 21:25:57 +00:00
Error SceneTree : : change_scene_to_packed ( const Ref < PackedScene > & p_scene ) {
2020-04-01 23:20:12 +00:00
Node * new_scene = nullptr ;
2015-05-17 19:33:35 +00:00
if ( p_scene . is_valid ( ) ) {
2021-06-17 22:03:09 +00:00
new_scene = p_scene - > instantiate ( ) ;
2017-03-05 15:44:50 +00:00
ERR_FAIL_COND_V ( ! new_scene , ERR_CANT_CREATE ) ;
2015-05-17 19:33:35 +00:00
}
2021-07-17 21:22:52 +00:00
call_deferred ( SNAME ( " _change_scene " ) , new_scene ) ;
2015-05-17 19:33:35 +00:00
return OK ;
}
2020-01-19 21:06:26 +00:00
Error SceneTree : : reload_current_scene ( ) {
2017-03-05 15:44:50 +00:00
ERR_FAIL_COND_V ( ! current_scene , ERR_UNCONFIGURED ) ;
2021-09-30 14:30:55 +00:00
String fname = current_scene - > get_scene_file_path ( ) ;
2022-07-28 21:25:57 +00:00
return change_scene_to_file ( fname ) ;
2015-05-17 19:33:35 +00:00
}
2017-03-05 15:44:50 +00:00
void SceneTree : : add_current_scene ( Node * p_current ) {
current_scene = p_current ;
2015-05-17 19:33:35 +00:00
root - > add_child ( p_current ) ;
}
2020-01-19 21:06:26 +00:00
2022-07-15 06:21:51 +00:00
Ref < SceneTreeTimer > SceneTree : : create_timer ( double p_delay_sec , bool p_process_always , bool p_process_in_physics , bool p_ignore_time_scale ) {
2016-08-07 00:39:50 +00:00
Ref < SceneTreeTimer > stt ;
2021-06-17 22:03:09 +00:00
stt . instantiate ( ) ;
2021-02-19 12:57:41 +00:00
stt - > set_process_always ( p_process_always ) ;
2016-08-07 00:39:50 +00:00
stt - > set_time_left ( p_delay_sec ) ;
2022-07-15 06:21:51 +00:00
stt - > set_process_in_physics ( p_process_in_physics ) ;
stt - > set_ignore_time_scale ( p_ignore_time_scale ) ;
2016-08-07 00:39:50 +00:00
timers . push_back ( stt ) ;
return stt ;
}
2020-09-05 01:05:30 +00:00
Ref < Tween > SceneTree : : create_tween ( ) {
2022-04-17 21:13:39 +00:00
Ref < Tween > tween = memnew ( Tween ( true ) ) ;
2020-09-05 01:05:30 +00:00
tweens . push_back ( tween ) ;
return tween ;
}
2022-08-05 18:35:08 +00:00
TypedArray < Tween > SceneTree : : get_processed_tweens ( ) {
TypedArray < Tween > ret ;
2020-09-05 01:05:30 +00:00
ret . resize ( tweens . size ( ) ) ;
int i = 0 ;
2021-07-26 15:50:35 +00:00
for ( const Ref < Tween > & tween : tweens ) {
ret [ i ] = tween ;
2020-09-05 01:05:30 +00:00
i + + ;
}
return ret ;
}
2022-02-05 00:43:47 +00:00
Ref < MultiplayerAPI > SceneTree : : get_multiplayer ( const NodePath & p_for_path ) const {
Ref < MultiplayerAPI > out = multiplayer ;
2022-05-08 08:09:19 +00:00
for ( const KeyValue < NodePath , Ref < MultiplayerAPI > > & E : custom_multiplayers ) {
const Vector < StringName > snames = E . key . get_names ( ) ;
2022-02-05 00:43:47 +00:00
const Vector < StringName > tnames = p_for_path . get_names ( ) ;
if ( tnames . size ( ) < snames . size ( ) ) {
continue ;
}
const StringName * sptr = snames . ptr ( ) ;
const StringName * nptr = tnames . ptr ( ) ;
bool valid = true ;
for ( int i = 0 ; i < snames . size ( ) ; i + + ) {
if ( sptr [ i ] ! = nptr [ i ] ) {
valid = false ;
break ;
}
}
if ( valid ) {
2022-05-08 08:09:19 +00:00
out = E . value ;
2022-02-05 00:43:47 +00:00
break ;
}
}
return out ;
}
void SceneTree : : set_multiplayer ( Ref < MultiplayerAPI > p_multiplayer , const NodePath & p_root_path ) {
if ( p_root_path . is_empty ( ) ) {
ERR_FAIL_COND ( ! p_multiplayer . is_valid ( ) ) ;
if ( multiplayer . is_valid ( ) ) {
2022-07-12 21:12:42 +00:00
multiplayer - > object_configuration_remove ( nullptr , NodePath ( " / " + root - > get_name ( ) ) ) ;
2022-02-05 00:43:47 +00:00
}
multiplayer = p_multiplayer ;
2022-07-12 21:12:42 +00:00
multiplayer - > object_configuration_add ( nullptr , NodePath ( " / " + root - > get_name ( ) ) ) ;
2022-02-05 00:43:47 +00:00
} else {
2022-07-12 21:12:42 +00:00
if ( custom_multiplayers . has ( p_root_path ) ) {
custom_multiplayers [ p_root_path ] - > object_configuration_remove ( nullptr , p_root_path ) ;
}
2022-02-05 00:43:47 +00:00
if ( p_multiplayer . is_valid ( ) ) {
custom_multiplayers [ p_root_path ] = p_multiplayer ;
2022-07-12 21:12:42 +00:00
p_multiplayer - > object_configuration_add ( nullptr , p_root_path ) ;
2022-02-05 00:43:47 +00:00
}
}
2018-03-03 17:30:11 +00:00
}
2018-06-02 12:32:30 +00:00
void SceneTree : : set_multiplayer_poll_enabled ( bool p_enabled ) {
multiplayer_poll = p_enabled ;
}
bool SceneTree : : is_multiplayer_poll_enabled ( ) const {
return multiplayer_poll ;
}
2014-11-06 00:20:42 +00:00
void SceneTree : : _bind_methods ( ) {
2017-08-09 11:19:41 +00:00
ClassDB : : bind_method ( D_METHOD ( " get_root " ) , & SceneTree : : get_root ) ;
2017-03-05 15:44:50 +00:00
ClassDB : : bind_method ( D_METHOD ( " has_group " , " name " ) , & SceneTree : : has_group ) ;
2014-02-10 01:10:30 +00:00
2022-05-14 10:18:26 +00:00
ClassDB : : bind_method ( D_METHOD ( " is_auto_accept_quit " ) , & SceneTree : : is_auto_accept_quit ) ;
2017-03-05 15:44:50 +00:00
ClassDB : : bind_method ( D_METHOD ( " set_auto_accept_quit " , " enabled " ) , & SceneTree : : set_auto_accept_quit ) ;
2022-05-14 10:18:26 +00:00
ClassDB : : bind_method ( D_METHOD ( " is_quit_on_go_back " ) , & SceneTree : : is_quit_on_go_back ) ;
2017-12-30 12:15:17 +00:00
ClassDB : : bind_method ( D_METHOD ( " set_quit_on_go_back " , " enabled " ) , & SceneTree : : set_quit_on_go_back ) ;
2014-02-10 01:10:30 +00:00
2017-03-05 15:44:50 +00: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 ) ;
2022-06-15 21:24:06 +00:00
ClassDB : : bind_method ( D_METHOD ( " set_debug_paths_hint " , " enable " ) , & SceneTree : : set_debug_paths_hint ) ;
ClassDB : : bind_method ( D_METHOD ( " is_debugging_paths_hint " ) , & SceneTree : : is_debugging_paths_hint ) ;
2017-03-05 15:44:50 +00:00
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 16:03:46 +00:00
2017-08-09 11:19:41 +00: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 01:10:30 +00:00
2017-03-05 15:44:50 +00: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 01:10:30 +00:00
2022-07-15 06:21:51 +00:00
ClassDB : : bind_method ( D_METHOD ( " create_timer " , " time_sec " , " process_always " , " process_in_physics " , " ignore_time_scale " ) , & SceneTree : : create_timer , DEFVAL ( true ) , DEFVAL ( false ) , DEFVAL ( false ) ) ;
2020-09-05 01:05:30 +00:00
ClassDB : : bind_method ( D_METHOD ( " create_tween " ) , & SceneTree : : create_tween ) ;
ClassDB : : bind_method ( D_METHOD ( " get_processed_tweens " ) , & SceneTree : : get_processed_tweens ) ;
2014-02-10 01:10:30 +00:00
2017-03-05 15:44:50 +00:00
ClassDB : : bind_method ( D_METHOD ( " get_node_count " ) , & SceneTree : : get_node_count ) ;
ClassDB : : bind_method ( D_METHOD ( " get_frame " ) , & SceneTree : : get_frame ) ;
2020-06-04 20:03:45 +00:00
ClassDB : : bind_method ( D_METHOD ( " quit " , " exit_code " ) , & SceneTree : : quit , DEFVAL ( EXIT_SUCCESS ) ) ;
2014-02-10 01:10:30 +00:00
2017-03-05 15:44:50 +00:00
ClassDB : : bind_method ( D_METHOD ( " queue_delete " , " obj " ) , & SceneTree : : queue_delete ) ;
2015-05-17 19:33:35 +00:00
2014-02-10 01:10:30 +00:00
MethodInfo mi ;
2017-03-05 15:44:50 +00:00
mi . name = " call_group_flags " ;
mi . arguments . push_back ( PropertyInfo ( Variant : : INT , " flags " ) ) ;
2020-02-20 21:58:05 +00:00
mi . arguments . push_back ( PropertyInfo ( Variant : : STRING_NAME , " group " ) ) ;
mi . arguments . push_back ( PropertyInfo ( Variant : : STRING_NAME , " method " ) ) ;
2016-09-07 22:39:02 +00:00
2017-03-05 15:44:50 +00:00
ClassDB : : bind_vararg_method ( METHOD_FLAGS_DEFAULT , " call_group_flags " , & SceneTree : : _call_group_flags , mi ) ;
2017-01-14 13:03:53 +00:00
2017-03-05 15:44:50 +00: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 13:03:53 +00:00
MethodInfo mi2 ;
2017-03-05 15:44:50 +00:00
mi2 . name = " call_group " ;
2020-02-20 21:58:05 +00:00
mi2 . arguments . push_back ( PropertyInfo ( Variant : : STRING_NAME , " group " ) ) ;
mi2 . arguments . push_back ( PropertyInfo ( Variant : : STRING_NAME , " method " ) ) ;
2017-01-14 13:03:53 +00:00
2017-03-05 15:44:50 +00:00
ClassDB : : bind_vararg_method ( METHOD_FLAGS_DEFAULT , " call_group " , & SceneTree : : _call_group , mi2 ) ;
2014-02-10 01:10:30 +00:00
2017-08-09 11:54:55 +00: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 19:33:35 +00:00
2017-03-05 15:44:50 +00:00
ClassDB : : bind_method ( D_METHOD ( " get_nodes_in_group " , " group " ) , & SceneTree : : _get_nodes_in_group ) ;
2021-02-22 13:54:12 +00:00
ClassDB : : bind_method ( D_METHOD ( " get_first_node_in_group " , " group " ) , & SceneTree : : get_first_node_in_group ) ;
2015-05-17 19:33:35 +00:00
2017-08-09 11:19:41 +00: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 19:33:35 +00:00
2022-07-28 21:25:57 +00:00
ClassDB : : bind_method ( D_METHOD ( " change_scene_to_file " , " path " ) , & SceneTree : : change_scene_to_file ) ;
ClassDB : : bind_method ( D_METHOD ( " change_scene_to_packed " , " packed_scene " ) , & SceneTree : : change_scene_to_packed ) ;
2015-05-17 19:33:35 +00:00
2017-03-05 15:44:50 +00:00
ClassDB : : bind_method ( D_METHOD ( " reload_current_scene " ) , & SceneTree : : reload_current_scene ) ;
2016-08-14 21:49:50 +00:00
2017-03-05 15:44:50 +00:00
ClassDB : : bind_method ( D_METHOD ( " _change_scene " ) , & SceneTree : : _change_scene ) ;
2016-08-14 21:49:50 +00:00
2022-02-05 00:43:47 +00:00
ClassDB : : bind_method ( D_METHOD ( " set_multiplayer " , " multiplayer " , " root_path " ) , & SceneTree : : set_multiplayer , DEFVAL ( NodePath ( ) ) ) ;
ClassDB : : bind_method ( D_METHOD ( " get_multiplayer " , " for_path " ) , & SceneTree : : get_multiplayer , DEFVAL ( NodePath ( ) ) ) ;
2018-06-02 12:32:30 +00: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 ) ;
2014-02-10 01:10:30 +00:00
2022-05-14 10:18:26 +00:00
ADD_PROPERTY ( PropertyInfo ( Variant : : BOOL , " auto_accept_quit " ) , " set_auto_accept_quit " , " is_auto_accept_quit " ) ;
ADD_PROPERTY ( PropertyInfo ( Variant : : BOOL , " quit_on_go_back " ) , " set_quit_on_go_back " , " is_quit_on_go_back " ) ;
2018-01-11 22:35:12 +00:00
ADD_PROPERTY ( PropertyInfo ( Variant : : BOOL , " debug_collisions_hint " ) , " set_debug_collisions_hint " , " is_debugging_collisions_hint " ) ;
2022-06-15 21:24:06 +00:00
ADD_PROPERTY ( PropertyInfo ( Variant : : BOOL , " debug_paths_hint " ) , " set_debug_paths_hint " , " is_debugging_paths_hint " ) ;
2018-01-11 22:35:12 +00:00
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 " ) ;
2021-06-17 23:10:18 +00:00
ADD_PROPERTY ( PropertyInfo ( Variant : : OBJECT , " edited_scene_root " , PROPERTY_HINT_RESOURCE_TYPE , " Node " , PROPERTY_USAGE_NONE ) , " set_edited_scene_root " , " get_edited_scene_root " ) ;
ADD_PROPERTY ( PropertyInfo ( Variant : : OBJECT , " current_scene " , PROPERTY_HINT_RESOURCE_TYPE , " Node " , PROPERTY_USAGE_NONE ) , " set_current_scene " , " get_current_scene " ) ;
ADD_PROPERTY ( PropertyInfo ( Variant : : OBJECT , " root " , PROPERTY_HINT_RESOURCE_TYPE , " Node " , PROPERTY_USAGE_NONE ) , " " , " get_root " ) ;
2018-06-02 12:32:30 +00:00
ADD_PROPERTY ( PropertyInfo ( Variant : : BOOL , " multiplayer_poll " ) , " set_multiplayer_poll_enabled " , " is_multiplayer_poll_enabled " ) ;
2018-01-11 22:35:12 +00:00
2017-03-05 15:44:50 +00:00
ADD_SIGNAL ( MethodInfo ( " tree_changed " ) ) ;
2021-05-20 10:07:26 +00:00
ADD_SIGNAL ( MethodInfo ( " tree_process_mode_changed " ) ) ; //editor only signal, but due to API hash it can't be removed in run-time
2018-09-01 10:05:51 +00: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 13:27:22 +00:00
ADD_SIGNAL ( MethodInfo ( " node_renamed " , PropertyInfo ( Variant : : OBJECT , " node " , PROPERTY_HINT_RESOURCE_TYPE , " Node " ) ) ) ;
2018-09-01 10:05:51 +00:00
ADD_SIGNAL ( MethodInfo ( " node_configuration_warning_changed " , PropertyInfo ( Variant : : OBJECT , " node " , PROPERTY_HINT_RESOURCE_TYPE , " Node " ) ) ) ;
2015-06-12 16:53:18 +00:00
2020-12-22 09:50:29 +00:00
ADD_SIGNAL ( MethodInfo ( " process_frame " ) ) ;
2017-09-30 14:19:07 +00:00
ADD_SIGNAL ( MethodInfo ( " physics_frame " ) ) ;
2016-05-27 17:18:40 +00:00
2017-08-20 15:45:01 +00:00
BIND_ENUM_CONSTANT ( GROUP_CALL_DEFAULT ) ;
BIND_ENUM_CONSTANT ( GROUP_CALL_REVERSE ) ;
2021-08-12 21:40:13 +00:00
BIND_ENUM_CONSTANT ( GROUP_CALL_DEFERRED ) ;
2017-08-20 15:45:01 +00:00
BIND_ENUM_CONSTANT ( GROUP_CALL_UNIQUE ) ;
2014-02-10 01:10:30 +00:00
}
2020-04-01 23:20:12 +00:00
SceneTree * SceneTree : : singleton = nullptr ;
2016-10-27 14:50:26 +00:00
SceneTree : : IdleCallback SceneTree : : idle_callbacks [ SceneTree : : MAX_IDLE_CALLBACKS ] ;
2017-03-05 15:44:50 +00:00
int SceneTree : : idle_callback_count = 0 ;
2016-10-27 14:50:26 +00:00
void SceneTree : : _call_idle_callbacks ( ) {
2017-03-05 15:44:50 +00:00
for ( int i = 0 ; i < idle_callback_count ; i + + ) {
2016-10-27 14:50:26 +00:00
idle_callbacks [ i ] ( ) ;
}
}
void SceneTree : : add_idle_callback ( IdleCallback p_callback ) {
2017-03-05 15:44:50 +00:00
ERR_FAIL_COND ( idle_callback_count > = MAX_IDLE_CALLBACKS ) ;
idle_callbacks [ idle_callback_count + + ] = p_callback ;
2016-10-27 14:50:26 +00:00
}
2019-03-09 02:05:59 +00:00
void SceneTree : : get_argument_options ( const StringName & p_function , int p_idx , List < String > * r_options ) const {
2022-07-28 21:25:57 +00:00
if ( p_function = = " change_scene_to_file " ) {
2022-03-23 09:08:58 +00:00
Ref < DirAccess > dir_access = DirAccess : : create ( DirAccess : : ACCESS_RESOURCES ) ;
2019-03-09 02:05:59 +00:00
List < String > directories ;
directories . push_back ( dir_access - > get_current_dir ( ) ) ;
2020-12-15 12:04:21 +00:00
while ( ! directories . is_empty ( ) ) {
2019-03-09 02:05:59 +00:00
dir_access - > change_dir ( directories . back ( ) - > get ( ) ) ;
directories . pop_back ( ) ;
dir_access - > list_dir_begin ( ) ;
String filename = dir_access - > get_next ( ) ;
2021-12-09 09:42:46 +00:00
while ( ! filename . is_empty ( ) ) {
2019-03-09 02:05:59 +00:00
if ( filename = = " . " | | filename = = " .. " ) {
filename = dir_access - > get_next ( ) ;
continue ;
}
if ( dir_access - > dir_exists ( filename ) ) {
2022-08-30 00:34:01 +00:00
directories . push_back ( dir_access - > get_current_dir ( ) . path_join ( filename ) ) ;
2019-03-09 02:05:59 +00:00
} else if ( filename . ends_with ( " .tscn " ) | | filename . ends_with ( " .scn " ) ) {
2022-08-30 00:34:01 +00:00
r_options - > push_back ( " \" " + dir_access - > get_current_dir ( ) . path_join ( filename ) + " \" " ) ;
2019-03-09 02:05:59 +00:00
}
filename = dir_access - > get_next ( ) ;
}
}
}
}
2014-11-06 00:20:42 +00:00
SceneTree : : SceneTree ( ) {
2020-05-14 14:41:43 +00:00
if ( singleton = = nullptr ) {
2020-05-10 10:56:01 +00:00
singleton = this ;
2020-05-14 14:41:43 +00:00
}
2021-01-20 14:42:11 +00:00
debug_collisions_color = GLOBAL_DEF ( " debug/shapes/collision/shape_color " , Color ( 0.0 , 0.6 , 0.7 , 0.42 ) ) ;
2017-07-18 00:05:38 +00:00
debug_collision_contact_color = GLOBAL_DEF ( " debug/shapes/collision/contact_color " , Color ( 1.0 , 0.2 , 0.1 , 0.8 ) ) ;
2022-06-15 21:24:06 +00:00
debug_paths_color = GLOBAL_DEF ( " debug/shapes/paths/geometry_color " , Color ( 0.1 , 1.0 , 0.7 , 0.4 ) ) ;
debug_paths_width = GLOBAL_DEF ( " debug/shapes/paths/geometry_width " , 2.0 ) ;
2017-07-18 00:05:38 +00:00
collision_debug_contacts = GLOBAL_DEF ( " debug/shapes/collision/max_contacts_displayed " , 10000 ) ;
2018-10-05 16:43:53 +00: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 15:44:50 +00:00
2021-02-25 13:56:47 +00:00
GLOBAL_DEF ( " debug/shapes/collision/draw_2d_outlines " , true ) ;
2020-11-05 10:04:25 +00:00
Math : : randomize ( ) ;
2020-12-11 14:54:03 +00:00
// Create with mainloop.
2014-02-10 01:10:30 +00:00
2020-03-04 01:51:12 +00:00
root = memnew ( Window ) ;
2021-06-22 00:49:34 +00:00
root - > set_process_mode ( Node : : PROCESS_MODE_PAUSABLE ) ;
2014-02-10 01:10:30 +00:00
root - > set_name ( " root " ) ;
2022-10-18 14:43:37 +00:00
root - > set_title ( GLOBAL_GET ( " application/config/name " ) ) ;
2022-01-21 09:08:07 +00:00
2021-07-04 01:43:23 +00:00
# ifndef _3D_DISABLED
2020-05-14 14:41:43 +00:00
if ( ! root - > get_world_3d ( ) . is_valid ( ) ) {
2020-04-18 09:00:51 +00:00
root - > set_world_3d ( Ref < World3D > ( memnew ( World3D ) ) ) ;
2020-05-14 14:41:43 +00:00
}
2021-07-04 01:43:23 +00:00
root - > set_as_audio_listener_3d ( true ) ;
# endif // _3D_DISABLED
2017-05-29 00:46:48 +00:00
2020-12-11 14:54:03 +00:00
// Initialize network state.
2022-07-12 21:12:42 +00:00
set_multiplayer ( MultiplayerAPI : : create_default_interface ( ) ) ;
2018-03-03 17:30:11 +00:00
2014-02-10 01:10:30 +00:00
root - > set_as_audio_listener_2d ( true ) ;
2020-04-01 23:20:12 +00:00
current_scene = nullptr ;
2014-02-10 01:10:30 +00:00
2022-08-12 23:02:32 +00:00
const int msaa_mode_2d = GLOBAL_DEF_BASIC ( " rendering/anti_aliasing/quality/msaa_2d " , 0 ) ;
ProjectSettings : : get_singleton ( ) - > set_custom_property_info ( " rendering/anti_aliasing/quality/msaa_2d " , PropertyInfo ( Variant : : INT , " rendering/anti_aliasing/quality/msaa_2d " , PROPERTY_HINT_ENUM , String : : utf8 ( " Disabled (Fastest),2× (Average),4× (Slow),8× (Slowest) " ) ) ) ;
root - > set_msaa_2d ( Viewport : : MSAA ( msaa_mode_2d ) ) ;
const int msaa_mode_3d = GLOBAL_DEF_BASIC ( " rendering/anti_aliasing/quality/msaa_3d " , 0 ) ;
ProjectSettings : : get_singleton ( ) - > set_custom_property_info ( " rendering/anti_aliasing/quality/msaa_3d " , PropertyInfo ( Variant : : INT , " rendering/anti_aliasing/quality/msaa_3d " , PROPERTY_HINT_ENUM , String : : utf8 ( " Disabled (Fastest),2× (Average),4× (Slow),8× (Slowest) " ) ) ) ;
root - > set_msaa_3d ( Viewport : : MSAA ( msaa_mode_3d ) ) ;
2017-07-19 20:00:46 +00:00
2022-10-08 22:05:56 +00:00
const bool transparent_background = GLOBAL_DEF ( " rendering/transparent_background " , false ) ;
root - > set_transparent_background ( transparent_background ) ;
2022-06-12 17:50:14 +00:00
const int ssaa_mode = GLOBAL_DEF_BASIC ( " rendering/anti_aliasing/quality/screen_space_aa " , 0 ) ;
2021-02-17 16:44:49 +00:00
ProjectSettings : : get_singleton ( ) - > set_custom_property_info ( " rendering/anti_aliasing/quality/screen_space_aa " , PropertyInfo ( Variant : : INT , " rendering/anti_aliasing/quality/screen_space_aa " , PROPERTY_HINT_ENUM , " Disabled (Fastest),FXAA (Fast) " ) ) ;
2020-04-12 04:49:10 +00:00
root - > set_screen_space_aa ( Viewport : : ScreenSpaceAA ( ssaa_mode ) ) ;
2022-06-12 17:50:14 +00:00
const bool use_taa = GLOBAL_DEF_BASIC ( " rendering/anti_aliasing/quality/use_taa " , false ) ;
2022-04-04 14:10:22 +00:00
root - > set_use_taa ( use_taa ) ;
2021-02-17 16:44:49 +00:00
const bool use_debanding = GLOBAL_DEF ( " rendering/anti_aliasing/quality/use_debanding " , false ) ;
2020-04-20 21:34:47 +00:00
root - > set_use_debanding ( use_debanding ) ;
2021-04-20 16:40:24 +00:00
const bool use_occlusion_culling = GLOBAL_DEF ( " rendering/occlusion_culling/use_occlusion_culling " , false ) ;
root - > set_use_occlusion_culling ( use_occlusion_culling ) ;
2021-12-28 23:10:41 +00:00
float mesh_lod_threshold = GLOBAL_DEF ( " rendering/mesh_lod/lod_change/threshold_pixels " , 1.0 ) ;
2021-02-17 16:44:49 +00:00
ProjectSettings : : get_singleton ( ) - > set_custom_property_info ( " rendering/mesh_lod/lod_change/threshold_pixels " , PropertyInfo ( Variant : : FLOAT , " rendering/mesh_lod/lod_change/threshold_pixels " , PROPERTY_HINT_RANGE , " 0,1024,0.1 " ) ) ;
2021-12-28 23:10:41 +00:00
root - > set_mesh_lod_threshold ( mesh_lod_threshold ) ;
2020-12-17 18:56:59 +00:00
2021-02-17 16:44:49 +00:00
bool snap_2d_transforms = GLOBAL_DEF ( " rendering/2d/snap/snap_2d_transforms_to_pixel " , false ) ;
2020-10-29 21:09:16 +00:00
root - > set_snap_2d_transforms_to_pixel ( snap_2d_transforms ) ;
2021-02-17 16:44:49 +00:00
bool snap_2d_vertices = GLOBAL_DEF ( " rendering/2d/snap/snap_2d_vertices_to_pixel " , false ) ;
2020-10-29 21:09:16 +00:00
root - > set_snap_2d_vertices_to_pixel ( snap_2d_vertices ) ;
2022-02-11 11:33:54 +00:00
// We setup VRS for the main viewport here, in the editor this will have little effect.
const int vrs_mode = GLOBAL_DEF ( " rendering/vrs/mode " , 0 ) ;
ProjectSettings : : get_singleton ( ) - > set_custom_property_info ( " rendering/vrs/mode " , PropertyInfo ( Variant : : INT , " rendering/vrs/mode " , PROPERTY_HINT_ENUM , String : : utf8 ( " Disabled,Texture,XR " ) ) ) ;
root - > set_vrs_mode ( Viewport : : VRSMode ( vrs_mode ) ) ;
const String vrs_texture_path = String ( GLOBAL_DEF ( " rendering/vrs/texture " , String ( ) ) ) . strip_edges ( ) ;
ProjectSettings : : get_singleton ( ) - > set_custom_property_info ( " rendering/vrs/texture " ,
PropertyInfo ( Variant : : STRING ,
" rendering/vrs/texture " ,
2022-11-18 15:29:08 +00:00
PROPERTY_HINT_FILE , " *.bmp,*.png,*.tga,*.webp " ) ) ;
2022-02-11 11:33:54 +00:00
if ( vrs_mode = = 1 & & ! vrs_texture_path . is_empty ( ) ) {
Ref < Image > vrs_image ;
vrs_image . instantiate ( ) ;
Error load_err = ImageLoader : : load_image ( vrs_texture_path , vrs_image ) ;
if ( load_err ) {
ERR_PRINT ( " Non-existing or invalid VRS texture at ' " + vrs_texture_path + " '. " ) ;
} else {
Ref < ImageTexture > vrs_texture ;
vrs_texture . instantiate ( ) ;
vrs_texture - > create_from_image ( vrs_image ) ;
root - > set_vrs_texture ( vrs_texture ) ;
}
}
2022-07-31 23:20:24 +00:00
int shadowmap_size = GLOBAL_DEF ( " rendering/lights_and_shadows/positional_shadow/atlas_size " , 4096 ) ;
ProjectSettings : : get_singleton ( ) - > set_custom_property_info ( " rendering/lights_and_shadows/positional_shadow/atlas_size " , PropertyInfo ( Variant : : INT , " rendering/lights_and_shadows/positional_shadow/atlas_size " , PROPERTY_HINT_RANGE , " 256,16384 " ) ) ;
GLOBAL_DEF ( " rendering/lights_and_shadows/positional_shadow/atlas_size.mobile " , 2048 ) ;
bool shadowmap_16_bits = GLOBAL_DEF ( " rendering/lights_and_shadows/positional_shadow/atlas_16_bits " , true ) ;
int atlas_q0 = GLOBAL_DEF ( " rendering/lights_and_shadows/positional_shadow/atlas_quadrant_0_subdiv " , 2 ) ;
int atlas_q1 = GLOBAL_DEF ( " rendering/lights_and_shadows/positional_shadow/atlas_quadrant_1_subdiv " , 2 ) ;
int atlas_q2 = GLOBAL_DEF ( " rendering/lights_and_shadows/positional_shadow/atlas_quadrant_2_subdiv " , 3 ) ;
int atlas_q3 = GLOBAL_DEF ( " rendering/lights_and_shadows/positional_shadow/atlas_quadrant_3_subdiv " , 4 ) ;
ProjectSettings : : get_singleton ( ) - > set_custom_property_info ( " rendering/lights_and_shadows/positional_shadow/atlas_quadrant_0_subdiv " , PropertyInfo ( Variant : : INT , " rendering/lights_and_shadows/positional_shadow/atlas_quadrant_0_subdiv " , PROPERTY_HINT_ENUM , " Disabled,1 Shadow,4 Shadows,16 Shadows,64 Shadows,256 Shadows,1024 Shadows " ) ) ;
ProjectSettings : : get_singleton ( ) - > set_custom_property_info ( " rendering/lights_and_shadows/positional_shadow/atlas_quadrant_1_subdiv " , PropertyInfo ( Variant : : INT , " rendering/lights_and_shadows/positional_shadow/atlas_quadrant_1_subdiv " , PROPERTY_HINT_ENUM , " Disabled,1 Shadow,4 Shadows,16 Shadows,64 Shadows,256 Shadows,1024 Shadows " ) ) ;
ProjectSettings : : get_singleton ( ) - > set_custom_property_info ( " rendering/lights_and_shadows/positional_shadow/atlas_quadrant_2_subdiv " , PropertyInfo ( Variant : : INT , " rendering/lights_and_shadows/positional_shadow/atlas_quadrant_2_subdiv " , PROPERTY_HINT_ENUM , " Disabled,1 Shadow,4 Shadows,16 Shadows,64 Shadows,256 Shadows,1024 Shadows " ) ) ;
ProjectSettings : : get_singleton ( ) - > set_custom_property_info ( " rendering/lights_and_shadows/positional_shadow/atlas_quadrant_3_subdiv " , PropertyInfo ( Variant : : INT , " rendering/lights_and_shadows/positional_shadow/atlas_quadrant_3_subdiv " , PROPERTY_HINT_ENUM , " Disabled,1 Shadow,4 Shadows,16 Shadows,64 Shadows,256 Shadows,1024 Shadows " ) ) ;
2022-04-30 23:40:30 +00:00
root - > set_positional_shadow_atlas_size ( shadowmap_size ) ;
root - > set_positional_shadow_atlas_16_bits ( shadowmap_16_bits ) ;
root - > set_positional_shadow_atlas_quadrant_subdiv ( 0 , Viewport : : PositionalShadowAtlasQuadrantSubdiv ( atlas_q0 ) ) ;
root - > set_positional_shadow_atlas_quadrant_subdiv ( 1 , Viewport : : PositionalShadowAtlasQuadrantSubdiv ( atlas_q1 ) ) ;
root - > set_positional_shadow_atlas_quadrant_subdiv ( 2 , Viewport : : PositionalShadowAtlasQuadrantSubdiv ( atlas_q2 ) ) ;
root - > set_positional_shadow_atlas_quadrant_subdiv ( 3 , Viewport : : PositionalShadowAtlasQuadrantSubdiv ( atlas_q3 ) ) ;
2021-01-24 19:00:20 +00:00
2021-02-17 16:44:49 +00:00
Viewport : : SDFOversize sdf_oversize = Viewport : : SDFOversize ( int ( GLOBAL_DEF ( " rendering/2d/sdf/oversize " , 1 ) ) ) ;
2020-11-26 12:50:21 +00:00
root - > set_sdf_oversize ( sdf_oversize ) ;
2021-02-17 16:44:49 +00:00
Viewport : : SDFScale sdf_scale = Viewport : : SDFScale ( int ( GLOBAL_DEF ( " rendering/2d/sdf/scale " , 1 ) ) ) ;
2020-11-26 12:50:21 +00:00
root - > set_sdf_scale ( sdf_scale ) ;
2021-02-17 16:44:49 +00:00
ProjectSettings : : get_singleton ( ) - > set_custom_property_info ( " rendering/2d/sdf/oversize " , PropertyInfo ( Variant : : INT , " rendering/2d/sdf/oversize " , PROPERTY_HINT_ENUM , " 100%,120%,150%,200% " ) ) ;
ProjectSettings : : get_singleton ( ) - > set_custom_property_info ( " rendering/2d/sdf/scale " , PropertyInfo ( Variant : : INT , " rendering/2d/sdf/scale " , PROPERTY_HINT_ENUM , " 100%,50%,25% " ) ) ;
2020-11-26 12:50:21 +00:00
2021-07-04 01:43:23 +00:00
# ifndef _3D_DISABLED
2020-12-11 14:54:03 +00:00
{ // Load default fallback environment.
// Get possible extensions.
2017-05-29 00:46:48 +00:00
List < String > exts ;
ResourceLoader : : get_recognized_extensions_for_type ( " Environment " , & exts ) ;
String ext_hint ;
2021-07-24 13:46:25 +00:00
for ( const String & E : exts ) {
2021-12-09 09:42:46 +00:00
if ( ! ext_hint . is_empty ( ) ) {
2017-05-29 00:46:48 +00:00
ext_hint + = " , " ;
2020-05-14 14:41:43 +00:00
}
2021-07-16 03:45:57 +00:00
ext_hint + = " *. " + E ;
2017-05-29 00:46:48 +00:00
}
2020-12-11 14:54:03 +00:00
// Get path.
2021-02-17 16:44:49 +00:00
String env_path = GLOBAL_DEF ( " rendering/environment/defaults/default_environment " , " " ) ;
2020-12-11 14:54:03 +00:00
// Setup property.
2021-02-17 16:44:49 +00:00
ProjectSettings : : get_singleton ( ) - > set_custom_property_info ( " rendering/environment/defaults/default_environment " , PropertyInfo ( Variant : : STRING , " rendering/viewport/default_environment " , PROPERTY_HINT_FILE , ext_hint ) ) ;
2017-05-29 00:46:48 +00:00
env_path = env_path . strip_edges ( ) ;
2021-12-09 09:42:46 +00:00
if ( ! env_path . is_empty ( ) ) {
2017-05-29 00:46:48 +00:00
Ref < Environment > env = ResourceLoader : : load ( env_path ) ;
if ( env . is_valid ( ) ) {
2020-04-18 09:00:51 +00:00
root - > get_world_3d ( ) - > set_fallback_environment ( env ) ;
2017-05-29 00:46:48 +00:00
} else {
2017-08-18 23:02:56 +00:00
if ( Engine : : get_singleton ( ) - > is_editor_hint ( ) ) {
2020-12-11 14:54:03 +00:00
// File was erased, clear the field.
2021-02-17 16:44:49 +00:00
ProjectSettings : : get_singleton ( ) - > set ( " rendering/environment/defaults/default_environment " , " " ) ;
2017-05-29 00:46:48 +00:00
} else {
2020-12-11 14:54:03 +00:00
// File was erased, notify user.
2019-11-06 16:03:04 +00:00
ERR_PRINT ( RTR ( " Default Environment as specified in Project Settings (Rendering -> Environment -> Default Environment) could not be loaded. " ) ) ;
2017-05-29 00:46:48 +00:00
}
}
}
}
2021-07-04 01:43:23 +00:00
# endif // _3D_DISABLED
2017-05-29 00:46:48 +00:00
2017-03-05 15:44:50 +00:00
root - > set_physics_object_picking ( GLOBAL_DEF ( " physics/common/enable_object_picking " , true ) ) ;
2014-09-15 14:33:30 +00:00
2020-03-04 16:36:09 +00: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 04:01:25 +00:00
# ifdef TOOLS_ENABLED
2020-04-01 23:20:12 +00:00
edited_scene_root = nullptr ;
2014-10-14 04:01:25 +00:00
# endif
2014-02-10 01:10:30 +00:00
}
2014-11-06 00:20:42 +00:00
SceneTree : : ~ SceneTree ( ) {
2019-06-01 13:42:22 +00:00
if ( root ) {
2020-04-01 23:20:12 +00:00
root - > _set_tree ( nullptr ) ;
2019-06-01 13:42:22 +00:00
root - > _propagate_after_exit_tree ( ) ;
memdelete ( root ) ;
}
2020-05-14 14:41:43 +00:00
if ( singleton = = this ) {
2020-05-10 10:56:01 +00:00
singleton = nullptr ;
2020-05-14 14:41:43 +00:00
}
2014-02-10 01:10:30 +00:00
}