2014-02-10 01:10:30 +00:00
/*************************************************************************/
/* packed_scene.cpp */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
2017-08-27 12:16:55 +00:00
/* https://godotengine.org */
2014-02-10 01:10:30 +00:00
/*************************************************************************/
2018-01-01 13:40:08 +00:00
/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */
/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */
2014-02-10 01:10:30 +00:00
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
/* "Software"), to deal in the Software without restriction, including */
/* without limitation the rights to use, copy, modify, merge, publish, */
/* distribute, sublicense, and/or sell copies of the Software, and to */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions: */
/* */
/* The above copyright notice and this permission notice shall be */
/* included in all copies or substantial portions of the Software. */
/* */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
2018-01-04 23:50:27 +00:00
2014-02-23 13:35:05 +00:00
# include "packed_scene.h"
2017-08-27 19:07:15 +00:00
2017-03-05 15:44:50 +00:00
# include "core/core_string_names.h"
2018-09-11 16:13:45 +00:00
# include "core/engine.h"
# include "core/io/resource_loader.h"
# include "core/project_settings.h"
2017-03-05 15:44:50 +00:00
# include "scene/2d/node_2d.h"
2014-10-07 04:31:49 +00:00
# include "scene/3d/spatial.h"
# include "scene/gui/control.h"
2015-10-16 22:11:23 +00:00
# include "scene/main/instance_placeholder.h"
2017-08-27 19:07:15 +00:00
2015-10-10 12:09:09 +00:00
# define PACK_VERSION 2
bool SceneState : : can_instance ( ) const {
2014-02-23 13:35:05 +00:00
2017-03-05 15:44:50 +00:00
return nodes . size ( ) > 0 ;
2014-02-23 13:35:05 +00:00
}
2017-01-10 04:04:31 +00:00
Node * SceneState : : instance ( GenEditState p_edit_state ) const {
2015-10-10 12:09:09 +00:00
// nodes where instancing failed (because something is missing)
2017-03-05 15:44:50 +00:00
List < Node * > stray_instances ;
2015-10-10 12:09:09 +00:00
2017-03-05 15:44:50 +00:00
# define NODE_FROM_ID(p_name, p_id) \
Node * p_name ; \
if ( p_id & FLAG_ID_IS_PATH ) { \
NodePath np = node_paths [ p_id & FLAG_MASK ] ; \
p_name = ret_nodes [ 0 ] - > _get_node ( np ) ; \
} else { \
ERR_FAIL_INDEX_V ( p_id & FLAG_MASK , nc , NULL ) ; \
p_name = ret_nodes [ p_id & FLAG_MASK ] ; \
2015-10-10 12:09:09 +00:00
}
2014-02-23 13:35:05 +00:00
int nc = nodes . size ( ) ;
2017-03-05 15:44:50 +00:00
ERR_FAIL_COND_V ( nc = = 0 , NULL ) ;
2014-02-23 13:35:05 +00:00
2017-03-05 15:44:50 +00:00
const StringName * snames = NULL ;
int sname_count = names . size ( ) ;
2014-02-23 13:35:05 +00:00
if ( sname_count )
2017-03-05 15:44:50 +00:00
snames = & names [ 0 ] ;
2014-02-23 13:35:05 +00:00
2017-03-05 15:44:50 +00:00
const Variant * props = NULL ;
int prop_count = variants . size ( ) ;
2014-02-23 13:35:05 +00:00
if ( prop_count )
2017-03-05 15:44:50 +00:00
props = & variants [ 0 ] ;
2014-02-23 13:35:05 +00:00
2015-06-29 03:29:49 +00:00
//Vector<Variant> properties;
2014-02-23 13:35:05 +00:00
const NodeData * nd = & nodes [ 0 ] ;
2017-03-05 15:44:50 +00:00
Node * * ret_nodes = ( Node * * ) alloca ( sizeof ( Node * ) * nc ) ;
2014-02-23 13:35:05 +00:00
2017-03-05 15:44:50 +00:00
bool gen_node_path_cache = p_edit_state ! = GEN_EDIT_STATE_DISABLED & & node_path_cache . empty ( ) ;
2017-01-10 04:04:31 +00:00
2017-03-05 15:44:50 +00:00
Map < Ref < Resource > , Ref < Resource > > resources_local_to_scene ;
2014-02-23 13:35:05 +00:00
2017-03-05 15:44:50 +00:00
for ( int i = 0 ; i < nc ; i + + ) {
2014-02-23 13:35:05 +00:00
2017-03-05 15:44:50 +00:00
const NodeData & n = nd [ i ] ;
2014-02-23 13:35:05 +00:00
2017-03-05 15:44:50 +00:00
Node * parent = NULL ;
2015-10-10 12:09:09 +00:00
2017-03-05 15:44:50 +00:00
if ( i > 0 ) {
2015-10-10 12:09:09 +00:00
2017-03-05 15:44:50 +00:00
NODE_FROM_ID ( nparent , n . parent ) ;
2015-10-10 12:09:09 +00:00
# ifdef DEBUG_ENABLED
2017-09-07 19:48:50 +00:00
if ( ! nparent & & ( n . parent & FLAG_ID_IS_PATH ) ) {
2015-10-10 12:09:09 +00:00
2017-03-05 15:44:50 +00:00
WARN_PRINT ( String ( " Parent path ' " + String ( node_paths [ n . parent & FLAG_MASK ] ) + " ' for node ' " + String ( snames [ n . name ] ) + " ' has vanished when instancing: ' " + get_path ( ) + " '. " ) . ascii ( ) . get_data ( ) ) ;
2015-10-10 12:09:09 +00:00
}
# endif
2017-03-05 15:44:50 +00:00
parent = nparent ;
2014-02-23 13:35:05 +00:00
}
2017-03-05 15:44:50 +00:00
Node * node = NULL ;
2016-01-24 00:42:15 +00:00
2017-03-05 15:44:50 +00:00
if ( i = = 0 & & base_scene_idx > = 0 ) {
2015-10-10 12:09:09 +00:00
//scene inheritance on root node
2017-03-05 15:44:50 +00:00
Ref < PackedScene > sdata = props [ base_scene_idx ] ;
ERR_FAIL_COND_V ( ! sdata . is_valid ( ) , NULL ) ;
node = sdata - > instance ( p_edit_state = = GEN_EDIT_STATE_DISABLED ? PackedScene : : GEN_EDIT_STATE_DISABLED : PackedScene : : GEN_EDIT_STATE_INSTANCE ) ; //only main gets main edit state
ERR_FAIL_COND_V ( ! node , NULL ) ;
if ( p_edit_state ! = GEN_EDIT_STATE_DISABLED ) {
2015-10-10 12:09:09 +00:00
node - > set_scene_inherited_state ( sdata - > get_state ( ) ) ;
}
2017-03-05 15:44:50 +00:00
} else if ( n . instance > = 0 ) {
2015-10-10 12:09:09 +00:00
//instance a scene into this node
2017-03-05 15:44:50 +00:00
if ( n . instance & FLAG_INSTANCE_IS_PLACEHOLDER ) {
2015-10-16 22:11:23 +00:00
2017-03-05 15:44:50 +00:00
String path = props [ n . instance & FLAG_MASK ] ;
2015-10-16 22:11:23 +00:00
if ( disable_placeholders ) {
2017-03-05 15:44:50 +00:00
Ref < PackedScene > sdata = ResourceLoader : : load ( path , " PackedScene " ) ;
ERR_FAIL_COND_V ( ! sdata . is_valid ( ) , NULL ) ;
node = sdata - > instance ( p_edit_state = = GEN_EDIT_STATE_DISABLED ? PackedScene : : GEN_EDIT_STATE_DISABLED : PackedScene : : GEN_EDIT_STATE_INSTANCE ) ;
ERR_FAIL_COND_V ( ! node , NULL ) ;
2015-10-16 22:11:23 +00:00
} else {
2017-03-05 15:44:50 +00:00
InstancePlaceholder * ip = memnew ( InstancePlaceholder ) ;
2015-11-13 23:56:44 +00:00
ip - > set_instance_path ( path ) ;
2017-03-05 15:44:50 +00:00
node = ip ;
2015-10-16 22:11:23 +00:00
}
node - > set_scene_instance_load_placeholder ( true ) ;
} else {
2017-03-05 15:44:50 +00:00
Ref < PackedScene > sdata = props [ n . instance & FLAG_MASK ] ;
ERR_FAIL_COND_V ( ! sdata . is_valid ( ) , NULL ) ;
node = sdata - > instance ( p_edit_state = = GEN_EDIT_STATE_DISABLED ? PackedScene : : GEN_EDIT_STATE_DISABLED : PackedScene : : GEN_EDIT_STATE_INSTANCE ) ;
ERR_FAIL_COND_V ( ! node , NULL ) ;
2015-10-16 22:11:23 +00:00
}
2014-02-23 13:35:05 +00:00
2017-03-05 15:44:50 +00:00
} else if ( n . type = = TYPE_INSTANCED ) {
2015-10-10 12:09:09 +00:00
//get the node from somewhere, it likely already exists from another instance
if ( parent ) {
2017-03-05 15:44:50 +00:00
node = parent - > _get_child_by_name ( snames [ n . name ] ) ;
2015-10-10 12:09:09 +00:00
# ifdef DEBUG_ENABLED
if ( ! node ) {
2017-09-02 14:19:06 +00:00
WARN_PRINT ( String ( " Node ' " + String ( ret_nodes [ 0 ] - > get_path_to ( parent ) ) + " / " + String ( snames [ n . name ] ) + " ' was modified from inside an instance, but it has vanished. " ) . ascii ( ) . get_data ( ) ) ;
2015-10-10 12:09:09 +00:00
}
# endif
}
2017-01-03 02:03:46 +00:00
} else if ( ClassDB : : is_class_enabled ( snames [ n . type ] ) ) {
2015-10-10 12:09:09 +00:00
//node belongs to this scene and must be created
2017-03-05 15:44:50 +00:00
Object * obj = ClassDB : : instance ( snames [ n . type ] ) ;
2017-08-24 20:58:51 +00:00
if ( ! Object : : cast_to < Node > ( obj ) ) {
2014-10-07 04:31:49 +00:00
if ( obj ) {
memdelete ( obj ) ;
2017-03-05 15:44:50 +00:00
obj = NULL ;
2014-10-07 04:31:49 +00:00
}
2017-03-05 15:44:50 +00:00
WARN_PRINT ( String ( " Warning node of type " + snames [ n . type ] . operator String ( ) + " does not exist. " ) . ascii ( ) . get_data ( ) ) ;
if ( n . parent > = 0 & & n . parent < nc & & ret_nodes [ n . parent ] ) {
2017-08-24 20:58:51 +00:00
if ( Object : : cast_to < Spatial > ( ret_nodes [ n . parent ] ) ) {
2017-03-05 15:44:50 +00:00
obj = memnew ( Spatial ) ;
2017-08-24 20:58:51 +00:00
} else if ( Object : : cast_to < Control > ( ret_nodes [ n . parent ] ) ) {
2017-03-05 15:44:50 +00:00
obj = memnew ( Control ) ;
2017-08-24 20:58:51 +00:00
} else if ( Object : : cast_to < Node2D > ( ret_nodes [ n . parent ] ) ) {
2017-03-05 15:44:50 +00:00
obj = memnew ( Node2D ) ;
2014-10-07 04:31:49 +00:00
}
}
2017-01-10 04:04:31 +00:00
2014-10-07 04:31:49 +00:00
if ( ! obj ) {
2017-03-05 15:44:50 +00:00
obj = memnew ( Node ) ;
2014-10-07 04:31:49 +00:00
}
}
2014-02-23 13:35:05 +00:00
2017-08-24 20:58:51 +00:00
node = Object : : cast_to < Node > ( obj ) ;
2014-10-07 13:25:30 +00:00
2017-02-15 11:29:46 +00:00
} else {
2017-12-05 14:41:38 +00:00
print_line ( " Class is disabled for: " + itos ( n . type ) ) ;
2017-03-05 15:44:50 +00:00
print_line ( " name: " + String ( snames [ n . type ] ) ) ;
2014-02-23 13:35:05 +00:00
}
2015-10-10 12:09:09 +00:00
if ( node ) {
// may not have found the node (part of instanced scene and removed)
// if found all is good, otherwise ignore
//properties
2017-03-05 15:44:50 +00:00
int nprop_count = n . properties . size ( ) ;
2015-10-10 12:09:09 +00:00
if ( nprop_count ) {
2014-02-23 13:35:05 +00:00
2017-03-05 15:44:50 +00:00
const NodeData : : Property * nprops = & n . properties [ 0 ] ;
2014-02-23 13:35:05 +00:00
2017-03-05 15:44:50 +00:00
for ( int j = 0 ; j < nprop_count ; j + + ) {
2014-02-23 13:35:05 +00:00
2015-10-10 12:09:09 +00:00
bool valid ;
2017-03-05 15:44:50 +00:00
ERR_FAIL_INDEX_V ( nprops [ j ] . name , sname_count , NULL ) ;
ERR_FAIL_INDEX_V ( nprops [ j ] . value , prop_count , NULL ) ;
2017-02-15 11:29:46 +00:00
2017-03-05 15:44:50 +00:00
if ( snames [ nprops [ j ] . name ] = = CoreStringNames : : get_singleton ( ) - > _script ) {
2016-01-24 00:42:15 +00:00
//work around to avoid old script variables from disappearing, should be the proper fix to:
//https://github.com/godotengine/godot/issues/2958
//store old state
2017-03-05 15:44:50 +00:00
List < Pair < StringName , Variant > > old_state ;
2016-01-24 00:42:15 +00:00
if ( node - > get_script_instance ( ) ) {
node - > get_script_instance ( ) - > get_property_state ( old_state ) ;
}
2017-03-05 15:44:50 +00:00
node - > set ( snames [ nprops [ j ] . name ] , props [ nprops [ j ] . value ] , & valid ) ;
2016-01-24 00:42:15 +00:00
//restore old state for new script, if exists
2017-03-05 15:44:50 +00:00
for ( List < Pair < StringName , Variant > > : : Element * E = old_state . front ( ) ; E ; E = E - > next ( ) ) {
node - > set ( E - > get ( ) . first , E - > get ( ) . second ) ;
2016-01-24 00:42:15 +00:00
}
} else {
2017-03-05 15:44:50 +00:00
Variant value = props [ nprops [ j ] . value ] ;
2017-01-10 04:04:31 +00:00
2017-03-05 15:44:50 +00:00
if ( value . get_type ( ) = = Variant : : OBJECT ) {
2017-01-10 04:04:31 +00:00
//handle resources that are local to scene by duplicating them if needed
Ref < Resource > res = value ;
if ( res . is_valid ( ) ) {
if ( res - > is_local_to_scene ( ) ) {
2017-03-05 15:44:50 +00:00
Map < Ref < Resource > , Ref < Resource > > : : Element * E = resources_local_to_scene . find ( res ) ;
2017-01-10 04:04:31 +00:00
if ( E ) {
2017-03-05 15:44:50 +00:00
value = E - > get ( ) ;
2017-01-10 04:04:31 +00:00
} else {
2017-03-05 15:44:50 +00:00
Node * base = i = = 0 ? node : ret_nodes [ 0 ] ;
2017-01-10 04:04:31 +00:00
2017-03-05 15:44:50 +00:00
if ( p_edit_state = = GEN_EDIT_STATE_MAIN ) {
2017-12-04 18:55:20 +00:00
//for the main scene, use the resource as is
res - > configure_for_local_scene ( base , resources_local_to_scene ) ;
2018-01-11 18:26:28 +00:00
resources_local_to_scene [ res ] = res ;
2017-01-10 04:04:31 +00:00
} else {
2017-12-04 18:55:20 +00:00
//for instances, a copy must be made
2017-03-05 15:44:50 +00:00
Node * base = i = = 0 ? node : ret_nodes [ 0 ] ;
Ref < Resource > local_dupe = res - > duplicate_for_local_scene ( base , resources_local_to_scene ) ;
resources_local_to_scene [ res ] = local_dupe ;
res = local_dupe ;
value = local_dupe ;
2017-01-10 04:04:31 +00:00
}
}
//must make a copy, because this res is local to scene
}
}
2018-03-09 19:16:08 +00:00
} else if ( p_edit_state = = GEN_EDIT_STATE_INSTANCE ) {
value = value . duplicate ( true ) ; // Duplicate arrays and dictionaries for the editor
2017-01-10 04:04:31 +00:00
}
2017-03-05 15:44:50 +00:00
node - > set ( snames [ nprops [ j ] . name ] , value , & valid ) ;
2016-01-24 00:42:15 +00:00
}
2015-10-10 12:09:09 +00:00
}
2014-02-23 13:35:05 +00:00
}
2015-10-10 12:09:09 +00:00
//name
2014-02-23 13:35:05 +00:00
2015-10-10 12:09:09 +00:00
//groups
2017-03-05 15:44:50 +00:00
for ( int j = 0 ; j < n . groups . size ( ) ; j + + ) {
2014-02-23 13:35:05 +00:00
2017-03-05 15:44:50 +00:00
ERR_FAIL_INDEX_V ( n . groups [ j ] , sname_count , NULL ) ;
node - > add_to_group ( snames [ n . groups [ j ] ] , true ) ;
2015-10-10 12:09:09 +00:00
}
2014-02-23 13:35:05 +00:00
2017-03-05 15:44:50 +00:00
if ( n . instance > = 0 | | n . type ! = TYPE_INSTANCED | | i = = 0 ) {
2018-10-25 00:19:21 +00:00
//if node was not part of instance, must set its name, parenthood and ownership
2017-03-05 15:44:50 +00:00
if ( i > 0 ) {
2015-10-10 12:09:09 +00:00
if ( parent ) {
2017-03-05 15:44:50 +00:00
parent - > _add_child_nocheck ( node , snames [ n . name ] ) ;
2017-12-08 14:05:15 +00:00
if ( n . index > = 0 & & n . index < parent - > get_child_count ( ) - 1 )
parent - > move_child ( node , n . index ) ;
2015-10-10 12:09:09 +00:00
} else {
//it may be possible that an instanced scene has changed
//and the node has nowhere to go anymore
stray_instances . push_back ( node ) ; //can't be added, go to stray list
}
} else {
2018-07-29 20:39:06 +00:00
if ( Engine : : get_singleton ( ) - > is_editor_hint ( ) ) {
//validate name if using editor, to avoid broken
node - > set_name ( snames [ n . name ] ) ;
} else {
node - > _set_name_nocheck ( snames [ n . name ] ) ;
}
2015-10-10 12:09:09 +00:00
}
}
2014-02-23 13:35:05 +00:00
2017-03-05 15:44:50 +00:00
if ( n . owner > = 0 ) {
2014-02-23 13:35:05 +00:00
2017-03-05 15:44:50 +00:00
NODE_FROM_ID ( owner , n . owner ) ;
2015-10-10 12:09:09 +00:00
if ( owner )
node - > _set_owner_nocheck ( owner ) ;
}
2014-02-23 13:35:05 +00:00
}
2017-03-05 15:44:50 +00:00
ret_nodes [ i ] = node ;
2015-10-10 12:09:09 +00:00
if ( node & & gen_node_path_cache & & ret_nodes [ 0 ] ) {
NodePath n = ret_nodes [ 0 ] - > get_path_to ( node ) ;
2017-03-05 15:44:50 +00:00
node_path_cache [ n ] = i ;
2015-10-10 12:09:09 +00:00
}
2014-02-23 13:35:05 +00:00
}
2017-08-18 11:25:04 +00:00
for ( Map < Ref < Resource > , Ref < Resource > > : : Element * E = resources_local_to_scene . front ( ) ; E ; E = E - > next ( ) ) {
E - > get ( ) - > setup_local_to_scene ( ) ;
}
2014-02-23 13:35:05 +00:00
//do connections
int cc = connections . size ( ) ;
const ConnectionData * cdata = connections . ptr ( ) ;
2017-03-05 15:44:50 +00:00
for ( int i = 0 ; i < cc ; i + + ) {
2014-02-23 13:35:05 +00:00
2017-03-05 15:44:50 +00:00
const ConnectionData & c = cdata [ i ] ;
2015-10-10 12:09:09 +00:00
//ERR_FAIL_INDEX_V( c.from, nc, NULL );
//ERR_FAIL_INDEX_V( c.to, nc, NULL );
2017-03-05 15:44:50 +00:00
NODE_FROM_ID ( cfrom , c . from ) ;
NODE_FROM_ID ( cto , c . to ) ;
2015-10-10 12:09:09 +00:00
if ( ! cfrom | | ! cto )
continue ;
2014-02-23 13:35:05 +00:00
Vector < Variant > binds ;
if ( c . binds . size ( ) ) {
binds . resize ( c . binds . size ( ) ) ;
2017-03-05 15:44:50 +00:00
for ( int j = 0 ; j < c . binds . size ( ) ; j + + )
2018-07-25 01:11:03 +00:00
binds . write [ j ] = props [ c . binds [ j ] ] ;
2014-02-23 13:35:05 +00:00
}
2017-03-05 15:44:50 +00:00
cfrom - > connect ( snames [ c . signal ] , cto , snames [ c . method ] , binds , CONNECT_PERSIST | c . flags ) ;
2014-02-23 13:35:05 +00:00
}
2015-10-10 12:09:09 +00:00
//Node *s = ret_nodes[0];
2014-02-23 13:35:05 +00:00
2015-10-10 12:09:09 +00:00
//remove nodes that could not be added, likely as a result that
2017-03-05 15:44:50 +00:00
while ( stray_instances . size ( ) ) {
2015-10-10 12:09:09 +00:00
memdelete ( stray_instances . front ( ) - > get ( ) ) ;
2017-01-14 17:03:38 +00:00
stray_instances . pop_front ( ) ;
2015-10-10 12:09:09 +00:00
}
2017-03-05 15:44:50 +00:00
for ( int i = 0 ; i < editable_instances . size ( ) ; i + + ) {
2015-10-10 12:09:09 +00:00
Node * ei = ret_nodes [ 0 ] - > _get_node ( editable_instances [ i ] ) ;
if ( ei ) {
2017-03-05 15:44:50 +00:00
ret_nodes [ 0 ] - > set_editable_instance ( ei , true ) ;
2015-10-10 12:09:09 +00:00
}
}
2015-05-04 21:30:57 +00:00
2014-02-23 13:35:05 +00:00
return ret_nodes [ 0 ] ;
}
2017-03-05 15:44:50 +00:00
static int _nm_get_string ( const String & p_string , Map < StringName , int > & name_map ) {
2014-02-23 13:35:05 +00:00
if ( name_map . has ( p_string ) )
return name_map [ p_string ] ;
int idx = name_map . size ( ) ;
2017-03-05 15:44:50 +00:00
name_map [ p_string ] = idx ;
2014-02-23 13:35:05 +00:00
return idx ;
}
2017-03-05 15:44:50 +00:00
static int _vm_get_variant ( const Variant & p_variant , HashMap < Variant , int , VariantHasher , VariantComparator > & variant_map ) {
2014-02-23 13:35:05 +00:00
if ( variant_map . has ( p_variant ) )
return variant_map [ p_variant ] ;
int idx = variant_map . size ( ) ;
2017-03-05 15:44:50 +00:00
variant_map [ p_variant ] = idx ;
2014-02-23 13:35:05 +00:00
return idx ;
}
2017-03-05 15:44:50 +00:00
Error SceneState : : _parse_node ( Node * p_owner , Node * p_node , int p_parent_idx , Map < StringName , int > & name_map , HashMap < Variant , int , VariantHasher , VariantComparator > & variant_map , Map < Node * , int > & node_map , Map < Node * , int > & nodepath_map ) {
2015-10-10 12:09:09 +00:00
// this function handles all the work related to properly packing scenes, be it
// instanced or inherited.
// given the complexity of this process, an attempt will be made to properly
// document it. if you fail to understand something, please ask!
2014-02-23 13:35:05 +00:00
2015-10-10 12:09:09 +00:00
//discard nodes that do not belong to be processed
2017-03-05 15:44:50 +00:00
if ( p_node ! = p_owner & & p_node - > get_owner ( ) ! = p_owner & & ! p_owner - > is_editable_instance ( p_node - > get_owner ( ) ) )
2015-10-10 12:09:09 +00:00
return OK ;
// save the child instanced scenes that are chosen as editable, so they can be restored
// upon load back
2017-03-05 15:44:50 +00:00
if ( p_node ! = p_owner & & p_node - > get_filename ( ) ! = String ( ) & & p_owner - > is_editable_instance ( p_node ) )
2015-10-10 12:09:09 +00:00
editable_instances . push_back ( p_owner - > get_path_to ( p_node ) ) ;
2014-02-23 13:35:05 +00:00
NodeData nd ;
2017-03-05 15:44:50 +00:00
nd . name = _nm_get_string ( p_node - > get_name ( ) , name_map ) ;
nd . instance = - 1 ; //not instanced by default
2018-08-05 14:42:47 +00:00
//really convoluted condition, but it basically checks that index is only saved when part of an inherited scene OR the node parent is from the edited scene
if ( p_owner - > get_scene_inherited_state ( ) . is_null ( ) & & ( p_node = = p_owner | | ( p_node - > get_owner ( ) = = p_owner & & ( p_node - > get_parent ( ) = = p_owner | | p_node - > get_parent ( ) - > get_owner ( ) = = p_owner ) ) ) ) {
//do not save index, because it belongs to saved scene and scene is not inherited
nd . index = - 1 ;
} else {
//part of an inherited scene, or parent is from an instanced scene
nd . index = p_node - > get_index ( ) ;
}
2015-10-10 12:09:09 +00:00
// if this node is part of an instanced scene or sub-instanced scene
// we need to get the corresponding instance states.
// with the instance states, we can query for identical properties/groups
// and only save what has changed
List < PackState > pack_state_stack ;
2017-03-05 15:44:50 +00:00
bool instanced_by_owner = true ;
2014-02-23 13:35:05 +00:00
2015-10-10 12:09:09 +00:00
{
2017-03-05 15:44:50 +00:00
Node * n = p_node ;
2014-02-23 13:35:05 +00:00
2017-03-05 15:44:50 +00:00
while ( n ) {
2014-02-23 13:35:05 +00:00
2017-03-05 15:44:50 +00:00
if ( n = = p_owner ) {
2015-10-10 12:09:09 +00:00
Ref < SceneState > state = n - > get_scene_inherited_state ( ) ;
if ( state . is_valid ( ) ) {
int node = state - > find_node_by_path ( n - > get_path_to ( p_node ) ) ;
2017-03-05 15:44:50 +00:00
if ( node > = 0 ) {
2015-10-10 12:09:09 +00:00
//this one has state for this node, save
PackState ps ;
2017-03-05 15:44:50 +00:00
ps . node = node ;
ps . state = state ;
2016-06-28 12:47:03 +00:00
pack_state_stack . push_back ( ps ) ;
2017-03-05 15:44:50 +00:00
instanced_by_owner = false ;
2015-10-10 12:09:09 +00:00
}
}
2014-02-23 13:35:05 +00:00
2017-03-05 15:44:50 +00:00
if ( p_node - > get_filename ( ) ! = String ( ) & & p_node - > get_owner ( ) = = p_owner & & instanced_by_owner ) {
2015-10-10 12:09:09 +00:00
2015-10-16 22:11:23 +00:00
if ( p_node - > get_scene_instance_load_placeholder ( ) ) {
//it's a placeholder, use the placeholder path
2017-03-05 15:44:50 +00:00
nd . instance = _vm_get_variant ( p_node - > get_filename ( ) , variant_map ) ;
nd . instance | = FLAG_INSTANCE_IS_PLACEHOLDER ;
2015-10-16 22:11:23 +00:00
} else {
//must instance ourselves
Ref < PackedScene > instance = ResourceLoader : : load ( p_node - > get_filename ( ) ) ;
if ( ! instance . is_valid ( ) ) {
return ERR_CANT_OPEN ;
}
2017-03-05 15:44:50 +00:00
nd . instance = _vm_get_variant ( instance , variant_map ) ;
2015-10-16 22:11:23 +00:00
}
2015-10-10 12:09:09 +00:00
}
2017-03-05 15:44:50 +00:00
n = NULL ;
2015-10-10 12:09:09 +00:00
} else {
2017-03-05 15:44:50 +00:00
if ( n - > get_filename ( ) ! = String ( ) ) {
2015-10-10 12:09:09 +00:00
//is an instance
Ref < SceneState > state = n - > get_scene_instance_state ( ) ;
if ( state . is_valid ( ) ) {
int node = state - > find_node_by_path ( n - > get_path_to ( p_node ) ) ;
2017-03-05 15:44:50 +00:00
if ( node > = 0 ) {
2015-10-10 12:09:09 +00:00
//this one has state for this node, save
PackState ps ;
2017-03-05 15:44:50 +00:00
ps . node = node ;
ps . state = state ;
2015-10-10 12:09:09 +00:00
pack_state_stack . push_back ( ps ) ;
}
}
}
2017-03-05 15:44:50 +00:00
n = n - > get_owner ( ) ;
2015-10-10 12:09:09 +00:00
}
}
}
// all setup, we then proceed to check all properties for the node
// and save the ones that are worth saving
2014-02-23 13:35:05 +00:00
List < PropertyInfo > plist ;
p_node - > get_property_list ( & plist ) ;
2018-11-08 14:30:02 +00:00
StringName type = p_node - > get_class ( ) ;
2015-10-10 12:09:09 +00:00
2017-03-05 15:44:50 +00:00
for ( List < PropertyInfo > : : Element * E = plist . front ( ) ; E ; E = E - > next ( ) ) {
2014-10-03 03:10:51 +00:00
if ( ! ( E - > get ( ) . usage & PROPERTY_USAGE_STORAGE ) ) {
2014-02-23 13:35:05 +00:00
continue ;
2014-10-03 03:10:51 +00:00
}
2014-02-23 13:35:05 +00:00
String name = E - > get ( ) . name ;
2017-03-05 15:44:50 +00:00
Variant value = p_node - > get ( E - > get ( ) . name ) ;
2014-02-23 13:35:05 +00:00
2018-11-08 14:30:02 +00:00
bool isdefault = false ;
Variant default_value = ClassDB : : class_get_default_property_value ( type , name ) ;
if ( default_value . get_type ( ) ! = Variant : : NIL ) {
isdefault = bool ( Variant : : evaluate ( Variant : : OP_EQUAL , value , default_value ) ) ;
}
2015-10-10 12:09:09 +00:00
2018-11-09 11:16:01 +00:00
Ref < Script > script = p_node - > get_script ( ) ;
if ( ! isdefault & & script . is_valid ( ) & & script - > get_property_default_value ( name , default_value ) ) {
isdefault = bool ( Variant : : evaluate ( Variant : : OP_EQUAL , value , default_value ) ) ;
2017-08-06 12:32:52 +00:00
}
2018-11-09 11:16:01 +00:00
// the version above makes more sense, because it does not rely on placeholder or usage flag
// in the script, just the default value function.
// if (E->get().usage & PROPERTY_USAGE_SCRIPT_DEFAULT_VALUE) {
// isdefault = true; //is script default value
// }
2015-10-10 12:09:09 +00:00
if ( pack_state_stack . size ( ) ) {
// we are on part of an instanced subscene
// or part of instanced scene.
// only save what has been changed
// only save changed properties in instance
2017-09-07 19:48:50 +00:00
if ( ( E - > get ( ) . usage & PROPERTY_USAGE_NO_INSTANCE_STATE ) | | E - > get ( ) . name = = " __meta__ " ) {
2015-10-10 12:09:09 +00:00
//property has requested that no instance state is saved, sorry
2017-03-24 20:45:31 +00:00
//also, meta won't be overridden or saved
2014-02-23 13:35:05 +00:00
continue ;
2015-10-10 12:09:09 +00:00
}
2017-03-05 15:44:50 +00:00
bool exists = false ;
2015-10-10 12:09:09 +00:00
Variant original ;
2017-03-05 15:44:50 +00:00
for ( List < PackState > : : Element * F = pack_state_stack . back ( ) ; F ; F = F - > prev ( ) ) {
2015-10-10 12:09:09 +00:00
//check all levels of pack to see if the property exists somewhere
2017-03-05 15:44:50 +00:00
const PackState & ps = F - > get ( ) ;
2015-10-10 12:09:09 +00:00
2017-03-05 15:44:50 +00:00
original = ps . state - > get_property_value ( ps . node , E - > get ( ) . name , exists ) ;
2015-10-10 12:09:09 +00:00
if ( exists ) {
break ;
}
}
2015-12-12 19:46:25 +00:00
2016-06-12 22:33:07 +00:00
if ( exists ) {
//check if already exists and did not change
2017-03-05 15:44:50 +00:00
if ( value . get_type ( ) = = Variant : : REAL & & original . get_type ( ) = = Variant : : REAL ) {
2016-06-12 22:33:07 +00:00
//this must be done because, as some scenes save as text, there might be a tiny difference in floats due to numerical error
float a = value ;
float b = original ;
2017-03-05 15:44:50 +00:00
if ( Math : : abs ( a - b ) < CMP_EPSILON )
2016-06-12 22:33:07 +00:00
continue ;
2017-03-05 15:44:50 +00:00
} else if ( bool ( Variant : : evaluate ( Variant : : OP_EQUAL , value , original ) ) ) {
2016-06-28 12:47:03 +00:00
2016-06-12 22:33:07 +00:00
continue ;
}
2014-11-02 14:31:01 +00:00
}
2015-10-10 12:09:09 +00:00
if ( ! exists & & isdefault ) {
//does not exist in original node, but it's the default value
//so safe to skip too.
2014-02-23 13:35:05 +00:00
continue ;
2014-10-03 03:10:51 +00:00
}
2014-02-23 13:35:05 +00:00
2017-03-05 15:44:50 +00:00
} else {
2015-10-10 12:09:09 +00:00
if ( isdefault ) {
//it's the default value, no point in saving it
continue ;
}
2014-02-23 13:35:05 +00:00
}
NodeData : : Property prop ;
2017-03-05 15:44:50 +00:00
prop . name = _nm_get_string ( name , name_map ) ;
prop . value = _vm_get_variant ( value , variant_map ) ;
2014-02-23 13:35:05 +00:00
nd . properties . push_back ( prop ) ;
}
2015-10-10 12:09:09 +00:00
// save the groups this node is into
// discard groups that come from the original scene
2014-02-23 13:35:05 +00:00
List < Node : : GroupInfo > groups ;
p_node - > get_groups ( & groups ) ;
2017-03-05 15:44:50 +00:00
for ( List < Node : : GroupInfo > : : Element * E = groups . front ( ) ; E ; E = E - > next ( ) ) {
Node : : GroupInfo & gi = E - > get ( ) ;
2014-02-23 13:35:05 +00:00
if ( ! gi . persistent )
continue ;
2017-01-14 11:26:56 +00:00
/*
if ( instance_state_node > = 0 & & instance_state - > is_node_in_group ( instance_state_node , gi . name ) )
continue ; //group was instanced, don't add here
*/
2015-10-10 12:09:09 +00:00
2017-03-05 15:44:50 +00:00
bool skip = false ;
for ( List < PackState > : : Element * F = pack_state_stack . front ( ) ; F ; F = F - > next ( ) ) {
2015-10-10 12:09:09 +00:00
//check all levels of pack to see if the group was added somewhere
2017-03-05 15:44:50 +00:00
const PackState & ps = F - > get ( ) ;
if ( ps . state - > is_node_in_group ( ps . node , gi . name ) ) {
skip = true ;
2015-10-10 12:09:09 +00:00
break ;
}
}
if ( skip )
continue ;
2014-02-23 13:35:05 +00:00
2017-03-05 15:44:50 +00:00
nd . groups . push_back ( _nm_get_string ( gi . name , name_map ) ) ;
2014-02-23 13:35:05 +00:00
}
2015-10-10 12:09:09 +00:00
// save the right owner
// for the saved scene root this is -1
// for nodes of the saved scene this is 0
// for nodes of instanced scenes this is >0
2017-03-05 15:44:50 +00:00
if ( p_node = = p_owner ) {
2015-10-10 12:09:09 +00:00
//saved scene root
2017-03-05 15:44:50 +00:00
nd . owner = - 1 ;
} else if ( p_node - > get_owner ( ) = = p_owner ) {
2015-10-10 12:09:09 +00:00
//part of saved scene
2017-03-05 15:44:50 +00:00
nd . owner = 0 ;
2015-10-10 12:09:09 +00:00
} else {
2017-03-05 15:44:50 +00:00
nd . owner = - 1 ;
2015-10-10 12:09:09 +00:00
}
// Save the right type. If this node was created by an instance
2016-03-08 23:00:52 +00:00
// then flag that the node should not be created but reused
2015-10-10 12:09:09 +00:00
if ( pack_state_stack . empty ( ) ) {
//this node is not part of an instancing process, so save the type
2017-03-05 15:44:50 +00:00
nd . type = _nm_get_string ( p_node - > get_class ( ) , name_map ) ;
2015-10-10 12:09:09 +00:00
} else {
// this node is part of an instanced process, so do not save the type.
// instead, save that it was instanced
2017-03-05 15:44:50 +00:00
nd . type = TYPE_INSTANCED ;
2015-10-10 12:09:09 +00:00
}
// determine whether to save this node or not
// if this node is part of an instanced sub-scene, we can skip storing it if basically
// no properties changed and no groups were added to it.
// below condition is true for all nodes of the scene being saved, and ones in subscenes
// that hold changes
bool save_node = nd . properties . size ( ) | | nd . groups . size ( ) ; // some local properties or groups exist
2017-03-05 15:44:50 +00:00
save_node = save_node | | p_node = = p_owner ; // owner is always saved
save_node = save_node | | ( p_node - > get_owner ( ) = = p_owner & & instanced_by_owner ) ; //part of scene and not instanced
2014-02-23 13:35:05 +00:00
int idx = nodes . size ( ) ;
2017-03-05 15:44:50 +00:00
int parent_node = NO_PARENT_SAVED ;
2015-10-10 12:09:09 +00:00
if ( save_node ) {
//don't save the node if nothing and subscene
2017-03-05 15:44:50 +00:00
node_map [ p_node ] = idx ;
2015-10-10 12:09:09 +00:00
//ok validate parent node
2017-03-05 15:44:50 +00:00
if ( p_parent_idx = = NO_PARENT_SAVED ) {
2015-10-10 12:09:09 +00:00
int sidx ;
if ( nodepath_map . has ( p_node - > get_parent ( ) ) ) {
2017-03-05 15:44:50 +00:00
sidx = nodepath_map [ p_node - > get_parent ( ) ] ;
2015-10-10 12:09:09 +00:00
} else {
2017-03-05 15:44:50 +00:00
sidx = nodepath_map . size ( ) ;
nodepath_map [ p_node - > get_parent ( ) ] = sidx ;
2015-10-10 12:09:09 +00:00
}
2017-03-05 15:44:50 +00:00
nd . parent = FLAG_ID_IS_PATH | sidx ;
2015-10-10 12:09:09 +00:00
} else {
2017-03-05 15:44:50 +00:00
nd . parent = p_parent_idx ;
2015-10-10 12:09:09 +00:00
}
2017-03-05 15:44:50 +00:00
parent_node = idx ;
2015-10-10 12:09:09 +00:00
nodes . push_back ( nd ) ;
}
2014-02-23 13:35:05 +00:00
2017-03-05 15:44:50 +00:00
for ( int i = 0 ; i < p_node - > get_child_count ( ) ; i + + ) {
2014-02-23 13:35:05 +00:00
2017-03-05 15:44:50 +00:00
Node * c = p_node - > get_child ( i ) ;
Error err = _parse_node ( p_owner , c , parent_node , name_map , variant_map , node_map , nodepath_map ) ;
2014-02-23 13:35:05 +00:00
if ( err )
return err ;
}
return OK ;
}
2017-03-05 15:44:50 +00:00
Error SceneState : : _parse_connections ( Node * p_owner , Node * p_node , Map < StringName , int > & name_map , HashMap < Variant , int , VariantHasher , VariantComparator > & variant_map , Map < Node * , int > & node_map , Map < Node * , int > & nodepath_map ) {
2014-02-23 13:35:05 +00:00
2017-03-05 15:44:50 +00:00
if ( p_node ! = p_owner & & p_node - > get_owner ( ) & & p_node - > get_owner ( ) ! = p_owner & & ! p_owner - > is_editable_instance ( p_node - > get_owner ( ) ) )
2015-10-10 12:09:09 +00:00
return OK ;
2014-02-23 13:35:05 +00:00
2015-10-10 12:09:09 +00:00
List < MethodInfo > _signals ;
p_node - > get_signal_list ( & _signals ) ;
2016-06-30 21:43:47 +00:00
_signals . sort ( ) ;
2014-02-23 13:35:05 +00:00
2015-10-10 12:09:09 +00:00
//ERR_FAIL_COND_V( !node_map.has(p_node), ERR_BUG);
//NodeData &nd = nodes[node_map[p_node]];
2014-02-23 13:35:05 +00:00
2017-03-05 15:44:50 +00:00
for ( List < MethodInfo > : : Element * E = _signals . front ( ) ; E ; E = E - > next ( ) ) {
2014-02-23 13:35:05 +00:00
List < Node : : Connection > conns ;
2017-03-05 15:44:50 +00:00
p_node - > get_signal_connection_list ( E - > get ( ) . name , & conns ) ;
2016-06-30 21:43:47 +00:00
conns . sort ( ) ;
2017-03-05 15:44:50 +00:00
for ( List < Node : : Connection > : : Element * F = conns . front ( ) ; F ; F = F - > next ( ) ) {
2014-02-23 13:35:05 +00:00
const Node : : Connection & c = F - > get ( ) ;
2015-10-10 12:09:09 +00:00
2017-03-05 15:44:50 +00:00
if ( ! ( c . flags & CONNECT_PERSIST ) ) //only persistent connections get saved
2014-02-23 13:35:05 +00:00
continue ;
2015-10-10 12:09:09 +00:00
// only connections that originate or end into main saved scene are saved
// everything else is discarded
2014-02-23 13:35:05 +00:00
2017-08-24 20:58:51 +00:00
Node * target = Object : : cast_to < Node > ( c . target ) ;
2016-07-19 23:04:06 +00:00
if ( ! target ) {
2014-02-23 13:35:05 +00:00
continue ;
2015-10-10 12:09:09 +00:00
}
2016-07-19 23:04:06 +00:00
//find if this connection already exists
Node * common_parent = target - > find_common_parent_with ( p_node ) ;
ERR_CONTINUE ( ! common_parent ) ;
2017-03-05 15:44:50 +00:00
if ( common_parent ! = p_owner & & common_parent - > get_filename ( ) = = String ( ) ) {
common_parent = common_parent - > get_owner ( ) ;
2016-07-19 23:04:06 +00:00
}
2017-03-05 15:44:50 +00:00
bool exists = false ;
2016-07-19 23:04:06 +00:00
//go through ownership chain to see if this exists
2017-03-05 15:44:50 +00:00
while ( common_parent ) {
2016-07-19 23:04:06 +00:00
Ref < SceneState > ps ;
2014-02-23 13:35:05 +00:00
2017-03-05 15:44:50 +00:00
if ( common_parent = = p_owner )
ps = common_parent - > get_scene_inherited_state ( ) ;
2016-07-19 23:04:06 +00:00
else
2017-03-05 15:44:50 +00:00
ps = common_parent - > get_scene_instance_state ( ) ;
2016-07-19 23:04:06 +00:00
if ( ps . is_valid ( ) ) {
NodePath signal_from = common_parent - > get_path_to ( p_node ) ;
NodePath signal_to = common_parent - > get_path_to ( target ) ;
2017-03-05 15:44:50 +00:00
if ( ps - > has_connection ( signal_from , c . signal , signal_to , c . method ) ) {
exists = true ;
2016-07-20 00:26:12 +00:00
break ;
2016-07-19 23:04:06 +00:00
}
}
2017-03-05 15:44:50 +00:00
if ( common_parent = = p_owner )
2016-07-19 23:04:06 +00:00
break ;
else
2017-03-05 15:44:50 +00:00
common_parent = common_parent - > get_owner ( ) ;
2016-07-19 23:04:06 +00:00
}
if ( exists ) { //already exists (comes from instance or inheritance), so don't save
2014-02-23 13:35:05 +00:00
continue ;
}
2015-10-10 12:09:09 +00:00
{
2017-03-05 15:44:50 +00:00
Node * nl = p_node ;
2015-10-10 12:09:09 +00:00
2017-03-05 15:44:50 +00:00
bool exists = false ;
2015-10-10 12:09:09 +00:00
2017-03-05 15:44:50 +00:00
while ( nl ) {
2015-10-10 12:09:09 +00:00
2017-03-05 15:44:50 +00:00
if ( nl = = p_owner ) {
2015-10-10 12:09:09 +00:00
Ref < SceneState > state = nl - > get_scene_inherited_state ( ) ;
if ( state . is_valid ( ) ) {
int from_node = state - > find_node_by_path ( nl - > get_path_to ( p_node ) ) ;
2016-07-19 23:04:06 +00:00
int to_node = state - > find_node_by_path ( nl - > get_path_to ( target ) ) ;
2015-10-10 12:09:09 +00:00
2017-03-05 15:44:50 +00:00
if ( from_node > = 0 & & to_node > = 0 ) {
2015-10-10 12:09:09 +00:00
//this one has state for this node, save
2017-03-05 15:44:50 +00:00
if ( state - > is_connection ( from_node , c . signal , to_node , c . method ) ) {
exists = true ;
2015-10-10 12:09:09 +00:00
break ;
}
}
}
2017-03-05 15:44:50 +00:00
nl = NULL ;
2015-10-10 12:09:09 +00:00
} else {
2017-03-05 15:44:50 +00:00
if ( nl - > get_filename ( ) ! = String ( ) ) {
2015-10-10 12:09:09 +00:00
//is an instance
Ref < SceneState > state = nl - > get_scene_instance_state ( ) ;
if ( state . is_valid ( ) ) {
int from_node = state - > find_node_by_path ( nl - > get_path_to ( p_node ) ) ;
2016-07-19 23:04:06 +00:00
int to_node = state - > find_node_by_path ( nl - > get_path_to ( target ) ) ;
2015-10-10 12:09:09 +00:00
2017-03-05 15:44:50 +00:00
if ( from_node > = 0 & & to_node > = 0 ) {
2015-10-10 12:09:09 +00:00
//this one has state for this node, save
2017-03-05 15:44:50 +00:00
if ( state - > is_connection ( from_node , c . signal , to_node , c . method ) ) {
exists = true ;
2015-10-10 12:09:09 +00:00
break ;
}
}
}
}
2017-03-05 15:44:50 +00:00
nl = nl - > get_owner ( ) ;
2015-10-10 12:09:09 +00:00
}
}
if ( exists ) {
continue ;
}
}
int src_id ;
if ( node_map . has ( p_node ) ) {
2017-03-05 15:44:50 +00:00
src_id = node_map [ p_node ] ;
2015-10-10 12:09:09 +00:00
} else {
if ( nodepath_map . has ( p_node ) ) {
2017-03-05 15:44:50 +00:00
src_id = FLAG_ID_IS_PATH | nodepath_map [ p_node ] ;
2015-10-10 12:09:09 +00:00
} else {
2017-03-05 15:44:50 +00:00
int sidx = nodepath_map . size ( ) ;
nodepath_map [ p_node ] = sidx ;
src_id = FLAG_ID_IS_PATH | sidx ;
2015-10-10 12:09:09 +00:00
}
}
int target_id ;
2016-07-19 23:04:06 +00:00
if ( node_map . has ( target ) ) {
2017-03-05 15:44:50 +00:00
target_id = node_map [ target ] ;
2015-10-10 12:09:09 +00:00
} else {
2016-07-19 23:04:06 +00:00
if ( nodepath_map . has ( target ) ) {
2017-03-05 15:44:50 +00:00
target_id = FLAG_ID_IS_PATH | nodepath_map [ target ] ;
2015-10-10 12:09:09 +00:00
} else {
2017-03-05 15:44:50 +00:00
int sidx = nodepath_map . size ( ) ;
nodepath_map [ target ] = sidx ;
target_id = FLAG_ID_IS_PATH | sidx ;
2015-10-10 12:09:09 +00:00
}
}
2014-02-23 13:35:05 +00:00
ConnectionData cd ;
2017-03-05 15:44:50 +00:00
cd . from = src_id ;
cd . to = target_id ;
cd . method = _nm_get_string ( c . method , name_map ) ;
cd . signal = _nm_get_string ( c . signal , name_map ) ;
cd . flags = c . flags ;
for ( int i = 0 ; i < c . binds . size ( ) ; i + + ) {
cd . binds . push_back ( _vm_get_variant ( c . binds [ i ] , variant_map ) ) ;
2014-02-23 13:35:05 +00:00
}
connections . push_back ( cd ) ;
}
}
2017-03-05 15:44:50 +00:00
for ( int i = 0 ; i < p_node - > get_child_count ( ) ; i + + ) {
2014-02-23 13:35:05 +00:00
2017-03-05 15:44:50 +00:00
Node * c = p_node - > get_child ( i ) ;
Error err = _parse_connections ( p_owner , c , name_map , variant_map , node_map , nodepath_map ) ;
2014-02-23 13:35:05 +00:00
if ( err )
return err ;
}
return OK ;
}
2015-10-10 12:09:09 +00:00
Error SceneState : : pack ( Node * p_scene ) {
2017-03-05 15:44:50 +00:00
ERR_FAIL_NULL_V ( p_scene , ERR_INVALID_PARAMETER ) ;
2014-02-23 13:35:05 +00:00
clear ( ) ;
Node * scene = p_scene ;
2017-03-05 15:44:50 +00:00
Map < StringName , int > name_map ;
HashMap < Variant , int , VariantHasher , VariantComparator > variant_map ;
Map < Node * , int > node_map ;
Map < Node * , int > nodepath_map ;
2015-10-10 12:09:09 +00:00
//if using scene inheritance, pack the scene it inherits from
if ( scene - > get_scene_inherited_state ( ) . is_valid ( ) ) {
String path = scene - > get_scene_inherited_state ( ) - > get_path ( ) ;
Ref < PackedScene > instance = ResourceLoader : : load ( path ) ;
if ( instance . is_valid ( ) ) {
2017-03-05 15:44:50 +00:00
base_scene_idx = _vm_get_variant ( instance , variant_map ) ;
2015-10-10 12:09:09 +00:00
}
}
//instanced, only direct sub-scnes are supported of course
2017-03-05 15:44:50 +00:00
Error err = _parse_node ( scene , scene , - 1 , name_map , variant_map , node_map , nodepath_map ) ;
2014-02-23 13:35:05 +00:00
if ( err ) {
clear ( ) ;
ERR_FAIL_V ( err ) ;
}
2017-03-05 15:44:50 +00:00
err = _parse_connections ( scene , scene , name_map , variant_map , node_map , nodepath_map ) ;
2014-02-23 13:35:05 +00:00
if ( err ) {
clear ( ) ;
ERR_FAIL_V ( err ) ;
}
names . resize ( name_map . size ( ) ) ;
2017-03-05 15:44:50 +00:00
for ( Map < StringName , int > : : Element * E = name_map . front ( ) ; E ; E = E - > next ( ) ) {
2014-02-23 13:35:05 +00:00
2018-07-25 01:11:03 +00:00
names . write [ E - > get ( ) ] = E - > key ( ) ;
2014-02-23 13:35:05 +00:00
}
variants . resize ( variant_map . size ( ) ) ;
2017-03-05 15:44:50 +00:00
const Variant * K = NULL ;
while ( ( K = variant_map . next ( K ) ) ) {
2014-02-23 13:35:05 +00:00
int idx = variant_map [ * K ] ;
2018-07-25 01:11:03 +00:00
variants . write [ idx ] = * K ;
2014-02-23 13:35:05 +00:00
}
2015-10-10 12:09:09 +00:00
node_paths . resize ( nodepath_map . size ( ) ) ;
2017-03-05 15:44:50 +00:00
for ( Map < Node * , int > : : Element * E = nodepath_map . front ( ) ; E ; E = E - > next ( ) ) {
2015-10-10 12:09:09 +00:00
2018-07-25 01:11:03 +00:00
node_paths . write [ E - > get ( ) ] = scene - > get_path_to ( E - > key ( ) ) ;
2015-10-10 12:09:09 +00:00
}
2014-02-23 13:35:05 +00:00
return OK ;
}
2015-10-10 12:09:09 +00:00
void SceneState : : set_path ( const String & p_path ) {
2017-03-05 15:44:50 +00:00
path = p_path ;
2015-10-10 12:09:09 +00:00
}
2017-03-05 15:44:50 +00:00
String SceneState : : get_path ( ) const {
2015-10-10 12:09:09 +00:00
return path ;
}
void SceneState : : clear ( ) {
2014-02-23 13:35:05 +00:00
names . clear ( ) ;
variants . clear ( ) ;
nodes . clear ( ) ;
connections . clear ( ) ;
2015-10-10 12:09:09 +00:00
node_path_cache . clear ( ) ;
node_paths . clear ( ) ;
editable_instances . clear ( ) ;
2017-03-05 15:44:50 +00:00
base_scene_idx = - 1 ;
2014-02-23 13:35:05 +00:00
}
2015-10-10 12:09:09 +00:00
Ref < SceneState > SceneState : : _get_base_scene_state ( ) const {
2017-03-05 15:44:50 +00:00
if ( base_scene_idx > = 0 ) {
2015-10-10 12:09:09 +00:00
Ref < PackedScene > ps = variants [ base_scene_idx ] ;
if ( ps . is_valid ( ) ) {
return ps - > get_state ( ) ;
}
}
return Ref < SceneState > ( ) ;
}
2017-03-05 15:44:50 +00:00
int SceneState : : find_node_by_path ( const NodePath & p_node ) const {
2015-10-10 12:09:09 +00:00
2016-03-08 23:00:52 +00:00
if ( ! node_path_cache . has ( p_node ) ) {
2015-10-10 12:09:09 +00:00
if ( _get_base_scene_state ( ) . is_valid ( ) ) {
int idx = _get_base_scene_state ( ) - > find_node_by_path ( p_node ) ;
2017-03-05 15:44:50 +00:00
if ( idx > = 0 ) {
2017-03-08 19:08:24 +00:00
int rkey = _find_base_scene_node_remap_key ( idx ) ;
if ( rkey = = - 1 ) {
rkey = nodes . size ( ) + base_scene_node_remap . size ( ) ;
base_scene_node_remap [ rkey ] = idx ;
2015-10-10 12:09:09 +00:00
}
2017-03-08 19:08:24 +00:00
return rkey ;
2015-10-10 12:09:09 +00:00
}
}
return - 1 ;
}
int nid = node_path_cache [ p_node ] ;
if ( _get_base_scene_state ( ) . is_valid ( ) & & ! base_scene_node_remap . has ( nid ) ) {
//for nodes that _do_ exist in current scene, still try to look for
//the node in the instanced scene, as a property may be missing
//from the local one
int idx = _get_base_scene_state ( ) - > find_node_by_path ( p_node ) ;
2017-03-08 19:08:24 +00:00
if ( idx ! = - 1 ) {
base_scene_node_remap [ nid ] = idx ;
}
2015-10-10 12:09:09 +00:00
}
return nid ;
}
2017-03-08 19:08:24 +00:00
int SceneState : : _find_base_scene_node_remap_key ( int p_idx ) const {
for ( Map < int , int > : : Element * E = base_scene_node_remap . front ( ) ; E ; E = E - > next ( ) ) {
if ( E - > value ( ) = = p_idx ) {
return E - > key ( ) ;
}
}
return - 1 ;
}
2017-03-05 15:44:50 +00:00
Variant SceneState : : get_property_value ( int p_node , const StringName & p_property , bool & found ) const {
2015-10-10 12:09:09 +00:00
2017-03-05 15:44:50 +00:00
found = false ;
2015-10-10 12:09:09 +00:00
2017-03-05 15:44:50 +00:00
ERR_FAIL_COND_V ( p_node < 0 , Variant ( ) ) ;
2015-10-10 12:09:09 +00:00
2017-03-05 15:44:50 +00:00
if ( p_node < nodes . size ( ) ) {
2015-10-10 12:09:09 +00:00
//find in built-in nodes
int pc = nodes [ p_node ] . properties . size ( ) ;
2017-03-05 15:44:50 +00:00
const StringName * namep = names . ptr ( ) ;
2015-10-10 12:09:09 +00:00
2017-03-05 15:44:50 +00:00
const NodeData : : Property * p = nodes [ p_node ] . properties . ptr ( ) ;
for ( int i = 0 ; i < pc ; i + + ) {
if ( p_property = = namep [ p [ i ] . name ] ) {
found = true ;
2015-10-10 12:09:09 +00:00
return variants [ p [ i ] . value ] ;
}
}
}
//property not found, try on instance
if ( base_scene_node_remap . has ( p_node ) ) {
2017-03-05 15:44:50 +00:00
return _get_base_scene_state ( ) - > get_property_value ( base_scene_node_remap [ p_node ] , p_property , found ) ;
2015-10-10 12:09:09 +00:00
}
return Variant ( ) ;
}
2017-03-05 15:44:50 +00:00
bool SceneState : : is_node_in_group ( int p_node , const StringName & p_group ) const {
2015-10-10 12:09:09 +00:00
2017-03-05 15:44:50 +00:00
ERR_FAIL_COND_V ( p_node < 0 , false ) ;
2015-10-10 12:09:09 +00:00
2017-03-05 15:44:50 +00:00
if ( p_node < nodes . size ( ) ) {
const StringName * namep = names . ptr ( ) ;
for ( int i = 0 ; i < nodes [ p_node ] . groups . size ( ) ; i + + ) {
if ( namep [ nodes [ p_node ] . groups [ i ] ] = = p_group )
2015-10-10 12:09:09 +00:00
return true ;
}
}
if ( base_scene_node_remap . has ( p_node ) ) {
2017-03-05 15:44:50 +00:00
return _get_base_scene_state ( ) - > is_node_in_group ( base_scene_node_remap [ p_node ] , p_group ) ;
2015-10-10 12:09:09 +00:00
}
return false ;
}
2017-03-05 15:44:50 +00:00
bool SceneState : : disable_placeholders = false ;
2015-10-16 22:11:23 +00:00
void SceneState : : set_disable_placeholders ( bool p_disable ) {
2017-03-05 15:44:50 +00:00
disable_placeholders = p_disable ;
2015-10-16 22:11:23 +00:00
}
2017-03-05 15:44:50 +00:00
bool SceneState : : is_connection ( int p_node , const StringName & p_signal , int p_to_node , const StringName & p_to_method ) const {
2015-10-10 12:09:09 +00:00
2017-03-05 15:44:50 +00:00
ERR_FAIL_COND_V ( p_node < 0 , false ) ;
ERR_FAIL_COND_V ( p_to_node < 0 , false ) ;
2015-10-10 12:09:09 +00:00
2017-03-05 15:44:50 +00:00
if ( p_node < nodes . size ( ) & & p_to_node < nodes . size ( ) ) {
2015-10-10 12:09:09 +00:00
2017-03-05 15:44:50 +00:00
int signal_idx = - 1 ;
int method_idx = - 1 ;
for ( int i = 0 ; i < names . size ( ) ; i + + ) {
if ( names [ i ] = = p_signal ) {
signal_idx = i ;
} else if ( names [ i ] = = p_to_method ) {
method_idx = i ;
2015-10-10 12:09:09 +00:00
}
}
2017-03-05 15:44:50 +00:00
if ( signal_idx > = 0 & & method_idx > = 0 ) {
2015-10-10 12:09:09 +00:00
//signal and method strings are stored..
2017-03-05 15:44:50 +00:00
for ( int i = 0 ; i < connections . size ( ) ; i + + ) {
2015-10-10 12:09:09 +00:00
2017-03-05 15:44:50 +00:00
if ( connections [ i ] . from = = p_node & & connections [ i ] . to = = p_to_node & & connections [ i ] . signal = = signal_idx & & connections [ i ] . method = = method_idx ) {
2015-10-10 12:09:09 +00:00
return true ;
}
}
}
}
if ( base_scene_node_remap . has ( p_node ) & & base_scene_node_remap . has ( p_to_node ) ) {
2017-03-05 15:44:50 +00:00
return _get_base_scene_state ( ) - > is_connection ( base_scene_node_remap [ p_node ] , p_signal , base_scene_node_remap [ p_to_node ] , p_to_method ) ;
2015-10-10 12:09:09 +00:00
}
return false ;
}
2017-08-11 19:10:05 +00:00
void SceneState : : set_bundled_scene ( const Dictionary & p_dictionary ) {
2015-10-10 12:09:09 +00:00
2017-08-11 19:10:05 +00:00
ERR_FAIL_COND ( ! p_dictionary . has ( " names " ) ) ;
ERR_FAIL_COND ( ! p_dictionary . has ( " variants " ) ) ;
ERR_FAIL_COND ( ! p_dictionary . has ( " node_count " ) ) ;
ERR_FAIL_COND ( ! p_dictionary . has ( " nodes " ) ) ;
ERR_FAIL_COND ( ! p_dictionary . has ( " conn_count " ) ) ;
ERR_FAIL_COND ( ! p_dictionary . has ( " conns " ) ) ;
//ERR_FAIL_COND( !p_dictionary.has("path"));
2014-02-23 13:35:05 +00:00
2017-03-05 15:44:50 +00:00
int version = 1 ;
2017-08-11 19:10:05 +00:00
if ( p_dictionary . has ( " version " ) )
version = p_dictionary [ " version " ] ;
2015-10-10 12:09:09 +00:00
2017-03-05 15:44:50 +00:00
if ( version > PACK_VERSION ) {
2015-10-10 12:09:09 +00:00
ERR_EXPLAIN ( " Save format version too new! " ) ;
ERR_FAIL ( ) ;
}
2017-08-11 19:10:05 +00:00
PoolVector < String > snames = p_dictionary [ " names " ] ;
2014-02-23 13:35:05 +00:00
if ( snames . size ( ) ) {
int namecount = snames . size ( ) ;
names . resize ( namecount ) ;
2017-03-05 15:44:50 +00:00
PoolVector < String > : : Read r = snames . read ( ) ;
for ( int i = 0 ; i < names . size ( ) ; i + + )
2018-07-25 01:11:03 +00:00
names . write [ i ] = r [ i ] ;
2014-02-23 13:35:05 +00:00
}
2017-08-11 19:10:05 +00:00
Array svariants = p_dictionary [ " variants " ] ;
2014-02-23 13:35:05 +00:00
if ( svariants . size ( ) ) {
2017-03-05 15:44:50 +00:00
int varcount = svariants . size ( ) ;
2014-02-23 13:35:05 +00:00
variants . resize ( varcount ) ;
2017-03-05 15:44:50 +00:00
for ( int i = 0 ; i < varcount ; i + + ) {
2014-02-23 13:35:05 +00:00
2018-07-25 01:11:03 +00:00
variants . write [ i ] = svariants [ i ] ;
2014-02-23 13:35:05 +00:00
}
} else {
variants . clear ( ) ;
}
2017-08-11 19:10:05 +00:00
nodes . resize ( p_dictionary [ " node_count " ] ) ;
2017-03-05 15:44:50 +00:00
int nc = nodes . size ( ) ;
2014-02-23 13:35:05 +00:00
if ( nc ) {
2017-08-11 19:10:05 +00:00
PoolVector < int > snodes = p_dictionary [ " nodes " ] ;
2017-01-07 21:25:37 +00:00
PoolVector < int > : : Read r = snodes . read ( ) ;
2017-03-05 15:44:50 +00:00
int idx = 0 ;
for ( int i = 0 ; i < nc ; i + + ) {
2018-07-25 01:11:03 +00:00
NodeData & nd = nodes . write [ i ] ;
2017-03-05 15:44:50 +00:00
nd . parent = r [ idx + + ] ;
nd . owner = r [ idx + + ] ;
nd . type = r [ idx + + ] ;
2017-12-16 18:48:16 +00:00
uint32_t name_index = r [ idx + + ] ;
nd . name = name_index & ( ( 1 < < NAME_INDEX_BITS ) - 1 ) ;
nd . index = ( name_index > > NAME_INDEX_BITS ) ;
2018-01-18 20:37:17 +00:00
nd . index - - ; //0 is invalid, stored as 1
2017-03-05 15:44:50 +00:00
nd . instance = r [ idx + + ] ;
2014-02-23 13:35:05 +00:00
nd . properties . resize ( r [ idx + + ] ) ;
2017-03-05 15:44:50 +00:00
for ( int j = 0 ; j < nd . properties . size ( ) ; j + + ) {
2014-02-23 13:35:05 +00:00
2018-07-25 01:11:03 +00:00
nd . properties . write [ j ] . name = r [ idx + + ] ;
nd . properties . write [ j ] . value = r [ idx + + ] ;
2014-02-23 13:35:05 +00:00
}
nd . groups . resize ( r [ idx + + ] ) ;
2017-03-05 15:44:50 +00:00
for ( int j = 0 ; j < nd . groups . size ( ) ; j + + ) {
2014-02-23 13:35:05 +00:00
2018-07-25 01:11:03 +00:00
nd . groups . write [ j ] = r [ idx + + ] ;
2014-02-23 13:35:05 +00:00
}
}
}
2017-08-11 19:10:05 +00:00
connections . resize ( p_dictionary [ " conn_count " ] ) ;
2017-03-05 15:44:50 +00:00
int cc = connections . size ( ) ;
2014-02-23 13:35:05 +00:00
if ( cc ) {
2017-08-11 19:10:05 +00:00
PoolVector < int > sconns = p_dictionary [ " conns " ] ;
2017-01-07 21:25:37 +00:00
PoolVector < int > : : Read r = sconns . read ( ) ;
2017-03-05 15:44:50 +00:00
int idx = 0 ;
for ( int i = 0 ; i < cc ; i + + ) {
2018-07-25 01:11:03 +00:00
ConnectionData & cd = connections . write [ i ] ;
2017-03-05 15:44:50 +00:00
cd . from = r [ idx + + ] ;
cd . to = r [ idx + + ] ;
cd . signal = r [ idx + + ] ;
cd . method = r [ idx + + ] ;
cd . flags = r [ idx + + ] ;
2014-02-23 13:35:05 +00:00
cd . binds . resize ( r [ idx + + ] ) ;
2017-03-05 15:44:50 +00:00
for ( int j = 0 ; j < cd . binds . size ( ) ; j + + ) {
2014-02-23 13:35:05 +00:00
2018-07-25 01:11:03 +00:00
cd . binds . write [ j ] = r [ idx + + ] ;
2014-02-23 13:35:05 +00:00
}
}
}
2015-10-10 12:09:09 +00:00
Array np ;
2017-08-11 19:10:05 +00:00
if ( p_dictionary . has ( " node_paths " ) ) {
np = p_dictionary [ " node_paths " ] ;
2015-10-10 12:09:09 +00:00
}
node_paths . resize ( np . size ( ) ) ;
2017-03-05 15:44:50 +00:00
for ( int i = 0 ; i < np . size ( ) ; i + + ) {
2018-07-25 01:11:03 +00:00
node_paths . write [ i ] = np [ i ] ;
2015-10-10 12:09:09 +00:00
}
Array ei ;
2017-08-11 19:10:05 +00:00
if ( p_dictionary . has ( " editable_instances " ) ) {
ei = p_dictionary [ " editable_instances " ] ;
2015-10-10 12:09:09 +00:00
}
2017-08-11 19:10:05 +00:00
if ( p_dictionary . has ( " base_scene " ) ) {
base_scene_idx = p_dictionary [ " base_scene " ] ;
2015-10-10 12:09:09 +00:00
}
editable_instances . resize ( ei . size ( ) ) ;
2017-03-05 15:44:50 +00:00
for ( int i = 0 ; i < editable_instances . size ( ) ; i + + ) {
2018-07-25 01:11:03 +00:00
editable_instances . write [ i ] = ei [ i ] ;
2015-10-10 12:09:09 +00:00
}
2017-08-11 19:10:05 +00:00
//path=p_dictionary["path"];
2014-02-23 13:35:05 +00:00
}
2015-10-10 12:09:09 +00:00
Dictionary SceneState : : get_bundled_scene ( ) const {
2014-02-23 13:35:05 +00:00
2017-01-07 21:25:37 +00:00
PoolVector < String > rnames ;
2014-02-23 13:35:05 +00:00
rnames . resize ( names . size ( ) ) ;
if ( names . size ( ) ) {
2017-03-05 15:44:50 +00:00
PoolVector < String > : : Write r = rnames . write ( ) ;
2014-02-23 13:35:05 +00:00
2017-03-05 15:44:50 +00:00
for ( int i = 0 ; i < names . size ( ) ; i + + )
r [ i ] = names [ i ] ;
2014-02-23 13:35:05 +00:00
}
Dictionary d ;
2017-03-05 15:44:50 +00:00
d [ " names " ] = rnames ;
d [ " variants " ] = variants ;
2014-02-23 13:35:05 +00:00
Vector < int > rnodes ;
2017-03-05 15:44:50 +00:00
d [ " node_count " ] = nodes . size ( ) ;
2014-02-23 13:35:05 +00:00
2017-03-05 15:44:50 +00:00
for ( int i = 0 ; i < nodes . size ( ) ; i + + ) {
2014-02-23 13:35:05 +00:00
2017-03-05 15:44:50 +00:00
const NodeData & nd = nodes [ i ] ;
2014-02-23 13:35:05 +00:00
rnodes . push_back ( nd . parent ) ;
rnodes . push_back ( nd . owner ) ;
rnodes . push_back ( nd . type ) ;
2017-12-16 18:48:16 +00:00
uint32_t name_index = nd . name ;
2018-01-18 20:37:17 +00:00
if ( nd . index < ( 1 < < ( 32 - NAME_INDEX_BITS ) ) - 1 ) { //save if less than 16k children
2017-12-16 18:48:16 +00:00
name_index | = uint32_t ( nd . index + 1 ) < < NAME_INDEX_BITS ; //for backwards compatibility, index 0 is no index
}
rnodes . push_back ( name_index ) ;
2014-02-23 13:35:05 +00:00
rnodes . push_back ( nd . instance ) ;
rnodes . push_back ( nd . properties . size ( ) ) ;
2017-03-05 15:44:50 +00:00
for ( int j = 0 ; j < nd . properties . size ( ) ; j + + ) {
2014-02-23 13:35:05 +00:00
rnodes . push_back ( nd . properties [ j ] . name ) ;
rnodes . push_back ( nd . properties [ j ] . value ) ;
}
rnodes . push_back ( nd . groups . size ( ) ) ;
2017-03-05 15:44:50 +00:00
for ( int j = 0 ; j < nd . groups . size ( ) ; j + + ) {
2014-02-23 13:35:05 +00:00
rnodes . push_back ( nd . groups [ j ] ) ;
}
}
2017-03-05 15:44:50 +00:00
d [ " nodes " ] = rnodes ;
2014-02-23 13:35:05 +00:00
Vector < int > rconns ;
2017-03-05 15:44:50 +00:00
d [ " conn_count " ] = connections . size ( ) ;
2014-02-23 13:35:05 +00:00
2017-03-05 15:44:50 +00:00
for ( int i = 0 ; i < connections . size ( ) ; i + + ) {
2014-02-23 13:35:05 +00:00
2017-03-05 15:44:50 +00:00
const ConnectionData & cd = connections [ i ] ;
2014-02-23 13:35:05 +00:00
rconns . push_back ( cd . from ) ;
rconns . push_back ( cd . to ) ;
rconns . push_back ( cd . signal ) ;
rconns . push_back ( cd . method ) ;
rconns . push_back ( cd . flags ) ;
rconns . push_back ( cd . binds . size ( ) ) ;
2017-03-05 15:44:50 +00:00
for ( int j = 0 ; j < cd . binds . size ( ) ; j + + )
2014-02-23 13:35:05 +00:00
rconns . push_back ( cd . binds [ j ] ) ;
}
2017-03-05 15:44:50 +00:00
d [ " conns " ] = rconns ;
2015-10-10 12:09:09 +00:00
Array rnode_paths ;
rnode_paths . resize ( node_paths . size ( ) ) ;
2017-03-05 15:44:50 +00:00
for ( int i = 0 ; i < node_paths . size ( ) ; i + + ) {
rnode_paths [ i ] = node_paths [ i ] ;
2016-03-08 23:00:52 +00:00
}
2017-03-05 15:44:50 +00:00
d [ " node_paths " ] = rnode_paths ;
2015-10-10 12:09:09 +00:00
Array reditable_instances ;
reditable_instances . resize ( editable_instances . size ( ) ) ;
2017-03-05 15:44:50 +00:00
for ( int i = 0 ; i < editable_instances . size ( ) ; i + + ) {
reditable_instances [ i ] = editable_instances [ i ] ;
2015-10-10 12:09:09 +00:00
}
2017-03-05 15:44:50 +00:00
d [ " editable_instances " ] = reditable_instances ;
if ( base_scene_idx > = 0 ) {
d [ " base_scene " ] = base_scene_idx ;
2015-10-10 12:09:09 +00:00
}
2017-03-05 15:44:50 +00:00
d [ " version " ] = PACK_VERSION ;
2014-02-23 13:35:05 +00:00
2017-01-14 11:26:56 +00:00
//d["path"]=path;
2014-02-23 13:35:05 +00:00
return d ;
}
2015-10-10 12:09:09 +00:00
int SceneState : : get_node_count ( ) const {
return nodes . size ( ) ;
}
StringName SceneState : : get_node_type ( int p_idx ) const {
2017-03-05 15:44:50 +00:00
ERR_FAIL_INDEX_V ( p_idx , nodes . size ( ) , StringName ( ) ) ;
if ( nodes [ p_idx ] . type = = TYPE_INSTANCED )
2015-10-10 12:09:09 +00:00
return StringName ( ) ;
return names [ nodes [ p_idx ] . type ] ;
}
StringName SceneState : : get_node_name ( int p_idx ) const {
2017-03-05 15:44:50 +00:00
ERR_FAIL_INDEX_V ( p_idx , nodes . size ( ) , StringName ( ) ) ;
2015-10-10 12:09:09 +00:00
return names [ nodes [ p_idx ] . name ] ;
}
2017-12-08 14:05:15 +00:00
int SceneState : : get_node_index ( int p_idx ) const {
ERR_FAIL_INDEX_V ( p_idx , nodes . size ( ) , - 1 ) ;
return nodes [ p_idx ] . index ;
}
2016-02-21 14:17:50 +00:00
bool SceneState : : is_node_instance_placeholder ( int p_idx ) const {
2017-03-05 15:44:50 +00:00
ERR_FAIL_INDEX_V ( p_idx , nodes . size ( ) , false ) ;
2016-02-21 14:17:50 +00:00
2017-09-07 19:48:50 +00:00
return nodes [ p_idx ] . instance > = 0 & & ( nodes [ p_idx ] . instance & FLAG_INSTANCE_IS_PLACEHOLDER ) ;
2016-02-21 14:17:50 +00:00
}
2015-10-10 12:09:09 +00:00
Ref < PackedScene > SceneState : : get_node_instance ( int p_idx ) const {
2017-03-05 15:44:50 +00:00
ERR_FAIL_INDEX_V ( p_idx , nodes . size ( ) , Ref < PackedScene > ( ) ) ;
2015-11-28 23:56:14 +00:00
2017-03-05 15:44:50 +00:00
if ( nodes [ p_idx ] . instance > = 0 ) {
if ( nodes [ p_idx ] . instance & FLAG_INSTANCE_IS_PLACEHOLDER )
2016-02-21 14:17:50 +00:00
return Ref < PackedScene > ( ) ;
else
2017-03-05 15:44:50 +00:00
return variants [ nodes [ p_idx ] . instance & FLAG_MASK ] ;
} else if ( nodes [ p_idx ] . parent < 0 | | nodes [ p_idx ] . parent = = NO_PARENT_SAVED ) {
2015-10-10 12:09:09 +00:00
2017-03-05 15:44:50 +00:00
if ( base_scene_idx > = 0 ) {
2015-10-10 12:09:09 +00:00
return variants [ base_scene_idx ] ;
}
}
return Ref < PackedScene > ( ) ;
}
2016-02-21 14:17:50 +00:00
String SceneState : : get_node_instance_placeholder ( int p_idx ) const {
2017-03-05 15:44:50 +00:00
ERR_FAIL_INDEX_V ( p_idx , nodes . size ( ) , String ( ) ) ;
2016-02-21 14:17:50 +00:00
2017-09-07 19:48:50 +00:00
if ( nodes [ p_idx ] . instance > = 0 & & ( nodes [ p_idx ] . instance & FLAG_INSTANCE_IS_PLACEHOLDER ) ) {
2017-03-05 15:44:50 +00:00
return variants [ nodes [ p_idx ] . instance & FLAG_MASK ] ;
2016-02-21 14:17:50 +00:00
}
return String ( ) ;
}
2017-03-05 15:44:50 +00:00
Vector < StringName > SceneState : : get_node_groups ( int p_idx ) const {
ERR_FAIL_INDEX_V ( p_idx , nodes . size ( ) , Vector < StringName > ( ) ) ;
2015-10-10 12:09:09 +00:00
Vector < StringName > groups ;
2017-03-05 15:44:50 +00:00
for ( int i = 0 ; i < nodes [ p_idx ] . groups . size ( ) ; i + + ) {
2015-10-10 12:09:09 +00:00
groups . push_back ( names [ nodes [ p_idx ] . groups [ i ] ] ) ;
}
return groups ;
}
2017-03-05 15:44:50 +00:00
NodePath SceneState : : get_node_path ( int p_idx , bool p_for_parent ) const {
2015-10-10 12:09:09 +00:00
2017-03-05 15:44:50 +00:00
ERR_FAIL_INDEX_V ( p_idx , nodes . size ( ) , NodePath ( ) ) ;
2015-10-10 12:09:09 +00:00
2017-03-05 15:44:50 +00:00
if ( nodes [ p_idx ] . parent < 0 | | nodes [ p_idx ] . parent = = NO_PARENT_SAVED ) {
2015-10-10 12:09:09 +00:00
if ( p_for_parent ) {
return NodePath ( ) ;
} else {
return NodePath ( " . " ) ;
}
}
Vector < StringName > sub_path ;
NodePath base_path ;
2017-03-05 15:44:50 +00:00
int nidx = p_idx ;
while ( true ) {
if ( nodes [ nidx ] . parent = = NO_PARENT_SAVED | | nodes [ nidx ] . parent < 0 ) {
2015-10-10 12:09:09 +00:00
2017-03-05 15:44:50 +00:00
sub_path . insert ( 0 , " . " ) ;
2015-10-10 12:09:09 +00:00
break ;
}
2017-03-05 15:44:50 +00:00
if ( ! p_for_parent | | p_idx ! = nidx ) {
sub_path . insert ( 0 , names [ nodes [ nidx ] . name ] ) ;
2015-10-10 12:09:09 +00:00
}
2017-03-05 15:44:50 +00:00
if ( nodes [ nidx ] . parent & FLAG_ID_IS_PATH ) {
base_path = node_paths [ nodes [ nidx ] . parent & FLAG_MASK ] ;
2015-10-10 12:09:09 +00:00
break ;
} else {
2017-03-05 15:44:50 +00:00
nidx = nodes [ nidx ] . parent & FLAG_MASK ;
2015-10-10 12:09:09 +00:00
}
}
2017-03-05 15:44:50 +00:00
for ( int i = base_path . get_name_count ( ) - 1 ; i > = 0 ; i - - ) {
sub_path . insert ( 0 , base_path . get_name ( i ) ) ;
2015-10-10 12:09:09 +00:00
}
if ( sub_path . empty ( ) ) {
return NodePath ( " . " ) ;
}
2017-03-05 15:44:50 +00:00
return NodePath ( sub_path , false ) ;
2015-10-10 12:09:09 +00:00
}
int SceneState : : get_node_property_count ( int p_idx ) const {
2017-03-05 15:44:50 +00:00
ERR_FAIL_INDEX_V ( p_idx , nodes . size ( ) , - 1 ) ;
2015-10-10 12:09:09 +00:00
return nodes [ p_idx ] . properties . size ( ) ;
}
2017-03-05 15:44:50 +00:00
StringName SceneState : : get_node_property_name ( int p_idx , int p_prop ) const {
ERR_FAIL_INDEX_V ( p_idx , nodes . size ( ) , StringName ( ) ) ;
ERR_FAIL_INDEX_V ( p_prop , nodes [ p_idx ] . properties . size ( ) , StringName ( ) ) ;
2015-10-10 12:09:09 +00:00
return names [ nodes [ p_idx ] . properties [ p_prop ] . name ] ;
}
2017-03-05 15:44:50 +00:00
Variant SceneState : : get_node_property_value ( int p_idx , int p_prop ) const {
ERR_FAIL_INDEX_V ( p_idx , nodes . size ( ) , Variant ( ) ) ;
ERR_FAIL_INDEX_V ( p_prop , nodes [ p_idx ] . properties . size ( ) , Variant ( ) ) ;
2015-10-10 12:09:09 +00:00
return variants [ nodes [ p_idx ] . properties [ p_prop ] . value ] ;
}
NodePath SceneState : : get_node_owner_path ( int p_idx ) const {
2017-03-05 15:44:50 +00:00
ERR_FAIL_INDEX_V ( p_idx , nodes . size ( ) , NodePath ( ) ) ;
if ( nodes [ p_idx ] . owner < 0 | | nodes [ p_idx ] . owner = = NO_PARENT_SAVED )
2015-10-10 12:09:09 +00:00
return NodePath ( ) ; //root likely
2017-03-05 15:44:50 +00:00
if ( nodes [ p_idx ] . owner & FLAG_ID_IS_PATH ) {
return node_paths [ nodes [ p_idx ] . owner & FLAG_MASK ] ;
2015-10-10 12:09:09 +00:00
} else {
2017-03-05 15:44:50 +00:00
return get_node_path ( nodes [ p_idx ] . owner & FLAG_MASK ) ;
2015-10-10 12:09:09 +00:00
}
}
int SceneState : : get_connection_count ( ) const {
return connections . size ( ) ;
}
2017-03-05 15:44:50 +00:00
NodePath SceneState : : get_connection_source ( int p_idx ) const {
2015-10-10 12:09:09 +00:00
2017-03-05 15:44:50 +00:00
ERR_FAIL_INDEX_V ( p_idx , connections . size ( ) , NodePath ( ) ) ;
if ( connections [ p_idx ] . from & FLAG_ID_IS_PATH ) {
return node_paths [ connections [ p_idx ] . from & FLAG_MASK ] ;
2015-10-10 12:09:09 +00:00
} else {
2017-03-05 15:44:50 +00:00
return get_node_path ( connections [ p_idx ] . from & FLAG_MASK ) ;
2015-10-10 12:09:09 +00:00
}
}
2017-03-05 15:44:50 +00:00
StringName SceneState : : get_connection_signal ( int p_idx ) const {
2015-10-10 12:09:09 +00:00
2017-03-05 15:44:50 +00:00
ERR_FAIL_INDEX_V ( p_idx , connections . size ( ) , StringName ( ) ) ;
2015-10-10 12:09:09 +00:00
return names [ connections [ p_idx ] . signal ] ;
}
2017-03-05 15:44:50 +00:00
NodePath SceneState : : get_connection_target ( int p_idx ) const {
2015-10-10 12:09:09 +00:00
2017-03-05 15:44:50 +00:00
ERR_FAIL_INDEX_V ( p_idx , connections . size ( ) , NodePath ( ) ) ;
if ( connections [ p_idx ] . to & FLAG_ID_IS_PATH ) {
return node_paths [ connections [ p_idx ] . to & FLAG_MASK ] ;
2015-10-10 12:09:09 +00:00
} else {
2017-03-05 15:44:50 +00:00
return get_node_path ( connections [ p_idx ] . to & FLAG_MASK ) ;
2015-10-10 12:09:09 +00:00
}
}
2017-03-05 15:44:50 +00:00
StringName SceneState : : get_connection_method ( int p_idx ) const {
2015-10-10 12:09:09 +00:00
2017-03-05 15:44:50 +00:00
ERR_FAIL_INDEX_V ( p_idx , connections . size ( ) , StringName ( ) ) ;
2015-10-10 12:09:09 +00:00
return names [ connections [ p_idx ] . method ] ;
}
2016-07-19 23:04:06 +00:00
2017-03-05 15:44:50 +00:00
int SceneState : : get_connection_flags ( int p_idx ) const {
2016-07-19 23:04:06 +00:00
2017-03-05 15:44:50 +00:00
ERR_FAIL_INDEX_V ( p_idx , connections . size ( ) , - 1 ) ;
2015-10-10 12:09:09 +00:00
return connections [ p_idx ] . flags ;
}
Array SceneState : : get_connection_binds ( int p_idx ) const {
2017-03-05 15:44:50 +00:00
ERR_FAIL_INDEX_V ( p_idx , connections . size ( ) , Array ( ) ) ;
2015-10-10 12:09:09 +00:00
Array binds ;
2017-03-05 15:44:50 +00:00
for ( int i = 0 ; i < connections [ p_idx ] . binds . size ( ) ; i + + ) {
2015-10-10 12:09:09 +00:00
binds . push_back ( variants [ connections [ p_idx ] . binds [ i ] ] ) ;
}
return binds ;
}
2017-03-15 10:46:45 +00:00
bool SceneState : : has_connection ( const NodePath & p_node_from , const StringName & p_signal , const NodePath & p_node_to , const StringName & p_method ) {
2016-07-19 23:04:06 +00:00
2017-03-15 10:46:45 +00:00
// this method cannot be const because of this
Ref < SceneState > ss = this ;
2016-07-19 23:04:06 +00:00
2017-03-15 10:46:45 +00:00
do {
for ( int i = 0 ; i < ss - > connections . size ( ) ; i + + ) {
const ConnectionData & c = ss - > connections [ i ] ;
2016-07-20 00:26:12 +00:00
2017-03-15 10:46:45 +00:00
NodePath np_from ;
2016-07-20 00:26:12 +00:00
2017-03-15 10:46:45 +00:00
if ( c . from & FLAG_ID_IS_PATH ) {
np_from = ss - > node_paths [ c . from & FLAG_MASK ] ;
} else {
np_from = ss - > get_node_path ( c . from ) ;
}
2016-07-20 00:26:12 +00:00
2017-03-15 10:46:45 +00:00
NodePath np_to ;
2016-07-20 00:26:12 +00:00
2017-03-15 10:46:45 +00:00
if ( c . to & FLAG_ID_IS_PATH ) {
np_to = ss - > node_paths [ c . to & FLAG_MASK ] ;
} else {
np_to = ss - > get_node_path ( c . to ) ;
}
2016-07-19 23:04:06 +00:00
2017-03-15 10:46:45 +00:00
StringName sn_signal = ss - > names [ c . signal ] ;
StringName sn_method = ss - > names [ c . method ] ;
if ( np_from = = p_node_from & & sn_signal = = p_signal & & np_to = = p_node_to & & sn_method = = p_method ) {
return true ;
}
2016-07-19 23:04:06 +00:00
}
2017-03-15 10:46:45 +00:00
ss = ss - > _get_base_scene_state ( ) ;
} while ( ss . is_valid ( ) ) ;
2016-07-19 23:04:06 +00:00
return false ;
}
2015-10-10 12:09:09 +00:00
Vector < NodePath > SceneState : : get_editable_instances ( ) const {
return editable_instances ;
}
2015-11-28 23:56:14 +00:00
//add
2017-03-05 15:44:50 +00:00
int SceneState : : add_name ( const StringName & p_name ) {
2015-11-28 23:56:14 +00:00
names . push_back ( p_name ) ;
2017-03-05 15:44:50 +00:00
return names . size ( ) - 1 ;
2015-11-28 23:56:14 +00:00
}
2017-03-05 15:44:50 +00:00
int SceneState : : find_name ( const StringName & p_name ) const {
2016-07-19 23:04:06 +00:00
2017-03-05 15:44:50 +00:00
for ( int i = 0 ; i < names . size ( ) ; i + + ) {
if ( names [ i ] = = p_name )
2016-07-19 23:04:06 +00:00
return i ;
}
return - 1 ;
}
2017-03-05 15:44:50 +00:00
int SceneState : : add_value ( const Variant & p_value ) {
2015-11-28 23:56:14 +00:00
variants . push_back ( p_value ) ;
2017-03-05 15:44:50 +00:00
return variants . size ( ) - 1 ;
2015-11-28 23:56:14 +00:00
}
2017-03-05 15:44:50 +00:00
int SceneState : : add_node_path ( const NodePath & p_path ) {
2015-11-28 23:56:14 +00:00
node_paths . push_back ( p_path ) ;
2017-03-05 15:44:50 +00:00
return ( node_paths . size ( ) - 1 ) | FLAG_ID_IS_PATH ;
2015-11-28 23:56:14 +00:00
}
2017-12-08 14:05:15 +00:00
int SceneState : : add_node ( int p_parent , int p_owner , int p_type , int p_name , int p_instance , int p_index ) {
2015-11-28 23:56:14 +00:00
NodeData nd ;
2017-03-05 15:44:50 +00:00
nd . parent = p_parent ;
nd . owner = p_owner ;
nd . type = p_type ;
nd . name = p_name ;
nd . instance = p_instance ;
2017-12-08 14:05:15 +00:00
nd . index = p_index ;
2015-11-28 23:56:14 +00:00
nodes . push_back ( nd ) ;
2017-03-05 15:44:50 +00:00
return nodes . size ( ) - 1 ;
2015-11-28 23:56:14 +00:00
}
2017-03-05 15:44:50 +00:00
void SceneState : : add_node_property ( int p_node , int p_name , int p_value ) {
2015-11-28 23:56:14 +00:00
2017-03-05 15:44:50 +00:00
ERR_FAIL_INDEX ( p_node , nodes . size ( ) ) ;
ERR_FAIL_INDEX ( p_name , names . size ( ) ) ;
ERR_FAIL_INDEX ( p_value , variants . size ( ) ) ;
2015-11-28 23:56:14 +00:00
NodeData : : Property prop ;
2017-03-05 15:44:50 +00:00
prop . name = p_name ;
prop . value = p_value ;
2018-07-25 01:11:03 +00:00
nodes . write [ p_node ] . properties . push_back ( prop ) ;
2015-11-28 23:56:14 +00:00
}
2017-03-05 15:44:50 +00:00
void SceneState : : add_node_group ( int p_node , int p_group ) {
2015-11-28 23:56:14 +00:00
2017-03-05 15:44:50 +00:00
ERR_FAIL_INDEX ( p_node , nodes . size ( ) ) ;
ERR_FAIL_INDEX ( p_group , names . size ( ) ) ;
2018-07-25 01:11:03 +00:00
nodes . write [ p_node ] . groups . push_back ( p_group ) ;
2015-11-28 23:56:14 +00:00
}
2017-03-05 15:44:50 +00:00
void SceneState : : set_base_scene ( int p_idx ) {
2015-11-28 23:56:14 +00:00
2017-03-05 15:44:50 +00:00
ERR_FAIL_INDEX ( p_idx , variants . size ( ) ) ;
base_scene_idx = p_idx ;
2015-11-28 23:56:14 +00:00
}
2017-03-05 15:44:50 +00:00
void SceneState : : add_connection ( int p_from , int p_to , int p_signal , int p_method , int p_flags , const Vector < int > & p_binds ) {
2015-11-28 23:56:14 +00:00
2017-03-05 15:44:50 +00:00
ERR_FAIL_INDEX ( p_signal , names . size ( ) ) ;
ERR_FAIL_INDEX ( p_method , names . size ( ) ) ;
2015-11-28 23:56:14 +00:00
2017-03-05 15:44:50 +00:00
for ( int i = 0 ; i < p_binds . size ( ) ; i + + ) {
ERR_FAIL_INDEX ( p_binds [ i ] , variants . size ( ) ) ;
2015-11-28 23:56:14 +00:00
}
ConnectionData c ;
2017-03-05 15:44:50 +00:00
c . from = p_from ;
c . to = p_to ;
c . signal = p_signal ;
c . method = p_method ;
c . flags = p_flags ;
c . binds = p_binds ;
2015-11-28 23:56:14 +00:00
connections . push_back ( c ) ;
}
2017-03-05 15:44:50 +00:00
void SceneState : : add_editable_instance ( const NodePath & p_path ) {
2015-11-28 23:56:14 +00:00
editable_instances . push_back ( p_path ) ;
}
2017-01-07 21:25:37 +00:00
PoolVector < String > SceneState : : _get_node_groups ( int p_idx ) const {
2015-10-10 12:09:09 +00:00
2016-01-23 15:01:42 +00:00
Vector < StringName > groups = get_node_groups ( p_idx ) ;
2017-01-07 21:25:37 +00:00
PoolVector < String > ret ;
2016-01-23 15:01:42 +00:00
2017-03-05 15:44:50 +00:00
for ( int i = 0 ; i < groups . size ( ) ; i + + )
2016-01-23 15:01:42 +00:00
ret . push_back ( groups [ i ] ) ;
return ret ;
}
void SceneState : : _bind_methods ( ) {
//unbuild API
2017-03-05 15:44:50 +00:00
ClassDB : : bind_method ( D_METHOD ( " get_node_count " ) , & SceneState : : get_node_count ) ;
ClassDB : : bind_method ( D_METHOD ( " get_node_type " , " idx " ) , & SceneState : : get_node_type ) ;
ClassDB : : bind_method ( D_METHOD ( " get_node_name " , " idx " ) , & SceneState : : get_node_name ) ;
ClassDB : : bind_method ( D_METHOD ( " get_node_path " , " idx " , " for_parent " ) , & SceneState : : get_node_path , DEFVAL ( false ) ) ;
ClassDB : : bind_method ( D_METHOD ( " get_node_owner_path " , " idx " ) , & SceneState : : get_node_owner_path ) ;
ClassDB : : bind_method ( D_METHOD ( " is_node_instance_placeholder " , " idx " ) , & SceneState : : is_node_instance_placeholder ) ;
ClassDB : : bind_method ( D_METHOD ( " get_node_instance_placeholder " , " idx " ) , & SceneState : : get_node_instance_placeholder ) ;
2017-08-09 11:19:41 +00:00
ClassDB : : bind_method ( D_METHOD ( " get_node_instance " , " idx " ) , & SceneState : : get_node_instance ) ;
2017-03-05 15:44:50 +00:00
ClassDB : : bind_method ( D_METHOD ( " get_node_groups " , " idx " ) , & SceneState : : _get_node_groups ) ;
2017-12-08 14:05:15 +00:00
ClassDB : : bind_method ( D_METHOD ( " get_node_index " , " idx " ) , & SceneState : : get_node_index ) ;
2017-03-05 15:44:50 +00:00
ClassDB : : bind_method ( D_METHOD ( " get_node_property_count " , " idx " ) , & SceneState : : get_node_property_count ) ;
ClassDB : : bind_method ( D_METHOD ( " get_node_property_name " , " idx " , " prop_idx " ) , & SceneState : : get_node_property_name ) ;
2017-08-09 11:19:41 +00:00
ClassDB : : bind_method ( D_METHOD ( " get_node_property_value " , " idx " , " prop_idx " ) , & SceneState : : get_node_property_value ) ;
2017-03-05 15:44:50 +00:00
ClassDB : : bind_method ( D_METHOD ( " get_connection_count " ) , & SceneState : : get_connection_count ) ;
ClassDB : : bind_method ( D_METHOD ( " get_connection_source " , " idx " ) , & SceneState : : get_connection_source ) ;
ClassDB : : bind_method ( D_METHOD ( " get_connection_signal " , " idx " ) , & SceneState : : get_connection_signal ) ;
ClassDB : : bind_method ( D_METHOD ( " get_connection_target " , " idx " ) , & SceneState : : get_connection_target ) ;
ClassDB : : bind_method ( D_METHOD ( " get_connection_method " , " idx " ) , & SceneState : : get_connection_method ) ;
ClassDB : : bind_method ( D_METHOD ( " get_connection_flags " , " idx " ) , & SceneState : : get_connection_flags ) ;
ClassDB : : bind_method ( D_METHOD ( " get_connection_binds " , " idx " ) , & SceneState : : get_connection_binds ) ;
2017-08-20 15:45:01 +00:00
BIND_ENUM_CONSTANT ( GEN_EDIT_STATE_DISABLED ) ;
BIND_ENUM_CONSTANT ( GEN_EDIT_STATE_INSTANCE ) ;
BIND_ENUM_CONSTANT ( GEN_EDIT_STATE_MAIN ) ;
2016-01-23 15:01:42 +00:00
}
2015-10-10 12:09:09 +00:00
SceneState : : SceneState ( ) {
2017-03-05 15:44:50 +00:00
base_scene_idx = - 1 ;
last_modified_time = 0 ;
2015-10-10 12:09:09 +00:00
}
////////////////
2017-08-11 19:10:05 +00:00
void PackedScene : : _set_bundled_scene ( const Dictionary & p_scene ) {
2015-10-10 12:09:09 +00:00
2017-08-11 19:10:05 +00:00
state - > set_bundled_scene ( p_scene ) ;
2015-10-10 12:09:09 +00:00
}
Dictionary PackedScene : : _get_bundled_scene ( ) const {
return state - > get_bundled_scene ( ) ;
}
Error PackedScene : : pack ( Node * p_scene ) {
return state - > pack ( p_scene ) ;
}
void PackedScene : : clear ( ) {
state - > clear ( ) ;
}
bool PackedScene : : can_instance ( ) const {
return state - > can_instance ( ) ;
}
2017-01-10 04:04:31 +00:00
Node * PackedScene : : instance ( GenEditState p_edit_state ) const {
2015-10-10 12:09:09 +00:00
# ifndef TOOLS_ENABLED
2017-03-05 15:44:50 +00:00
if ( p_edit_state ! = GEN_EDIT_STATE_DISABLED ) {
2015-10-10 12:09:09 +00:00
ERR_EXPLAIN ( " Edit state is only for editors, does not work without tools compiled " ) ;
2017-03-05 15:44:50 +00:00
ERR_FAIL_COND_V ( p_edit_state ! = GEN_EDIT_STATE_DISABLED , NULL ) ;
2015-10-10 12:09:09 +00:00
}
# endif
2017-01-10 04:04:31 +00:00
Node * s = state - > instance ( ( SceneState : : GenEditState ) p_edit_state ) ;
2015-10-10 12:09:09 +00:00
if ( ! s )
return NULL ;
2017-03-05 15:44:50 +00:00
if ( p_edit_state ! = GEN_EDIT_STATE_DISABLED ) {
2015-10-10 12:09:09 +00:00
s - > set_scene_instance_state ( state ) ;
}
2017-03-05 15:44:50 +00:00
if ( get_path ( ) ! = " " & & get_path ( ) . find ( " :: " ) = = - 1 )
2015-10-10 12:09:09 +00:00
s - > set_filename ( get_path ( ) ) ;
s - > notification ( Node : : NOTIFICATION_INSTANCED ) ;
return s ;
}
2016-01-14 14:06:20 +00:00
void PackedScene : : replace_state ( Ref < SceneState > p_by ) {
2017-03-05 15:44:50 +00:00
state = p_by ;
2016-01-14 14:06:20 +00:00
state - > set_path ( get_path ( ) ) ;
# ifdef TOOLS_ENABLED
state - > set_last_modified_time ( get_last_modified_time ( ) ) ;
# endif
}
2015-12-13 23:39:01 +00:00
void PackedScene : : recreate_state ( ) {
2017-03-05 15:44:50 +00:00
state = Ref < SceneState > ( memnew ( SceneState ) ) ;
2015-12-13 23:39:01 +00:00
state - > set_path ( get_path ( ) ) ;
# ifdef TOOLS_ENABLED
state - > set_last_modified_time ( get_last_modified_time ( ) ) ;
# endif
}
2015-10-10 12:09:09 +00:00
Ref < SceneState > PackedScene : : get_state ( ) {
return state ;
}
2017-03-05 15:44:50 +00:00
void PackedScene : : set_path ( const String & p_path , bool p_take_over ) {
2015-10-10 12:09:09 +00:00
state - > set_path ( p_path ) ;
2017-03-05 15:44:50 +00:00
Resource : : set_path ( p_path , p_take_over ) ;
2015-10-10 12:09:09 +00:00
}
2014-02-23 13:35:05 +00:00
void PackedScene : : _bind_methods ( ) {
2017-08-09 11:19:41 +00:00
ClassDB : : bind_method ( D_METHOD ( " pack " , " path " ) , & PackedScene : : pack ) ;
ClassDB : : bind_method ( D_METHOD ( " instance " , " edit_state " ) , & PackedScene : : instance , DEFVAL ( GEN_EDIT_STATE_DISABLED ) ) ;
2017-03-05 15:44:50 +00:00
ClassDB : : bind_method ( D_METHOD ( " can_instance " ) , & PackedScene : : can_instance ) ;
ClassDB : : bind_method ( D_METHOD ( " _set_bundled_scene " ) , & PackedScene : : _set_bundled_scene ) ;
ClassDB : : bind_method ( D_METHOD ( " _get_bundled_scene " ) , & PackedScene : : _get_bundled_scene ) ;
2017-08-09 11:19:41 +00:00
ClassDB : : bind_method ( D_METHOD ( " get_state " ) , & PackedScene : : get_state ) ;
2014-02-23 13:35:05 +00:00
2017-03-05 15:44:50 +00:00
ADD_PROPERTY ( PropertyInfo ( Variant : : DICTIONARY , " _bundled " ) , " _set_bundled_scene " , " _get_bundled_scene " ) ;
2017-01-10 04:04:31 +00:00
2017-08-20 15:45:01 +00:00
BIND_ENUM_CONSTANT ( GEN_EDIT_STATE_DISABLED ) ;
BIND_ENUM_CONSTANT ( GEN_EDIT_STATE_INSTANCE ) ;
BIND_ENUM_CONSTANT ( GEN_EDIT_STATE_MAIN ) ;
2014-02-23 13:35:05 +00:00
}
PackedScene : : PackedScene ( ) {
2017-03-05 15:44:50 +00:00
state = Ref < SceneState > ( memnew ( SceneState ) ) ;
2014-02-23 13:35:05 +00:00
}