|
@@ -550,6 +550,10 @@ bool SceneTree::process(double p_time) {
|
|
#endif // _3D_DISABLED
|
|
#endif // _3D_DISABLED
|
|
#endif // TOOLS_ENABLED
|
|
#endif // TOOLS_ENABLED
|
|
|
|
|
|
|
|
+ if (unlikely(pending_new_scene)) {
|
|
|
|
+ _flush_scene_change();
|
|
|
|
+ }
|
|
|
|
+
|
|
return _quit;
|
|
return _quit;
|
|
}
|
|
}
|
|
|
|
|
|
@@ -1378,27 +1382,16 @@ Node *SceneTree::get_current_scene() const {
|
|
return current_scene;
|
|
return current_scene;
|
|
}
|
|
}
|
|
|
|
|
|
-void SceneTree::_change_scene(Node *p_to) {
|
|
|
|
- ERR_FAIL_COND_MSG(!Thread::is_main_thread(), "Changing scene can only be done from the main thread.");
|
|
|
|
- if (current_scene) {
|
|
|
|
- memdelete(current_scene);
|
|
|
|
- current_scene = nullptr;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- // If we're quitting, abort.
|
|
|
|
- if (unlikely(_quit)) {
|
|
|
|
- if (p_to) { // Prevent memory leak.
|
|
|
|
- memdelete(p_to);
|
|
|
|
- }
|
|
|
|
- return;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- if (p_to) {
|
|
|
|
- current_scene = p_to;
|
|
|
|
- root->add_child(p_to);
|
|
|
|
- // Update display for cursor instantly.
|
|
|
|
- root->update_mouse_cursor_state();
|
|
|
|
|
|
+void SceneTree::_flush_scene_change() {
|
|
|
|
+ if (prev_scene) {
|
|
|
|
+ memdelete(prev_scene);
|
|
|
|
+ prev_scene = nullptr;
|
|
}
|
|
}
|
|
|
|
+ current_scene = pending_new_scene;
|
|
|
|
+ root->add_child(pending_new_scene);
|
|
|
|
+ pending_new_scene = nullptr;
|
|
|
|
+ // Update display for cursor instantly.
|
|
|
|
+ root->update_mouse_cursor_state();
|
|
}
|
|
}
|
|
|
|
|
|
Error SceneTree::change_scene_to_file(const String &p_path) {
|
|
Error SceneTree::change_scene_to_file(const String &p_path) {
|
|
@@ -1417,7 +1410,22 @@ Error SceneTree::change_scene_to_packed(const Ref<PackedScene> &p_scene) {
|
|
Node *new_scene = p_scene->instantiate();
|
|
Node *new_scene = p_scene->instantiate();
|
|
ERR_FAIL_NULL_V(new_scene, ERR_CANT_CREATE);
|
|
ERR_FAIL_NULL_V(new_scene, ERR_CANT_CREATE);
|
|
|
|
|
|
- call_deferred(SNAME("_change_scene"), new_scene);
|
|
|
|
|
|
+ // If called again while a change is pending.
|
|
|
|
+ if (pending_new_scene) {
|
|
|
|
+ queue_delete(pending_new_scene);
|
|
|
|
+ pending_new_scene = nullptr;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ prev_scene = current_scene;
|
|
|
|
+
|
|
|
|
+ if (current_scene) {
|
|
|
|
+ // Let as many side effects as possible happen or be queued now,
|
|
|
|
+ // so they are run before the scene is actually deleted.
|
|
|
|
+ root->remove_child(current_scene);
|
|
|
|
+ }
|
|
|
|
+ DEV_ASSERT(!current_scene);
|
|
|
|
+
|
|
|
|
+ pending_new_scene = new_scene;
|
|
return OK;
|
|
return OK;
|
|
}
|
|
}
|
|
|
|
|
|
@@ -1595,8 +1603,6 @@ void SceneTree::_bind_methods() {
|
|
ClassDB::bind_method(D_METHOD("reload_current_scene"), &SceneTree::reload_current_scene);
|
|
ClassDB::bind_method(D_METHOD("reload_current_scene"), &SceneTree::reload_current_scene);
|
|
ClassDB::bind_method(D_METHOD("unload_current_scene"), &SceneTree::unload_current_scene);
|
|
ClassDB::bind_method(D_METHOD("unload_current_scene"), &SceneTree::unload_current_scene);
|
|
|
|
|
|
- ClassDB::bind_method(D_METHOD("_change_scene"), &SceneTree::_change_scene);
|
|
|
|
-
|
|
|
|
ClassDB::bind_method(D_METHOD("set_multiplayer", "multiplayer", "root_path"), &SceneTree::set_multiplayer, DEFVAL(NodePath()));
|
|
ClassDB::bind_method(D_METHOD("set_multiplayer", "multiplayer", "root_path"), &SceneTree::set_multiplayer, DEFVAL(NodePath()));
|
|
ClassDB::bind_method(D_METHOD("get_multiplayer", "for_path"), &SceneTree::get_multiplayer, DEFVAL(NodePath()));
|
|
ClassDB::bind_method(D_METHOD("get_multiplayer", "for_path"), &SceneTree::get_multiplayer, DEFVAL(NodePath()));
|
|
ClassDB::bind_method(D_METHOD("set_multiplayer_poll_enabled", "enabled"), &SceneTree::set_multiplayer_poll_enabled);
|
|
ClassDB::bind_method(D_METHOD("set_multiplayer_poll_enabled", "enabled"), &SceneTree::set_multiplayer_poll_enabled);
|
|
@@ -1835,6 +1841,14 @@ SceneTree::SceneTree() {
|
|
}
|
|
}
|
|
|
|
|
|
SceneTree::~SceneTree() {
|
|
SceneTree::~SceneTree() {
|
|
|
|
+ if (prev_scene) {
|
|
|
|
+ memdelete(prev_scene);
|
|
|
|
+ prev_scene = nullptr;
|
|
|
|
+ }
|
|
|
|
+ if (pending_new_scene) {
|
|
|
|
+ memdelete(pending_new_scene);
|
|
|
|
+ pending_new_scene = nullptr;
|
|
|
|
+ }
|
|
if (root) {
|
|
if (root) {
|
|
root->_set_tree(nullptr);
|
|
root->_set_tree(nullptr);
|
|
root->_propagate_after_exit_tree();
|
|
root->_propagate_after_exit_tree();
|