c4d对象名称批量更名字段替换脚本
2个月前 /
Directory:Plugin
/
Views:23
使用说明:
1. 安装使用:
将脚本保存为
.py文件在 Cinema 4D 中通过
脚本→用户脚本→加载脚本来运行
2. 功能介绍:
序列号重命名:
可以设置前缀(如"对象_")
可以设置起始序号
会自动生成
对象_001、对象_002这样的名称
自定义重命名:
输入新的名称
如果选择多个对象,会自动添加序号
字符替换:
输入要替换的文字(如广告内容)
输入替换成的文字
会在所有对象名称中进行查找替换
3. 操作选项:
重命名所有对象:处理场景中的所有对象
重命名选中对象:只处理当前选中的对象(包括子对象)
4. 安全特性:
支持撤销操作(Ctrl+Z)
操作前会提示确认
显示处理结果统计
# -*- coding: utf-8 -*-
"""
Cinema 4D 批量重命名工具
支持序列号重命名、自定义重命名和字符替换
"""
import c4d
from c4d import gui
# 全局变量定义
DIALOG_ID = 1000
GROUP_MAIN = 2000
GROUP_BUTTONS = 2001
GROUP_RADIO = 2002 # 单选按钮组
# 控件ID
RADIO_SEQUENCE = 3001 # 序列号重命名
RADIO_CUSTOM = 3002 # 自定义重命名
RADIO_REPLACE = 3003 # 字符替换
EDIT_PREFIX = 4001 # 前缀输入框
EDIT_START_NUM = 4002 # 起始序号
EDIT_CUSTOM_NAME = 4003 # 自定义名称
EDIT_OLD_TEXT = 4004 # 要替换的文字
EDIT_NEW_TEXT = 4005 # 替换成的文字
BTN_RENAME_ALL = 5001 # 重命名所有对象
BTN_RENAME_SELECTED = 5002 # 重命名选中对象
BTN_CANCEL = 5003 # 取消按钮
class RenameDialog(gui.GeDialog):
"""重命名对话框类"""
def CreateLayout(self):
"""创建对话框布局"""
self.SetTitle("批量重命名工具")
# 主要分组
self.GroupBegin(GROUP_MAIN, c4d.BFH_SCALEFIT | c4d.BFV_SCALEFIT, 1, 0)
self.GroupBorderSpace(10, 10, 10, 10)
# 重命名方式选择标题
self.AddStaticText(0, c4d.BFH_LEFT, 0, 0, "选择重命名方式:", 0)
self.AddSeparatorH(0, c4d.BFH_SCALEFIT)
# 单选按钮组 - 确保互斥
self.GroupBegin(GROUP_RADIO, c4d.BFH_SCALEFIT, 1, 0)
# 方式1:序列号重命名
self.AddRadioButton(RADIO_SEQUENCE, c4d.BFH_LEFT, 0, 0, "1. 序列号重命名")
# 序列号重命名的参数
self.GroupBegin(0, c4d.BFH_SCALEFIT, 2, 0)
self.GroupBorderSpace(20, 5, 10, 5)
self.AddStaticText(0, c4d.BFH_LEFT, 60, 0, "前缀:", 0)
self.AddEditText(EDIT_PREFIX, c4d.BFH_SCALEFIT, 150, 0)
self.AddStaticText(0, c4d.BFH_LEFT, 60, 0, "起始序号:", 0)
self.AddEditNumberArrows(EDIT_START_NUM, c4d.BFH_LEFT, 80, 0)
self.GroupEnd()
# 分隔线
self.AddSeparatorH(0, c4d.BFH_SCALEFIT)
# 方式2:自定义重命名
self.AddRadioButton(RADIO_CUSTOM, c4d.BFH_LEFT, 0, 0, "2. 自定义重命名")
# 自定义重命名的参数
self.GroupBegin(0, c4d.BFH_SCALEFIT, 2, 0)
self.GroupBorderSpace(20, 5, 10, 5)
self.AddStaticText(0, c4d.BFH_LEFT, 60, 0, "新名称:", 0)
self.AddEditText(EDIT_CUSTOM_NAME, c4d.BFH_SCALEFIT, 150, 0)
self.AddStaticText(0, c4d.BFH_LEFT, 0, 0, "注意:多个对象会自动添加序号", 0)
self.GroupEnd()
# 分隔线
self.AddSeparatorH(0, c4d.BFH_SCALEFIT)
# 方式3:字符替换
self.AddRadioButton(RADIO_REPLACE, c4d.BFH_LEFT, 0, 0, "3. 字符替换")
# 字符替换的参数
self.GroupBegin(0, c4d.BFH_SCALEFIT, 2, 0)
self.GroupBorderSpace(20, 5, 10, 5)
self.AddStaticText(0, c4d.BFH_LEFT, 80, 0, "要替换的文字:", 0)
self.AddEditText(EDIT_OLD_TEXT, c4d.BFH_SCALEFIT, 150, 0)
self.AddStaticText(0, c4d.BFH_LEFT, 80, 0, "替换成:", 0)
self.AddEditText(EDIT_NEW_TEXT, c4d.BFH_SCALEFIT, 150, 0)
self.AddStaticText(0, c4d.BFH_LEFT, 0, 0, "注意:仅替换包含指定文字的对象名称", 0)
self.GroupEnd()
self.GroupEnd() # 结束单选按钮组
self.GroupEnd() # 结束主分组
# 分隔线
self.AddSeparatorH(0, c4d.BFH_SCALEFIT)
# 按钮组
self.GroupBegin(GROUP_BUTTONS, c4d.BFH_CENTER, 3, 1)
self.AddButton(BTN_RENAME_ALL, c4d.BFH_LEFT, 120, 0, "处理所有对象")
self.AddButton(BTN_RENAME_SELECTED, c4d.BFH_LEFT, 120, 0, "处理选中对象")
self.AddButton(BTN_CANCEL, c4d.BFH_LEFT, 80, 0, "取消")
self.GroupEnd()
return True
def InitValues(self):
"""初始化控件值"""
# 设置单选按钮组 - 默认选择序列号重命名
self.SetBool(RADIO_SEQUENCE, True)
self.SetBool(RADIO_CUSTOM, False)
self.SetBool(RADIO_REPLACE, False)
# 设置默认值
self.SetString(EDIT_PREFIX, "对象_")
self.SetInt32(EDIT_START_NUM, 1)
self.SetString(EDIT_CUSTOM_NAME, "新对象")
self.SetString(EDIT_OLD_TEXT, "")
self.SetString(EDIT_NEW_TEXT, "")
return True
def Command(self, id, msg):
"""处理命令事件"""
# 处理单选按钮互斥
if id == RADIO_SEQUENCE:
self.SetBool(RADIO_SEQUENCE, True)
self.SetBool(RADIO_CUSTOM, False)
self.SetBool(RADIO_REPLACE, False)
elif id == RADIO_CUSTOM:
self.SetBool(RADIO_SEQUENCE, False)
self.SetBool(RADIO_CUSTOM, True)
self.SetBool(RADIO_REPLACE, False)
elif id == RADIO_REPLACE:
self.SetBool(RADIO_SEQUENCE, False)
self.SetBool(RADIO_CUSTOM, False)
self.SetBool(RADIO_REPLACE, True)
# 处理按钮点击
elif id == BTN_RENAME_ALL:
self.ProcessObjects(False) # 处理所有对象
elif id == BTN_RENAME_SELECTED:
self.ProcessObjects(True) # 处理选中对象
elif id == BTN_CANCEL:
self.Close()
return True
def ProcessObjects(self, selected_only):
"""处理对象 - 根据选择的模式执行不同操作"""
doc = c4d.documents.GetActiveDocument()
if not doc:
gui.MessageDialog("没有活动的文档!")
return
# 获取要处理的对象列表
if selected_only:
objects = doc.GetActiveObjects(c4d.GETACTIVEOBJECTFLAGS_CHILDREN)
if not objects:
gui.MessageDialog("请先选择要处理的对象!")
return
scope_text = "选中"
else:
objects = self.GetAllObjects(doc.GetFirstObject())
scope_text = "所有"
if not objects:
gui.MessageDialog("没有找到可处理的对象!")
return
# 开始撤销记录
doc.StartUndo()
try:
# 根据选择的重命名方式进行处理
if self.GetBool(RADIO_SEQUENCE):
processed_count = self.RenameWithSequence(objects, doc)
operation_text = "重命名"
elif self.GetBool(RADIO_CUSTOM):
processed_count = self.RenameWithCustomName(objects, doc)
operation_text = "重命名"
elif self.GetBool(RADIO_REPLACE):
processed_count = self.ReplaceInObjects(objects, doc)
operation_text = "替换"
else:
gui.MessageDialog("请选择一种处理方式!")
doc.EndUndo()
return
# 结束撤销记录
doc.EndUndo()
# 刷新视图
c4d.EventAdd()
# 显示结果
if processed_count > 0:
gui.MessageDialog(f"成功{operation_text}了 {processed_count} 个对象!\n(从{scope_text}{len(objects)}个对象中筛选)")
else:
if self.GetBool(RADIO_REPLACE):
old_text = self.GetString(EDIT_OLD_TEXT)
gui.MessageDialog(f"在{scope_text}{len(objects)}个对象中没有找到包含'{old_text}'的对象名称!")
else:
gui.MessageDialog("没有对象需要处理!")
except Exception as e:
doc.EndUndo()
gui.MessageDialog(f"处理过程中出现错误:{str(e)}")
def GetAllObjects(self, obj):
"""递归获取所有对象"""
objects = []
while obj:
objects.append(obj)
# 递归获取子对象
if obj.GetDown():
objects.extend(self.GetAllObjects(obj.GetDown()))
obj = obj.GetNext()
return objects
def RenameWithSequence(self, objects, doc):
"""使用序列号重命名 - 重命名所有传入的对象"""
prefix = self.GetString(EDIT_PREFIX)
start_num = self.GetInt32(EDIT_START_NUM)
processed_count = 0
for i, obj in enumerate(objects):
doc.AddUndo(c4d.UNDOTYPE_CHANGE, obj)
new_name = f"{prefix}{start_num + i:03d}"
obj.SetName(new_name)
processed_count += 1
return processed_count
def RenameWithCustomName(self, objects, doc):
"""使用自定义名称重命名 - 重命名所有传入的对象"""
custom_name = self.GetString(EDIT_CUSTOM_NAME)
if not custom_name.strip():
gui.MessageDialog("请输入自定义名称!")
return 0
processed_count = 0
if len(objects) == 1:
# 只有一个对象时直接使用自定义名称
doc.AddUndo(c4d.UNDOTYPE_CHANGE, objects[0])
objects[0].SetName(custom_name)
processed_count = 1
else:
# 多个对象时添加序号
for i, obj in enumerate(objects):
doc.AddUndo(c4d.UNDOTYPE_CHANGE, obj)
new_name = f"{custom_name}_{i + 1:03d}"
obj.SetName(new_name)
processed_count += 1
return processed_count
def ReplaceInObjects(self, objects, doc):
"""字符替换功能 - 只替换包含指定字符的对象"""
old_text = self.GetString(EDIT_OLD_TEXT)
new_text = self.GetString(EDIT_NEW_TEXT)
if not old_text.strip():
gui.MessageDialog("请输入要替换的文字!")
return 0
processed_count = 0
# 扫描所有对象,只处理包含指定文字的对象
for obj in objects:
current_name = obj.GetName()
if old_text in current_name:
doc.AddUndo(c4d.UNDOTYPE_CHANGE, obj)
new_name = current_name.replace(old_text, new_text)
obj.SetName(new_name)
processed_count += 1
# 可以添加调试信息
print(f"替换: '{current_name}' -> '{new_name}'")
return processed_count
def main():
"""主函数"""
dialog = RenameDialog()
dialog.Open(c4d.DLG_TYPE_MODAL, defaultw=400, defaulth=500)
if __name__ == '__main__':
main()