c4d 2023+一键删除对象材质标签脚本

2025-06-22 11:14:14 / Directory:Soft · cinema4d / Views:16

一键删除打开模型中所有的对象后面材质标签脚本,脚本是为针对C4D 2023版本写的,其它版本没有测试,理论上来讲是向上向下兼容的,如果想在其它版本中使用,可以联系我。

1.下面这个版本就是只删除材质标签的脚本

import c4d
from c4d import gui

def remove_material_tags_from_object(obj):
    """递归删除对象及其子对象上的所有材质标签"""
    if not obj:
        return 0
    
    removed_count = 0
    
    # 获取对象的所有标签
    tag = obj.GetFirstTag()
    while tag:
        next_tag = tag.GetNext()  # 先获取下一个标签,因为当前标签可能会被删除
        
        # 检查是否是材质标签
        if tag.GetType() == c4d.Ttexture:
            doc.AddUndo(c4d.UNDOTYPE_DELETE, tag)
            tag.Remove()
            removed_count += 1
        
        tag = next_tag
    
    # 递归处理子对象
    child = obj.GetDown()
    while child:
        removed_count += remove_material_tags_from_object(child)
        child = child.GetNext()
    
    return removed_count

def main():
    # 获取当前文档
    global doc
    doc = c4d.documents.GetActiveDocument()
    if not doc:
        gui.MessageDialog("没有找到活动文档")
        return
    
    # 开始撤销记录
    doc.StartUndo()
    
    total_removed = 0
    
    # 获取场景中的所有顶级对象
    obj = doc.GetFirstObject()
    while obj:
        total_removed += remove_material_tags_from_object(obj)
        obj = obj.GetNext()
    
    # 结束撤销记录
    doc.EndUndo()
    
    # 更新文档
    c4d.EventAdd()
    
    # 显示完成消息
    if total_removed > 0:
        gui.MessageDialog(f"成功删除了 {total_removed} 个材质标签")
    else:
        gui.MessageDialog("没有找到任何材质标签")

if __name__ == '__main__':
    main()


2.如果您只想删除选中对象的材质标签,可以使用这个版本:

import c4d
from c4d import gui

def remove_material_tags_from_object(obj):
    """递归删除对象及其子对象上的所有材质标签"""
    if not obj:
        return 0
    
    removed_count = 0
    
    # 获取对象的所有标签
    tag = obj.GetFirstTag()
    while tag:
        next_tag = tag.GetNext()
        
        # 检查是否是材质标签
        if tag.GetType() == c4d.Ttexture:
            doc.AddUndo(c4d.UNDOTYPE_DELETE, tag)
            tag.Remove()
            removed_count += 1
        
        tag = next_tag
    
    # 递归处理子对象
    child = obj.GetDown()
    while child:
        removed_count += remove_material_tags_from_object(child)
        child = child.GetNext()
    
    return removed_count

def main():
    # 获取当前文档
    global doc
    doc = c4d.documents.GetActiveDocument()
    if not doc:
        gui.MessageDialog("没有找到活动文档")
        return
    
    # 获取选中的对象
    selected_objects = doc.GetActiveObjects(c4d.GETACTIVEOBJECTFLAGS_CHILDREN)
    
    if not selected_objects:
        gui.MessageDialog("请先选择要删除材质标签的对象")
        return
    
    # 开始撤销记录
    doc.StartUndo()
    
    total_removed = 0
    
    # 处理所有选中的对象
    for obj in selected_objects:
        total_removed += remove_material_tags_from_object(obj)
    
    # 结束撤销记录
    doc.EndUndo()
    
    # 更新文档
    c4d.EventAdd()
    
    # 显示完成消息
    if total_removed > 0:
        gui.MessageDialog(f"成功删除了 {total_removed} 个材质标签")
    else:
        gui.MessageDialog("选中的对象上没有找到任何材质标签")

if __name__ == '__main__':
    main()


3.还可以扩展以下功能:群组,并将群组重命名的脚本

import c4d
from c4d import gui

