Forráskód Böngészése

Merge pull request #73256 from KoBeWi/OUR_pr

Fix typed array export
Rémi Verschelde 2 éve
szülő
commit
412721d51a

+ 42 - 26
editor/editor_properties_array_dict.cpp

@@ -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) {
@@ -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) {
@@ -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));

+ 67 - 10
scene/resources/packed_scene.cpp

@@ -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;
 }
@@ -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;
@@ -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) {
@@ -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.
 		}
 
@@ -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.
 			}
@@ -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)) {
@@ -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 {

+ 2 - 0
scene/resources/packed_scene.h

@@ -221,6 +221,8 @@ protected:
 	virtual void reset_state() override;
 
 public:
+	static const String META_POINTER_PROPERTY_BASE;
+
 	enum GenEditState {
 		GEN_EDIT_STATE_DISABLED,
 		GEN_EDIT_STATE_INSTANCE,