在 OpenMaya 辨識節點類型

在 cmds 裡面辨識一個 node 的類型可以透過 cmds.nodeType, i.e.

1
2
3
4
print(cmds.nodeType("persp"))
# Result: transform
print(cmds.nodeType("perspShape"))
# camera

typeName & hasFn

如果使用 OpenMaya 的話有兩種方法可以辨識節點類型:

MFnDependencyNode.typeName

透過 MFnDependencyNode 的 typeName**

1
2
3
4
5
6
7
8
9
import maya.api.OpenMaya as OpenMaya

# Get the mobject of the node
sel = OpenMaya.MGlobal.getSelectionListByName("perspShape")
mobject = sel.getDependNode(0)

fn = OpenMaya.MFnDependencyNode(mobj)
print(fn.typeName)
# camera

MObject.hasFn

透過相容的 MFn, node function set (類似 isinstance 的用法)

1
2
3
4
5
6
7
import maya.api.OpenMaya as OpenMaya

# Get the mobject of the node
sel = OpenMaya.MGlobal.getSelectionListByName("perspShape")
mobject = sel.getDependNode(0)

print(mobject.hasFn(OpenMaya.MFn.kCamera))

Performance & Duck Typing

透過 MFn 的效能更好. 而且同一個 node 可能和多種 MFn 相容, 透過這個方式更容易取得和你想做的操作相容的 node(Duck Typing).

Performance

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
import timeit
import maya.api.OpenMaya as OpenMaya

# Get the mobject of the node
sel = OpenMaya.MGlobal.getSelectionListByName("perspShape")
mobject = sel.getDependNode(0)

def typename_matches(mobject, type_name):
    return OpenMaya.MFnDependencyNode(mobject).typeName == type_name

def is_compatible_with(mobject, fn_type):
    return mobject.hasFn(fn_type)

time_type = timeit.Timer(lambda: typename_matches(mobject, "camera"))
time_fn = timeit.Timer(lambda: is_compatible_with(mobject, OpenMaya.MFn.kCamera))

print("typeName", time_type.timeit(1000000))
print("hasFn", time_fn.timeit(1000000))

# typeName 0.9594104999996489
# hasFn 0.13348910000058822

Duck Typing

1
2
3
4
5
print(is_compatible_with(mobject, OpenMaya.MFn.kCamera))
print(is_compatible_with(mobject, OpenMaya.MFn.kDagNode))
# True
# True
# (Camera 的 shape node 和 camera 以及 DagNode 的 function set 都相容.)