tracksperanto 2.2.4 → 2.3.0
Sign up to get free protection for your applications and to get access to all the features.
- data/History.txt +6 -0
- data/MIT_LICENSE.txt +1 -1
- data/Manifest.txt +1 -0
- data/bin/tracksperanto +3 -3
- data/lib/export/flame_stabilizer.rb +8 -1
- data/lib/import/flame_stabilizer.rb +65 -49
- data/lib/import/shake_grammar/lexer.rb +1 -1
- data/lib/import/shake_script.rb +1 -1
- data/lib/import/syntheyes.rb +1 -0
- data/lib/pipeline/base.rb +39 -37
- data/lib/tracksperanto.rb +1 -1
- data/lib/tracksperanto/accumulator.rb +43 -12
- data/lib/tracksperanto/buffer_io.rb +26 -10
- data/lib/tracksperanto/pbar.rb +13 -0
- data/test/export/samples/ref_flame.stabilizer +25 -24
- data/test/import/test_flame_import.rb +1 -2
- data/test/test_accumulator.rb +43 -0
- data/test/test_buffer_io.rb +11 -0
- metadata +6 -5
data/History.txt
CHANGED
@@ -1,3 +1,9 @@
|
|
1
|
+
=== 2.3.0 / 2011-17-04
|
2
|
+
|
3
|
+
* Fixed issue#1 (Last tracker in some Flame exports receives an empty shift channel)
|
4
|
+
* Nicer progress reports
|
5
|
+
* Modified the Accumulator to support nested iterations and random access
|
6
|
+
|
1
7
|
=== 2.2.4 / 2011-04-04
|
2
8
|
|
3
9
|
* Properly deal with negative frames happening in Shake scripts sometimes. We will now recognize a script starting at negative
|
data/MIT_LICENSE.txt
CHANGED
data/Manifest.txt
CHANGED
@@ -56,6 +56,7 @@ lib/tracksperanto/ext_io.rb
|
|
56
56
|
lib/tracksperanto/flame_builder.rb
|
57
57
|
lib/tracksperanto/format_detector.rb
|
58
58
|
lib/tracksperanto/keyframe.rb
|
59
|
+
lib/tracksperanto/pbar.rb
|
59
60
|
lib/tracksperanto/progressive_io.rb
|
60
61
|
lib/tracksperanto/returning.rb
|
61
62
|
lib/tracksperanto/safety.rb
|
data/bin/tracksperanto
CHANGED
@@ -17,6 +17,7 @@ require 'progressbar'
|
|
17
17
|
require "net/http"
|
18
18
|
require "open-uri"
|
19
19
|
require "timeout"
|
20
|
+
require File.dirname(__FILE__) + '/../lib/tracksperanto/pbar'
|
20
21
|
|
21
22
|
def version_check(version_present)
|
22
23
|
begin
|
@@ -104,12 +105,11 @@ unless File.exist?(input_file)
|
|
104
105
|
exit(-1)
|
105
106
|
end
|
106
107
|
|
107
|
-
pbar =
|
108
|
-
pipe = Tracksperanto::Pipeline::Base.new(:progress_block => lambda{|p,m| pbar.
|
108
|
+
pbar = Tracksperanto::PBar.new("Converting", 100, $stderr)
|
109
|
+
pipe = Tracksperanto::Pipeline::Base.new(:progress_block => lambda{|p,m| pbar.set_with_message(p, m) }, :middleware_tuples => $middlewares)
|
109
110
|
pipe.exporters = [Tracksperanto.get_exporter(writer_klass_name)] if writer_klass_name
|
110
111
|
pipe.run(input_file, options)
|
111
112
|
pbar.finish
|
112
113
|
|
113
|
-
puts "Converted #{pipe.converted_points} trackers with #{pipe.converted_keyframes} keys."
|
114
114
|
puts disclaimer
|
115
115
|
version_check(Tracksperanto::VERSION)
|
@@ -44,6 +44,9 @@ class Tracksperanto::Export::FlameStabilizer < Tracksperanto::Export::Base
|
|
44
44
|
t.tolerance 100
|
45
45
|
end
|
46
46
|
end
|
47
|
+
|
48
|
+
# Write the finalizing "End"
|
49
|
+
@writer.write_loose!("end")
|
47
50
|
end
|
48
51
|
|
49
52
|
def start_tracker_segment(tracker_name)
|
@@ -66,6 +69,11 @@ class Tracksperanto::Export::FlameStabilizer < Tracksperanto::Export::Base
|
|
66
69
|
# how many keyframes they should contain
|
67
70
|
write_shift_channel("shift/x", @x_shift_values)
|
68
71
|
write_shift_channel("shift/y", @y_shift_values)
|
72
|
+
|
73
|
+
# And finish with the offset channels. The order of channels is important!
|
74
|
+
# (otherwise the last tracker's shift animation is not imported by Flame)
|
75
|
+
# https://github.com/guerilla-di/tracksperanto/issues/1
|
76
|
+
write_offset_channels
|
69
77
|
end
|
70
78
|
|
71
79
|
private
|
@@ -140,7 +148,6 @@ class Tracksperanto::Export::FlameStabilizer < Tracksperanto::Export::Base
|
|
140
148
|
write_ref_width_and_height
|
141
149
|
write_ref_channels(x, y)
|
142
150
|
write_deltax_and_deltay_channels
|
143
|
-
write_offset_channels
|
144
151
|
end
|
145
152
|
|
146
153
|
def write_track_channels
|
@@ -75,13 +75,15 @@ class Tracksperanto::Import::FlameStabilizer < Tracksperanto::Import::Base
|
|
75
75
|
report_progress("Extracting setup size")
|
76
76
|
self.width, self.height = extract_width_and_height_from_stream(@io)
|
77
77
|
report_progress("Extracting all animation channels")
|
78
|
-
channels = extract_channels_from_stream(@io)
|
78
|
+
channels, names = extract_channels_from_stream(@io)
|
79
79
|
|
80
80
|
raise "The setup contained no channels that we could process" if channels.empty?
|
81
81
|
raise "A channel was nil" if channels.find{|e| e.nil? }
|
82
82
|
|
83
83
|
report_progress("Assembling tracker curves from channels")
|
84
|
-
scavenge_trackers_from_channels(channels) {|t| yield(t) }
|
84
|
+
scavenge_trackers_from_channels(channels, names) {|t| yield(t) }
|
85
|
+
ensure
|
86
|
+
channels.clear
|
85
87
|
end
|
86
88
|
|
87
89
|
private
|
@@ -103,54 +105,20 @@ class Tracksperanto::Import::FlameStabilizer < Tracksperanto::Import::Base
|
|
103
105
|
end
|
104
106
|
|
105
107
|
end
|
106
|
-
=begin
|
107
|
-
Here's how a Flame channel looks like
|
108
|
-
The Size will not be present if there are no keyframes
|
109
|
-
|
110
|
-
Channel tracker1/ref/x
|
111
|
-
Extrapolation constant
|
112
|
-
Value 770.41
|
113
|
-
Size 4
|
114
|
-
KeyVersion 1
|
115
|
-
Key 0
|
116
|
-
Frame 1
|
117
|
-
Value 770.41
|
118
|
-
Interpolation constant
|
119
|
-
End
|
120
|
-
Key 1
|
121
|
-
Frame 44
|
122
|
-
Value 858.177
|
123
|
-
Interpolation constant
|
124
|
-
RightSlope 2.31503
|
125
|
-
LeftSlope 2.31503
|
126
|
-
End
|
127
|
-
Key 2
|
128
|
-
Frame 74
|
129
|
-
Value 939.407
|
130
|
-
Interpolation constant
|
131
|
-
RightSlope 2.24201
|
132
|
-
LeftSlope 2.24201
|
133
|
-
End
|
134
|
-
Key 3
|
135
|
-
Frame 115
|
136
|
-
Value 1017.36
|
137
|
-
Interpolation constant
|
138
|
-
End
|
139
|
-
Colour 50 50 50
|
140
|
-
End
|
141
|
-
=end
|
142
108
|
|
143
109
|
def extract_channels_from_stream(io)
|
144
|
-
channels =
|
110
|
+
channels = Tracksperanto::Accumulator.new
|
111
|
+
names = []
|
145
112
|
channel_matcher = /Channel (.+)\n/
|
146
113
|
until io.eof?
|
147
114
|
line = io.gets
|
148
115
|
if line =~ channel_matcher && channel_is_useful?(line)
|
149
116
|
report_progress("Extracting channel #{$1}")
|
150
117
|
channels << ChannelBlock.new(io, $1)
|
118
|
+
names << $1
|
151
119
|
end
|
152
120
|
end
|
153
|
-
channels
|
121
|
+
[channels, names]
|
154
122
|
end
|
155
123
|
|
156
124
|
USEFUL_CHANNELS = %w( /shift/x /shift/y /ref/x /ref/y ).map(&Regexp.method(:new))
|
@@ -166,21 +134,32 @@ Channel tracker1/ref/x
|
|
166
134
|
|
167
135
|
REF_CHANNEL = "ref" # or "track" - sometimes works sometimes don't
|
168
136
|
|
169
|
-
def scavenge_trackers_from_channels(channels)
|
170
|
-
|
171
|
-
|
172
|
-
|
137
|
+
def scavenge_trackers_from_channels(channels, names)
|
138
|
+
|
139
|
+
|
140
|
+
channels.each do |c|
|
141
|
+
next unless c.name =~ /\/#{REF_CHANNEL}\/x/
|
142
|
+
|
143
|
+
report_progress("Detected reference channel #{c.name}")
|
144
|
+
|
145
|
+
yield grab_tracker(channels, c, names)
|
173
146
|
end
|
174
147
|
end
|
175
148
|
|
176
|
-
def grab_tracker(channels, track_x)
|
149
|
+
def grab_tracker(channels, track_x, names)
|
177
150
|
t = Tracksperanto::Tracker.new(:name => track_x.name.split('/').shift)
|
178
151
|
|
179
152
|
report_progress("Extracting tracker #{t.name}")
|
180
153
|
|
181
|
-
|
182
|
-
|
183
|
-
|
154
|
+
# This takes a LONG time when we have alot of channels, we need a precache of
|
155
|
+
# some sort to do this
|
156
|
+
ref_idx = names.index("#{t.name}/#{REF_CHANNEL}/y")
|
157
|
+
shift_x_idx = names.index("#{t.name}/shift/x")
|
158
|
+
shift_y_idx = names.index("#{t.name}/shift/y")
|
159
|
+
|
160
|
+
track_y = channels[ref_idx]
|
161
|
+
shift_x = channels[shift_x_idx]
|
162
|
+
shift_y = channels[shift_y_idx]
|
184
163
|
|
185
164
|
shift_tuples = zip_curve_tuples(shift_x, shift_y)
|
186
165
|
track_tuples = zip_curve_tuples(track_x, track_y)
|
@@ -207,4 +186,41 @@ Channel tracker1/ref/x
|
|
207
186
|
end || track_tuples[0]
|
208
187
|
base_track_tuple[1..2]
|
209
188
|
end
|
210
|
-
end
|
189
|
+
end
|
190
|
+
|
191
|
+
__END__
|
192
|
+
|
193
|
+
Here's how a Flame channel looks like
|
194
|
+
The Size will not be present if there are no keyframes
|
195
|
+
|
196
|
+
Channel tracker1/ref/x
|
197
|
+
Extrapolation constant
|
198
|
+
Value 770.41
|
199
|
+
Size 4
|
200
|
+
KeyVersion 1
|
201
|
+
Key 0
|
202
|
+
Frame 1
|
203
|
+
Value 770.41
|
204
|
+
Interpolation constant
|
205
|
+
End
|
206
|
+
Key 1
|
207
|
+
Frame 44
|
208
|
+
Value 858.177
|
209
|
+
Interpolation constant
|
210
|
+
RightSlope 2.31503
|
211
|
+
LeftSlope 2.31503
|
212
|
+
End
|
213
|
+
Key 2
|
214
|
+
Frame 74
|
215
|
+
Value 939.407
|
216
|
+
Interpolation constant
|
217
|
+
RightSlope 2.24201
|
218
|
+
LeftSlope 2.24201
|
219
|
+
End
|
220
|
+
Key 3
|
221
|
+
Frame 115
|
222
|
+
Value 1017.36
|
223
|
+
Interpolation constant
|
224
|
+
End
|
225
|
+
Colour 50 50 50
|
226
|
+
End
|
data/lib/import/shake_script.rb
CHANGED
@@ -243,7 +243,7 @@ class Tracksperanto::Import::ShakeScript < Tracksperanto::Import::Base
|
|
243
243
|
def collect_stabilizer_tracker(name, x_curve, y_curve)
|
244
244
|
return unless valid_curves?(x_curve, y_curve)
|
245
245
|
|
246
|
-
report_progress("
|
246
|
+
report_progress("Assembling Stabilizer node tracker #{name}")
|
247
247
|
|
248
248
|
keyframes = zip_curve_tuples(x_curve, y_curve).map do | (frame, x, y) |
|
249
249
|
Tracksperanto::Keyframe.new(:frame => frame - 1, :abs_x => x, :abs_y => y)
|
data/lib/import/syntheyes.rb
CHANGED
data/lib/pipeline/base.rb
CHANGED
@@ -140,52 +140,54 @@ module Tracksperanto::Pipeline
|
|
140
140
|
@ios.push(io_with_progress)
|
141
141
|
|
142
142
|
@accumulator = Tracksperanto::Accumulator.new
|
143
|
+
begin
|
144
|
+
|
145
|
+
# OBSOLETE - for this version we are going to permit it.
|
146
|
+
if importer.respond_to?(:stream_parse)
|
147
|
+
STDERR.puts "Import::Base#stream_parse(io) is obsolete, please rewrite your importer to use each instead"
|
148
|
+
importer.receiver = @accumulator
|
149
|
+
importer.stream_parse(io_with_progress)
|
150
|
+
else
|
151
|
+
importer.io = io_with_progress
|
152
|
+
importer.each {|t| @accumulator.push(t) unless t.empty? }
|
153
|
+
end
|
143
154
|
|
144
|
-
|
145
|
-
|
146
|
-
STDERR.puts "Import::Base#stream_parse(io) is obsolete, please rewrite your importer to use each instead"
|
147
|
-
importer.receiver = @accumulator
|
148
|
-
importer.stream_parse(io_with_progress)
|
149
|
-
else
|
150
|
-
importer.io = io_with_progress
|
151
|
-
importer.each {|t| @accumulator.push(t) unless t.empty? }
|
152
|
-
end
|
153
|
-
|
154
|
-
report_progress(percent_complete = 50.0, "Validating #{@accumulator.size} imported trackers")
|
155
|
-
raise NoTrackersRecoveredError if @accumulator.size.zero?
|
155
|
+
report_progress(percent_complete = 50.0, "Validating #{@accumulator.size} imported trackers")
|
156
|
+
raise NoTrackersRecoveredError if @accumulator.size.zero?
|
156
157
|
|
157
|
-
|
158
|
+
report_progress(percent_complete, "Starting export")
|
158
159
|
|
159
|
-
|
160
|
+
percent_per_tracker = (100.0 - percent_complete) / @accumulator.size
|
160
161
|
|
161
|
-
|
162
|
-
|
162
|
+
# Use the width and height provided by the parser itself
|
163
|
+
exporter.start_export(importer.width, importer.height)
|
163
164
|
|
164
|
-
|
165
|
-
|
165
|
+
# Now send each tracker through the middleware chain
|
166
|
+
@accumulator.each_with_index do | t, tracker_idx |
|
166
167
|
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
168
|
+
kf_weight = percent_per_tracker / t.keyframes.length
|
169
|
+
points += 1
|
170
|
+
exporter.start_tracker_segment(t.name)
|
171
|
+
t.each_with_index do | kf, idx |
|
172
|
+
keyframes += 1
|
173
|
+
exporter.export_point(kf.frame, kf.abs_x, kf.abs_y, kf.residual)
|
174
|
+
report_progress(
|
175
|
+
percent_complete += kf_weight,
|
176
|
+
"Writing keyframe #{idx+1} of #{t.name.inspect}, #{@accumulator.size - tracker_idx} trackers to go"
|
177
|
+
)
|
178
|
+
end
|
179
|
+
exporter.end_tracker_segment
|
177
180
|
end
|
178
|
-
exporter.
|
179
|
-
end
|
180
|
-
exporter.end_export
|
181
|
+
exporter.end_export
|
181
182
|
|
182
|
-
|
183
|
+
report_progress(100.0, "Wrote #{points} points and #{keyframes} keyframes")
|
183
184
|
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
185
|
+
[points, keyframes]
|
186
|
+
ensure
|
187
|
+
@accumulator.clear
|
188
|
+
@ios.map!{|e| e.close! rescue e.close }
|
189
|
+
@ios.clear
|
190
|
+
end
|
189
191
|
end
|
190
192
|
|
191
193
|
# Setup output files and return a single output
|
data/lib/tracksperanto.rb
CHANGED
@@ -17,26 +17,27 @@
|
|
17
17
|
class Tracksperanto::Accumulator
|
18
18
|
include Enumerable
|
19
19
|
|
20
|
+
DELIM = "\n"
|
21
|
+
|
20
22
|
# Returns the number of objects stored so far
|
21
23
|
attr_reader :size
|
22
24
|
|
23
25
|
def initialize
|
24
26
|
@store = Tracksperanto::BufferIO.new
|
25
|
-
|
26
27
|
@size = 0
|
27
|
-
@byte_size = 0
|
28
28
|
|
29
29
|
super
|
30
30
|
end
|
31
31
|
|
32
|
+
def empty?
|
33
|
+
@size.zero?
|
34
|
+
end
|
35
|
+
|
32
36
|
# Store an object
|
33
37
|
def push(object_to_store)
|
34
|
-
@store.seek(@byte_size)
|
35
|
-
|
36
38
|
blob = marshal_object(object_to_store)
|
37
39
|
@store.write(blob)
|
38
40
|
@size += 1
|
39
|
-
@byte_size = @byte_size + blob.size
|
40
41
|
|
41
42
|
object_to_store
|
42
43
|
end
|
@@ -46,27 +47,57 @@ class Tracksperanto::Accumulator
|
|
46
47
|
# Retreive each stored object in succession. All other Enumerable
|
47
48
|
# methods are also available (but be careful with Enumerable#map and to_a)
|
48
49
|
def each
|
49
|
-
|
50
|
-
|
50
|
+
with_separate_read_io do | iterable |
|
51
|
+
@size.times { yield(recover_object_from(iterable)) }
|
52
|
+
end
|
51
53
|
end
|
52
54
|
|
53
55
|
# Calls close! on the datastore and deletes the objects in it
|
54
56
|
def clear
|
55
57
|
@store.close!
|
56
58
|
@size = 0
|
57
|
-
|
59
|
+
end
|
60
|
+
|
61
|
+
# Retreive a concrete object at index
|
62
|
+
def [](idx)
|
63
|
+
idx.respond_to?(:each) ? idx.map{|i| recover_at(i) } : recover_at(idx)
|
58
64
|
end
|
59
65
|
|
60
66
|
private
|
61
67
|
|
68
|
+
def recover_at(idx)
|
69
|
+
with_separate_read_io do | iterable |
|
70
|
+
iterable.seek(0)
|
71
|
+
|
72
|
+
# Do not unmarshal anything but wind the IO in fixed offsets
|
73
|
+
idx.times do
|
74
|
+
skip_bytes = iterable.gets("\t").to_i
|
75
|
+
iterable.seek(iterable.pos + skip_bytes)
|
76
|
+
end
|
77
|
+
|
78
|
+
recover_object_from(iterable)
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
# We first ensure that we have a disk-backed file, then reopen it as read-only
|
83
|
+
# and iterate through that (we will have one IO handle per loop nest)
|
84
|
+
def with_separate_read_io
|
85
|
+
iterable = File.open(@store.to_file.path, "r")
|
86
|
+
yield(iterable)
|
87
|
+
ensure
|
88
|
+
iterable.close
|
89
|
+
end
|
90
|
+
|
62
91
|
def marshal_object(object_to_store)
|
63
92
|
d = Marshal.dump(object_to_store)
|
64
|
-
blob = [d.size, "\t", d,
|
93
|
+
blob = [d.size, "\t", d, DELIM].join
|
65
94
|
end
|
66
95
|
|
67
|
-
def
|
96
|
+
def recover_object_from(io)
|
68
97
|
# Up to the tab is the amount of bytes to read
|
69
|
-
demarshal_bytes =
|
70
|
-
|
98
|
+
demarshal_bytes = io.gets("\t").to_i
|
99
|
+
blob = io.read(demarshal_bytes)
|
100
|
+
|
101
|
+
Marshal.load(blob)
|
71
102
|
end
|
72
103
|
end
|
@@ -30,18 +30,34 @@ class Tracksperanto::BufferIO < DelegateClass(IO)
|
|
30
30
|
__setobj__(nil)
|
31
31
|
end
|
32
32
|
|
33
|
+
# Sometimes you just need to upgrade to a File forcibly (for example if you want)
|
34
|
+
# to have an object with many iterators sitting on it. We also flush here.
|
35
|
+
def to_file
|
36
|
+
replace_with_tempfile unless @tempfile_in
|
37
|
+
flush
|
38
|
+
self
|
39
|
+
end
|
40
|
+
|
41
|
+
# Tells whether this one is on disk
|
42
|
+
def file_backed?
|
43
|
+
@tempfile_in
|
44
|
+
end
|
45
|
+
|
33
46
|
private
|
34
47
|
|
48
|
+
def replace_with_tempfile
|
49
|
+
sio = __getobj__
|
50
|
+
tf = Tempfile.new("tracksperanto-xbuf")
|
51
|
+
tf.write(sio.string)
|
52
|
+
tf.flush # Needed of we will reopen this file soon from another thread/loop
|
53
|
+
sio.string = ""
|
54
|
+
GC.start
|
55
|
+
__setobj__(tf)
|
56
|
+
|
57
|
+
@tempfile_in = true
|
58
|
+
end
|
59
|
+
|
35
60
|
def replace_with_tempfile_if_needed
|
36
|
-
|
37
|
-
io = __getobj__
|
38
|
-
if io.pos > MAX_IN_MEM_BYTES
|
39
|
-
tf = Tempfile.new("tracksperanto-xbuf")
|
40
|
-
tf.write(io.string)
|
41
|
-
io.string = ""
|
42
|
-
GC.start
|
43
|
-
__setobj__(tf)
|
44
|
-
@tempfile_in = true
|
45
|
-
end
|
61
|
+
replace_with_tempfile if !@tempfile_in && pos > MAX_IN_MEM_BYTES
|
46
62
|
end
|
47
63
|
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
# We make use of the implementation details of the progress bar to also show our current status
|
2
|
+
class Tracksperanto::PBar < ::ProgressBar
|
3
|
+
|
4
|
+
def fmt_title
|
5
|
+
"%20s" % @title
|
6
|
+
end
|
7
|
+
|
8
|
+
def set_with_message(pcnt, message)
|
9
|
+
@title = message
|
10
|
+
set(pcnt)
|
11
|
+
end
|
12
|
+
|
13
|
+
end
|
@@ -122,14 +122,6 @@ Channel tracker1/ref/dy
|
|
122
122
|
Interpolation constant
|
123
123
|
End
|
124
124
|
End
|
125
|
-
Channel tracker1/offset/x
|
126
|
-
Extrapolation constant
|
127
|
-
Value 0
|
128
|
-
End
|
129
|
-
Channel tracker1/offset/y
|
130
|
-
Extrapolation constant
|
131
|
-
Value 0
|
132
|
-
End
|
133
125
|
Channel tracker1/shift/x
|
134
126
|
Extrapolation constant
|
135
127
|
Value 0
|
@@ -408,6 +400,14 @@ Channel tracker1/shift/y
|
|
408
400
|
RightSlope 2.400
|
409
401
|
End
|
410
402
|
End
|
403
|
+
Channel tracker1/offset/x
|
404
|
+
Extrapolation constant
|
405
|
+
Value 0
|
406
|
+
End
|
407
|
+
Channel tracker1/offset/y
|
408
|
+
Extrapolation constant
|
409
|
+
Value 0
|
410
|
+
End
|
411
411
|
Channel tracker2/track/x
|
412
412
|
Extrapolation constant
|
413
413
|
Value 960
|
@@ -508,14 +508,6 @@ Channel tracker2/ref/dy
|
|
508
508
|
Interpolation constant
|
509
509
|
End
|
510
510
|
End
|
511
|
-
Channel tracker2/offset/x
|
512
|
-
Extrapolation constant
|
513
|
-
Value 0
|
514
|
-
End
|
515
|
-
Channel tracker2/offset/y
|
516
|
-
Extrapolation constant
|
517
|
-
Value 0
|
518
|
-
End
|
519
511
|
Channel tracker2/shift/x
|
520
512
|
Extrapolation constant
|
521
513
|
Value 0
|
@@ -794,6 +786,14 @@ Channel tracker2/shift/y
|
|
794
786
|
RightSlope 2.400
|
795
787
|
End
|
796
788
|
End
|
789
|
+
Channel tracker2/offset/x
|
790
|
+
Extrapolation constant
|
791
|
+
Value 0
|
792
|
+
End
|
793
|
+
Channel tracker2/offset/y
|
794
|
+
Extrapolation constant
|
795
|
+
Value 0
|
796
|
+
End
|
797
797
|
Channel tracker3/track/x
|
798
798
|
Extrapolation constant
|
799
799
|
Value 960
|
@@ -894,14 +894,6 @@ Channel tracker3/ref/dy
|
|
894
894
|
Interpolation constant
|
895
895
|
End
|
896
896
|
End
|
897
|
-
Channel tracker3/offset/x
|
898
|
-
Extrapolation constant
|
899
|
-
Value 0
|
900
|
-
End
|
901
|
-
Channel tracker3/offset/y
|
902
|
-
Extrapolation constant
|
903
|
-
Value 0
|
904
|
-
End
|
905
897
|
Channel tracker3/shift/x
|
906
898
|
Extrapolation constant
|
907
899
|
Value 0
|
@@ -928,6 +920,14 @@ Channel tracker3/shift/y
|
|
928
920
|
RightSlope 2.400
|
929
921
|
End
|
930
922
|
End
|
923
|
+
Channel tracker3/offset/x
|
924
|
+
Extrapolation constant
|
925
|
+
Value 0
|
926
|
+
End
|
927
|
+
Channel tracker3/offset/y
|
928
|
+
Extrapolation constant
|
929
|
+
Value 0
|
930
|
+
End
|
931
931
|
ChannelEnd
|
932
932
|
Tracker 0
|
933
933
|
Active yes
|
@@ -959,3 +959,4 @@ Tracker 2
|
|
959
959
|
FixedX no
|
960
960
|
FixedY no
|
961
961
|
Tolerance 100
|
962
|
+
End
|
@@ -151,8 +151,7 @@ class FlameImportTest < Test::Unit::TestCase
|
|
151
151
|
|
152
152
|
def test_from_tracksperanto
|
153
153
|
fixture = File.open(File.dirname(__FILE__) + '/samples/flame_stabilizer/fromTracksperanto.stabilizer')
|
154
|
-
|
155
|
-
trackers = parser.to_a
|
154
|
+
trackers = Tracksperanto::Import::FlameStabilizer.new(:io => fixture).to_a
|
156
155
|
|
157
156
|
assert_equal 3, trackers.length
|
158
157
|
assert_equal 3, trackers[0].length
|
data/test/test_accumulator.rb
CHANGED
@@ -17,6 +17,49 @@ class TestAccumulator < Test::Unit::TestCase
|
|
17
17
|
assert_equal 50_000, a.size
|
18
18
|
end
|
19
19
|
|
20
|
+
def test_accumulator_saves_shitload_of_objs
|
21
|
+
a = Tracksperanto::Accumulator.new
|
22
|
+
4.times { a.push("A \tstring") }
|
23
|
+
a.each {|e| assert_equal "A \tstring", e }
|
24
|
+
end
|
25
|
+
|
26
|
+
def test_accumulator_empty
|
27
|
+
a = Tracksperanto::Accumulator.new
|
28
|
+
assert a.empty?
|
29
|
+
a.push(1)
|
30
|
+
assert !a.empty?
|
31
|
+
end
|
32
|
+
|
33
|
+
def test_accumulator_supports_nested_iteration
|
34
|
+
a = Tracksperanto::Accumulator.new
|
35
|
+
("A".."Z").each{|e| a << e}
|
36
|
+
|
37
|
+
accumulated = []
|
38
|
+
seen_g = false
|
39
|
+
a.each do | first_level |
|
40
|
+
if first_level == "G"
|
41
|
+
seen_g = true
|
42
|
+
# Force a nested iteration and break it midway
|
43
|
+
a.each do | second_level |
|
44
|
+
accumulated.push(second_level)
|
45
|
+
break if second_level == "E"
|
46
|
+
end
|
47
|
+
elsif seen_g
|
48
|
+
assert_equal "H", first_level
|
49
|
+
return
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
def test_random_access
|
55
|
+
a = Tracksperanto::Accumulator.new
|
56
|
+
letters = ("A".."Z").map{|e| "#{e}\r\nWow!"}.to_a
|
57
|
+
letters.map(&a.method(:push))
|
58
|
+
|
59
|
+
assert_equal "B\r\nWow!", a[1]
|
60
|
+
assert_equal "E\r\nWow!", a[4]
|
61
|
+
end
|
62
|
+
|
20
63
|
def test_clear_calls_close_on_buffer
|
21
64
|
io = Tracksperanto::BufferIO.new
|
22
65
|
flexmock(io).should_receive(:close!)
|
data/test/test_buffer_io.rb
CHANGED
@@ -19,4 +19,15 @@ class TestBufferIO < Test::Unit::TestCase
|
|
19
19
|
flexmock(f).should_receive(:close!).once
|
20
20
|
io.close!
|
21
21
|
end
|
22
|
+
|
23
|
+
def test_to_file_forces_immediate_promotion_to_file
|
24
|
+
io = Tracksperanto::BufferIO.new
|
25
|
+
io.write("a" * 3000)
|
26
|
+
assert_equal 3000, io.pos
|
27
|
+
assert !io.file_backed?
|
28
|
+
|
29
|
+
f = io.to_file
|
30
|
+
assert_equal 3000, f.pos
|
31
|
+
assert f.file_backed?
|
32
|
+
end
|
22
33
|
end
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: tracksperanto
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 3
|
5
5
|
prerelease:
|
6
6
|
segments:
|
7
7
|
- 2
|
8
|
-
-
|
9
|
-
-
|
10
|
-
version: 2.
|
8
|
+
- 3
|
9
|
+
- 0
|
10
|
+
version: 2.3.0
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- Julik Tarkhanov
|
@@ -15,7 +15,7 @@ autorequire:
|
|
15
15
|
bindir: bin
|
16
16
|
cert_chain: []
|
17
17
|
|
18
|
-
date: 2011-04-
|
18
|
+
date: 2011-04-17 00:00:00 +02:00
|
19
19
|
default_executable:
|
20
20
|
dependencies:
|
21
21
|
- !ruby/object:Gem::Dependency
|
@@ -134,6 +134,7 @@ files:
|
|
134
134
|
- lib/tracksperanto/flame_builder.rb
|
135
135
|
- lib/tracksperanto/format_detector.rb
|
136
136
|
- lib/tracksperanto/keyframe.rb
|
137
|
+
- lib/tracksperanto/pbar.rb
|
137
138
|
- lib/tracksperanto/progressive_io.rb
|
138
139
|
- lib/tracksperanto/returning.rb
|
139
140
|
- lib/tracksperanto/safety.rb
|