Add support for placeholders in tscn, which was missing. Closes #3652

This commit is contained in:
Juan Linietsky 2016-02-21 11:17:50 -03:00
parent d27b83d4bd
commit b91b89cf60
3 changed files with 64 additions and 7 deletions

View File

@ -1316,11 +1316,23 @@ StringName SceneState::get_node_name(int p_idx) const {
return names[nodes[p_idx].name];
}
bool SceneState::is_node_instance_placeholder(int p_idx) const {
ERR_FAIL_INDEX_V(p_idx,nodes.size(),false);
return nodes[p_idx].instance>=0 && nodes[p_idx].instance&FLAG_INSTANCE_IS_PLACEHOLDER;
}
Ref<PackedScene> SceneState::get_node_instance(int p_idx) const {
ERR_FAIL_INDEX_V(p_idx,nodes.size(),Ref<PackedScene>());
if (nodes[p_idx].instance>=0) {
return variants[nodes[p_idx].instance];
if (nodes[p_idx].instance&FLAG_INSTANCE_IS_PLACEHOLDER)
return Ref<PackedScene>();
else
return variants[nodes[p_idx].instance&FLAG_MASK];
} else if (nodes[p_idx].parent<0 || nodes[p_idx].parent==NO_PARENT_SAVED) {
if (base_scene_idx>=0) {
@ -1334,6 +1346,19 @@ Ref<PackedScene> SceneState::get_node_instance(int p_idx) const {
}
String SceneState::get_node_instance_placeholder(int p_idx) const {
ERR_FAIL_INDEX_V(p_idx,nodes.size(),String());
if (nodes[p_idx].instance>=0 && nodes[p_idx].instance&FLAG_INSTANCE_IS_PLACEHOLDER) {
return variants[nodes[p_idx].instance&FLAG_MASK];
}
return String();
}
Vector<StringName> SceneState::get_node_groups(int p_idx) const{
ERR_FAIL_INDEX_V(p_idx,nodes.size(),Vector<StringName>());
Vector<StringName> groups;
@ -1577,6 +1602,8 @@ void SceneState::_bind_methods() {
ObjectTypeDB::bind_method(_MD("get_node_name","idx"),&SceneState::get_node_name);
ObjectTypeDB::bind_method(_MD("get_node_path","idx","for_parent"),&SceneState::get_node_path,DEFVAL(false));
ObjectTypeDB::bind_method(_MD("get_node_owner_path","idx"),&SceneState::get_node_owner_path);
ObjectTypeDB::bind_method(_MD("is_node_instance_placeholder","idx"),&SceneState::is_node_instance_placeholder);
ObjectTypeDB::bind_method(_MD("get_node_instance_placeholder","idx"),&SceneState::get_node_instance_placeholder);
ObjectTypeDB::bind_method(_MD("get_node_instance:PackedScene","idx"),&SceneState::get_node_instance);
ObjectTypeDB::bind_method(_MD("get_node_groups","idx"),&SceneState::_get_node_groups);
ObjectTypeDB::bind_method(_MD("get_node_property_count","idx"),&SceneState::get_node_property_count);

View File

@ -48,11 +48,7 @@ class SceneState : public Reference {
int base_scene_idx;
enum {
FLAG_ID_IS_PATH=(1<<30),
FLAG_INSTANCE_IS_PLACEHOLDER=(1<<30),
FLAG_MASK=(1<<24)-1,
NO_PARENT_SAVED=0x7FFFFFFF,
};
struct NodeData {
@ -115,7 +111,10 @@ protected:
public:
enum {
TYPE_INSTANCED=0x7FFFFFFF
FLAG_ID_IS_PATH=(1<<30),
TYPE_INSTANCED=0x7FFFFFFF,
FLAG_INSTANCE_IS_PLACEHOLDER=(1<<30),
FLAG_MASK=(1<<24)-1,
};
static void set_disable_placeholders(bool p_disable);
@ -148,6 +147,8 @@ public:
NodePath get_node_path(int p_idx,bool p_for_parent=false) const;
NodePath get_node_owner_path(int p_idx) const;
Ref<PackedScene> get_node_instance(int p_idx) const;
String get_node_instance_placeholder(int p_idx) const;
bool is_node_instance_placeholder(int p_idx) const;
Vector<StringName> get_node_groups(int p_idx) const;
int get_node_property_count(int p_idx) const;

View File

@ -389,6 +389,22 @@ Error ResourceInteractiveLoaderText::poll() {
}
}
if (next_tag.fields.has("instance_placeholder")) {
String path=next_tag.fields["instance_placeholder"];
int path_v = packed_scene->get_state()->add_value(path);
if (packed_scene->get_state()->get_node_count()==0) {
error=ERR_FILE_CORRUPT;
error_text="Instance Placeholder can't be used for inheritance.";
_printerr();
return error;
}
instance=path_v|SceneState::FLAG_INSTANCE_IS_PLACEHOLDER;
}
if (next_tag.fields.has("owner")) {
owner=packed_scene->get_state()->add_node_path(next_tag.fields["owner"]);
} else {
@ -1124,7 +1140,10 @@ Error ResourceFormatSaverTextInstance::save(const String &p_path,const RES& p_re
if (packed_scene.is_valid()) {
//add instances to external resources if saving a packed scene
for(int i=0;i<packed_scene->get_state()->get_node_count();i++) {
Ref<PackedScene> instance=packed_scene->get_state()->get_node_instance(i);
if (packed_scene->get_state()->is_node_instance_placeholder(i))
continue;
Ref<PackedScene> instance=packed_scene->get_state()->get_node_instance(i);
if (instance.is_valid() && !external_resources.has(instance)) {
int index = external_resources.size();
external_resources[instance]=index;
@ -1268,8 +1287,10 @@ Error ResourceFormatSaverTextInstance::save(const String &p_path,const RES& p_re
NodePath path = state->get_node_path(i,true);
NodePath owner = state->get_node_owner_path(i);
Ref<PackedScene> instance = state->get_node_instance(i);
String instance_placeholder = state->get_node_instance_placeholder(i);
Vector<StringName> groups = state->get_node_groups(i);
if (instance.is_valid())
print_line("for path "+String(path)+" instance "+instance->get_path());
@ -1298,6 +1319,14 @@ Error ResourceFormatSaverTextInstance::save(const String &p_path,const RES& p_re
f->store_string(header);
if (instance_placeholder!=String()) {
String vars;
f->store_string(" instance_placeholder=");
VariantWriter::write_to_string(instance_placeholder,vars,_write_resources,this);
f->store_string(vars);
}
if (instance.is_valid()) {
String vars;