Python:Spoonfed - (2-10) 激励选择脚本(搬砖)

https://www.patreon.com/posts/python-spoonfed-31572219

2019年11月15日

利用上一课的选择函数,我们现在可以拼凑出一些脚本(有一些事情我们还没有解释,但应该很容易理解)。以下代码将允许您选择当前所选对象的父对象、顶级对象、同级对象、表兄弟对象或子对象。这些功能的一部分过去已包含在 Cineversity 中,但在这里您可以获取它们,包括源代码。

我们先从Parent的选择开始。PS_SelectObject_Parent.py

python 复制代码
import c4d

def SetActiveObjects(objlist):
    cleared = False
    for obj in objlist:
        if not cleared:
            doc.SetActiveObject(obj, c4d.SELECTION_NEW)
            cleared = True
        else:
            doc.SetActiveObject(obj, c4d.SELECTION_ADD)
            

def main():
    if doc == None: return

    activeObjectList = doc.GetActiveObjects(c4d.GETACTIVEOBJECTFLAGS_CHILDREN)
    if not activeObjectList: return
    
    newSelection = []
    for obj in activeObjectList:
        if obj.GetUp() != None:
            newSelection += [obj.GetUp()]
        else:
            newSelection += [obj]

    SetActiveObjects(newSelection)
    c4d.EventAdd()


if __name__=='__main__':
    main()

在这里,我们将函数 SetActiveObjects() 添加到 API 中的选择设置函数数量中。由于给定的函数 只能选择一个BaseObject 一次 **,因此我们在这里封装SetActiveObject()**并允许传递整个列表。

