From 1dc30dcc85e6ce1fc7173bf9aad65ac68a6704b0 Mon Sep 17 00:00:00 2001
From: tetrapod00 <145553014+tetrapod00@users.noreply.github.com>
Date: Sat, 14 Sep 2024 19:38:17 -0700
Subject: [PATCH] Add quad mesh to material preview
---
editor/icons/MaterialPreviewQuad.svg | 1 +
editor/plugins/material_editor_plugin.cpp | 92 ++++++++++++++++++-----
editor/plugins/material_editor_plugin.h | 6 ++
editor/themes/editor_color_map.cpp | 2 +
4 files changed, 84 insertions(+), 17 deletions(-)
create mode 100644 editor/icons/MaterialPreviewQuad.svg
diff --git a/editor/icons/MaterialPreviewQuad.svg b/editor/icons/MaterialPreviewQuad.svg
new file mode 100644
index 000000000000..bec8be950ab2
--- /dev/null
+++ b/editor/icons/MaterialPreviewQuad.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/editor/plugins/material_editor_plugin.cpp b/editor/plugins/material_editor_plugin.cpp
index 2702b6c90957..30ebe24423b0 100644
--- a/editor/plugins/material_editor_plugin.cpp
+++ b/editor/plugins/material_editor_plugin.cpp
@@ -56,8 +56,14 @@ void MaterialEditor::gui_input(const Ref &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.
+ // Magic numbers so that the range is a bit less than 90 degrees in either direction.
+ rot.x = CLAMP(rot.x, -Math_PI / 2.2, Math_PI / 2.2);
+ rot.y = CLAMP(rot.y, -Math_PI / 2.2, Math_PI / 2.2);
+ } else {
+ rot.x = CLAMP(rot.x, -Math_PI / 2, Math_PI / 2);
+ }
_update_rotation();
}
}
@@ -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_icon(theme_cache.sphere_icon);
box_switch->set_icon(theme_cache.box_icon);
+ quad_switch->set_icon(theme_cache.quad_icon);
error_label->add_theme_color_override(SceneStringName(font_color), get_theme_color(SNAME("error_color"), EditorStringName(Editor)));
} break;
@@ -95,11 +103,20 @@ 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();
+}
+
void MaterialEditor::_update_rotation() {
Transform3D t;
t.basis.rotate(Vector3(0, 1, 0), -rot.y);
t.basis.rotate(Vector3(1, 0, 0), -rot.x);
rotation->set_transform(t);
+ // Store the rotation so it can persist when switching between materials.
+ 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::edit(Ref p_material, const Ref &p_env) {
@@ -124,6 +141,7 @@ void MaterialEditor::edit(Ref p_material, const Ref &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 +154,6 @@ void MaterialEditor::edit(Ref p_material, const Ref &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 +165,36 @@ void MaterialEditor::_on_light_2_switch_pressed() {
}
void MaterialEditor::_on_sphere_switch_pressed() {
- box_instance->hide();
sphere_instance->show();
- box_switch->set_pressed(false);
+ box_instance->hide();
+ quad_instance->hide();
sphere_switch->set_pressed(true);
- EditorSettings::get_singleton()->set_project_metadata("inspector_options", "material_preview_on_sphere", true);
+ box_switch->set_pressed(false);
+ quad_switch->set_pressed(false);
+ _set_rotation(-15.0, 30.0);
+ EditorSettings::get_singleton()->set_project_metadata("inspector_options", "material_preview_mesh", "sphere");
}
void MaterialEditor::_on_box_switch_pressed() {
- box_instance->show();
sphere_instance->hide();
+ box_instance->show();
+ quad_instance->hide();
+ sphere_switch->set_pressed(false);
box_switch->set_pressed(true);
+ quad_switch->set_pressed(false);
+ _set_rotation(-15.0, 30.0);
+ EditorSettings::get_singleton()->set_project_metadata("inspector_options", "material_preview_mesh", "box");
+}
+
+void MaterialEditor::_on_quad_switch_pressed() {
+ sphere_instance->hide();
+ 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);
+ quad_switch->set_pressed(true);
+ _set_rotation(0.0, 0.0);
+ EditorSettings::get_singleton()->set_project_metadata("inspector_options", "material_preview_mesh", "quad");
}
MaterialEditor::MaterialEditor() {
@@ -213,7 +244,7 @@ MaterialEditor::MaterialEditor() {
viewport = memnew(SubViewport);
Ref 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 +252,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 +280,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.25);
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);
@@ -280,6 +317,13 @@ MaterialEditor::MaterialEditor() {
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);
+ quad_switch->set_pressed(false);
+ 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,28 @@ 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();
- } else {
- box_instance->show();
+ quad_instance->hide();
+ } else if (shape == "box") {
sphere_instance->hide();
+ box_instance->show();
+ quad_instance->hide();
+ sphere_switch->set_pressed(false);
box_switch->set_pressed(true);
+ quad_switch->set_pressed(false);
+ } else {
+ sphere_instance->hide();
+ box_instance->hide();
+ quad_instance->show();
sphere_switch->set_pressed(false);
+ box_switch->set_pressed(false);
+ quad_switch->set_pressed(true);
}
+
+ Vector2 stored_rot = EditorSettings::get_singleton()->get_project_metadata("inspector_options", "material_preview_rotation", Vector2());
+ _set_rotation(stored_rot.x, stored_rot.y);
}
///////////////////////
diff --git a/editor/plugins/material_editor_plugin.h b/editor/plugins/material_editor_plugin.h
index 28c59d27dba6..d2bd8a59160e 100644
--- a/editor/plugins/material_editor_plugin.h
+++ b/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 sphere_mesh;
Ref box_mesh;
+ Ref 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 light_2_icon;
Ref sphere_icon;
Ref box_icon;
+ Ref quad_icon;
Ref checkerboard;
} theme_cache;
@@ -95,11 +99,13 @@ 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 &p_event) override;
+ void _set_rotation(real_t p_x_degrees, real_t p_y_degrees);
void _update_rotation();
public:
diff --git a/editor/themes/editor_color_map.cpp b/editor/themes/editor_color_map.cpp
index 9046a8b688f0..3c3d755586dd 100644
--- a/editor/themes/editor_color_map.cpp
+++ b/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");