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

Updating node properties in multi-scene inheritance #61076

Draft
wants to merge 2 commits into
base: master
Choose a base branch
from

Conversation

keptsecret
Copy link
Contributor

@keptsecret keptsecret commented May 16, 2022

Opening as a draft to write down the different problems I'm finding about this issue.

This issue affects both opened and closed scenes. Making changes in a level 1 scene before opening a previously closed level 3 scene does not affect the same changes.
As far as I can tell this is happening in two places:

  1. EditorData::_find_updated_instances is only checking the immediate scene it inherits from
  2. When packing a scene to instantiate, SceneState::_parse_node is overwriting default values from the inherited scene with its own previous values, but only if the inheritance is more than one level.
    • For some reason, PropertyUtils::get_property_default_value is unable to find the value from the scene it inherits from, possibly due to construction of states_stack. This means one level inheritance is working fine because the following block tells it to not update the property when being instantiated (whether it's intended or not, I don't know).

if (!pinned_props.has(name)) {
bool is_valid_default = false;
Variant default_value = PropertyUtils::get_property_default_value(p_node, name, &is_valid_default, &states_stack, true);
if (is_valid_default && !PropertyUtils::is_property_value_different(value, default_value)) {
continue;
}
}

Current commit has a fix for 1) but only works if all inherited scenes are open. I haven't found a way to traverse back the inheritance tree that works with checking modified time. This was the attempt at going back the inheritance tree. Since SceneState that the node scene saves is unique and the modified time value is pulled from the scene file when instantiating a node from the SceneState, checking modified time didn't work.

bool EditorData::_find_updated_instances(Node *p_root, Node *p_node, Set<String> &checked_paths) {
	Ref<SceneState> ss;

	if (p_node == p_root) {
		ss = p_node->get_scene_inherited_state();
	} else if (!p_node->get_scene_file_path().is_empty()) {
		ss = p_node->get_scene_instance_state();
	}

	if (ss.is_valid()) {
		String path = ss->get_path();

		if (!checked_paths.has(path)) {
			uint64_t modified_time = FileAccess::get_modified_time(path);
			if (modified_time != ss->get_last_modified_time()) {
				return true; //external scene changed
			}

			checked_paths.insert(path);
		}

		Node *p = ss->instantiate(SceneState::GEN_EDIT_STATE_MAIN);
		bool found = _find_updated_instances(p, p, checked_paths);
		memdelete(p);
		if (found) {
			return true;
		}
	}

	for (int i = 0; i < p_node->get_child_count(); i++) {
		bool found = _find_updated_instances(p_root, p_node->get_child(i), checked_paths);
		if (found) {
			return true;
		}
	}

	return false;
}

Working on a fix for #60846

@Chaosus Chaosus added this to the 4.0 milestone May 16, 2022
@keptsecret keptsecret force-pushed the update_multiscene_inherit branch 2 times, most recently from b9db587 to b05857b Compare May 18, 2022 02:38
@keptsecret
Copy link
Contributor Author

Crucially, current commit version doesn't update level 3 scene properly if level 2 scene is opened before it. Caused by how the modified time field in SceneStates are updated when instantiated, which will not trigger update when opened after.

@keptsecret keptsecret force-pushed the update_multiscene_inherit branch from b05857b to 8c086af Compare May 19, 2022 02:33
@keptsecret keptsecret force-pushed the update_multiscene_inherit branch from d4eb28d to 190d29e Compare June 10, 2022 03:17
@akien-mga akien-mga modified the milestones: 4.0, 4.x Feb 13, 2023
@@ -569,6 +569,7 @@ bool EditorData::_find_updated_instances(Node *p_root, Node *p_node, HashSet<Str

checked_paths.insert(path);
}
ss = ss->get_base_scene_state();
Copy link
Contributor

@Rindbee Rindbee Jul 9, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Due to #57606, get_base_scene_state() gets the latest version of base scene state.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants