tracksperanto 2.2.4 → 2.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|