|
@@ -327,35 +327,16 @@ Node *SceneState::instantiate(GenEditState p_edit_state) const {
|
|
//handle resources that are local to scene by duplicating them if needed
|
|
//handle resources that are local to scene by duplicating them if needed
|
|
Ref<Resource> res = value;
|
|
Ref<Resource> res = value;
|
|
if (res.is_valid()) {
|
|
if (res.is_valid()) {
|
|
- if (res->is_local_to_scene()) {
|
|
|
|
- if (n.instance >= 0) { // For the root node of a sub-scene, treat it as part of the sub-scene.
|
|
|
|
- value = get_remap_resource(res, resources_local_to_sub_scene, node->get(snames[nprops[j].name]), node);
|
|
|
|
- } else {
|
|
|
|
- HashMap<Ref<Resource>, Ref<Resource>>::Iterator E = resources_local_to_scene.find(res);
|
|
|
|
- Node *base = i == 0 ? node : ret_nodes[0];
|
|
|
|
- if (E) {
|
|
|
|
- value = E->value;
|
|
|
|
- } else {
|
|
|
|
- if (p_edit_state == GEN_EDIT_STATE_MAIN) {
|
|
|
|
- //for the main scene, use the resource as is
|
|
|
|
- res->configure_for_local_scene(base, resources_local_to_scene);
|
|
|
|
- resources_local_to_scene[res] = res;
|
|
|
|
- } else {
|
|
|
|
- //for instances, a copy must be made
|
|
|
|
- Ref<Resource> local_dupe = res->duplicate_for_local_scene(base, resources_local_to_scene);
|
|
|
|
- resources_local_to_scene[res] = local_dupe;
|
|
|
|
- value = local_dupe;
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
- //must make a copy, because this res is local to scene
|
|
|
|
- }
|
|
|
|
|
|
+ value = make_local_resource(value, n, resources_local_to_sub_scene, node, snames[nprops[j].name], resources_local_to_scene, i, ret_nodes, p_edit_state);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
if (value.get_type() == Variant::ARRAY) {
|
|
if (value.get_type() == Variant::ARRAY) {
|
|
Array set_array = value;
|
|
Array set_array = value;
|
|
|
|
+ value = setup_resources_in_array(set_array, n, resources_local_to_sub_scene, node, snames[nprops[j].name], resources_local_to_scene, i, ret_nodes, p_edit_state);
|
|
|
|
+
|
|
bool is_get_valid = false;
|
|
bool is_get_valid = false;
|
|
Variant get_value = node->get(snames[nprops[j].name], &is_get_valid);
|
|
Variant get_value = node->get(snames[nprops[j].name], &is_get_valid);
|
|
|
|
+
|
|
if (is_get_valid && get_value.get_type() == Variant::ARRAY) {
|
|
if (is_get_valid && get_value.get_type() == Variant::ARRAY) {
|
|
Array get_array = get_value;
|
|
Array get_array = get_value;
|
|
if (!set_array.is_same_typed(get_array)) {
|
|
if (!set_array.is_same_typed(get_array)) {
|
|
@@ -363,8 +344,26 @@ Node *SceneState::instantiate(GenEditState p_edit_state) const {
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
- if (p_edit_state == GEN_EDIT_STATE_INSTANCE && value.get_type() != Variant::OBJECT) {
|
|
|
|
- value = value.duplicate(true); // Duplicate arrays and dictionaries for the editor
|
|
|
|
|
|
+ if (value.get_type() == Variant::DICTIONARY) {
|
|
|
|
+ Dictionary dictionary = value;
|
|
|
|
+ const Array keys = dictionary.keys();
|
|
|
|
+ const Array values = dictionary.values();
|
|
|
|
+
|
|
|
|
+ if (has_local_resource(values) || has_local_resource(keys)) {
|
|
|
|
+ Array duplicated_keys = keys.duplicate(true);
|
|
|
|
+ Array duplicated_values = values.duplicate(true);
|
|
|
|
+
|
|
|
|
+ duplicated_keys = setup_resources_in_array(duplicated_keys, n, resources_local_to_sub_scene, node, snames[nprops[j].name], resources_local_to_scene, i, ret_nodes, p_edit_state);
|
|
|
|
+ duplicated_values = setup_resources_in_array(duplicated_values, n, resources_local_to_sub_scene, node, snames[nprops[j].name], resources_local_to_scene, i, ret_nodes, p_edit_state);
|
|
|
|
+
|
|
|
|
+ dictionary.clear();
|
|
|
|
+
|
|
|
|
+ for (int dictionary_index = 0; dictionary_index < keys.size(); dictionary_index++) {
|
|
|
|
+ dictionary[duplicated_keys[dictionary_index]] = duplicated_values[dictionary_index];
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ value = dictionary;
|
|
|
|
+ }
|
|
}
|
|
}
|
|
|
|
|
|
bool set_valid = true;
|
|
bool set_valid = true;
|
|
@@ -379,6 +378,9 @@ Node *SceneState::instantiate(GenEditState p_edit_state) const {
|
|
if (set_valid) {
|
|
if (set_valid) {
|
|
node->set(snames[nprops[j].name], value, &valid);
|
|
node->set(snames[nprops[j].name], value, &valid);
|
|
}
|
|
}
|
|
|
|
+ if (p_edit_state == GEN_EDIT_STATE_INSTANCE && value.get_type() != Variant::OBJECT) {
|
|
|
|
+ value = value.duplicate(true); // Duplicate arrays and dictionaries for the editor.
|
|
|
|
+ }
|
|
}
|
|
}
|
|
}
|
|
}
|
|
if (!missing_resource_properties.is_empty()) {
|
|
if (!missing_resource_properties.is_empty()) {
|
|
@@ -566,6 +568,50 @@ Node *SceneState::instantiate(GenEditState p_edit_state) const {
|
|
return ret_nodes[0];
|
|
return ret_nodes[0];
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+Variant SceneState::make_local_resource(Variant &p_value, const SceneState::NodeData &p_node_data, HashMap<Ref<Resource>, Ref<Resource>> &p_resources_local_to_sub_scene, Node *p_node, const StringName p_sname, HashMap<Ref<Resource>, Ref<Resource>> &p_resources_local_to_scene, int p_i, Node **p_ret_nodes, SceneState::GenEditState p_edit_state) const {
|
|
|
|
+ Ref<Resource> res = p_value;
|
|
|
|
+ if (res.is_null() || !res->is_local_to_scene()) {
|
|
|
|
+ return p_value;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if (p_node_data.instance >= 0) { // For the root node of a sub-scene, treat it as part of the sub-scene.
|
|
|
|
+ return get_remap_resource(res, p_resources_local_to_sub_scene, p_node->get(p_sname), p_node);
|
|
|
|
+ } else {
|
|
|
|
+ HashMap<Ref<Resource>, Ref<Resource>>::Iterator E = p_resources_local_to_scene.find(res);
|
|
|
|
+ Node *base = p_i == 0 ? p_node : p_ret_nodes[0];
|
|
|
|
+ if (E) {
|
|
|
|
+ return E->value;
|
|
|
|
+ } else if (p_edit_state == GEN_EDIT_STATE_MAIN) { // For the main scene, use the resource as is
|
|
|
|
+ res->configure_for_local_scene(base, p_resources_local_to_scene);
|
|
|
|
+ p_resources_local_to_scene[res] = res;
|
|
|
|
+ return res;
|
|
|
|
+ } else { // For instances, a copy must be made.
|
|
|
|
+ Ref<Resource> local_dupe = res->duplicate_for_local_scene(base, p_resources_local_to_scene);
|
|
|
|
+ p_resources_local_to_scene[res] = local_dupe;
|
|
|
|
+ return local_dupe;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+Array SceneState::setup_resources_in_array(Array &p_array_to_scan, const SceneState::NodeData &p_n, HashMap<Ref<Resource>, Ref<Resource>> &p_resources_local_to_sub_scene, Node *p_node, const StringName p_sname, HashMap<Ref<Resource>, Ref<Resource>> &p_resources_local_to_scene, int p_i, Node **p_ret_nodes, SceneState::GenEditState p_edit_state) const {
|
|
|
|
+ for (int i = 0; i < p_array_to_scan.size(); i++) {
|
|
|
|
+ if (p_array_to_scan[i].get_type() == Variant::OBJECT) {
|
|
|
|
+ p_array_to_scan[i] = make_local_resource(p_array_to_scan[i], p_n, p_resources_local_to_sub_scene, p_node, p_sname, p_resources_local_to_scene, p_i, p_ret_nodes, p_edit_state);
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ return p_array_to_scan;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+bool SceneState::has_local_resource(const Array &p_array) const {
|
|
|
|
+ for (int i = 0; i < p_array.size(); i++) {
|
|
|
|
+ Ref<Resource> res = p_array[i];
|
|
|
|
+ if (res.is_valid() && res->is_local_to_scene()) {
|
|
|
|
+ return true;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ return false;
|
|
|
|
+}
|
|
|
|
+
|
|
static int _nm_get_string(const String &p_string, HashMap<StringName, int> &name_map) {
|
|
static int _nm_get_string(const String &p_string, HashMap<StringName, int> &name_map) {
|
|
if (name_map.has(p_string)) {
|
|
if (name_map.has(p_string)) {
|
|
return name_map[p_string];
|
|
return name_map[p_string];
|
|
@@ -730,8 +776,18 @@ Error SceneState::_parse_node(Node *p_owner, Node *p_node, int p_parent_idx, Has
|
|
if (!pinned_props.has(name)) {
|
|
if (!pinned_props.has(name)) {
|
|
bool is_valid_default = false;
|
|
bool is_valid_default = false;
|
|
Variant default_value = PropertyUtils::get_property_default_value(p_node, name, &is_valid_default, &states_stack, true);
|
|
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)) {
|
|
if (is_valid_default && !PropertyUtils::is_property_value_different(value, default_value)) {
|
|
- continue;
|
|
|
|
|
|
+ if (value.get_type() == Variant::ARRAY && has_local_resource(value)) {
|
|
|
|
+ // Save anyway
|
|
|
|
+ } else if (value.get_type() == Variant::DICTIONARY) {
|
|
|
|
+ Dictionary dictionary = value;
|
|
|
|
+ if (!has_local_resource(dictionary.values()) && !has_local_resource(dictionary.keys())) {
|
|
|
|
+ continue;
|
|
|
|
+ }
|
|
|
|
+ } else {
|
|
|
|
+ continue;
|
|
|
|
+ }
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|