浏览代码

added a built-in scene changer API, closes #1928

Juan Linietsky 10 年之前
父节点
当前提交
b6b346e8ae

+ 4 - 0
demos/misc/scene_changer/engine.cfg

@@ -0,0 +1,4 @@
+[application]
+
+name="Scene Changer"
+main_scene="res://scene_a.scn"

+ 17 - 0
demos/misc/scene_changer/scene_a.gd

@@ -0,0 +1,17 @@
+
+extends Panel
+
+# member variables here, example:
+# var a=2
+# var b="textvar"
+
+func _ready():
+	# Initalization here
+	pass
+
+
+
+
+func _on_goto_scene_pressed():
+	get_tree().change_scene("res://scene_b.scn")
+	pass # replace with function body

二进制
demos/misc/scene_changer/scene_a.scn


+ 17 - 0
demos/misc/scene_changer/scene_b.gd

@@ -0,0 +1,17 @@
+
+extends Panel
+
+# member variables here, example:
+# var a=2
+# var b="textvar"
+
+func _ready():
+	# Initalization here
+	pass
+
+
+
+
+func _on_goto_scene_pressed():
+	get_tree().change_scene("res://scene_a.scn")
+	pass # replace with function body

二进制
demos/misc/scene_changer/scene_b.scn


+ 2 - 1
main/main.cpp

