浏览代码

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

Juan Linietsky 9 年之前
父节点
当前提交
b91b89cf60
共有 3 个文件被更改,包括 64 次插入7 次删除
  1. 28 1
      scene/resources/packed_scene.cpp
  2. 6 5
      scene/resources/packed_scene.h
  3. 30 1
      scene/resources/scene_format_text.cpp

+ 28 - 1
scene/resources/packed_scene.cpp

@@ -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);

+ 6 - 5
scene/resources/packed_scene.h

@@ -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;

+ 30 - 1
scene/resources/scene_format_text.cpp

@@ -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;