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
/*************************************************************************/
2022-01-03 21:27:34 +01:00
/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
/* Copyright (c) 2014-2022 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-11-07 23:33:38 +01:00
# include "core/config/project_settings.h"
2020-02-27 03:30:20 +01:00
# include "core/debugger/engine_debugger.h"
2020-04-28 15:19:37 +02:00
# include "core/input/input.h"
2021-06-11 14:51:48 +02:00
# include "core/io/dir_access.h"
2022-02-11 12:33:54 +01:00
# include "core/io/image_loader.h"
2018-09-11 18:13:45 +02:00
# include "core/io/marshalls.h"
# include "core/io/resource_loader.h"
2020-11-07 23:33:38 +01:00
# include "core/object/message_queue.h"
2018-09-11 18:13:45 +02:00
# include "core/os/keyboard.h"
# include "core/os/os.h"
2020-11-07 23:33:38 +01:00
# include "core/string/print_string.h"
2014-02-10 02:10:30 +01:00
# include "node.h"
2020-09-05 03:05:30 +02:00
# include "scene/animation/tween.h"
2020-02-07 02:52:05 +01:00
# include "scene/debugger/scene_debugger.h"
2022-07-12 23:12:42 +02:00
# include "scene/main/multiplayer_api.h"
2022-02-12 02:46:22 +01:00
# include "scene/main/viewport.h"
2022-08-01 01:20:24 +02:00
# include "scene/resources/environment.h"
2020-09-03 13:22:16 +02:00
# include "scene/resources/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"
2022-02-12 02:46:22 +01:00
# include "scene/resources/world_2d.h"
# include "scene/resources/world_3d.h"
2017-03-05 16:44:50 +01:00
# include "scene/scene_string_names.h"
2020-03-03 14:36:29 +01:00
# include "servers/display_server.h"
2020-03-27 19:21:27 +01:00
# include "servers/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>
2020-05-21 18:08:48 +02:00
# include <stdlib.h>
2017-08-27 21:07:15 +02:00
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
2021-12-03 01:09:19 +01:00
ADD_PROPERTY ( PropertyInfo ( Variant : : FLOAT , " time_left " , PROPERTY_HINT_NONE , " suffix:s " ) , " 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 " ) ) ;
}
2021-05-21 07:23:35 +02:00
void SceneTreeTimer : : set_time_left ( double p_time ) {
2017-03-05 16:44:50 +01:00
time_left = p_time ;
2016-08-07 02:39:50 +02:00
}
2021-05-21 07:23:35 +02:00
double SceneTreeTimer : : get_time_left ( ) const {
2016-08-07 02:39:50 +02:00
return time_left ;
}
2021-02-19 13:57:41 +01:00
void SceneTreeTimer : : set_process_always ( bool p_process_always ) {
process_always = p_process_always ;
2017-02-14 00:34:33 +01:00
}
2021-02-19 13:57:41 +01:00
bool SceneTreeTimer : : is_process_always ( ) {
return process_always ;
2017-02-14 00:34:33 +01:00
}
2016-08-07 02:39:50 +02:00
2021-02-27 00:37:20 +01: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 18:45:17 +02:00
void SceneTreeTimer : : release_connections ( ) {
List < Connection > connections ;
get_all_signal_connections ( & connections ) ;
2021-07-24 15:46:25 +02:00
for ( const Connection & connection : connections ) {
2020-02-21 23:26:13 +01:00
disconnect ( connection . signal . get_name ( ) , connection . callable ) ;
2019-10-19 18:45:17 +02:00
}
}
2021-02-09 18:24:36 +01:00
SceneTreeTimer : : SceneTreeTimer ( ) { }
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 ) {
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 ) ;
2020-05-14 16:41:43 +02:00
if ( call_lock > 0 ) {
2014-02-10 02:10:30 +01:00
call_skip . insert ( p_node ) ;
2020-05-14 16:41:43 +02:00
}
2014-02-10 02:10:30 +01:00
}
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 ) {
2022-05-13 15:04:37 +02:00
HashMap < StringName , Group > : : Iterator 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
}
2022-05-13 15:04:37 +02: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 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 ) {
2022-05-13 15:04:37 +02:00
HashMap < StringName , Group > : : Iterator E = group_map . find ( p_group ) ;
2014-02-10 02:10:30 +01:00
ERR_FAIL_COND ( ! E ) ;
2022-05-13 15:04:37 +02:00
E - > value . nodes . erase ( p_node ) ;
if ( E - > value . nodes . is_empty ( ) ) {
group_map . remove ( E ) ;
2020-05-14 16:41:43 +02:00
}
2014-02-10 02:10:30 +01:00
}
2018-07-02 07:30:40 +02:00
void SceneTree : : make_group_changed ( const StringName & p_group ) {
2022-05-13 15:04:37 +02:00
HashMap < StringName , Group > : : Iterator E = group_map . find ( p_group ) ;
2020-05-14 16:41:43 +02:00
if ( E ) {
2022-05-13 15:04:37 +02:00
E - > value . changed = true ;
2020-05-14 16:41:43 +02:00
}
2018-07-02 07:30:40 +02:00
}
2017-10-30 19:43:19 +01:00
void SceneTree : : flush_transform_notifications ( ) {
2017-03-05 16:44:50 +01:00
SelfList < Node > * n = xform_change_list . first ( ) ;
while ( n ) {
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 ( ) {
2017-03-05 16:44:50 +01:00
ugc_locked = true ;
2014-02-10 02:10:30 +01:00
while ( unique_group_calls . size ( ) ) {
2022-05-13 15:04:37 +02:00
HashMap < UGCall , Vector < Variant > , UGCall > : : Iterator E = unique_group_calls . begin ( ) ;
2014-02-10 02:10:30 +01:00
2022-05-13 15:04:37 +02:00
const Variant * * argptrs = ( const Variant * * ) alloca ( E - > value . size ( ) * sizeof ( Variant * ) ) ;
2022-03-09 14:58:40 +01:00
2022-05-13 15:04:37 +02:00
for ( int i = 0 ; i < E - > value . size ( ) ; i + + ) {
argptrs [ i ] = & E - > value [ i ] ;
2020-05-14 16:41:43 +02:00
}
2014-02-10 02:10:30 +01:00
2022-05-13 15:04:37 +02:00
call_group_flagsp ( GROUP_CALL_DEFAULT , E - > key . group , E - > key . call , argptrs , E - > value . size ( ) ) ;
2014-02-10 02:10:30 +01:00
2022-05-13 15:04:37 +02:00
unique_group_calls . remove ( E ) ;
2014-02-10 02:10:30 +01:00
}
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 ) {
2020-05-14 16:41:43 +02:00
if ( ! g . changed ) {
2014-02-10 02:10:30 +01:00
return ;
2020-05-14 16:41:43 +02:00
}
2020-12-15 13:04:21 +01:00
if ( g . nodes . is_empty ( ) ) {
2014-02-10 02:10:30 +01:00
return ;
2020-05-14 16:41:43 +02:00
}
2014-02-10 02:10:30 +01:00
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
}
2022-03-09 14:58:40 +01: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 15:04:37 +02:00
HashMap < StringName , Group > : : Iterator E = group_map . find ( p_group ) ;
2020-05-14 16:41:43 +02:00
if ( ! E ) {
2014-02-10 02:10:30 +01:00
return ;
2020-05-14 16:41:43 +02:00
}
2022-05-13 15:04:37 +02:00
Group & g = E - > value ;
2020-12-15 13:04:21 +01:00
if ( g . nodes . is_empty ( ) ) {
2014-02-10 02:10:30 +01:00
return ;
2020-05-14 16:41:43 +02:00
}
2014-02-10 02:10:30 +01:00
2021-08-12 23:40:13 +02:00
if ( p_call_flags & GROUP_CALL_UNIQUE & & p_call_flags & GROUP_CALL_DEFERRED ) {
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
2020-05-14 16:41:43 +02:00
if ( unique_group_calls . has ( ug ) ) {
2014-02-10 02:10:30 +01:00
return ;
2020-05-14 16:41:43 +02:00
}
2014-02-10 02:10:30 +01:00
Vector < Variant > args ;
2022-03-09 14:58:40 +01:00
for ( int i = 0 ; i < p_argcount ; i + + ) {
args . push_back ( * p_args [ i ] ) ;
2014-02-10 02:10:30 +01:00
}
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 ) {
for ( int i = node_count - 1 ; i > = 0 ; i - - ) {
2020-05-14 16:41:43 +02:00
if ( call_lock & & call_skip . has ( nodes [ i ] ) ) {
2014-02-10 02:10:30 +01:00
continue ;
2020-05-14 16:41:43 +02:00
}
2014-02-10 02:10:30 +01:00
2021-08-12 23:40:13 +02:00
if ( ! ( p_call_flags & GROUP_CALL_DEFERRED ) ) {
2022-03-09 14:58:40 +01:00
Callable : : CallError ce ;
nodes [ i ] - > callp ( p_function , p_args , p_argcount , ce ) ;
2020-05-14 16:41:43 +02:00
} else {
2022-03-09 14:58:40 +01:00
MessageQueue : : get_singleton ( ) - > push_callp ( nodes [ i ] , p_function , p_args , p_argcount ) ;
2020-05-14 16:41:43 +02:00
}
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 + + ) {
2020-05-14 16:41:43 +02:00
if ( call_lock & & call_skip . has ( nodes [ i ] ) ) {
2014-02-10 02:10:30 +01:00
continue ;
2020-05-14 16:41:43 +02:00
}
2014-02-10 02:10:30 +01:00
2021-08-12 23:40:13 +02:00
if ( ! ( p_call_flags & GROUP_CALL_DEFERRED ) ) {
2022-03-09 14:58:40 +01:00
Callable : : CallError ce ;
nodes [ i ] - > callp ( p_function , p_args , p_argcount , ce ) ;
2020-05-14 16:41:43 +02:00
} else {
2022-03-09 14:58:40 +01:00
MessageQueue : : get_singleton ( ) - > push_callp ( nodes [ i ] , p_function , p_args , p_argcount ) ;
2020-05-14 16:41:43 +02:00
}
2014-02-10 02:10:30 +01:00
}
}
call_lock - - ;
2020-05-14 16:41:43 +02:00
if ( call_lock = = 0 ) {
2014-02-10 02:10:30 +01:00
call_skip . clear ( ) ;
2020-05-14 16:41:43 +02:00
}
2014-02-10 02:10:30 +01:00
}
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 ) {
2022-05-13 15:04:37 +02:00
HashMap < StringName , Group > : : Iterator E = group_map . find ( p_group ) ;
2020-05-14 16:41:43 +02:00
if ( ! E ) {
2014-02-10 02:10:30 +01:00
return ;
2020-05-14 16:41:43 +02:00
}
2022-05-13 15:04:37 +02:00
Group & g = E - > value ;
2020-12-15 13:04:21 +01:00
if ( g . nodes . is_empty ( ) ) {
2014-02-10 02:10:30 +01:00
return ;
2020-05-14 16:41:43 +02:00
}
2014-02-10 02:10:30 +01:00
_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 ) {
for ( int i = node_count - 1 ; i > = 0 ; i - - ) {
2020-05-14 16:41:43 +02:00
if ( call_lock & & call_skip . has ( nodes [ i ] ) ) {
2014-02-10 02:10:30 +01:00
continue ;
2020-05-14 16:41:43 +02:00
}
2014-02-10 02:10:30 +01:00
2021-08-12 23:40:13 +02:00
if ( ! ( p_call_flags & GROUP_CALL_DEFERRED ) ) {
2014-02-10 02:10:30 +01:00
nodes [ i ] - > notification ( p_notification ) ;
2020-05-14 16:41:43 +02:00
} else {
2017-03-05 16:44:50 +01:00
MessageQueue : : get_singleton ( ) - > push_notification ( nodes [ i ] , p_notification ) ;
2020-05-14 16:41:43 +02:00
}
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 + + ) {
2020-05-14 16:41:43 +02:00
if ( call_lock & & call_skip . has ( nodes [ i ] ) ) {
2014-02-10 02:10:30 +01:00
continue ;
2020-05-14 16:41:43 +02:00
}
2014-02-10 02:10:30 +01:00
2021-08-12 23:40:13 +02:00
if ( ! ( p_call_flags & GROUP_CALL_DEFERRED ) ) {
2014-02-10 02:10:30 +01:00
nodes [ i ] - > notification ( p_notification ) ;
2020-05-14 16:41:43 +02:00
} else {
2017-03-05 16:44:50 +01:00
MessageQueue : : get_singleton ( ) - > push_notification ( nodes [ i ] , p_notification ) ;
2020-05-14 16:41:43 +02:00
}
2014-02-10 02:10:30 +01:00
}
}
call_lock - - ;
2020-05-14 16:41:43 +02:00
if ( call_lock = = 0 ) {
2014-02-10 02:10:30 +01:00
call_skip . clear ( ) ;
2020-05-14 16:41:43 +02:00
}
2014-02-10 02:10:30 +01:00
}
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 ) {
2022-05-13 15:04:37 +02:00
HashMap < StringName , Group > : : Iterator E = group_map . find ( p_group ) ;
2020-05-14 16:41:43 +02:00
if ( ! E ) {
2014-02-10 02:10:30 +01:00
return ;
2020-05-14 16:41:43 +02:00
}
2022-05-13 15:04:37 +02:00
Group & g = E - > value ;
2020-12-15 13:04:21 +01:00
if ( g . nodes . is_empty ( ) ) {
2014-02-10 02:10:30 +01:00
return ;
2020-05-14 16:41:43 +02:00
}
2014-02-10 02:10:30 +01:00
_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 ) {
for ( int i = node_count - 1 ; i > = 0 ; i - - ) {
2020-05-14 16:41:43 +02:00
if ( call_lock & & call_skip . has ( nodes [ i ] ) ) {
2014-02-10 02:10:30 +01:00
continue ;
2020-05-14 16:41:43 +02:00
}
2014-02-10 02:10:30 +01:00
2021-08-12 23:40:13 +02:00
if ( ! ( p_call_flags & GROUP_CALL_DEFERRED ) ) {
2017-03-05 16:44:50 +01:00
nodes [ i ] - > set ( p_name , p_value ) ;
2020-05-14 16:41:43 +02:00
} else {
2017-03-05 16:44:50 +01:00
MessageQueue : : get_singleton ( ) - > push_set ( nodes [ i ] , p_name , p_value ) ;
2020-05-14 16:41:43 +02:00
}
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 + + ) {
2020-05-14 16:41:43 +02:00
if ( call_lock & & call_skip . has ( nodes [ i ] ) ) {
2014-02-10 02:10:30 +01:00
continue ;
2020-05-14 16:41:43 +02:00
}
2014-02-10 02:10:30 +01:00
2021-08-12 23:40:13 +02:00
if ( ! ( p_call_flags & GROUP_CALL_DEFERRED ) ) {
2017-03-05 16:44:50 +01:00
nodes [ i ] - > set ( p_name , p_value ) ;
2020-05-14 16:41:43 +02:00
} else {
2017-03-05 16:44:50 +01:00
MessageQueue : : get_singleton ( ) - > push_set ( nodes [ i ] , p_name , p_value ) ;
2020-05-14 16:41:43 +02:00
}
2014-02-10 02:10:30 +01:00
}
}
call_lock - - ;
2020-05-14 16:41:43 +02:00
if ( call_lock = = 0 ) {
2014-02-10 02:10:30 +01:00
call_skip . clear ( ) ;
2020-05-14 16:41:43 +02:00
}
2014-02-10 02:10:30 +01:00
}
2017-03-05 16:44:50 +01:00
void SceneTree : : notify_group ( const StringName & p_group , int p_notification ) {
2022-06-19 16:04:53 +02:00
notify_group_flags ( GROUP_CALL_DEFAULT , 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 ) {
2021-08-12 23:40:13 +02:00
set_group_flags ( GROUP_CALL_DEFAULT , p_group , p_name , p_value ) ;
2017-01-14 14:03:53 +01:00
}
2020-12-22 10:50:29 +01:00
void SceneTree : : initialize ( ) {
2021-03-21 00:48:41 +01:00
ERR_FAIL_COND ( ! root ) ;
2017-03-05 16:44:50 +01:00
initialized = true ;
2014-11-06 01:20:42 +01:00
root - > _set_tree ( this ) ;
2020-12-22 10:50:29 +01:00
MainLoop : : initialize ( ) ;
2014-02-10 02:10:30 +01:00
}
2021-05-21 07:23:35 +02:00
bool SceneTree : : physics_process ( double 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
2020-12-22 10:50:29 +01:00
MainLoop : : physics_process ( p_time ) ;
2017-09-30 16:19:07 +02:00
physics_process_time = p_time ;
2014-09-15 16:33:30 +02:00
2021-07-17 23:22:52 +02:00
emit_signal ( SNAME ( " physics_frame " ) ) ;
2014-09-15 16:33:30 +02:00
2022-07-01 20:16:05 +02:00
_notify_group_pause ( SNAME ( " _physics_process_internal " ) , Node : : NOTIFICATION_INTERNAL_PHYSICS_PROCESS ) ;
2021-08-12 23:40:13 +02:00
call_group ( SNAME ( " _picking_viewports " ) , SNAME ( " _process_picking " ) ) ;
2022-07-01 20:16:05 +02:00
_notify_group_pause ( SNAME ( " _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
2020-09-05 03:05:30 +02:00
process_tweens ( p_time , true ) ;
2017-10-30 19:43:19 +01:00
flush_transform_notifications ( ) ;
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 ;
}
2021-05-21 07:23:35 +02:00
bool SceneTree : : process ( double p_time ) {
2014-02-10 02:10:30 +01:00
root_lock + + ;
2020-12-22 10:50:29 +01:00
MainLoop : : process ( p_time ) ;
2014-02-10 02:10:30 +01:00
2020-12-22 10:50:29 +01:00
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 ( ) ;
2022-05-08 10:09:19 +02:00
for ( KeyValue < NodePath , Ref < MultiplayerAPI > > & E : custom_multiplayers ) {
E . value - > poll ( ) ;
2022-02-05 01:43:47 +01:00
}
2018-06-02 14:32:30 +02:00
}
2016-08-14 23:49:50 +02:00
2021-07-17 23:22:52 +02:00
emit_signal ( SNAME ( " process_frame " ) ) ;
2014-09-15 16:33:30 +02:00
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
2022-07-01 20:16:05 +02:00
_notify_group_pause ( SNAME ( " _process_internal " ) , Node : : NOTIFICATION_INTERNAL_PROCESS ) ;
_notify_group_pause ( SNAME ( " _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
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 ; ) {
List < Ref < SceneTreeTimer > > : : Element * N = E - > next ( ) ;
2021-02-19 13:57:41 +01:00
if ( paused & & ! E - > get ( ) - > is_process_always ( ) ) {
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 ;
}
2021-02-27 00:37:20 +01:00
2021-05-21 07:23:35 +02:00
double time_left = E - > get ( ) - > get_time_left ( ) ;
2021-02-27 00:37:20 +01:00
if ( E - > get ( ) - > is_ignore_time_scale ( ) ) {
time_left - = Engine : : get_singleton ( ) - > get_process_step ( ) ;
} else {
time_left - = p_time ;
}
2016-08-07 02:39:50 +02:00
E - > get ( ) - > set_time_left ( time_left ) ;
2022-03-05 21:22:38 +01:00
if ( time_left < = 0 ) {
2021-07-17 23:22:52 +02:00
E - > get ( ) - > emit_signal ( SNAME ( " timeout " ) ) ;
2016-08-07 02:39:50 +02:00
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
}
2020-09-05 03:05:30 +02:00
process_tweens ( p_time , false ) ;
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
2021-07-04 03:43:23 +02:00
# ifndef _3D_DISABLED
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
2021-07-19 19:25:15 +02:00
String env_path = ProjectSettings : : get_singleton ( ) - > get ( SNAME ( " rendering/environment/defaults/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 ;
2020-04-18 11:00:51 +02:00
Ref < Environment > fallback = get_root ( ) - > get_world_3d ( ) - > get_fallback_environment ( ) ;
2017-05-29 02:46:48 +02:00
if ( fallback . is_valid ( ) ) {
cpath = fallback - > get_path ( ) ;
}
if ( cpath ! = env_path ) {
2021-12-09 10:42:46 +01:00
if ( ! env_path . is_empty ( ) ) {
2017-05-29 02:46:48 +02:00
fallback = ResourceLoader : : load ( env_path ) ;
2017-08-31 13:55:20 +02:00
if ( fallback . is_null ( ) ) {
//could not load fallback, set as empty
2021-02-17 17:44:49 +01:00
ProjectSettings : : get_singleton ( ) - > set ( " rendering/environment/defaults/default_environment " , " " ) ;
2017-08-31 13:55:20 +02:00
}
2017-05-29 02:46:48 +02:00
} else {
fallback . unref ( ) ;
}
2020-04-18 11:00:51 +02:00
get_root ( ) - > get_world_3d ( ) - > set_fallback_environment ( fallback ) ;
2017-05-29 02:46:48 +02:00
}
}
2021-07-04 03:43:23 +02:00
# endif // _3D_DISABLED
# endif // TOOLS_ENABLED
2017-05-29 02:46:48 +02:00
2014-02-10 02:10:30 +01:00
return _quit ;
}
2020-09-05 03:05:30 +02:00
void SceneTree : : process_tweens ( float p_delta , bool p_physics ) {
// 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 18:23:53 +01:00
if ( ! E - > get ( ) - > can_process ( paused ) | | ( p_physics = = ( E - > get ( ) - > get_process_mode ( ) = = Tween : : TWEEN_PROCESS_IDLE ) ) ) {
2020-09-05 03:05:30 +02:00
if ( E = = L ) {
break ;
}
E = N ;
continue ;
}
if ( ! E - > get ( ) - > step ( p_delta ) ) {
2021-08-05 13:05:14 +02:00
E - > get ( ) - > clear ( ) ;
2020-09-05 03:05:30 +02:00
tweens . erase ( E ) ;
}
if ( E = = L ) {
break ;
}
E = N ;
}
}
2020-12-22 10:50:29 +01:00
void SceneTree : : finalize ( ) {
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
2020-12-22 10:50:29 +01:00
MainLoop : : finalize ( ) ;
2014-02-10 02:10:30 +01:00
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
2021-10-08 16:37:03 +02: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 17:50:35 +02:00
for ( Ref < SceneTreeTimer > & timer : timers ) {
timer - > release_connections ( ) ;
2019-10-19 18:45:17 +02:00
}
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 ) {
2020-06-04 22:03:45 +02:00
OS : : get_singleton ( ) - > set_exit_code ( p_exit_code ) ;
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 ( ) {
if ( accept_quit ) {
_quit = true ;
}
}
2020-05-14 14:29:06 +02:00
2020-03-04 17:36:09 +01:00
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 ( ) {
2020-04-28 15:19:37 +02:00
Input * id = Input : : get_singleton ( ) ;
2020-03-04 17:36:09 +01:00
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 ) {
switch ( p_notification ) {
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 ;
2022-02-15 18:06:48 +01:00
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 :
2020-06-30 01:47:18 +02:00
case NOTIFICATION_APPLICATION_RESUMED :
case NOTIFICATION_APPLICATION_PAUSED :
case NOTIFICATION_APPLICATION_FOCUS_IN :
case NOTIFICATION_APPLICATION_FOCUS_OUT : {
2022-02-15 18:06:48 +01:00
// Pass these to nodes, since they are mirrored.
get_root ( ) - > propagate_notification ( p_notification ) ;
2018-07-02 21:18:58 +02:00
} break ;
2022-02-15 18:06:48 +01:00
}
}
2014-02-10 02:10:30 +01:00
2022-05-14 12:18:26 +02:00
bool SceneTree : : is_auto_accept_quit ( ) const {
return accept_quit ;
}
2014-11-06 01:20:42 +01:00
void SceneTree : : set_auto_accept_quit ( bool p_enable ) {
2017-03-05 16:44:50 +01:00
accept_quit = p_enable ;
2014-02-10 02:10:30 +01:00
}
2022-05-14 12:18:26 +02:00
bool SceneTree : : is_quit_on_go_back ( ) const {
return quit_on_go_back ;
}
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 {
2021-06-19 00:02:50 +02: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 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 ;
}
2022-06-15 23:24:06 +02: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 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 ) {
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 ) {
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 ;
}
2022-06-15 23:24:06 +02: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 ;
}
2017-03-05 16:44:50 +01:00
void SceneTree : : set_debug_navigation_color ( const Color & p_color ) {
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 ) {
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 ;
}
2022-06-15 23:24:06 +02:00
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 18:03:46 +02:00
Ref < Material > SceneTree : : get_debug_navigation_material ( ) {
2020-05-14 16:41:43 +02:00
if ( navigation_material . is_valid ( ) ) {
2015-09-20 18:03:46 +02:00
return navigation_material ;
2020-05-14 16:41:43 +02:00
}
2015-09-20 18:03:46 +02:00
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 ( ) {
2020-05-14 16:41:43 +02:00
if ( navigation_disabled_material . is_valid ( ) ) {
2015-09-20 18:03:46 +02:00
return navigation_disabled_material ;
2020-05-14 16:41:43 +02:00
}
2015-09-20 18:03:46 +02:00
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 ;
}
2020-05-14 14:29:06 +02:00
2015-09-20 18:03:46 +02:00
Ref < Material > SceneTree : : get_debug_collision_material ( ) {
2020-05-14 16:41:43 +02:00
if ( collision_material . is_valid ( ) ) {
2015-09-20 18:03:46 +02:00
return collision_material ;
2020-05-14 16:41:43 +02:00
}
2015-09-20 18:03:46 +02:00
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 ( ) {
2020-05-14 16:41:43 +02:00
if ( debug_contact_mesh . is_valid ( ) ) {
2015-09-20 18:03:46 +02:00
return debug_contact_mesh ;
2020-05-14 16:41:43 +02:00
}
2015-09-20 18:03:46 +02:00
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 ;
2020-05-14 16:41:43 +02:00
for ( int i = 0 ; i < 8 * 3 ; i + + ) {
2015-09-20 18:03:46 +02:00
indices . push_back ( diamond_faces [ i ] ) ;
2020-05-14 16:41:43 +02:00
}
2015-09-20 18:03:46 +02:00
2020-02-17 22:06:54 +01:00
Vector < Vector3 > vertices ;
2020-05-14 16:41:43 +02:00
for ( int i = 0 ; i < 6 ; i + + ) {
2017-03-05 16:44:50 +01:00
vertices . push_back ( diamond [ i ] * 0.1 ) ;
2020-05-14 16:41:43 +02:00
}
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 ) {
2021-02-19 13:57:41 +01:00
if ( p_enabled = = paused ) {
2014-02-10 02:10:30 +01:00
return ;
2020-05-14 16:41:43 +02:00
}
2021-02-19 13:57:41 +01:00
paused = 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 ) ;
2020-05-14 16:41:43 +02:00
if ( get_root ( ) ) {
2021-02-18 19:52:29 +01:00
get_root ( ) - > _propagate_pause_notification ( p_enabled ) ;
2020-05-14 16:41:43 +02:00
}
2014-02-10 02:10:30 +01:00
}
2014-11-06 01:20:42 +01:00
bool SceneTree : : is_paused ( ) const {
2021-02-19 13:57:41 +01:00
return paused ;
2014-02-10 02:10:30 +01:00
}
2020-03-04 17:36:09 +01:00
void SceneTree : : _notify_group_pause ( const StringName & p_group , int p_notification ) {
2022-05-13 15:04:37 +02:00
HashMap < StringName , Group > : : Iterator E = group_map . find ( p_group ) ;
2020-05-14 16:41:43 +02:00
if ( ! E ) {
2014-02-10 02:10:30 +01:00
return ;
2020-05-14 16:41:43 +02:00
}
2022-05-13 15:04:37 +02:00
Group & g = E - > value ;
2020-12-15 13:04:21 +01:00
if ( g . nodes . is_empty ( ) ) {
2014-02-10 02:10:30 +01:00
return ;
2020-05-14 16:41:43 +02:00
}
2014-02-10 02:10:30 +01:00
2020-03-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 ] ;
2020-05-14 16:41:43 +02:00
if ( call_lock & & call_skip . has ( n ) ) {
2014-02-10 02:10:30 +01:00
continue ;
2020-05-14 16:41:43 +02:00
}
2014-02-10 02:10:30 +01:00
2020-05-14 16:41:43 +02:00
if ( ! n - > can_process ( ) ) {
2014-02-10 02:10:30 +01:00
continue ;
2020-05-14 16:41:43 +02:00
}
if ( ! n - > can_process_notification ( p_notification ) ) {
2020-03-04 17:36:09 +01:00
continue ;
2020-05-14 16:41:43 +02:00
}
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 - - ;
2020-05-14 16:41:43 +02:00
if ( call_lock = = 0 ) {
2014-02-10 02:10:30 +01:00
call_skip . clear ( ) ;
2020-05-14 16:41:43 +02:00
}
2014-02-10 02:10:30 +01:00
}
2021-08-22 17:37:22 +02: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 15:04:37 +02:00
HashMap < StringName , Group > : : Iterator E = group_map . find ( p_group ) ;
2020-05-14 16:41:43 +02:00
if ( ! E ) {
2014-02-10 02:10:30 +01:00
return ;
2020-05-14 16:41:43 +02:00
}
2022-05-13 15:04:37 +02:00
Group & g = E - > value ;
2020-12-15 13:04:21 +01:00
if ( g . nodes . is_empty ( ) ) {
2014-02-10 02:10:30 +01:00
return ;
2020-05-14 16:41:43 +02:00
}
2014-02-10 02:10:30 +01:00
2020-03-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
call_lock + + ;
2020-03-04 17:36:09 +01:00
for ( int i = node_count - 1 ; i > = 0 ; i - - ) {
2020-05-14 16:41:43 +02:00
if ( p_viewport - > is_input_handled ( ) ) {
2020-03-04 17:36:09 +01:00
break ;
2020-05-14 16:41:43 +02:00
}
2014-02-10 02:10:30 +01:00
Node * n = nodes [ i ] ;
2020-05-14 16:41:43 +02:00
if ( call_lock & & call_skip . has ( n ) ) {
2014-02-10 02:10:30 +01:00
continue ;
2020-05-14 16:41:43 +02:00
}
2014-02-10 02:10:30 +01:00
2020-05-14 16:41:43 +02:00
if ( ! n - > can_process ( ) ) {
2014-02-10 02:10:30 +01:00
continue ;
2020-05-14 16:41:43 +02:00
}
2014-02-10 02:10:30 +01:00
2021-08-22 17:37:22 +02:00
switch ( p_call_type ) {
case CALL_INPUT_TYPE_INPUT :
n - > _call_input ( p_input ) ;
break ;
2022-01-11 14:59:52 +01:00
case CALL_INPUT_TYPE_SHORTCUT_INPUT :
n - > _call_shortcut_input ( p_input ) ;
break ;
2021-08-22 17:37:22 +02: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 13:39:04 +02:00
}
2014-02-10 02:10:30 +01:00
}
call_lock - - ;
2020-05-14 16:41:43 +02:00
if ( call_lock = = 0 ) {
2014-02-10 02:10:30 +01:00
call_skip . clear ( ) ;
2020-05-14 16:41:43 +02:00
}
2014-02-10 02:10:30 +01:00
}
2020-05-14 14:29:06 +02:00
2022-02-22 12:15:43 +01:00
void SceneTree : : _call_group_flags ( const Variant * * p_args , int p_argcount , Callable : : CallError & r_error ) {
2020-02-19 20:27:19 +01:00
r_error . error = Callable : : CallError : : CALL_OK ;
2014-02-10 02:10:30 +01:00
2022-02-22 12:15:43 +01: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 02:10:30 +01:00
int flags = * p_args [ 0 ] ;
StringName group = * p_args [ 1 ] ;
StringName method = * p_args [ 2 ] ;
2022-03-09 14:58:40 +01:00
call_group_flagsp ( flags , group , method , p_args + 3 , p_argcount - 3 ) ;
2014-02-10 02:10:30 +01:00
}
2022-02-22 12:15:43 +01:00
void SceneTree : : _call_group ( const Variant * * p_args , int p_argcount , Callable : : CallError & r_error ) {
2020-02-19 20:27:19 +01:00
r_error . error = Callable : : CallError : : CALL_OK ;
2017-01-14 14:03:53 +01:00
2022-02-22 12:15:43 +01: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 14:03:53 +01:00
StringName group = * p_args [ 0 ] ;
StringName method = * p_args [ 1 ] ;
2021-08-12 23:40:13 +02:00
call_group_flagsp ( GROUP_CALL_DEFAULT , group , method , p_args + 2 , p_argcount - 2 ) ;
2017-01-14 14:03:53 +01:00
}
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 ;
}
2020-05-14 14:29:06 +02:00
2022-08-05 20:35:08 +02:00
TypedArray < Node > SceneTree : : _get_nodes_in_group ( const StringName & p_group ) {
TypedArray < Node > ret ;
2022-05-13 15:04:37 +02:00
HashMap < StringName , Group > : : Iterator E = group_map . find ( p_group ) ;
2020-05-14 16:41:43 +02:00
if ( ! E ) {
2014-02-10 02:10:30 +01:00
return ret ;
2020-05-14 16:41:43 +02:00
}
2014-02-10 02:10:30 +01:00
2022-05-13 15:04:37 +02:00
_update_group_order ( E - > value ) ; //update order just in case
int nc = E - > value . nodes . size ( ) ;
2020-05-14 16:41:43 +02:00
if ( nc = = 0 ) {
2014-02-10 02:10:30 +01:00
return ret ;
2020-05-14 16:41:43 +02:00
}
2014-02-10 02:10:30 +01:00
ret . resize ( nc ) ;
2022-05-13 15:04:37 +02:00
Node * * ptr = E - > value . nodes . ptrw ( ) ;
2017-03-05 16:44:50 +01:00
for ( int i = 0 ; i < nc ; i + + ) {
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 ) ;
}
2020-05-14 14:29:06 +02:00
2021-02-22 14:54:12 +01:00
Node * SceneTree : : get_first_node_in_group ( const StringName & p_group ) {
2022-05-13 15:04:37 +02:00
HashMap < StringName , Group > : : Iterator E = group_map . find ( p_group ) ;
2021-02-22 14:54:12 +01:00
if ( ! E ) {
2022-04-29 16:14:48 +02:00
return nullptr ; // No group.
2021-02-22 14:54:12 +01:00
}
2022-05-13 15:04:37 +02:00
_update_group_order ( E - > value ) ; // Update order just in case.
2021-02-22 14:54:12 +01:00
2022-05-13 15:04:37 +02:00
if ( E - > value . nodes . is_empty ( ) ) {
2021-02-22 14:54:12 +01:00
return nullptr ;
}
2022-05-13 15:04:37 +02:00
return E - > value . nodes [ 0 ] ;
2021-02-22 14:54:12 +01:00
}
2017-03-05 16:44:50 +01:00
void SceneTree : : get_nodes_in_group ( const StringName & p_group , List < Node * > * p_list ) {
2022-05-13 15:04:37 +02:00
HashMap < StringName , Group > : : Iterator E = group_map . find ( p_group ) ;
2020-05-14 16:41:43 +02:00
if ( ! E ) {
2014-02-10 02:10:30 +01:00
return ;
2020-05-14 16:41:43 +02:00
}
2014-02-10 02:10:30 +01:00
2022-05-13 15:04:37 +02:00
_update_group_order ( E - > value ) ; //update order just in case
int nc = E - > value . nodes . size ( ) ;
2020-05-14 16:41:43 +02:00
if ( nc = = 0 ) {
2014-02-10 02:10:30 +01:00
return ;
2020-05-14 16:41:43 +02:00
}
2022-05-13 15:04:37 +02:00
Node * * ptr = E - > value . 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 ( ) ) {
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 {
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 ) {
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 ) ;
2020-05-14 16:41:43 +02:00
if ( new_scene . is_null ( ) ) {
2015-05-17 21:33:35 +02:00
return ERR_CANT_OPEN ;
2020-05-14 16:41:43 +02:00
}
2015-05-17 21:33:35 +02:00
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 ( ) ) {
2021-06-18 00:03:09 +02:00
new_scene = p_scene - > instantiate ( ) ;
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
}
2021-07-17 23:22:52 +02:00
call_deferred ( SNAME ( " _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 ) ;
2021-09-30 16:30:55 +02:00
String fname = current_scene - > get_scene_file_path ( ) ;
2015-05-17 21:33:35 +02:00
return change_scene ( fname ) ;
}
2017-03-05 16:44:50 +01:00
void SceneTree : : add_current_scene ( Node * p_current ) {
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
2021-05-21 07:23:35 +02:00
Ref < SceneTreeTimer > SceneTree : : create_timer ( double p_delay_sec , bool p_process_always ) {
2016-08-07 02:39:50 +02:00
Ref < SceneTreeTimer > stt ;
2021-06-18 00:03:09 +02:00
stt . instantiate ( ) ;
2021-02-19 13:57:41 +01:00
stt - > set_process_always ( p_process_always ) ;
2016-08-07 02:39:50 +02:00
stt - > set_time_left ( p_delay_sec ) ;
timers . push_back ( stt ) ;
return stt ;
}
2020-09-05 03:05:30 +02:00
Ref < Tween > SceneTree : : create_tween ( ) {
2022-04-17 23:13:39 +02:00
Ref < Tween > tween = memnew ( Tween ( true ) ) ;
2020-09-05 03:05:30 +02:00
tweens . push_back ( tween ) ;
return tween ;
}
2022-08-05 20:35:08 +02:00
TypedArray < Tween > SceneTree : : get_processed_tweens ( ) {
TypedArray < Tween > ret ;
2020-09-05 03:05:30 +02:00
ret . resize ( tweens . size ( ) ) ;
int i = 0 ;
2021-07-26 17:50:35 +02:00
for ( const Ref < Tween > & tween : tweens ) {
ret [ i ] = tween ;
2020-09-05 03:05:30 +02:00
i + + ;
}
return ret ;
}
2022-02-05 01:43:47 +01:00
Ref < MultiplayerAPI > SceneTree : : get_multiplayer ( const NodePath & p_for_path ) const {
Ref < MultiplayerAPI > out = multiplayer ;
2022-05-08 10:09:19 +02:00
for ( const KeyValue < NodePath , Ref < MultiplayerAPI > > & E : custom_multiplayers ) {
const Vector < StringName > snames = E . key . get_names ( ) ;
2022-02-05 01:43:47 +01: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 10:09:19 +02:00
out = E . value ;
2022-02-05 01:43:47 +01: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 23:12:42 +02:00
multiplayer - > object_configuration_remove ( nullptr , NodePath ( " / " + root - > get_name ( ) ) ) ;
2022-02-05 01:43:47 +01:00
}
multiplayer = p_multiplayer ;
2022-07-12 23:12:42 +02:00
multiplayer - > object_configuration_add ( nullptr , NodePath ( " / " + root - > get_name ( ) ) ) ;
2022-02-05 01:43:47 +01:00
} else {
2022-07-12 23:12:42 +02:00
if ( custom_multiplayers . has ( p_root_path ) ) {
custom_multiplayers [ p_root_path ] - > object_configuration_remove ( nullptr , p_root_path ) ;
}
2022-02-05 01:43:47 +01:00
if ( p_multiplayer . is_valid ( ) ) {
custom_multiplayers [ p_root_path ] = p_multiplayer ;
2022-07-12 23:12:42 +02:00
p_multiplayer - > object_configuration_add ( nullptr , p_root_path ) ;
2022-02-05 01:43:47 +01:00
}
}
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 ;
}
2014-11-06 01:20:42 +01:00
void SceneTree : : _bind_methods ( ) {
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
2022-05-14 12:18:26 +02:00
ClassDB : : bind_method ( D_METHOD ( " is_auto_accept_quit " ) , & SceneTree : : is_auto_accept_quit ) ;
2017-03-05 16:44:50 +01:00
ClassDB : : bind_method ( D_METHOD ( " set_auto_accept_quit " , " enabled " ) , & SceneTree : : set_auto_accept_quit ) ;
2022-05-14 12:18:26 +02:00
ClassDB : : bind_method ( D_METHOD ( " is_quit_on_go_back " ) , & SceneTree : : is_quit_on_go_back ) ;
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 ) ;
2022-06-15 23:24:06 +02: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 16:44:50 +01: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 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
2021-02-19 13:57:41 +01:00
ClassDB : : bind_method ( D_METHOD ( " create_timer " , " time_sec " , " process_always " ) , & SceneTree : : create_timer , DEFVAL ( true ) ) ;
2020-09-05 03:05:30 +02: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 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 ) ;
2020-06-04 22:03:45 +02:00
ClassDB : : bind_method ( D_METHOD ( " quit " , " exit_code " ) , & SceneTree : : quit , DEFVAL ( EXIT_SUCCESS ) ) ;
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 ) ;
2021-02-22 14:54:12 +01:00
ClassDB : : bind_method ( D_METHOD ( " get_first_node_in_group " , " group " ) , & SceneTree : : get_first_node_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
2022-02-05 01:43:47 +01: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 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 ) ;
2014-02-10 02:10:30 +01:00
2022-05-14 12:18:26 +02: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 23:35:12 +01:00
ADD_PROPERTY ( PropertyInfo ( Variant : : BOOL , " debug_collisions_hint " ) , " set_debug_collisions_hint " , " is_debugging_collisions_hint " ) ;
2022-06-15 23:24:06 +02:00
ADD_PROPERTY ( PropertyInfo ( Variant : : BOOL , " debug_paths_hint " ) , " set_debug_paths_hint " , " is_debugging_paths_hint " ) ;
2018-01-11 23:35:12 +01: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-18 01:10:18 +02: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 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 " ) ) ;
2021-05-20 12:07:26 +02: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 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
2020-12-22 10:50:29 +01:00
ADD_SIGNAL ( MethodInfo ( " process_frame " ) ) ;
2017-09-30 16:19:07 +02:00
ADD_SIGNAL ( MethodInfo ( " physics_frame " ) ) ;
2016-05-27 19:18:40 +02:00
2017-08-20 17:45:01 +02:00
BIND_ENUM_CONSTANT ( GROUP_CALL_DEFAULT ) ;
BIND_ENUM_CONSTANT ( GROUP_CALL_REVERSE ) ;
2021-08-12 23:40:13 +02:00
BIND_ENUM_CONSTANT ( GROUP_CALL_DEFERRED ) ;
2017-08-20 17:45:01 +02:00
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 " ) {
2022-03-23 10:08:58 +01:00
Ref < DirAccess > dir_access = DirAccess : : create ( DirAccess : : ACCESS_RESOURCES ) ;
2019-03-09 03:05:59 +01:00
List < String > directories ;
directories . push_back ( dir_access - > get_current_dir ( ) ) ;
2020-12-15 13:04:21 +01:00
while ( ! directories . is_empty ( ) ) {
2019-03-09 03:05:59 +01: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 10:42:46 +01:00
while ( ! filename . is_empty ( ) ) {
2019-03-09 03:05:59 +01:00
if ( filename = = " . " | | filename = = " .. " ) {
filename = dir_access - > get_next ( ) ;
continue ;
}
if ( dir_access - > dir_exists ( filename ) ) {
2022-08-30 02:34:01 +02:00
directories . push_back ( dir_access - > get_current_dir ( ) . path_join ( filename ) ) ;
2019-03-09 03:05:59 +01:00
} else if ( filename . ends_with ( " .tscn " ) | | filename . ends_with ( " .scn " ) ) {
2022-08-30 02:34:01 +02:00
r_options - > push_back ( " \" " + dir_access - > get_current_dir ( ) . path_join ( filename ) + " \" " ) ;
2019-03-09 03:05:59 +01:00
}
filename = dir_access - > get_next ( ) ;
}
}
}
}
2014-11-06 01:20:42 +01:00
SceneTree : : SceneTree ( ) {
2020-05-14 16:41:43 +02:00
if ( singleton = = nullptr ) {
2020-05-10 12:56:01 +02:00
singleton = this ;
2020-05-14 16:41:43 +02:00
}
2021-01-20 15:42:11 +01:00
debug_collisions_color = GLOBAL_DEF ( " debug/shapes/collision/shape_color " , Color ( 0.0 , 0.6 , 0.7 , 0.42 ) ) ;
2017-07-18 02:05:38 +02:00
debug_collision_contact_color = GLOBAL_DEF ( " debug/shapes/collision/contact_color " , Color ( 1.0 , 0.2 , 0.1 , 0.8 ) ) ;
2022-06-15 23:24:06 +02: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 02:05:38 +02:00
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
2021-02-25 14:56:47 +01:00
GLOBAL_DEF ( " debug/shapes/collision/draw_2d_outlines " , true ) ;
2020-11-05 11:04:25 +01:00
Math : : randomize ( ) ;
2020-12-11 15:54:03 +01:00
// Create with mainloop.
2014-02-10 02:10:30 +01:00
2020-03-04 02:51:12 +01:00
root = memnew ( Window ) ;
2021-06-22 02:49:34 +02:00
root - > set_process_mode ( Node : : PROCESS_MODE_PAUSABLE ) ;
2014-02-10 02:10:30 +01:00
root - > set_name ( " root " ) ;
2022-01-21 10:08:07 +01:00
root - > set_title ( ProjectSettings : : get_singleton ( ) - > get ( " application/config/name " ) ) ;
2021-07-04 03:43:23 +02:00
# ifndef _3D_DISABLED
2020-05-14 16:41:43 +02:00
if ( ! root - > get_world_3d ( ) . is_valid ( ) ) {
2020-04-18 11:00:51 +02:00
root - > set_world_3d ( Ref < World3D > ( memnew ( World3D ) ) ) ;
2020-05-14 16:41:43 +02:00
}
2021-07-04 03:43:23 +02:00
root - > set_as_audio_listener_3d ( true ) ;
# endif // _3D_DISABLED
2017-05-29 02:46:48 +02:00
2020-12-11 15:54:03 +01:00
// Initialize network state.
2022-07-12 23:12:42 +02:00
set_multiplayer ( MultiplayerAPI : : create_default_interface ( ) ) ;
2018-03-03 18:30:11 +01:00
2014-02-10 02:10:30 +01:00
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
2022-08-13 01:02:32 +02: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 22:00:46 +02:00
2022-06-12 19:50:14 +02:00
const int ssaa_mode = GLOBAL_DEF_BASIC ( " rendering/anti_aliasing/quality/screen_space_aa " , 0 ) ;
2021-02-17 17:44:49 +01: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 06:49:10 +02:00
root - > set_screen_space_aa ( Viewport : : ScreenSpaceAA ( ssaa_mode ) ) ;
2022-06-12 19:50:14 +02:00
const bool use_taa = GLOBAL_DEF_BASIC ( " rendering/anti_aliasing/quality/use_taa " , false ) ;
2022-04-04 16:10:22 +02:00
root - > set_use_taa ( use_taa ) ;
2021-02-17 17:44:49 +01:00
const bool use_debanding = GLOBAL_DEF ( " rendering/anti_aliasing/quality/use_debanding " , false ) ;
2020-04-20 23:34:47 +02:00
root - > set_use_debanding ( use_debanding ) ;
2021-04-20 18:40:24 +02: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-29 00:10:41 +01:00
float mesh_lod_threshold = GLOBAL_DEF ( " rendering/mesh_lod/lod_change/threshold_pixels " , 1.0 ) ;
2021-02-17 17:44:49 +01: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-29 00:10:41 +01:00
root - > set_mesh_lod_threshold ( mesh_lod_threshold ) ;
2020-12-17 19:56:59 +01:00
2021-02-17 17:44:49 +01:00
bool snap_2d_transforms = GLOBAL_DEF ( " rendering/2d/snap/snap_2d_transforms_to_pixel " , false ) ;
2020-10-29 22:09:16 +01:00
root - > set_snap_2d_transforms_to_pixel ( snap_2d_transforms ) ;
2021-02-17 17:44:49 +01:00
bool snap_2d_vertices = GLOBAL_DEF ( " rendering/2d/snap/snap_2d_vertices_to_pixel " , false ) ;
2020-10-29 22:09:16 +01:00
root - > set_snap_2d_vertices_to_pixel ( snap_2d_vertices ) ;
2022-02-11 12:33:54 +01: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 " ,
PROPERTY_HINT_FILE , " *.png " ) ) ;
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-08-01 01:20:24 +02: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-05-01 01:40:30 +02: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 20:00:20 +01:00
2021-02-17 17:44:49 +01:00
Viewport : : SDFOversize sdf_oversize = Viewport : : SDFOversize ( int ( GLOBAL_DEF ( " rendering/2d/sdf/oversize " , 1 ) ) ) ;
2020-11-26 13:50:21 +01:00
root - > set_sdf_oversize ( sdf_oversize ) ;
2021-02-17 17:44:49 +01:00
Viewport : : SDFScale sdf_scale = Viewport : : SDFScale ( int ( GLOBAL_DEF ( " rendering/2d/sdf/scale " , 1 ) ) ) ;
2020-11-26 13:50:21 +01:00
root - > set_sdf_scale ( sdf_scale ) ;
2021-02-17 17:44:49 +01: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 13:50:21 +01:00
2021-07-04 03:43:23 +02:00
# ifndef _3D_DISABLED
2020-12-11 15:54:03 +01:00
{ // Load default fallback environment.
// Get possible extensions.
2017-05-29 02:46:48 +02:00
List < String > exts ;
ResourceLoader : : get_recognized_extensions_for_type ( " Environment " , & exts ) ;
String ext_hint ;
2021-07-24 15:46:25 +02:00
for ( const String & E : exts ) {
2021-12-09 10:42:46 +01:00
if ( ! ext_hint . is_empty ( ) ) {
2017-05-29 02:46:48 +02:00
ext_hint + = " , " ;
2020-05-14 16:41:43 +02:00
}
2021-07-16 05:45:57 +02:00
ext_hint + = " *. " + E ;
2017-05-29 02:46:48 +02:00
}
2020-12-11 15:54:03 +01:00
// Get path.
2021-02-17 17:44:49 +01:00
String env_path = GLOBAL_DEF ( " rendering/environment/defaults/default_environment " , " " ) ;
2020-12-11 15:54:03 +01:00
// Setup property.
2021-02-17 17:44:49 +01: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 02:46:48 +02:00
env_path = env_path . strip_edges ( ) ;
2021-12-09 10:42:46 +01:00
if ( ! env_path . is_empty ( ) ) {
2017-05-29 02:46:48 +02:00
Ref < Environment > env = ResourceLoader : : load ( env_path ) ;
if ( env . is_valid ( ) ) {
2020-04-18 11:00:51 +02:00
root - > get_world_3d ( ) - > set_fallback_environment ( env ) ;
2017-05-29 02:46:48 +02:00
} else {
2017-08-19 01:02:56 +02:00
if ( Engine : : get_singleton ( ) - > is_editor_hint ( ) ) {
2020-12-11 15:54:03 +01:00
// File was erased, clear the field.
2021-02-17 17:44:49 +01:00
ProjectSettings : : get_singleton ( ) - > set ( " rendering/environment/defaults/default_environment " , " " ) ;
2017-05-29 02:46:48 +02:00
} else {
2020-12-11 15:54:03 +01:00
// 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
}
}
}
}
2021-07-04 03:43:23 +02:00
# endif // _3D_DISABLED
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-05-14 16:41:43 +02:00
if ( singleton = = this ) {
2020-05-10 12:56:01 +02:00
singleton = nullptr ;
2020-05-14 16:41:43 +02:00
}
2014-02-10 02:10:30 +01:00
}