Browse Source

Add quad mesh to material preview

tetrapod00 1 year ago
parent
commit
6454ea4606

+ 1 - 0
editor/icons/MaterialPreviewQuad.svg

@@ -0,0 +1 @@
+<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16"><path fill="none" stroke="#000" stroke-linejoin="round" stroke-opacity=".8" stroke-width="2" d="m2 1 12 1v11l-12 1z"/><path fill="#f9f9f9" d="m2 14 12-1v-11l-12-1z"/></svg>

+ 73 - 20
editor/plugins/material_editor_plugin.cpp

@@ -56,9 +56,15 @@ void MaterialEditor::gui_input(const Ref<InputEvent> &p_event) {
 	if (mm.is_valid() && (mm->get_button_mask().has_flag(MouseButtonMask::LEFT))) {
 		rot.x -= mm->get_relative().y * 0.01;
 		rot.y -= mm->get_relative().x * 0.01;
-
-		rot.x = CLAMP(rot.x, -Math_PI / 2, Math_PI / 2);
+		if (quad_instance->is_visible()) {
+			// Clamp rotation so the quad is always visible.
+			const real_t limit = Math::deg_to_rad(80.0);
+			rot = rot.clampf(-limit, limit);
+		} else {
+			rot.x = CLAMP(rot.x, -Math_PI / 2, Math_PI / 2);
+		}
 		_update_rotation();
+		_store_rotation_metadata();
 	}
 }
 
@@ -70,6 +76,7 @@ void MaterialEditor::_update_theme_item_cache() {
 
 	theme_cache.sphere_icon = get_editor_theme_icon(SNAME("MaterialPreviewSphere"));
 	theme_cache.box_icon = get_editor_theme_icon(SNAME("MaterialPreviewCube"));
+	theme_cache.quad_icon = get_editor_theme_icon(SNAME("MaterialPreviewQuad"));
 
 	theme_cache.checkerboard = get_editor_theme_icon(SNAME("Checkerboard"));
 }
@@ -82,6 +89,7 @@ void MaterialEditor::_notification(int p_what) {
 
 			sphere_switch->set_button_icon(theme_cache.sphere_icon);
 			box_switch->set_button_icon(theme_cache.box_icon);
+			quad_switch->set_button_icon(theme_cache.quad_icon);
 
 			error_label->add_theme_color_override(SceneStringName(font_color), get_theme_color(SNAME("error_color"), EditorStringName(Editor)));
 		} break;
@@ -95,6 +103,18 @@ void MaterialEditor::_notification(int p_what) {
 	}
 }
 
