Browse Source

Mesh instance UV2 unwrapping improvements:
Enforce foreign resource modification rules.
Add more helpful error handling for ArrayMesh unwrapping.

Saracen 1 năm trước cách đây
mục cha
commit
e865bad06a
2 tập tin đã thay đổi với 61 bổ sung31 xóa
  1. 5 9
      editor/editor_node.cpp
  2. 56 22
      editor/plugins/mesh_instance_3d_editor_plugin.cpp

+ 5 - 9
editor/editor_node.cpp

@@ -1279,11 +1279,9 @@ void EditorNode::save_resource_as(const Ref<Resource> &p_resource, const String
 					return;
 				}
 			}
-		} else {
-			if (FileAccess::exists(path + ".import")) {
-				show_warning(TTR("This resource can't be saved because it was imported from another file. Make it unique first."));
-				return;
-			}
+		} else if (FileAccess::exists(path + ".import")) {
+			show_warning(TTR("This resource can't be saved because it was imported from another file. Make it unique first."));
+			return;
 		}
 	}
 
@@ -4062,11 +4060,9 @@ bool EditorNode::is_resource_read_only(Ref<Resource> p_resource, bool p_foreign_
 				}
 			}
 		}
-	} else {
+	} else if (FileAccess::exists(path + ".import")) {
 		// The resource is not a subresource, but if it has an .import file, it's imported so treat it as read only.
-		if (FileAccess::exists(path + ".import")) {
-			return true;
-		}
+		return true;
 	}
 
 	return false;

+ 56 - 22
editor/plugins/mesh_instance_3d_editor_plugin.cpp

@@ -301,7 +301,40 @@ void MeshInstance3DEditor::_menu_option(int p_option) {
 			ur->commit_action();
 		} break;
 		case MENU_OPTION_CREATE_UV2: {
-			Ref<PrimitiveMesh> primitive_mesh = Object::cast_to<PrimitiveMesh>(*node->get_mesh());
+			Ref<Mesh> mesh2 = node->get_mesh();
+			if (!mesh.is_valid()) {
+				err_dialog->set_text(TTR("No mesh to unwrap."));
+				err_dialog->popup_centered();
+				return;
+			}
+
+			// Test if we are allowed to unwrap this mesh resource.
+			String path = mesh2->get_path();
+			int srpos = path.find("::");
+			if (srpos != -1) {
+				String base = path.substr(0, srpos);
+				if (ResourceLoader::get_resource_type(base) == "PackedScene") {
+					if (!get_tree()->get_edited_scene_root() || get_tree()->get_edited_scene_root()->get_scene_file_path() != base) {
+						err_dialog->set_text(TTR("Mesh cannot unwrap UVs because it does not belong to the edited scene. Make it unique first."));
+						err_dialog->popup_centered();
+						return;
+					}
+				} else {
+					if (FileAccess::exists(path + ".import")) {
+						err_dialog->set_text(TTR("Mesh cannot unwrap UVs because it belongs to another resource which was imported from another file type. Make it unique first."));
+						err_dialog->popup_centered();
+						return;
+					}
+				}
+			} else {
+				if (FileAccess::exists(path + ".import")) {
+					err_dialog->set_text(TTR("Mesh cannot unwrap UVs because it was imported from another file type. Make it unique first."));
+					err_dialog->popup_centered();
+					return;
+				}
+			}
+
+			Ref<PrimitiveMesh> primitive_mesh = mesh2;
 			if (primitive_mesh.is_valid()) {
 				EditorUndoRedoManager *ur = EditorUndoRedoManager::get_singleton();
 				ur->create_action(TTR("Unwrap UV2"));
@@ -309,39 +342,40 @@ void MeshInstance3DEditor::_menu_option(int p_option) {
 				ur->add_undo_method(*primitive_mesh, "set_add_uv2", primitive_mesh->get_add_uv2());
 				ur->commit_action();
 			} else {
-				Ref<ArrayMesh> mesh2 = node->get_mesh();
-				if (!mesh2.is_valid()) {
+				Ref<ArrayMesh> array_mesh = mesh2;
+				if (!array_mesh.is_valid()) {
 					err_dialog->set_text(TTR("Contained Mesh is not of type ArrayMesh."));
 					err_dialog->popup_centered();
 					return;
 				}
 
-				String path = mesh2->get_path();
-				int srpos = path.find("::");
-				if (srpos != -1) {
-					String base = path.substr(0, srpos);
-					if (ResourceLoader::get_resource_type(base) == "PackedScene") {
-						if (!get_tree()->get_edited_scene_root() || get_tree()->get_edited_scene_root()->get_scene_file_path() != base) {
-							err_dialog->set_text(TTR("Mesh cannot unwrap UVs because it does not belong to the edited scene. Make it unique first."));
+				// Preemptively evaluate common fail cases for lightmap unwrapping.
+				{
+					if (array_mesh->get_blend_shape_count() > 0) {
+						err_dialog->set_text(TTR("Can't unwrap mesh with blend shapes."));
+						err_dialog->popup_centered();
+						return;
+					}
+
+					for (int i = 0; i < array_mesh->get_surface_count(); i++) {
+						Mesh::PrimitiveType primitive = array_mesh->surface_get_primitive_type(i);
+
+						if (primitive != Mesh::PRIMITIVE_TRIANGLES) {
+							err_dialog->set_text(TTR("Only triangles are supported for lightmap unwrap."));
 							err_dialog->popup_centered();
 							return;
 						}
-					} else {
-						if (FileAccess::exists(path + ".import")) {
-							err_dialog->set_text(TTR("Mesh cannot unwrap UVs because it belongs to another resource which was imported from another file type. Make it unique first."));
+
+						uint64_t format = array_mesh->surface_get_format(i);
+						if (format & Mesh::ArrayFormat::ARRAY_FORMAT_NORMAL) {
+							err_dialog->set_text(TTR("Normals are required for lightmap unwrap."));
 							err_dialog->popup_centered();
 							return;
 						}
 					}
-				} else {
-					if (FileAccess::exists(path + ".import")) {
-						err_dialog->set_text(TTR("Mesh cannot unwrap UVs because it was imported from another file type. Make it unique first."));
-						err_dialog->popup_centered();
-						return;
-					}
 				}
 
-				Ref<ArrayMesh> unwrapped_mesh = mesh2->duplicate(false);
+				Ref<ArrayMesh> unwrapped_mesh = array_mesh->duplicate(false);
 
 				Error err = unwrapped_mesh->lightmap_unwrap(node->get_global_transform());
 				if (err != OK) {
@@ -355,9 +389,9 @@ void MeshInstance3DEditor::_menu_option(int p_option) {
 
 				ur->add_do_method(node, "set_mesh", unwrapped_mesh);
 				ur->add_do_reference(node);
-				ur->add_do_reference(mesh2.ptr());
+				ur->add_do_reference(array_mesh.ptr());
 
-				ur->add_undo_method(node, "set_mesh", mesh2);
+				ur->add_undo_method(node, "set_mesh", array_mesh);
 				ur->add_undo_reference(unwrapped_mesh.ptr());
 
 				ur->commit_action();