Skip to content

Instantly share code, notes, and snippets.

@MitchellKehn
Last active December 24, 2019 10:56
Show Gist options
  • Save MitchellKehn/3484bad294049b457b100e9a0c588e4e to your computer and use it in GitHub Desktop.
Save MitchellKehn/3484bad294049b457b100e9a0c588e4e to your computer and use it in GitHub Desktop.
[nuke track exporter] Exporter for nuke 2D tracks into PFTrack-importable format. Exporter not quite working, but has some attribute access stuff that could prove useful #nuke #pftrack
"""
Export a nuke tracker node to an ACII file that can be read by PFTrack
"""
from math import sqrt
HEADER = """\
# "Name"
# clipNumber
# frameCount
# frame, xpos, ypos, similarity
"""
ATTRS = [
"e", "name", "track_x", "track_y", "offset_x", "offset_y", "T", "R", "S",
"error", "error_min", "error_max",
"pattern_x", "pattern_y", "pattern_r", "pattern_t",
"search_x", "search_y", "search_r", "search_t",
"key_track", "key_search_x", "key_search_y", "key_search_r", "key_search_t",
"key_track_x", "key_track_y", "key_track_r", "key_track_t",
"key_centre_offset_x", "key_centre_offset_y"
]
COL_COUNT = 31
RESIZE = 1520.0 / 4448.0
def attrIndex(attribute, row):
"""
Get the index of an attribute of the Tracker node
@param attribute: the name of the attribute
@param row: the row of the table you're accessing
"""
col = ATTRS.index(attribute)
return row * COL_COUNT + col
def trackCount(tracker):
"""@return the number of trackers on the selected node"""
tracks = 0
while node.knob('tracks').isAnimated(31 * tracks + 2):
tracks += 1
return tracks
def trackRange(tracker, row, first, last):
"""@return: frame range where there are keyframes for the given row. None, None if there are none"""
tracks = tracker["tracks"]
# work out first frame by stepping forwards
firstKey = first
while firstKey < last:
if tracks.isKeyAt(firstKey, attrIndex("track_x", row)) or \
tracks.isKeyAt(firstKey, attrIndex("track_y", row)):
break
firstKey += 1
else:
return None, None
# work out last frame by stepping backwards
lastKey = last
while lastKey > first:
if tracks.isKeyAt(lastKey, attrIndex("track_x", row)) or \
tracks.isKeyAt(lastKey, attrIndex("track_y", row)):
break
lastKey -= 1
return firstKey, lastKey
def getTrackNames(tracker4Node):
k = tracker4Node['tracks']
s = tracker4Node['tracks'].toScript().split(' \n} \n{ \n ')
s.pop(0)
ss = str(s)[2:].split('\\n')
if ss:
ss.pop(-1)
if ss:
ss.pop(-1)
outList = []
for i in ss:
outList.append(i.split('"')[1])
return outList
def exportTracker(tracker):
frange, views = nuke.getFramesAndViews("frame range", "{}-{}".format(nuke.root().firstFrame(), nuke.root().lastFrame()))
frange = frange.split("-")
firstFrame, lastFrame = int(frange[0]), int(frange[-1])
tracks = tracker["tracks"]
fp = nuke.getFilename("Path to ASCII file", "*.txt")
with open(fp, "w") as file:
file.write(HEADER)
for row in range(trackCount(tracker)):
firstKey, lastKey = trackRange(tracker, row, firstFrame, lastFrame)
if any([firstKey == lastKey, firstKey is None, lastKey is None]):
print "no keys in row", row
continue # there are no keyframes on this track
file.write("\n")
# print tracks.getValue(attrIndex("name", row)) # can't get strings from values key_search_t
file.write('"NukeTrack{:04d}"\n'.format(row+1))
file.write("1\n")
file.write("{}\n".format(lastKey - firstKey + 1))
for frame in range(firstKey, lastKey + 1):
xpos = tracks.getValueAt(frame, attrIndex("track_x", row))
ypos = tracks.getValueAt(frame, attrIndex("track_y", row))
simi = 1 - sqrt(tracks.getValueAt(frame, attrIndex("error", row)))
file.write("{} {} {} {}\n".format(frame, xpos * RESIZE, ypos * RESIZE, simi))
file.write("\n")
with open(fp, "r") as file:
print file.read()
if __name__ == "__main__":
node = nuke.selectedNode()
exportTracker(node)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment