summaryrefslogtreecommitdiffstats
path: root/scene/resources/packed_scene.cpp
diff options
context:
space:
mode:
authorPedro J. Estébanez <pedrojrulez@gmail.com>2021-10-26 21:12:25 +0200
committerPedro J. Estébanez <pedrojrulez@gmail.com>2021-11-08 17:42:30 +0100
commit8d6f80d3677a31aee13e7f531b46ada0b6ef8bf3 (patch)
tree4c7b6c1ea393b0f30d5cad525adcd956384f69ea /scene/resources/packed_scene.cpp
parent1806ec7c14a8f038c0ff33a88d19087225c8d7ab (diff)
downloadredot-engine-8d6f80d3677a31aee13e7f531b46ada0b6ef8bf3.tar.gz
Add property value pinning
Diffstat (limited to 'scene/resources/packed_scene.cpp')
-rw-r--r--scene/resources/packed_scene.cpp65
1 files changed, 57 insertions, 8 deletions
diff --git a/scene/resources/packed_scene.cpp b/scene/resources/packed_scene.cpp
index 6eeeccc081..f43715a463 100644
--- a/scene/resources/packed_scene.cpp
+++ b/scene/resources/packed_scene.cpp
@@ -47,6 +47,30 @@ bool SceneState::can_instantiate() const {
return nodes.size() > 0;
}
+static Array _sanitize_node_pinned_properties(Node *p_node) {
+ if (!p_node->has_meta("_edit_pinned_properties_")) {
+ return Array();
+ }
+ Array pinned = p_node->get_meta("_edit_pinned_properties_");
+ if (pinned.is_empty()) {
+ return Array();
+ }
+ Set<StringName> storable_properties;
+ p_node->get_storable_properties(storable_properties);
+ int i = 0;
+ do {
+ if (storable_properties.has(pinned[i])) {
+ i++;
+ } else {
+ pinned.remove(i);
+ }
+ } while (i < pinned.size());
+ if (pinned.is_empty()) {
+ p_node->remove_meta("_edit_pinned_properties_");
+ }
+ return pinned;
+}
+
Node *SceneState::instantiate(GenEditState p_edit_state) const {
// nodes where instancing failed (because something is missing)
List<Node *> stray_instances;
@@ -229,7 +253,7 @@ Node *SceneState::instantiate(GenEditState p_edit_state) const {
} else {
Node *base = i == 0 ? node : ret_nodes[0];
- if (p_edit_state == GEN_EDIT_STATE_MAIN) {
+ if (p_edit_state == GEN_EDIT_STATE_MAIN || p_edit_state == GEN_EDIT_STATE_MAIN_INHERITED) {
//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;
@@ -293,6 +317,13 @@ Node *SceneState::instantiate(GenEditState p_edit_state) const {
}
}
+ // we only want to deal with pinned flag if instancing as pure main (no instance, no inheriting)
+ if (p_edit_state == GEN_EDIT_STATE_MAIN) {
+ _sanitize_node_pinned_properties(node);
+ } else {
+ node->remove_meta("_edit_pinned_properties_");
+ }
+
ret_nodes[i] = node;
if (node && gen_node_path_cache && ret_nodes[0]) {
@@ -442,22 +473,38 @@ Error SceneState::_parse_node(Node *p_owner, Node *p_node, int p_parent_idx, Map
List<PropertyInfo> plist;
p_node->get_property_list(&plist);
+ Array pinned_props = _sanitize_node_pinned_properties(p_node);
+
for (const PropertyInfo &E : plist) {
if (!(E.usage & PROPERTY_USAGE_STORAGE)) {
continue;
}
+ Variant forced_value;
+
// If instance or inheriting, not saving if property requested so, or it's meta
- if (states_stack.size() && ((E.usage & PROPERTY_USAGE_NO_INSTANCE_STATE) || E.name == "__meta__")) {
- continue;
+ if (states_stack.size()) {
+ if ((E.usage & PROPERTY_USAGE_NO_INSTANCE_STATE)) {
+ continue;
+ }
+ // Meta is normally not saved in instances/inherited (see GH-12838), but we need to save the pinned list
+ if (E.name == "__meta__") {
+ if (pinned_props.size()) {
+ Dictionary meta_override;
+ meta_override["_edit_pinned_properties_"] = pinned_props;
+ forced_value = meta_override;
+ }
+ }
}
- String name = E.name;
- Variant value = p_node->get(name);
+ StringName name = E.name;
+ Variant value = forced_value.get_type() == Variant::NIL ? p_node->get(name) : forced_value;
- Variant default_value = PropertyUtils::get_property_default_value(p_node, name, &states_stack, true);
- if (!PropertyUtils::is_property_value_different(value, default_value)) {
- continue;
+ if (!pinned_props.has(name) && forced_value.get_type() == Variant::NIL) {
+ Variant default_value = PropertyUtils::get_property_default_value(p_node, name, &states_stack, true);
+ if (!PropertyUtils::is_property_value_different(value, default_value)) {
+ continue;
+ }
}
NodeData::Property prop;
@@ -1505,6 +1552,7 @@ void SceneState::_bind_methods() {
BIND_ENUM_CONSTANT(GEN_EDIT_STATE_DISABLED);
BIND_ENUM_CONSTANT(GEN_EDIT_STATE_INSTANCE);
BIND_ENUM_CONSTANT(GEN_EDIT_STATE_MAIN);
+ BIND_ENUM_CONSTANT(GEN_EDIT_STATE_MAIN_INHERITED);
}
SceneState::SceneState() {
@@ -1596,6 +1644,7 @@ void PackedScene::_bind_methods() {
BIND_ENUM_CONSTANT(GEN_EDIT_STATE_DISABLED);
BIND_ENUM_CONSTANT(GEN_EDIT_STATE_INSTANCE);
BIND_ENUM_CONSTANT(GEN_EDIT_STATE_MAIN);
+ BIND_ENUM_CONSTANT(GEN_EDIT_STATE_MAIN_INHERITED);
}
PackedScene::PackedScene() {