class GroupNameDialog(gui.GeDialog):
    """群组名称选择对话框"""
    
    # 控件ID
    ID_COMBO_NAMES = 1000
    ID_EDIT_CUSTOM = 1001
    ID_BTN_OK = 1002
    ID_BTN_CANCEL = 1003
    
    def __init__(self):
        self.group_name = None  # 默认为None,表示未选择
        
    def CreateLayout(self):
        """创建对话框布局"""
        self.SetTitle("选择群组名称")
        
        # 主要布局
        self.GroupBegin(0, c4d.BFH_SCALEFIT, 1, 0)
        self.GroupBorderSpace(15, 15, 15, 15)
        
        # 标题
        self.AddStaticText(0, c4d.BFH_LEFT, name="请选择群组名称:")
        self.AddSeparatorH(0)
        
        # 下拉选择框
        self.GroupBegin(0, c4d.BFH_SCALEFIT, 2, 0)
        self.AddStaticText(0, c4d.BFH_LEFT, name="预设名称:")
        self.AddComboBox(self.ID_COMBO_NAMES, c4d.BFH_SCALEFIT)
        self.GroupEnd()
        
        # 自定义输入框
        self.GroupBegin(0, c4d.BFH_SCALEFIT, 2, 0)
        self.AddStaticText(0, c4d.BFH_LEFT, name="自定义名称:")
        self.AddEditText(self.ID_EDIT_CUSTOM, c4d.BFH_SCALEFIT)
        self.GroupEnd()
        
        # 说明文字
        self.AddSeparatorH(0)
        self.AddStaticText(0, c4d.BFH_LEFT, name="提示:选择预设名称或输入自定义名称")
        self.AddStaticText(0, c4d.BFH_LEFT, name="如果两者都有内容,将优先使用自定义名称")
        
        self.AddSeparatorH(0)
        
        # 按钮
        self.GroupBegin(0, c4d.BFH_CENTER, 2, 0)
        self.AddButton(self.ID_BTN_OK, c4d.BFH_LEFT, name="确定")
        self.AddButton(self.ID_BTN_CANCEL, c4d.BFH_LEFT, name="取消")
        self.GroupEnd()
        
        self.GroupEnd()
        
        return True
    
    def InitValues(self):
        """初始化控件值"""
        # 添加下拉选项
        self.AddChild(self.ID_COMBO_NAMES, 0, "请选择...")
        self.AddChild(self.ID_COMBO_NAMES, 1, "c4d.cn")
        self.AddChild(self.ID_COMBO_NAMES, 2, "c4d.com")
        self.AddChild(self.ID_COMBO_NAMES, 3, "pic.net")
        self.AddChild(self.ID_COMBO_NAMES, 4, "c4d.net")
        
        # 设置默认选择
        self.SetLong(self.ID_COMBO_NAMES, 0)  # 默认选择"请选择..."
        self.SetString(self.ID_EDIT_CUSTOM, "")
        
        return True
    
    def Command(self, id, msg):
        """处理控件事件"""
        if id == self.ID_BTN_OK:
            # 确定按钮
            custom_name = self.GetString(self.ID_EDIT_CUSTOM).strip()
            combo_selection = self.GetLong(self.ID_COMBO_NAMES)
            
            # 优先使用自定义名称
            if custom_name:
                self.group_name = custom_name
            elif combo_selection > 0:  # 0是"请选择..."
                preset_names = ["", "c4d.cn", "c4d.com", "pic.net", "c4d.net"]
                self.group_name = preset_names[combo_selection]
            else:
                gui.MessageDialog("请选择预设名称或输入自定义名称")
                return True
            
            self.Close()
        elif id == self.ID_BTN_CANCEL:
            # 取消按钮
            self.group_name = None
            self.Close()
        
        return True

def remove_material_tags_from_object(obj, doc):
    """递归删除对象及其子对象上的所有材质标签"""
    if not obj:
        return 0
    
    removed_count = 0
    
    # 获取对象的所有标签
    tag = obj.GetFirstTag()
    while tag:
        next_tag = tag.GetNext()
        
        # 检查是否是材质标签
        if tag.GetType() == c4d.Ttexture:
            doc.AddUndo(c4d.UNDOTYPE_DELETE, tag)
            tag.Remove()
            removed_count += 1
        
        tag = next_tag
    
    # 递归处理子对象
    child = obj.GetDown()
    while child:
        removed_count += remove_material_tags_from_object(child, doc)
        child = child.GetNext()
    
    return removed_count

def create_group_with_all_objects(doc, group_name):
    """创建群组并将所有对象放入其中"""
    # 获取所有顶级对象
    objects = []
    obj = doc.GetFirstObject()
    while obj:
        objects.append(obj)
        obj = obj.GetNext()
    
    if not objects:
        return None
    
    # 创建空对象作为群组
    group = c4d.BaseObject(c4d.Onull)
    group.SetName(group_name)
    
    # 将群组插入到文档中
    doc.InsertObject(group)
    doc.AddUndo(c4d.UNDOTYPE_NEW, group)
    
    # 将所有对象移动到群组下
    for obj in objects:
        doc.AddUndo(c4d.UNDOTYPE_CHANGE, obj)
        obj.Remove()
        obj.InsertUnder(group)
    
    return group

def main():
    # 获取当前文档
    doc = c4d.documents.GetActiveDocument()
    if not doc:
        gui.MessageDialog("没有找到活动文档")
        return
    
    # 显示群组名称选择对话框
    dialog = GroupNameDialog()
    dialog.Open(c4d.DLG_TYPE_MODAL)
    
    if dialog.group_name is None:
        # 用户取消了操作
        gui.MessageDialog("操作已取消")
        return
    
    # 开始撤销记录
    doc.StartUndo()
    
    # 第一步:删除所有材质标签
    total_removed = 0
    obj = doc.GetFirstObject()
    while obj:
        total_removed += remove_material_tags_from_object(obj, doc)
        obj = obj.GetNext()
    
    # 第二步:创建群组并移动所有对象
    group = create_group_with_all_objects(doc, dialog.group_name)
    
    # 结束撤销记录
    doc.EndUndo()
    
    # 更新文档
    c4d.EventAdd()
    
    # 显示完成消息
    message = f"操作完成!\n"
    if total_removed > 0:
        message += f"删除了 {total_removed} 个材质标签\n"
    if group:
        message += f"创建了群组 '{dialog.group_name}' 并移动了所有对象"
    else:
        message += "场景中没有对象需要分组"
    
    gui.MessageDialog(message)

if __name__ == '__main__':
    main()