如何通过OpenMaya实现顶点pnt属性的锁定状态读写?
使用OpenMaya实现顶点pnt属性的锁定状态获取与设置
问题背景
当前使用Maya cmds操作顶点pntx/pnty/pntz属性的锁定状态时速度过慢,希望改用OpenMaya API实现对应的获取器(getter)和设置器(setter)。
现有cmds实现:
获取顶点pntx锁定状态
mesh = cmds.ls(sl=1)[0] vertices = cmds.ls(cmds.polyListComponentConversion(mesh, toVertex=True), flatten=True) cmds.getAttr("{}.pntx".format(vertices[0]), lock=True)
设置顶点pntx锁定状态
mesh = cmds.ls(sl=1)[0] vertices = cmds.ls(cmds.polyListComponentConversion(mesh, toVertex=True), flatten=True) cmds.setAttr("{}.pntx".format(vertices[0]), lock=False)
已完成的OpenMaya基础代码:
import maya.api.OpenMaya as om sel = om.MSelectionList() sel.add(meshes[0]) dag = sel.getDagPath(0) fn_mesh = om.MFnMesh(dag)
困惑点:不知道如何获取顶点对应的pntx/pnty/pntz属性的MPlug,从而调用isLocked()和setLocked()方法——因为MFnMesh获取的顶点是整数索引,不是可传入MPlug的对象。
解决方案
核心思路是通过网格的DAG路径,结合顶点索引构建对应pnt属性的MPlug,再调用MPlug的锁定相关方法。
1. 获取顶点pnt属性的锁定状态(Getter)
import maya.api.OpenMaya as om def get_vertex_pnt_lock_status(mesh_dag_path, vertex_index, axis="x"): # 获取网格的依赖节点对象,用于访问属性 fn_dep_node = om.MFnDependencyNode(mesh_dag_path.node()) # 获取对应轴的pnt属性MObject(pnt是多属性,对应所有顶点的位置) pnt_attr = fn_dep_node.attribute(f"pnt{axis}") # 构建基础MPlug并定位到目标顶点的属性实例 pnt_plug = om.MPlug(mesh_dag_path.node(), pnt_attr) pnt_plug.selectAncestorLogicalIndex(vertex_index, pnt_attr) # 返回锁定状态 return pnt_plug.isLocked() # 使用示例 if __name__ == "__main__": # 获取选中的第一个网格 sel = om.MSelectionList() sel.add(om.MGlobal.getActiveSelectionList()[0]) mesh_dag = sel.getDagPath(0) # 获取第0个顶点pntx的锁定状态 lock_status = get_vertex_pnt_lock_status(mesh_dag, 0, "x") print(f"顶点0的pntx锁定状态:{lock_status}")
2. 设置顶点pnt属性的锁定状态(Setter)
import maya.api.OpenMaya as om def set_vertex_pnt_lock_status(mesh_dag_path, vertex_index, lock, axis="x"): fn_dep_node = om.MFnDependencyNode(mesh_dag_path.node()) pnt_attr = fn_dep_node.attribute(f"pnt{axis}") pnt_plug = om.MPlug(mesh_dag_path.node(), pnt_attr) pnt_plug.selectAncestorLogicalIndex(vertex_index, pnt_attr) # 设置锁定状态 pnt_plug.setLocked(lock) # 可选:同步设置关键帧可编辑状态(锁定时关闭关键帧) # pnt_plug.setKeyable(not lock) # 使用示例 if __name__ == "__main__": sel = om.MSelectionList() sel.add(om.MGlobal.getActiveSelectionList()[0]) mesh_dag = sel.getDagPath(0) # 将第0个顶点的pntx设置为锁定 set_vertex_pnt_lock_status(mesh_dag, 0, True, "x")
关键步骤解释
pntx/pnty/pntz是网格节点的多属性(multi-attribute),每个顶点对应一个独立的逻辑索引- 通过
MFnDependencyNode.attribute()获取目标属性的MObject - 使用
MPlug.selectAncestorLogicalIndex()定位到对应顶点索引的属性实例 - 最终通过
MPlug.isLocked()和MPlug.setLocked()完成状态的读取与修改
内容的提问来源于stack exchange,提问作者Adam Sirrelle
相关产品推荐
相关产品推荐

