Fix performance issue reimport file reload scene

This commit is contained in:
Hilderin 2024-08-06 17:59:41 -04:00
parent eabeafd8c3
commit 7934e73d78
2 changed files with 432 additions and 413 deletions

View file

@ -3870,17 +3870,18 @@ void EditorNode::_set_current_scene_nocheck(int p_idx) {
changing_scene = true;
editor_data.save_edited_scene_state(editor_selection, &editor_history, _get_main_scene_state());
if (get_editor_data().get_edited_scene_root()) {
if (get_editor_data().get_edited_scene_root()->get_parent() == scene_root) {
scene_root->remove_child(get_editor_data().get_edited_scene_root());
}
}
Node *old_scene = get_editor_data().get_edited_scene_root();
editor_selection->clear();
editor_data.set_edited_scene(p_idx);
Node *new_scene = editor_data.get_edited_scene_root();
// Remove the scene only if it's a new scene, preventing performance issues when adding and removing scenes.
if (old_scene && new_scene != old_scene && old_scene->get_parent() == scene_root) {
scene_root->remove_child(old_scene);
}
if (Popup *p = Object::cast_to<Popup>(new_scene)) {
p->show();
}
@ -4154,25 +4155,48 @@ HashMap<StringName, Variant> EditorNode::get_modified_properties_for_node(Node *
p_node->get_property_list(&pinfo);
for (const PropertyInfo &E : pinfo) {
if (E.usage & PROPERTY_USAGE_STORAGE) {
bool node_reference = (E.type == Variant::OBJECT && E.hint == PROPERTY_HINT_NODE_TYPE);
if (p_node_references_only && !node_reference) {
continue;
}
bool is_valid_revert = false;
Variant revert_value = EditorPropertyRevert::get_property_revert_value(p_node, E.name, &is_valid_revert);
Variant current_value = p_node->get(E.name);
if (is_valid_revert) {
if (PropertyUtils::is_property_value_different(p_node, current_value, revert_value)) {
// If this property is a direct node reference, save a NodePath instead to prevent corrupted references.
if (E.type == Variant::OBJECT && E.hint == PROPERTY_HINT_NODE_TYPE) {
if (node_reference) {
Node *target_node = Object::cast_to<Node>(current_value);
if (target_node) {
modified_property_map[E.name] = p_node->get_path_to(target_node);
}
} else {
if (!p_node_references_only) {
modified_property_map[E.name] = current_value;
}
}
}
}
}
return modified_property_map;
}
HashMap<StringName, Variant> EditorNode::get_modified_properties_reference_to_nodes(Node *p_node, List<Node *> &p_nodes_referenced_by) {
HashMap<StringName, Variant> modified_property_map;
List<PropertyInfo> pinfo;
p_node->get_property_list(&pinfo);
for (const PropertyInfo &E : pinfo) {
if (E.usage & PROPERTY_USAGE_STORAGE) {
if (E.type != Variant::OBJECT || E.hint != PROPERTY_HINT_NODE_TYPE) {
continue;
}
Variant current_value = p_node->get(E.name);
Node *target_node = Object::cast_to<Node>(current_value);
if (target_node && p_nodes_referenced_by.find(target_node)) {
modified_property_map[E.name] = p_node->get_path_to(target_node);
}
}
}
return modified_property_map;
@ -4264,28 +4288,6 @@ void EditorNode::update_node_from_node_modification_entry(Node *p_node, Modifica
}
}
void EditorNode::update_node_reference_modification_table_for_node(
Node *p_root,
Node *p_node,
List<Node *> p_excluded_nodes,
HashMap<NodePath, ModificationNodeEntry> &p_modification_table) {
if (!p_excluded_nodes.find(p_node)) {
HashMap<StringName, Variant> modified_properties = get_modified_properties_for_node(p_node, false);
if (!modified_properties.is_empty()) {
ModificationNodeEntry modification_node_entry;
modification_node_entry.property_table = modified_properties;
p_modification_table[p_root->get_path_to(p_node)] = modification_node_entry;
}
for (int i = 0; i < p_node->get_child_count(); i++) {
Node *child = p_node->get_child(i);
update_node_reference_modification_table_for_node(p_root, child, p_excluded_nodes, p_modification_table);
}
}
}
bool EditorNode::is_additional_node_in_scene(Node *p_edited_scene, Node *p_reimported_root, Node *p_node) {
if (p_node == p_reimported_root) {
return false;
@ -4328,11 +4330,39 @@ bool EditorNode::is_additional_node_in_scene(Node *p_edited_scene, Node *p_reimp
void EditorNode::get_preload_scene_modification_table(
Node *p_edited_scene,
Node *p_reimported_root,
Node *p_node, HashMap<NodePath, ModificationNodeEntry> &p_modification_table) {
// Only take the nodes that are in the base imported scene. The additional nodes will be managed
// after the resources are reimported. It's not important to check which property has
// changed on nodes that will not be reimported because they are not part of the reimported scene.
if (!is_additional_node_in_scene(p_edited_scene, p_reimported_root, p_node)) {
Node *p_node, InstanceModificationsEntry &p_instance_modifications) {
if (is_additional_node_in_scene(p_edited_scene, p_reimported_root, p_node)) {
// Only save additional nodes which have an owner since this was causing issues transient ownerless nodes
// which get recreated upon scene tree entry.
// For now instead, assume all ownerless nodes are transient and will have to be recreated.
if (p_node->get_owner()) {
HashMap<StringName, Variant> modified_properties = get_modified_properties_for_node(p_node, true);
if (p_node->get_owner() == p_edited_scene) {
AdditiveNodeEntry new_additive_node_entry;
new_additive_node_entry.node = p_node;
new_additive_node_entry.parent = p_reimported_root->get_path_to(p_node->get_parent());
new_additive_node_entry.owner = p_node->get_owner();
new_additive_node_entry.index = p_node->get_index();
Node2D *node_2d = Object::cast_to<Node2D>(p_node);
if (node_2d) {
new_additive_node_entry.transform_2d = node_2d->get_transform();
}
Node3D *node_3d = Object::cast_to<Node3D>(p_node);
if (node_3d) {
new_additive_node_entry.transform_3d = node_3d->get_transform();
}
p_instance_modifications.addition_list.push_back(new_additive_node_entry);
}
if (!modified_properties.is_empty()) {
ModificationNodeEntry modification_node_entry;
modification_node_entry.property_table = modified_properties;
p_instance_modifications.modifications[p_reimported_root->get_path_to(p_node)] = modification_node_entry;
}
}
} else {
HashMap<StringName, Variant> modified_properties = get_modified_properties_for_node(p_node, false);
// Find all valid connections to other nodes.
@ -4391,58 +4421,42 @@ void EditorNode::get_preload_scene_modification_table(
modification_node_entry.connections_from = valid_connections_from;
modification_node_entry.groups = groups;
p_modification_table[p_reimported_root->get_path_to(p_node)] = modification_node_entry;
p_instance_modifications.modifications[p_reimported_root->get_path_to(p_node)] = modification_node_entry;
}
}
for (int i = 0; i < p_node->get_child_count(); i++) {
Node *child = p_node->get_child(i);
get_preload_scene_modification_table(p_edited_scene, p_reimported_root, child, p_modification_table);
get_preload_scene_modification_table(p_edited_scene, p_reimported_root, p_node->get_child(i), p_instance_modifications);
}
}
void EditorNode::update_reimported_diff_data_for_additional_nodes(
Node *p_edited_scene,
Node *p_reimported_root,
void EditorNode::get_preload_modifications_reference_to_nodes(
Node *p_root,
Node *p_node,
HashMap<NodePath, ModificationNodeEntry> &p_modification_table,
List<AdditiveNodeEntry> &p_addition_list) {
if (is_additional_node_in_scene(p_edited_scene, p_reimported_root, p_node)) {
// Only save additional nodes which have an owner since this was causing issues transient ownerless nodes
// which get recreated upon scene tree entry.
// For now instead, assume all ownerless nodes are transient and will have to be recreated.
if (p_node->get_owner()) {
HashMap<StringName, Variant> modified_properties = get_modified_properties_for_node(p_node, true);
if (p_node->get_owner() == p_edited_scene) {
AdditiveNodeEntry new_additive_node_entry;
new_additive_node_entry.node = p_node;
new_additive_node_entry.parent = p_reimported_root->get_path_to(p_node->get_parent());
new_additive_node_entry.owner = p_node->get_owner();
new_additive_node_entry.index = p_node->get_index();
List<Node *> &p_excluded_nodes,
List<Node *> &p_instance_list_with_children,
HashMap<NodePath, ModificationNodeEntry> &p_modification_table) {
if (!p_excluded_nodes.find(p_node)) {
HashMap<StringName, Variant> modified_properties = get_modified_properties_reference_to_nodes(p_node, p_instance_list_with_children);
Node2D *node_2d = Object::cast_to<Node2D>(p_node);
if (node_2d) {
new_additive_node_entry.transform_2d = node_2d->get_relative_transform_to_parent(node_2d->get_parent());
}
Node3D *node_3d = Object::cast_to<Node3D>(p_node);
if (node_3d) {
new_additive_node_entry.transform_3d = node_3d->get_relative_transform(node_3d->get_parent());
}
p_addition_list.push_back(new_additive_node_entry);
}
if (!modified_properties.is_empty()) {
ModificationNodeEntry modification_node_entry;
modification_node_entry.property_table = modified_properties;
p_modification_table[p_reimported_root->get_path_to(p_node)] = modification_node_entry;
p_modification_table[p_root->get_path_to(p_node)] = modification_node_entry;
}
for (int i = 0; i < p_node->get_child_count(); i++) {
get_preload_modifications_reference_to_nodes(p_root, p_node->get_child(i), p_excluded_nodes, p_instance_list_with_children, p_modification_table);
}
}
}
void EditorNode::get_children_nodes(Node *p_node, List<Node *> &p_nodes) {
for (int i = 0; i < p_node->get_child_count(); i++) {
Node *child = p_node->get_child(i);
update_reimported_diff_data_for_additional_nodes(p_edited_scene, p_reimported_root, child, p_modification_table, p_addition_list);
p_nodes.push_back(child);
get_children_nodes(child, p_nodes);
}
}
@ -4456,8 +4470,7 @@ void EditorNode::replace_history_reimported_nodes(Node *p_original_root_node, No
}
for (int i = 0; i < p_node->get_child_count(); i++) {
Node *child = p_node->get_child(i);
replace_history_reimported_nodes(p_original_root_node, p_new_root_node, child);
replace_history_reimported_nodes(p_original_root_node, p_new_root_node, p_node->get_child(i));
}
}
@ -5831,25 +5844,6 @@ void EditorNode::reload_scene(const String &p_path) {
scene_tabs->set_current_tab(current_tab);
}
void EditorNode::get_edited_scene_map(const String &p_instance_path, HashMap<int, List<Node *>> &p_edited_scene_map) {
// Walk through each opened scene to get a global list of all instances which match
// the current reimported scenes.
for (int i = 0; i < editor_data.get_edited_scene_count(); i++) {
if (editor_data.get_scene_path(i) == p_instance_path) {
continue;
}
Node *edited_scene_root = editor_data.get_edited_scene_root(i);
if (edited_scene_root) {
List<Node *> valid_nodes;
find_all_instances_inheriting_path_in_node(edited_scene_root, edited_scene_root, p_instance_path, valid_nodes);
if (valid_nodes.size() > 0) {
p_edited_scene_map[i] = valid_nodes;
}
}
}
}
void EditorNode::find_all_instances_inheriting_path_in_node(Node *p_root, Node *p_node, const String &p_instance_path, List<Node *> &p_instance_list) {
String scene_file_path = p_node->get_scene_file_path();
@ -5872,61 +5866,70 @@ void EditorNode::find_all_instances_inheriting_path_in_node(Node *p_root, Node *
}
for (int i = 0; i < p_node->get_child_count(); i++) {
Node *child = p_node->get_child(i);
find_all_instances_inheriting_path_in_node(p_root, child, p_instance_path, p_instance_list);
find_all_instances_inheriting_path_in_node(p_root, p_node->get_child(i), p_instance_path, p_instance_list);
}
}
void EditorNode::preload_reimporting_with_path_in_edited_scenes(const String &p_instance_path) {
HashMap<int, List<Node *>> edited_scene_map;
scenes_modification_table.clear();
get_edited_scene_map(p_instance_path, edited_scene_map);
if (edited_scene_map.size() > 0) {
scenes_modification_table.clear();
EditorProgress progress("preload_reimporting_scene", TTR("Preparing scenes for reload"), editor_data.get_edited_scene_count());
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);
// Walk through each opened scene to get a global list of all instances which match
// the current reimported scenes.
for (int current_scene_idx = 0; current_scene_idx < editor_data.get_edited_scene_count(); current_scene_idx++) {
progress.step(vformat(TTR("Analyzing scene %s"), editor_data.get_scene_title(current_scene_idx)), current_scene_idx);
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;
if (editor_data.get_scene_path(current_scene_idx) == p_instance_path) {
continue;
}
Node *edited_scene_root = editor_data.get_edited_scene_root(current_scene_idx);
if (edited_scene_root) {
List<Node *> instance_list;
find_all_instances_inheriting_path_in_node(edited_scene_root, edited_scene_root, p_instance_path, instance_list);
if (instance_list.size() > 0) {
SceneModificationsEntry scene_motifications;
editor_data.set_edited_scene(current_scene_idx);
Node *current_edited_scene = editor_data.get_edited_scene_root(current_scene_idx);
// Make sure the node is in the tree so that editor_selection can add node smoothly.
scene_root->add_child(current_edited_scene);
List<Node *> instance_list_with_children;
for (Node *original_node : instance_list) {
InstanceModificationsEntry instance_modifications;
for (Node *original_node : edited_scene_map_elem.value) {
// Fetching all the modified properties of the nodes reimported scene.
HashMap<NodePath, ModificationNodeEntry> modification_table;
get_preload_scene_modification_table(current_edited_scene, original_node, original_node, modification_table);
get_preload_scene_modification_table(edited_scene_root, original_node, original_node, instance_modifications);
if (modification_table.size() > 0) {
NodePath scene_path_to_node = current_edited_scene->get_path_to(original_node);
scenes_modification_table[current_scene_idx][scene_path_to_node] = modification_table;
}
instance_modifications.original_node = original_node;
scene_motifications.instance_list.push_back(instance_modifications);
instance_list_with_children.push_back(original_node);
get_children_nodes(original_node, instance_list_with_children);
}
scene_root->remove_child(current_edited_scene);
// Search the scene to find nodes that references the nodes will be recreated.
get_preload_modifications_reference_to_nodes(edited_scene_root, edited_scene_root, instance_list, instance_list_with_children, scene_motifications.other_instances_modifications);
scenes_modification_table[current_scene_idx] = scene_motifications;
}
}
}
editor_data.set_edited_scene(original_edited_scene_idx);
scene_root->add_child(original_edited_scene_root);
}
progress.step(TTR("Preparation done."), editor_data.get_edited_scene_count());
}
void EditorNode::reload_instances_with_path_in_edited_scenes(const String &p_instance_path) {
HashMap<int, List<Node *>> edited_scene_map;
if (scenes_modification_table.size() == 0) {
return;
}
Array replaced_nodes;
get_edited_scene_map(p_instance_path, edited_scene_map);
EditorProgress progress("reloading_scene", TTR("Scenes reloading"), editor_data.get_edited_scene_count());
progress.step(TTR("Reloading..."), 0, true);
if (edited_scene_map.size() > 0) {
// Reload the new instance.
Error err;
Ref<PackedScene> instance_scene_packed_scene = ResourceLoader::load(p_instance_path, "", ResourceFormatLoader::CACHE_MODE_REPLACE, &err);
@ -5943,19 +5946,24 @@ void EditorNode::reload_instances_with_path_in_edited_scenes(const String &p_ins
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 (KeyValue<int, SceneModificationsEntry> &scene_modifications_elem : scenes_modification_table) {
// Set the current scene.
int current_scene_idx = edited_scene_map_elem.key;
int current_scene_idx = scene_modifications_elem.key;
SceneModificationsEntry *scene_modifications = &scene_modifications_elem.value;
editor_data.set_edited_scene(current_scene_idx);
Node *current_edited_scene = editor_data.get_edited_scene_root(current_scene_idx);
// Make sure the node is in the tree so that editor_selection can add node smoothly.
if (original_edited_scene_idx != current_scene_idx) {
// Prevent scene roots with the same name from being in the tree at the same time.
Node *original_edited_scene_root = editor_data.get_edited_scene_root(original_edited_scene_idx);
if (original_edited_scene_root && original_edited_scene_root->get_name() == current_edited_scene->get_name()) {
scene_root->remove_child(original_edited_scene_root);
}
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);
@ -5969,11 +5977,8 @@ void EditorNode::reload_instances_with_path_in_edited_scenes(const String &p_ins
// Update the version
editor_data.is_scene_changed(current_scene_idx);
// Contains modifications in the edited scene which reference nodes inside of any nodes we will be reimporting.
HashMap<NodePath, ModificationNodeEntry> 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 (InstanceModificationsEntry instance_modifications : scene_modifications->instance_list) {
Node *original_node = instance_modifications.original_node;
String original_node_file_path = original_node->get_scene_file_path();
// Load a replacement scene for the node.
@ -6064,17 +6069,8 @@ void EditorNode::reload_instances_with_path_in_edited_scenes(const String &p_ins
}
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;
List<AdditiveNodeEntry> addition_list;
if (scenes_modification_table.has(current_scene_idx) && scenes_modification_table[current_scene_idx].has(scene_path_to_node)) {
modification_table = scenes_modification_table[current_scene_idx][scene_path_to_node];
}
update_reimported_diff_data_for_additional_nodes(current_edited_scene, original_node, original_node, modification_table, addition_list);
// Disconnect all relevant connections, all connections from and persistent connections to.
for (const KeyValue<NodePath, ModificationNodeEntry> &modification_table_entry : modification_table) {
for (const KeyValue<NodePath, ModificationNodeEntry> &modification_table_entry : instance_modifications.modifications) {
for (Connection conn : modification_table_entry.value.connections_from) {
conn.signal.get_object()->disconnect(conn.signal.get_name(), conn.callable);
}
@ -6096,7 +6092,7 @@ void EditorNode::reload_instances_with_path_in_edited_scenes(const String &p_ins
}
// Remove all nodes which were added as additional elements (they will be restored later).
for (AdditiveNodeEntry additive_node_entry : addition_list) {
for (AdditiveNodeEntry additive_node_entry : instance_modifications.addition_list) {
Node *addition_node = additive_node_entry.node;
addition_node->get_parent()->remove_child(addition_node);
}
@ -6146,6 +6142,16 @@ void EditorNode::reload_instances_with_path_in_edited_scenes(const String &p_ins
instantiated_node->set_scene_file_path(original_node_file_path);
current_edited_scene = instantiated_node;
editor_data.set_edited_scene_root(current_edited_scene);
if (original_edited_scene_idx == current_scene_idx) {
// How that the editor executes a redraw while destroying or progressing the EditorProgress,
// it crashes when the root scene has been replaced because the edited scene
// was freed and no longer in the scene tree.
SceneTreeDock::get_singleton()->set_edited_scene(current_edited_scene);
if (get_tree()) {
get_tree()->set_edited_scene_root(current_edited_scene);
}
}
}
// Replace the original node with the instantiated version.
@ -6168,7 +6174,7 @@ void EditorNode::reload_instances_with_path_in_edited_scenes(const String &p_ins
}
// Attempt to re-add all the additional nodes.
for (AdditiveNodeEntry additive_node_entry : addition_list) {
for (AdditiveNodeEntry additive_node_entry : instance_modifications.addition_list) {
Node *parent_node = instantiated_node->get_node_or_null(additive_node_entry.parent);
if (!parent_node) {
@ -6210,7 +6216,7 @@ void EditorNode::reload_instances_with_path_in_edited_scenes(const String &p_ins
}
// Attempt to restore the modified properties and signals for the instantitated node and all its owned children.
for (KeyValue<NodePath, ModificationNodeEntry> &E : modification_table) {
for (KeyValue<NodePath, ModificationNodeEntry> &E : instance_modifications.modifications) {
NodePath new_current_path = E.key;
Node *modifiable_node = instantiated_node->get_node_or_null(new_current_path);
@ -6221,7 +6227,7 @@ void EditorNode::reload_instances_with_path_in_edited_scenes(const String &p_ins
}
// Attempt to restore the modified properties and signals for the instantitated node and all its owned children.
for (KeyValue<NodePath, ModificationNodeEntry> &E : edited_scene_global_modification_table) {
for (KeyValue<NodePath, ModificationNodeEntry> &E : scene_modifications->other_instances_modifications) {
NodePath new_current_path = E.key;
Node *modifiable_node = current_edited_scene->get_node_or_null(new_current_path);
@ -6241,24 +6247,30 @@ void EditorNode::reload_instances_with_path_in_edited_scenes(const String &p_ins
// Cleanup the history of the changes.
editor_history.cleanup_history();
if (original_edited_scene_idx != current_scene_idx) {
scene_root->remove_child(current_edited_scene);
// Ensure the current edited scene is re-added if removed earlier because it has the same name
// as the reimported scene. The editor could crash when reloading SceneTreeDock if the current
// edited scene is not in the scene tree.
Node *original_edited_scene_root = editor_data.get_edited_scene_root(original_edited_scene_idx);
if (original_edited_scene_root && !original_edited_scene_root->get_parent()) {
scene_root->add_child(original_edited_scene_root);
}
}
}
// 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);
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);
}
scenes_modification_table.clear();
progress.step(TTR("Reloading done."), editor_data.get_edited_scene_count());
}
void EditorNode::_remove_all_not_owned_children(Node *p_node, Node *p_owner) {

View file

@ -797,6 +797,7 @@ public:
Error load_resource(const String &p_resource, bool p_ignore_broken_deps = false);
HashMap<StringName, Variant> get_modified_properties_for_node(Node *p_node, bool p_node_references_only);
HashMap<StringName, Variant> get_modified_properties_reference_to_nodes(Node *p_node, List<Node *> &p_nodes_referenced_by);
struct AdditiveNodeEntry {
Node *node = nullptr;
@ -820,27 +821,34 @@ public:
List<Node::GroupInfo> groups;
};
HashMap<int, HashMap<NodePath, HashMap<NodePath, ModificationNodeEntry>>> scenes_modification_table;
struct InstanceModificationsEntry {
Node *original_node;
List<Node *> instance_list;
HashMap<NodePath, ModificationNodeEntry> modifications;
List<AdditiveNodeEntry> addition_list;
};
struct SceneModificationsEntry {
List<InstanceModificationsEntry> instance_list;
HashMap<NodePath, ModificationNodeEntry> other_instances_modifications;
};
HashMap<int, SceneModificationsEntry> scenes_modification_table;
void update_node_from_node_modification_entry(Node *p_node, ModificationNodeEntry &p_node_modification);
void update_node_reference_modification_table_for_node(
Node *p_root,
Node *p_node,
List<Node *> p_excluded_nodes,
HashMap<NodePath, ModificationNodeEntry> &p_modification_table);
void get_preload_scene_modification_table(
Node *p_edited_scene,
Node *p_reimported_root,
Node *p_node, HashMap<NodePath, ModificationNodeEntry> &p_modification_table);
Node *p_node, InstanceModificationsEntry &p_instance_modifications);
void update_reimported_diff_data_for_additional_nodes(
Node *p_edited_scene,
Node *p_reimported_root,
void get_preload_modifications_reference_to_nodes(
Node *p_root,
Node *p_node,
HashMap<NodePath, ModificationNodeEntry> &p_modification_table,
List<AdditiveNodeEntry> &p_addition_list);
List<Node *> &p_excluded_nodes,
List<Node *> &p_instance_list_with_children,
HashMap<NodePath, ModificationNodeEntry> &p_modification_table);
void get_children_nodes(Node *p_node, List<Node *> &p_nodes);
bool is_additional_node_in_scene(Node *p_edited_scene, Node *p_reimported_root, Node *p_node);
void replace_history_reimported_nodes(Node *p_original_root_node, Node *p_new_root_node, Node *p_node);
@ -898,7 +906,6 @@ public:
void reload_scene(const String &p_path);
void get_edited_scene_map(const String &p_instance_path, HashMap<int, List<Node *>> &p_edited_scene_map);
void find_all_instances_inheriting_path_in_node(Node *p_root, Node *p_node, const String &p_instance_path, List<Node *> &p_instance_list);
void preload_reimporting_with_path_in_edited_scenes(const String &p_path);
void reload_instances_with_path_in_edited_scenes(const String &p_path);