diff options
author | Juan Linietsky <reduzio@gmail.com> | 2017-01-10 01:04:31 -0300 |
---|---|---|
committer | Juan Linietsky <reduzio@gmail.com> | 2017-01-10 01:07:03 -0300 |
commit | a503f8aadcb8cbc85bde589fb25ea06e599b367b (patch) | |
tree | 070ebbf0dd6af2d43c5519f5e32045b3512f0e9e /scene/resources | |
parent | 68c008ca8d87a1f72fcf17467ee43714954e9ce4 (diff) |
Groundbreaking!! Godot resources can now be flagged to be local to the scene being edited!
This means that each time this scene is instanced, the resource will be unique!
As such, thanks to this, the following features were implemented:
-ButtonGroup is no longer a control, it's now a resource local to the scene
-ViewportTexture can be created from the editor and set to any object, making ViewportSprite and other kind of nodes obsolete!
Diffstat (limited to 'scene/resources')
-rw-r--r-- | scene/resources/packed_scene.cpp | 70 | ||||
-rw-r--r-- | scene/resources/packed_scene.h | 19 |
2 files changed, 75 insertions, 14 deletions
diff --git a/scene/resources/packed_scene.cpp b/scene/resources/packed_scene.cpp index c3b98af811..b0161f6898 100644 --- a/scene/resources/packed_scene.cpp +++ b/scene/resources/packed_scene.cpp @@ -42,7 +42,7 @@ bool SceneState::can_instance() const { } -Node *SceneState::instance(bool p_gen_edit_state) const { +Node *SceneState::instance(GenEditState p_edit_state) const { // nodes where instancing failed (because something is missing) List<Node*> stray_instances; @@ -76,7 +76,9 @@ Node *SceneState::instance(bool p_gen_edit_state) const { Node **ret_nodes=(Node**)alloca( sizeof(Node*)*nc ); - bool gen_node_path_cache=p_gen_edit_state && node_path_cache.empty(); + bool gen_node_path_cache=p_edit_state!=GEN_EDIT_STATE_DISABLED && node_path_cache.empty(); + + Map<Ref<Resource>,Ref<Resource> > resources_local_to_scene; for(int i=0;i<nc;i++) { @@ -105,9 +107,9 @@ Node *SceneState::instance(bool p_gen_edit_state) const { //print_line("scene inherit"); Ref<PackedScene> sdata = props[ base_scene_idx ]; ERR_FAIL_COND_V( !sdata.is_valid(), NULL); - node = sdata->instance(p_gen_edit_state); + 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_gen_edit_state) { + if (p_edit_state!=GEN_EDIT_STATE_DISABLED) { node->set_scene_inherited_state(sdata->get_state()); } @@ -121,7 +123,7 @@ Node *SceneState::instance(bool p_gen_edit_state) const { Ref<PackedScene> sdata = ResourceLoader::load(path,"PackedScene"); ERR_FAIL_COND_V( !sdata.is_valid(), NULL); - node = sdata->instance(p_gen_edit_state); + 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); } else { InstancePlaceholder *ip = memnew( InstancePlaceholder ); @@ -132,7 +134,7 @@ Node *SceneState::instance(bool p_gen_edit_state) const { } else { Ref<PackedScene> sdata = props[ n.instance&FLAG_MASK ]; ERR_FAIL_COND_V( !sdata.is_valid(), NULL); - node = sdata->instance(p_gen_edit_state); + 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); } @@ -166,8 +168,8 @@ Node *SceneState::instance(bool p_gen_edit_state) const { } else if (ret_nodes[n.parent]->cast_to<Node2D>()) { obj = memnew( Node2D ); } - } + if (!obj) { obj = memnew( Node ); } @@ -212,7 +214,43 @@ Node *SceneState::instance(bool p_gen_edit_state) const { } } else { - node->set(snames[ nprops[j].name ],props[ nprops[j].value ],&valid); + Variant value = props[ nprops[j].value ]; + + if (value.get_type()==Variant::OBJECT) { + //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()) { + + Map<Ref<Resource>,Ref<Resource> >::Element *E=resources_local_to_scene.find(res); + + if (E) { + value=E->get(); + } else { + + Node *base = i==0?node:ret_nodes[0]; + + if (p_edit_state==GEN_EDIT_STATE_MAIN) { + + res->local_scene=base; + resources_local_to_scene[res]=res; + + } else { + 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; + } + + res->setup_local_to_scene(); + + } + //must make a copy, because this res is local to scene + } + } + } + node->set(snames[ nprops[j].name ],value,&valid); } } } @@ -1693,6 +1731,10 @@ void SceneState::_bind_methods() { ClassDB::bind_method(_MD("get_connection_method","idx"),&SceneState::get_connection_method); ClassDB::bind_method(_MD("get_connection_flags","idx"),&SceneState::get_connection_flags); ClassDB::bind_method(_MD("get_connection_binds","idx"),&SceneState::get_connection_binds); + + BIND_CONSTANT( GEN_EDIT_STATE_DISABLED ); + BIND_CONSTANT( GEN_EDIT_STATE_INSTANCE ); + BIND_CONSTANT( GEN_EDIT_STATE_MAIN ); } SceneState::SceneState() { @@ -1732,7 +1774,7 @@ bool PackedScene::can_instance() const { return state->can_instance(); } -Node *PackedScene::instance(bool p_gen_edit_state) const { +Node *PackedScene::instance(GenEditState p_edit_state) const { #ifndef TOOLS_ENABLED if (p_gen_edit_state) { @@ -1741,11 +1783,11 @@ Node *PackedScene::instance(bool p_gen_edit_state) const { } #endif - Node *s = state->instance(p_gen_edit_state); + Node *s = state->instance((SceneState::GenEditState)p_edit_state); if (!s) return NULL; - if (p_gen_edit_state) { + if (p_edit_state!=GEN_EDIT_STATE_DISABLED) { s->set_scene_instance_state(state); } @@ -1792,7 +1834,7 @@ void PackedScene::set_path(const String& p_path,bool p_take_over) { void PackedScene::_bind_methods() { ClassDB::bind_method(_MD("pack","path:Node"),&PackedScene::pack); - ClassDB::bind_method(_MD("instance:Node","gen_edit_state"),&PackedScene::instance,DEFVAL(false)); + ClassDB::bind_method(_MD("instance:Node","edit_state"),&PackedScene::instance,DEFVAL(false)); ClassDB::bind_method(_MD("can_instance"),&PackedScene::can_instance); ClassDB::bind_method(_MD("_set_bundled_scene"),&PackedScene::_set_bundled_scene); ClassDB::bind_method(_MD("_get_bundled_scene"),&PackedScene::_get_bundled_scene); @@ -1800,6 +1842,10 @@ void PackedScene::_bind_methods() { ADD_PROPERTY( PropertyInfo(Variant::DICTIONARY,"_bundled"),_SCS("_set_bundled_scene"),_SCS("_get_bundled_scene")); + BIND_CONSTANT( GEN_EDIT_STATE_DISABLED ); + BIND_CONSTANT( GEN_EDIT_STATE_INSTANCE ); + BIND_CONSTANT( GEN_EDIT_STATE_MAIN ); + } PackedScene::PackedScene() { diff --git a/scene/resources/packed_scene.h b/scene/resources/packed_scene.h index fd4ed106df..381b356b1e 100644 --- a/scene/resources/packed_scene.h +++ b/scene/resources/packed_scene.h @@ -117,6 +117,12 @@ public: FLAG_MASK=(1<<24)-1, }; + enum GenEditState { + GEN_EDIT_STATE_DISABLED, + GEN_EDIT_STATE_INSTANCE, + GEN_EDIT_STATE_MAIN, + }; + static void set_disable_placeholders(bool p_disable); int find_node_by_path(const NodePath& p_node) const; @@ -136,7 +142,7 @@ public: void clear(); bool can_instance() const; - Node *instance(bool p_gen_edit_state=false) const; + Node *instance(GenEditState p_edit_state) const; //unbuild API @@ -187,6 +193,8 @@ public: SceneState(); }; +VARIANT_ENUM_CAST(SceneState::GenEditState) + class PackedScene : public Resource { GDCLASS(PackedScene, Resource ); @@ -203,13 +211,18 @@ protected: static void _bind_methods(); public: + enum GenEditState { + GEN_EDIT_STATE_DISABLED, + GEN_EDIT_STATE_INSTANCE, + GEN_EDIT_STATE_MAIN, + }; Error pack(Node *p_scene); void clear(); bool can_instance() const; - Node *instance(bool p_gen_edit_state=false) const; + Node *instance(GenEditState p_edit_state=GEN_EDIT_STATE_DISABLED) const; void recreate_state(); void replace_state(Ref<SceneState> p_by); @@ -225,4 +238,6 @@ public: }; +VARIANT_ENUM_CAST(PackedScene::GenEditState) + #endif // SCENE_PRELOADER_H |