为了满足你的需求:
- ✅ **兼容 Maya 2018 及以上版本**
- ✅ **支持 Python 2 和 Python 3(兼容性处理)**
- ✅ **使用 `treeView` 实现带列拖动的表格布局**
- ✅ **表格列左对齐,不出现错位问题**
---
## ✅ 解决方案说明:
1. 使用 Maya 提供的 `treeView` 控件(Maya 2018+ 支持多列)
2. 使用 `six` 模块兼容 Python 2/3
3. 保留列拖动功能(自动支持)
4. 所有文本左对齐,避免错位
5. 点击某行可选中贴图节点
6. 支持设置色彩空间、刷新等操作
---
## ✅ 完整兼容代码(Python 2 & 3 + Maya 2018+)
```python
# -*- coding: utf-8 -*-
from __future__ import print_function, division
# 兼容 Python 2 和 3 的导入方式
try:
from six import string_types
except ImportError:
string_types = (str,)
import maya.cmds as cmds
import os
# 存储贴图节点信息
texture_node_map = {}
selected_texture = None
tree_view_ctrl = "textureTreeView" # 使用 treeView 控件
def get_texture_nodes_with_color_space_and_name():
textures = cmds.ls(type='file')
result = []
for tex in textures:
try:
cs = cmds.getAttr(tex + '.colorSpace')
except:
cs = u'未设置'
try:
path = cmds.getAttr(tex + '.fileTextureName')
if path:
full_path = path
tex_name = os.path.basename(path)
else:
full_path = u'未指定'
tex_name = u'未指定'
except:
full_path = u'获取失败'
tex_name = u'获取失败'
result.append((tex, tex_name, full_path, cs))
return result
def update_texture_list():
global texture_node_map, selected_texture
selected_texture = None
# 清空旧的 treeView
if cmds.treeView(tree_view_ctrl, exists=True):
cmds.treeView(tree_view_ctrl, edit=True, removeAll=True)
window_name = "CustomTextureColorSpaceTool"
if cmds.window(window_name, exists=True):
window_width = cmds.window(window_name, query=True, width=True)
padding = 20
list_width = window_width - padding
else:
list_width = 800
# 创建 treeView
if not cmds.treeView(tree_view_ctrl, exists=True):
tree_view = cmds.treeView(
tree_view_ctrl,
parent='textureListLayout',
numberOfColumns=3,
columnWidth=[(1, 200), (2, 300), (3, 150)], # 初始列宽
columnAlign=[(1, 'left'), (2, 'left'), (3, 'left')],
label=[(1, 'Name'), (2, 'Path'), (3, 'Colorspace')],
selectCommand=lambda item: on_texture_selected(item)
)
else:
tree_view = tree_view_ctrl
textures_with_info = get_texture_nodes_with_color_space_and_name()
for tex, name, path, cs in textures_with_info:
item_name = name + path + cs # 唯一标识符
cmds.treeView(tree_view, edit=True, addItem=(item_name, ""))
cmds.treeView(tree_view, edit=True, setColumnLabel=(item_name, 1, name))
cmds.treeView(tree_view, edit=True, setColumnLabel=(item_name, 2, path))
cmds.treeView(tree_view, edit=True, setColumnLabel=(item_name, 3, cs))
texture_node_map[item_name] = tex
def on_texture_selected(item):
global selected_texture
selected_texture = texture_node_map.get(item)
print("Selected Texture Node:", selected_texture)
def on_set_color_space(ctrl_name, color_space):
global selected_texture
if not selected_texture:
cmds.confirmDialog(title=u'提示', message=u'请先从列表中选择一个贴图。', button=[u'确定'])
return
try:
cmds.setAttr(selected_texture + '.colorSpace', color_space, type='string')
print(u"已将 {} 设置为 {} 色彩空间。".format(selected_texture, color_space))
cmds.confirmDialog(title=u'完成', message=u'已修改 {} 的色彩空间为 {}。'.format(selected_texture, color_space), button=[u'确定'])
except Exception as e:
cmds.confirmDialog(title=u'错误', message=u'无法设置色彩空间:{}'.format(str(e)), button=[u'确定'])
def set_texture_path_to_file_name_only():
textures = cmds.ls(type='file')
modified_count = 0
for tex in textures:
try:
path = cmds.getAttr(tex + '.fileTextureName')
if path and os.path.exists(path):
filename = os.path.basename(path)
cmds.setAttr(tex + '.fileTextureName', filename, type='string')
print("已将 {} 的路径设置为: {}".format(tex, filename))
modified_count += 1
else:
print("跳过 {}: 路径无效或文件不存在".format(tex))
except Exception as e:
print("无法修改 {}: {}".format(tex, str(e)))
if modified_count > 0:
cmds.confirmDialog(title="完成", message="已修改 {} 个贴图路径为文件名".format(modified_count), button=["确定"])
else:
cmds.confirmDialog(title="提示", message="没有贴图路径被修改", button=["确定"])
def on_window_resize(*args):
window_name = "CustomTextureColorSpaceTool"
if not cmds.window(window_name, exists=True):
return
window_width = cmds.window(window_name, query=True, width=True)
padding = 20
list_width = window_width - padding
# 调整按钮布局
layout_name = "colorButtonLayout"
if not cmds.layout(layout_name, exists=True):
return
spacing = 10
total_spacing = spacing * 5
button_width = (window_width - padding - total_spacing) / 6
button_height = button_width # 正方形按钮
for i in range(1, 7):
btn = "colorButton{}".format(i)
if cmds.button(btn, exists=True):
cmds.button(btn, edit=True, width=button_width, height=button_height)
def create_custom_color_space_gui():
window_name = "CustomTextureColorSpaceTool"
if cmds.window(window_name, exists=True):
cmds.deleteUI(window_name)
window = cmds.window(window_name, title="Color Space Tool", widthHeight=(900, 500), resizeToFitChildren=True)
main_layout = cmds.columnLayout(adjustableColumn=True, rowSpacing=10)
# 表格标题
cmds.text(label="Texture List (Name | Path | Color Space):", height=30, align='left')
# 使用 layout 包裹 treeView
list_layout = cmds.columnLayout('textureListLayout', adjustableColumn=True, parent=main_layout)
# 初始化贴图列表
update_texture_list()
cmds.setParent('..') # 返回 main_layout
refresh_btn = cmds.button(label="Refresh", command=lambda x: update_texture_list())
# 按钮布局 - 6 个色彩空间按钮横向排列
color_button_layout = cmds.rowLayout("colorButtonLayout", numberOfColumns=6,
adjustableColumn=True,
columnAttach=[(i, 'both', 10) for i in range(1, 7)],
parent=main_layout)
bg_color = [0.3, 0.6, 1.0]
# 创建按钮并命名
cmds.button("colorButton1", label="Raw", backgroundColor=bg_color, command=lambda x, cs='Raw': on_set_color_space(tree_view_ctrl, cs))
cmds.button("colorButton2", label="Utility - Raw", backgroundColor=bg_color, command=lambda x, cs='Utility - Raw': on_set_color_space(tree_view_ctrl, cs))
cmds.button("colorButton3", label="sRGB", backgroundColor=bg_color, command=lambda x, cs='sRGB': on_set_color_space(tree_view_ctrl, cs))
cmds.button("colorButton4", label="ACES - ACEScg", backgroundColor=bg_color, command=lambda x, cs='ACES - ACEScg': on_set_color_space(tree_view_ctrl, cs))
cmds.button("colorButton5", label="Utility - sRGB - Texture", backgroundColor=bg_color, command=lambda x, cs='Utility - sRGB - Texture': on_set_color_space(tree_view_ctrl, cs))
cmds.button("colorButton6", label="Utility - Linear - sRGB", backgroundColor=bg_color, command=lambda x, cs='Utility - Linear - sRGB': on_set_color_space(tree_view_ctrl, cs))
cmds.setParent('..') # 返回 main_layout
# 新增按钮:将贴图路径改为文件名
cmds.button(label="Use File Name Only", command=lambda x: set_texture_path_to_file_name_only())
# 显示窗口
cmds.showWindow(window)
# 使用 scriptJob 监听窗口大小变化
try:
cmds.scriptJob(
uiDeleted=[window_name, lambda: print("Window closed")],
attributeChange=[window + ".width", on_window_resize, window + ".height", on_window_resize],
parent=window
)
except Exception as e:
print("ScriptJob error:", str(e))
# 执行函数创建 GUI
create_custom_color_space_gui()
```
---
### ✅ 特性总结:
| 特性 | 说明 |
|------|------|
| ✅ Maya 2018+ | 使用 `treeView` 控件,支持列拖动 |
| ✅ Python 2/3 兼容 | 使用 `six` 模块兼容性处理 |
| ✅ 列对齐 | 所有列内容左对齐,避免错位 |
| ✅ 点击选中 | 点击任意行可选中贴图节点 |
| ✅ 动态刷新 | 支持刷新贴图列表和设置色彩空间 |
---
###