-
Notifications
You must be signed in to change notification settings - Fork 8
/
sticker.py
150 lines (109 loc) · 3.93 KB
/
sticker.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
"""Put custom icon on any node for display in the Maya GUI
Currently the icon only shows up in Outliner panels (the DAG Outliner,
Graph Editor and Dope Sheet).
Note:
Powered by Maya Python API 1.0, API 2.0 didn't able to do this.
The key was the `setIcon` method in `MFnDependencyNode` class, Python
API 2.0 didn't have that method.
Example Usage:
>> import sticker
>> sticker.put("pSphereShape1", "polyUnite.png")
Remove custom icon
>> sticker.remove("pSphereShape1")
Custom icon displayed in GUI will not persist after scene closed, but
the icon path wiil be saved into node's custom attribute, so next time
we only need to call `reveal` to reveal custom icon in GUI.
Reveal custom icon from previous saved scene
>> sticker.reveal()
"""
import os
from maya import OpenMaya as oldOm
ICON_ATTRIBUTE = "customIconPath"
ICON_ATTR = "cuip"
def put(target, icon):
"""Associates a custom icon with the node for display in the Maya UI
Arguments:
target (str, list): Node name
icon (str): icon file, must be a PNG file (.png) and may
either be an absolute pathname or be relative to the
`XBMLANGPATH` environment variable.
"""
target = _parse_target(target)
mfn_nodes = _parse_nodes(target)
mattr = _create_attribute()
for node in mfn_nodes:
try:
node.setIcon(os.path.expandvars(icon))
except RuntimeError:
raise RuntimeError("Not a valid icon: {!r}".format(icon))
has_attr = node.hasAttribute(ICON_ATTRIBUTE)
set_icon = icon != ""
if set_icon:
if not has_attr:
# Add attribute to save icon path
node.addAttribute(mattr)
plug = node.findPlug(ICON_ATTRIBUTE)
plug.setString(icon)
elif has_attr:
del_cmd = "deleteAttr -at {attr} {node}".format(
attr=ICON_ATTRIBUTE,
node=node.name()
)
oldOm.MGlobal.executeCommand(del_cmd)
def remove(target):
"""Revert back to Node's default icon
Arguments:
target (str, list): Node name
"""
put(target, icon="")
def reveal():
"""Reveal custom icon from previous saved scene
Can use with scene open callback for auto display custom icon saved
from previous session.
"""
sel_list = oldOm.MSelectionList()
ns_list = [""] + oldOm.MNamespace.getNamespaces(":", True)
for ns in ns_list:
if ns in (":UI", ":shared"):
continue
try:
sel_list.add(ns + ":*." + ICON_ATTRIBUTE)
except RuntimeError:
pass
for i in range(sel_list.length()):
mobj = oldOm.MObject()
sel_list.getDependNode(i, mobj)
node = oldOm.MFnDependencyNode(mobj)
plug = node.findPlug(ICON_ATTRIBUTE)
icon_path = plug.asString()
try:
node.setIcon(os.path.expandvars(icon_path))
except RuntimeError:
pass
def _parse_target(target):
"""Internal function for type check"""
if isinstance(target, (str, unicode)):
target = [target]
if not isinstance(target, (list, tuple)):
raise TypeError("`target` should be string or list.")
if not len(target):
raise ValueError("No input target, selection empty.")
return target
def _parse_nodes(target):
"""Internal function for getting MFnDependencyNode"""
mfn_nodes = list()
sel_list = oldOm.MSelectionList()
for path in target:
sel_list.add(path)
for i in range(len(target)):
mobj = oldOm.MObject()
sel_list.getDependNode(i, mobj)
mfn_nodes.append(oldOm.MFnDependencyNode(mobj))
return mfn_nodes
def _create_attribute():
"""Internal function for attribute create"""
attr = oldOm.MFnTypedAttribute()
mattr = attr.create(ICON_ATTRIBUTE,
ICON_ATTR,
oldOm.MFnData.kString)
return mattr