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

Fix typed array export #73256

Merged
merged 1 commit into from
Apr 12, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
68 changes: 42 additions & 26 deletions editor/editor_properties_array_dict.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -38,34 +38,48 @@
#include "editor/gui/editor_spin_slider.h"
#include "editor/inspector_dock.h"
#include "scene/gui/button.h"
#include "scene/resources/packed_scene.h"

bool EditorPropertyArrayObject::_set(const StringName &p_name, const Variant &p_value) {
String name = p_name;

if (name.begins_with("indices")) {
int index = name.get_slicec('/', 1).to_int();
array.set(index, p_value);
return true;
if (!name.begins_with("indices") && !name.begins_with(PackedScene::META_POINTER_PROPERTY_BASE + "indices")) {
return false;
}

return false;
int index;
if (name.begins_with("metadata/")) {
index = name.get_slice("/", 2).to_int();
} else {
index = name.get_slice("/", 1).to_int();
}

array.set(index, p_value);
return true;
}

bool EditorPropertyArrayObject::_get(const StringName &p_name, Variant &r_ret) const {
String name = p_name;

if (name.begins_with("indices")) {
int index = name.get_slicec('/', 1).to_int();
bool valid;
r_ret = array.get(index, &valid);
if (r_ret.get_type() == Variant::OBJECT && Object::cast_to<EncodedObjectAsID>(r_ret)) {
r_ret = Object::cast_to<EncodedObjectAsID>(r_ret)->get_object_id();
}
if (!name.begins_with("indices") && !name.begins_with(PackedScene::META_POINTER_PROPERTY_BASE + "indices")) {
return false;
}

return valid;
int index;
if (name.begins_with("metadata/")) {
index = name.get_slice("/", 2).to_int();
} else {
index = name.get_slice("/", 1).to_int();
}

return false;
bool valid;
r_ret = array.get(index, &valid);

if (r_ret.get_type() == Variant::OBJECT && Object::cast_to<EncodedObjectAsID>(r_ret)) {
r_ret = Object::cast_to<EncodedObjectAsID>(r_ret)->get_object_id();
}

return valid;
}

void EditorPropertyArrayObject::set_array(const Variant &p_array) {
Expand Down Expand Up @@ -178,15 +192,22 @@ void EditorPropertyArray::initialize_array(Variant &p_array) {
}

void EditorPropertyArray::_property_changed(const String &p_property, Variant p_value, const String &p_name, bool p_changing) {
if (p_property.begins_with("indices")) {
int index = p_property.get_slice("/", 1).to_int();

Variant array = object->get_array().duplicate();
array.set(index, p_value);
if (!p_property.begins_with("indices") && !p_property.begins_with(PackedScene::META_POINTER_PROPERTY_BASE + "indices")) {
return;
}

object->set_array(array);
emit_changed(get_edited_property(), array, "", true);
int index;
if (p_property.begins_with("metadata/")) {
index = p_property.get_slice("/", 2).to_int();
} else {
index = p_property.get_slice("/", 1).to_int();
}

Array array;
array.assign(object->get_array().duplicate());
array.set(index, p_value);
object->set_array(array);
emit_changed(get_edited_property(), array, "", true);
}

void EditorPropertyArray::_change_type(Object *p_button, int p_index) {
Expand Down Expand Up @@ -690,11 +711,6 @@ EditorPropertyArray::EditorPropertyArray() {
add_child(edit);
add_focusable(edit);

container = nullptr;
property_vbox = nullptr;
size_slider = nullptr;
button_add_item = nullptr;
paginator = nullptr;
change_type = memnew(PopupMenu);
add_child(change_type);
change_type->connect("id_pressed", callable_mp(this, &EditorPropertyArray::_change_type_menu));
Expand Down
77 changes: 67 additions & 10 deletions scene/resources/packed_scene.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,9 @@
#include "scene/property_utils.h"

#define PACKED_SCENE_VERSION 3
#define META_POINTER_PROPERTY_BASE "metadata/_editor_prop_ptr_"

const String PackedScene::META_POINTER_PROPERTY_BASE = "metadata/_editor_prop_ptr_";

bool SceneState::can_instantiate() const {
return nodes.size() > 0;
}
Expand Down Expand Up @@ -239,15 +241,38 @@ Node *SceneState::instantiate(GenEditState p_edit_state) const {
if (nprops[j].name & FLAG_PATH_PROPERTY_IS_NODE) {
uint32_t name_idx = nprops[j].name & (FLAG_PATH_PROPERTY_IS_NODE - 1);
ERR_FAIL_UNSIGNED_INDEX_V(name_idx, (uint32_t)sname_count, nullptr);
if (Engine::get_singleton()->is_editor_hint()) {
// If editor, just set the metadata and be it
node->set(META_POINTER_PROPERTY_BASE + String(snames[name_idx]), props[nprops[j].value]);

const StringName &prop_name = snames[name_idx];
const Variant &prop_variant = props[nprops[j].value];

if (prop_variant.get_type() == Variant::ARRAY) {
if (Engine::get_singleton()->is_editor_hint()) {
// If editor, simply set the original array of NodePaths.
node->set(prop_name, prop_variant);
continue;
}

const Array &array = prop_variant;
for (int k = 0; k < array.size(); k++) {
DeferredNodePathProperties dnp;
dnp.path = array[k];
dnp.base = node;
// Use special property name to signify an array. This is only used in deferred_node_paths.
dnp.property = String(prop_name) + "/indices/" + itos(k);
deferred_node_paths.push_back(dnp);
}

} else {
if (Engine::get_singleton()->is_editor_hint()) {
// If editor, just set the metadata and be it.
node->set(PackedScene::META_POINTER_PROPERTY_BASE + String(prop_name), prop_variant);
continue;
}
// Do an actual deferred sed of the property path.
DeferredNodePathProperties dnp;
dnp.path = props[nprops[j].value];
dnp.path = prop_variant;
dnp.base = node;
dnp.property = snames[name_idx];
dnp.property = prop_name;
deferred_node_paths.push_back(dnp);
}
continue;
Expand Down Expand Up @@ -415,8 +440,26 @@ Node *SceneState::instantiate(GenEditState p_edit_state) const {
}

for (const DeferredNodePathProperties &dnp : deferred_node_paths) {
// Replace properties stored as NodePaths with actual Nodes.
Node *other = dnp.base->get_node_or_null(dnp.path);
dnp.base->set(dnp.property, other);

const String string_property = dnp.property;
if (string_property.contains("/indices/")) {
// For properties with "/indices/", the replacement takes place inside an Array.
const String base_property = string_property.get_slice("/", 0);
const int index = string_property.get_slice("/", 2).to_int();

Array array = dnp.base->get(base_property);
if (array.size() >= index) {
array.push_back(other);
} else {
array.set(index, other);
}

dnp.base->set(base_property, array);
} else {
dnp.base->set(dnp.property, other);
}
}

for (KeyValue<Ref<Resource>, Ref<Resource>> &E : resources_local_to_scene) {
Expand Down Expand Up @@ -584,7 +627,7 @@ Error SceneState::_parse_node(Node *p_owner, Node *p_node, int p_parent_idx, Has
if (E.name == META_PROPERTY_MISSING_RESOURCES) {
continue; // Ignore this property when packing.
}
if (E.name.begins_with(META_POINTER_PROPERTY_BASE)) {
if (E.name.begins_with(PackedScene::META_POINTER_PROPERTY_BASE)) {
continue; // do not save.
}

Expand All @@ -600,7 +643,7 @@ Error SceneState::_parse_node(Node *p_owner, Node *p_node, int p_parent_idx, Has
bool use_deferred_node_path_bit = false;

if (E.type == Variant::OBJECT && E.hint == PROPERTY_HINT_NODE_TYPE) {
value = p_node->get(META_POINTER_PROPERTY_BASE + E.name);
value = p_node->get(PackedScene::META_POINTER_PROPERTY_BASE + E.name);
if (value.get_type() != Variant::NODE_PATH) {
continue; //was never set, ignore.
}
Expand All @@ -611,6 +654,20 @@ Error SceneState::_parse_node(Node *p_owner, Node *p_node, int p_parent_idx, Has
if (ures.is_null()) {
value = missing_resource_properties[E.name];
}
} else if (E.type == Variant::ARRAY && E.hint == PROPERTY_HINT_TYPE_STRING) {
int hint_subtype_separator = E.hint_string.find(":");
if (hint_subtype_separator >= 0) {
String subtype_string = E.hint_string.substr(0, hint_subtype_separator);
int slash_pos = subtype_string.find("/");
PropertyHint subtype_hint = PropertyHint::PROPERTY_HINT_NONE;
if (slash_pos >= 0) {
subtype_hint = PropertyHint(subtype_string.get_slice("/", 1).to_int());
subtype_string = subtype_string.substr(0, slash_pos);
}
Variant::Type subtype = Variant::Type(subtype_string.to_int());

use_deferred_node_path_bit = subtype == Variant::OBJECT && subtype_hint == PROPERTY_HINT_NODE_TYPE;
}
}

if (!pinned_props.has(name)) {
Expand Down Expand Up @@ -1736,7 +1793,7 @@ void SceneState::add_editable_instance(const NodePath &p_path) {
}

String SceneState::get_meta_pointer_property(const String &p_property) {
return META_POINTER_PROPERTY_BASE + p_property;
return PackedScene::META_POINTER_PROPERTY_BASE + p_property;
}

Vector<String> SceneState::_get_node_groups(int p_idx) const {
Expand Down
2 changes: 2 additions & 0 deletions scene/resources/packed_scene.h
Original file line number Diff line number Diff line change
Expand Up @@ -221,6 +221,8 @@ class PackedScene : public Resource {
virtual void reset_state() override;

public:
static const String META_POINTER_PROPERTY_BASE;

enum GenEditState {
GEN_EDIT_STATE_DISABLED,
GEN_EDIT_STATE_INSTANCE,
Expand Down