tracksperanto 1.8.1 → 1.8.2
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 +5 -0
- data/Manifest.txt +3 -0
- data/README.txt +6 -1
- data/Rakefile +1 -0
- data/lib/export/equalizer3.rb +1 -1
- data/lib/export/equalizer4.rb +2 -2
- data/lib/export/flame_stabilizer.rb +80 -36
- data/lib/export/nuke_script.rb +1 -1
- data/lib/export/pftrack.rb +11 -7
- data/lib/export/pftrack_5.rb +8 -6
- data/lib/import/match_mover.rb +3 -0
- data/lib/pipeline/base.rb +17 -20
- data/lib/tracksperanto.rb +3 -1
- data/lib/tracksperanto/buffer_io.rb +48 -0
- data/lib/tracksperanto/flame_builder.rb +24 -17
- data/lib/tracksperanto/progressive_io.rb +4 -7
- data/lib/tracksperanto/returning.rb +6 -0
- data/test/export/samples/ref_flame.stabilizer +0 -18
- data/test/export/test_flame_stabilizer_export.rb +1 -1
- data/test/test_buffer_io.rb +22 -0
- data/test/test_flame_builder.rb +1 -0
- metadata +6 -2
data/History.txt
CHANGED
@@ -1,3 +1,8 @@
|
|
1
|
+
=== 1.8.2 / 2010-03-04
|
2
|
+
|
3
|
+
* Fix the bug in the Flame exporter that was convincing Flame that there is only one tracker in the setup
|
4
|
+
* Buffer temporary outputs to String buffers until they reach a certain size. Helps with tempfile pollution and IO speed
|
5
|
+
|
1
6
|
=== 1.8.1 / 2010-02-18
|
2
7
|
|
3
8
|
* Add Flame stabilizer export support
|
data/Manifest.txt
CHANGED
@@ -42,6 +42,7 @@ lib/middleware/slipper.rb
|
|
42
42
|
lib/pipeline/base.rb
|
43
43
|
lib/tracksperanto.rb
|
44
44
|
lib/tracksperanto/block_init.rb
|
45
|
+
lib/tracksperanto/buffer_io.rb
|
45
46
|
lib/tracksperanto/casts.rb
|
46
47
|
lib/tracksperanto/const_name.rb
|
47
48
|
lib/tracksperanto/ext_io.rb
|
@@ -49,6 +50,7 @@ lib/tracksperanto/flame_builder.rb
|
|
49
50
|
lib/tracksperanto/format_detector.rb
|
50
51
|
lib/tracksperanto/keyframe.rb
|
51
52
|
lib/tracksperanto/progressive_io.rb
|
53
|
+
lib/tracksperanto/returning.rb
|
52
54
|
lib/tracksperanto/safety.rb
|
53
55
|
lib/tracksperanto/simple_export.rb
|
54
56
|
lib/tracksperanto/tracker.rb
|
@@ -130,6 +132,7 @@ test/middleware/test_reformat_middleware.rb
|
|
130
132
|
test/middleware/test_scaler_middleware.rb
|
131
133
|
test/middleware/test_shift_middleware.rb
|
132
134
|
test/middleware/test_slip_middleware.rb
|
135
|
+
test/test_buffer_io.rb
|
133
136
|
test/test_const_name.rb
|
134
137
|
test/test_extio.rb
|
135
138
|
test/test_flame_builder.rb
|
data/README.txt
CHANGED
@@ -69,7 +69,7 @@ Import and export support:
|
|
69
69
|
* Syntheyes 2D tracking data exports
|
70
70
|
* 3DE point exports (as output by the default script) - versions 3 and 4
|
71
71
|
* MatchMover Pro .rz2
|
72
|
-
* MayaLive track export (square pixel aspect only)
|
72
|
+
* MayaLive track export (square pixel aspect only, you will need to write some extra code to convert that)
|
73
73
|
* Flame .stabilizer file
|
74
74
|
|
75
75
|
Import only:
|
@@ -98,6 +98,11 @@ are themselves arrays of Tracksperanto::Keyframe objects.
|
|
98
98
|
|
99
99
|
You can easily write an exporter. Refer to the Tracksperanto::Export::Base docs.
|
100
100
|
|
101
|
+
== Ading your own processing steps
|
102
|
+
|
103
|
+
You probably want to write a Middleware (consult the Tracksperanto::Middleware::Base docs). A Middleware is just like
|
104
|
+
an exporter, except that it wraps another exporter instead (so you can intercept export calls and massage the data as it is moving through).
|
105
|
+
|
101
106
|
== Limitations
|
102
107
|
|
103
108
|
Information about the search area, reference area and offset is not passed along (outside
|
data/Rakefile
CHANGED
data/lib/export/equalizer3.rb
CHANGED
@@ -14,7 +14,7 @@ class Tracksperanto::Export::Equalizer3 < Tracksperanto::Export::Base
|
|
14
14
|
def start_export( img_width, img_height)
|
15
15
|
@w, @h = img_width, img_height
|
16
16
|
# 3DE needs to know the number of keyframes in advance
|
17
|
-
@buffer =
|
17
|
+
@buffer = Tracksperanto::BufferIO.new
|
18
18
|
@highest_keyframe = 0
|
19
19
|
end
|
20
20
|
|
data/lib/export/equalizer4.rb
CHANGED
@@ -12,13 +12,13 @@ class Tracksperanto::Export::Equalizer4 < Tracksperanto::Export::Base
|
|
12
12
|
def start_export( img_width, img_height)
|
13
13
|
# 3DE needs to know the number of points in advance,
|
14
14
|
# so we will just buffer to a StringIO
|
15
|
-
@internal_io, @num_of_trackers =
|
15
|
+
@internal_io, @num_of_trackers = Tracksperanto::BufferIO.new, 0
|
16
16
|
end
|
17
17
|
|
18
18
|
def start_tracker_segment(tracker_name)
|
19
19
|
@internal_io.puts(tracker_name)
|
20
20
|
@num_of_trackers += 1
|
21
|
-
@tracker_buffer, @num_of_kfs =
|
21
|
+
@tracker_buffer, @num_of_kfs = Tracksperanto::BufferIO.new, 0
|
22
22
|
end
|
23
23
|
|
24
24
|
def export_point(frame, abs_float_x, abs_float_y, float_residual)
|
@@ -1,6 +1,9 @@
|
|
1
|
+
# TODO: this exporter is MAJORLY slow now
|
1
2
|
class Tracksperanto::Export::FlameStabilizer < Tracksperanto::Export::Base
|
2
3
|
|
3
4
|
COLOR = "50 50 50"
|
5
|
+
DATETIME_FORMAT = '%a %b %d %H:%M:%S %Y'
|
6
|
+
|
4
7
|
def self.desc_and_extension
|
5
8
|
"flame.stabilizer"
|
6
9
|
end
|
@@ -12,22 +15,27 @@ class Tracksperanto::Export::FlameStabilizer < Tracksperanto::Export::Base
|
|
12
15
|
def start_export( img_width, img_height)
|
13
16
|
@counter = 0
|
14
17
|
@width, @height = img_width, img_height
|
15
|
-
@temp =
|
18
|
+
@temp = Tracksperanto::BufferIO.new
|
16
19
|
@writer = Tracksperanto::FlameBuilder.new(@temp)
|
17
20
|
end
|
18
21
|
|
19
22
|
def end_export
|
23
|
+
# Now make another writer, this time for our main IO
|
20
24
|
@writer = Tracksperanto::FlameBuilder.new(@io)
|
21
|
-
|
25
|
+
|
26
|
+
# Now we know how many trackers we have so we can write the header
|
27
|
+
# data along with NbTrackers
|
28
|
+
write_header_with_number_of_trackers(@counter)
|
22
29
|
|
23
30
|
# Now write everything that we accumulated earlier into the base IO
|
24
31
|
@temp.rewind
|
25
32
|
@io.write(@temp.read) until @temp.eof?
|
26
33
|
@temp.close!
|
27
34
|
|
35
|
+
# Send the ChannelEnd command and list the trackers
|
28
36
|
@writer.channel_end
|
29
37
|
@counter.times do |i|
|
30
|
-
@writer.tracker
|
38
|
+
@writer.write_unterminated_block!("tracker", i) do |t|
|
31
39
|
t.active true
|
32
40
|
t.color_hash!("colour", 0, 100, 0)
|
33
41
|
t.fixed_ref true
|
@@ -40,30 +48,39 @@ class Tracksperanto::Export::FlameStabilizer < Tracksperanto::Export::Base
|
|
40
48
|
|
41
49
|
def start_tracker_segment(tracker_name)
|
42
50
|
@counter += 1
|
43
|
-
@tracker_name = tracker_name
|
44
|
-
@x_values, @y_values = [], []
|
45
51
|
@write_first_frame = true
|
46
52
|
end
|
47
53
|
|
48
54
|
def export_point(frame, abs_float_x, abs_float_y, float_residual)
|
55
|
+
flame_frame = frame + 1
|
49
56
|
if @write_first_frame
|
50
|
-
|
51
|
-
|
52
|
-
|
57
|
+
@base_x, @base_y = abs_float_x, abs_float_y
|
58
|
+
write_first_frame(abs_float_x, abs_float_y)
|
59
|
+
# For Flame to recognize the reference frame of the Shift channel
|
60
|
+
# we need it to contain zero as an int, not as a float. The shift proceeds
|
61
|
+
# from there.
|
62
|
+
@x_shift_values = [[flame_frame, 0]]
|
63
|
+
@y_shift_values = [[flame_frame, 0]]
|
64
|
+
@write_first_frame = false
|
53
65
|
else
|
54
|
-
|
55
|
-
@
|
66
|
+
# Just continue buffering the upcoming shift keyframes and flush them in the end
|
67
|
+
shift_x, shift_y = @base_x - abs_float_x, @base_y - abs_float_y
|
68
|
+
@x_shift_values.push([flame_frame, shift_x])
|
69
|
+
@y_shift_values.push([flame_frame, shift_y])
|
56
70
|
end
|
57
71
|
end
|
58
72
|
|
59
73
|
def end_tracker_segment
|
60
|
-
|
61
|
-
|
74
|
+
# We write these at tracker end since we need to know in advance
|
75
|
+
# how many keyframes they should contain
|
76
|
+
write_shift_channel("shift/x", @x_shift_values)
|
77
|
+
write_shift_channel("shift/y", @y_shift_values)
|
62
78
|
end
|
63
79
|
|
64
80
|
private
|
65
81
|
|
66
|
-
|
82
|
+
# The shift channel is what determines how the tracking point moves.
|
83
|
+
def write_shift_channel(name_without_prefix, values)
|
67
84
|
@writer.channel(prefix(name_without_prefix)) do | c |
|
68
85
|
c.extrapolation :constant
|
69
86
|
c.value values[0][1]
|
@@ -71,8 +88,8 @@ class Tracksperanto::Export::FlameStabilizer < Tracksperanto::Export::Base
|
|
71
88
|
c.size values.length
|
72
89
|
values.each_with_index do | (f, v), i |
|
73
90
|
c.key(i) do | k |
|
74
|
-
k.frame
|
75
|
-
k.value
|
91
|
+
k.frame f
|
92
|
+
k.value v
|
76
93
|
k.interpolation :linear
|
77
94
|
k.left_slope 2.4
|
78
95
|
k.right_slope 2.4
|
@@ -85,12 +102,12 @@ class Tracksperanto::Export::FlameStabilizer < Tracksperanto::Export::Base
|
|
85
102
|
["tracker#{@counter}", tracker_channel].join("/")
|
86
103
|
end
|
87
104
|
|
88
|
-
def
|
105
|
+
def write_header_with_number_of_trackers(number_of_trackers)
|
89
106
|
@writer.stabilizer_file_version "5.0"
|
90
|
-
@writer.creation_date(Time.now.strftime(
|
107
|
+
@writer.creation_date(Time.now.strftime(DATETIME_FORMAT))
|
91
108
|
@writer.linebreak!(2)
|
92
109
|
|
93
|
-
@writer.nb_trackers
|
110
|
+
@writer.nb_trackers number_of_trackers
|
94
111
|
@writer.selected 0
|
95
112
|
@writer.frame_width @width
|
96
113
|
@writer.frame_height @height
|
@@ -109,19 +126,31 @@ class Tracksperanto::Export::FlameStabilizer < Tracksperanto::Export::Base
|
|
109
126
|
@writer.anim
|
110
127
|
end
|
111
128
|
|
112
|
-
def write_first_frame(x, y
|
113
|
-
|
114
|
-
|
129
|
+
def write_first_frame(x, y)
|
130
|
+
write_track_channels
|
131
|
+
write_track_width_and_height
|
132
|
+
write_ref_width_and_height
|
133
|
+
write_ref_channels(x, y)
|
134
|
+
write_deltax_and_deltay_channels
|
135
|
+
write_offset_channels
|
136
|
+
end
|
137
|
+
|
138
|
+
def write_track_channels
|
139
|
+
ctr_x, ctr_y = @width / 2, @height / 2
|
115
140
|
|
116
|
-
|
117
|
-
|
141
|
+
# track determines where the tracking box is, and should be in the center
|
142
|
+
# of the image for Flame to compute all other shifts properly
|
143
|
+
%w( track/x track/y).map(&method(:prefix)).zip([ctr_x, ctr_y]).each do | cname, default |
|
118
144
|
@writer.channel(cname) do | c |
|
119
145
|
c.extrapolation("constant")
|
120
146
|
c.value(default.to_i)
|
121
147
|
c.colour(COLOR)
|
122
148
|
end
|
123
149
|
end
|
124
|
-
|
150
|
+
end
|
151
|
+
|
152
|
+
# The size of the tracking area
|
153
|
+
def write_track_width_and_height
|
125
154
|
%w( track/width track/height ).map(&method(:prefix)).each do | channel_name |
|
126
155
|
@writer.channel(channel_name) do | c |
|
127
156
|
c.extrapolation :linear
|
@@ -129,7 +158,10 @@ class Tracksperanto::Export::FlameStabilizer < Tracksperanto::Export::Base
|
|
129
158
|
c.colour COLOR
|
130
159
|
end
|
131
160
|
end
|
132
|
-
|
161
|
+
end
|
162
|
+
|
163
|
+
# The size of the reference area
|
164
|
+
def write_ref_width_and_height
|
133
165
|
%w( ref/width ref/height).map(&method(:prefix)).each do | channel_name |
|
134
166
|
@writer.channel(channel_name) do | c |
|
135
167
|
c.extrapolation :linear
|
@@ -137,8 +169,14 @@ class Tracksperanto::Export::FlameStabilizer < Tracksperanto::Export::Base
|
|
137
169
|
c.colour COLOR
|
138
170
|
end
|
139
171
|
end
|
140
|
-
|
141
|
-
|
172
|
+
end
|
173
|
+
|
174
|
+
# The Ref channel contains the reference for the shift channel in absolute
|
175
|
+
# coordinates, and is set as float. Since we do not "snap" the tracker in
|
176
|
+
# the process it's enough for us to make one keyframe in the ref channels
|
177
|
+
# at the same frame as the first shift keyframe
|
178
|
+
def write_ref_channels(ref_x, ref_y)
|
179
|
+
%w( ref/x ref/y).map(&method(:prefix)).zip([ref_x, ref_y]).each do | cname, default |
|
142
180
|
@writer.channel(cname) do | c |
|
143
181
|
c.extrapolation("constant")
|
144
182
|
c.value(default)
|
@@ -154,7 +192,11 @@ class Tracksperanto::Export::FlameStabilizer < Tracksperanto::Export::Base
|
|
154
192
|
end
|
155
193
|
end
|
156
194
|
end
|
157
|
-
|
195
|
+
end
|
196
|
+
|
197
|
+
def write_deltax_and_deltay_channels
|
198
|
+
# This is used for deltax and deltay (offset tracking).
|
199
|
+
# We set it to zero and lock
|
158
200
|
%w( ref/dx ref/dy).map(&method(:prefix)).each do | chan, v |
|
159
201
|
@writer.channel(chan) do | c |
|
160
202
|
c.extrapolation("constant")
|
@@ -177,14 +219,16 @@ class Tracksperanto::Export::FlameStabilizer < Tracksperanto::Export::Base
|
|
177
219
|
k.interpolation :constant
|
178
220
|
end
|
179
221
|
end # Chan block
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
222
|
+
end
|
223
|
+
end
|
224
|
+
|
225
|
+
def write_offset_channels
|
226
|
+
%w(offset/x offset/y).map(&method(:prefix)).each do | c |
|
227
|
+
@writer.channel(c) do | chan |
|
228
|
+
chan.extrapolation :constant
|
229
|
+
chan.value 0
|
186
230
|
end
|
187
|
-
end
|
188
|
-
end
|
231
|
+
end
|
232
|
+
end
|
189
233
|
|
190
234
|
end
|
data/lib/export/nuke_script.rb
CHANGED
@@ -45,7 +45,7 @@ Constant {
|
|
45
45
|
# We allocate an IO for the file being output that will contain all the trackers,
|
46
46
|
# and then write that one into the script preceded by the preamble that sets length
|
47
47
|
# based on the last frame position in time
|
48
|
-
@trackers_io =
|
48
|
+
@trackers_io = Tracksperanto::BufferIO.new
|
49
49
|
end
|
50
50
|
|
51
51
|
# We accumulate a tracker and on end dump it out in one piece
|
data/lib/export/pftrack.rb
CHANGED
@@ -13,20 +13,24 @@ class Tracksperanto::Export::PFTrack4 < Tracksperanto::Export::Base
|
|
13
13
|
|
14
14
|
def start_tracker_segment(tracker_name)
|
15
15
|
# Setup for the next tracker
|
16
|
-
@
|
16
|
+
@frame_count = 0
|
17
17
|
@tracker_name = tracker_name
|
18
|
+
@tracker_io = Tracksperanto::BufferIO.new
|
18
19
|
end
|
19
20
|
|
20
21
|
def end_tracker_segment
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
@
|
22
|
+
@io.write("\n\n")
|
23
|
+
@io.puts(@tracker_name.inspect) # autoquotes
|
24
|
+
@io.puts(@frame_count)
|
25
|
+
|
26
|
+
@tracker_io.rewind
|
27
|
+
@io.write(@tracker_io.read) until @tracker_io.eof?
|
28
|
+
@tracker_io.close!
|
26
29
|
end
|
27
30
|
|
28
31
|
def export_point(frame, abs_float_x, abs_float_y, float_residual)
|
32
|
+
@frame_count += 1
|
29
33
|
line = KEYFRAME_TEMPLATE % [frame, abs_float_x, abs_float_y, float_residual / 8]
|
30
|
-
@
|
34
|
+
@tracker_io.puts(line)
|
31
35
|
end
|
32
36
|
end
|
data/lib/export/pftrack_5.rb
CHANGED
@@ -10,11 +10,13 @@ class Tracksperanto::Export::PFTrack5 < Tracksperanto::Export::PFTrack4
|
|
10
10
|
end
|
11
11
|
|
12
12
|
def end_tracker_segment
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
@
|
13
|
+
@io.write("\n\n")
|
14
|
+
@io.puts(@tracker_name.inspect) # autoquotes
|
15
|
+
@io.puts("Primary".inspect) # For primary/secondary cam in stereo pair
|
16
|
+
@io.puts(@frame_count)
|
17
|
+
|
18
|
+
@tracker_io.rewind
|
19
|
+
@io.write(@tracker_io.read) until @tracker_io.eof?
|
20
|
+
@tracker_io.close!
|
19
21
|
end
|
20
22
|
end
|
data/lib/import/match_mover.rb
CHANGED
@@ -21,6 +21,7 @@ class Tracksperanto::Import::MatchMover < Tracksperanto::Import::Base
|
|
21
21
|
private
|
22
22
|
|
23
23
|
def detect_format(io)
|
24
|
+
report_progress("Detecting width and height")
|
24
25
|
lines = (0..2).map{ io.gets }
|
25
26
|
last_line = lines[-1]
|
26
27
|
w, h, _ = last_line.scan(/(\d+)/).flatten
|
@@ -37,10 +38,12 @@ class Tracksperanto::Import::MatchMover < Tracksperanto::Import::Base
|
|
37
38
|
|
38
39
|
def extract_track(start_line, io)
|
39
40
|
tracker_name = start_line.scan(/\"([^\"]+)\"/).flatten[0]
|
41
|
+
report_progress("Extracting tracker #{tracker_name}")
|
40
42
|
t = Tracksperanto::Tracker.new(:name => tracker_name)
|
41
43
|
while(line = io.gets) do
|
42
44
|
return t if line =~ /\}/
|
43
45
|
t.keyframes.push(extract_key(line.strip)) if line =~ /^(\s+?)(\d)/
|
46
|
+
report_progress("Extracting keyframe")
|
44
47
|
end
|
45
48
|
raise "Track didn't close"
|
46
49
|
end
|
data/lib/pipeline/base.rb
CHANGED
@@ -59,9 +59,11 @@ class Tracksperanto::Pipeline::Base
|
|
59
59
|
# Yield middlewares to the block
|
60
60
|
yield(*middlewares) if block_given?
|
61
61
|
|
62
|
-
@converted_points, @converted_keyframes = run_export(read_data, importer, middlewares[-1])
|
63
|
-
|
64
|
-
|
62
|
+
@converted_points, @converted_keyframes = run_export(read_data, importer, middlewares[-1])
|
63
|
+
end
|
64
|
+
|
65
|
+
def report_progress(percent_complete, message)
|
66
|
+
@progress_block.call(percent_complete, message) if @progress_block
|
65
67
|
end
|
66
68
|
|
67
69
|
def detect_importer_or_use_options(path, opts)
|
@@ -87,31 +89,26 @@ class Tracksperanto::Pipeline::Base
|
|
87
89
|
def run_export(tracker_data_io, parser, processor)
|
88
90
|
points, keyframes, percent_complete = 0, 0, 0.0
|
89
91
|
|
90
|
-
|
92
|
+
report_progress(percent_complete, "Starting the parser")
|
91
93
|
|
92
94
|
# Report progress from the parser
|
93
|
-
parser.progress_block = lambda
|
94
|
-
yield(percent_complete, message) if block_given?
|
95
|
-
end
|
95
|
+
parser.progress_block = lambda { | m | report_progress(percent_complete, m) }
|
96
96
|
|
97
|
-
# Wrap the input in a progressive IO
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
# Setup a lambda that will spy on the reader and update the percentage.
|
102
|
-
# We will only broadcast messages that come from the parser though (complementing it
|
103
|
-
# with a percentage)
|
104
|
-
io_with_progress.progress_block = lambda do | offset, of_total |
|
97
|
+
# Wrap the input in a progressive IO, setup a lambda that will spy on the reader and
|
98
|
+
# update the percentage. We will only broadcast messages that come from the parser
|
99
|
+
# though (complementing it with a percentage)
|
100
|
+
io_with_progress = Tracksperanto::ProgressiveIO.new(tracker_data_io) do | offset, of_total |
|
105
101
|
percent_complete = (50.0 / of_total) * offset
|
106
102
|
end
|
103
|
+
@ios << io_with_progress
|
107
104
|
|
108
105
|
trackers = parser.parse(io_with_progress)
|
109
106
|
|
110
|
-
|
107
|
+
report_progress(percent_complete = 50.0, "Validating #{trackers.length} imported trackers")
|
111
108
|
|
112
109
|
validate_trackers!(trackers)
|
113
110
|
|
114
|
-
|
111
|
+
report_progress(percent_complete, "Starting export")
|
115
112
|
|
116
113
|
percent_per_tracker = (100.0 - percent_complete) / trackers.length
|
117
114
|
|
@@ -124,13 +121,13 @@ class Tracksperanto::Pipeline::Base
|
|
124
121
|
t.each_with_index do | kf, idx |
|
125
122
|
keyframes += 1
|
126
123
|
processor.export_point(kf.frame, kf.abs_x, kf.abs_y, kf.residual)
|
127
|
-
|
124
|
+
report_progress(percent_complete += kf_weight, "Writing keyframe #{idx+1} of #{t.name.inspect}, #{trackers.length - idx + 1} trackers to go")
|
128
125
|
end
|
129
126
|
processor.end_tracker_segment
|
130
127
|
end
|
131
128
|
processor.end_export
|
132
129
|
|
133
|
-
|
130
|
+
report_progress(100.0, "Wrote #{points} points and #{keyframes} keyframes")
|
134
131
|
|
135
132
|
[points, keyframes]
|
136
133
|
ensure
|
@@ -176,7 +173,7 @@ class Tracksperanto::Pipeline::Base
|
|
176
173
|
|
177
174
|
# Check that the trackers made by the parser are A-OK
|
178
175
|
def validate_trackers!(trackers)
|
179
|
-
trackers.reject!{|t| t.
|
176
|
+
trackers.reject!{|t| t.empty? }
|
180
177
|
raise "Could not recover any non-empty trackers from this file. Wrong import format maybe?" if trackers.empty?
|
181
178
|
end
|
182
179
|
end
|
data/lib/tracksperanto.rb
CHANGED
@@ -4,7 +4,7 @@ require 'tempfile'
|
|
4
4
|
|
5
5
|
module Tracksperanto
|
6
6
|
PATH = File.expand_path(File.dirname(__FILE__))
|
7
|
-
VERSION = '1.8.
|
7
|
+
VERSION = '1.8.2'
|
8
8
|
|
9
9
|
module Import; end
|
10
10
|
module Export; end
|
@@ -59,6 +59,7 @@ module Tracksperanto
|
|
59
59
|
end
|
60
60
|
|
61
61
|
%w(
|
62
|
+
returning
|
62
63
|
const_name
|
63
64
|
casts
|
64
65
|
block_init
|
@@ -69,6 +70,7 @@ end
|
|
69
70
|
format_detector
|
70
71
|
ext_io
|
71
72
|
progressive_io
|
73
|
+
buffer_io
|
72
74
|
simple_export
|
73
75
|
uv_coordinates
|
74
76
|
flame_builder
|
@@ -0,0 +1,48 @@
|
|
1
|
+
require "tempfile"
|
2
|
+
|
3
|
+
# BufferIO is used for writing big segments of text. When the segment is bigger than a certain number of bytes,
|
4
|
+
# the underlying memory buffer will be swapped with a tempfile
|
5
|
+
class Tracksperanto::BufferIO < DelegateClass(IO)
|
6
|
+
include Tracksperanto::Returning
|
7
|
+
|
8
|
+
IN_MEMORY_SIZE_LIMIT = 100_000
|
9
|
+
|
10
|
+
def initialize
|
11
|
+
__setobj__(StringIO.new)
|
12
|
+
end
|
13
|
+
|
14
|
+
def write(s)
|
15
|
+
returning(super) { replace_with_tempfile_if_needed }
|
16
|
+
end
|
17
|
+
|
18
|
+
def puts(s)
|
19
|
+
returning(super) { replace_with_tempfile_if_needed }
|
20
|
+
end
|
21
|
+
|
22
|
+
def <<(s)
|
23
|
+
returning(super) { replace_with_tempfile_if_needed }
|
24
|
+
end
|
25
|
+
|
26
|
+
def putc(c)
|
27
|
+
returning(super) { replace_with_tempfile_if_needed }
|
28
|
+
end
|
29
|
+
|
30
|
+
def close!
|
31
|
+
__getobj__.close! if @tempfile_in
|
32
|
+
__setobj__(nil)
|
33
|
+
end
|
34
|
+
|
35
|
+
private
|
36
|
+
|
37
|
+
def replace_with_tempfile_if_needed
|
38
|
+
return if @tempfile_in
|
39
|
+
io = __getobj__
|
40
|
+
if io.pos > IN_MEMORY_SIZE_LIMIT
|
41
|
+
@tempfile_in = true
|
42
|
+
tf = Tempfile.new("tracksperanto-xbuf")
|
43
|
+
io.rewind
|
44
|
+
tf.write(io.read) until io.eof?
|
45
|
+
__setobj__(tf)
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
@@ -12,6 +12,11 @@ class Tracksperanto::FlameBuilder
|
|
12
12
|
@io.puts(INDENT * (@indent + 1) + "End")
|
13
13
|
end
|
14
14
|
|
15
|
+
def write_unterminated_block!(name, value = nil, &blk)
|
16
|
+
value.nil? ? write_loose!(name) : write_tuple!(name, value)
|
17
|
+
yield(self.class.new(@io, @indent + 1))
|
18
|
+
end
|
19
|
+
|
15
20
|
def write_tuple!(key, value)
|
16
21
|
@io.puts("%s%s %s" % [INDENT * @indent, __camelize(key), __flameize(value)])
|
17
22
|
end
|
@@ -25,34 +30,36 @@ class Tracksperanto::FlameBuilder
|
|
25
30
|
end
|
26
31
|
|
27
32
|
def color_hash!(name, red, green, blue)
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
+
write_unterminated_block!(name) do | b |
|
34
|
+
b.red(red)
|
35
|
+
b.green(green)
|
36
|
+
b.blue(blue)
|
37
|
+
end
|
33
38
|
end
|
34
39
|
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
self.class.send(:alias_method, meth, :__generic)
|
39
|
-
if block_given?
|
40
|
-
__generic(meth, arg) {|*a| yield(*a) if block_given? }
|
41
|
-
else
|
42
|
-
__generic(meth, arg)
|
40
|
+
def <<(some_verbatim_string)
|
41
|
+
some_verbatim_string.split("\n").each do | line |
|
42
|
+
@io.puts(["\t" * @indent, line].join)
|
43
43
|
end
|
44
44
|
end
|
45
45
|
|
46
|
-
|
46
|
+
private
|
47
|
+
|
48
|
+
def method_missing(meth, arg = nil)
|
47
49
|
if block_given?
|
48
|
-
write_block!(meth, arg) {
|
50
|
+
write_block!(meth, arg) {|c| yield(c) }
|
49
51
|
else
|
50
|
-
arg.nil?
|
52
|
+
if arg.nil?
|
53
|
+
write_loose!(meth)
|
54
|
+
else
|
55
|
+
write_tuple!(meth, arg)
|
56
|
+
end
|
51
57
|
end
|
52
58
|
end
|
53
59
|
|
54
60
|
def __camelize(s)
|
55
|
-
|
61
|
+
@@camelizations ||= {}
|
62
|
+
@@camelizations[s] ||= s.to_s.gsub(/(^|_)(.)/) { $2.upcase }
|
56
63
|
end
|
57
64
|
|
58
65
|
def __flameize(v)
|
@@ -1,17 +1,17 @@
|
|
1
1
|
# Used for IO objects that need to report the current offset at each operation that changes the said offset
|
2
2
|
# (useful for building progress bars that report on a file read operation)
|
3
3
|
class Tracksperanto::ProgressiveIO < DelegateClass(IO)
|
4
|
-
|
5
|
-
# Should contain a block that accepts the current offset in bytes and the total size
|
6
|
-
attr_accessor :progress_block
|
4
|
+
include Tracksperanto::Returning
|
7
5
|
|
8
6
|
# Get or set the total size of the contained IO. If the passed IO is a File object
|
9
7
|
# the size will be preset automatically
|
10
8
|
attr_accessor :total_size
|
9
|
+
attr_accessor :progress_block
|
11
10
|
|
12
|
-
def initialize(with_file)
|
11
|
+
def initialize(with_file, &blk)
|
13
12
|
__setobj__(with_file)
|
14
13
|
@total_size = with_file.stat.size if with_file.respond_to?(:stat)
|
14
|
+
@progress_block = blk.to_proc if blk
|
15
15
|
end
|
16
16
|
|
17
17
|
def each(sep_string = $/, &blk)
|
@@ -69,9 +69,6 @@ class Tracksperanto::ProgressiveIO < DelegateClass(IO)
|
|
69
69
|
end
|
70
70
|
|
71
71
|
private
|
72
|
-
def returning(r)
|
73
|
-
yield; r
|
74
|
-
end
|
75
72
|
|
76
73
|
def notify_read
|
77
74
|
@progress_block.call(pos, @total_size) if @progress_block
|
@@ -101,14 +101,6 @@ Channel tracker1/ref/dx
|
|
101
101
|
Interpolation constant
|
102
102
|
End
|
103
103
|
End
|
104
|
-
Channel tracker1/offset/x
|
105
|
-
Extrapolation constant
|
106
|
-
Value 0
|
107
|
-
End
|
108
|
-
Channel tracker1/offset/y
|
109
|
-
Extrapolation constant
|
110
|
-
Value 0
|
111
|
-
End
|
112
104
|
Channel tracker1/ref/dy
|
113
105
|
Extrapolation constant
|
114
106
|
Value 0
|
@@ -495,14 +487,6 @@ Channel tracker2/ref/dx
|
|
495
487
|
Interpolation constant
|
496
488
|
End
|
497
489
|
End
|
498
|
-
Channel tracker2/offset/x
|
499
|
-
Extrapolation constant
|
500
|
-
Value 0
|
501
|
-
End
|
502
|
-
Channel tracker2/offset/y
|
503
|
-
Extrapolation constant
|
504
|
-
Value 0
|
505
|
-
End
|
506
490
|
Channel tracker2/ref/dy
|
507
491
|
Extrapolation constant
|
508
492
|
Value 0
|
@@ -821,7 +805,6 @@ Tracker 0
|
|
821
805
|
FixedX no
|
822
806
|
FixedY no
|
823
807
|
Tolerance 100
|
824
|
-
End
|
825
808
|
Tracker 1
|
826
809
|
Active yes
|
827
810
|
Colour
|
@@ -832,4 +815,3 @@ Tracker 1
|
|
832
815
|
FixedX no
|
833
816
|
FixedY no
|
834
817
|
Tolerance 100
|
835
|
-
End
|
@@ -7,7 +7,7 @@ class FlameStabilizerExportTestTest < Test::Unit::TestCase
|
|
7
7
|
def test_export_output_written
|
8
8
|
t = Time.local(2010, "Feb", 18, 17, 22, 12)
|
9
9
|
flexmock(Time).should_receive(:now).once.and_return(t)
|
10
|
-
ensure_same_output Tracksperanto::Export::FlameStabilizer, P
|
10
|
+
ensure_same_output Tracksperanto::Export::FlameStabilizer, P
|
11
11
|
end
|
12
12
|
|
13
13
|
def test_exporter_meta
|
@@ -0,0 +1,22 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/helper'
|
2
|
+
|
3
|
+
class TestBufferIO < Test::Unit::TestCase
|
4
|
+
|
5
|
+
def test_write_in_mem_has_a_stringio
|
6
|
+
io = Tracksperanto::BufferIO.new
|
7
|
+
9000.times { io.write("a") }
|
8
|
+
assert_kind_of StringIO, io.__getobj__
|
9
|
+
assert_nothing_raised { io.close! }
|
10
|
+
end
|
11
|
+
|
12
|
+
def test_write_larger_than_max_swaps_tempfile
|
13
|
+
io = Tracksperanto::BufferIO.new
|
14
|
+
110_000.times { io.write("a") }
|
15
|
+
f = io.__getobj__
|
16
|
+
assert_kind_of Tempfile, f
|
17
|
+
f.rewind
|
18
|
+
assert_equal 110_000, f.read.length
|
19
|
+
flexmock(f).should_receive(:close!).once
|
20
|
+
io.close!
|
21
|
+
end
|
22
|
+
end
|
data/test/test_flame_builder.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: tracksperanto
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.8.
|
4
|
+
version: 1.8.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Julik Tarkhanov
|
@@ -9,7 +9,7 @@ autorequire:
|
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
11
|
|
12
|
-
date: 2010-
|
12
|
+
date: 2010-03-04 00:00:00 +01:00
|
13
13
|
default_executable:
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
@@ -89,6 +89,7 @@ files:
|
|
89
89
|
- lib/pipeline/base.rb
|
90
90
|
- lib/tracksperanto.rb
|
91
91
|
- lib/tracksperanto/block_init.rb
|
92
|
+
- lib/tracksperanto/buffer_io.rb
|
92
93
|
- lib/tracksperanto/casts.rb
|
93
94
|
- lib/tracksperanto/const_name.rb
|
94
95
|
- lib/tracksperanto/ext_io.rb
|
@@ -96,6 +97,7 @@ files:
|
|
96
97
|
- lib/tracksperanto/format_detector.rb
|
97
98
|
- lib/tracksperanto/keyframe.rb
|
98
99
|
- lib/tracksperanto/progressive_io.rb
|
100
|
+
- lib/tracksperanto/returning.rb
|
99
101
|
- lib/tracksperanto/safety.rb
|
100
102
|
- lib/tracksperanto/simple_export.rb
|
101
103
|
- lib/tracksperanto/tracker.rb
|
@@ -177,6 +179,7 @@ files:
|
|
177
179
|
- test/middleware/test_scaler_middleware.rb
|
178
180
|
- test/middleware/test_shift_middleware.rb
|
179
181
|
- test/middleware/test_slip_middleware.rb
|
182
|
+
- test/test_buffer_io.rb
|
180
183
|
- test/test_const_name.rb
|
181
184
|
- test/test_extio.rb
|
182
185
|
- test/test_flame_builder.rb
|
@@ -248,6 +251,7 @@ test_files:
|
|
248
251
|
- test/middleware/test_scaler_middleware.rb
|
249
252
|
- test/middleware/test_shift_middleware.rb
|
250
253
|
- test/middleware/test_slip_middleware.rb
|
254
|
+
- test/test_buffer_io.rb
|
251
255
|
- test/test_const_name.rb
|
252
256
|
- test/test_extio.rb
|
253
257
|
- test/test_flame_builder.rb
|