228 lines
11 KiB
Python
228 lines
11 KiB
Python
from imgui_bundle import imgui, imgui_ctx
|
|
|
|
class EditorPanelsRightMaterialMixin:
|
|
"""Auto-split mixin from editor_panels_right.py."""
|
|
|
|
def _draw_appearance_properties(self, node):
|
|
"""绘制外观属性"""
|
|
# 颜色属性
|
|
if hasattr(node, 'getColor'):
|
|
imgui.text("颜色")
|
|
try:
|
|
color = node.getColor()
|
|
# 确保颜色是有效的
|
|
if not color or len(color) < 3:
|
|
color = (1.0, 1.0, 1.0, 1.0) # 默认白色
|
|
except:
|
|
color = (1.0, 1.0, 1.0, 1.0) # 默认白色
|
|
|
|
# 颜色滑块
|
|
changed, new_r = imgui.slider_float("R##color_r", color[0], 0.0, 1.0)
|
|
if changed:
|
|
new_color = (new_r, color[1], color[2], color[3] if len(color) > 3 else 1.0)
|
|
node.setColor(new_color)
|
|
color = new_color
|
|
|
|
changed, new_g = imgui.slider_float("G##color_g", color[1], 0.0, 1.0)
|
|
if changed:
|
|
new_color = (color[0], new_g, color[2], color[3] if len(color) > 3 else 1.0)
|
|
node.setColor(new_color)
|
|
color = new_color
|
|
|
|
changed, new_b = imgui.slider_float("B##color_b", color[2], 0.0, 1.0)
|
|
if changed:
|
|
new_color = (color[0], color[1], new_b, color[3] if len(color) > 3 else 1.0)
|
|
node.setColor(new_color)
|
|
color = new_color
|
|
|
|
# 只有当颜色有alpha通道时才显示alpha滑块
|
|
if len(color) > 3:
|
|
changed, new_a = imgui.slider_float("A##color_a", color[3], 0.0, 1.0)
|
|
if changed:
|
|
new_color = (color[0], color[1], color[2], new_a)
|
|
node.setColor(new_color)
|
|
color = new_color
|
|
|
|
# 颜色预览和选择器
|
|
imgui.text("颜色预览")
|
|
color_with_alpha = (color[0], color[1], color[2], color[3] if len(color) > 3 else 1.0)
|
|
if imgui.color_button("颜色预览##preview", color_with_alpha, 0, (100, 30)):
|
|
# 点击颜色按钮打开颜色选择器
|
|
self.show_color_picker(node, 'color', color_with_alpha)
|
|
|
|
imgui.same_line()
|
|
if imgui.button("选择颜色##color_picker_btn"):
|
|
self.show_color_picker(node, 'color', (color.x, color.y, color.z, color.w))
|
|
|
|
# 透明度
|
|
if hasattr(node, 'setTransparency') and hasattr(node, 'getTransparency'):
|
|
imgui.text("透明度")
|
|
current_transparency = node.getTransparency()
|
|
# 将当前的透明度值转换为0.0-1.0范围用于显示
|
|
display_transparency = 1.0 - current_transparency if current_transparency <= 1 else 0.0
|
|
changed, new_transparency = imgui.slider_float("透明度", display_transparency, 0.0, 1.0)
|
|
if changed:
|
|
# 将0.0-1.0范围转换回Panda3D的透明度格式
|
|
panda_transparency = int((1.0 - new_transparency) * 255)
|
|
node.setTransparency(panda_transparency)
|
|
|
|
# 材质属性
|
|
self._draw_material_properties(node)
|
|
|
|
# 渲染状态
|
|
imgui.text("渲染状态")
|
|
if imgui.button("应用材质"):
|
|
self._apply_material_to_node(node)
|
|
|
|
imgui.same_line()
|
|
if imgui.button("重置材质"):
|
|
self._reset_material(node)
|
|
|
|
def _draw_material_properties(self, node):
|
|
"""绘制材质属性"""
|
|
materials = node.find_all_materials()
|
|
|
|
if not materials:
|
|
imgui.text_colored((0.5, 0.5, 0.5, 1.0), "无材质")
|
|
return
|
|
|
|
for i, material in enumerate(materials):
|
|
material_name = material.get_name() if hasattr(material, 'get_name') and material.get_name() else f"材质{i + 1}"
|
|
|
|
if imgui.collapsing_header(f"材质: {material_name}"):
|
|
# 材质基础颜色
|
|
base_color = self._get_material_base_color(material)
|
|
if base_color:
|
|
imgui.text("基础颜色")
|
|
changed, new_r = imgui.slider_float(f"R##mat_r_{i}", base_color[0], 0.0, 1.0)
|
|
if changed:
|
|
self._update_material_base_color(material, 'r', new_r)
|
|
base_color = (new_r, base_color[1], base_color[2], base_color[3])
|
|
|
|
changed, new_g = imgui.slider_float(f"G##mat_g_{i}", base_color[1], 0.0, 1.0)
|
|
if changed:
|
|
self._update_material_base_color(material, 'g', new_g)
|
|
base_color = (base_color[0], new_g, base_color[2], base_color[3])
|
|
|
|
changed, new_b = imgui.slider_float(f"B##mat_b_{i}", base_color[2], 0.0, 1.0)
|
|
if changed:
|
|
self._update_material_base_color(material, 'b', new_b)
|
|
base_color = (base_color[0], base_color[1], new_b, base_color[3])
|
|
|
|
changed, new_a = imgui.slider_float(f"A##mat_a_{i}", base_color[3], 0.0, 1.0)
|
|
if changed:
|
|
self._update_material_base_color(material, 'a', new_a)
|
|
base_color = (base_color[0], base_color[1], base_color[2], new_a)
|
|
|
|
# PBR属性
|
|
if hasattr(material, 'roughness') and material.roughness is not None:
|
|
imgui.text("PBR属性")
|
|
try:
|
|
roughness_value = float(material.roughness)
|
|
changed, new_roughness = imgui.slider_float(f"粗糙度##rough_{i}", roughness_value, 0.0, 1.0)
|
|
if changed:
|
|
self._update_material_roughness(material, new_roughness)
|
|
except:
|
|
imgui.text_colored((0.7, 0.7, 0.7, 1.0), "粗糙度: 不可用")
|
|
|
|
if hasattr(material, 'metallic') and material.metallic is not None:
|
|
try:
|
|
metallic_value = float(material.metallic)
|
|
changed, new_metallic = imgui.slider_float(f"金属性##metal_{i}", metallic_value, 0.0, 1.0)
|
|
if changed:
|
|
self._update_material_metallic(material, new_metallic)
|
|
except:
|
|
imgui.text_colored((0.7, 0.7, 0.7, 1.0), "金属性: 不可用")
|
|
|
|
if hasattr(material, 'refractive_index') and material.refractive_index is not None:
|
|
try:
|
|
ior_value = float(material.refractive_index)
|
|
changed, new_ior = imgui.slider_float(f"折射率##ior_{i}", ior_value, 1.0, 3.0)
|
|
if changed:
|
|
self._update_material_ior(material, new_ior)
|
|
except:
|
|
imgui.text_colored((0.7, 0.7, 0.7, 1.0), "折射率: 不可用")
|
|
|
|
# 材质预设
|
|
imgui.text("材质预设")
|
|
presets = ["默认", "金属", "塑料", "玻璃", "木材", "混凝土"]
|
|
current_preset = 0 # 默认选择
|
|
|
|
if imgui.begin_combo(f"预设##preset_{i}", presets[current_preset]):
|
|
for j, preset_name in enumerate(presets):
|
|
if imgui.selectable(preset_name, j == current_preset):
|
|
self._apply_material_preset(material, preset_name)
|
|
imgui.end_combo()
|
|
|
|
# 纹理信息
|
|
imgui.text("纹理贴图")
|
|
if imgui.button(f"选择漫反射贴图##diffuse_{i}"):
|
|
self._select_texture_for_material(node, material, "diffuse")
|
|
|
|
imgui.same_line()
|
|
if imgui.button(f"选择法线贴图##normal_{i}"):
|
|
self._select_texture_for_material(node, material, "normal")
|
|
|
|
imgui.same_line()
|
|
if imgui.button(f"选择粗糙度贴图##roughness_{i}"):
|
|
self._select_texture_for_material(node, material, "roughness")
|
|
|
|
if imgui.button(f"选择金属性贴图##metallic_{i}"):
|
|
self._select_texture_for_material(node, material, "metallic")
|
|
|
|
imgui.same_line()
|
|
if imgui.button(f"选择自发光贴图##emission_{i}"):
|
|
self._select_texture_for_material(node, material, "emission")
|
|
|
|
imgui.same_line()
|
|
if imgui.button(f"清除所有贴图##clear_{i}"):
|
|
self._clear_all_textures(node)
|
|
|
|
# 着色模型选择
|
|
self._draw_shading_model_panel(material, i)
|
|
|
|
# 显示当前纹理信息
|
|
self._display_current_textures(node, material)
|
|
|
|
def _draw_shading_model_panel(self, material, material_index):
|
|
"""绘制着色模型选择面板"""
|
|
try:
|
|
imgui.text("着色模型")
|
|
|
|
# RenderPipeline支持的着色模型
|
|
shading_models = ["默认", "自发光", "透明"]
|
|
current_model = 0 # 默认选择
|
|
|
|
# 安全地获取当前着色模型
|
|
try:
|
|
if hasattr(material, 'emission') and material.emission is not None:
|
|
current_model = int(material.emission.x)
|
|
except:
|
|
current_model = 0
|
|
|
|
# 着色模型选择
|
|
if imgui.begin_combo(f"着色模型##shading_{material_index}", shading_models[current_model]):
|
|
for j, model_name in enumerate(shading_models):
|
|
if imgui.selectable(model_name, j == current_model):
|
|
self._update_shading_model(material, j)
|
|
imgui.end_combo()
|
|
|
|
# 如果是透明着色模型,添加透明度控制
|
|
if current_model == 3: # 透明着色模型
|
|
imgui.text("透明度设置")
|
|
try:
|
|
if hasattr(material, 'shading_model_param0'):
|
|
current_opacity = material.shading_model_param0
|
|
else:
|
|
current_opacity = 1.0
|
|
|
|
changed, new_opacity = imgui.slider_float(f"不透明度##opacity_{material_index}", current_opacity, 0.0, 1.0)
|
|
if changed:
|
|
self._update_transparency(material, new_opacity)
|
|
except:
|
|
imgui.text_colored((0.7, 0.7, 0.7, 1.0), "透明度控制不可用")
|
|
|
|
except Exception as e:
|
|
print(f"绘制着色模型面板失败: {e}")
|
|
|