+void MaterialEditor::_set_rotation(real_t p_x_degrees, real_t p_y_degrees) {
+	rot.x = Math::deg_to_rad(p_x_degrees);
+	rot.y = Math::deg_to_rad(p_y_degrees);
+	_update_rotation();
+}
+
+// Store the rotation so it can persist when switching between materials.
+void MaterialEditor::_store_rotation_metadata() {
+	Vector2 rotation_degrees = Vector2(Math::rad_to_deg(rot.x), Math::rad_to_deg(rot.y));
+	EditorSettings::get_singleton()->set_project_metadata("inspector_options", "material_preview_rotation", rotation_degrees);
+}
+
 void MaterialEditor::_update_rotation() {
 	Transform3D t;
 	t.basis.rotate(Vector3(0, 1, 0), -rot.y);
@@ -124,6 +144,7 @@ void MaterialEditor::edit(Ref<Material> p_material, const Ref<Environment> &p_en
 				vc->show();
 				sphere_instance->set_material_override(material);
 				box_instance->set_material_override(material);
+				quad_instance->set_material_override(material);
 				break;
 			default:
 				layout_error->show();
@@ -136,10 +157,6 @@ void MaterialEditor::edit(Ref<Material> p_material, const Ref<Environment> &p_en
 	} else {
 		hide();
 	}
-
-	rot.x = Math::deg_to_rad(-15.0);
-	rot.y = Math::deg_to_rad(30.0);
-	_update_rotation();
 }
 
 void MaterialEditor::_on_light_1_switch_pressed() {
@@ -151,19 +168,36 @@ void MaterialEditor::_on_light_2_switch_pressed() {
 }
 
 void MaterialEditor::_on_sphere_switch_pressed() {
-	box_instance->hide();
 	sphere_instance->show();
+	box_instance->hide();
+	quad_instance->hide();
 	box_switch->set_pressed(false);
-	sphere_switch->set_pressed(true);
-	EditorSettings::get_singleton()->set_project_metadata("inspector_options", "material_preview_on_sphere", true);
+	quad_switch->set_pressed(false);
+	_set_rotation(-15.0, 30.0);
+	_store_rotation_metadata();
+	EditorSettings::get_singleton()->set_project_metadata("inspector_options", "material_preview_mesh", "sphere");
 }
 
 void MaterialEditor::_on_box_switch_pressed() {
+	sphere_instance->hide();
 	box_instance->show();
+	quad_instance->hide();
+	sphere_switch->set_pressed(false);
+	quad_switch->set_pressed(false);
+	_set_rotation(-15.0, 30.0);
+	_store_rotation_metadata();
+	EditorSettings::get_singleton()->set_project_metadata("inspector_options", "material_preview_mesh", "box");
+}
+
+void MaterialEditor::_on_quad_switch_pressed() {
 	sphere_instance->hide();
-	box_switch->set_pressed(true);
+	box_instance->hide();
+	quad_instance->show();
 	sphere_switch->set_pressed(false);
-	EditorSettings::get_singleton()->set_project_metadata("inspector_options", "material_preview_on_sphere", false);
+	box_switch->set_pressed(false);
+	_set_rotation(0.0, 0.0);
+	_store_rotation_metadata();
+	EditorSettings::get_singleton()->set_project_metadata("inspector_options", "material_preview_mesh", "quad");
 }
 
 MaterialEditor::MaterialEditor() {
@@ -213,7 +247,7 @@ MaterialEditor::MaterialEditor() {
 	viewport = memnew(SubViewport);
 	Ref<World3D> world_3d;
 	world_3d.instantiate();
-	viewport->set_world_3d(world_3d); //use own world
+	viewport->set_world_3d(world_3d); // Use own world.
 	vc->add_child(viewport);
 	viewport->set_disable_input(true);
 	viewport->set_transparent_background(true);
@@ -221,7 +255,7 @@ MaterialEditor::MaterialEditor() {
 
 	camera = memnew(Camera3D);
 	camera->set_transform(Transform3D(Basis(), Vector3(0, 0, 1.1)));
-	// Use low field of view so the sphere/box is fully encompassed within the preview,
+	// Use low field of view so the sphere/box/quad is fully encompassed within the preview,
 	// without much distortion.
 	camera->set_perspective(20, 0.1, 10);
 	camera->make_current();
@@ -249,13 +283,19 @@ MaterialEditor::MaterialEditor() {
 	box_instance = memnew(MeshInstance3D);
 	rotation->add_child(box_instance);
 
-	box_instance->set_transform(Transform3D() * 0.25);
+	quad_instance = memnew(MeshInstance3D);
+	rotation->add_child(quad_instance);
+
 	sphere_instance->set_transform(Transform3D() * 0.375);
+	box_instance->set_transform(Transform3D() * 0.25);
+	quad_instance->set_transform(Transform3D() * 0.375);
 
 	sphere_mesh.instantiate();
 	sphere_instance->set_mesh(sphere_mesh);
 	box_mesh.instantiate();
 	box_instance->set_mesh(box_mesh);
+	quad_mesh.instantiate();
+	quad_instance->set_mesh(quad_mesh);
 
 	set_custom_minimum_size(Size2(1, 150) * EDSCALE);
 
@@ -269,17 +309,21 @@ MaterialEditor::MaterialEditor() {
 	sphere_switch = memnew(Button);
 	sphere_switch->set_theme_type_variation("PreviewLightButton");
 	sphere_switch->set_toggle_mode(true);
-	sphere_switch->set_pressed(true);
 	vb_shape->add_child(sphere_switch);
 	sphere_switch->connect(SceneStringName(pressed), callable_mp(this, &MaterialEditor::_on_sphere_switch_pressed));
 
 	box_switch = memnew(Button);
 	box_switch->set_theme_type_variation("PreviewLightButton");
 	box_switch->set_toggle_mode(true);
-	box_switch->set_pressed(false);
 	vb_shape->add_child(box_switch);
 	box_switch->connect(SceneStringName(pressed), callable_mp(this, &MaterialEditor::_on_box_switch_pressed));
 
+	quad_switch = memnew(Button);
+	quad_switch->set_theme_type_variation("PreviewLightButton");
+	quad_switch->set_toggle_mode(true);
+	vb_shape->add_child(quad_switch);
+	quad_switch->connect(SceneStringName(pressed), callable_mp(this, &MaterialEditor::_on_quad_switch_pressed));
+
 	layout_3d->add_spacer();
 
 	VBoxContainer *vb_light = memnew(VBoxContainer);
@@ -299,14 +343,23 @@ MaterialEditor::MaterialEditor() {
 	vb_light->add_child(light_2_switch);
 	light_2_switch->connect(SceneStringName(pressed), callable_mp(this, &MaterialEditor::_on_light_2_switch_pressed));
 
-	if (EditorSettings::get_singleton()->get_project_metadata("inspector_options", "material_preview_on_sphere", true)) {
+	String shape = EditorSettings::get_singleton()->get_project_metadata("inspector_options", "material_preview_mesh", "sphere");
+	if (shape == "sphere") {
 		box_instance->hide();
+		quad_instance->hide();
+		sphere_switch->set_pressed_no_signal(true);
+	} else if (shape == "box") {
+		sphere_instance->hide();
+		quad_instance->hide();
+		box_switch->set_pressed_no_signal(true);
 	} else {
-		box_instance->show();
 		sphere_instance->hide();
-		box_switch->set_pressed(true);
-		sphere_switch->set_pressed(false);
+		box_instance->hide();
+		quad_switch->set_pressed_no_signal(true);
 	}
+
+	Vector2 stored_rot = EditorSettings::get_singleton()->get_project_metadata("inspector_options", "material_preview_rotation", Vector2());
+	_set_rotation(stored_rot.x, stored_rot.y);
 }
 
 ///////////////////////

+ 7 - 0
editor/plugins/material_editor_plugin.h

@@ -62,6 +62,7 @@ class MaterialEditor : public Control {
 	Node3D *rotation = nullptr;
 	MeshInstance3D *sphere_instance = nullptr;
 	MeshInstance3D *box_instance = nullptr;
+	MeshInstance3D *quad_instance = nullptr;
 	DirectionalLight3D *light1 = nullptr;
 	DirectionalLight3D *light2 = nullptr;
 	Camera3D *camera = nullptr;
@@ -69,6 +70,7 @@ class MaterialEditor : public Control {
 
 	Ref<SphereMesh> sphere_mesh;
 	Ref<BoxMesh> box_mesh;
+	Ref<QuadMesh> quad_mesh;
 
 	VBoxContainer *layout_error = nullptr;
 	Label *error_label = nullptr;
@@ -80,6 +82,7 @@ class MaterialEditor : public Control {
 
 	Button *sphere_switch = nullptr;
 	Button *box_switch = nullptr;
+	Button *quad_switch = nullptr;
 	Button *light_1_switch = nullptr;
 	Button *light_2_switch = nullptr;
 
@@ -88,6 +91,7 @@ class MaterialEditor : public Control {
 		Ref<Texture2D> light_2_icon;
 		Ref<Texture2D> sphere_icon;
 		Ref<Texture2D> box_icon;
+		Ref<Texture2D> quad_icon;
 		Ref<Texture2D> checkerboard;
 	} theme_cache;
 
@@ -95,11 +99,14 @@ class MaterialEditor : public Control {
 	void _on_light_2_switch_pressed();
 	void _on_sphere_switch_pressed();
 	void _on_box_switch_pressed();
+	void _on_quad_switch_pressed();
 
 protected:
 	virtual void _update_theme_item_cache() override;
 	void _notification(int p_what);
 	void gui_input(const Ref<InputEvent> &p_event) override;
+	void _set_rotation(real_t p_x_degrees, real_t p_y_degrees);
+	void _store_rotation_metadata();
 	void _update_rotation();
 
 public:

+ 2 - 0
editor/themes/editor_color_map.cpp

@@ -173,6 +173,8 @@ void EditorColorMap::create() {
 	add_conversion_exception("OverbrightIndicator");
 	add_conversion_exception("MaterialPreviewCube");
 	add_conversion_exception("MaterialPreviewSphere");
+	add_conversion_exception("MaterialPreviewQuad");
+
 	add_conversion_exception("MaterialPreviewLight1");
 	add_conversion_exception("MaterialPreviewLight2");