Merge pull request #90531 from Rindbee/fix-reload_instances_with_path_in_edited_scenes-in-EditorNode
Fix errors when re-importing 3D asset files
This commit is contained in:
commit
d9609ff1b0
1 changed files with 93 additions and 62 deletions
|
@ -1067,7 +1067,7 @@ void EditorNode::_resources_reimported(const Vector<String> &p_resources) {
|
||||||
reload_instances_with_path_in_edited_scenes(E);
|
reload_instances_with_path_in_edited_scenes(E);
|
||||||
}
|
}
|
||||||
|
|
||||||
scene_tabs->set_current_tab(current_tab);
|
_set_current_scene_nocheck(current_tab);
|
||||||
}
|
}
|
||||||
|
|
||||||
void EditorNode::_sources_changed(bool p_exist) {
|
void EditorNode::_sources_changed(bool p_exist) {
|
||||||
|
@ -5719,8 +5719,14 @@ void EditorNode::reload_scene(const String &p_path) {
|
||||||
|
|
||||||
if (scene_idx == -1) {
|
if (scene_idx == -1) {
|
||||||
if (get_edited_scene()) {
|
if (get_edited_scene()) {
|
||||||
|
int current_history_id = editor_data.get_current_edited_scene_history_id();
|
||||||
|
bool is_unsaved = EditorUndoRedoManager::get_singleton()->is_history_unsaved(current_history_id);
|
||||||
|
|
||||||
// Scene is not open, so at it might be instantiated. We'll refresh the whole scene later.
|
// Scene is not open, so at it might be instantiated. We'll refresh the whole scene later.
|
||||||
EditorUndoRedoManager::get_singleton()->clear_history(false, editor_data.get_current_edited_scene_history_id());
|
EditorUndoRedoManager::get_singleton()->clear_history(false, current_history_id);
|
||||||
|
if (is_unsaved) {
|
||||||
|
EditorUndoRedoManager::get_singleton()->set_history_as_unsaved(current_history_id);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -5770,7 +5776,6 @@ void EditorNode::find_all_instances_inheriting_path_in_node(Node *p_root, Node *
|
||||||
}
|
}
|
||||||
|
|
||||||
void EditorNode::reload_instances_with_path_in_edited_scenes(const String &p_instance_path) {
|
void EditorNode::reload_instances_with_path_in_edited_scenes(const String &p_instance_path) {
|
||||||
int original_edited_scene_idx = editor_data.get_edited_scene();
|
|
||||||
HashMap<int, List<Node *>> edited_scene_map;
|
HashMap<int, List<Node *>> edited_scene_map;
|
||||||
Array replaced_nodes;
|
Array replaced_nodes;
|
||||||
|
|
||||||
|
@ -5801,14 +5806,34 @@ void EditorNode::reload_instances_with_path_in_edited_scenes(const String &p_ins
|
||||||
HashMap<String, Ref<PackedScene>> local_scene_cache;
|
HashMap<String, Ref<PackedScene>> local_scene_cache;
|
||||||
local_scene_cache[p_instance_path] = instance_scene_packed_scene;
|
local_scene_cache[p_instance_path] = instance_scene_packed_scene;
|
||||||
|
|
||||||
|
// Save the current scene state/selection in case of lost.
|
||||||
|
Dictionary editor_state = _get_main_scene_state();
|
||||||
|
editor_data.save_edited_scene_state(editor_selection, &editor_history, editor_state);
|
||||||
|
editor_selection->clear();
|
||||||
|
|
||||||
|
int original_edited_scene_idx = editor_data.get_edited_scene();
|
||||||
|
Node *original_edited_scene_root = editor_data.get_edited_scene_root();
|
||||||
|
|
||||||
|
// Prevent scene roots with the same name from being in the tree at the same time.
|
||||||
|
scene_root->remove_child(original_edited_scene_root);
|
||||||
|
|
||||||
for (const KeyValue<int, List<Node *>> &edited_scene_map_elem : edited_scene_map) {
|
for (const KeyValue<int, List<Node *>> &edited_scene_map_elem : edited_scene_map) {
|
||||||
// Set the current scene.
|
// Set the current scene.
|
||||||
int current_scene_idx = edited_scene_map_elem.key;
|
int current_scene_idx = edited_scene_map_elem.key;
|
||||||
editor_data.set_edited_scene(current_scene_idx);
|
editor_data.set_edited_scene(current_scene_idx);
|
||||||
Node *current_edited_scene = editor_data.get_edited_scene_root(current_scene_idx);
|
Node *current_edited_scene = editor_data.get_edited_scene_root(current_scene_idx);
|
||||||
|
|
||||||
// Clear the history for this tab (should we allow history to be retained?).
|
// Make sure the node is in the tree so that editor_selection can add node smoothly.
|
||||||
EditorUndoRedoManager::get_singleton()->clear_history();
|
scene_root->add_child(current_edited_scene);
|
||||||
|
|
||||||
|
// Restore the state so that the selection can be updated.
|
||||||
|
editor_state = editor_data.restore_edited_scene_state(editor_selection, &editor_history);
|
||||||
|
|
||||||
|
int current_history_id = editor_data.get_current_edited_scene_history_id();
|
||||||
|
bool is_unsaved = EditorUndoRedoManager::get_singleton()->is_history_unsaved(current_history_id);
|
||||||
|
|
||||||
|
// Clear the history for this affected tab.
|
||||||
|
EditorUndoRedoManager::get_singleton()->clear_history(false, current_history_id);
|
||||||
|
|
||||||
// Update the version
|
// Update the version
|
||||||
editor_data.is_scene_changed(current_scene_idx);
|
editor_data.is_scene_changed(current_scene_idx);
|
||||||
|
@ -5818,6 +5843,52 @@ void EditorNode::reload_instances_with_path_in_edited_scenes(const String &p_ins
|
||||||
update_node_reference_modification_table_for_node(current_edited_scene, current_edited_scene, edited_scene_map_elem.value, edited_scene_global_modification_table);
|
update_node_reference_modification_table_for_node(current_edited_scene, current_edited_scene, edited_scene_map_elem.value, edited_scene_global_modification_table);
|
||||||
|
|
||||||
for (Node *original_node : edited_scene_map_elem.value) {
|
for (Node *original_node : edited_scene_map_elem.value) {
|
||||||
|
String original_node_file_path = original_node->get_scene_file_path();
|
||||||
|
|
||||||
|
// Load a replacement scene for the node.
|
||||||
|
Ref<PackedScene> current_packed_scene;
|
||||||
|
if (original_node_file_path == p_instance_path) {
|
||||||
|
// If the node file name directly matches the scene we're replacing,
|
||||||
|
// just load it since we already cached it.
|
||||||
|
current_packed_scene = instance_scene_packed_scene;
|
||||||
|
} else {
|
||||||
|
// Otherwise, check the inheritance chain, reloading and caching any scenes
|
||||||
|
// we require along the way.
|
||||||
|
List<String> required_load_paths;
|
||||||
|
|
||||||
|
// Do we need to check if the paths are empty?
|
||||||
|
if (!original_node_file_path.is_empty()) {
|
||||||
|
required_load_paths.push_front(original_node_file_path);
|
||||||
|
}
|
||||||
|
Ref<SceneState> inherited_state = original_node->get_scene_inherited_state();
|
||||||
|
while (inherited_state.is_valid()) {
|
||||||
|
String inherited_path = inherited_state->get_path();
|
||||||
|
// Do we need to check if the paths are empty?
|
||||||
|
if (!inherited_path.is_empty()) {
|
||||||
|
required_load_paths.push_front(inherited_path);
|
||||||
|
}
|
||||||
|
inherited_state = inherited_state->get_base_scene_state();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Ensure the inheritance chain is loaded in the correct order so that cache can
|
||||||
|
// be properly updated.
|
||||||
|
for (String path : required_load_paths) {
|
||||||
|
if (!local_scene_cache.find(path)) {
|
||||||
|
current_packed_scene = ResourceLoader::load(path, "", ResourceFormatLoader::CACHE_MODE_REPLACE_DEEP, &err);
|
||||||
|
local_scene_cache[path] = current_packed_scene;
|
||||||
|
} else {
|
||||||
|
current_packed_scene = local_scene_cache[path];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ERR_FAIL_COND(current_packed_scene.is_null());
|
||||||
|
|
||||||
|
// Instantiate early so that caches cleared on load in SceneState can be rebuilt early.
|
||||||
|
Node *instantiated_node = current_packed_scene->instantiate(PackedScene::GEN_EDIT_STATE_INSTANCE);
|
||||||
|
|
||||||
|
ERR_FAIL_NULL(instantiated_node);
|
||||||
|
|
||||||
// Walk the tree for the current node and extract relevant diff data, storing it in the modification table.
|
// Walk the tree for the current node and extract relevant diff data, storing it in the modification table.
|
||||||
// For additional nodes which are part of the current scene, they get added to the addition table.
|
// For additional nodes which are part of the current scene, they get added to the addition table.
|
||||||
HashMap<NodePath, ModificationNodeEntry> modification_table;
|
HashMap<NodePath, ModificationNodeEntry> modification_table;
|
||||||
|
@ -5875,53 +5946,6 @@ void EditorNode::reload_instances_with_path_in_edited_scenes(const String &p_ins
|
||||||
is_editable = owner->is_editable_instance(original_node);
|
is_editable = owner->is_editable_instance(original_node);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Load a replacement scene for the node.
|
|
||||||
Ref<PackedScene> current_packed_scene;
|
|
||||||
if (original_node->get_scene_file_path() == p_instance_path) {
|
|
||||||
// If the node file name directly matches the scene we're replacing,
|
|
||||||
// just load it since we already cached it.
|
|
||||||
current_packed_scene = instance_scene_packed_scene;
|
|
||||||
} else {
|
|
||||||
// Otherwise, check the inheritance chain, reloading and caching any scenes
|
|
||||||
// we require along the way.
|
|
||||||
List<String> required_load_paths;
|
|
||||||
String scene_path = original_node->get_scene_file_path();
|
|
||||||
// Do we need to check if the paths are empty?
|
|
||||||
if (!scene_path.is_empty()) {
|
|
||||||
required_load_paths.push_front(scene_path);
|
|
||||||
}
|
|
||||||
Ref<SceneState> inherited_state = original_node->get_scene_inherited_state();
|
|
||||||
while (inherited_state.is_valid()) {
|
|
||||||
String inherited_path = inherited_state->get_path();
|
|
||||||
// Do we need to check if the paths are empty?
|
|
||||||
if (!inherited_path.is_empty()) {
|
|
||||||
required_load_paths.push_front(inherited_path);
|
|
||||||
}
|
|
||||||
inherited_state = inherited_state->get_base_scene_state();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Ensure the inheritance chain is loaded in the correct order so that cache can
|
|
||||||
// be properly updated.
|
|
||||||
for (String path : required_load_paths) {
|
|
||||||
if (!local_scene_cache.find(path)) {
|
|
||||||
current_packed_scene = ResourceLoader::load(path, "", ResourceFormatLoader::CACHE_MODE_REPLACE_DEEP, &err);
|
|
||||||
local_scene_cache[path] = current_packed_scene;
|
|
||||||
} else {
|
|
||||||
current_packed_scene = local_scene_cache[path];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ERR_FAIL_COND(current_packed_scene.is_null());
|
|
||||||
|
|
||||||
// Instantiate the node.
|
|
||||||
Node *instantiated_node = nullptr;
|
|
||||||
if (current_packed_scene.is_valid()) {
|
|
||||||
instantiated_node = current_packed_scene->instantiate(PackedScene::GEN_EDIT_STATE_INSTANCE);
|
|
||||||
}
|
|
||||||
|
|
||||||
ERR_FAIL_NULL(instantiated_node);
|
|
||||||
|
|
||||||
// For clear instance state for path recaching.
|
// For clear instance state for path recaching.
|
||||||
instantiated_node->set_scene_instance_state(Ref<SceneState>());
|
instantiated_node->set_scene_instance_state(Ref<SceneState>());
|
||||||
|
|
||||||
|
@ -5932,7 +5956,6 @@ void EditorNode::reload_instances_with_path_in_edited_scenes(const String &p_ins
|
||||||
instantiated_node->set_name(original_node->get_name());
|
instantiated_node->set_name(original_node->get_name());
|
||||||
|
|
||||||
// Is this replacing the edited root node?
|
// Is this replacing the edited root node?
|
||||||
String original_node_file_path = original_node->get_scene_file_path();
|
|
||||||
|
|
||||||
if (current_edited_scene == original_node) {
|
if (current_edited_scene == original_node) {
|
||||||
instantiated_node->set_scene_instance_state(original_node->get_scene_instance_state());
|
instantiated_node->set_scene_instance_state(original_node->get_scene_instance_state());
|
||||||
|
@ -5943,13 +5966,7 @@ void EditorNode::reload_instances_with_path_in_edited_scenes(const String &p_ins
|
||||||
instantiated_node->set_scene_inherited_state(state);
|
instantiated_node->set_scene_inherited_state(state);
|
||||||
instantiated_node->set_scene_file_path(String());
|
instantiated_node->set_scene_file_path(String());
|
||||||
}
|
}
|
||||||
editor_data.set_edited_scene_root(instantiated_node);
|
|
||||||
current_edited_scene = instantiated_node;
|
current_edited_scene = instantiated_node;
|
||||||
|
|
||||||
if (original_node->is_inside_tree()) {
|
|
||||||
SceneTreeDock::get_singleton()->set_edited_scene(current_edited_scene);
|
|
||||||
original_node->get_tree()->set_edited_scene_root(instantiated_node);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Replace the original node with the instantiated version.
|
// Replace the original node with the instantiated version.
|
||||||
|
@ -6046,8 +6063,18 @@ void EditorNode::reload_instances_with_path_in_edited_scenes(const String &p_ins
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (is_unsaved) {
|
||||||
|
EditorUndoRedoManager::get_singleton()->set_history_as_unsaved(current_history_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Save the current handled scene state.
|
||||||
|
editor_data.save_edited_scene_state(editor_selection, &editor_history, editor_state);
|
||||||
|
editor_selection->clear();
|
||||||
|
|
||||||
// Cleanup the history of the changes.
|
// Cleanup the history of the changes.
|
||||||
editor_history.cleanup_history();
|
editor_history.cleanup_history();
|
||||||
|
|
||||||
|
scene_root->remove_child(current_edited_scene);
|
||||||
}
|
}
|
||||||
|
|
||||||
// For the whole editor, call the _notify_nodes_scene_reimported with a list of replaced nodes.
|
// For the whole editor, call the _notify_nodes_scene_reimported with a list of replaced nodes.
|
||||||
|
@ -6055,10 +6082,14 @@ void EditorNode::reload_instances_with_path_in_edited_scenes(const String &p_ins
|
||||||
_notify_nodes_scene_reimported(this, replaced_nodes);
|
_notify_nodes_scene_reimported(this, replaced_nodes);
|
||||||
|
|
||||||
edited_scene_map.clear();
|
edited_scene_map.clear();
|
||||||
}
|
|
||||||
editor_data.set_edited_scene(original_edited_scene_idx);
|
|
||||||
|
|
||||||
_edit_current();
|
editor_data.set_edited_scene(original_edited_scene_idx);
|
||||||
|
|
||||||
|
original_edited_scene_root = editor_data.get_edited_scene_root();
|
||||||
|
scene_root->add_child(original_edited_scene_root);
|
||||||
|
|
||||||
|
editor_data.restore_edited_scene_state(editor_selection, &editor_history);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int EditorNode::plugin_init_callback_count = 0;
|
int EditorNode::plugin_init_callback_count = 0;
|
||||||
|
|
Loading…
Add table
Reference in a new issue