-
Notifications
You must be signed in to change notification settings - Fork 47
/
init.py
196 lines (164 loc) · 7.59 KB
/
init.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
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
'''
Introduction
============
This script recursively adds path trees rooted in one or more directories to
the Nuke plugin path. If Nuke is running in GUI mode, it can also be used to
automatically build menu trees for any gizmo files it locates. (Note: see the
accompanying `menu.py` file for a predefined implementation of this.)
These root directories can be resolved in several ways. In order of precedence,
they are:
1) Using the `CUSTOM_GIZMO_LOCATION` variable below, if it is set to an
existing directory. Note that environment variables will be expanded.
2) From the `NUKE_GIZMO_PATH` environment variable, if it is set.
3) The location of the file in which the ``GizmoPathManager`` code resides.
4) The Nuke plugin path.
Installation
============
To use the ``GizmoPathManager``, copy or move this file as-is to a directory on
your Nuke plugin path, or merge its contents with an existing `init.py` file.
The default directories included on the plugin path are:
Linux::
/users/<LOGIN NAME>/.nuke
/usr/local/Nuke6.2v6/plugins
Mac OS X::
/Users/<LOGIN NAME>/.nuke
/Applications/Nuke6.2v6/Nuke6.2v6.app/Contents/MacOS/plugins
Windows:
In the .nuke directory, which can be found under the directory pointed to
by the HOME environment variable. If this variable is not set (which is
common), the .nuke directory will be under the folder specified by the
USERPROFILE environment variable, which is generally in one of the
following forms::
<DRIVE LETTER>:\Documents and Settings\<LOGIN NAME>\ (Windows XP)
<DRIVE LETTER>:\Users\<LOGIN NAME>\ (Windows Vista/7)
'''
import os
import re
import nuke
# This can be used to set the root directory for the GizmoPathManager search
# without the need to define any environment variables. Note that if this is
# defined and points to an existing directory, other possible search locations
# will be ignored, unless the `__main__` entry point code is modified below.
CUSTOM_GIZMO_LOCATION = r''
class GizmoPathManager(object):
'''
Class used to automatically add directory trees to the Nuke plugin path,
and to build menu items for any gizmos found in those trees.
'''
def __init__(self, searchPaths=None, exclude=r'^\.', ):
'''
'searchPaths': An iterable of paths to recursively search. If omitted,
the search will first try to use the `NUKE_GIZMO_PATH` environment
variable. If that is also undefined, it will resolve and use the
directory in which this file resides. If that cannot be determined, the
contents of the Nuke plugin path will be used.
'exclude': A regular expression for folders and gizmo files to ignore.
The default pattern ignores anything beginning with `.`.
'''
if isinstance(exclude, basestring):
exclude = re.compile(exclude)
self.exclude = exclude
if searchPaths is None:
searchPaths = os.environ.get('NUKE_GIZMO_PATH', '').split(os.pathsep)
if not searchPaths:
import inspect
thisFile = inspect.getsourcefile(lambda: None)
if thisFile:
searchPaths = [os.path.dirname(os.path.abspath(thisFile))]
else:
searchPaths = list(nuke.pluginPath())
self.searchPaths = searchPaths
self.reset()
@classmethod
def canonical_path(cls, path):
return os.path.normcase(os.path.normpath(os.path.realpath(os.path.abspath(path))))
def reset(self):
self._crawlData = {}
def addGizmoPaths(self):
'''
Recursively search ``self.searchPaths`` for folders whose names do not
match the exclusion pattern ``self.exclude``, and add them to the Nuke
plugin path.
'''
self.reset()
self._visited = set()
for gizPath in self.searchPaths:
self._recursiveAddGizmoPaths(gizPath, self._crawlData,
foldersOnly=True)
def _recursiveAddGizmoPaths(self, folder, crawlData, foldersOnly=False):
# If we're in GUI mode, also store away data in _crawlDatato to be used
# later by addGizmoMenuItems
if not os.path.isdir(folder):
return
if nuke.GUI:
if 'files' not in crawlData:
crawlData['gizmos'] = []
if 'dirs' not in crawlData:
crawlData['dirs'] = {}
# avoid an infinite loop due to symlinks...
canonical_path = self.canonical_path(folder)
if canonical_path in self._visited:
return
self._visited.add(canonical_path)
for subItem in sorted(os.listdir(canonical_path)):
if self.exclude and self.exclude.search(subItem):
continue
subPath = os.path.join(canonical_path, subItem)
if os.path.isdir(subPath):
nuke.pluginAppendPath(subPath)
subData = {}
if nuke.GUI:
crawlData['dirs'][subItem] = subData
self._recursiveAddGizmoPaths(subPath, subData)
elif nuke.GUI and (not foldersOnly) and os.path.isfile(subPath):
name, ext = os.path.splitext(subItem)
if ext == '.gizmo':
crawlData['gizmos'].append(name)
def addGizmoMenuItems(self, rootMenu=None, defaultTopMenu=None):
'''
Recursively creates menu items for gizmos found on this instance's
search paths. This only has an effect if Nuke is in GUI mode.
'rootMenu': The root Nuke menu to which the menus and menu items should
be added, either as a ``nuke.Menu`` object or a string. If omitted, the
Nuke 'Nodes' menu will be used.
'defaultTopMenu': If you do not wish to create new menu items at the
top level of the target parent menu, directories for which top-level
menus do not already exist will be added to this menu instead. This
must be the name of an existing menu.
'''
if not nuke.GUI:
return
if not self._crawlData:
self.addGizmoPaths()
if rootMenu is None:
rootMenu = nuke.menu('Nodes')
elif isinstance(rootMenu, basestring):
rootMenu = nuke.menu(rootMenu)
self._recursiveAddGizmoMenuItems(rootMenu, self._crawlData,
defaultSubMenu=defaultTopMenu,
topLevel=True)
def _recursiveAddGizmoMenuItems(self, toolbar, crawlData,
defaultSubMenu=None, topLevel=False):
for name in crawlData.get('gizmos', ()):
niceName = name
if niceName.find('_v')==len(name) - 4:
niceName = name[:-4]
toolbar.addCommand(niceName,"nuke.createNode('%s')" % name)
for folder, data in crawlData.get('dirs', {}).iteritems():
import sys
subMenu = toolbar.findItem(folder)
if subMenu is None:
if defaultSubMenu:
subMenu = toolbar.findItem(defaultSubMenu)
else:
subMenu = toolbar.addMenu(folder)
self._recursiveAddGizmoMenuItems(subMenu, data)
if __name__ == '__main__':
CUSTOM_GIZMO_LOCATION = os.path.expandvars(CUSTOM_GIZMO_LOCATION.strip()).rstrip('/\\')
if CUSTOM_GIZMO_LOCATION and os.path.isdir(CUSTOM_GIZMO_LOCATION):
gizManager = GizmoPathManager(searchPaths=[CUSTOM_GIZMO_LOCATION])
else:
gizManager = GizmoPathManager()
gizManager.addGizmoPaths()
if not nuke.GUI:
del gizManager