Add property value pinning

This commit is contained in:
Pedro J. Estébanez 2021-10-26 21:12:35 +02:00
parent 76b7d23a10
commit 4dba25b3ff
14 changed files with 335 additions and 21 deletions

View File

@ -102,7 +102,7 @@
</signal>
<signal name="property_checked">
<argument index="0" name="property" type="String" />
<argument index="1" name="bool" type="String" />
<argument index="1" name="checked" type="bool" />
<description>
Emitted when a property was checked. Used internally.
</description>
@ -120,6 +120,14 @@
Emit it if you want to key a property with a single value.
</description>
</signal>
<signal name="property_pinned">
<argument index="0" name="property" type="String" />
<argument index="1" name="pinned" type="bool" />
<description>
Emit it if you want to mark (or unmark) the value of a property for being saved regardless of being equal to the default value.
The default value is the one the property will get when the node is just instantiated and can come from an ancestor scene in the inheritance/instancing chain, a script or a builtin class.
</description>
</signal>
<signal name="resource_selected">
<argument index="0" name="path" type="String" />
<argument index="1" name="resource" type="Resource" />

View File

@ -86,5 +86,9 @@
If passed to [method instance], provides local scene resources to the local scene. Only the main scene should receive the main edit state.
[b]Note:[/b] Only available in editor builds.
</constant>
<constant name="GEN_EDIT_STATE_MAIN_INHERITED" value="3" enum="GenEditState">
It's similar to [constant GEN_EDIT_STATE_MAIN], but for the case where the scene is being instantiated to be the base of another one.
[b]Note:[/b] Only available in editor builds.
</constant>
</constants>
</class>

View File

@ -168,5 +168,9 @@
If passed to [method PackedScene.instance], provides local scene resources to the local scene. Only the main scene should receive the main edit state.
[b]Note:[/b] Only available in editor builds.
</constant>
<constant name="GEN_EDIT_STATE_MAIN_INHERITED" value="3" enum="GenEditState">
If passed to [method PackedScene.instance], it's similar to [constant GEN_EDIT_STATE_MAIN], but for the case where the scene is being instantiated to be the base of another one.
[b]Note:[/b] Only available in editor builds.
</constant>
</constants>
</class>

View File