@@ -1248,7 +1248,8 @@ bool Main::start() {
 
 
 				ERR_EXPLAIN("Failed loading scene: "+local_game_path);
 				ERR_EXPLAIN("Failed loading scene: "+local_game_path);
 				ERR_FAIL_COND_V(!scene,false)
 				ERR_FAIL_COND_V(!scene,false)
-				sml->get_root()->add_child(scene);
+				//sml->get_root()->add_child(scene);
+				sml->add_current_scene(scene);
 
 
 				String iconpath = GLOBAL_DEF("application/icon","Variant()""");
 				String iconpath = GLOBAL_DEF("application/icon","Variant()""");
 				if (iconpath!="") {
 				if (iconpath!="") {

+ 74 - 2
scene/main/scene_main_loop.cpp

@@ -41,7 +41,7 @@
 #include "scene/scene_string_names.h"
 #include "scene/scene_string_names.h"
 #include "io/resource_loader.h"
 #include "io/resource_loader.h"
 #include "viewport.h"
 #include "viewport.h"
-
+#include "scene/resources/packed_scene.h"
 
 
 void SceneTree::tree_changed() {
 void SceneTree::tree_changed() {
 
 
@@ -51,6 +51,9 @@ void SceneTree::tree_changed() {
 
 
 void SceneTree::node_removed(Node *p_node) {
 void SceneTree::node_removed(Node *p_node) {
 
 
+	if (current_scene==p_node) {
+		current_scene=NULL;
+	}
 	emit_signal(node_removed_name,p_node);
 	emit_signal(node_removed_name,p_node);
 	if (call_lock>0)
 	if (call_lock>0)
 		call_skip.insert(p_node);
 		call_skip.insert(p_node);
@@ -984,6 +987,63 @@ Node *SceneTree::get_edited_scene_root() const {
 }
 }
 #endif
 #endif
 
 
+void SceneTree::set_current_scene(Node* p_scene) {
+
+	ERR_FAIL_COND(p_scene && p_scene->get_parent()!=root);
+	current_scene=p_scene;
+}
+
+Node* SceneTree::get_current_scene() const{
+
+	return current_scene;
+}
+
+void SceneTree::_change_scene(Node* p_to) {
+
+	if (current_scene) {
+		memdelete( current_scene );
+		current_scene=NULL;
+	}
+
+	if (p_to) {
+		current_scene=p_to;
+		root->add_child(p_to);
+	}
+}
+
+Error SceneTree::change_scene(const String& p_path){
+
+	Ref<PackedScene> new_scene = ResourceLoader::load(p_path);
+	if (new_scene.is_null())
+		return ERR_CANT_OPEN;
+
+	return change_scene_to(new_scene);
+
+}
+Error SceneTree::change_scene_to(const Ref<PackedScene>& p_scene){
+
+	Node *new_scene=NULL;
+	if (p_scene.is_valid()) {
+		new_scene = p_scene->instance();
+		ERR_FAIL_COND_V(!new_scene,ERR_CANT_CREATE);
+	}
+
+	call_deferred("_change_scene",new_scene);
+	return OK;
+
+}
+Error SceneTree::reload_current_scene() {
+
+	ERR_FAIL_COND_V(!current_scene,ERR_UNCONFIGURED);
+	String fname = current_scene->get_filename();
+	return change_scene(fname);
+}
+
+void SceneTree::add_current_scene(Node * p_current) {
+
+	current_scene=p_current;
+	root->add_child(p_current);
+}
 
 
 void SceneTree::_bind_methods() {
 void SceneTree::_bind_methods() {
 
 
@@ -1016,10 +1076,11 @@ void SceneTree::_bind_methods() {
 
 
 	ObjectTypeDB::bind_method(_MD("set_screen_stretch","mode","aspect","minsize"),&SceneTree::set_screen_stretch);
 	ObjectTypeDB::bind_method(_MD("set_screen_stretch","mode","aspect","minsize"),&SceneTree::set_screen_stretch);
 
 
-
 	ObjectTypeDB::bind_method(_MD("queue_delete","obj"),&SceneTree::queue_delete);
 	ObjectTypeDB::bind_method(_MD("queue_delete","obj"),&SceneTree::queue_delete);
 
 
 
 
+
+
 	MethodInfo mi;
 	MethodInfo mi;
 	mi.name="call_group";
 	mi.name="call_group";
 	mi.arguments.push_back( PropertyInfo( Variant::INT, "flags"));
 	mi.arguments.push_back( PropertyInfo( Variant::INT, "flags"));
@@ -1033,6 +1094,16 @@ void SceneTree::_bind_methods() {
 
 
 	ObjectTypeDB::bind_native_method(METHOD_FLAGS_DEFAULT,"call_group",&SceneTree::_call_group,mi,defargs);
 	ObjectTypeDB::bind_native_method(METHOD_FLAGS_DEFAULT,"call_group",&SceneTree::_call_group,mi,defargs);
 
 
+	ObjectTypeDB::bind_method(_MD("set_current_scene","child_node"),&SceneTree::set_current_scene);
+	ObjectTypeDB::bind_method(_MD("get_current_scene"),&SceneTree::get_current_scene);
+
+	ObjectTypeDB::bind_method(_MD("change_scene","path"),&SceneTree::change_scene);
+	ObjectTypeDB::bind_method(_MD("change_scene_to","packed_scene"),&SceneTree::change_scene_to);
+
+	ObjectTypeDB::bind_method(_MD("reload_current_scene"),&SceneTree::reload_current_scene);
+
+	ObjectTypeDB::bind_method(_MD("_change_scene"),&SceneTree::_change_scene);
+
 	ADD_SIGNAL( MethodInfo("tree_changed") );
 	ADD_SIGNAL( MethodInfo("tree_changed") );
 	ADD_SIGNAL( MethodInfo("node_removed",PropertyInfo( Variant::OBJECT, "node") ) );
 	ADD_SIGNAL( MethodInfo("node_removed",PropertyInfo( Variant::OBJECT, "node") ) );
 	ADD_SIGNAL( MethodInfo("screen_resized") );
 	ADD_SIGNAL( MethodInfo("screen_resized") );
@@ -1077,6 +1148,7 @@ SceneTree::SceneTree() {
 	//root->set_world_2d( Ref<World2D>( memnew( World2D )));
 	//root->set_world_2d( Ref<World2D>( memnew( World2D )));
 	root->set_as_audio_listener(true);
 	root->set_as_audio_listener(true);
 	root->set_as_audio_listener_2d(true);
 	root->set_as_audio_listener_2d(true);
+	current_scene=NULL;
 
 
 	stretch_mode=STRETCH_MODE_DISABLED;
 	stretch_mode=STRETCH_MODE_DISABLED;
 	stretch_aspect=STRETCH_ASPECT_IGNORE;
 	stretch_aspect=STRETCH_ASPECT_IGNORE;

+ 14 - 1
scene/main/scene_main_loop.h

@@ -42,7 +42,7 @@
 
 
 
 
 class SceneTree;
 class SceneTree;
-
+class PackedScene;
 class Node;
 class Node;
 class Viewport;
 class Viewport;
 
 
@@ -136,7 +136,9 @@ private:
 
 
 	Array _get_nodes_in_group(const StringName& p_group);
 	Array _get_nodes_in_group(const StringName& p_group);
 
 
+	Node *current_scene;
 
 
+	void _change_scene(Node* p_to);
 	//void _call_group(uint32_t p_call_flags,const StringName& p_group,const StringName& p_function,const Variant& p_arg1,const Variant& p_arg2);
 	//void _call_group(uint32_t p_call_flags,const StringName& p_group,const StringName& p_function,const Variant& p_arg1,const Variant& p_arg2);
 
 
 friend class Node;
 friend class Node;
@@ -234,6 +236,17 @@ public:
 	Node *get_edited_scene_root() const;
 	Node *get_edited_scene_root() const;
 #endif
 #endif
 
 
+	void set_current_scene(Node* p_scene);
+	Node* get_current_scene() const;
+	Error change_scene(const String& p_path);
+	Error change_scene_to(const Ref<PackedScene>& p_scene);
+	Error reload_current_scene();
+
+	//used by Main::start, don't use otherwise
+	void add_current_scene(Node * p_current);
+
+
+
 	SceneTree();
 	SceneTree();
 	~SceneTree();
 	~SceneTree();