唯一的技巧是,我们必须使用标志 SELECTION_NEW 设置第一个对象以清除 以前的 设置其他每个对象 选择,但必须使用SELECTION_ADD 。为此,我们使用一个布尔变量 清除 开始 ,它从False 设置为 True ,并在第一次有机会时 保持True )。 (此后一直

在函数 main() 循环中迭代当前选择 中,我们在for,获取每个对象的直接父对象并将其添加到新选择中。如果没有父对象,则将添加对象本身(本质上保持选中状态)。

newSelection 是一个列表对象。 文字初始化为空列表 它由[ ] 。要添加对象,我们首先通过再次将对象括在方括号中来创建一个列表,其中包含该对象中的一项。 将此迷你列表附加到现有列表 可以使用扩展赋值+=

第二个脚本基本相同,但它不是寻找直接父代,而是寻找最顶层的祖先。这是在 while 循环中完成的: PS_SelectObject_Top.py

python 复制代码
import c4d

def SetActiveObjects(objlist):
    cleared = False
    for obj in objlist:
        if not cleared:
            doc.SetActiveObject(obj, c4d.SELECTION_NEW)
            cleared = True
        else:
            doc.SetActiveObject(obj, c4d.SELECTION_ADD)


def main():
    if doc == None: return

    activeObjectList = doc.GetActiveObjects(c4d.GETACTIVEOBJECTFLAGS_CHILDREN)
    if not activeObjectList: return

    newSelection = []
    for obj in activeObjectList:
        while obj.GetUp() != None:
            obj = obj.GetUp()
        newSelection += [obj]

    SetActiveObjects(newSelection)
    c4d.EventAdd()


if __name__=='__main__':
    main()

我们不需要额外的情况来包含 obj 请注意,如果没有祖先, 循环 本身。在这种情况下,while 结束 本身在obj 处

如果我们在最初的选择中有两个兄弟姐妹会怎样?难道我们不会为两者获得相同的父级或祖先,并且有一个包含重复元素的列表可供选择吗? -- 确实如此,但没关系:将对象设置为活动 两次 不会产生不良影响,因此我们不需要经历整理重复项的麻烦。PS_SelectObject_Siblings.py

python 复制代码
import c4d

def SetActiveObjects(objlist):
    cleared = False
    for obj in objlist:
        if not cleared:
            doc.SetActiveObject(obj, c4d.SELECTION_NEW)
            cleared = True
        else:
            doc.SetActiveObject(obj, c4d.SELECTION_ADD)


def SelectSiblings(startobj):
    global newSelection
    if startobj == None: return

    newSelection += [startobj]
    obj = startobj
    while obj.GetPred() != None:
        newSelection += [obj.GetPred()]
        obj = obj.GetPred()
    obj = startobj
    while obj.GetNext() != None:
        newSelection += [obj.GetNext()]
        obj = obj.GetNext()


def main():
    global newSelection
    if doc == None: return

    activeObjectList = doc.GetActiveObjects(c4d.GETACTIVEOBJECTFLAGS_CHILDREN)
    if not activeObjectList: return

    newSelection = []
    for obj in activeObjectList:
        SelectSiblings(obj)

    SetActiveObjects(newSelection)
    c4d.EventAdd()


if __name__=='__main__':
    main()

在第三个脚本(选择最初选定对象的所有同级)中,我们引入了一个新函数 SelectSiblings() 。这将获取一个 BaseObject ,并将该对象本身及其所有同级添加到共享全局列表 newSelection 中。 它通过从参数对象走到列表的前面,然后再次从参数对象走到列表的后面来实现这一点。

我们只调用 SelectSiblings 一次,因此我们可能直接保留该代码而不是函数调用(这种做法也称为 内联代码 )。 函数 但是,分离出SetActiveObjectsSelectSiblings 使代码更清晰、更易于阅读 - 而且,我们可以为最后两个脚本重用相同的结构。PS_SelectObject_Cousins.py

python 复制代码
import c4d

def SetActiveObjects(objlist):
    cleared = False
    for obj in objlist:
        if not cleared:
            doc.SetActiveObject(obj, c4d.SELECTION_NEW)
            cleared = True
        else:
            doc.SetActiveObject(obj, c4d.SELECTION_ADD)


def SelectSiblings(startobj):
    global newSelection
    if startobj == None: return

    newSelection += [startobj]
    obj = startobj
    while obj.GetPred() != None:
        newSelection += [obj.GetPred()]
        obj = obj.GetPred()
    obj = startobj
    while obj.GetNext() != None:
        newSelection += [obj.GetNext()]
        obj = obj.GetNext()


def main():
    global newSelection
    if doc == None: return

    activeObjectList = doc.GetActiveObjects(c4d.GETACTIVEOBJECTFLAGS_CHILDREN)
    if not activeObjectList: return

    newSelection = []
    for obj in activeObjectList:
        if obj.GetUp() == None:
            SelectSiblings(obj)
        else:
            parent = obj.GetUp()
            while parent.GetPred() != None:
                parent = parent.GetPred()
            while parent != None:
                SelectSiblings(parent.GetDown())
                parent = parent.GetNext()

    SetActiveObjects(newSelection)
    c4d.EventAdd()


if __name__=='__main__':
    main()

第四个脚本不仅选择兄弟姐妹,还选择最初选择的对象的"表兄弟"。在这种情况下,"表兄弟"是父母的兄弟姐妹的子对象。为了找到这些,代码首先上一层,然后从头到尾遍历这一层,将所有节点的所有子节点添加到选择中。如果没有父母,代码只会添加兄弟姐妹。

第五个也是最后一个选择器脚本选择最初选定对象的子对象:PS_SelectObject_Children

python 复制代码
import c4d

def SetActiveObjects(objlist):
    cleared = False
    for obj in objlist:
        if not cleared:
            doc.SetActiveObject(obj, c4d.SELECTION_NEW)
            cleared = True
        else:
            doc.SetActiveObject(obj, c4d.SELECTION_ADD)
            

def main():
    if doc == None: return

    activeObjectList = doc.GetActiveObjects(c4d.GETACTIVEOBJECTFLAGS_CHILDREN)
    if not activeObjectList: return
    
    newSelection = []
    for obj in activeObjectList:
        if obj.GetUp() != None:
            newSelection += [obj.GetUp()]
        else:
            newSelection += [obj]

    SetActiveObjects(newSelection)
    c4d.EventAdd()


if __name__=='__main__':
    main()

这与 Cinema 4D 的内置功能"选择子项"不同,因为该功能会选择所有依赖子树直至最低级别。相反,脚本仅限于 直接子对象(如果没有子对象,甚至是原始对象)。

我没有包含像 C4D 的"选择子项"(无论如何应该命名为"选择子树")这样的功能,因为该功能已经可用。

一点作业:如果所需的目标对象(父对象、顶级对象、兄弟姐妹、子对象、表兄弟)不可用,则所有五个脚本都会保留最初选择的对象。您可能想要更改该行为,以便不再选择最初选择的对象。在什么情况下这才有意义?这容易实现吗?

相关推荐
数据智能老司机2 小时前
精通 Python 设计模式——分布式系统模式
python·设计模式·架构
数据智能老司机3 小时前
精通 Python 设计模式——并发与异步模式
python·设计模式·编程语言
数据智能老司机3 小时前
精通 Python 设计模式——测试模式
python·设计模式·架构
数据智能老司机3 小时前
精通 Python 设计模式——性能模式
python·设计模式·架构
c8i3 小时前
drf初步梳理
python·django
每日AI新事件3 小时前
python的异步函数
python
这里有鱼汤5 小时前
miniQMT下载历史行情数据太慢怎么办?一招提速10倍!
前端·python
databook14 小时前
Manim实现脉冲闪烁特效
后端·python·动效
程序设计实验室14 小时前
2025年了,在 Django 之外,Python Web 框架还能怎么选?
python
倔强青铜三16 小时前
苦练Python第46天:文件写入与上下文管理器
人工智能·python·面试