lib/import/flame_stabilizer.rb in tracksperanto-3.3.6 vs lib/import/flame_stabilizer.rb in tracksperanto-3.3.7
- old
+ new
@@ -63,62 +63,71 @@
def channel_is_useful?(channel_name)
USEFUL_CHANNELS.any?{|e| channel_name =~ e }
end
end
+ # Extracts the animation channels and stores them in Obufs
+ # keyed by the channel path (like "tracker1/ref/x")
def extract_channels_from_stream(io)
parser = StabilizerParser.new
parser.logger_proc = method(:report_progress)
- channels = Obuf.new
- names = []
+ channel_map = {}
parser.parse(io) do | channel |
- channels.push(channel)
- names.push(channel.path)
+ # Serialize the channel and store it on disk.
+ # Flame stabilizers are NOT likely to contain hundreds of
+ # trackers unless they were machine-exported from something,
+ # but we need to be memory-aware when we do things like this.
+ # On our test suite we lose half a second on disk IO overhead
+ # of the Obuf here, which is an acceptable compromise.
+ # To get rid of the disk-based cache just toss the outer
+ # Obuf constructor and pass in an Array
+ channel_map[channel.path] = Obuf.new([channel])
end
- [channels, names]
+ channel_map
end
- def scavenge_trackers_from_channels(channels, names)
- channels.each do |c|
- next unless c.name =~ /\/ref\/x/
+ def scavenge_trackers_from_channels(channel_map, names)
+ # Use Hash#keys.sort because we want a consistent export order
+ # irregardless of the Ruby version in use
+ # (hash keys are ordered on 1.9 and not ordered on 1.8)
+ channel_map.keys.sort.each do |c|
+ next unless c =~ /\/ref\/x$/
- report_progress("Detected reference channel #{c.name}")
+ report_progress("Detected reference channel #{c.inspect}")
- t = grab_tracker(channels, c, names)
- yield(t) if t
+ extracted_tracker = grab_tracker(channel_map, c)
+ if extracted_tracker
+ yield(extracted_tracker)
+ end
end
end
def channel_to_frames_and_values(chan)
chan.map{|key| [key.frame, key.value]}
end
- def grab_tracker(channels, track_x, names)
- t = Tracksperanto::Tracker.new(:name => track_x.name.split('/').shift)
+ def grab_tracker(channel_map, ref_x_channel_name)
+ t = Tracksperanto::Tracker.new(:name => ref_x_channel_name.split('/').shift)
report_progress("Extracting tracker #{t.name}")
- # This takes a LONG time when we have alot of channels, we need a precache of
- # some sort to do this
- ref_idx = names.index("#{t.name}/ref/y")
- shift_x_idx = names.index("#{t.name}/shift/x")
- shift_y_idx = names.index("#{t.name}/shift/y")
+ shift_x = channel_map["#{t.name}/shift/x"][0]
+ shift_y = channel_map["#{t.name}/shift/y"][0]
+ ref_x = channel_map["#{t.name}/ref/x"][0]
+ ref_y = channel_map["#{t.name}/ref/y"][0]
- track_y = channels[ref_idx]
- shift_x = channels[shift_x_idx]
- shift_y = channels[shift_y_idx]
-
+ # Collapse separate X and Y curves into series of XY values
shift_tuples = zip_curve_tuples(channel_to_frames_and_values(shift_x), channel_to_frames_and_values(shift_y))
- track_tuples = zip_curve_tuples(channel_to_frames_and_values(track_x), channel_to_frames_and_values(track_y))
+ ref_tuples = zip_curve_tuples(channel_to_frames_and_values(ref_x), channel_to_frames_and_values(ref_y))
# If the channels are just empty go to next tracker
- return if shift_tuples.empty? || track_tuples.empty?
+ return if shift_tuples.empty? || ref_tuples.empty?
report_progress("Detecting base value")
- base_x, base_y = find_base_x_and_y(track_tuples, shift_tuples)
+ base_x, base_y = find_base_x_and_y(ref_tuples, shift_tuples)
total_kf = 1
t.keyframes = shift_tuples.map do | (at, x, y) |
# Flame keyframes are sort of minus-one based, so to start at frame 0
# we need to decrement one frame, always. Also, the shift value is inverted!
@@ -129,12 +138,12 @@
end
return t
end
- def find_base_x_and_y(track_tuples, shift_tuples)
- base_track_tuple = track_tuples.find do | track_tuple |
+ def find_base_x_and_y(ref_tuples, shift_tuples)
+ base_ref_tuple = ref_tuples.find do | track_tuple |
shift_tuples.find { |shift_tuple| shift_tuple[0] == track_tuple[0] }
end
- (base_track_tuple || track_tuples[0])[1..2]
+ (base_ref_tuple || ref_tuples[0])[1..2]
end
end