Browse Source

Added properties and methods to allow for dragging and dropping multiple files onto exported arrays.

Eric M 5 years ago
parent
commit
b9d10c5743
2 changed files with 109 additions and 0 deletions
  1. 102 0
      editor/editor_properties_array_dict.cpp
  2. 7 0
      editor/editor_properties_array_dict.h

+ 102 - 0
editor/editor_properties_array_dict.cpp

@@ -412,8 +412,104 @@ void EditorPropertyArray::_remove_pressed(int p_index) {
 	update_property();
 	update_property();
 }
 }
 
 
+void EditorPropertyArray::_button_draw() {
+	if (dropping) {
+		Color color = get_theme_color("accent_color", "Editor");
+		edit->draw_rect(Rect2(Point2(), edit->get_size()), color, false);
+	}
+}
+
+bool EditorPropertyArray::_is_drop_valid(const Dictionary &p_drag_data) const {
+	String allowed_type = Variant::get_type_name(subtype);
+
+	Dictionary drag_data = p_drag_data;
+
+	if (drag_data.has("type") && String(drag_data["type"]) == "files") {
+
+		Vector<String> files = drag_data["files"];
+
+		for (int i = 0; i < files.size(); i++) {
+			String file = files[i];
+			String ftype = EditorFileSystem::get_singleton()->get_file_type(file);
+
+			for (int j = 0; j < allowed_type.get_slice_count(","); j++) {
+				String at = allowed_type.get_slice(",", j).strip_edges();
+				// Fail if one of the files is not of allowed type
+				if (!ClassDB::is_parent_class(ftype, at)) {
+					return false;
+				}
+			}
+		}
+
+		// If no files fail, drop is valid
+		return true;
+	}
+
+	return false;
+}
+
+bool EditorPropertyArray::can_drop_data_fw(const Point2 &p_point, const Variant &p_data, Control *p_from) const {
+
+	return _is_drop_valid(p_data);
+}
+
+void EditorPropertyArray::drop_data_fw(const Point2 &p_point, const Variant &p_data, Control *p_from) {
+	ERR_FAIL_COND(!_is_drop_valid(p_data));
+
+	Dictionary drag_data = p_data;
+
+	if (drag_data.has("type") && String(drag_data["type"]) == "files") {
+
+		Vector<String> files = drag_data["files"];
+
+		Variant array = object->get_array();
+
+		// Handle the case where array is not initialised yet
+		if (!array.is_array()) {
+			Callable::CallError ce;
+			array = Variant::construct(array_type, nullptr, 0, ce);
+		}
+
+		// Loop the file array and add to existing array
+		for (int i = 0; i < files.size(); i++) {
+			String file = files[i];
+
+			RES res = ResourceLoader::load(file);
+			if (res.is_valid()) {
+				array.call("push_back", res);
+			}
+		}
+
+		if (array.get_type() == Variant::ARRAY) {
+			array = array.call("duplicate");
+		}
+
+		emit_changed(get_edited_property(), array, "", false);
+		object->set_array(array);
+
+		update_property();
+	}
+}
+
 void EditorPropertyArray::_notification(int p_what) {
 void EditorPropertyArray::_notification(int p_what) {
+	if (p_what == NOTIFICATION_DRAG_BEGIN) {
+
+		if (is_visible_in_tree()) {
+			if (_is_drop_valid(get_viewport()->gui_get_drag_data())) {
+				dropping = true;
+				edit->update();
+			}
+		}
+	}
+
+	if (p_what == NOTIFICATION_DRAG_END) {
+		if (dropping) {
+			dropping = false;
+			edit->update();
+		}
+	}
 }
 }
+
 void EditorPropertyArray::_edit_pressed() {
 void EditorPropertyArray::_edit_pressed() {
 
 
 	Variant array = get_edited_object()->get(get_edited_property());
 	Variant array = get_edited_object()->get(get_edited_property());
@@ -490,6 +586,8 @@ void EditorPropertyArray::setup(Variant::Type p_array_type, const String &p_hint
 }
 }
 
 
 void EditorPropertyArray::_bind_methods() {
 void EditorPropertyArray::_bind_methods() {
+	ClassDB::bind_method(D_METHOD("can_drop_data_fw"), &EditorPropertyArray::can_drop_data_fw);
+	ClassDB::bind_method(D_METHOD("drop_data_fw"), &EditorPropertyArray::drop_data_fw);
 }
 }
 
 
 EditorPropertyArray::EditorPropertyArray() {
 EditorPropertyArray::EditorPropertyArray() {
@@ -503,6 +601,8 @@ EditorPropertyArray::EditorPropertyArray() {
 	edit->set_clip_text(true);
 	edit->set_clip_text(true);
 	edit->connect("pressed", callable_mp(this, &EditorPropertyArray::_edit_pressed));
 	edit->connect("pressed", callable_mp(this, &EditorPropertyArray::_edit_pressed));
 	edit->set_toggle_mode(true);
 	edit->set_toggle_mode(true);
+	edit->set_drag_forwarding(this);
+	edit->connect("draw", callable_mp(this, &EditorPropertyArray::_button_draw));
 	add_child(edit);
 	add_child(edit);
 	add_focusable(edit);
 	add_focusable(edit);
 	vbox = nullptr;
 	vbox = nullptr;
@@ -524,6 +624,8 @@ EditorPropertyArray::EditorPropertyArray() {
 	subtype = Variant::NIL;
 	subtype = Variant::NIL;
 	subtype_hint = PROPERTY_HINT_NONE;
 	subtype_hint = PROPERTY_HINT_NONE;
 	subtype_hint_string = "";
 	subtype_hint_string = "";
+
+	dropping = false;
 }
 }
 
 
 ///////////////////// DICTIONARY ///////////////////////////
 ///////////////////// DICTIONARY ///////////////////////////

+ 7 - 0
editor/editor_properties_array_dict.h

@@ -33,6 +33,7 @@
 
 
 #include "editor/editor_inspector.h"
 #include "editor/editor_inspector.h"
 #include "editor/editor_spin_slider.h"
 #include "editor/editor_spin_slider.h"
+#include "editor/filesystem_dock.h"
 #include "scene/gui/button.h"
 #include "scene/gui/button.h"
 
 
 class EditorPropertyArrayObject : public Reference {
 class EditorPropertyArrayObject : public Reference {
@@ -82,6 +83,7 @@ class EditorPropertyArray : public EditorProperty {
 
 
 	PopupMenu *change_type;
 	PopupMenu *change_type;
 	bool updating;
 	bool updating;
+	bool dropping;
 
 
 	Ref<EditorPropertyArrayObject> object;
 	Ref<EditorPropertyArrayObject> object;
 	int page_len;
 	int page_len;
@@ -107,6 +109,11 @@ class EditorPropertyArray : public EditorProperty {
 	void _object_id_selected(const StringName &p_property, ObjectID p_id);
 	void _object_id_selected(const StringName &p_property, ObjectID p_id);
 	void _remove_pressed(int p_index);
 	void _remove_pressed(int p_index);
 
 
+	void _button_draw();
+	bool _is_drop_valid(const Dictionary &p_drag_data) const;
+	bool can_drop_data_fw(const Point2 &p_point, const Variant &p_data, Control *p_from) const;
+	void drop_data_fw(const Point2 &p_point, const Variant &p_data, Control *p_from);
+
 protected:
 protected:
 	static void _bind_methods();
 	static void _bind_methods();
 	void _notification(int p_what);
 	void _notification(int p_what);