@ -261,6 +261,14 @@ void EditorProperty::_notification(int p_what) {
revert_rect = Rect2();
}
if (!pin_hidden && is_pinned) {
Ref<Texture> pinned_icon = get_icon("Pin", "EditorIcons");
int margin_w = get_constant("hseparator", "Tree") * 2;
text_limit -= margin_w + pinned_icon->get_width();
int text_w = MIN(font->get_string_size(label).x, text_limit);
draw_texture(pinned_icon, Vector2(ofs + text_w + margin_w, (size.height - pinned_icon->get_height()) / 2), color);
}
int v_ofs = (size.height - font->get_height()) / 2;
draw_string(font, Point2(ofs, v_ofs + font->get_ascent()), label, color, text_limit);
@ -337,15 +345,22 @@ bool EditorPropertyRevert::can_property_revert(Object *p_object, const StringNam
return PropertyUtils::is_property_value_different(current_value, revert_value);
}
void EditorProperty::update_reload_status() {
void EditorProperty::update_revert_and_pin_status() {
if (property == StringName()) {
return; //no property, so nothing to do
}
bool new_is_pinned = false;
if (can_pin) {
Node *node = Object::cast_to<Node>(object);
CRASH_COND(!node);
new_is_pinned = node->is_property_pinned(property);
}
bool new_can_revert = EditorPropertyRevert::can_property_revert(object, property);
if (new_can_revert != can_revert) {
if (new_can_revert != can_revert || new_is_pinned != is_pinned) {
can_revert = new_can_revert;
is_pinned = new_is_pinned;
update();
}
}
@ -516,6 +531,14 @@ void EditorProperty::_gui_input(const Ref<InputEvent> &p_event) {
update();
emit_signal("property_checked", property, checked);
}
} else if (mb.is_valid() && mb->is_pressed() && mb->get_button_index() == BUTTON_RIGHT) {
_update_popup();
if (menu->get_item_count()) {
menu->set_position(get_global_mouse_position());
menu->set_as_minsize();
menu->popup();
select();
}
}
}
@ -575,6 +598,56 @@ float EditorProperty::get_name_split_ratio() const {
void EditorProperty::set_object_and_property(Object *p_object, const StringName &p_property) {
object = p_object;
property = p_property;
_update_pin_flags();
}
static bool _is_value_potential_override(Node *p_node, const String &p_property) {
// Consider a value is potentially overriding another if either of the following is true:
// a) The node is foreign (inheriting or an instance), so the original value may come from another scene.
// b) The node belongs to the scene, but the original value comes from somewhere but the builtin class (i.e., a script).
Node *edited_scene = EditorNode::get_singleton()->get_edited_scene();
Vector<SceneState::PackState> states_stack = PropertyUtils::get_node_states_stack(p_node, edited_scene);
if (states_stack.size()) {
return true;
} else {
bool is_class_default = false;
PropertyUtils::get_property_default_value(p_node, p_property, &states_stack, false, nullptr, &is_class_default);
return !is_class_default;
}
}
void EditorProperty::_update_pin_flags() {
can_pin = false;
pin_hidden = true;
if (read_only) {
return;
}
if (Node *node = Object::cast_to<Node>(object)) {
// Avoid errors down the road by ignoring nodes which are not part of a scene
if (!node->get_owner()) {
bool is_scene_root = false;
for (int i = 0; i < EditorNode::get_singleton()->get_editor_data().get_edited_scene_count(); ++i) {
if (EditorNode::get_singleton()->get_editor_data().get_edited_scene_root(i) == node) {
is_scene_root = true;
break;
}
}
if (!is_scene_root) {
return;
}
}
if (!_is_value_potential_override(node, property)) {
return;
}
pin_hidden = false;
{
Set<StringName> storable_properties;
node->get_storable_properties(storable_properties);
if (storable_properties.has(node->get_property_store_alias(property))) {
can_pin = true;
}
}
}
}
Control *EditorProperty::make_custom_tooltip(const String &p_text) const {
@ -627,6 +700,7 @@ void EditorProperty::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_edited_object"), &EditorProperty::get_edited_object);
ClassDB::bind_method(D_METHOD("_gui_input"), &EditorProperty::_gui_input);
ClassDB::bind_method(D_METHOD("_menu_option"), &EditorProperty::_menu_option);
ClassDB::bind_method(D_METHOD("_focusable_focused"), &EditorProperty::_focusable_focused);
ClassDB::bind_method(D_METHOD("get_tooltip_text"), &EditorProperty::get_tooltip_text);
@ -646,7 +720,8 @@ void EditorProperty::_bind_methods() {
ADD_SIGNAL(MethodInfo("multiple_properties_changed", PropertyInfo(Variant::POOL_STRING_ARRAY, "properties"), PropertyInfo(Variant::ARRAY, "value")));
ADD_SIGNAL(MethodInfo("property_keyed", PropertyInfo(Variant::STRING, "property")));
ADD_SIGNAL(MethodInfo("property_keyed_with_value", PropertyInfo(Variant::STRING, "property"), PropertyInfo(Variant::NIL, "value", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NIL_IS_VARIANT)));
ADD_SIGNAL(MethodInfo("property_checked", PropertyInfo(Variant::STRING, "property"), PropertyInfo(Variant::STRING, "bool")));
ADD_SIGNAL(MethodInfo("property_checked", PropertyInfo(Variant::STRING, "property"), PropertyInfo(Variant::BOOL, "checked")));
ADD_SIGNAL(MethodInfo("property_pinned", PropertyInfo(Variant::STRING, "property"), PropertyInfo(Variant::BOOL, "pinned")));
ADD_SIGNAL(MethodInfo("resource_selected", PropertyInfo(Variant::STRING, "path"), PropertyInfo(Variant::OBJECT, "resource", PROPERTY_HINT_RESOURCE_TYPE, "Resource")));
ADD_SIGNAL(MethodInfo("object_id_selected", PropertyInfo(Variant::STRING, "property"), PropertyInfo(Variant::INT, "id")));
ADD_SIGNAL(MethodInfo("selected", PropertyInfo(Variant::STRING, "path"), PropertyInfo(Variant::INT, "focusable_idx")));
@ -654,6 +729,8 @@ void EditorProperty::_bind_methods() {
MethodInfo vm;
vm.name = "update_property";
BIND_VMETHOD(vm);
ClassDB::bind_method(D_METHOD("_update_revert_and_pin_status"), &EditorProperty::update_revert_and_pin_status);
}
EditorProperty::EditorProperty() {
@ -671,13 +748,47 @@ EditorProperty::EditorProperty() {
revert_hover = false;
check_hover = false;
can_revert = false;
can_pin = false;
pin_hidden = false;
is_pinned = false;
use_folding = false;
property_usage = 0;
selected = false;
selected_focusable = -1;
label_reference = nullptr;
bottom_editor = nullptr;
menu = nullptr;
}
void EditorProperty::_update_popup() {
if (menu) {
menu->clear();
} else {
menu = memnew(PopupMenu);
add_child(menu);
menu->connect("id_pressed", this, "_menu_option");
}
if (!pin_hidden) {
if (can_pin) {
menu->add_check_item(TTR("Pin value"), MENU_PIN_VALUE);
menu->set_item_checked(menu->get_item_index(MENU_PIN_VALUE), is_pinned);
menu->set_item_tooltip(menu->get_item_index(MENU_PIN_VALUE), TTR("Pinning a value forces it to be saved even if it's equal to the default."));
} else {
menu->add_check_item(vformat(TTR("Pin value [Disabled because '%s' is editor-only]"), property), MENU_PIN_VALUE);
menu->set_item_disabled(menu->get_item_index(MENU_PIN_VALUE), true);
}
}
}
void EditorProperty::_menu_option(int p_option) {
switch (p_option) {
case MENU_PIN_VALUE: {
emit_signal("property_pinned", property, !is_pinned);
update();
} break;
}
}
////////////////////////////////////////////////
////////////////////////////////////////////////
@ -1142,6 +1253,7 @@ void EditorInspector::_parse_added_editors(VBoxContainer *current_vbox, Ref<Edit
ep->connect("property_keyed", this, "_property_keyed");
ep->connect("property_keyed_with_value", this, "_property_keyed_with_value");
ep->connect("property_checked", this, "_property_checked");
ep->connect("property_pinned", this, "_property_pinned");
ep->connect("selected", this, "_property_selected");
ep->connect("multiple_properties_changed", this, "_multiple_properties_changed");
ep->connect("resource_selected", this, "_resource_selected", varray(), CONNECT_DEFERRED);
@ -1170,7 +1282,8 @@ void EditorInspector::_parse_added_editors(VBoxContainer *current_vbox, Ref<Edit
ep->set_read_only(read_only);
ep->update_property();
ep->update_reload_status();
ep->_update_pin_flags();
ep->update_revert_and_pin_status();
}
}
ped->added_editors.clear();
@ -1566,6 +1679,7 @@ void EditorInspector::update_tree() {
ep->connect("property_keyed", this, "_property_keyed");
ep->connect("property_keyed_with_value", this, "_property_keyed_with_value");
ep->connect("property_checked", this, "_property_checked");
ep->connect("property_pinned", this, "_property_pinned");
ep->connect("selected", this, "_property_selected");
ep->connect("multiple_properties_changed", this, "_multiple_properties_changed");
ep->connect("resource_selected", this, "_resource_selected", varray(), CONNECT_DEFERRED);
@ -1576,7 +1690,8 @@ void EditorInspector::update_tree() {
ep->set_tooltip(property_prefix + p.name);
}
ep->update_property();
ep->update_reload_status();
ep->_update_pin_flags();
ep->update_revert_and_pin_status();
if (current_selected && ep->property == current_selected) {
ep->select(current_focusable);
@ -1605,7 +1720,7 @@ void EditorInspector::update_property(const String &p_prop) {
for (List<EditorProperty *>::Element *E = editor_property_map[p_prop].front(); E; E = E->next()) {
E->get()->update_property();
E->get()->update_reload_status();
E->get()->update_revert_and_pin_status();
}
}
@ -1844,7 +1959,7 @@ void EditorInspector::_edit_set(const String &p_name, const Variant &p_value, bo
if (editor_property_map.has(p_name)) {
for (List<EditorProperty *>::Element *E = editor_property_map[p_name].front(); E; E = E->next()) {
E->get()->update_reload_status();
E->get()->update_revert_and_pin_status();
}
}
}
@ -1935,7 +2050,7 @@ void EditorInspector::_property_checked(const String &p_path, bool p_checked) {
if (editor_property_map.has(p_path)) {
for (List<EditorProperty *>::Element *E = editor_property_map[p_path].front(); E; E = E->next()) {
E->get()->update_property();
E->get()->update_reload_status();
E->get()->update_revert_and_pin_status();
}
}
@ -1944,6 +2059,35 @@ void EditorInspector::_property_checked(const String &p_path, bool p_checked) {
}
}
void EditorInspector::_property_pinned(const String &p_path, bool p_pinned) {
if (!object) {
return;
}
Node *node = Object::cast_to<Node>(object);
ERR_FAIL_COND(!node);
if (undo_redo) {
undo_redo->create_action(vformat(p_pinned ? TTR("Pinned %s") : TTR("Unpinned %s"), p_path));
undo_redo->add_do_method(node, "_set_property_pinned", p_path, p_pinned);
undo_redo->add_undo_method(node, "_set_property_pinned", p_path, !p_pinned);
if (editor_property_map.has(p_path)) {
for (List<EditorProperty *>::Element *E = editor_property_map[p_path].front(); E; E = E->next()) {
undo_redo->add_do_method(E->get(), "_update_revert_and_pin_status");
undo_redo->add_undo_method(E->get(), "_update_revert_and_pin_status");
}
}
undo_redo->commit_action();
} else {
node->set_property_pinned(p_path, p_pinned);
if (editor_property_map.has(p_path)) {
for (List<EditorProperty *>::Element *E = editor_property_map[p_path].front(); E; E = E->next()) {
E->get()->update_revert_and_pin_status();
}
}
}
}
void EditorInspector::_property_selected(const String &p_path, int p_focusable) {
property_selected = p_path;
property_focusable = p_focusable;
@ -2008,7 +2152,7 @@ void EditorInspector::_notification(int p_what) {
for (Map<StringName, List<EditorProperty *>>::Element *F = editor_property_map.front(); F; F = F->next()) {
for (List<EditorProperty *>::Element *E = F->get().front(); E; E = E->next()) {
E->get()->update_property();
E->get()->update_reload_status();
E->get()->update_revert_and_pin_status();
}
}
}
@ -2027,7 +2171,7 @@ void EditorInspector::_notification(int p_what) {
if (editor_property_map.has(prop)) {
for (List<EditorProperty *>::Element *E = editor_property_map[prop].front(); E; E = E->next()) {
E->get()->update_property();
E->get()->update_reload_status();
E->get()->update_revert_and_pin_status();
}
}
pending.erase(pending.front());
@ -2090,6 +2234,7 @@ void EditorInspector::_bind_methods() {
ClassDB::bind_method("_property_keyed", &EditorInspector::_property_keyed);
ClassDB::bind_method("_property_keyed_with_value", &EditorInspector::_property_keyed_with_value);
ClassDB::bind_method("_property_checked", &EditorInspector::_property_checked);
ClassDB::bind_method("_property_pinned", &EditorInspector::_property_pinned);
ClassDB::bind_method("_property_selected", &EditorInspector::_property_selected);
ClassDB::bind_method("_resource_selected", &EditorInspector::_resource_selected);
ClassDB::bind_method("_object_id_selected", &EditorInspector::_object_id_selected);

View File

@ -50,6 +50,11 @@ public:
class EditorProperty : public Container {
GDCLASS(EditorProperty, Container);
public:
enum MenuItems {
MENU_PIN_VALUE,
};
private:
String label;
int text_size;
@ -76,10 +81,15 @@ private:
bool check_hover;
bool can_revert;
bool can_pin;
bool pin_hidden;
bool is_pinned;
bool use_folding;
bool draw_top_bg;
void _update_popup();
void _menu_option(int p_option);
void _focusable_focused(int p_index);
bool selectable;
@ -91,9 +101,12 @@ private:
Vector<Control *> focusables;
Control *label_reference;
Control *bottom_editor;
PopupMenu *menu;
mutable String tooltip_text;
void _update_pin_flags();
protected:
void _notification(int p_what);
static void _bind_methods();
@ -115,7 +128,7 @@ public:
StringName get_edited_property();
virtual void update_property();
void update_reload_status();
void update_revert_and_pin_status();
virtual bool use_keying_next() const;
@ -305,8 +318,8 @@ class EditorInspector : public ScrollContainer {
void _multiple_properties_changed(Vector<String> p_paths, Array p_values);
void _property_keyed(const String &p_path, bool p_advance);
void _property_keyed_with_value(const String &p_path, const Variant &p_value, bool p_advance);
void _property_checked(const String &p_path, bool p_checked);
void _property_pinned(const String &p_path, bool p_pinned);
void _resource_selected(const String &p_path, RES p_resource);
void _property_selected(const String &p_path, int p_focusable);

View File

@ -3588,7 +3588,7 @@ Error EditorNode::load_scene(const String &p_scene, bool p_ignore_broken_deps, b
sdata->set_path(lpath, true); //take over path
}
Node *new_scene = sdata->instance(PackedScene::GEN_EDIT_STATE_MAIN);
Node *new_scene = sdata->instance(p_set_inherited ? PackedScene::GEN_EDIT_STATE_MAIN_INHERITED : PackedScene::GEN_EDIT_STATE_MAIN);
if (!new_scene) {
sdata.unref();

View File

@ -439,6 +439,16 @@ void Node2D::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "z_as_relative"), "set_z_as_relative", "is_z_relative");
}
#ifdef TOOLS_ENABLED
StringName Node2D::get_property_store_alias(const StringName &p_property) const {
if (p_property == "rotation_degrees") {
return "rotation";
} else {
return Node::get_property_store_alias(p_property);
}
}
#endif
Node2D::Node2D() {
angle = 0;
_scale = Vector2(1, 1);

View File

@ -116,6 +116,10 @@ public:
Transform2D get_transform() const;
#ifdef TOOLS_ENABLED
virtual StringName get_property_store_alias(const StringName &p_property) const;
#endif
Node2D();
};

View File

@ -306,6 +306,16 @@ void CanvasLayer::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::REAL, "follow_viewport_scale", PROPERTY_HINT_RANGE, "0.001,1000,0.001,or_greater,or_lesser"), "set_follow_viewport_scale", "get_follow_viewport_scale");
}
#ifdef TOOLS_ENABLED
StringName CanvasLayer::get_property_store_alias(const StringName &p_property) const {
if (p_property == "rotation_degrees") {
return "rotation";
} else {
return Node::get_property_store_alias(p_property);
}
}
#endif
CanvasLayer::CanvasLayer() {
vp = nullptr;
scale = Vector2(1, 1);

View File

@ -102,6 +102,10 @@ public:
RID get_canvas() const;
#ifdef TOOLS_ENABLED
StringName get_property_store_alias(const StringName &p_property) const;
#endif
CanvasLayer();
~CanvasLayer();
};

View File

@ -1866,6 +1866,56 @@ Node *Node::get_deepest_editable_node(Node *p_start_node) const {
return node;
}
#ifdef TOOLS_ENABLED
void Node::set_property_pinned(const StringName &p_property, bool p_pinned) {
bool current_pinned = false;
bool has_pinned = has_meta("_edit_pinned_properties_");
Array pinned;
String psa = get_property_store_alias(p_property);
if (has_pinned) {
pinned = get_meta("_edit_pinned_properties_");
current_pinned = pinned.has(psa);
}
if (current_pinned != p_pinned) {
if (p_pinned) {
pinned.append(psa);
if (!has_pinned) {
set_meta("_edit_pinned_properties_", pinned);
}
} else {
pinned.erase(psa);
if (pinned.empty()) {
remove_meta("_edit_pinned_properties_");
}
}
}
}
bool Node::is_property_pinned(const StringName &p_property) const {
if (!has_meta("_edit_pinned_properties_")) {
return false;
}
Array pinned = get_meta("_edit_pinned_properties_");
String psa = get_property_store_alias(p_property);
return pinned.has(psa);
}
StringName Node::get_property_store_alias(const StringName &p_property) const {
return p_property;
}
#endif
void Node::get_storable_properties(Set<StringName> &r_storable_properties) const {
List<PropertyInfo> pi;
get_property_list(&pi);
for (List<PropertyInfo>::Element *E = pi.front(); E; E = E->next()) {
if ((E->get().usage & PROPERTY_USAGE_STORAGE)) {
r_storable_properties.insert(E->get().name);
}
}
}
String Node::to_string() {
if (get_script_instance()) {
bool valid;
@ -2811,6 +2861,10 @@ void Node::_bind_methods() {
ClassDB::bind_method(D_METHOD("_get_import_path"), &Node::get_import_path);
ADD_PROPERTY(PropertyInfo(Variant::NODE_PATH, "_import_path", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL), "_set_import_path", "_get_import_path");
#ifdef TOOLS_ENABLED
ClassDB::bind_method(D_METHOD("_set_property_pinned", "property", "pinned"), &Node::set_property_pinned);
#endif
{
MethodInfo mi;

View File

@ -314,6 +314,13 @@ public:
bool is_editable_instance(const Node *p_node) const;
Node *get_deepest_editable_node(Node *start_node) const;
#ifdef TOOLS_ENABLED
void set_property_pinned(const StringName &p_property, bool p_pinned);
bool is_property_pinned(const StringName &p_property) const;
virtual StringName get_property_store_alias(const StringName &p_property) const;
#endif
void get_storable_properties(Set<StringName> &r_storable_properties) const;
virtual String to_string();
/* NOTIFICATIONS */

View File

@ -47,6 +47,30 @@ bool SceneState::can_instance() 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.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.empty()) {
p_node->remove_meta("_edit_pinned_properties_");
}
return pinned;
}
Node *SceneState::instance(GenEditState p_edit_state) const {
// nodes where instancing failed (because something is missing)
List<Node *> stray_instances;
@ -227,7 +251,7 @@ Node *SceneState::instance(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;
@ -291,6 +315,13 @@ Node *SceneState::instance(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]) {
@ -440,22 +471,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 (List<PropertyInfo>::Element *E = plist.front(); E; E = E->next()) {
if (!(E->get().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->get().usage & PROPERTY_USAGE_NO_INSTANCE_STATE) || E->get().name == "__meta__")) {
continue;
if (states_stack.size()) {
if ((E->get().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->get().name == "__meta__") {
if (pinned_props.size()) {
Dictionary meta_override;
meta_override["_edit_pinned_properties_"] = pinned_props;
forced_value = meta_override;
}
}
}
String name = E->get().name;
Variant value = p_node->get(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;
@ -1504,6 +1551,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() {
@ -1594,6 +1642,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() {

View File

@ -110,6 +110,7 @@ public:
GEN_EDIT_STATE_DISABLED,
GEN_EDIT_STATE_INSTANCE,
GEN_EDIT_STATE_MAIN,
GEN_EDIT_STATE_MAIN_INHERITED,
};
struct PackState {
@ -207,6 +208,7 @@ public:
GEN_EDIT_STATE_DISABLED,
GEN_EDIT_STATE_INSTANCE,
GEN_EDIT_STATE_MAIN,
GEN_EDIT_STATE_MAIN_INHERITED,
};
Error pack(Node *p_scene);