"""MaterialSection -- PBR material editing.
Registered with the section registry via @register_inspector_section at
import time.
"""
from simvx.core import (
CheckBox,
ColourPicker,
Control,
DropDown,
MeshInstance3D,
Slider,
Vec2,
)
from ._base import (
InspectorSection,
_font_size,
_make_property_row,
_make_resource_picker,
register_inspector_section,
)
[docs]
@register_inspector_section
class MaterialSection(InspectorSection):
section_title = "Material"
priority = 11
[docs]
def can_handle(self, node):
return isinstance(node, MeshInstance3D) and node.material is not None
[docs]
def build_rows(self, node, ctx):
mat = node.material
rows: list[Control] = []
# Colour
picker = ColourPicker()
picker.size = Vec2(200, 180)
picker.colour = mat.colour
picker.colour_changed.connect(lambda colour, c=ctx, n=node: c.on_material_colour_changed(n, colour))
colour_row = _make_property_row("Colour", picker)
colour_row.size = Vec2(300, 184)
rows.append(colour_row)
ctx.register_widget("mat_colour", picker)
# Metallic
metallic_slider = Slider(min_val=0.0, max_val=1.0, value=mat.metallic)
metallic_slider.step = 0.01
metallic_slider.value_changed.connect(
lambda val, c=ctx, n=node: c.on_material_prop_changed(n, "metallic", val))
rows.append(_make_property_row("Metallic", metallic_slider))
ctx.register_widget("mat_metallic", metallic_slider)
# Roughness
roughness_slider = Slider(min_val=0.0, max_val=1.0, value=mat.roughness)
roughness_slider.step = 0.01
roughness_slider.value_changed.connect(
lambda val, c=ctx, n=node: c.on_material_prop_changed(n, "roughness", val))
rows.append(_make_property_row("Roughness", roughness_slider))
ctx.register_widget("mat_roughness", roughness_slider)
# Blend mode
blend_modes = ["opaque", "alpha", "additive"]
blend_idx = blend_modes.index(mat.blend) if mat.blend in blend_modes else 0
blend_dd = DropDown(items=blend_modes, selected=blend_idx)
blend_dd.font_size = _font_size()
blend_dd.item_selected.connect(
lambda idx, c=ctx, n=node: c.on_material_prop_changed(n, "blend", blend_modes[idx]))
rows.append(_make_property_row("Blend", blend_dd))
ctx.register_widget("mat_blend", blend_dd)
# Wireframe
wire_cb = CheckBox("", checked=mat.wireframe)
wire_cb.toggled.connect(lambda checked, c=ctx, n=node: c.on_material_prop_changed(n, "wireframe", checked))
rows.append(_make_property_row("Wireframe", wire_cb))
ctx.register_widget("mat_wireframe", wire_cb)
# Unlit
unlit_cb = CheckBox("", checked=mat.unlit)
unlit_cb.toggled.connect(lambda checked, c=ctx, n=node: c.on_material_prop_changed(n, "unlit", checked))
rows.append(_make_property_row("Unlit", unlit_cb))
ctx.register_widget("mat_unlit", unlit_cb)
# Texture pickers
tex_filter = "*.png;*.jpg;*.jpeg;*.bmp;*.tga"
albedo_picker = _make_resource_picker(current_path=mat.albedo_uri, file_filter=tex_filter)
albedo_picker.file_selected.connect(
lambda path, c=ctx, n=node: c.on_material_texture_changed(n, "albedo_uri", path))
albedo_picker.cleared.connect(
lambda c=ctx, n=node: c.on_material_texture_changed(n, "albedo_uri", None))
rows.append(_make_property_row("Albedo Tex", albedo_picker))
ctx.register_widget("mat_albedo_tex", albedo_picker)
normal_picker = _make_resource_picker(current_path=mat.normal_uri, file_filter=tex_filter)
normal_picker.file_selected.connect(
lambda path, c=ctx, n=node: c.on_material_texture_changed(n, "normal_uri", path))
normal_picker.cleared.connect(
lambda c=ctx, n=node: c.on_material_texture_changed(n, "normal_uri", None))
rows.append(_make_property_row("Normal Map", normal_picker))
ctx.register_widget("mat_normal_tex", normal_picker)
return rows