Browse Source

-fixes and more fixes to new scene system, seems stable now..
BUT DONT TRUST ME IT MAY STILL BREAK, USE WITH CARE!!

reduz 10 năm trước cách đây
mục cha
commit
078a474135

+ 74 - 0
scene/main/instance_placeholder.cpp

@@ -0,0 +1,74 @@
+#include "instance_placeholder.h"
+
+#include "scene/resources/packed_scene.h"
+#include "io/resource_loader.h"
+
+bool InstancePlaceholder::_set(const StringName& p_name, const Variant& p_value) {
+
+	PropSet ps;
+	ps.name=p_name;
+	ps.value=p_value;
+	stored_values.push_back(ps);
+	return true;
+}
+
+bool InstancePlaceholder::_get(const StringName& p_name,Variant &r_ret) const{
+
+	return false;
+}
+void InstancePlaceholder::_get_property_list( List<PropertyInfo> *p_list) const{
+
+
+}
+
+
+void InstancePlaceholder::set_path(const String& p_name) {
+
+	path=p_name;
+}
+
+String InstancePlaceholder::get_path() const {
+
+	return path;
+}
+void InstancePlaceholder::replace_by_instance(const Ref<PackedScene> &p_custom_scene){
+
+	ERR_FAIL_COND(!is_inside_tree());
+
+	Node *base = get_parent();
+	if (!base)
+		return;
+
+	Ref<PackedScene> ps;
+	if (p_custom_scene.is_valid())
+		ps = p_custom_scene;
+	else
+		ps = ResourceLoader::load(path,"PackedScene");
+
+	if (!ps.is_valid())
+		return;
+	Node *scene = ps->instance();
+	scene->set_name(get_name());
+	int pos = get_position_in_parent();
+
+	for(List<PropSet>::Element *E=stored_values.front();E;E=E->next()) {
+		scene->set(E->get().name,E->get().value);
+	}
+
+	queue_delete();
+
+	base->remove_child(this);
+	base->add_child(scene);
+	base->move_child(scene,pos);
+
+}
+
+void InstancePlaceholder::_bind_methods() {
+
+	ObjectTypeDB::bind_method(_MD("replace_by_instance","custom_scene:PackedScene"),&InstancePlaceholder::replace_by_instance,DEFVAL(Variant()));
+}
+
+InstancePlaceholder::InstancePlaceholder() {
+
+
+}

+ 37 - 0
scene/main/instance_placeholder.h

@@ -0,0 +1,37 @@
+#ifndef INSTANCE_PLACEHOLDER_H
+#define INSTANCE_PLACEHOLDER_H
+
+#include "scene/main/node.h"
+
+class PackedScene;
+
+class InstancePlaceholder : public Node {
+
+	OBJ_TYPE(InstancePlaceholder,Node);
+
+	String path;
+	struct PropSet {
+		StringName name;
+		Variant value;
+	};
+
+	List<PropSet> stored_values;
+
+protected:
+	bool _set(const StringName& p_name, const Variant& p_value);
+	bool _get(const StringName& p_name,Variant &r_ret) const;
+	void _get_property_list( List<PropertyInfo> *p_list) const;
+
+	static void _bind_methods();
+
+public:
+
+	void set_path(const String& p_name);
+	String get_path() const;
+
+	void replace_by_instance(const Ref<PackedScene>& p_custom_scene=Ref<PackedScene>());
+
+	InstancePlaceholder();
+};
+
+#endif // INSTANCE_PLACEHOLDER_H

+ 8 - 4
scene/main/node.cpp

