mirror of
https://github.com/godotengine/godot.git
synced 2024-11-22 20:23:53 +00:00
Make reimported models reimport their owner.
Changes the behaviour of the scene hot-reload system so that if the scene which needs to be reimported is owned by another instance, reload that instance instead.
This commit is contained in:
parent
61598c5c88
commit
86ce15fb7a
@ -4391,6 +4391,21 @@ bool EditorNode::is_additional_node_in_scene(Node *p_edited_scene, Node *p_reimp
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void EditorNode::get_scene_editor_data_for_node(Node *p_root, Node *p_node, HashMap<NodePath, SceneEditorDataEntry> &p_table) {
|
||||||
|
SceneEditorDataEntry new_entry;
|
||||||
|
new_entry.is_display_folded = p_node->is_displayed_folded();
|
||||||
|
|
||||||
|
if (p_root != p_node) {
|
||||||
|
new_entry.is_editable = p_root->is_editable_instance(p_node);
|
||||||
|
}
|
||||||
|
|
||||||
|
p_table.insert(p_root->get_path_to(p_node), new_entry);
|
||||||
|
|
||||||
|
for (int i = 0; i < p_node->get_child_count(); i++) {
|
||||||
|
get_scene_editor_data_for_node(p_root, p_node->get_child(i), p_table);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void EditorNode::get_preload_scene_modification_table(
|
void EditorNode::get_preload_scene_modification_table(
|
||||||
Node *p_edited_scene,
|
Node *p_edited_scene,
|
||||||
Node *p_reimported_root,
|
Node *p_reimported_root,
|
||||||
@ -4497,7 +4512,7 @@ void EditorNode::get_preload_scene_modification_table(
|
|||||||
void EditorNode::get_preload_modifications_reference_to_nodes(
|
void EditorNode::get_preload_modifications_reference_to_nodes(
|
||||||
Node *p_root,
|
Node *p_root,
|
||||||
Node *p_node,
|
Node *p_node,
|
||||||
List<Node *> &p_excluded_nodes,
|
HashSet<Node *> &p_excluded_nodes,
|
||||||
List<Node *> &p_instance_list_with_children,
|
List<Node *> &p_instance_list_with_children,
|
||||||
HashMap<NodePath, ModificationNodeEntry> &p_modification_table) {
|
HashMap<NodePath, ModificationNodeEntry> &p_modification_table) {
|
||||||
if (!p_excluded_nodes.find(p_node)) {
|
if (!p_excluded_nodes.find(p_node)) {
|
||||||
@ -5962,12 +5977,14 @@ void EditorNode::reload_scene(const String &p_path) {
|
|||||||
scene_tabs->set_current_tab(current_tab);
|
scene_tabs->set_current_tab(current_tab);
|
||||||
}
|
}
|
||||||
|
|
||||||
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) {
|
void EditorNode::find_all_instances_inheriting_path_in_node(Node *p_root, Node *p_node, const String &p_instance_path, HashSet<Node *> &p_instance_list) {
|
||||||
String scene_file_path = p_node->get_scene_file_path();
|
String scene_file_path = p_node->get_scene_file_path();
|
||||||
|
|
||||||
// This is going to get messy...
|
bool valid_instance_found = false;
|
||||||
|
|
||||||
|
// Attempt to find all the instances matching path we're going to reload.
|
||||||
if (p_node->get_scene_file_path() == p_instance_path) {
|
if (p_node->get_scene_file_path() == p_instance_path) {
|
||||||
p_instance_list.push_back(p_node);
|
valid_instance_found = true;
|
||||||
} else {
|
} else {
|
||||||
Node *current_node = p_node;
|
Node *current_node = p_node;
|
||||||
|
|
||||||
@ -5975,7 +5992,7 @@ void EditorNode::find_all_instances_inheriting_path_in_node(Node *p_root, Node *
|
|||||||
while (inherited_state.is_valid()) {
|
while (inherited_state.is_valid()) {
|
||||||
String inherited_path = inherited_state->get_path();
|
String inherited_path = inherited_state->get_path();
|
||||||
if (inherited_path == p_instance_path) {
|
if (inherited_path == p_instance_path) {
|
||||||
p_instance_list.push_back(p_node);
|
valid_instance_found = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -5983,6 +6000,19 @@ void EditorNode::find_all_instances_inheriting_path_in_node(Node *p_root, Node *
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Instead of adding this instance directly, if its not owned by the scene, walk its ancestors
|
||||||
|
// and find the first node still owned by the scene. This is what we will reloading instead.
|
||||||
|
if (valid_instance_found) {
|
||||||
|
Node *current_node = p_node;
|
||||||
|
while (true) {
|
||||||
|
if (current_node->get_owner() == p_root || current_node->get_owner() == nullptr) {
|
||||||
|
p_instance_list.insert(current_node);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
current_node = current_node->get_parent();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
for (int i = 0; i < p_node->get_child_count(); i++) {
|
for (int i = 0; i < p_node->get_child_count(); i++) {
|
||||||
find_all_instances_inheriting_path_in_node(p_root, p_node->get_child(i), 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);
|
||||||
}
|
}
|
||||||
@ -6001,20 +6031,20 @@ void EditorNode::preload_reimporting_with_path_in_edited_scenes(const List<Strin
|
|||||||
Node *edited_scene_root = editor_data.get_edited_scene_root(current_scene_idx);
|
Node *edited_scene_root = editor_data.get_edited_scene_root(current_scene_idx);
|
||||||
|
|
||||||
if (edited_scene_root) {
|
if (edited_scene_root) {
|
||||||
SceneModificationsEntry scene_motifications;
|
SceneModificationsEntry scene_modifications;
|
||||||
|
|
||||||
for (const String &instance_path : p_scenes) {
|
for (const String &instance_path : p_scenes) {
|
||||||
if (editor_data.get_scene_path(current_scene_idx) == instance_path) {
|
if (editor_data.get_scene_path(current_scene_idx) == instance_path) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
List<Node *> instance_list;
|
HashSet<Node *> instances_to_reimport;
|
||||||
find_all_instances_inheriting_path_in_node(edited_scene_root, edited_scene_root, instance_path, instance_list);
|
find_all_instances_inheriting_path_in_node(edited_scene_root, edited_scene_root, instance_path, instances_to_reimport);
|
||||||
if (instance_list.size() > 0) {
|
if (instances_to_reimport.size() > 0) {
|
||||||
editor_data.set_edited_scene(current_scene_idx);
|
editor_data.set_edited_scene(current_scene_idx);
|
||||||
|
|
||||||
List<Node *> instance_list_with_children;
|
List<Node *> instance_list_with_children;
|
||||||
for (Node *original_node : instance_list) {
|
for (Node *original_node : instances_to_reimport) {
|
||||||
InstanceModificationsEntry instance_modifications;
|
InstanceModificationsEntry instance_modifications;
|
||||||
|
|
||||||
// Fetching all the modified properties of the nodes reimported scene.
|
// Fetching all the modified properties of the nodes reimported scene.
|
||||||
@ -6022,19 +6052,19 @@ void EditorNode::preload_reimporting_with_path_in_edited_scenes(const List<Strin
|
|||||||
|
|
||||||
instance_modifications.original_node = original_node;
|
instance_modifications.original_node = original_node;
|
||||||
instance_modifications.instance_path = instance_path;
|
instance_modifications.instance_path = instance_path;
|
||||||
scene_motifications.instance_list.push_back(instance_modifications);
|
scene_modifications.instance_list.push_back(instance_modifications);
|
||||||
|
|
||||||
instance_list_with_children.push_back(original_node);
|
instance_list_with_children.push_back(original_node);
|
||||||
get_children_nodes(original_node, instance_list_with_children);
|
get_children_nodes(original_node, instance_list_with_children);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Search the scene to find nodes that references the nodes will be recreated.
|
// 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);
|
get_preload_modifications_reference_to_nodes(edited_scene_root, edited_scene_root, instances_to_reimport, instance_list_with_children, scene_modifications.other_instances_modifications);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (scene_motifications.instance_list.size() > 0) {
|
if (scene_modifications.instance_list.size() > 0) {
|
||||||
scenes_modification_table[current_scene_idx] = scene_motifications;
|
scenes_modification_table[current_scene_idx] = scene_modifications;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -6157,10 +6187,10 @@ void EditorNode::reload_instances_with_path_in_edited_scenes() {
|
|||||||
// Instantiate early so that caches cleared on load in SceneState can be rebuilt early.
|
// Instantiate early so that caches cleared on load in SceneState can be rebuilt early.
|
||||||
Node *instantiated_node = nullptr;
|
Node *instantiated_node = nullptr;
|
||||||
|
|
||||||
// If we are in a inherit scene, it's easier to create a new base scene and
|
// If we are in a inherited scene, it's easier to create a new base scene and
|
||||||
// grab the node from there.
|
// grab the node from there.
|
||||||
// When scene_path_to_node is '.' and we have scene_inherited_state, it's because
|
// When scene_path_to_node is '.' and we have scene_inherited_state, it's because
|
||||||
// it's a muli-level inheritance scene. We should use
|
// it's a multi-level inheritance scene. We should use
|
||||||
NodePath scene_path_to_node = current_edited_scene->get_path_to(original_node);
|
NodePath scene_path_to_node = current_edited_scene->get_path_to(original_node);
|
||||||
Ref<SceneState> scene_state = current_edited_scene->get_scene_inherited_state();
|
Ref<SceneState> scene_state = current_edited_scene->get_scene_inherited_state();
|
||||||
if (scene_path_to_node != "." && scene_state.is_valid() && scene_state->get_path() != instance_modifications.instance_path && scene_state->find_node_by_path(scene_path_to_node) >= 0) {
|
if (scene_path_to_node != "." && scene_state.is_valid() && scene_state->get_path() != instance_modifications.instance_path && scene_state->find_node_by_path(scene_path_to_node) >= 0) {
|
||||||
@ -6184,9 +6214,9 @@ void EditorNode::reload_instances_with_path_in_edited_scenes() {
|
|||||||
|
|
||||||
if (!instantiated_node) {
|
if (!instantiated_node) {
|
||||||
// If no base scene was found to create the node, we will use the reimported packed scene directly.
|
// If no base scene was found to create the node, we will use the reimported packed scene directly.
|
||||||
// But, when the current edited scene is the reimported scene, it's because it's a inherited scene
|
// But, when the current edited scene is the reimported scene, it's because it's an inherited scene
|
||||||
// of the reimported scene. In that case, we will not instantiate current_packed_scene, because
|
// derived from the reimported scene. In that case, we will not instantiate current_packed_scene, because
|
||||||
// we would reinstanciate ourself. Using the base scene is better.
|
// we would reinstantiate ourself. Using the base scene is better.
|
||||||
if (current_edited_scene == original_node) {
|
if (current_edited_scene == original_node) {
|
||||||
if (base_packed_scene.is_valid()) {
|
if (base_packed_scene.is_valid()) {
|
||||||
instantiated_node = base_packed_scene->instantiate(PackedScene::GEN_EDIT_STATE_INSTANCE);
|
instantiated_node = base_packed_scene->instantiate(PackedScene::GEN_EDIT_STATE_INSTANCE);
|
||||||
@ -6242,6 +6272,17 @@ void EditorNode::reload_instances_with_path_in_edited_scenes() {
|
|||||||
// crash when reimporting scenes with animations when "Editable children" was enabled.
|
// crash when reimporting scenes with animations when "Editable children" was enabled.
|
||||||
replace_history_reimported_nodes(original_node, instantiated_node, original_node);
|
replace_history_reimported_nodes(original_node, instantiated_node, original_node);
|
||||||
|
|
||||||
|
// Reset the editable instance state.
|
||||||
|
HashMap<NodePath, SceneEditorDataEntry> scene_editor_data_table;
|
||||||
|
Node *owner = original_node->get_owner();
|
||||||
|
if (!owner) {
|
||||||
|
owner = original_node;
|
||||||
|
}
|
||||||
|
|
||||||
|
get_scene_editor_data_for_node(owner, original_node, scene_editor_data_table);
|
||||||
|
|
||||||
|
bool original_node_scene_instance_load_placeholder = original_node->get_scene_instance_load_placeholder();
|
||||||
|
|
||||||
// Delete all the remaining node children.
|
// Delete all the remaining node children.
|
||||||
while (original_node->get_child_count()) {
|
while (original_node->get_child_count()) {
|
||||||
Node *child = original_node->get_child(0);
|
Node *child = original_node->get_child(0);
|
||||||
@ -6250,16 +6291,6 @@ void EditorNode::reload_instances_with_path_in_edited_scenes() {
|
|||||||
child->queue_free();
|
child->queue_free();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Reset the editable instance state.
|
|
||||||
bool is_editable = true;
|
|
||||||
Node *owner = original_node->get_owner();
|
|
||||||
if (owner) {
|
|
||||||
is_editable = owner->is_editable_instance(original_node);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool original_node_is_displayed_folded = original_node->is_displayed_folded();
|
|
||||||
bool original_node_scene_instance_load_placeholder = original_node->get_scene_instance_load_placeholder();
|
|
||||||
|
|
||||||
// Update the name to match
|
// Update the name to match
|
||||||
instantiated_node->set_name(original_node->get_name());
|
instantiated_node->set_name(original_node->get_name());
|
||||||
|
|
||||||
@ -6290,19 +6321,9 @@ void EditorNode::reload_instances_with_path_in_edited_scenes() {
|
|||||||
// Mark the old node for deletion.
|
// Mark the old node for deletion.
|
||||||
original_node->queue_free();
|
original_node->queue_free();
|
||||||
|
|
||||||
// Restore the folded and placeholder state from the original node.
|
// Restore the placeholder state from the original node.
|
||||||
instantiated_node->set_display_folded(original_node_is_displayed_folded);
|
|
||||||
instantiated_node->set_scene_instance_load_placeholder(original_node_scene_instance_load_placeholder);
|
instantiated_node->set_scene_instance_load_placeholder(original_node_scene_instance_load_placeholder);
|
||||||
|
|
||||||
if (owner) {
|
|
||||||
Ref<SceneState> ss_inst = owner->get_scene_instance_state();
|
|
||||||
if (ss_inst.is_valid()) {
|
|
||||||
ss_inst->update_instance_resource(instance_modifications.instance_path, current_packed_scene);
|
|
||||||
}
|
|
||||||
|
|
||||||
owner->set_editable_instance(instantiated_node, is_editable);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Attempt to re-add all the additional nodes.
|
// Attempt to re-add all the additional nodes.
|
||||||
for (AdditiveNodeEntry additive_node_entry : instance_modifications.addition_list) {
|
for (AdditiveNodeEntry additive_node_entry : instance_modifications.addition_list) {
|
||||||
Node *parent_node = instantiated_node->get_node_or_null(additive_node_entry.parent);
|
Node *parent_node = instantiated_node->get_node_or_null(additive_node_entry.parent);
|
||||||
@ -6334,6 +6355,17 @@ void EditorNode::reload_instances_with_path_in_edited_scenes() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Restore the scene's editable instance and folded states.
|
||||||
|
for (HashMap<NodePath, SceneEditorDataEntry>::Iterator I = scene_editor_data_table.begin(); I; ++I) {
|
||||||
|
Node *node = owner->get_node_or_null(I->key);
|
||||||
|
if (node) {
|
||||||
|
if (owner != node) {
|
||||||
|
owner->set_editable_instance(node, I->value.is_editable);
|
||||||
|
}
|
||||||
|
node->set_display_folded(I->value.is_display_folded);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Restore the selection.
|
// Restore the selection.
|
||||||
if (selected_node_paths.size()) {
|
if (selected_node_paths.size()) {
|
||||||
for (NodePath selected_node_path : selected_node_paths) {
|
for (NodePath selected_node_path : selected_node_paths) {
|
||||||
|
@ -849,12 +849,19 @@ public:
|
|||||||
HashMap<NodePath, ModificationNodeEntry> other_instances_modifications;
|
HashMap<NodePath, ModificationNodeEntry> other_instances_modifications;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct SceneEditorDataEntry {
|
||||||
|
bool is_editable;
|
||||||
|
bool is_display_folded;
|
||||||
|
};
|
||||||
|
|
||||||
HashMap<int, SceneModificationsEntry> scenes_modification_table;
|
HashMap<int, SceneModificationsEntry> scenes_modification_table;
|
||||||
List<String> scenes_reimported;
|
List<String> scenes_reimported;
|
||||||
List<String> resources_reimported;
|
List<String> resources_reimported;
|
||||||
|
|
||||||
void update_node_from_node_modification_entry(Node *p_node, ModificationNodeEntry &p_node_modification);
|
void update_node_from_node_modification_entry(Node *p_node, ModificationNodeEntry &p_node_modification);
|
||||||
|
|
||||||
|
void get_scene_editor_data_for_node(Node *p_root, Node *p_node, HashMap<NodePath, SceneEditorDataEntry> &p_table);
|
||||||
|
|
||||||
void get_preload_scene_modification_table(
|
void get_preload_scene_modification_table(
|
||||||
Node *p_edited_scene,
|
Node *p_edited_scene,
|
||||||
Node *p_reimported_root,
|
Node *p_reimported_root,
|
||||||
@ -863,7 +870,7 @@ public:
|
|||||||
void get_preload_modifications_reference_to_nodes(
|
void get_preload_modifications_reference_to_nodes(
|
||||||
Node *p_root,
|
Node *p_root,
|
||||||
Node *p_node,
|
Node *p_node,
|
||||||
List<Node *> &p_excluded_nodes,
|
HashSet<Node *> &p_excluded_nodes,
|
||||||
List<Node *> &p_instance_list_with_children,
|
List<Node *> &p_instance_list_with_children,
|
||||||
HashMap<NodePath, ModificationNodeEntry> &p_modification_table);
|
HashMap<NodePath, ModificationNodeEntry> &p_modification_table);
|
||||||
void get_children_nodes(Node *p_node, List<Node *> &p_nodes);
|
void get_children_nodes(Node *p_node, List<Node *> &p_nodes);
|
||||||
@ -924,7 +931,7 @@ public:
|
|||||||
|
|
||||||
void reload_scene(const String &p_path);
|
void reload_scene(const String &p_path);
|
||||||
|
|
||||||
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 find_all_instances_inheriting_path_in_node(Node *p_root, Node *p_node, const String &p_instance_path, HashSet<Node *> &p_instance_list);
|
||||||
void preload_reimporting_with_path_in_edited_scenes(const List<String> &p_scenes);
|
void preload_reimporting_with_path_in_edited_scenes(const List<String> &p_scenes);
|
||||||
void reload_instances_with_path_in_edited_scenes();
|
void reload_instances_with_path_in_edited_scenes();
|
||||||
|
|
||||||
|
@ -1267,25 +1267,6 @@ Ref<SceneState> SceneState::get_base_scene_state() const {
|
|||||||
return Ref<SceneState>();
|
return Ref<SceneState>();
|
||||||
}
|
}
|
||||||
|
|
||||||
void SceneState::update_instance_resource(String p_path, Ref<PackedScene> p_packed_scene) {
|
|
||||||
ERR_FAIL_COND(p_packed_scene.is_null());
|
|
||||||
|
|
||||||
for (const NodeData &nd : nodes) {
|
|
||||||
if (nd.instance >= 0) {
|
|
||||||
if (!(nd.instance & FLAG_INSTANCE_IS_PLACEHOLDER)) {
|
|
||||||
int instance_id = nd.instance & FLAG_MASK;
|
|
||||||
Ref<PackedScene> original_packed_scene = variants[instance_id];
|
|
||||||
if (original_packed_scene.is_valid()) {
|
|
||||||
if (original_packed_scene->get_path() == p_path) {
|
|
||||||
variants.remove_at(instance_id);
|
|
||||||
variants.insert(instance_id, p_packed_scene);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
int SceneState::find_node_by_path(const NodePath &p_node) const {
|
int SceneState::find_node_by_path(const NodePath &p_node) const {
|
||||||
ERR_FAIL_COND_V_MSG(node_path_cache.is_empty(), -1, "This operation requires the node cache to have been built.");
|
ERR_FAIL_COND_V_MSG(node_path_cache.is_empty(), -1, "This operation requires the node cache to have been built.");
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user