Skip to content

Commit

Permalink
fix sub-inherited scene proper node update
Browse files Browse the repository at this point in the history
  • Loading branch information
sodaJar committed Feb 21, 2023
1 parent 7e79aea commit ae07d59
Show file tree
Hide file tree
Showing 5 changed files with 76 additions and 2 deletions.
38 changes: 37 additions & 1 deletion editor/editor_data.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -635,7 +635,10 @@ bool EditorData::check_and_update_scene(int p_idx) {

HashSet<String> checked_scenes;

bool must_reload = _find_updated_instances(edited_scene[p_idx].root, edited_scene[p_idx].root, checked_scenes);
//_find_updated_instances() only detects changes in direct inherited scenes
//if the edited scene has inherited_nodes stored it means that an ancestor scene was saved and the current edited scene hasn't been reloaded since then
bool base_scene_updated = edited_scene[p_idx].root->get_scene_inherited_state().is_valid() && edited_scene[p_idx].inherited_nodes.size() > 0;
bool must_reload = _find_updated_instances(edited_scene[p_idx].root, edited_scene[p_idx].root, checked_scenes) || base_scene_updated;

if (must_reload) {
Ref<PackedScene> pscene;
Expand All @@ -644,6 +647,7 @@ bool EditorData::check_and_update_scene(int p_idx) {
EditorProgress ep("update_scene", TTR("Updating Scene"), 2);
ep.step(TTR("Storing local changes..."), 0);
// Pack first, so it stores diffs to previous version of saved scene.
pscene->get_state()->set_inherited_nodes(edited_scene[p_idx].inherited_nodes); //tell the packed scene which nodes are inherited
Error err = pscene->pack(edited_scene[p_idx].root);
ERR_FAIL_COND_V(err != OK, false);
ep.step(TTR("Updating scene..."), 1);
Expand All @@ -669,6 +673,9 @@ bool EditorData::check_and_update_scene(int p_idx) {
}
edited_scene.write[p_idx].selection = new_selection;

//information no longer needed, if kept, the editor won't add nodes of the same name as the ones deleted in an ancestor scene
clear_edited_scene_inherited_nodes(p_idx);

return true;
}

Expand Down Expand Up @@ -877,6 +884,35 @@ void EditorData::clear_edited_scenes() {
edited_scene.clear();
}

void EditorData::update_edited_scene_inherited_nodes(int p_edited_scene) {
//adds to the set of inherited nodes of the edited_scene specified by p_edited_scene
//helps correctly updating sub-inherited scenes
//the function is currently called when a scene is saved
if (p_edited_scene >= edited_scene.size()) {
return;
}
EditedScene es = edited_scene.get(p_edited_scene);
es.inherited_nodes.insert(NodePath(".")); //store something even if there are no inherited nodes to indicate scene save
Ref<SceneState> inherited_state = es.root->get_scene_inherited_state();
while (inherited_state.is_valid()) {
for (int i = 1; i < inherited_state->get_node_count(); i++) {
es.inherited_nodes.insert(inherited_state->get_node_path(i));
}
inherited_state = inherited_state->get_base_scene_state();
}
edited_scene.set(p_edited_scene, es);
}

void EditorData::clear_edited_scene_inherited_nodes(int p_edited_scene) {
//this function is called after the edited scene is updated, as it no longer needs the information on which nodes are inherited
if (p_edited_scene >= edited_scene.size()) {
return;
}
EditedScene es = edited_scene.get(p_edited_scene);
es.inherited_nodes.clear();
edited_scene.set(p_edited_scene, es);
}

void EditorData::set_plugin_window_layout(Ref<ConfigFile> p_layout) {
for (int i = 0; i < editor_plugins.size(); i++) {
editor_plugins[i]->set_window_layout(p_layout);
Expand Down
3 changes: 3 additions & 0 deletions editor/editor_data.h
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,7 @@ class EditorData {
NodePath live_edit_root;
int history_id = 0;
uint64_t last_checked_version = 0;
HashSet<NodePath> inherited_nodes;
};

private:
Expand Down Expand Up @@ -196,6 +197,8 @@ class EditorData {
Node *get_edited_scene_root(int p_idx = -1);
int get_edited_scene_count() const;
Vector<EditedScene> get_edited_scenes() const;
void update_edited_scene_inherited_nodes(int p_edited_scene);
void clear_edited_scene_inherited_nodes(int p_edited_scene);
String get_scene_title(int p_idx, bool p_always_strip_extension = false) const;
String get_scene_path(int p_idx) const;
String get_scene_type(int p_idx) const;
Expand Down
19 changes: 19 additions & 0 deletions editor/editor_node.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1743,6 +1743,24 @@ void EditorNode::_save_scene(String p_file, int idx) {

_set_scene_metadata(p_file, idx);

//tell (sub)inherited edited scenes to keep track of nodes inherited
//the states are still in their old versions, this allows for knowing which nodes were deleted when updating an inherited scene
for (int i = 0; i < editor_data.get_edited_scene_count(); i++) {
//only update for edited scenes that has just been reloaded to avoid issues when saving more than once
if (editor_data.get_edited_scenes()[i].inherited_nodes.size() > 0) {
continue;
}
Ref<SceneState> ss = editor_data.get_edited_scene_root(i)->get_scene_inherited_state();
//update for edited scenes that inherit the saved scene
while (ss.is_valid()) {
if (ss->get_path() == p_file) {
editor_data.update_edited_scene_inherited_nodes(i);
break;
}
ss = ss->get_base_scene_state();
}
}

Ref<PackedScene> sdata;

if (ResourceCache::has(p_file)) {
Expand Down Expand Up @@ -3718,6 +3736,7 @@ bool EditorNode::is_changing_scene() const {
}

void EditorNode::set_current_scene(int p_idx) {
HashSet<String> checked_scenes;
// Save the folding in case the scene gets reloaded.
if (editor_data.get_scene_path(p_idx) != "" && editor_data.get_edited_scene_root(p_idx)) {
editor_folding.save_scene_folding(editor_data.get_edited_scene_root(p_idx), editor_data.get_scene_path(p_idx));
Expand Down
14 changes: 13 additions & 1 deletion scene/resources/packed_scene.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -549,7 +549,18 @@ Error SceneState::_parse_node(Node *p_owner, Node *p_node, int p_parent_idx, Has
// and only save what has changed

bool instantiated_by_owner = false;
//the following line doesn't deal with nodes in sub-inherited scenes
Vector<SceneState::PackState> states_stack = PropertyUtils::get_node_states_stack(p_node, p_owner, &instantiated_by_owner);
//below fixes above issue so sub-inherited scenes can update properly after changes in ancestor scenes
bool node_inherited = false;
if (p_node != p_owner) {
for (HashSet<NodePath>::Iterator E = inherited_nodes.begin(); E; ++E) {
if (String(*E) == "./" + String(p_owner->get_path_to(p_node))) {
node_inherited = true; //so save_node becomes false
break;
}
}
}

if (!p_node->get_scene_file_path().is_empty() && p_node->get_owner() == p_owner && instantiated_by_owner) {
if (p_node->get_scene_instance_load_placeholder()) {
Expand Down Expand Up @@ -696,8 +707,9 @@ Error SceneState::_parse_node(Node *p_owner, Node *p_node, int p_parent_idx, Has
// that hold changes

bool save_node = nd.properties.size() || nd.groups.size(); // some local properties or groups exist
save_node = save_node || p_node == p_owner; // owner is always saved
save_node = save_node || (p_node->get_owner() == p_owner && instantiated_by_owner); //part of scene and not instanced
save_node = save_node && !node_inherited; //even if local properties exist, if the node is inherited, it should not be saved
save_node = save_node || p_node == p_owner; // owner is always saved

int idx = nodes.size();
int parent_node = NO_PARENT_SAVED;
Expand Down
4 changes: 4 additions & 0 deletions scene/resources/packed_scene.h
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ class SceneState : public RefCounted {
Vector<NodePath> editable_instances;
mutable HashMap<NodePath, int> node_path_cache;
mutable HashMap<int, int> base_scene_node_remap;
HashSet<NodePath> inherited_nodes;

int base_scene_idx = -1;

Expand Down Expand Up @@ -183,6 +184,9 @@ class SceneState : public RefCounted {

Vector<NodePath> get_editable_instances() const;

void set_inherited_nodes(HashSet<NodePath> p_inherited_node_paths) { inherited_nodes = p_inherited_node_paths; }
HashSet<NodePath> get_inherited_nodes() const { return inherited_nodes; }

//build API

int add_name(const StringName &p_name);
Expand Down

0 comments on commit ae07d59

Please sign in to comment.