Repository: godotengine/godot
File: editor/plugins/texture_layered_editor_plugin.cpp (C++)

Code before:
	b.rotate(Vector3(1, 0, 0), x_rot);
	b.rotate(Vector3(0, 1, 0), y_rot);

	materials[1]->set_shader_parameter("normal", v);
	materials[1]->set_shader_parameter("rot", b);
	materials[2]->set_shader_parameter("normal", v);
	materials[2]->set_shader_parameter("rot", b);

	String format = Image::get_format_name(texture->get_format());

	String text;
	if (texture->get_layered_type() == TextureLayered::LAYERED_TYPE_2D_ARRAY) {
		text = itos(texture->get_width()) + "x" + itos(texture->get_height()) + " (x " + itos(texture->get_layers()) + ")" + format;
	} else if (texture->get_layered_type() == TextureLayered::LAYERED_TYPE_CUBEMAP) {
		text = itos(texture->get_width()) + "x" + itos(texture->get_height()) + " " + format;
	} else if (texture->get_layered_type() == TextureLayered::LAYERED_TYPE_CUBEMAP_ARRAY) {
		text = itos(texture->get_width()) + "x" + itos(texture->get_height()) + " (x " + itos(texture->get_layers() / 6) + ")" + format;
	}

	info->set_text(text);
}

void TextureLayeredEditor::_make_shaders() {
	shaders[0].instantiate();
	shaders[0]->set_code(R"(
// TextureLayeredEditor preview shader (2D array).

shader_type canvas_item;

uniform sampler2DArray tex;
uniform float layer;

void fragment() {
	COLOR = textureLod(tex, vec3(UV, layer), 0.0);
}
)");

	shaders[1].instantiate();
	shaders[1]->set_code(R"(
// TextureLayeredEditor preview shader (cubemap).

shader_type canvas_item;

uniform samplerCube tex;
uniform vec3 normal;
uniform mat3 rot;

void fragment() {
	vec3 n = rot * normalize(vec3(normal.xy * (UV * 2.0 - 1.0), normal.z));
	COLOR = textureLod(tex, n, 0.0);
}

Review comment (suggestion):
Use the Unicode multiplication symbol:

```suggestion
				info->set_text(vformat(String::utf8("%d×%d (×%d) %s\n") + TTR("%s Mipmaps") + "\n" + TTR("Memory: %s"),
```

Code after:

void TextureLayeredEditor::gui_input(const Ref<InputEvent> &p_event) {
	ERR_FAIL_COND(p_event.is_null());

	Ref<InputEventMouseMotion> mm = p_event;
	if (mm.is_valid() && (mm->get_button_mask().has_flag(MouseButtonMask::LEFT))) {
		y_rot += -mm->get_relative().x * 0.01;
		x_rot += -mm->get_relative().y * 0.01;

		_update_material(false);
	}
}

void TextureLayeredEditor::_texture_rect_draw() {
	texture_rect->draw_rect(Rect2(Point2(), texture_rect->get_size()), Color(1, 1, 1, 1));
}

void TextureLayeredEditor::_update_gui() {
	if (texture.is_null()) {
		return;
	}

	_texture_rect_update_area();

	const String format = Image::get_format_name(texture->get_format());
	String texture_info;

	switch (texture->get_layered_type()) {
		case TextureLayered::LAYERED_TYPE_2D_ARRAY: {
			layer->set_max(texture->get_layers() - 1);

			texture_info = vformat(String::utf8("%d×%d (×%d) %s\n"),
					texture->get_width(),
					texture->get_height(),
					texture->get_layers(),
					format);

		} break;
		case TextureLayered::LAYERED_TYPE_CUBEMAP: {
			layer->hide();

			texture_info = vformat(String::utf8("%d×%d %s\n"),
					texture->get_width(),
					texture->get_height(),
					format);

		} break;
		case TextureLayered::LAYERED_TYPE_CUBEMAP_ARRAY: {
			layer->set_max(texture->get_layers() / 6 - 1);

			texture_info = vformat(String::utf8("%d×%d (×%d) %s\n"),