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-13 09:45:09 +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
2018-09-11 18:13:45 +02:00
# include "core/io/marshalls.h"
# include "core/io/resource_loader.h"
# include "core/message_queue.h"
2019-03-09 03:05:59 +01:00
# include "core/os/dir_access.h"
2018-09-11 18:13:45 +02:00
# include "core/os/keyboard.h"
# include "core/os/os.h"
# include "core/print_string.h"
# include "core/project_settings.h"
2018-02-24 03:04:30 +01:00
# include "main/input_default.h"
2014-02-10 02:10:30 +01:00
# include "node.h"
2019-04-06 22:55:01 +02:00
# include "scene/debugger/script_debugger_remote.h"
2017-12-19 22:48:30 +01:00
# include "scene/resources/dynamic_font.h"
2015-09-20 18:03:46 +02:00
# include "scene/resources/material.h"
# include "scene/resources/mesh.h"
2017-03-05 16:44:50 +01:00
# include "scene/resources/packed_scene.h"
# include "scene/scene_string_names.h"
2021-12-16 06:15:23 +01:00
# include "servers/navigation_server.h"
2017-03-05 16:44:50 +01:00
# include "servers/physics_2d_server.h"
# include "servers/physics_server.h"
# include "viewport.h"
2016-08-07 02:39:50 +02:00
2021-11-12 13:34:25 +01:00
# include "modules/modules_enabled.gen.h" // For freetype.
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
2018-01-11 23:35:12 +01:00
ADD_PROPERTY ( PropertyInfo ( Variant : : REAL , " time_left " ) , " set_time_left " , " get_time_left " ) ;
2016-08-07 02:39:50 +02:00
ADD_SIGNAL ( MethodInfo ( " timeout " ) ) ;
}
void SceneTreeTimer : : set_time_left ( float p_time ) {
2017-03-05 16:44:50 +01:00
time_left = p_time ;
2016-08-07 02:39:50 +02:00
}
float SceneTreeTimer : : get_time_left ( ) const {
return time_left ;
}
2017-02-14 00:34:33 +01:00
void SceneTreeTimer : : set_pause_mode_process ( bool p_pause_mode_process ) {
2019-10-14 11:40:55 +02:00
process_pause = p_pause_mode_process ;
2017-02-14 00:34:33 +01:00
}
bool SceneTreeTimer : : is_pause_mode_process ( ) {
return process_pause ;
}
2016-08-07 02:39:50 +02:00
2021-11-22 12:54:05 +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 ) ;
for ( List < Connection > : : Element * E = connections . front ( ) ; E ; E = E - > next ( ) ) {
Connection const & connection = E - > get ( ) ;
disconnect ( connection . signal , connection . target , connection . method ) ;
}
}
2016-08-07 02:39:50 +02:00
SceneTreeTimer : : SceneTreeTimer ( ) {
2017-03-05 16:44:50 +01:00
time_left = 0 ;
2017-02-14 00:34:33 +01:00
process_pause = true ;
2016-08-07 02:39:50 +02:00
}
2022-02-21 08:34:42 +01:00
// This should be called once per physics tick, to make sure the transform previous and current
// is kept up to date on the few spatials that are using client side physics interpolation
void SceneTree : : ClientPhysicsInterpolation : : physics_process ( ) {
for ( SelfList < Spatial > * E = _spatials_list . first ( ) ; E ; ) {
Spatial * spatial = E - > self ( ) ;
SelfList < Spatial > * current = E ;
// get the next element here BEFORE we potentially delete one
E = E - > next ( ) ;
// This will return false if the spatial has timed out ..
// i.e. If get_global_transform_interpolated() has not been called
// for a few seconds, we can delete from the list to keep processing
// to a minimum.
if ( ! spatial - > update_client_physics_interpolation_data ( ) ) {
_spatials_list . remove ( current ) ;
}
}
}
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 ) {
2021-05-04 16:00:45 +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 ) ;
2021-05-05 12:44:11 +02:00
if ( call_lock > 0 ) {
2014-02-10 02:10:30 +01:00
call_skip . insert ( p_node ) ;
2021-05-05 12:44:11 +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 ) {
Map < StringName , Group > : : Element * E = group_map . find ( p_group ) ;
2014-02-10 02:10:30 +01:00
if ( ! E ) {
2017-03-05 16:44:50 +01:00
E = group_map . insert ( p_group , Group ( ) ) ;
2014-02-10 02:10:30 +01:00
}
2019-08-08 22:11:48 +02:00
ERR_FAIL_COND_V_MSG ( E - > get ( ) . nodes . find ( p_node ) ! = - 1 , & E - > get ( ) , " Already in group: " + p_group + " . " ) ;
2014-02-10 02:10:30 +01:00
E - > get ( ) . nodes . push_back ( p_node ) ;
2016-06-08 03:08:12 +02:00
//E->get().last_tree_version=0;
2017-03-05 16:44:50 +01:00
E - > get ( ) . changed = true ;
2016-06-08 03:08:12 +02:00
return & E - > get ( ) ;
2014-02-10 02:10:30 +01:00
}
2017-03-05 16:44:50 +01:00
void SceneTree : : remove_from_group ( const StringName & p_group , Node * p_node ) {
Map < StringName , Group > : : Element * E = group_map . find ( p_group ) ;
2014-02-10 02:10:30 +01:00
ERR_FAIL_COND ( ! E ) ;
E - > get ( ) . nodes . erase ( p_node ) ;
2021-05-05 12:44:11 +02:00
if ( E - > get ( ) . nodes . empty ( ) ) {
2014-02-10 02:10:30 +01:00
group_map . erase ( E ) ;
2021-05-05 12:44:11 +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 ) {
Map < StringName , Group > : : Element * E = group_map . find ( p_group ) ;
2021-05-05 12:44:11 +02:00
if ( E ) {
2018-07-02 07:30:40 +02:00
E - > get ( ) . changed = true ;
2021-05-05 12:44:11 +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 ( ) ) {
2021-05-04 14:20:36 +02:00
Map < UGCall , Vector < Variant > > : : Element * E = unique_group_calls . front ( ) ;
2014-02-10 02:10:30 +01:00
Variant v [ VARIANT_ARG_MAX ] ;
2021-05-05 12:44:11 +02:00
for ( int i = 0 ; i < E - > get ( ) . size ( ) ; i + + ) {
2017-03-05 16:44:50 +01:00
v [ i ] = E - > get ( ) [ i ] ;
2021-05-05 12:44:11 +02:00
}
2014-02-10 02:10:30 +01:00
2021-10-24 04:40:03 +02:00
static_assert ( VARIANT_ARG_MAX = = 8 , " This code needs to be updated if VARIANT_ARG_MAX != 8 " ) ;
call_group_flags ( GROUP_CALL_REALTIME , E - > key ( ) . group , E - > key ( ) . call , v [ 0 ] , v [ 1 ] , v [ 2 ] , v [ 3 ] , v [ 4 ] , v [ 5 ] , v [ 6 ] , v [ 7 ] ) ;
2014-02-10 02:10:30 +01:00
unique_group_calls . erase ( E ) ;
}
2017-03-05 16:44:50 +01:00
ugc_locked = false ;
2014-02-10 02:10:30 +01:00
}
2018-07-02 07:30:40 +02:00
void SceneTree : : _update_group_order ( Group & g , bool p_use_priority ) {
2021-05-05 12:44:11 +02:00
if ( ! g . changed ) {
2014-02-10 02:10:30 +01:00
return ;
2021-05-05 12:44:11 +02:00
}
if ( g . nodes . empty ( ) ) {
2014-02-10 02:10:30 +01:00
return ;
2021-05-05 12:44:11 +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
}
2017-03-05 16:44:50 +01:00
void SceneTree : : call_group_flags ( uint32_t p_call_flags , const StringName & p_group , const StringName & p_function , VARIANT_ARG_DECLARE ) {
Map < StringName , Group > : : Element * E = group_map . find ( p_group ) ;
2021-05-05 12:44:11 +02:00
if ( ! E ) {
2014-02-10 02:10:30 +01:00
return ;
2021-05-05 12:44:11 +02:00
}
2017-03-05 16:44:50 +01:00
Group & g = E - > get ( ) ;
2021-05-05 12:44:11 +02:00
if ( g . nodes . empty ( ) ) {
2014-02-10 02:10:30 +01:00
return ;
2021-05-05 12:44:11 +02:00
}
2014-02-10 02:10:30 +01:00
2017-03-05 16:44:50 +01:00
if ( p_call_flags & GROUP_CALL_UNIQUE & & ! ( p_call_flags & GROUP_CALL_REALTIME ) ) {
2014-02-10 02:10:30 +01:00
ERR_FAIL_COND ( ugc_locked ) ;
UGCall ug ;
2017-03-05 16:44:50 +01:00
ug . call = p_function ;
ug . group = p_group ;
2014-02-10 02:10:30 +01:00
2021-05-05 12:44:11 +02:00
if ( unique_group_calls . has ( ug ) ) {
2014-02-10 02:10:30 +01:00
return ;
2021-05-05 12:44:11 +02:00
}
2014-02-10 02:10:30 +01:00
VARIANT_ARGPTRS ;
Vector < Variant > args ;
2017-03-05 16:44:50 +01:00
for ( int i = 0 ; i < VARIANT_ARG_MAX ; i + + ) {
2021-05-05 12:44:11 +02:00
if ( argptr [ i ] - > get_type ( ) = = Variant : : NIL ) {
2014-02-10 02:10:30 +01:00
break ;
2021-05-05 12:44:11 +02:00
}
2014-02-10 02:10:30 +01:00
args . push_back ( * argptr [ i ] ) ;
}
2017-03-05 16:44:50 +01:00
unique_group_calls [ ug ] = args ;
2014-02-10 02:10:30 +01:00
return ;
}
2016-06-08 03:08:12 +02:00
_update_group_order ( g ) ;
2017-03-05 16:44:50 +01:00
Vector < Node * > nodes_copy = g . nodes ;
2018-07-25 03:11:03 +02:00
Node * * nodes = nodes_copy . ptrw ( ) ;
2017-03-05 16:44:50 +01:00
int node_count = nodes_copy . size ( ) ;
2014-02-10 02:10:30 +01:00
call_lock + + ;
2017-03-05 16:44:50 +01:00
if ( p_call_flags & GROUP_CALL_REVERSE ) {
for ( int i = node_count - 1 ; i > = 0 ; i - - ) {
2021-05-05 12:44:11 +02:00
if ( call_lock & & call_skip . has ( nodes [ i ] ) ) {
2014-02-10 02:10:30 +01:00
continue ;
2021-05-05 12:44:11 +02:00
}
2014-02-10 02:10:30 +01:00
2017-03-05 16:44:50 +01:00
if ( p_call_flags & GROUP_CALL_REALTIME ) {
2021-05-05 12:44:11 +02:00
if ( p_call_flags & GROUP_CALL_MULTILEVEL ) {
2017-03-05 16:44:50 +01:00
nodes [ i ] - > call_multilevel ( p_function , VARIANT_ARG_PASS ) ;
2021-05-05 12:44:11 +02:00
} else {
2017-03-05 16:44:50 +01:00
nodes [ i ] - > call ( p_function , VARIANT_ARG_PASS ) ;
2021-05-05 12:44:11 +02:00
}
} else {
2017-03-05 16:44:50 +01:00
MessageQueue : : get_singleton ( ) - > push_call ( nodes [ i ] , p_function , VARIANT_ARG_PASS ) ;
2021-05-05 12:44:11 +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 + + ) {
2021-05-05 12:44:11 +02:00
if ( call_lock & & call_skip . has ( nodes [ i ] ) ) {
2014-02-10 02:10:30 +01:00
continue ;
2021-05-05 12:44:11 +02:00
}
2014-02-10 02:10:30 +01:00
2017-03-05 16:44:50 +01:00
if ( p_call_flags & GROUP_CALL_REALTIME ) {
2021-05-05 12:44:11 +02:00
if ( p_call_flags & GROUP_CALL_MULTILEVEL ) {
2017-03-05 16:44:50 +01:00
nodes [ i ] - > call_multilevel ( p_function , VARIANT_ARG_PASS ) ;
2021-05-05 12:44:11 +02:00
} else {
2017-03-05 16:44:50 +01:00
nodes [ i ] - > call ( p_function , VARIANT_ARG_PASS ) ;
2021-05-05 12:44:11 +02:00
}
} else {
2017-03-05 16:44:50 +01:00
MessageQueue : : get_singleton ( ) - > push_call ( nodes [ i ] , p_function , VARIANT_ARG_PASS ) ;
2021-05-05 12:44:11 +02:00
}
2014-02-10 02:10:30 +01:00
}
}
call_lock - - ;
2021-05-05 12:44:11 +02:00
if ( call_lock = = 0 ) {
2014-02-10 02:10:30 +01:00
call_skip . clear ( ) ;
2021-05-05 12:44:11 +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 ) {
Map < StringName , Group > : : Element * E = group_map . find ( p_group ) ;
2021-05-05 12:44:11 +02:00
if ( ! E ) {
2014-02-10 02:10:30 +01:00
return ;
2021-05-05 12:44:11 +02:00
}
2017-03-05 16:44:50 +01:00
Group & g = E - > get ( ) ;
2021-05-05 12:44:11 +02:00
if ( g . nodes . empty ( ) ) {
2014-02-10 02:10:30 +01:00
return ;
2021-05-05 12:44:11 +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 - - ) {
2021-05-05 12:44:11 +02:00
if ( call_lock & & call_skip . has ( nodes [ i ] ) ) {
2014-02-10 02:10:30 +01:00
continue ;
2021-05-05 12:44:11 +02:00
}
2014-02-10 02:10:30 +01:00
2021-05-05 12:44:11 +02:00
if ( p_call_flags & GROUP_CALL_REALTIME ) {
2014-02-10 02:10:30 +01:00
nodes [ i ] - > notification ( p_notification ) ;
2021-05-05 12:44:11 +02:00
} else {
2017-03-05 16:44:50 +01:00
MessageQueue : : get_singleton ( ) - > push_notification ( nodes [ i ] , p_notification ) ;
2021-05-05 12:44:11 +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 + + ) {
2021-05-05 12:44:11 +02:00
if ( call_lock & & call_skip . has ( nodes [ i ] ) ) {
2014-02-10 02:10:30 +01:00
continue ;
2021-05-05 12:44:11 +02:00
}
2014-02-10 02:10:30 +01:00
2021-05-05 12:44:11 +02:00
if ( p_call_flags & GROUP_CALL_REALTIME ) {
2014-02-10 02:10:30 +01:00
nodes [ i ] - > notification ( p_notification ) ;
2021-05-05 12:44:11 +02:00
} else {
2017-03-05 16:44:50 +01:00
MessageQueue : : get_singleton ( ) - > push_notification ( nodes [ i ] , p_notification ) ;
2021-05-05 12:44:11 +02:00
}
2014-02-10 02:10:30 +01:00
}
}
call_lock - - ;
2021-05-05 12:44:11 +02:00
if ( call_lock = = 0 ) {
2014-02-10 02:10:30 +01:00
call_skip . clear ( ) ;
2021-05-05 12:44:11 +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 ) {
Map < StringName , Group > : : Element * E = group_map . find ( p_group ) ;
2021-05-05 12:44:11 +02:00
if ( ! E ) {
2014-02-10 02:10:30 +01:00
return ;
2021-05-05 12:44:11 +02:00
}
2017-03-05 16:44:50 +01:00
Group & g = E - > get ( ) ;
2021-05-05 12:44:11 +02:00
if ( g . nodes . empty ( ) ) {
2014-02-10 02:10:30 +01:00
return ;
2021-05-05 12:44:11 +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 - - ) {
2021-05-05 12:44:11 +02:00
if ( call_lock & & call_skip . has ( nodes [ i ] ) ) {
2014-02-10 02:10:30 +01:00
continue ;
2021-05-05 12:44:11 +02:00
}
2014-02-10 02:10:30 +01:00
2021-05-05 12:44:11 +02:00
if ( p_call_flags & GROUP_CALL_REALTIME ) {
2017-03-05 16:44:50 +01:00
nodes [ i ] - > set ( p_name , p_value ) ;
2021-05-05 12:44:11 +02:00
} else {
2017-03-05 16:44:50 +01:00
MessageQueue : : get_singleton ( ) - > push_set ( nodes [ i ] , p_name , p_value ) ;
2021-05-05 12:44:11 +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 + + ) {
2021-05-05 12:44:11 +02:00
if ( call_lock & & call_skip . has ( nodes [ i ] ) ) {
2014-02-10 02:10:30 +01:00
continue ;
2021-05-05 12:44:11 +02:00
}
2014-02-10 02:10:30 +01:00
2021-05-05 12:44:11 +02:00
if ( p_call_flags & GROUP_CALL_REALTIME ) {
2017-03-05 16:44:50 +01:00
nodes [ i ] - > set ( p_name , p_value ) ;
2021-05-05 12:44:11 +02:00
} else {
2017-03-05 16:44:50 +01:00
MessageQueue : : get_singleton ( ) - > push_set ( nodes [ i ] , p_name , p_value ) ;
2021-05-05 12:44:11 +02:00
}
2014-02-10 02:10:30 +01:00
}
}
call_lock - - ;
2021-05-05 12:44:11 +02:00
if ( call_lock = = 0 ) {
2014-02-10 02:10:30 +01:00
call_skip . clear ( ) ;
2021-05-05 12:44:11 +02:00
}
2014-02-10 02:10:30 +01:00
}
2017-03-05 16:44:50 +01:00
void SceneTree : : call_group ( const StringName & p_group , const StringName & p_function , VARIANT_ARG_DECLARE ) {
2019-04-07 06:19:52 +02:00
call_group_flags ( 0 , p_group , p_function , VARIANT_ARG_PASS ) ;
2017-01-14 14:03:53 +01:00
}
2017-03-05 16:44:50 +01:00
void SceneTree : : notify_group ( const StringName & p_group , int p_notification ) {
notify_group_flags ( 0 , p_group , p_notification ) ;
2017-01-14 14:03:53 +01:00
}
2017-03-05 16:44:50 +01:00
void SceneTree : : set_group ( const StringName & p_group , const String & p_name , const Variant & p_value ) {
set_group_flags ( 0 , p_group , p_name , p_value ) ;
2017-01-14 14:03:53 +01:00
}
2014-11-06 01:20:42 +01:00
void SceneTree : : set_input_as_handled ( ) {
2017-03-05 16:44:50 +01:00
input_handled = true ;
2014-02-10 02:10:30 +01:00
}
2017-03-05 16:44:50 +01:00
void SceneTree : : input_text ( const String & p_text ) {
2014-02-10 02:10:30 +01:00
root_lock + + ;
2017-03-05 16:44:50 +01:00
call_group_flags ( GROUP_CALL_REALTIME , " _viewports " , " _vp_input_text " , p_text ) ; //special one for GUI, as controls use their own process check
2016-01-17 02:41:10 +01:00
2014-02-10 02:10:30 +01:00
root_lock - - ;
}
2017-03-16 17:52:50 +01:00
bool SceneTree : : is_input_handled ( ) {
return input_handled ;
}
2017-05-20 17:38:03 +02:00
void SceneTree : : input_event ( const Ref < InputEvent > & p_event ) {
2021-05-05 12:44:11 +02:00
if ( Engine : : get_singleton ( ) - > is_editor_hint ( ) & & ( Object : : cast_to < InputEventJoypadButton > ( p_event . ptr ( ) ) | | Object : : cast_to < InputEventJoypadMotion > ( * p_event ) ) ) {
2014-12-07 06:04:20 +01:00
return ; //avoid joy input on editor
2021-05-05 12:44:11 +02:00
}
2014-12-07 06:04:20 +01:00
2017-12-26 13:48:50 +01:00
current_event + + ;
2014-02-10 02:10:30 +01:00
root_lock + + ;
2017-03-05 16:44:50 +01:00
input_handled = false ;
2014-02-10 02:10:30 +01:00
2020-01-17 12:47:23 +01:00
// Don't make const ref unless you can find and fix what caused GH-34691.
Ref < InputEvent > ev = p_event ;
2014-02-10 02:10:30 +01:00
2014-11-06 01:20:42 +01:00
MainLoop : : input_event ( ev ) ;
2014-04-10 05:18:27 +02:00
2017-03-05 16:44:50 +01:00
call_group_flags ( GROUP_CALL_REALTIME , " _viewports " , " _vp_input " , ev ) ; //special one for GUI, as controls use their own process check
2014-02-10 02:10:30 +01:00
2017-05-20 17:38:03 +02:00
if ( ScriptDebugger : : get_singleton ( ) & & ScriptDebugger : : get_singleton ( ) - > is_remote ( ) ) {
//quit from game window using F8
Ref < InputEventKey > k = ev ;
if ( k . is_valid ( ) & & k - > is_pressed ( ) & & ! k - > is_echo ( ) & & k - > get_scancode ( ) = = KEY_F8 ) {
ScriptDebugger : : get_singleton ( ) - > request_quit ( ) ;
}
2014-02-10 02:10:30 +01:00
}
2016-03-09 00:00:52 +01:00
_flush_ugc ( ) ;
2014-02-10 02:10:30 +01:00
root_lock - - ;
2017-08-19 04:01:27 +02:00
//MessageQueue::get_singleton()->flush(); //flushing here causes UI and other places slowness
2014-02-10 02:10:30 +01:00
root_lock + + ;
if ( ! input_handled ) {
2017-03-05 16:44:50 +01:00
call_group_flags ( GROUP_CALL_REALTIME , " _viewports " , " _vp_unhandled_input " , ev ) ; //special one for GUI, as controls use their own process check
2014-02-10 02:10:30 +01:00
_flush_ugc ( ) ;
2017-12-04 21:35:58 +01:00
// input_handled = true; - no reason to set this as handled
2014-02-10 02:10:30 +01:00
root_lock - - ;
2017-08-19 04:01:27 +02:00
//MessageQueue::get_singleton()->flush(); //flushing here causes UI and other places slowness
2014-02-10 02:10:30 +01:00
} else {
2017-12-04 21:35:58 +01:00
// input_handled = true; - no reason to set this as handled
2014-02-10 02:10:30 +01:00
root_lock - - ;
}
2016-10-27 16:50:26 +02:00
_call_idle_callbacks ( ) ;
2014-02-10 02:10:30 +01:00
}
2014-11-06 01:20:42 +01:00
void SceneTree : : init ( ) {
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 ) ;
2014-02-10 02:10:30 +01:00
MainLoop : : init ( ) ;
}
2021-09-15 13:30:45 +02:00
void SceneTree : : set_physics_interpolation_enabled ( bool p_enabled ) {
// disallow interpolation in editor
if ( Engine : : get_singleton ( ) - > is_editor_hint ( ) ) {
p_enabled = false ;
}
if ( p_enabled = = _physics_interpolation_enabled ) {
return ;
}
_physics_interpolation_enabled = p_enabled ;
if ( root - > get_world ( ) . is_valid ( ) ) {
RID scenario = root - > get_world ( ) - > get_scenario ( ) ;
if ( scenario . is_valid ( ) ) {
VisualServer : : get_singleton ( ) - > scenario_set_physics_interpolation_enabled ( scenario , p_enabled ) ;
}
}
}
bool SceneTree : : is_physics_interpolation_enabled ( ) const {
return _physics_interpolation_enabled ;
}
2022-02-21 08:34:42 +01:00
void SceneTree : : client_physics_interpolation_add_spatial ( SelfList < Spatial > * p_elem ) {
// This ensures that _update_physics_interpolation_data() will be called at least once every
// physics tick, to ensure the previous and current transforms are kept up to date.
_client_physics_interpolation . _spatials_list . add ( p_elem ) ;
}
void SceneTree : : client_physics_interpolation_remove_spatial ( SelfList < Spatial > * p_elem ) {
_client_physics_interpolation . _spatials_list . remove ( p_elem ) ;
}
2014-11-06 01:20:42 +01:00
bool SceneTree : : iteration ( float p_time ) {
2014-02-10 02:10:30 +01:00
root_lock + + ;
current_frame + + ;
2021-09-15 13:30:45 +02:00
if ( root - > get_world ( ) . is_valid ( ) ) {
RID scenario = root - > get_world ( ) - > get_scenario ( ) ;
if ( scenario . is_valid ( ) ) {
VisualServer : : get_singleton ( ) - > scenario_tick ( scenario ) ;
}
}
2022-02-21 08:34:42 +01:00
// Any objects performing client physics interpolation
// should be given an opportunity to keep their previous transforms
// up to take before each new physics tick.
_client_physics_interpolation . physics_process ( ) ;
2017-10-30 19:43:19 +01:00
flush_transform_notifications ( ) ;
2014-02-10 02:10:30 +01:00
MainLoop : : iteration ( p_time ) ;
2017-09-30 16:19:07 +02:00
physics_process_time = p_time ;
2014-09-15 16:33:30 +02:00
2017-09-30 16:19:07 +02:00
emit_signal ( " physics_frame " ) ;
2014-09-15 16:33:30 +02:00
2017-09-30 16:19:07 +02:00
_notify_group_pause ( " physics_process_internal " , Node : : NOTIFICATION_INTERNAL_PHYSICS_PROCESS ) ;
2021-02-06 20:57:00 +01:00
if ( GLOBAL_GET ( " physics/common/enable_pause_aware_picking " ) ) {
call_group_flags ( GROUP_CALL_REALTIME , " _viewports " , " _process_picking " , true ) ;
}
2017-09-30 16:19:07 +02:00
_notify_group_pause ( " physics_process " , Node : : NOTIFICATION_PHYSICS_PROCESS ) ;
2014-02-10 02:10:30 +01:00
_flush_ugc ( ) ;
2017-08-08 03:18:12 +02:00
MessageQueue : : get_singleton ( ) - > flush ( ) ; //small little hack
2017-10-30 19:43:19 +01:00
flush_transform_notifications ( ) ;
2017-03-05 16:44:50 +01:00
call_group_flags ( GROUP_CALL_REALTIME , " _viewports " , " update_worlds " ) ;
2014-02-10 02:10:30 +01:00
root_lock - - ;
_flush_delete_queue ( ) ;
2016-10-27 16:50:26 +02:00
_call_idle_callbacks ( ) ;
2014-02-10 02:10:30 +01:00
return _quit ;
}
2019-01-26 18:56:22 +01:00
void SceneTree : : _update_font_oversampling ( float p_ratio ) {
2021-07-30 04:47:16 +02:00
# ifdef MODULE_FREETYPE_ENABLED
2019-01-26 18:56:22 +01:00
if ( use_font_oversampling ) {
DynamicFontAtSize : : font_oversampling = p_ratio ;
DynamicFont : : update_oversampling ( ) ;
}
2021-07-30 04:47:16 +02:00
# endif // MODULE_FREETYPE_ENABLED
2019-01-26 18:56:22 +01:00
}
2017-03-05 16:44:50 +01:00
bool SceneTree : : idle ( float p_time ) {
2017-01-14 12:26:56 +01:00
//print_line("ram: "+itos(OS::get_singleton()->get_static_memory_usage())+" sram: "+itos(OS::get_singleton()->get_dynamic_memory_usage()));
//print_line("node count: "+itos(get_node_count()));
//print_line("TEXTURE RAM: "+itos(VS::get_singleton()->get_render_info(VS::INFO_TEXTURE_MEM_USED)));
2014-02-10 02:10:30 +01:00
root_lock + + ;
MainLoop : : idle ( p_time ) ;
2017-03-05 16:44:50 +01:00
idle_process_time = p_time ;
2014-02-10 02:10:30 +01:00
2018-06-02 14:32:30 +02:00
if ( multiplayer_poll ) {
multiplayer - > poll ( ) ;
}
2016-08-14 23:49:50 +02:00
2014-09-15 16:33:30 +02:00
emit_signal ( " idle_frame " ) ;
2017-08-08 03:18:12 +02:00
MessageQueue : : get_singleton ( ) - > flush ( ) ; //small little hack
2017-10-30 19:43:19 +01:00
flush_transform_notifications ( ) ;
2014-02-10 02:10:30 +01:00
2017-03-05 16:44:50 +01:00
_notify_group_pause ( " idle_process_internal " , Node : : NOTIFICATION_INTERNAL_PROCESS ) ;
_notify_group_pause ( " idle_process " , Node : : NOTIFICATION_PROCESS ) ;
2014-02-10 02:10:30 +01:00
2022-01-28 23:02:48 +01:00
Size2 win_size = OS : : get_singleton ( ) - > get_window_size ( ) ;
2018-07-03 23:52:23 +02:00
2017-03-05 16:44:50 +01:00
if ( win_size ! = last_screen_size ) {
2018-03-19 14:44:26 +01:00
last_screen_size = win_size ;
_update_root_rect ( ) ;
2014-02-10 02:10:30 +01:00
emit_signal ( " screen_resized " ) ;
}
_flush_ugc ( ) ;
2017-08-08 03:18:12 +02:00
MessageQueue : : get_singleton ( ) - > flush ( ) ; //small little hack
2017-10-30 19:43:19 +01:00
flush_transform_notifications ( ) ; //transforms after world update, to avoid unnecessary enter/exit notifications
2017-03-05 16:44:50 +01:00
call_group_flags ( GROUP_CALL_REALTIME , " _viewports " , " update_worlds " ) ;
2014-02-10 02:10:30 +01:00
root_lock - - ;
_flush_delete_queue ( ) ;
2016-08-07 02:39:50 +02:00
//go through timers
2021-05-04 14:20:36 +02:00
List < Ref < SceneTreeTimer > > : : Element * L = timers . back ( ) ; //last element
2018-11-14 00:11:22 +01:00
2021-05-04 14:20:36 +02:00
for ( List < Ref < SceneTreeTimer > > : : Element * E = timers . front ( ) ; E ; ) {
List < Ref < SceneTreeTimer > > : : Element * N = E - > next ( ) ;
2017-02-14 00:34:33 +01:00
if ( pause & & ! E - > get ( ) - > is_pause_mode_process ( ) ) {
2018-11-14 00:11:22 +01:00
if ( E = = L ) {
break ; //break on last, so if new timers were added during list traversal, ignore them.
}
2017-03-05 16:44:50 +01:00
E = N ;
2017-02-14 00:34:33 +01:00
continue ;
}
2021-11-22 12:54:05 +01:00
2016-08-07 02:39:50 +02:00
float time_left = E - > get ( ) - > get_time_left ( ) ;
2021-11-22 12:54:05 +01:00
if ( E - > get ( ) - > is_ignore_time_scale ( ) ) {
time_left - = Engine : : get_singleton ( ) - > get_idle_frame_step ( ) ;
} else {
time_left - = p_time ;
}
2016-08-07 02:39:50 +02:00
E - > get ( ) - > set_time_left ( time_left ) ;
2017-03-05 16:44:50 +01:00
if ( time_left < 0 ) {
2016-08-07 02:39:50 +02:00
E - > get ( ) - > emit_signal ( " timeout " ) ;
timers . erase ( E ) ;
}
2018-11-14 00:11:22 +01:00
if ( E = = L ) {
break ; //break on last, so if new timers were added during list traversal, ignore them.
}
2017-03-05 16:44:50 +01:00
E = N ;
2016-08-07 02:39:50 +02:00
}
2019-07-29 12:33:38 +02:00
flush_transform_notifications ( ) ; //additional transforms after timers update
2016-10-27 16:50:26 +02:00
_call_idle_callbacks ( ) ;
2021-10-01 12:47:28 +02:00
ProjectSettings : : get_singleton ( ) - > update ( ) ;
2017-05-29 02:46:48 +02:00
# ifdef TOOLS_ENABLED
2017-08-19 01:02:56 +02:00
if ( Engine : : get_singleton ( ) - > is_editor_hint ( ) ) {
2017-05-29 02:46:48 +02:00
//simple hack to reload fallback environment if it changed from editor
2017-07-19 22:00:46 +02:00
String env_path = ProjectSettings : : get_singleton ( ) - > get ( " rendering/environment/default_environment " ) ;
2017-05-29 02:46:48 +02:00
env_path = env_path . strip_edges ( ) ; //user may have added a space or two
String cpath ;
Ref < Environment > fallback = get_root ( ) - > get_world ( ) - > get_fallback_environment ( ) ;
if ( fallback . is_valid ( ) ) {
cpath = fallback - > get_path ( ) ;
}
if ( cpath ! = env_path ) {
if ( env_path ! = String ( ) ) {
fallback = ResourceLoader : : load ( env_path ) ;
2017-08-31 13:55:20 +02:00
if ( fallback . is_null ( ) ) {
//could not load fallback, set as empty
ProjectSettings : : get_singleton ( ) - > set ( " rendering/environment/default_environment " , " " ) ;
}
2017-05-29 02:46:48 +02:00
} else {
fallback . unref ( ) ;
}
get_root ( ) - > get_world ( ) - > set_fallback_environment ( fallback ) ;
}
}
# endif
2021-09-15 13:30:45 +02:00
if ( root - > get_world ( ) . is_valid ( ) ) {
RID scenario = root - > get_world ( ) - > get_scenario ( ) ;
if ( scenario . is_valid ( ) ) {
VisualServer : : get_singleton ( ) - > scenario_pre_draw ( scenario , true ) ;
}
}
2014-02-10 02:10:30 +01:00
return _quit ;
}
2014-11-06 01:20:42 +01:00
void SceneTree : : finish ( ) {
2014-02-10 02:10:30 +01:00
_flush_delete_queue ( ) ;
_flush_ugc ( ) ;
2017-03-05 16:44:50 +01:00
initialized = false ;
2014-02-10 02:10:30 +01:00
MainLoop : : finish ( ) ;
if ( root ) {
2021-05-04 16:00:45 +02:00
root - > _set_tree ( nullptr ) ;
2022-03-12 12:48:15 +01:00
root - > _propagate_after_exit_branch ( true ) ;
2014-02-10 02:10:30 +01:00
memdelete ( root ) ; //delete root
2021-05-04 16:00:45 +02:00
root = nullptr ;
2014-02-10 02:10:30 +01:00
}
2019-10-19 18:45:17 +02:00
2021-10-08 16:38:38 +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-05-04 14:20:36 +02:00
for ( List < Ref < SceneTreeTimer > > : : Element * E = timers . front ( ) ; E ; E = E - > next ( ) ) {
2019-10-19 18:45:17 +02:00
E - > get ( ) - > release_connections ( ) ;
}
timers . clear ( ) ;
2014-02-10 02:10:30 +01:00
}
2019-12-29 16:39:24 +01:00
void SceneTree : : quit ( int p_exit_code ) {
if ( p_exit_code > = 0 ) {
// Override the exit code if a positive argument is given (the default is `-1`).
// This is a shorthand for calling `set_exit_code()` on the OS singleton then quitting.
OS : : get_singleton ( ) - > set_exit_code ( p_exit_code ) ;
2020-05-21 18:08:48 +02:00
} else if ( ! OS : : get_singleton ( ) - > is_custom_exit_code ( ) ) {
// Must customize exit code, otherwise it will default to a non-zero value
OS : : get_singleton ( ) - > set_exit_code ( EXIT_SUCCESS ) ;
2019-12-29 16:39:24 +01:00
}
2014-02-10 02:10:30 +01:00
2017-03-05 16:44:50 +01:00
_quit = true ;
2014-02-10 02:10:30 +01:00
}
2014-11-06 01:20:42 +01:00
void SceneTree : : _notification ( int p_notification ) {
2014-02-10 02:10:30 +01:00
switch ( p_notification ) {
case NOTIFICATION_WM_QUIT_REQUEST : {
get_root ( ) - > propagate_notification ( p_notification ) ;
if ( accept_quit ) {
2017-03-05 16:44:50 +01:00
_quit = true ;
2014-02-10 02:10:30 +01:00
break ;
}
} break ;
2019-09-09 23:42:17 +02:00
2017-01-11 20:34:32 +01:00
case NOTIFICATION_WM_GO_BACK_REQUEST : {
get_root ( ) - > propagate_notification ( p_notification ) ;
if ( quit_on_go_back ) {
2017-03-05 16:44:50 +01:00
_quit = true ;
2017-01-11 20:34:32 +01:00
break ;
}
} break ;
2014-02-10 02:10:30 +01:00
2019-09-09 23:42:17 +02:00
case NOTIFICATION_WM_FOCUS_IN : {
InputDefault * id = Object : : cast_to < InputDefault > ( Input : : get_singleton ( ) ) ;
if ( id ) {
id - > ensure_touch_mouse_raised ( ) ;
2018-02-24 03:04:30 +01:00
}
2014-02-10 02:10:30 +01:00
get_root ( ) - > propagate_notification ( p_notification ) ;
} break ;
2019-09-09 23:42:17 +02:00
2017-01-09 20:43:44 +01:00
case NOTIFICATION_TRANSLATION_CHANGED : {
2017-08-19 01:02:56 +02:00
if ( ! Engine : : get_singleton ( ) - > is_editor_hint ( ) ) {
2019-04-04 15:34:03 +02:00
get_root ( ) - > propagate_notification ( p_notification ) ;
2017-06-28 22:00:18 +02:00
}
2017-01-09 20:43:44 +01:00
} break ;
2019-09-09 23:42:17 +02:00
2014-02-10 02:10:30 +01:00
case NOTIFICATION_WM_UNFOCUS_REQUEST : {
2017-03-05 16:44:50 +01:00
notify_group_flags ( GROUP_CALL_REALTIME | GROUP_CALL_MULTILEVEL , " input " , NOTIFICATION_WM_UNFOCUS_REQUEST ) ;
2014-02-10 02:10:30 +01:00
2019-04-04 15:34:03 +02:00
get_root ( ) - > propagate_notification ( p_notification ) ;
2014-02-10 02:10:30 +01:00
} break ;
2019-09-09 23:42:17 +02:00
case NOTIFICATION_OS_MEMORY_WARNING :
case NOTIFICATION_OS_IME_UPDATE :
case NOTIFICATION_WM_MOUSE_ENTER :
case NOTIFICATION_WM_MOUSE_EXIT :
case NOTIFICATION_WM_FOCUS_OUT :
case NOTIFICATION_WM_ABOUT :
case NOTIFICATION_CRASH :
case NOTIFICATION_APP_RESUMED :
case NOTIFICATION_APP_PAUSED : {
2018-07-02 21:18:58 +02:00
get_root ( ) - > propagate_notification ( p_notification ) ;
} break ;
2014-02-10 02:10:30 +01:00
default :
break ;
} ;
} ;
2014-11-06 01:20:42 +01:00
void SceneTree : : set_auto_accept_quit ( bool p_enable ) {
2017-03-05 16:44:50 +01:00
accept_quit = p_enable ;
2014-02-10 02:10:30 +01:00
}
2017-01-11 20:34:32 +01:00
void SceneTree : : set_quit_on_go_back ( bool p_enable ) {
2017-03-05 16:44:50 +01:00
quit_on_go_back = p_enable ;
2017-01-11 20:34:32 +01:00
}
2017-04-07 16:17:16 +02:00
# ifdef TOOLS_ENABLED
2014-02-10 02:10:30 +01:00
2017-03-05 16:44:50 +01:00
bool SceneTree : : is_node_being_edited ( const Node * p_node ) const {
2017-09-24 17:10:17 +02:00
return Engine : : get_singleton ( ) - > is_editor_hint ( ) & & edited_scene_root & & ( edited_scene_root - > is_a_parent_of ( p_node ) | | edited_scene_root = = p_node ) ;
2014-02-10 02:10:30 +01:00
}
2017-04-07 16:17:16 +02:00
# endif
2014-02-10 02:10:30 +01:00
2017-04-07 16:17:16 +02:00
# ifdef DEBUG_ENABLED
2015-09-19 04:10:58 +02:00
void SceneTree : : set_debug_collisions_hint ( bool p_enabled ) {
2017-03-05 16:44:50 +01:00
debug_collisions_hint = p_enabled ;
2015-09-19 04:10:58 +02:00
}
bool SceneTree : : is_debugging_collisions_hint ( ) const {
return debug_collisions_hint ;
}
2015-09-20 18:03:46 +02:00
void SceneTree : : set_debug_navigation_hint ( bool p_enabled ) {
2017-03-05 16:44:50 +01:00
debug_navigation_hint = p_enabled ;
2015-09-20 18:03:46 +02:00
}
bool SceneTree : : is_debugging_navigation_hint ( ) const {
return debug_navigation_hint ;
}
2017-04-07 16:17:16 +02:00
# endif
2015-09-20 18:03:46 +02:00
2017-03-05 16:44:50 +01:00
void SceneTree : : set_debug_collisions_color ( const Color & p_color ) {
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 ;
}
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 ;
}
Ref < Material > SceneTree : : get_debug_navigation_material ( ) {
2021-05-05 12:44:11 +02:00
if ( navigation_material . is_valid ( ) ) {
2015-09-20 18:03:46 +02:00
return navigation_material ;
2021-05-05 12:44:11 +02:00
}
2015-09-20 18:03:46 +02:00
2017-04-07 04:36:37 +02:00
Ref < SpatialMaterial > line_material = Ref < SpatialMaterial > ( memnew ( SpatialMaterial ) ) ;
2017-08-15 22:21:05 +02:00
line_material - > set_flag ( SpatialMaterial : : FLAG_UNSHADED , true ) ;
line_material - > set_feature ( SpatialMaterial : : FEATURE_TRANSPARENT , true ) ;
line_material - > set_flag ( SpatialMaterial : : FLAG_SRGB_VERTEX_COLOR , true ) ;
line_material - > set_flag ( SpatialMaterial : : FLAG_ALBEDO_FROM_VERTEX_COLOR , true ) ;
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 ( ) {
2021-05-05 12:44:11 +02:00
if ( navigation_disabled_material . is_valid ( ) ) {
2015-09-20 18:03:46 +02:00
return navigation_disabled_material ;
2021-05-05 12:44:11 +02:00
}
2015-09-20 18:03:46 +02:00
2017-04-07 04:36:37 +02:00
Ref < SpatialMaterial > line_material = Ref < SpatialMaterial > ( memnew ( SpatialMaterial ) ) ;
2017-08-15 22:21:05 +02:00
line_material - > set_flag ( SpatialMaterial : : FLAG_UNSHADED , true ) ;
line_material - > set_feature ( SpatialMaterial : : FEATURE_TRANSPARENT , true ) ;
line_material - > set_flag ( SpatialMaterial : : FLAG_SRGB_VERTEX_COLOR , true ) ;
line_material - > set_flag ( SpatialMaterial : : FLAG_ALBEDO_FROM_VERTEX_COLOR , true ) ;
line_material - > set_albedo ( get_debug_navigation_disabled_color ( ) ) ;
2015-09-20 18:03:46 +02:00
2017-03-05 16:44:50 +01:00
navigation_disabled_material = line_material ;
2015-09-20 18:03:46 +02:00
return navigation_disabled_material ;
}
Ref < Material > SceneTree : : get_debug_collision_material ( ) {
2021-05-05 12:44:11 +02:00
if ( collision_material . is_valid ( ) ) {
2015-09-20 18:03:46 +02:00
return collision_material ;
2021-05-05 12:44:11 +02:00
}
2015-09-20 18:03:46 +02:00
2017-04-07 04:36:37 +02:00
Ref < SpatialMaterial > line_material = Ref < SpatialMaterial > ( memnew ( SpatialMaterial ) ) ;
2017-08-15 22:21:05 +02:00
line_material - > set_flag ( SpatialMaterial : : FLAG_UNSHADED , true ) ;
line_material - > set_feature ( SpatialMaterial : : FEATURE_TRANSPARENT , true ) ;
line_material - > set_flag ( SpatialMaterial : : FLAG_SRGB_VERTEX_COLOR , true ) ;
line_material - > set_flag ( SpatialMaterial : : FLAG_ALBEDO_FROM_VERTEX_COLOR , true ) ;
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 ( ) {
2021-05-05 12:44:11 +02:00
if ( debug_contact_mesh . is_valid ( ) ) {
2015-09-20 18:03:46 +02:00
return debug_contact_mesh ;
2021-05-05 12:44:11 +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
2017-08-15 22:21:05 +02:00
Ref < SpatialMaterial > mat = Ref < SpatialMaterial > ( memnew ( SpatialMaterial ) ) ;
mat - > set_flag ( SpatialMaterial : : FLAG_UNSHADED , true ) ;
mat - > set_feature ( SpatialMaterial : : FEATURE_TRANSPARENT , true ) ;
mat - > set_flag ( SpatialMaterial : : FLAG_SRGB_VERTEX_COLOR , true ) ;
mat - > set_flag ( SpatialMaterial : : FLAG_ALBEDO_FROM_VERTEX_COLOR , true ) ;
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
2017-01-07 22:25:37 +01:00
PoolVector < int > indices ;
2021-05-05 12:44:11 +02:00
for ( int i = 0 ; i < 8 * 3 ; i + + ) {
2015-09-20 18:03:46 +02:00
indices . push_back ( diamond_faces [ i ] ) ;
2021-05-05 12:44:11 +02:00
}
2015-09-20 18:03:46 +02:00
2017-01-07 22:25:37 +01:00
PoolVector < Vector3 > vertices ;
2021-05-05 12:44:11 +02:00
for ( int i = 0 ; i < 6 ; i + + ) {
2017-03-05 16:44:50 +01:00
vertices . push_back ( diamond [ i ] * 0.1 ) ;
2021-05-05 12:44:11 +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-05-05 12:44:11 +02:00
if ( p_enabled = = pause ) {
2014-02-10 02:10:30 +01:00
return ;
2021-05-05 12:44:11 +02:00
}
2017-03-05 16:44:50 +01:00
pause = p_enabled ;
2021-12-16 06:15:23 +01:00
NavigationServer : : get_singleton ( ) - > set_active ( ! p_enabled ) ;
2014-02-10 02:10:30 +01:00
PhysicsServer : : get_singleton ( ) - > set_active ( ! p_enabled ) ;
Physics2DServer : : get_singleton ( ) - > set_active ( ! p_enabled ) ;
2021-05-05 12:44:11 +02:00
if ( get_root ( ) ) {
2014-02-10 02:10:30 +01:00
get_root ( ) - > propagate_notification ( p_enabled ? Node : : NOTIFICATION_PAUSED : Node : : NOTIFICATION_UNPAUSED ) ;
2021-05-05 12:44:11 +02:00
}
2014-02-10 02:10:30 +01:00
}
2014-11-06 01:20:42 +01:00
bool SceneTree : : is_paused ( ) const {
2014-02-10 02:10:30 +01:00
return pause ;
}
2017-05-20 17:38:03 +02:00
void SceneTree : : _call_input_pause ( const StringName & p_group , const StringName & p_method , const Ref < InputEvent > & p_input ) {
2017-03-05 16:44:50 +01:00
Map < StringName , Group > : : Element * E = group_map . find ( p_group ) ;
2021-05-05 12:44:11 +02:00
if ( ! E ) {
2014-02-10 02:10:30 +01:00
return ;
2021-05-05 12:44:11 +02:00
}
2017-03-05 16:44:50 +01:00
Group & g = E - > get ( ) ;
2021-05-05 12:44:11 +02:00
if ( g . nodes . empty ( ) ) {
2014-02-10 02:10:30 +01:00
return ;
2021-05-05 12:44:11 +02:00
}
2014-02-10 02:10:30 +01:00
_update_group_order ( g ) ;
//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
2017-03-05 16:44:50 +01:00
Variant arg = p_input ;
const Variant * v [ 1 ] = { & arg } ;
2014-02-10 02:10:30 +01:00
call_lock + + ;
2017-03-05 16:44:50 +01:00
for ( int i = node_count - 1 ; i > = 0 ; i - - ) {
2021-05-05 12:44:11 +02:00
if ( input_handled ) {
2014-02-10 02:10:30 +01:00
break ;
2021-05-05 12:44:11 +02:00
}
2014-02-10 02:10:30 +01:00
Node * n = nodes [ i ] ;
2021-05-05 12:44:11 +02:00
if ( call_lock & & call_skip . has ( n ) ) {
2014-02-10 02:10:30 +01:00
continue ;
2021-05-05 12:44:11 +02:00
}
2014-02-10 02:10:30 +01:00
2021-05-05 12:44:11 +02:00
if ( ! n - > can_process ( ) ) {
2014-02-10 02:10:30 +01:00
continue ;
2021-05-05 12:44:11 +02:00
}
2014-02-10 02:10:30 +01:00
2017-03-05 16:44:50 +01:00
n - > call_multilevel ( p_method , ( const Variant * * ) v , 1 ) ;
2014-02-10 02:10:30 +01:00
//ERR_FAIL_COND(node_count != g.nodes.size());
}
call_lock - - ;
2021-05-05 12:44:11 +02:00
if ( call_lock = = 0 ) {
2014-02-10 02:10:30 +01:00
call_skip . clear ( ) ;
2021-05-05 12:44:11 +02:00
}
2014-02-10 02:10:30 +01:00
}
2017-03-05 16:44:50 +01:00
void SceneTree : : _notify_group_pause ( const StringName & p_group , int p_notification ) {
Map < StringName , Group > : : Element * E = group_map . find ( p_group ) ;
2021-05-05 12:44:11 +02:00
if ( ! E ) {
2014-02-10 02:10:30 +01:00
return ;
2021-05-05 12:44:11 +02:00
}
2017-03-05 16:44:50 +01:00
Group & g = E - > get ( ) ;
2021-05-05 12:44:11 +02:00
if ( g . nodes . empty ( ) ) {
2014-02-10 02:10:30 +01:00
return ;
2021-05-05 12:44:11 +02:00
}
2014-02-10 02:10:30 +01:00
2018-07-02 07:30:40 +02: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 + + ;
2017-03-05 16:44:50 +01:00
for ( int i = 0 ; i < node_count ; i + + ) {
2014-02-10 02:10:30 +01:00
Node * n = nodes [ i ] ;
2021-05-05 12:44:11 +02:00
if ( call_lock & & call_skip . has ( n ) ) {
2014-02-10 02:10:30 +01:00
continue ;
2021-05-05 12:44:11 +02:00
}
2014-02-10 02:10:30 +01:00
2021-05-05 12:44:11 +02:00
if ( ! n - > can_process ( ) ) {
2014-02-10 02:10:30 +01:00
continue ;
2021-05-05 12:44:11 +02:00
}
if ( ! n - > can_process_notification ( p_notification ) ) {
2018-07-30 02:20:41 +02:00
continue ;
2021-05-05 12:44:11 +02:00
}
2014-02-10 02:10:30 +01:00
n - > notification ( p_notification ) ;
//ERR_FAIL_COND(node_count != g.nodes.size());
}
call_lock - - ;
2021-05-05 12:44:11 +02:00
if ( call_lock = = 0 ) {
2014-02-10 02:10:30 +01:00
call_skip . clear ( ) ;
2021-05-05 12:44:11 +02:00
}
2014-02-10 02:10:30 +01:00
}
/*
void SceneMainLoop : : _update_listener_2d ( ) {
if ( listener_2d . is_valid ( ) ) {
SpatialSound2DServer : : get_singleton ( ) - > listener_set_space ( listener_2d , world_2d - > get_sound_space ( ) ) ;
}
}
*/
2017-03-05 16:44:50 +01:00
Variant SceneTree : : _call_group_flags ( const Variant * * p_args , int p_argcount , Variant : : CallError & r_error ) {
r_error . error = Variant : : CallError : : CALL_OK ;
2014-02-10 02:10:30 +01:00
2017-03-05 16:44:50 +01:00
ERR_FAIL_COND_V ( p_argcount < 3 , Variant ( ) ) ;
ERR_FAIL_COND_V ( ! p_args [ 0 ] - > is_num ( ) , Variant ( ) ) ;
ERR_FAIL_COND_V ( p_args [ 1 ] - > get_type ( ) ! = Variant : : STRING , Variant ( ) ) ;
ERR_FAIL_COND_V ( p_args [ 2 ] - > get_type ( ) ! = Variant : : STRING , Variant ( ) ) ;
2014-02-10 02:10:30 +01:00
int flags = * p_args [ 0 ] ;
StringName group = * p_args [ 1 ] ;
StringName method = * p_args [ 2 ] ;
Variant v [ VARIANT_ARG_MAX ] ;
2021-10-24 04:40:03 +02:00
for ( int i = 0 ; i < MIN ( p_argcount - 3 , VARIANT_ARG_MAX ) ; i + + ) {
2017-03-05 16:44:50 +01:00
v [ i ] = * p_args [ i + 3 ] ;
2014-02-10 02:10:30 +01:00
}
2021-10-24 04:40:03 +02:00
static_assert ( VARIANT_ARG_MAX = = 8 , " This code needs to be updated if VARIANT_ARG_MAX != 8 " ) ;
call_group_flags ( flags , group , method , v [ 0 ] , v [ 1 ] , v [ 2 ] , v [ 3 ] , v [ 4 ] , v [ 5 ] , v [ 6 ] , v [ 7 ] ) ;
2014-02-10 02:10:30 +01:00
return Variant ( ) ;
}
2017-03-05 16:44:50 +01:00
Variant SceneTree : : _call_group ( const Variant * * p_args , int p_argcount , Variant : : CallError & r_error ) {
r_error . error = Variant : : CallError : : CALL_OK ;
2017-01-14 14:03:53 +01:00
2017-03-05 16:44:50 +01:00
ERR_FAIL_COND_V ( p_argcount < 2 , Variant ( ) ) ;
ERR_FAIL_COND_V ( p_args [ 0 ] - > get_type ( ) ! = Variant : : STRING , Variant ( ) ) ;
ERR_FAIL_COND_V ( p_args [ 1 ] - > get_type ( ) ! = Variant : : STRING , Variant ( ) ) ;
2017-01-14 14:03:53 +01:00
StringName group = * p_args [ 0 ] ;
StringName method = * p_args [ 1 ] ;
Variant v [ VARIANT_ARG_MAX ] ;
2017-03-05 16:44:50 +01:00
for ( int i = 0 ; i < MIN ( p_argcount - 2 , 5 ) ; i + + ) {
v [ i ] = * p_args [ i + 2 ] ;
2017-01-14 14:03:53 +01:00
}
2017-03-05 16:44:50 +01:00
call_group_flags ( 0 , group , method , v [ 0 ] , v [ 1 ] , v [ 2 ] , v [ 3 ] , v [ 4 ] ) ;
2017-01-14 14:03:53 +01:00
return Variant ( ) ;
}
2014-11-06 01:20:42 +01:00
int64_t SceneTree : : get_frame ( ) const {
2014-02-10 02:10:30 +01:00
return current_frame ;
}
2017-12-26 13:48:50 +01:00
int64_t SceneTree : : get_event_count ( ) const {
return current_event ;
}
2014-02-10 02:10:30 +01:00
2017-03-05 16:44:50 +01:00
Array SceneTree : : _get_nodes_in_group ( const StringName & p_group ) {
2014-02-10 02:10:30 +01:00
Array ret ;
2017-03-05 16:44:50 +01:00
Map < StringName , Group > : : Element * E = group_map . find ( p_group ) ;
2021-05-05 12:44:11 +02:00
if ( ! E ) {
2014-02-10 02:10:30 +01:00
return ret ;
2021-05-05 12:44:11 +02:00
}
2014-02-10 02:10:30 +01:00
_update_group_order ( E - > get ( ) ) ; //update order just in case
int nc = E - > get ( ) . nodes . size ( ) ;
2021-05-05 12:44:11 +02:00
if ( nc = = 0 ) {
2014-02-10 02:10:30 +01:00
return ret ;
2021-05-05 12:44:11 +02:00
}
2014-02-10 02:10:30 +01:00
ret . resize ( nc ) ;
2017-11-25 04:07:54 +01:00
Node * * ptr = E - > get ( ) . nodes . ptrw ( ) ;
2017-03-05 16:44:50 +01:00
for ( int i = 0 ; i < nc ; i + + ) {
ret [ i ] = ptr [ i ] ;
2014-02-10 02:10:30 +01:00
}
return ret ;
}
2017-03-05 16:44:50 +01:00
bool SceneTree : : has_group ( const StringName & p_identifier ) const {
2016-01-02 21:18:45 +01:00
return group_map . has ( p_identifier ) ;
}
2017-03-05 16:44:50 +01:00
void SceneTree : : get_nodes_in_group ( const StringName & p_group , List < Node * > * p_list ) {
Map < StringName , Group > : : Element * E = group_map . find ( p_group ) ;
2021-05-05 12:44:11 +02:00
if ( ! E ) {
2014-02-10 02:10:30 +01:00
return ;
2021-05-05 12:44:11 +02:00
}
2014-02-10 02:10:30 +01:00
_update_group_order ( E - > get ( ) ) ; //update order just in case
int nc = E - > get ( ) . nodes . size ( ) ;
2021-05-05 12:44:11 +02:00
if ( nc = = 0 ) {
2014-02-10 02:10:30 +01:00
return ;
2021-05-05 12:44:11 +02:00
}
2017-11-25 04:07:54 +01:00
Node * * ptr = E - > get ( ) . nodes . ptrw ( ) ;
2017-03-05 16:44:50 +01:00
for ( int i = 0 ; i < nc ; i + + ) {
2014-02-10 02:10:30 +01:00
p_list - > push_back ( ptr [ i ] ) ;
}
}
2014-11-06 01:20:42 +01:00
void SceneTree : : _flush_delete_queue ( ) {
2014-02-10 02:10:30 +01:00
_THREAD_SAFE_METHOD_
2017-03-05 16:44:50 +01:00
while ( delete_queue . size ( ) ) {
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 : : _update_root_rect ( ) {
2017-03-05 16:44:50 +01:00
if ( stretch_mode = = STRETCH_MODE_DISABLED ) {
2021-09-29 17:35:25 +02:00
_update_font_oversampling ( stretch_scale ) ;
root - > set_size ( last_screen_size . floor ( ) ) ;
2017-03-05 16:44:50 +01:00
root - > set_attach_to_screen_rect ( Rect2 ( Point2 ( ) , last_screen_size ) ) ;
2021-09-29 17:35:25 +02:00
root - > set_size_override_stretch ( true ) ;
root - > set_size_override ( true , ( last_screen_size / stretch_scale ) . floor ( ) ) ;
2019-01-26 18:56:22 +01:00
root - > update_canvas_items ( ) ;
2014-04-15 03:43:44 +02:00
return ; //user will take care
}
//actual screen video mode
2022-01-28 23:02:48 +01:00
Size2 video_mode = OS : : get_singleton ( ) - > get_window_size ( ) ;
2014-04-15 03:43:44 +02:00
Size2 desired_res = stretch_min ;
Size2 viewport_size ;
Size2 screen_size ;
2017-01-14 00:00:43 +01:00
float viewport_aspect = desired_res . aspect ( ) ;
float video_mode_aspect = video_mode . aspect ( ) ;
2014-04-15 03:43:44 +02:00
2019-01-16 16:42:53 +01:00
if ( stretch_aspect = = STRETCH_ASPECT_IGNORE | | Math : : is_equal_approx ( viewport_aspect , video_mode_aspect ) ) {
2014-04-15 03:43:44 +02:00
//same aspect or ignore aspect
2017-03-05 16:44:50 +01:00
viewport_size = desired_res ;
screen_size = video_mode ;
2014-04-15 03:43:44 +02:00
} else if ( viewport_aspect < video_mode_aspect ) {
// screen ratio is smaller vertically
2017-08-09 09:53:38 +02:00
if ( stretch_aspect = = STRETCH_ASPECT_KEEP_HEIGHT | | stretch_aspect = = STRETCH_ASPECT_EXPAND ) {
2014-04-15 03:43:44 +02:00
//will stretch horizontally
2017-03-05 16:44:50 +01:00
viewport_size . x = desired_res . y * video_mode_aspect ;
viewport_size . y = desired_res . y ;
screen_size = video_mode ;
2014-04-15 03:43:44 +02:00
} else {
//will need black bars
2017-03-05 16:44:50 +01:00
viewport_size = desired_res ;
2014-04-15 03:43:44 +02:00
screen_size . x = video_mode . y * viewport_aspect ;
2017-03-05 16:44:50 +01:00
screen_size . y = video_mode . y ;
2014-04-15 03:43:44 +02:00
}
} else {
//screen ratio is smaller horizontally
2017-08-09 09:53:38 +02:00
if ( stretch_aspect = = STRETCH_ASPECT_KEEP_WIDTH | | stretch_aspect = = STRETCH_ASPECT_EXPAND ) {
2014-04-15 03:43:44 +02:00
//will stretch horizontally
2017-03-05 16:44:50 +01:00
viewport_size . x = desired_res . x ;
viewport_size . y = desired_res . x / video_mode_aspect ;
screen_size = video_mode ;
2014-04-15 03:43:44 +02:00
} else {
//will need black bars
2017-03-05 16:44:50 +01:00
viewport_size = desired_res ;
screen_size . x = video_mode . x ;
2014-04-15 03:43:44 +02:00
screen_size . y = video_mode . x / viewport_aspect ;
}
}
screen_size = screen_size . floor ( ) ;
viewport_size = viewport_size . floor ( ) ;
Size2 margin ;
Size2 offset ;
//black bars and margin
2017-08-09 09:53:38 +02:00
if ( stretch_aspect ! = STRETCH_ASPECT_EXPAND & & screen_size . x < video_mode . x ) {
2017-03-05 16:44:50 +01:00
margin . x = Math : : round ( ( video_mode . x - screen_size . x ) / 2.0 ) ;
VisualServer : : get_singleton ( ) - > black_bars_set_margins ( margin . x , 0 , margin . x , 0 ) ;
2014-04-15 03:43:44 +02:00
offset . x = Math : : round ( margin . x * viewport_size . y / screen_size . y ) ;
2017-08-09 09:53:38 +02:00
} else if ( stretch_aspect ! = STRETCH_ASPECT_EXPAND & & screen_size . y < video_mode . y ) {
2017-03-05 16:44:50 +01:00
margin . y = Math : : round ( ( video_mode . y - screen_size . y ) / 2.0 ) ;
VisualServer : : get_singleton ( ) - > black_bars_set_margins ( 0 , margin . y , 0 , margin . y ) ;
2014-04-15 03:43:44 +02:00
offset . y = Math : : round ( margin . y * viewport_size . x / screen_size . x ) ;
} else {
2017-03-05 16:44:50 +01:00
VisualServer : : get_singleton ( ) - > black_bars_set_margins ( 0 , 0 , 0 , 0 ) ;
2014-04-15 03:43:44 +02:00
}
switch ( stretch_mode ) {
2018-09-26 13:13:56 +02:00
case STRETCH_MODE_DISABLED : {
// Already handled above
} break ;
2014-04-15 03:43:44 +02:00
case STRETCH_MODE_2D : {
2021-09-29 17:35:25 +02:00
_update_font_oversampling ( ( screen_size . x / viewport_size . x ) * stretch_scale ) ; //screen / viewport ratio drives oversampling
root - > set_size ( screen_size . floor ( ) ) ;
2017-03-05 16:44:50 +01:00
root - > set_attach_to_screen_rect ( Rect2 ( margin , screen_size ) ) ;
2014-04-15 03:43:44 +02:00
root - > set_size_override_stretch ( true ) ;
2021-09-29 17:35:25 +02:00
root - > set_size_override ( true , ( viewport_size / stretch_scale ) . floor ( ) ) ;
2019-01-26 18:56:22 +01:00
root - > update_canvas_items ( ) ; //force them to update just in case
2014-04-15 03:43:44 +02:00
} break ;
case STRETCH_MODE_VIEWPORT : {
2019-01-26 18:56:22 +01:00
_update_font_oversampling ( 1.0 ) ;
2021-09-29 17:35:25 +02:00
root - > set_size ( ( viewport_size / stretch_scale ) . floor ( ) ) ;
2017-03-05 16:44:50 +01:00
root - > set_attach_to_screen_rect ( Rect2 ( margin , screen_size ) ) ;
2014-04-15 03:43:44 +02:00
root - > set_size_override_stretch ( false ) ;
2017-03-05 16:44:50 +01:00
root - > set_size_override ( false , Size2 ( ) ) ;
2019-01-26 18:56:22 +01:00
root - > update_canvas_items ( ) ; //force them to update just in case
2014-04-15 03:43:44 +02:00
} break ;
}
}
2021-09-29 17:35:25 +02:00
void SceneTree : : set_screen_stretch ( StretchMode p_mode , StretchAspect p_aspect , const Size2 & p_minsize , real_t p_scale ) {
2017-03-05 16:44:50 +01:00
stretch_mode = p_mode ;
stretch_aspect = p_aspect ;
stretch_min = p_minsize ;
2021-09-29 17:35:25 +02:00
stretch_scale = p_scale ;
2014-04-15 03:43:44 +02:00
_update_root_rect ( ) ;
}
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
return NULL ;
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 ) ;
2021-05-04 16:00:45 +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 ) ;
2021-05-05 12:44:11 +02:00
if ( new_scene . is_null ( ) ) {
2015-05-17 21:33:35 +02:00
return ERR_CANT_OPEN ;
2021-05-05 12:44:11 +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 ) {
2021-05-04 16:00:45 +02:00
Node * new_scene = nullptr ;
2015-05-17 21:33:35 +02:00
if ( p_scene . is_valid ( ) ) {
new_scene = p_scene - > instance ( ) ;
2017-03-05 16:44:50 +01:00
ERR_FAIL_COND_V ( ! new_scene , ERR_CANT_CREATE ) ;
2015-05-17 21:33:35 +02:00
}
2017-03-05 16:44:50 +01:00
call_deferred ( " _change_scene " , new_scene ) ;
2015-05-17 21:33:35 +02:00
return OK ;
}
2020-01-19 22:06:26 +01:00
Error SceneTree : : reload_current_scene ( ) {
2017-03-05 16:44:50 +01:00
ERR_FAIL_COND_V ( ! current_scene , ERR_UNCONFIGURED ) ;
2015-05-17 21:33:35 +02:00
String fname = current_scene - > get_filename ( ) ;
return change_scene ( fname ) ;
}
2017-03-05 16:44:50 +01:00
void SceneTree : : add_current_scene ( Node * p_current ) {
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
2015-08-02 17:29:37 +02:00
# ifdef DEBUG_ENABLED
2014-10-12 07:13:22 +02:00
2019-04-06 22:55:01 +02:00
static void _fill_array ( Node * p_node , Array & array , int p_level ) {
array . push_back ( p_node - > get_child_count ( ) ) ;
array . push_back ( p_node - > get_name ( ) ) ;
array . push_back ( p_node - > get_class ( ) ) ;
array . push_back ( p_node - > get_instance_id ( ) ) ;
for ( int i = 0 ; i < p_node - > get_child_count ( ) ; i + + ) {
_fill_array ( p_node - > get_child ( i ) , array , p_level + 1 ) ;
}
}
void SceneTree : : _debugger_request_tree ( ) {
Array arr ;
_fill_array ( root , arr , 0 ) ;
ScriptDebugger : : get_singleton ( ) - > send_message ( " scene_tree " , arr ) ;
}
2017-03-05 16:44:50 +01:00
void SceneTree : : _live_edit_node_path_func ( const NodePath & p_path , int p_id ) {
live_edit_node_path_cache [ p_id ] = p_path ;
2015-08-02 17:29:37 +02:00
}
2017-03-05 16:44:50 +01:00
void SceneTree : : _live_edit_res_path_func ( const String & p_path , int p_id ) {
live_edit_resource_cache [ p_id ] = p_path ;
2015-08-02 17:29:37 +02:00
}
2017-03-05 16:44:50 +01:00
void SceneTree : : _live_edit_node_set_func ( int p_id , const StringName & p_prop , const Variant & p_value ) {
2021-05-05 12:44:11 +02:00
if ( ! live_edit_node_path_cache . has ( p_id ) ) {
2015-08-02 17:29:37 +02:00
return ;
2021-05-05 12:44:11 +02:00
}
2015-08-02 17:29:37 +02:00
NodePath np = live_edit_node_path_cache [ p_id ] ;
2021-05-04 16:00:45 +02:00
Node * base = nullptr ;
2021-05-05 12:44:11 +02:00
if ( root - > has_node ( live_edit_root ) ) {
2015-08-02 17:29:37 +02:00
base = root - > get_node ( live_edit_root ) ;
2021-05-05 12:44:11 +02:00
}
2015-08-02 17:29:37 +02:00
2021-05-04 14:20:36 +02:00
Map < String , Set < Node * > > : : Element * E = live_scene_edit_cache . find ( live_edit_scene ) ;
2021-05-05 12:44:11 +02:00
if ( ! E ) {
2015-08-02 17:29:37 +02:00
return ; //scene not editable
2021-05-05 12:44:11 +02:00
}
2015-08-02 17:29:37 +02:00
2017-03-05 16:44:50 +01:00
for ( Set < Node * > : : Element * F = E - > get ( ) . front ( ) ; F ; F = F - > next ( ) ) {
Node * n = F - > get ( ) ;
2015-08-02 17:29:37 +02:00
2021-05-05 12:44:11 +02:00
if ( base & & ! base - > is_a_parent_of ( n ) ) {
2015-08-02 17:29:37 +02:00
continue ;
2021-05-05 12:44:11 +02:00
}
2015-08-02 17:29:37 +02:00
2021-05-05 12:44:11 +02:00
if ( ! n - > has_node ( np ) ) {
2015-08-02 17:29:37 +02:00
continue ;
2021-05-05 12:44:11 +02:00
}
2015-08-02 17:29:37 +02:00
Node * n2 = n - > get_node ( np ) ;
2017-03-05 16:44:50 +01:00
n2 - > set ( p_prop , p_value ) ;
2015-08-02 17:29:37 +02:00
}
}
2017-03-05 16:44:50 +01:00
void SceneTree : : _live_edit_node_set_res_func ( int p_id , const StringName & p_prop , const String & p_value ) {
2015-08-02 17:29:37 +02:00
RES r = ResourceLoader : : load ( p_value ) ;
2021-05-05 12:44:11 +02:00
if ( ! r . is_valid ( ) ) {
2015-08-02 17:29:37 +02:00
return ;
2021-05-05 12:44:11 +02:00
}
2017-03-05 16:44:50 +01:00
_live_edit_node_set_func ( p_id , p_prop , r ) ;
2015-08-02 17:29:37 +02:00
}
2017-03-05 16:44:50 +01:00
void SceneTree : : _live_edit_node_call_func ( int p_id , const StringName & p_method , VARIANT_ARG_DECLARE ) {
2021-05-05 12:44:11 +02:00
if ( ! live_edit_node_path_cache . has ( p_id ) ) {
2015-08-02 17:29:37 +02:00
return ;
2021-05-05 12:44:11 +02:00
}
2015-08-02 17:29:37 +02:00
NodePath np = live_edit_node_path_cache [ p_id ] ;
2021-05-04 16:00:45 +02:00
Node * base = nullptr ;
2021-05-05 12:44:11 +02:00
if ( root - > has_node ( live_edit_root ) ) {
2015-08-02 17:29:37 +02:00
base = root - > get_node ( live_edit_root ) ;
2021-05-05 12:44:11 +02:00
}
2015-08-02 17:29:37 +02:00
2021-05-04 14:20:36 +02:00
Map < String , Set < Node * > > : : Element * E = live_scene_edit_cache . find ( live_edit_scene ) ;
2021-05-05 12:44:11 +02:00
if ( ! E ) {
2015-08-02 17:29:37 +02:00
return ; //scene not editable
2021-05-05 12:44:11 +02:00
}
2015-08-02 17:29:37 +02:00
2017-03-05 16:44:50 +01:00
for ( Set < Node * > : : Element * F = E - > get ( ) . front ( ) ; F ; F = F - > next ( ) ) {
Node * n = F - > get ( ) ;
2015-08-02 17:29:37 +02:00
2021-05-05 12:44:11 +02:00
if ( base & & ! base - > is_a_parent_of ( n ) ) {
2015-08-02 17:29:37 +02:00
continue ;
2021-05-05 12:44:11 +02:00
}
2015-08-02 17:29:37 +02:00
2021-05-05 12:44:11 +02:00
if ( ! n - > has_node ( np ) ) {
2015-08-02 17:29:37 +02:00
continue ;
2021-05-05 12:44:11 +02:00
}
2015-08-02 17:29:37 +02:00
Node * n2 = n - > get_node ( np ) ;
2017-03-05 16:44:50 +01:00
n2 - > call ( p_method , VARIANT_ARG_PASS ) ;
2015-08-02 17:29:37 +02:00
}
}
2017-03-05 16:44:50 +01:00
void SceneTree : : _live_edit_res_set_func ( int p_id , const StringName & p_prop , const Variant & p_value ) {
2021-05-05 12:44:11 +02:00
if ( ! live_edit_resource_cache . has ( p_id ) ) {
2015-08-02 17:29:37 +02:00
return ;
2021-05-05 12:44:11 +02:00
}
2015-08-02 17:29:37 +02:00
String resp = live_edit_resource_cache [ p_id ] ;
2021-05-05 12:44:11 +02:00
if ( ! ResourceCache : : has ( resp ) ) {
2015-08-02 17:29:37 +02:00
return ;
2021-05-05 12:44:11 +02:00
}
2015-08-02 17:29:37 +02:00
RES r = ResourceCache : : get ( resp ) ;
2021-05-05 12:44:11 +02:00
if ( ! r . is_valid ( ) ) {
2015-08-02 17:29:37 +02:00
return ;
2021-05-05 12:44:11 +02:00
}
2015-08-02 17:29:37 +02:00
2017-03-05 16:44:50 +01:00
r - > set ( p_prop , p_value ) ;
2015-08-02 17:29:37 +02:00
}
2017-03-05 16:44:50 +01:00
void SceneTree : : _live_edit_res_set_res_func ( int p_id , const StringName & p_prop , const String & p_value ) {
2015-08-02 17:29:37 +02:00
RES r = ResourceLoader : : load ( p_value ) ;
2021-05-05 12:44:11 +02:00
if ( ! r . is_valid ( ) ) {
2015-08-02 17:29:37 +02:00
return ;
2021-05-05 12:44:11 +02:00
}
2017-03-05 16:44:50 +01:00
_live_edit_res_set_func ( p_id , p_prop , r ) ;
2015-08-02 17:29:37 +02:00
}
2017-03-05 16:44:50 +01:00
void SceneTree : : _live_edit_res_call_func ( int p_id , const StringName & p_method , VARIANT_ARG_DECLARE ) {
2021-05-05 12:44:11 +02:00
if ( ! live_edit_resource_cache . has ( p_id ) ) {
2015-08-02 17:29:37 +02:00
return ;
2021-05-05 12:44:11 +02:00
}
2015-08-02 17:29:37 +02:00
String resp = live_edit_resource_cache [ p_id ] ;
2021-05-05 12:44:11 +02:00
if ( ! ResourceCache : : has ( resp ) ) {
2015-08-02 17:29:37 +02:00
return ;
2021-05-05 12:44:11 +02:00
}
2015-08-02 17:29:37 +02:00
RES r = ResourceCache : : get ( resp ) ;
2021-05-05 12:44:11 +02:00
if ( ! r . is_valid ( ) ) {
2015-08-02 17:29:37 +02:00
return ;
2021-05-05 12:44:11 +02:00
}
2015-08-02 17:29:37 +02:00
2017-03-05 16:44:50 +01:00
r - > call ( p_method , VARIANT_ARG_PASS ) ;
2015-08-02 17:29:37 +02:00
}
2017-03-05 16:44:50 +01:00
void SceneTree : : _live_edit_root_func ( const NodePath & p_scene_path , const String & p_scene_from ) {
live_edit_root = p_scene_path ;
live_edit_scene = p_scene_from ;
2015-08-02 17:29:37 +02:00
}
2017-03-05 16:44:50 +01:00
void SceneTree : : _live_edit_create_node_func ( const NodePath & p_parent , const String & p_type , const String & p_name ) {
2021-05-04 16:00:45 +02:00
Node * base = nullptr ;
2021-05-05 12:44:11 +02:00
if ( root - > has_node ( live_edit_root ) ) {
2015-08-02 17:29:37 +02:00
base = root - > get_node ( live_edit_root ) ;
2021-05-05 12:44:11 +02:00
}
2015-08-02 17:29:37 +02:00
2021-05-04 14:20:36 +02:00
Map < String , Set < Node * > > : : Element * E = live_scene_edit_cache . find ( live_edit_scene ) ;
2021-05-05 12:44:11 +02:00
if ( ! E ) {
2015-08-02 17:29:37 +02:00
return ; //scene not editable
2021-05-05 12:44:11 +02:00
}
2015-08-02 17:29:37 +02:00
2017-03-05 16:44:50 +01:00
for ( Set < Node * > : : Element * F = E - > get ( ) . front ( ) ; F ; F = F - > next ( ) ) {
Node * n = F - > get ( ) ;
2015-08-02 17:29:37 +02:00
2021-05-05 12:44:11 +02:00
if ( base & & ! base - > is_a_parent_of ( n ) ) {
2015-08-02 17:29:37 +02:00
continue ;
2021-05-05 12:44:11 +02:00
}
2015-08-02 17:29:37 +02:00
2021-05-05 12:44:11 +02:00
if ( ! n - > has_node ( p_parent ) ) {
2015-08-02 17:29:37 +02:00
continue ;
2021-05-05 12:44:11 +02:00
}
2015-08-02 17:29:37 +02:00
Node * n2 = n - > get_node ( p_parent ) ;
2017-08-24 22:58:51 +02:00
Node * no = Object : : cast_to < Node > ( ClassDB : : instance ( p_type ) ) ;
2017-08-26 22:53:28 +02:00
if ( ! no ) {
continue ;
}
2015-08-02 17:29:37 +02:00
2017-08-26 22:53:28 +02:00
no - > set_name ( p_name ) ;
2015-08-02 17:29:37 +02:00
n2 - > add_child ( no ) ;
}
}
2017-03-05 16:44:50 +01:00
void SceneTree : : _live_edit_instance_node_func ( const NodePath & p_parent , const String & p_path , const String & p_name ) {
2015-08-02 17:29:37 +02:00
Ref < PackedScene > ps = ResourceLoader : : load ( p_path ) ;
2015-08-03 01:28:10 +02:00
2021-05-05 12:44:11 +02:00
if ( ! ps . is_valid ( ) ) {
2015-08-02 17:29:37 +02:00
return ;
2021-05-05 12:44:11 +02:00
}
2015-08-02 17:29:37 +02:00
2021-05-04 16:00:45 +02:00
Node * base = nullptr ;
2021-05-05 12:44:11 +02:00
if ( root - > has_node ( live_edit_root ) ) {
2015-08-02 17:29:37 +02:00
base = root - > get_node ( live_edit_root ) ;
2021-05-05 12:44:11 +02:00
}
2015-08-02 17:29:37 +02:00
2021-05-04 14:20:36 +02:00
Map < String , Set < Node * > > : : Element * E = live_scene_edit_cache . find ( live_edit_scene ) ;
2021-05-05 12:44:11 +02:00
if ( ! E ) {
2015-08-02 17:29:37 +02:00
return ; //scene not editable
2021-05-05 12:44:11 +02:00
}
2015-08-02 17:29:37 +02:00
2017-03-05 16:44:50 +01:00
for ( Set < Node * > : : Element * F = E - > get ( ) . front ( ) ; F ; F = F - > next ( ) ) {
Node * n = F - > get ( ) ;
2015-08-02 17:29:37 +02:00
2021-05-05 12:44:11 +02:00
if ( base & & ! base - > is_a_parent_of ( n ) ) {
2015-08-02 17:29:37 +02:00
continue ;
2021-05-05 12:44:11 +02:00
}
2015-08-02 17:29:37 +02:00
2021-05-05 12:44:11 +02:00
if ( ! n - > has_node ( p_parent ) ) {
2015-08-02 17:29:37 +02:00
continue ;
2021-05-05 12:44:11 +02:00
}
2015-08-02 17:29:37 +02:00
Node * n2 = n - > get_node ( p_parent ) ;
2017-03-05 16:44:50 +01:00
Node * no = ps - > instance ( ) ;
2019-07-23 09:14:31 +02:00
if ( ! no ) {
continue ;
}
2015-08-02 17:29:37 +02:00
2019-07-23 09:14:31 +02:00
no - > set_name ( p_name ) ;
2015-08-02 17:29:37 +02:00
n2 - > add_child ( no ) ;
}
}
2017-03-05 16:44:50 +01:00
void SceneTree : : _live_edit_remove_node_func ( const NodePath & p_at ) {
2021-05-04 16:00:45 +02:00
Node * base = nullptr ;
2021-05-05 12:44:11 +02:00
if ( root - > has_node ( live_edit_root ) ) {
2015-08-02 17:29:37 +02:00
base = root - > get_node ( live_edit_root ) ;
2021-05-05 12:44:11 +02:00
}
2015-08-02 17:29:37 +02:00
2021-05-04 14:20:36 +02:00
Map < String , Set < Node * > > : : Element * E = live_scene_edit_cache . find ( live_edit_scene ) ;
2021-05-05 12:44:11 +02:00
if ( ! E ) {
2015-08-02 17:29:37 +02:00
return ; //scene not editable
2021-05-05 12:44:11 +02:00
}
2015-08-02 17:29:37 +02:00
2017-03-05 16:44:50 +01:00
for ( Set < Node * > : : Element * F = E - > get ( ) . front ( ) ; F ; ) {
Set < Node * > : : Element * N = F - > next ( ) ;
2015-08-02 17:29:37 +02:00
2017-03-05 16:44:50 +01:00
Node * n = F - > get ( ) ;
2015-08-02 17:29:37 +02:00
2021-05-05 12:44:11 +02:00
if ( base & & ! base - > is_a_parent_of ( n ) ) {
2015-08-02 17:29:37 +02:00
continue ;
2021-05-05 12:44:11 +02:00
}
2015-08-02 17:29:37 +02:00
2021-05-05 12:44:11 +02:00
if ( ! n - > has_node ( p_at ) ) {
2015-08-02 17:29:37 +02:00
continue ;
2021-05-05 12:44:11 +02:00
}
2015-08-02 17:29:37 +02:00
Node * n2 = n - > get_node ( p_at ) ;
memdelete ( n2 ) ;
2017-03-05 16:44:50 +01:00
F = N ;
2015-08-02 17:29:37 +02:00
}
}
2017-03-05 16:44:50 +01:00
void SceneTree : : _live_edit_remove_and_keep_node_func ( const NodePath & p_at , ObjectID p_keep_id ) {
2021-05-04 16:00:45 +02:00
Node * base = nullptr ;
2021-05-05 12:44:11 +02:00
if ( root - > has_node ( live_edit_root ) ) {
2015-08-03 01:28:10 +02:00
base = root - > get_node ( live_edit_root ) ;
2021-05-05 12:44:11 +02:00
}
2015-08-03 01:28:10 +02:00
2021-05-04 14:20:36 +02:00
Map < String , Set < Node * > > : : Element * E = live_scene_edit_cache . find ( live_edit_scene ) ;
2021-05-05 12:44:11 +02:00
if ( ! E ) {
2015-08-03 01:28:10 +02:00
return ; //scene not editable
2021-05-05 12:44:11 +02:00
}
2015-08-03 01:28:10 +02:00
2017-03-05 16:44:50 +01:00
for ( Set < Node * > : : Element * F = E - > get ( ) . front ( ) ; F ; ) {
Set < Node * > : : Element * N = F - > next ( ) ;
2015-08-03 01:28:10 +02:00
2017-03-05 16:44:50 +01:00
Node * n = F - > get ( ) ;
2015-08-02 17:29:37 +02:00
2021-05-05 12:44:11 +02:00
if ( base & & ! base - > is_a_parent_of ( n ) ) {
2015-08-03 01:28:10 +02:00
continue ;
2021-05-05 12:44:11 +02:00
}
2015-08-03 01:28:10 +02:00
2021-05-05 12:44:11 +02:00
if ( ! n - > has_node ( p_at ) ) {
2015-08-03 01:28:10 +02:00
continue ;
2021-05-05 12:44:11 +02:00
}
2015-08-03 01:28:10 +02:00
Node * n2 = n - > get_node ( p_at ) ;
n2 - > get_parent ( ) - > remove_child ( n2 ) ;
2017-03-05 16:44:50 +01:00
live_edit_remove_list [ n ] [ p_keep_id ] = n2 ;
2015-08-03 01:28:10 +02:00
2017-03-05 16:44:50 +01:00
F = N ;
2015-08-03 01:28:10 +02:00
}
2015-08-02 17:29:37 +02:00
}
2017-03-05 16:44:50 +01:00
void SceneTree : : _live_edit_restore_node_func ( ObjectID p_id , const NodePath & p_at , int p_at_pos ) {
2021-05-04 16:00:45 +02:00
Node * base = nullptr ;
2021-05-05 12:44:11 +02:00
if ( root - > has_node ( live_edit_root ) ) {
2015-08-03 01:28:10 +02:00
base = root - > get_node ( live_edit_root ) ;
2021-05-05 12:44:11 +02:00
}
2015-08-03 01:28:10 +02:00
2021-05-04 14:20:36 +02:00
Map < String , Set < Node * > > : : Element * E = live_scene_edit_cache . find ( live_edit_scene ) ;
2021-05-05 12:44:11 +02:00
if ( ! E ) {
2015-08-03 01:28:10 +02:00
return ; //scene not editable
2021-05-05 12:44:11 +02:00
}
2015-08-03 01:28:10 +02:00
2017-03-05 16:44:50 +01:00
for ( Set < Node * > : : Element * F = E - > get ( ) . front ( ) ; F ; ) {
Set < Node * > : : Element * N = F - > next ( ) ;
2015-08-03 01:28:10 +02:00
2017-03-05 16:44:50 +01:00
Node * n = F - > get ( ) ;
2015-08-03 01:28:10 +02:00
2021-05-05 12:44:11 +02:00
if ( base & & ! base - > is_a_parent_of ( n ) ) {
2015-08-03 01:28:10 +02:00
continue ;
2021-05-05 12:44:11 +02:00
}
2015-08-03 01:28:10 +02:00
2021-05-05 12:44:11 +02:00
if ( ! n - > has_node ( p_at ) ) {
2015-08-03 01:28:10 +02:00
continue ;
2021-05-05 12:44:11 +02:00
}
2015-08-03 01:28:10 +02:00
Node * n2 = n - > get_node ( p_at ) ;
2021-05-04 14:20:36 +02:00
Map < Node * , Map < ObjectID , Node * > > : : Element * EN = live_edit_remove_list . find ( n ) ;
2015-08-03 01:28:10 +02:00
2021-05-05 12:44:11 +02:00
if ( ! EN ) {
2015-08-03 01:28:10 +02:00
continue ;
2021-05-05 12:44:11 +02:00
}
2015-08-03 01:28:10 +02:00
2017-03-05 16:44:50 +01:00
Map < ObjectID , Node * > : : Element * FN = EN - > get ( ) . find ( p_id ) ;
2015-08-03 01:28:10 +02:00
2021-05-05 12:44:11 +02:00
if ( ! FN ) {
2015-08-03 01:28:10 +02:00
continue ;
2021-05-05 12:44:11 +02:00
}
2015-08-03 01:28:10 +02:00
n2 - > add_child ( FN - > get ( ) ) ;
EN - > get ( ) . erase ( FN ) ;
2017-03-05 16:44:50 +01:00
if ( EN - > get ( ) . size ( ) = = 0 ) {
2015-08-03 01:28:10 +02:00
live_edit_remove_list . erase ( EN ) ;
}
2017-03-05 16:44:50 +01:00
F = N ;
2015-08-03 01:28:10 +02:00
}
2015-08-02 17:29:37 +02:00
}
2017-03-05 16:44:50 +01:00
void SceneTree : : _live_edit_duplicate_node_func ( const NodePath & p_at , const String & p_new_name ) {
2021-05-04 16:00:45 +02:00
Node * base = nullptr ;
2021-05-05 12:44:11 +02:00
if ( root - > has_node ( live_edit_root ) ) {
2015-08-02 17:29:37 +02:00
base = root - > get_node ( live_edit_root ) ;
2021-05-05 12:44:11 +02:00
}
2015-08-02 17:29:37 +02:00
2021-05-04 14:20:36 +02:00
Map < String , Set < Node * > > : : Element * E = live_scene_edit_cache . find ( live_edit_scene ) ;
2021-05-05 12:44:11 +02:00
if ( ! E ) {
2015-08-02 17:29:37 +02:00
return ; //scene not editable
2021-05-05 12:44:11 +02:00
}
2015-08-02 17:29:37 +02:00
2017-03-05 16:44:50 +01:00
for ( Set < Node * > : : Element * F = E - > get ( ) . front ( ) ; F ; F = F - > next ( ) ) {
Node * n = F - > get ( ) ;
2015-08-02 17:29:37 +02:00
2021-05-05 12:44:11 +02:00
if ( base & & ! base - > is_a_parent_of ( n ) ) {
2015-08-02 17:29:37 +02:00
continue ;
2021-05-05 12:44:11 +02:00
}
2015-08-02 17:29:37 +02:00
2021-05-05 12:44:11 +02:00
if ( ! n - > has_node ( p_at ) ) {
2015-08-02 17:29:37 +02:00
continue ;
2021-05-05 12:44:11 +02:00
}
2015-08-02 17:29:37 +02:00
Node * n2 = n - > get_node ( p_at ) ;
2018-09-22 12:37:21 +02:00
Node * dup = n2 - > duplicate ( Node : : DUPLICATE_SIGNALS | Node : : DUPLICATE_GROUPS | Node : : DUPLICATE_SCRIPTS ) ;
2015-08-02 17:29:37 +02:00
2021-05-05 12:44:11 +02:00
if ( ! dup ) {
2015-08-02 17:29:37 +02:00
continue ;
2021-05-05 12:44:11 +02:00
}
2015-08-02 17:29:37 +02:00
dup - > set_name ( p_new_name ) ;
n2 - > get_parent ( ) - > add_child ( dup ) ;
}
}
2017-03-05 16:44:50 +01:00
void SceneTree : : _live_edit_reparent_node_func ( const NodePath & p_at , const NodePath & p_new_place , const String & p_new_name , int p_at_pos ) {
2021-05-04 16:00:45 +02:00
Node * base = nullptr ;
2021-05-05 12:44:11 +02:00
if ( root - > has_node ( live_edit_root ) ) {
2015-08-02 17:29:37 +02:00
base = root - > get_node ( live_edit_root ) ;
2021-05-05 12:44:11 +02:00
}
2015-08-02 17:29:37 +02:00
2021-05-04 14:20:36 +02:00
Map < String , Set < Node * > > : : Element * E = live_scene_edit_cache . find ( live_edit_scene ) ;
2021-05-05 12:44:11 +02:00
if ( ! E ) {
2015-08-02 17:29:37 +02:00
return ; //scene not editable
2021-05-05 12:44:11 +02:00
}
2015-08-02 17:29:37 +02:00
2017-03-05 16:44:50 +01:00
for ( Set < Node * > : : Element * F = E - > get ( ) . front ( ) ; F ; F = F - > next ( ) ) {
Node * n = F - > get ( ) ;
2015-08-02 17:29:37 +02:00
2021-05-05 12:44:11 +02:00
if ( base & & ! base - > is_a_parent_of ( n ) ) {
2015-08-02 17:29:37 +02:00
continue ;
2021-05-05 12:44:11 +02:00
}
2015-08-02 17:29:37 +02:00
2021-05-05 12:44:11 +02:00
if ( ! n - > has_node ( p_at ) ) {
2015-08-02 17:29:37 +02:00
continue ;
2021-05-05 12:44:11 +02:00
}
2015-08-02 17:29:37 +02:00
Node * nfrom = n - > get_node ( p_at ) ;
2021-05-05 12:44:11 +02:00
if ( ! n - > has_node ( p_new_place ) ) {
2015-08-02 17:29:37 +02:00
continue ;
2021-05-05 12:44:11 +02:00
}
2015-08-02 17:29:37 +02:00
Node * nto = n - > get_node ( p_new_place ) ;
nfrom - > get_parent ( ) - > remove_child ( nfrom ) ;
nfrom - > set_name ( p_new_name ) ;
nto - > add_child ( nfrom ) ;
2021-05-05 12:44:11 +02:00
if ( p_at_pos > = 0 ) {
2017-03-05 16:44:50 +01:00
nto - > move_child ( nfrom , p_at_pos ) ;
2021-05-05 12:44:11 +02:00
}
2015-08-02 17:29:37 +02:00
}
}
# endif
2016-05-27 19:18:40 +02:00
2017-03-05 16:44:50 +01:00
void SceneTree : : drop_files ( const Vector < String > & p_files , int p_from_screen ) {
emit_signal ( " files_dropped " , p_files , p_from_screen ) ;
MainLoop : : drop_files ( p_files , p_from_screen ) ;
2016-05-27 19:18:40 +02:00
}
2019-02-06 14:57:06 +01:00
void SceneTree : : global_menu_action ( const Variant & p_id , const Variant & p_meta ) {
emit_signal ( " global_menu_action " , p_id , p_meta ) ;
MainLoop : : global_menu_action ( p_id , p_meta ) ;
}
2017-02-14 00:34:33 +01:00
Ref < SceneTreeTimer > SceneTree : : create_timer ( float p_delay_sec , bool p_process_pause ) {
2016-08-07 02:39:50 +02:00
Ref < SceneTreeTimer > stt ;
stt . instance ( ) ;
2017-02-14 00:34:33 +01:00
stt - > set_pause_mode_process ( p_process_pause ) ;
2016-08-07 02:39:50 +02:00
stt - > set_time_left ( p_delay_sec ) ;
timers . push_back ( stt ) ;
return stt ;
}
2016-08-19 21:48:08 +02:00
void SceneTree : : _network_peer_connected ( int p_id ) {
2017-03-05 16:44:50 +01:00
emit_signal ( " network_peer_connected " , p_id ) ;
2016-08-14 23:49:50 +02:00
}
2016-08-19 21:48:08 +02:00
void SceneTree : : _network_peer_disconnected ( int p_id ) {
2017-03-05 16:44:50 +01:00
emit_signal ( " network_peer_disconnected " , p_id ) ;
2016-08-14 23:49:50 +02:00
}
2016-08-19 21:48:08 +02:00
void SceneTree : : _connected_to_server ( ) {
emit_signal ( " connected_to_server " ) ;
}
void SceneTree : : _connection_failed ( ) {
emit_signal ( " connection_failed " ) ;
}
void SceneTree : : _server_disconnected ( ) {
emit_signal ( " server_disconnected " ) ;
}
2018-05-08 10:51:04 +02:00
Ref < MultiplayerAPI > SceneTree : : get_multiplayer ( ) const {
return multiplayer ;
2018-03-03 18:30:11 +01:00
}
2018-06-02 14:32:30 +02:00
void SceneTree : : set_multiplayer_poll_enabled ( bool p_enabled ) {
multiplayer_poll = p_enabled ;
}
bool SceneTree : : is_multiplayer_poll_enabled ( ) const {
return multiplayer_poll ;
}
2018-05-08 10:51:04 +02:00
void SceneTree : : set_multiplayer ( Ref < MultiplayerAPI > p_multiplayer ) {
ERR_FAIL_COND ( ! p_multiplayer . is_valid ( ) ) ;
2018-03-03 18:30:11 +01:00
2018-05-08 10:51:04 +02:00
if ( multiplayer . is_valid ( ) ) {
multiplayer - > disconnect ( " network_peer_connected " , this , " _network_peer_connected " ) ;
multiplayer - > disconnect ( " network_peer_disconnected " , this , " _network_peer_disconnected " ) ;
multiplayer - > disconnect ( " connected_to_server " , this , " _connected_to_server " ) ;
multiplayer - > disconnect ( " connection_failed " , this , " _connection_failed " ) ;
multiplayer - > disconnect ( " server_disconnected " , this , " _server_disconnected " ) ;
2016-08-14 23:49:50 +02:00
}
2018-05-08 10:51:04 +02:00
multiplayer = p_multiplayer ;
multiplayer - > set_root_node ( root ) ;
2016-08-14 23:49:50 +02:00
2018-05-08 10:51:04 +02:00
multiplayer - > connect ( " network_peer_connected " , this , " _network_peer_connected " ) ;
multiplayer - > connect ( " network_peer_disconnected " , this , " _network_peer_disconnected " ) ;
multiplayer - > connect ( " connected_to_server " , this , " _connected_to_server " ) ;
multiplayer - > connect ( " connection_failed " , this , " _connection_failed " ) ;
multiplayer - > connect ( " server_disconnected " , this , " _server_disconnected " ) ;
2018-03-03 18:30:11 +01:00
}
2016-08-14 23:49:50 +02:00
2018-03-03 18:30:11 +01:00
void SceneTree : : set_network_peer ( const Ref < NetworkedMultiplayerPeer > & p_network_peer ) {
2018-05-08 10:51:04 +02:00
multiplayer - > set_network_peer ( p_network_peer ) ;
2016-08-14 23:49:50 +02:00
}
2018-01-11 23:35:12 +01:00
Ref < NetworkedMultiplayerPeer > SceneTree : : get_network_peer ( ) const {
2018-05-08 10:51:04 +02:00
return multiplayer - > get_network_peer ( ) ;
2018-01-11 23:35:12 +01:00
}
2016-08-14 23:49:50 +02:00
bool SceneTree : : is_network_server ( ) const {
2018-05-08 10:51:04 +02:00
return multiplayer - > is_network_server ( ) ;
2016-08-14 23:49:50 +02:00
}
2017-03-04 11:35:44 +01:00
bool SceneTree : : has_network_peer ( ) const {
2018-05-08 10:51:04 +02:00
return multiplayer - > has_network_peer ( ) ;
2017-03-04 11:35:44 +01:00
}
2016-08-19 21:48:08 +02:00
int SceneTree : : get_network_unique_id ( ) const {
2018-05-08 10:51:04 +02:00
return multiplayer - > get_network_unique_id ( ) ;
2016-08-19 21:48:08 +02:00
}
2017-07-03 15:44:45 +02:00
Vector < int > SceneTree : : get_network_connected_peers ( ) const {
2018-05-08 10:51:04 +02:00
return multiplayer - > get_network_connected_peers ( ) ;
2017-07-03 15:44:45 +02:00
}
2017-08-23 10:43:25 +02:00
int SceneTree : : get_rpc_sender_id ( ) const {
2018-05-08 10:51:04 +02:00
return multiplayer - > get_rpc_sender_id ( ) ;
2017-08-23 10:43:25 +02:00
}
2016-08-19 21:48:08 +02:00
void SceneTree : : set_refuse_new_network_connections ( bool p_refuse ) {
2018-05-08 10:51:04 +02:00
multiplayer - > set_refuse_new_network_connections ( p_refuse ) ;
2016-08-19 21:48:08 +02:00
}
bool SceneTree : : is_refusing_new_network_connections ( ) const {
2018-05-08 10:51:04 +02:00
return multiplayer - > is_refusing_new_network_connections ( ) ;
2016-08-14 23:49:50 +02:00
}
2014-11-06 01:20:42 +01:00
void SceneTree : : _bind_methods ( ) {
2017-08-09 13:19:41 +02:00
ClassDB : : bind_method ( D_METHOD ( " get_root " ) , & SceneTree : : get_root ) ;
2017-03-05 16:44:50 +01:00
ClassDB : : bind_method ( D_METHOD ( " has_group " , " name " ) , & SceneTree : : has_group ) ;
2014-02-10 02:10:30 +01:00
2017-03-05 16:44:50 +01:00
ClassDB : : bind_method ( D_METHOD ( " set_auto_accept_quit " , " enabled " ) , & SceneTree : : set_auto_accept_quit ) ;
2017-12-30 13:15:17 +01:00
ClassDB : : bind_method ( D_METHOD ( " set_quit_on_go_back " , " enabled " ) , & SceneTree : : set_quit_on_go_back ) ;
2014-02-10 02:10:30 +01:00
2017-03-05 16:44:50 +01:00
ClassDB : : bind_method ( D_METHOD ( " set_debug_collisions_hint " , " enable " ) , & SceneTree : : set_debug_collisions_hint ) ;
ClassDB : : bind_method ( D_METHOD ( " is_debugging_collisions_hint " ) , & SceneTree : : is_debugging_collisions_hint ) ;
ClassDB : : bind_method ( D_METHOD ( " set_debug_navigation_hint " , " enable " ) , & SceneTree : : set_debug_navigation_hint ) ;
ClassDB : : bind_method ( D_METHOD ( " is_debugging_navigation_hint " ) , & SceneTree : : is_debugging_navigation_hint ) ;
2015-09-20 18:03:46 +02:00
2017-08-09 13:19:41 +02:00
ClassDB : : bind_method ( D_METHOD ( " set_edited_scene_root " , " scene " ) , & SceneTree : : set_edited_scene_root ) ;
ClassDB : : bind_method ( D_METHOD ( " get_edited_scene_root " ) , & SceneTree : : get_edited_scene_root ) ;
2014-02-10 02:10:30 +01:00
2017-03-05 16:44:50 +01:00
ClassDB : : bind_method ( D_METHOD ( " set_pause " , " enable " ) , & SceneTree : : set_pause ) ;
ClassDB : : bind_method ( D_METHOD ( " is_paused " ) , & SceneTree : : is_paused ) ;
ClassDB : : bind_method ( D_METHOD ( " set_input_as_handled " ) , & SceneTree : : set_input_as_handled ) ;
2017-03-16 17:52:50 +01:00
ClassDB : : bind_method ( D_METHOD ( " is_input_handled " ) , & SceneTree : : is_input_handled ) ;
2014-02-10 02:10:30 +01:00
2017-08-09 13:19:41 +02:00
ClassDB : : bind_method ( D_METHOD ( " create_timer " , " time_sec " , " pause_mode_process " ) , & SceneTree : : create_timer , DEFVAL ( true ) ) ;
2014-02-10 02:10:30 +01:00
2017-03-05 16:44:50 +01:00
ClassDB : : bind_method ( D_METHOD ( " get_node_count " ) , & SceneTree : : get_node_count ) ;
ClassDB : : bind_method ( D_METHOD ( " get_frame " ) , & SceneTree : : get_frame ) ;
2019-12-29 16:39:24 +01:00
ClassDB : : bind_method ( D_METHOD ( " quit " , " exit_code " ) , & SceneTree : : quit , DEFVAL ( - 1 ) ) ;
2014-02-10 02:10:30 +01:00
2021-09-29 17:35:25 +02:00
ClassDB : : bind_method ( D_METHOD ( " set_screen_stretch " , " mode " , " aspect " , " minsize " , " scale " ) , & SceneTree : : set_screen_stretch , DEFVAL ( 1 ) ) ;
2015-05-17 21:33:35 +02:00
2021-09-15 13:30:45 +02:00
ClassDB : : bind_method ( D_METHOD ( " set_physics_interpolation_enabled " , " enabled " ) , & SceneTree : : set_physics_interpolation_enabled ) ;
ClassDB : : bind_method ( D_METHOD ( " is_physics_interpolation_enabled " ) , & SceneTree : : is_physics_interpolation_enabled ) ;
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 " ) ) ;
mi . arguments . push_back ( PropertyInfo ( Variant : : STRING , " group " ) ) ;
mi . arguments . push_back ( PropertyInfo ( Variant : : STRING , " 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 " ;
mi2 . arguments . push_back ( PropertyInfo ( Variant : : STRING , " group " ) ) ;
mi2 . arguments . push_back ( PropertyInfo ( Variant : : STRING , " method " ) ) ;
2017-01-14 14:03:53 +01:00
2017-03-05 16:44:50 +01:00
ClassDB : : bind_vararg_method ( METHOD_FLAGS_DEFAULT , " call_group " , & SceneTree : : _call_group , mi2 ) ;
2014-02-10 02:10:30 +01:00
2017-08-09 13:54:55 +02:00
ClassDB : : bind_method ( D_METHOD ( " notify_group " , " group " , " notification " ) , & SceneTree : : notify_group ) ;
ClassDB : : bind_method ( D_METHOD ( " set_group " , " group " , " property " , " value " ) , & SceneTree : : set_group ) ;
2015-05-17 21:33:35 +02:00
2017-03-05 16:44:50 +01:00
ClassDB : : bind_method ( D_METHOD ( " get_nodes_in_group " , " group " ) , & SceneTree : : _get_nodes_in_group ) ;
2015-05-17 21:33:35 +02:00
2017-08-09 13:19:41 +02:00
ClassDB : : bind_method ( D_METHOD ( " set_current_scene " , " child_node " ) , & SceneTree : : set_current_scene ) ;
ClassDB : : bind_method ( D_METHOD ( " get_current_scene " ) , & SceneTree : : get_current_scene ) ;
2015-05-17 21:33:35 +02:00
2017-03-05 16:44:50 +01:00
ClassDB : : bind_method ( D_METHOD ( " change_scene " , " path " ) , & SceneTree : : change_scene ) ;
2017-08-09 13:19:41 +02:00
ClassDB : : bind_method ( D_METHOD ( " change_scene_to " , " packed_scene " ) , & SceneTree : : change_scene_to ) ;
2015-05-17 21:33:35 +02:00
2017-03-05 16:44:50 +01:00
ClassDB : : bind_method ( D_METHOD ( " reload_current_scene " ) , & SceneTree : : reload_current_scene ) ;
2016-08-14 23:49:50 +02:00
2017-03-05 16:44:50 +01:00
ClassDB : : bind_method ( D_METHOD ( " _change_scene " ) , & SceneTree : : _change_scene ) ;
2016-08-14 23:49:50 +02:00
2018-05-08 10:51:04 +02:00
ClassDB : : bind_method ( D_METHOD ( " set_multiplayer " , " multiplayer " ) , & SceneTree : : set_multiplayer ) ;
ClassDB : : bind_method ( D_METHOD ( " get_multiplayer " ) , & SceneTree : : get_multiplayer ) ;
2018-06-02 14:32:30 +02:00
ClassDB : : bind_method ( D_METHOD ( " set_multiplayer_poll_enabled " , " enabled " ) , & SceneTree : : set_multiplayer_poll_enabled ) ;
ClassDB : : bind_method ( D_METHOD ( " is_multiplayer_poll_enabled " ) , & SceneTree : : is_multiplayer_poll_enabled ) ;
2017-08-09 13:19:41 +02:00
ClassDB : : bind_method ( D_METHOD ( " set_network_peer " , " peer " ) , & SceneTree : : set_network_peer ) ;
2018-01-11 23:35:12 +01:00
ClassDB : : bind_method ( D_METHOD ( " get_network_peer " ) , & SceneTree : : get_network_peer ) ;
2017-03-05 16:44:50 +01:00
ClassDB : : bind_method ( D_METHOD ( " is_network_server " ) , & SceneTree : : is_network_server ) ;
ClassDB : : bind_method ( D_METHOD ( " has_network_peer " ) , & SceneTree : : has_network_peer ) ;
2017-07-03 15:44:45 +02:00
ClassDB : : bind_method ( D_METHOD ( " get_network_connected_peers " ) , & SceneTree : : get_network_connected_peers ) ;
2017-03-05 16:44:50 +01:00
ClassDB : : bind_method ( D_METHOD ( " get_network_unique_id " ) , & SceneTree : : get_network_unique_id ) ;
2017-08-23 10:43:25 +02:00
ClassDB : : bind_method ( D_METHOD ( " get_rpc_sender_id " ) , & SceneTree : : get_rpc_sender_id ) ;
2017-03-05 16:44:50 +01:00
ClassDB : : bind_method ( D_METHOD ( " set_refuse_new_network_connections " , " refuse " ) , & SceneTree : : set_refuse_new_network_connections ) ;
ClassDB : : bind_method ( D_METHOD ( " is_refusing_new_network_connections " ) , & SceneTree : : is_refusing_new_network_connections ) ;
ClassDB : : bind_method ( D_METHOD ( " _network_peer_connected " ) , & SceneTree : : _network_peer_connected ) ;
ClassDB : : bind_method ( D_METHOD ( " _network_peer_disconnected " ) , & SceneTree : : _network_peer_disconnected ) ;
ClassDB : : bind_method ( D_METHOD ( " _connected_to_server " ) , & SceneTree : : _connected_to_server ) ;
ClassDB : : bind_method ( D_METHOD ( " _connection_failed " ) , & SceneTree : : _connection_failed ) ;
ClassDB : : bind_method ( D_METHOD ( " _server_disconnected " ) , & SceneTree : : _server_disconnected ) ;
2014-02-10 02:10:30 +01:00
2017-12-19 22:48:30 +01:00
ClassDB : : bind_method ( D_METHOD ( " set_use_font_oversampling " , " enable " ) , & SceneTree : : set_use_font_oversampling ) ;
ClassDB : : bind_method ( D_METHOD ( " is_using_font_oversampling " ) , & SceneTree : : is_using_font_oversampling ) ;
2018-01-11 23:35:12 +01:00
ADD_PROPERTY ( PropertyInfo ( Variant : : BOOL , " debug_collisions_hint " ) , " set_debug_collisions_hint " , " is_debugging_collisions_hint " ) ;
ADD_PROPERTY ( PropertyInfo ( Variant : : BOOL , " debug_navigation_hint " ) , " set_debug_navigation_hint " , " is_debugging_navigation_hint " ) ;
ADD_PROPERTY ( PropertyInfo ( Variant : : BOOL , " paused " ) , " set_pause " , " is_paused " ) ;
ADD_PROPERTY ( PropertyInfo ( Variant : : BOOL , " refuse_new_network_connections " ) , " set_refuse_new_network_connections " , " is_refusing_new_network_connections " ) ;
2019-06-01 15:42:22 +02:00
ADD_PROPERTY_DEFAULT ( " refuse_new_network_connections " , false ) ;
2018-01-11 23:35:12 +01:00
ADD_PROPERTY ( PropertyInfo ( Variant : : BOOL , " use_font_oversampling " ) , " set_use_font_oversampling " , " is_using_font_oversampling " ) ;
ADD_PROPERTY ( PropertyInfo ( Variant : : OBJECT , " edited_scene_root " , PROPERTY_HINT_RESOURCE_TYPE , " Node " , 0 ) , " set_edited_scene_root " , " get_edited_scene_root " ) ;
ADD_PROPERTY ( PropertyInfo ( Variant : : OBJECT , " current_scene " , PROPERTY_HINT_RESOURCE_TYPE , " Node " , 0 ) , " set_current_scene " , " get_current_scene " ) ;
ADD_PROPERTY ( PropertyInfo ( Variant : : OBJECT , " network_peer " , PROPERTY_HINT_RESOURCE_TYPE , " NetworkedMultiplayerPeer " , 0 ) , " set_network_peer " , " get_network_peer " ) ;
ADD_PROPERTY ( PropertyInfo ( Variant : : OBJECT , " root " , PROPERTY_HINT_RESOURCE_TYPE , " Node " , 0 ) , " " , " get_root " ) ;
2018-05-08 10:51:04 +02:00
ADD_PROPERTY ( PropertyInfo ( Variant : : OBJECT , " multiplayer " , PROPERTY_HINT_RESOURCE_TYPE , " MultiplayerAPI " , 0 ) , " set_multiplayer " , " get_multiplayer " ) ;
2018-06-02 14:32:30 +02:00
ADD_PROPERTY ( PropertyInfo ( Variant : : BOOL , " multiplayer_poll " ) , " set_multiplayer_poll_enabled " , " is_multiplayer_poll_enabled " ) ;
2021-09-15 13:30:45 +02:00
ADD_PROPERTY ( PropertyInfo ( Variant : : BOOL , " physics_interpolation " ) , " set_physics_interpolation_enabled " , " is_physics_interpolation_enabled " ) ;
2018-01-11 23:35:12 +01:00
2017-03-05 16:44:50 +01:00
ADD_SIGNAL ( MethodInfo ( " tree_changed " ) ) ;
2018-09-01 12:05:51 +02:00
ADD_SIGNAL ( MethodInfo ( " node_added " , PropertyInfo ( Variant : : OBJECT , " node " , PROPERTY_HINT_RESOURCE_TYPE , " Node " ) ) ) ;
ADD_SIGNAL ( MethodInfo ( " node_removed " , PropertyInfo ( Variant : : OBJECT , " node " , PROPERTY_HINT_RESOURCE_TYPE , " Node " ) ) ) ;
2019-05-24 15:27:22 +02:00
ADD_SIGNAL ( MethodInfo ( " node_renamed " , PropertyInfo ( Variant : : OBJECT , " node " , PROPERTY_HINT_RESOURCE_TYPE , " Node " ) ) ) ;
2017-03-05 16:44:50 +01:00
ADD_SIGNAL ( MethodInfo ( " screen_resized " ) ) ;
2018-09-01 12:05:51 +02:00
ADD_SIGNAL ( MethodInfo ( " node_configuration_warning_changed " , PropertyInfo ( Variant : : OBJECT , " node " , PROPERTY_HINT_RESOURCE_TYPE , " Node " ) ) ) ;
2015-06-12 18:53:18 +02:00
2017-03-05 16:44:50 +01:00
ADD_SIGNAL ( MethodInfo ( " idle_frame " ) ) ;
2017-09-30 16:19:07 +02:00
ADD_SIGNAL ( MethodInfo ( " physics_frame " ) ) ;
2016-05-27 19:18:40 +02:00
2017-03-05 16:44:50 +01:00
ADD_SIGNAL ( MethodInfo ( " files_dropped " , PropertyInfo ( Variant : : POOL_STRING_ARRAY , " files " ) , PropertyInfo ( Variant : : INT , " screen " ) ) ) ;
2021-04-28 09:40:47 +02:00
ADD_SIGNAL ( MethodInfo ( " global_menu_action " ,
PropertyInfo ( Variant : : NIL , " id " , PROPERTY_HINT_NONE , " " , PROPERTY_USAGE_NIL_IS_VARIANT ) ,
PropertyInfo ( Variant : : NIL , " meta " , PROPERTY_HINT_NONE , " " , PROPERTY_USAGE_NIL_IS_VARIANT ) ) ) ;
2017-03-05 16:44:50 +01:00
ADD_SIGNAL ( MethodInfo ( " network_peer_connected " , PropertyInfo ( Variant : : INT , " id " ) ) ) ;
ADD_SIGNAL ( MethodInfo ( " network_peer_disconnected " , PropertyInfo ( Variant : : INT , " id " ) ) ) ;
ADD_SIGNAL ( MethodInfo ( " connected_to_server " ) ) ;
ADD_SIGNAL ( MethodInfo ( " connection_failed " ) ) ;
ADD_SIGNAL ( MethodInfo ( " server_disconnected " ) ) ;
2014-02-10 02:10:30 +01:00
2017-08-20 17:45:01 +02:00
BIND_ENUM_CONSTANT ( GROUP_CALL_DEFAULT ) ;
BIND_ENUM_CONSTANT ( GROUP_CALL_REVERSE ) ;
BIND_ENUM_CONSTANT ( GROUP_CALL_REALTIME ) ;
BIND_ENUM_CONSTANT ( GROUP_CALL_UNIQUE ) ;
BIND_ENUM_CONSTANT ( STRETCH_MODE_DISABLED ) ;
BIND_ENUM_CONSTANT ( STRETCH_MODE_2D ) ;
BIND_ENUM_CONSTANT ( STRETCH_MODE_VIEWPORT ) ;
BIND_ENUM_CONSTANT ( STRETCH_ASPECT_IGNORE ) ;
BIND_ENUM_CONSTANT ( STRETCH_ASPECT_KEEP ) ;
BIND_ENUM_CONSTANT ( STRETCH_ASPECT_KEEP_WIDTH ) ;
BIND_ENUM_CONSTANT ( STRETCH_ASPECT_KEEP_HEIGHT ) ;
2017-09-24 20:29:18 +02:00
BIND_ENUM_CONSTANT ( STRETCH_ASPECT_EXPAND ) ;
2014-02-10 02:10:30 +01:00
}
2021-05-04 16:00:45 +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
}
2017-12-19 22:48:30 +01:00
void SceneTree : : set_use_font_oversampling ( bool p_oversampling ) {
2021-05-05 12:44:11 +02:00
if ( use_font_oversampling = = p_oversampling ) {
2019-01-26 19:41:26 +01:00
return ;
2021-05-05 12:44:11 +02:00
}
2019-01-26 19:41:26 +01:00
2017-12-19 22:48:30 +01:00
use_font_oversampling = p_oversampling ;
2019-01-26 19:41:26 +01:00
_update_root_rect ( ) ;
2017-12-19 22:48:30 +01:00
}
bool SceneTree : : is_using_font_oversampling ( ) const {
return use_font_oversampling ;
}
2019-03-09 03:05:59 +01:00
void SceneTree : : get_argument_options ( const StringName & p_function , int p_idx , List < String > * r_options ) const {
if ( p_function = = " change_scene " ) {
DirAccessRef dir_access = DirAccess : : create ( DirAccess : : ACCESS_RESOURCES ) ;
List < String > directories ;
directories . push_back ( dir_access - > get_current_dir ( ) ) ;
while ( ! directories . empty ( ) ) {
dir_access - > change_dir ( directories . back ( ) - > get ( ) ) ;
directories . pop_back ( ) ;
dir_access - > list_dir_begin ( ) ;
String filename = dir_access - > get_next ( ) ;
while ( filename ! = " " ) {
if ( filename = = " . " | | filename = = " .. " ) {
filename = dir_access - > get_next ( ) ;
continue ;
}
if ( dir_access - > dir_exists ( filename ) ) {
directories . push_back ( dir_access - > get_current_dir ( ) . plus_file ( filename ) ) ;
} else if ( filename . ends_with ( " .tscn " ) | | filename . ends_with ( " .scn " ) ) {
r_options - > push_back ( " \" " + dir_access - > get_current_dir ( ) . plus_file ( filename ) + " \" " ) ;
}
filename = dir_access - > get_next ( ) ;
}
}
}
}
2014-11-06 01:20:42 +01:00
SceneTree : : SceneTree ( ) {
2021-05-05 12:44:11 +02:00
if ( singleton = = nullptr ) {
2021-05-04 14:28:27 +02:00
singleton = this ;
2021-05-05 12:44:11 +02:00
}
2017-03-05 16:44:50 +01:00
_quit = false ;
2017-04-25 13:05:22 +02:00
accept_quit = true ;
quit_on_go_back = true ;
2017-03-05 16:44:50 +01:00
initialized = false ;
2019-01-26 19:41:26 +01:00
use_font_oversampling = false ;
2017-04-07 16:17:16 +02:00
# ifdef DEBUG_ENABLED
2017-03-05 16:44:50 +01:00
debug_collisions_hint = false ;
debug_navigation_hint = false ;
2017-04-07 16:17:16 +02:00
# endif
2021-02-21 17:55:54 +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 ) ) ;
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 15:45:40 +01:00
GLOBAL_DEF ( " debug/shapes/collision/draw_2d_outlines " , true ) ;
2017-03-05 16:44:50 +01:00
tree_version = 1 ;
2017-09-30 16:19:07 +02:00
physics_process_time = 1 ;
2017-03-05 16:44:50 +01:00
idle_process_time = 1 ;
2017-12-26 13:48:50 +01:00
2021-05-04 16:00:45 +02:00
root = nullptr ;
2019-07-02 16:23:54 +02:00
input_handled = false ;
pause = false ;
2017-03-05 16:44:50 +01:00
current_frame = 0 ;
2017-12-26 13:48:50 +01:00
current_event = 0 ;
2017-03-05 16:44:50 +01:00
tree_changed_name = " tree_changed " ;
2017-10-19 02:30:27 +02:00
node_added_name = " node_added " ;
2017-03-05 16:44:50 +01:00
node_removed_name = " node_removed " ;
2019-05-24 15:27:22 +02:00
node_renamed_name = " node_renamed " ;
2017-03-05 16:44:50 +01:00
ugc_locked = false ;
call_lock = 0 ;
root_lock = 0 ;
node_count = 0 ;
2021-09-15 13:30:45 +02:00
_physics_interpolation_enabled = false ;
2014-02-10 02:10:30 +01:00
//create with mainloop
2017-03-05 16:44:50 +01:00
root = memnew ( Viewport ) ;
2014-02-10 02:10:30 +01:00
root - > set_name ( " root " ) ;
2018-11-15 17:54:26 +01:00
root - > set_handle_input_locally ( false ) ;
2021-05-05 12:44:11 +02:00
if ( ! root - > get_world ( ) . is_valid ( ) ) {
2017-05-29 02:46:48 +02:00
root - > set_world ( Ref < World > ( memnew ( World ) ) ) ;
2021-05-05 12:44:11 +02:00
}
2022-02-21 11:32:42 +01:00
2021-09-15 13:30:45 +02:00
set_physics_interpolation_enabled ( GLOBAL_DEF ( " physics/common/physics_interpolation " , false ) ) ;
2022-02-21 11:32:42 +01:00
// Always disable jitter fix if physics interpolation is enabled -
// Jitter fix will interfere with interpolation, and is not necessary
// when interpolation is active.
if ( is_physics_interpolation_enabled ( ) ) {
Engine : : get_singleton ( ) - > set_physics_jitter_fix ( 0 ) ;
}
2017-05-29 02:46:48 +02:00
2018-03-03 18:30:11 +01:00
// Initialize network state
2018-06-02 14:32:30 +02:00
multiplayer_poll = true ;
2018-05-08 10:51:04 +02:00
set_multiplayer ( Ref < MultiplayerAPI > ( memnew ( MultiplayerAPI ) ) ) ;
2018-03-03 18:30:11 +01:00
2014-02-10 02:10:30 +01:00
root - > set_as_audio_listener ( true ) ;
root - > set_as_audio_listener_2d ( true ) ;
2021-05-04 16:00:45 +02:00
current_scene = nullptr ;
2014-02-10 02:10:30 +01:00
2020-10-10 17:04:00 +02:00
int ref_atlas_size = GLOBAL_DEF_RST ( " rendering/quality/reflections/atlas_size " , 2048 ) ;
2022-02-03 11:57:32 +01:00
ProjectSettings : : get_singleton ( ) - > set_custom_property_info ( " rendering/quality/reflections/atlas_size " , PropertyInfo ( Variant : : INT , " rendering/quality/reflections/atlas_size " , PROPERTY_HINT_RANGE , " 0,8192,1,or_greater " ) ) ; // next_power_of_2 will return a 0 as min value.
2020-10-10 17:04:00 +02:00
int ref_atlas_subdiv = GLOBAL_DEF_RST ( " rendering/quality/reflections/atlas_subdiv " , 8 ) ;
2022-02-03 11:57:32 +01:00
ProjectSettings : : get_singleton ( ) - > set_custom_property_info ( " rendering/quality/reflections/atlas_subdiv " , PropertyInfo ( Variant : : INT , " rendering/quality/reflections/atlas_subdiv " , PROPERTY_HINT_RANGE , " 0,32,1,or_greater " ) ) ; // next_power_of_2 will return a 0 as min value.
2017-07-18 02:05:38 +02:00
int msaa_mode = GLOBAL_DEF ( " rendering/quality/filters/msaa " , 0 ) ;
2019-11-16 15:36:43 +01:00
ProjectSettings : : get_singleton ( ) - > set_custom_property_info ( " rendering/quality/filters/msaa " , PropertyInfo ( Variant : : INT , " rendering/quality/filters/msaa " , PROPERTY_HINT_ENUM , " Disabled,2x,4x,8x,16x,AndroidVR 2x,AndroidVR 4x " ) ) ;
2017-01-02 02:16:52 +01:00
root - > set_msaa ( Viewport : : MSAA ( msaa_mode ) ) ;
2017-07-19 22:00:46 +02:00
2020-08-22 00:15:50 +02:00
const bool use_fxaa = GLOBAL_DEF ( " rendering/quality/filters/use_fxaa " , false ) ;
root - > set_use_fxaa ( use_fxaa ) ;
2020-10-20 18:58:07 +02:00
const bool use_debanding = GLOBAL_DEF ( " rendering/quality/filters/use_debanding " , false ) ;
root - > set_use_debanding ( use_debanding ) ;
2021-03-27 18:58:12 +01:00
const float sharpen_intensity = GLOBAL_GET ( " rendering/quality/filters/sharpen_intensity " ) ;
root - > set_sharpen_intensity ( sharpen_intensity ) ;
2021-08-16 03:16:01 +02:00
GLOBAL_DEF ( " rendering/quality/depth/hdr " , true ) ;
2017-07-19 22:00:46 +02:00
GLOBAL_DEF ( " rendering/quality/depth/hdr.mobile " , false ) ;
2021-08-16 03:16:01 +02:00
const bool hdr = GLOBAL_GET ( " rendering/quality/depth/hdr " ) ;
2017-01-02 02:16:52 +01:00
root - > set_hdr ( hdr ) ;
2016-11-19 17:23:37 +01:00
2021-08-16 03:16:01 +02:00
GLOBAL_DEF ( " rendering/quality/depth/use_32_bpc_depth " , false ) ;
const bool use_32_bpc_depth = GLOBAL_GET ( " rendering/quality/depth/use_32_bpc_depth " ) ;
root - > set_use_32_bpc_depth ( use_32_bpc_depth ) ;
2017-03-05 16:44:50 +01:00
VS : : get_singleton ( ) - > scenario_set_reflection_atlas_size ( root - > get_world ( ) - > get_scenario ( ) , ref_atlas_size , ref_atlas_subdiv ) ;
2016-11-19 17:23:37 +01:00
2017-05-29 02:46:48 +02:00
{ //load default fallback environment
//get possible extensions
List < String > exts ;
ResourceLoader : : get_recognized_extensions_for_type ( " Environment " , & exts ) ;
String ext_hint ;
for ( List < String > : : Element * E = exts . front ( ) ; E ; E = E - > next ( ) ) {
2021-05-05 12:44:11 +02:00
if ( ext_hint ! = String ( ) ) {
2017-05-29 02:46:48 +02:00
ext_hint + = " , " ;
2021-05-05 12:44:11 +02:00
}
2017-05-29 02:46:48 +02:00
ext_hint + = " *. " + E - > get ( ) ;
}
//get path
2017-07-18 02:05:38 +02:00
String env_path = GLOBAL_DEF ( " rendering/environment/default_environment " , " " ) ;
2017-05-29 02:46:48 +02:00
//setup property
2017-07-19 22:00:46 +02:00
ProjectSettings : : get_singleton ( ) - > set_custom_property_info ( " rendering/environment/default_environment " , PropertyInfo ( Variant : : STRING , " rendering/viewport/default_environment " , PROPERTY_HINT_FILE , ext_hint ) ) ;
2017-05-29 02:46:48 +02:00
env_path = env_path . strip_edges ( ) ;
if ( env_path ! = String ( ) ) {
Ref < Environment > env = ResourceLoader : : load ( env_path ) ;
if ( env . is_valid ( ) ) {
root - > get_world ( ) - > set_fallback_environment ( env ) ;
} else {
2017-08-19 01:02:56 +02:00
if ( Engine : : get_singleton ( ) - > is_editor_hint ( ) ) {
2017-05-29 02:46:48 +02:00
//file was erased, clear the field.
2017-07-19 22:00:46 +02:00
ProjectSettings : : get_singleton ( ) - > set ( " rendering/environment/default_environment " , " " ) ;
2017-05-29 02:46:48 +02:00
} else {
//file was erased, notify user.
2021-06-16 12:56:25 +02:00
ERR_PRINT ( RTR ( " Default Environment as specified in Project Settings (Rendering -> Environment -> Default Environment) could not be loaded. " ) ) ;
2017-05-29 02:46:48 +02:00
}
}
}
}
2017-03-05 16:44:50 +01:00
stretch_mode = STRETCH_MODE_DISABLED ;
stretch_aspect = STRETCH_ASPECT_IGNORE ;
2021-09-29 17:35:25 +02:00
stretch_scale = 1.0 ;
2014-04-15 03:43:44 +02:00
2022-01-28 23:02:48 +01:00
last_screen_size = OS : : get_singleton ( ) - > get_window_size ( ) ;
2017-04-10 01:40:48 +02:00
_update_root_rect ( ) ;
2014-02-10 02:10:30 +01:00
if ( ScriptDebugger : : get_singleton ( ) ) {
2019-04-06 22:55:01 +02:00
if ( ScriptDebugger : : get_singleton ( ) - > is_remote ( ) ) {
ScriptDebuggerRemote * remote_debugger = static_cast < ScriptDebuggerRemote * > ( ScriptDebugger : : get_singleton ( ) ) ;
remote_debugger - > set_scene_tree ( this ) ;
}
2019-09-01 18:38:58 +02:00
ScriptDebugger : : get_singleton ( ) - > set_multiplayer ( multiplayer ) ;
2014-02-10 02:10:30 +01: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
2014-10-14 06:01:25 +02:00
# ifdef TOOLS_ENABLED
2021-05-04 16:00:45 +02:00
edited_scene_root = nullptr ;
2014-10-14 06:01:25 +02:00
# endif
2014-10-12 07:13:22 +02:00
2015-08-02 17:29:37 +02:00
# ifdef DEBUG_ENABLED
2017-03-05 16:44:50 +01:00
live_edit_root = NodePath ( " /root " ) ;
2015-08-02 17:29:37 +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 ) {
2021-05-04 16:00:45 +02:00
root - > _set_tree ( nullptr ) ;
2022-03-12 12:48:15 +01:00
root - > _propagate_after_exit_branch ( true ) ;
2019-06-01 15:42:22 +02:00
memdelete ( root ) ;
}
2021-05-05 12:44:11 +02:00
if ( singleton = = this ) {
2021-05-04 16:00:45 +02:00
singleton = nullptr ;
2021-05-05 12:44:11 +02:00
}
2014-02-10 02:10:30 +01:00
}