Explorar o código

Script-class-aware Inspector & related controls.

willnationsdev %!s(int64=3) %!d(string=hai) anos
pai
achega
d32f2700ff
Modificáronse 2 ficheiros con 92 adicións e 55 borrados
  1. 91 55
      editor/editor_resource_picker.cpp
  2. 1 0
      editor/editor_resource_picker.h

+ 91 - 55
editor/editor_resource_picker.cpp

@@ -53,6 +53,7 @@ void EditorResourcePicker::_update_resource() {
 	if (edited_resource.is_valid() && edited_resource->get_path().is_resource_file()) {
 		resource_path = edited_resource->get_path() + "\n";
 	}
+	String class_name = _get_resource_type(edited_resource);
 
 	if (preview_rect) {
 		preview_rect->set_texture(Ref<Texture2D>());
@@ -64,16 +65,20 @@ void EditorResourcePicker::_update_resource() {
 			assign_button->set_text(TTR("<empty>"));
 			assign_button->set_tooltip_text("");
 		} else {
-			assign_button->set_icon(EditorNode::get_singleton()->get_object_icon(edited_resource.operator->(), "Object"));
+			assign_button->set_icon(EditorNode::get_singleton()->get_object_icon(edited_resource.operator->(), SNAME("Object")));
 
 			if (!edited_resource->get_name().is_empty()) {
 				assign_button->set_text(edited_resource->get_name());
 			} else if (edited_resource->get_path().is_resource_file()) {
 				assign_button->set_text(edited_resource->get_path().get_file());
 			} else {
-				assign_button->set_text(edited_resource->get_class());
+				assign_button->set_text(class_name);
 			}
-			assign_button->set_tooltip_text(resource_path + TTR("Type:") + " " + edited_resource->get_class());
+
+			if (edited_resource->get_path().is_resource_file()) {
+				resource_path = edited_resource->get_path() + "\n";
+			}
+			assign_button->set_tooltip_text(resource_path + TTR("Type:") + " " + class_name);
 
 			// Preview will override the above, so called at the end.
 			EditorResourcePreview::get_singleton()->queue_edited_resource_preview(edited_resource, this, "_update_resource_preview", edited_resource->get_instance_id());
@@ -134,16 +139,29 @@ void EditorResourcePicker::_file_selected(const String &p_path) {
 	if (!base_type.is_empty()) {
 		bool any_type_matches = false;
 
+		String res_type = loaded_resource->get_class();
+		Ref<Script> res_script = loaded_resource->get_script();
+		bool is_global_class = false;
+		if (res_script.is_valid()) {
+			String script_type = EditorNode::get_editor_data().script_class_get_name(res_script->get_path());
+			if (!script_type.is_empty()) {
+				is_global_class = true;
+				res_type = script_type;
+			}
+		}
+
 		for (int i = 0; i < base_type.get_slice_count(","); i++) {
 			String base = base_type.get_slice(",", i);
-			if (loaded_resource->is_class(base)) {
-				any_type_matches = true;
+
+			any_type_matches = is_global_class ? EditorNode::get_editor_data().script_class_is_parent(res_type, base) : loaded_resource->is_class(base);
+
+			if (!any_type_matches) {
 				break;
 			}
 		}
 
 		if (!any_type_matches) {
-			EditorNode::get_singleton()->show_warning(vformat(TTR("The selected resource (%s) does not match any type expected for this property (%s)."), loaded_resource->get_class(), base_type));
+			EditorNode::get_singleton()->show_warning(vformat(TTR("The selected resource (%s) does not match any type expected for this property (%s)."), res_type, base_type));
 			return;
 		}
 	}
@@ -227,16 +245,19 @@ void EditorResourcePicker::_update_menu_items() {
 	// Add options to copy/paste resource.
 	Ref<Resource> cb = EditorSettings::get_singleton()->get_resource_clipboard();
 	bool paste_valid = false;
-	if (is_editable()) {
-		if (cb.is_valid()) {
-			if (base_type.is_empty()) {
-				paste_valid = true;
-			} else {
-				for (int i = 0; i < base_type.get_slice_count(","); i++) {
-					if (ClassDB::is_parent_class(cb->get_class(), base_type.get_slice(",", i))) {
-						paste_valid = true;
-						break;
-					}
+	if (is_editable() && cb.is_valid()) {
+		if (base_type.is_empty()) {
+			paste_valid = true;
+		} else {
+			String res_type = _get_resource_type(cb);
+
+			for (int i = 0; i < base_type.get_slice_count(","); i++) {
+				String base = base_type.get_slice(",", i);
+
+				paste_valid = ClassDB::is_parent_class(res_type, base) || EditorNode::get_editor_data().script_class_is_parent(res_type, base);
+
+				if (!paste_valid) {
+					break;
 				}
 			}
 		}
@@ -281,6 +302,9 @@ void EditorResourcePicker::_edit_menu_cbk(int p_which) {
 			for (int i = 0; i < base_type.get_slice_count(","); i++) {
 				String base = base_type.get_slice(",", i);
 				ResourceLoader::get_recognized_extensions_for_type(base, &extensions);
+				if (ScriptServer::is_global_class(base)) {
+					ResourceLoader::get_recognized_extensions_for_type(ScriptServer::get_global_class_native_base(base), &extensions);
+				}
 			}
 
 			HashSet<String> valid_extensions;
@@ -408,13 +432,7 @@ void EditorResourcePicker::_edit_menu_cbk(int p_which) {
 			Variant obj;
 
 			if (ScriptServer::is_global_class(intype)) {
-				obj = ClassDB::instantiate(ScriptServer::get_global_class_native_base(intype));
-				if (obj) {
-					Ref<Script> script = ResourceLoader::load(ScriptServer::get_global_class_path(intype));
-					if (script.is_valid()) {
-						((Object *)obj)->set_script(script);
-					}
-				}
+				obj = EditorNode::get_editor_data().script_class_instance(intype);
 			} else {
 				obj = ClassDB::instantiate(intype);
 			}
@@ -512,23 +530,40 @@ void EditorResourcePicker::_button_draw() {
 void EditorResourcePicker::_button_input(const Ref<InputEvent> &p_event) {
 	Ref<InputEventMouseButton> mb = p_event;
 
-	if (mb.is_valid()) {
-		if (mb->is_pressed() && mb->get_button_index() == MouseButton::RIGHT) {
-			// Only attempt to update and show the menu if we have
-			// a valid resource or the Picker is editable, as
-			// there will otherwise be nothing to display.
-			if (edited_resource.is_valid() || is_editable()) {
-				_update_menu_items();
-
-				Vector2 pos = get_screen_position() + mb->get_position();
-				edit_menu->reset_size();
-				edit_menu->set_position(pos);
-				edit_menu->popup();
-			}
+	if (mb.is_valid() && mb->is_pressed() && mb->get_button_index() == MouseButton::RIGHT) {
+		// Only attempt to update and show the menu if we have
+		// a valid resource or the Picker is editable, as
+		// there will otherwise be nothing to display.
+		if (edited_resource.is_valid() || is_editable()) {
+			_update_menu_items();
+
+			Vector2 pos = get_screen_position() + mb->get_position();
+			edit_menu->reset_size();
+			edit_menu->set_position(pos);
+			edit_menu->popup();
 		}
 	}
 }
 
+String EditorResourcePicker::_get_resource_type(const Ref<Resource> &p_resource) const {
+	if (p_resource.is_null()) {
+		return String();
+	}
+	String res_type = p_resource->get_class();
+
+	Ref<Script> res_script = p_resource->get_script();
+	if (res_script.is_null()) {
+		return res_type;
+	}
+
+	// TODO: Replace with EditorFileSystem when PR #60606 is merged to use cached resource type.
+	String script_type = EditorNode::get_editor_data().script_class_get_name(res_script->get_path());
+	if (!script_type.is_empty()) {
+		res_type = script_type;
+	}
+	return res_type;
+}
+
 void EditorResourcePicker::_get_allowed_types(bool p_with_convert, HashSet<String> *p_vector) const {
 	Vector<String> allowed_types = base_type.split(",");
 	int size = allowed_types.size();
@@ -550,7 +585,9 @@ void EditorResourcePicker::_get_allowed_types(bool p_with_convert, HashSet<Strin
 			List<StringName> allowed_subtypes;
 
 			List<StringName> inheriters;
-			ClassDB::get_inheriters_from_class(base, &inheriters);
+			if (!ScriptServer::is_global_class(base)) {
+				ClassDB::get_inheriters_from_class(base, &inheriters);
+			}
 			for (const StringName &subtype_name : inheriters) {
 				p_vector->insert(subtype_name);
 				allowed_subtypes.push_back(subtype_name);
@@ -602,32 +639,29 @@ bool EditorResourcePicker::_is_drop_valid(const Dictionary &p_drag_data) const {
 		}
 	} else if (drag_data.has("type") && String(drag_data["type"]) == "resource") {
 		res = drag_data["resource"];
+	} else if (drag_data.has("type") && String(drag_data["type"]) == "files") {
+		Vector<String> files = drag_data["files"];
+
+		// TODO: Extract the typename of the dropped filepath's resource in a more performant way, without fully loading it.
+		if (files.size() == 1) {
+			String file = files[0];
+			res = ResourceLoader::load(file);
+		}
 	}
 
 	HashSet<String> allowed_types;
 	_get_allowed_types(true, &allowed_types);
 
-	if (res.is_valid() && _is_type_valid(res->get_class(), allowed_types)) {
-		return true;
-	}
+	if (res.is_valid()) {
+		String res_type = _get_resource_type(res);
 
-	if (res.is_valid() && res->get_script()) {
-		StringName custom_class = EditorNode::get_singleton()->get_object_custom_type_name(res->get_script());
-		if (_is_type_valid(custom_class, allowed_types)) {
+		if (_is_type_valid(res_type, allowed_types)) {
 			return true;
 		}
-	}
-
-	if (drag_data.has("type") && String(drag_data["type"]) == "files") {
-		Vector<String> files = drag_data["files"];
-
-		if (files.size() == 1) {
-			String file = files[0];
 
-			String file_type = EditorFileSystem::get_singleton()->get_file_type(file);
-			if (!file_type.is_empty() && _is_type_valid(file_type, allowed_types)) {
-				return true;
-			}
+		StringName custom_class = EditorNode::get_singleton()->get_object_custom_type_name(res.ptr());
+		if (_is_type_valid(custom_class, allowed_types)) {
+			return true;
 		}
 	}
 
@@ -685,8 +719,10 @@ void EditorResourcePicker::drop_data_fw(const Point2 &p_point, const Variant &p_
 		HashSet<String> allowed_types;
 		_get_allowed_types(false, &allowed_types);
 
+		String res_type = _get_resource_type(dropped_resource);
+
 		// If the accepted dropped resource is from the extended list, it requires conversion.
-		if (!_is_type_valid(dropped_resource->get_class(), allowed_types)) {
+		if (!_is_type_valid(res_type, allowed_types)) {
 			for (const String &E : allowed_types) {
 				String at = E.strip_edges();
 

+ 1 - 0
editor/editor_resource_picker.h

@@ -91,6 +91,7 @@ class EditorResourcePicker : public HBoxContainer {
 	void _button_draw();
 	void _button_input(const Ref<InputEvent> &p_event);
 
+	String _get_resource_type(const Ref<Resource> &p_resource) const;
 	void _get_allowed_types(bool p_with_convert, HashSet<String> *p_vector) const;
 	bool _is_drop_valid(const Dictionary &p_drag_data) const;
 	bool _is_type_valid(const String p_type_name, HashSet<String> p_allowed_types) const;