Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix errors when re-importing 3D asset files #90531

Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
155 changes: 93 additions & 62 deletions editor/editor_node.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1067,7 +1067,7 @@ void EditorNode::_resources_reimported(const Vector<String> &p_resources) {
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) {
Expand Down Expand Up @@ -5719,8 +5719,14 @@ void EditorNode::reload_scene(const String &p_path) {

if (scene_idx == -1) {
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.
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;
}
Expand Down Expand Up @@ -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) {
int original_edited_scene_idx = editor_data.get_edited_scene();
HashMap<int, List<Node *>> edited_scene_map;
Array replaced_nodes;

Expand Down Expand Up @@ -5801,14 +5806,34 @@ void EditorNode::reload_instances_with_path_in_edited_scenes(const String &p_ins
HashMap<String, Ref<PackedScene>> local_scene_cache;
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) {
// Set the current scene.
int current_scene_idx = edited_scene_map_elem.key;
editor_data.set_edited_scene(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?).
EditorUndoRedoManager::get_singleton()->clear_history();
// Make sure the node is in the tree so that editor_selection can add node smoothly.
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
editor_data.is_scene_changed(current_scene_idx);
Expand All @@ -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);

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.
// For additional nodes which are part of the current scene, they get added to the addition table.
HashMap<NodePath, ModificationNodeEntry> modification_table;
Expand Down Expand Up @@ -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);
}

// 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.
instantiated_node->set_scene_instance_state(Ref<SceneState>());

Expand All @@ -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());

// Is this replacing the edited root node?
String original_node_file_path = original_node->get_scene_file_path();

if (current_edited_scene == original_node) {
instantiated_node->set_scene_instance_state(original_node->get_scene_instance_state());
Expand All @@ -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_file_path(String());
}
editor_data.set_edited_scene_root(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.
Expand Down Expand Up @@ -6046,19 +6063,33 @@ 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.
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.
// To inform anything that depends on them that they should update as appropriate.
_notify_nodes_scene_reimported(this, replaced_nodes);

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;
Expand Down
Loading