Maya材质纹理切换脚本修改:下拉选材质+滑块调纹理
解决Maya材质纹理切换脚本的问题
嘿,我帮你梳理了原脚本里的几个问题,并且重新写了一个完整的版本,完全满足你通过下拉菜单切换材质、滑块调节纹理,还能把设置应用到选中模型的需求。先说说原脚本的几个小疏漏:
- 删除窗口时误用了未定义的变量
ram,应该用窗口名字符串"ram" - 图片路径定义后没写完引用,会导致图片加载失败
- 缺少核心的材质选择、纹理调节UI组件,以及对应的功能逻辑
下面是修改后的完整脚本:
import maya.cmds as mc # 全局变量,存储当前编辑的材质和纹理节点 current_shader = None current_texture_place2d = None def delete_existing_window(): """清理已存在的窗口""" if mc.window("ram", exists=True): mc.deleteUI("ram") def create_shader(shader_type): """创建指定类型的材质,并绑定纹理""" global current_shader, current_texture_place2d # 清理旧的材质节点(避免节点过多冗余) if current_shader and mc.objExists(current_shader): mc.delete(current_shader) if current_texture_place2d and mc.objExists(current_texture_place2d): mc.delete(current_texture_place2d) # 创建材质与材质组 shader_name = f"{shader_type}_custom_shader" current_shader = mc.shadingNode(shader_type, asShader=True, name=shader_name) shader_sg = mc.sets(renderable=True, noSurfaceShader=True, empty=True, name=f"{shader_name}SG") mc.connectAttr(f"{current_shader}.outColor", f"{shader_sg}.surfaceShader", force=True) # 创建纹理与UV放置节点(这里用棋盘格示例,可替换为自定义图片) texture_node = mc.shadingNode("checker", asTexture=True, name="base_texture") current_texture_place2d = mc.shadingNode("place2dTexture", asUtility=True, name="texture_uv_place") # 连接纹理与材质的属性 mc.connectAttr(f"{current_texture_place2d}.outUV", f"{texture_node}.uvCoord") mc.connectAttr(f"{current_texture_place2d}.outUvFilterSize", f"{texture_node}.uvFilterSize") mc.connectAttr(f"{texture_node}.outColor", f"{current_shader}.color") def on_shader_selected(*args): """材质下拉菜单选择后的回调逻辑""" shader_type = mc.optionMenu("shader_menu", query=True, value=True) create_shader(shader_type) # 重置滑块初始值 mc.floatSlider("texture_repeat_slider", edit=True, value=2) on_texture_repeat_changed(2) def on_texture_repeat_changed(value): """滑块调节纹理重复次数的回调""" if not current_texture_place2d: return mc.setAttr(f"{current_texture_place2d}.repeatU", value) mc.setAttr(f"{current_texture_place2d}.repeatV", value) def apply_to_selected(): """将当前材质应用到选中模型""" if not current_shader: mc.warning("请先选择一种材质!") return selected_objs = mc.ls(selection=True, transforms=True) if not selected_objs: mc.warning("请先选中要应用材质的模型!") return shader_sg = f"{current_shader}SG" for obj in selected_objs: # 获取模型的形状节点并分配材质 shape_nodes = mc.listRelatives(obj, shapes=True) if shape_nodes: for shape in shape_nodes: mc.sets(shape, forceElement=shader_sg) # 主窗口初始化 delete_existing_window() ram = mc.window("ram", title="Material and Texture v0.9", width=300, height=300) mc.columnLayout(adjustableColumn=True, rowSpacing=12) # 加载Logo图片(路径错误时显示提示文本) try: imagePath = mc.internalVar(upd=True) + "icons/scriptlogo.jpg" mc.image(width=300, height=200, image=imagePath) except: mc.text(label="Logo加载失败", align="center", height=200, font="boldLabelFont") # 材质选择下拉菜单 mc.text(label="选择材质类型", align="center") mc.optionMenu("shader_menu", changeCommand=on_shader_selected) mc.menuItem(label="Blinn") mc.menuItem(label="Phong") mc.menuItem(label="Lambert") mc.menuItem(label="SurfaceShader") # 纹理重复次数调节滑块 mc.text(label="调节纹理重复次数", align="center") create_shader("blinn") # 初始化默认材质 mc.floatSlider("texture_repeat_slider", min=0.1, max=10.0, value=2, step=0.1, changeCommand=lambda val: on_texture_repeat_changed(val)) # 应用按钮 mc.button(label="应用到选中模型", command=lambda _: apply_to_selected(), width=220, height=30) # 显示窗口 mc.showWindow(ram)
几个关键功能说明:
- 材质自动创建:选中下拉菜单里的材质类型时,会自动创建对应材质并绑定纹理,旧材质节点会被清理避免冗余
- 纹理参数调节:滑块控制纹理的UV重复次数,你可以修改回调函数里的属性,换成调节纹理偏移、旋转或者材质的高光强度等参数
- 模型材质应用:点击按钮后,会把当前设置好的材质批量应用到你选中的所有模型,自动处理形状节点的材质组分配
- 自定义纹理替换:如果想用自己的图片纹理,把
create_shader里的checker换成file,再添加一行设置图片路径:mc.setAttr(f"{texture_node}.fileTextureName", "你的纹理文件绝对路径", type="string")
这样整个脚本就能正常运行,实现你想要的功能啦!
内容的提问来源于stack exchange,提问作者Jake




