forked from qLab/qLib
-
Notifications
You must be signed in to change notification settings - Fork 4
Expand file tree
/
Copy pathqlibutils.py
More file actions
237 lines (162 loc) · 5.37 KB
/
Copy pathqlibutils.py
File metadata and controls
237 lines (162 loc) · 5.37 KB
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
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
"""
@file qlibutils.py
@author xy
@since 2012-07-23
@brief qLib-related utility functions.
Location: $HIH/scripts/python/
"""
import hou
import glob
import os
import platform
import re
import subprocess
import traceback
# TODO: msg functions with exception handling
def is_platform(name='none'):
return name.lower() in platform.system().lower()
def is_linux(): return is_platform('linux')
def is_windows(): return is_platform('win')
def is_mac(): return is_platform('mac')
def statmsg(msg, warn=False):
'''.'''
s = hou.severityType.Warning if warn else hou.severityType.Message
if hou.isUIAvailable():
hou.ui.setStatusMessage(msg, severity=s)
def set_namespace_aliases(prefix="qLib::", alias=True, verbose=False):
"""
Defines (non-)namespaced aliases for operators with a particular namespace prefix.
This is used for always creating the namespaced versions of assets, even if an
older .hip file contains non-namespaced asset names.
Mapping looks like: <opname> --> <prefix>::<opname>::<version>
@note
IMPORTANT: Although the manual says it's fine to omit the version of a
namespaced asset (and that would refer to the latest version),
omitting it results in files getting messed up when loaded,
so version numbers _are_ included in the opaliases.
@note
This function should be called (preferably) on Houdini startup, e.g.
import qlibutils
qlibutils.set_namespace_aliases( ["qLib::", "myStuff::"] )
@todo
For each asset, the highest version number should be found and used.
Right now it uses the first version it founds (which is fine for now).
"""
if type(prefix) is list:
for p in prefix: set_namespace_aliases(p)
return
assert "::" in prefix, "Include trailing '::' characters in prefix"
cmds = []
for file in hou.hda.loadedFiles():
names = [ (d.nodeType().name(), d.nodeTypeCategory().name()) \
for d in list(hou.hda.definitionsInFile(file)) \
if prefix in d.nodeType().name() ]
for n in names:
try:
# strip namespace prefix and version suffix
old = re.sub("^[^:]+::", "", n[0])
old = re.search("^[^:]+", old).group(0)
# opalias <network> <namespaced-op.> <plain-old-op.>
cmd = "opalias %s %s %s" % (n[1], n[0], old)
if cmd not in cmds:
if verbose: print cmd
if alias: hou.hscript(cmd)
cmds.append(cmd)
else:
print "# ALREADY ALIASED: %s (%s)" % (cmd, file)
except:
print "ERROR: %s" % traceback.format_exc()
def do_crash_recovery(calledFromUI=False):
tmpdir = str(hou.getenv("TEMP"))
files = glob.glob( os.path.join(tmpdir, '*.hip') )
uicall = calledFromUI
if hou.isUIAvailable() and len(files)>0:
td = os.path.join(tmpdir, '') # dir with '/'
files = [ (f, os.path.getmtime(f), ) for f in files ]
files = sorted(files, key=lambda f: f[1], reverse=True)
files = [ str(re.sub('^%s' % td, '', f[0])) for f in files ]
sel = hou.ui.selectFromList(files, exclusive=True,
title="Crash Recovery",
message="Select .hip File to Recover")
recovered = False
if len(sel)>0:
f = files[sel[0]]
fn = os.path.join(tmpdir, f)
# extract HIPNAME
f = re.sub('^crash.', '', f)
f = re.sub('\..+_[0-9]+\.hip', '.hip', f)
# do recovery
try:
hou.hipFile.clear(True)
hou.hipFile.load(fn, True)
hou.setUpdateMode(hou.updateMode.Manual)
recovered = True
except:
hou.ui.setStatusMessage("error while recovering file %s" % fn, hou.severityType.Error)
print "ERROR: %s" % traceback.format_exc()
hou.hipFile.setName(f)
# delete crash file(s)
msg = 'Cleanup: Delete all crash recovery hip files?'
if recovered:
msg = \
'File recovered. Make sure to save it to a safe location.\n' \
'NOTE: Update mode is set to "Manual" to avoid potential re-crashes.\n' \
'\n%s' % msg
d = hou.ui.displayMessage(msg, buttons=("DELETE", "Skip", ))
if d==0:
files = \
glob.glob( os.path.join(tmpdir, 'crash.*') ) + \
glob.glob( os.path.join(tmpdir, '*.hip') )
for f in files:
try:
os.remove(f)
except:
pass
hou.ui.setStatusMessage("crash recovery cleanup: deleted %d files" % len(files))
else:
pass # user cancelled
else:
# no crash files found
#
if uicall:
hou.ui.setStatusMessage(" Crash Recovery: No emergency-saved .hip file(s) found -- nothing to recover.", hou.severityType.ImportantMessage)
pass
def open_dir(dir="", env=None):
'''.'''
dir=str(dir)
if env:
dir = str(hou.getenv(env))
if not os.path.exists(dir):
statmsg("Directory doesn't exist (%s)" % dir, warn=True)
return
if is_linux():
statmsg("(linux) xdg-open %s" % dir)
subprocess.call(["xdg-open", dir])
if is_windows():
dir = dir.replace('/', '\\')
statmsg("(windows) start %s" % dir)
subprocess.call(["start", dir])
if is_mac():
statmsg("(mac) open %s" % dir)
subprocess.call(["open", dir])
def find_camera(oppattern, path=None):
'''Finds a camera OBJ within nested subnets and returns its full path.'''
r = ''
try:
root = hou.pwd()
if path: root = hou.node(path)
root = root.glob(oppattern)
if len(root)>0:
cam = [ n.path() for n in root[0].allSubChildren() if n.type().name()=='cam' ]
if len(cam)>0:
r = cam[0]
else:
pass # no camera found
else:
pass # no root node found
except:
pass # TODO: error handling
return r
def backup_rop_output_file():
'''Creates a dated backup of an output file of a ROP. Useful as a ROP Pre-Render call.'''
pass