c4d对象名称批量更名字段替换脚本
2025-09-02 11:08:56 /
Directory:Plugin
/
Views:12
使用说明:
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()