@@ -1052,6 +1052,7 @@ void Node::get_owned_by(Node *p_by,List<Node*> *p_owned) {
 
 void Node::_set_owner_nocheck(Node* p_owner) {
 
+	ERR_FAIL_COND(data.owner);
 	data.owner=p_owner;
 	data.owner->data.owned.push_back( this );
 	data.OW = data.owner->data.owned.back();
@@ -1443,13 +1444,14 @@ Ref<SceneState> Node::get_scene_inherited_state() const{
 	return data.inherited_state;
 }
 
-Vector<StringName> Node::get_instance_groups() const {
+void Node::set_scene_instance_load_placeholder(bool p_enable) {
 
-	return data.instance_groups;
+	data.use_placeholder=p_enable;
 }
-Vector<Node::Connection> Node::get_instance_connections() const{
 
-	return data.instance_connections;
+bool Node::get_scene_instance_load_placeholder() const{
+
+	return data.use_placeholder;
 }
 
 int Node::get_position_in_parent() const {
@@ -2109,6 +2111,7 @@ Node::Node() {
 	data.parent_owned=false;
 	data.in_constructor=true;
 	data.viewport=NULL;
+	data.use_placeholder=false;
 }
 
 Node::~Node() {
@@ -2125,3 +2128,4 @@ Node::~Node() {
 }
 
 
+////////////////////////////////

+ 5 - 7
scene/main/node.h

@@ -75,9 +75,6 @@ private:
 
 		HashMap<NodePath,int> editable_instances;
 
-		Vector<StringName> instance_groups;
-		Vector<Connection> instance_connections;
-
 		Node *parent;
 		Node *owner;
 		Vector<Node*> children;	// list of children
@@ -111,6 +108,8 @@ private:
 
 		bool parent_owned;
 		bool in_constructor;
+		bool use_placeholder;
+
 
 	} data;
 	
@@ -241,6 +240,7 @@ public:
 	void set_editable_instance(Node* p_node,bool p_editable);
 	bool is_editable_instance(Node* p_node) const;
 
+
 	/* NOTIFICATIONS */
 	
 	void propagate_notification(int p_notification);
@@ -278,8 +278,8 @@ public:
 	void set_scene_inherited_state(const Ref<SceneState>& p_state);
 	Ref<SceneState> get_scene_inherited_state() const;
 
-	Vector<StringName> get_instance_groups() const;
-	Vector<Connection> get_instance_connections() const;
+	void set_scene_instance_load_placeholder(bool p_enable);
+	bool get_scene_instance_load_placeholder() const;
 
 	static Vector<Variant> make_binds(VARIANT_ARG_LIST);
 
@@ -322,6 +322,4 @@ public:
 typedef Set<Node*,Node::Comparator> NodeSet;
 
 
-
-
 #endif

+ 2 - 0
scene/register_scene_types.cpp

@@ -36,6 +36,7 @@
 #include "resources/default_theme/default_theme.h"
 #include "object_type_db.h"
 #include "scene/main/canvas_layer.h"
+#include "scene/main/instance_placeholder.h"
 #include "scene/main/viewport.h"
 #include "scene/gui/control.h"
 #include "scene/gui/texture_progress.h"
@@ -269,6 +270,7 @@ void register_scene_types() {
 	ObjectTypeDB::register_type<Object>();
 
 	ObjectTypeDB::register_type<Node>();
+	ObjectTypeDB::register_virtual_type<InstancePlaceholder>();
 
 	ObjectTypeDB::register_type<Viewport>();
 	ObjectTypeDB::register_virtual_type<RenderTargetTexture>();

+ 47 - 10
scene/resources/packed_scene.cpp

@@ -32,6 +32,7 @@
 #include "scene/3d/spatial.h"
 #include "scene/gui/control.h"
 #include "scene/2d/node_2d.h"
+#include "scene/main/instance_placeholder.h"
 
 #define PACK_VERSION 2
 
@@ -100,6 +101,7 @@ Node *SceneState::instance(bool p_gen_edit_state) const {
 
 		if (i==0 && base_scene_idx>=0) {
 			//scene inheritance on root node
+			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);
@@ -110,12 +112,32 @@ Node *SceneState::instance(bool p_gen_edit_state) const {
 
 		} else if (n.instance>=0) {
 			//instance a scene into this node
-			Ref<PackedScene> sdata = props[ n.instance ];
-			ERR_FAIL_COND_V( !sdata.is_valid(), NULL);
-			node = sdata->instance(p_gen_edit_state);
-			ERR_FAIL_COND_V(!node,NULL);
+			print_line("instance");
+			if (n.instance&FLAG_INSTANCE_IS_PLACEHOLDER) {
+
+				String path = props[n.instance&FLAG_MASK];
+				if (disable_placeholders) {
+
+					Ref<PackedScene> sdata = ResourceLoader::load(path,"PackedScene");
+					ERR_FAIL_COND_V( !sdata.is_valid(), NULL);
+					node = sdata->instance(p_gen_edit_state);
+					ERR_FAIL_COND_V(!node,NULL);
+				} else {
+					InstancePlaceholder *ip = memnew( InstancePlaceholder );
+					ip->set_path(path);
+					node=ip;
+				}
+				node->set_scene_instance_load_placeholder(true);
+			} else {
+				Ref<PackedScene> sdata = props[ n.instance&FLAG_MASK ];
+				ERR_FAIL_COND_V( !sdata.is_valid(), NULL);
+				node = sdata->instance(p_gen_edit_state);
+				ERR_FAIL_COND_V(!node,NULL);
+
+			}
 
 		} else if (n.type==TYPE_INSTANCED) {
+			//print_line("instanced");
 			//get the node from somewhere, it likely already exists from another instance
 			if (parent) {
 				node=parent->_get_child_by_name(snames[n.name]);
@@ -126,6 +148,7 @@ Node *SceneState::instance(bool p_gen_edit_state) const {
 #endif
 			}
 		} else if (ObjectTypeDB::is_type_enabled(snames[n.type])) {
+			print_line("created");
 			//node belongs to this scene and must be created
 			Object * obj = ObjectTypeDB::instance(snames[ n.type ]);
 			if (!obj || !obj->cast_to<Node>()) {
@@ -339,13 +362,20 @@ Error SceneState::_parse_node(Node *p_owner,Node *p_node,int p_parent_idx, Map<S
 				}
 
 				if (p_node->get_filename()!=String() && p_node->get_owner()==p_owner && instanced_by_owner) {
-					//must instance ourselves
-					Ref<PackedScene> instance = ResourceLoader::load(p_node->get_filename());
-					if (!instance.is_valid()) {
-						return ERR_CANT_OPEN;
-					}
 
-					nd.instance=_vm_get_variant(instance,variant_map);
+					if (p_node->get_scene_instance_load_placeholder()) {
+						//it's a placeholder, use the placeholder path
+						nd.instance=_vm_get_variant(p_node->get_filename(),variant_map);
+						nd.instance|=FLAG_INSTANCE_IS_PLACEHOLDER;
+					} else {
+						//must instance ourselves
+						Ref<PackedScene> instance = ResourceLoader::load(p_node->get_filename());
+						if (!instance.is_valid()) {
+							return ERR_CANT_OPEN;
+						}
+
+						nd.instance=_vm_get_variant(instance,variant_map);
+					}
 				}
 				n=NULL;
 			} else {
@@ -971,6 +1001,13 @@ bool SceneState::is_node_in_group(int p_node,const StringName& p_group) const {
 	return false;
 }
 
+bool SceneState::disable_placeholders=false;
+
+void SceneState::set_disable_placeholders(bool p_disable) {
+
+	disable_placeholders=p_disable;
+}
+
 bool SceneState::is_connection(int p_node,const StringName& p_signal,int p_to_node,const StringName& p_to_method) const {
 
 	ERR_FAIL_COND_V(p_node<0,false);

+ 4 - 5
scene/resources/packed_scene.h

@@ -45,13 +45,9 @@ class SceneState : public Reference {
 
 	int base_scene_idx;
 
-	//missing - instances
-	//missing groups
-	//missing - owner
-	//missing - override names and values
-
 	enum {
 		FLAG_ID_IS_PATH=(1<<30),
+		FLAG_INSTANCE_IS_PLACEHOLDER=(1<<30),
 		FLAG_MASK=(1<<24)-1,
 		NO_PARENT_SAVED=0x7FFFFFFF,
 		TYPE_INSTANCED=0x7FFFFFFF,
@@ -105,8 +101,11 @@ class SceneState : public Reference {
 
 	_FORCE_INLINE_ Ref<SceneState> _get_base_scene_state() const;
 
+	static bool disable_placeholders;
 public:
 
+	static void set_disable_placeholders(bool p_disable);
+
 	int find_node_by_path(const NodePath& p_node) const;
 	Variant get_property_value(int p_node,const StringName& p_property,bool &found) const;
 	bool is_node_in_group(int p_node,const StringName& p_group) const;

+ 1 - 0
tools/editor/editor_node.cpp

@@ -4417,6 +4417,7 @@ void EditorNode::_scene_tab_changed(int p_tab) {
 EditorNode::EditorNode() {
 
 	EditorHelp::generate_doc(); //before any editor classes are crated
+	SceneState::set_disable_placeholders(true);
 
 	InputDefault *id = Input::get_singleton()->cast_to<InputDefault>();
 

+ 31 - 1
tools/editor/scene_tree_editor.cpp

@@ -67,6 +67,26 @@ void SceneTreeEditor::_subscene_option(int p_idx) {
 			//node->set_instance_children_editable(editable);
 			EditorNode::get_singleton()->get_edited_scene()->set_editable_instance(node,editable);
 			instance_menu->set_item_checked(0,editable);
+			if (editable) {
+				node->set_scene_instance_load_placeholder(false);
+				instance_menu->set_item_checked(1,false);
+			}
+
+			_update_tree();
+
+		} break;
+		case SCENE_MENU_USE_PLACEHOLDER: {
+
+			bool placeholder = node->get_scene_instance_load_placeholder();
+			placeholder = !placeholder;
+
+			//node->set_instance_children_editable(editable);
+			if (placeholder) {
+				EditorNode::get_singleton()->get_edited_scene()->set_editable_instance(node,false);
+			}
+			node->set_scene_instance_load_placeholder(placeholder);
+			instance_menu->set_item_checked(0,false);
+			instance_menu->set_item_checked(1,placeholder);
 
 			_update_tree();
 
@@ -127,6 +147,15 @@ void SceneTreeEditor::_cell_button_pressed(Object *p_item,int p_column,int p_id)
 			else
 				instance_menu->set_item_checked(0,false);
 
+			if (n->get_owner()==get_scene_node()) {
+				instance_menu->set_item_checked(1,n->get_scene_instance_load_placeholder());
+				instance_menu->set_item_disabled(1,false);
+			} else {
+
+				instance_menu->set_item_checked(1,false);
+				instance_menu->set_item_disabled(1,true);
+			}
+
 			instance_menu->popup();
 			instance_node=n->get_instance_ID();
 		}
@@ -520,7 +549,7 @@ void SceneTreeEditor::_notification(int p_what) {
 
 		get_tree()->connect("tree_changed",this,"_tree_changed");
 		get_tree()->connect("node_removed",this,"_node_removed");
-		instance_menu->set_item_icon(2,get_icon("Load","EditorIcons"));
+		instance_menu->set_item_icon(3,get_icon("Load","EditorIcons"));
 		tree->connect("item_collapsed",this,"_cell_collapsed");
 		inheritance_menu->set_item_icon(2,get_icon("Load","EditorIcons"));
 		clear_inherit_confirm->connect("confirmed",this,"_subscene_option",varray(SCENE_MENU_CLEAR_INHERITANCE_CONFIRM));
@@ -826,6 +855,7 @@ SceneTreeEditor::SceneTreeEditor(bool p_label,bool p_can_rename, bool p_can_open
 
 	instance_menu = memnew( PopupMenu );
 	instance_menu->add_check_item("Editable Children",SCENE_MENU_EDITABLE_CHILDREN);
+	instance_menu->add_check_item("Load As Placeholder",SCENE_MENU_USE_PLACEHOLDER);
 	instance_menu->add_separator();
 	instance_menu->add_item("Open in Editor",SCENE_MENU_OPEN);
 	instance_menu->connect("item_pressed",this,"_subscene_option");

+ 1 - 0
tools/editor/scene_tree_editor.h

@@ -53,6 +53,7 @@ class SceneTreeEditor : public Control {
 
 	enum {
 		SCENE_MENU_EDITABLE_CHILDREN,
+		SCENE_MENU_USE_PLACEHOLDER,
 		SCENE_MENU_OPEN,
 		SCENE_MENU_CLEAR_INHERITANCE,
 		SCENE_MENU_OPEN_INHERITED,