tracksperanto 2.9.5 → 2.9.6
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/Gemfile +1 -1
- data/History.txt +5 -0
- data/bin/tracksperanto +32 -22
- data/lib/export/equalizer3.rb +1 -1
- data/lib/export/equalizer4.rb +1 -1
- data/lib/import/flame_stabilizer.rb +3 -3
- data/lib/import/nuke_script.rb +25 -7
- data/lib/middleware/base.rb +14 -7
- data/lib/middleware/crop.rb +9 -2
- data/lib/middleware/flip.rb +5 -3
- data/lib/middleware/flop.rb +4 -2
- data/lib/middleware/golden.rb +5 -2
- data/lib/middleware/length_cutoff.rb +6 -2
- data/lib/middleware/lerp.rb +5 -2
- data/lib/middleware/lint.rb +5 -0
- data/lib/middleware/move_to_first.rb +50 -0
- data/lib/middleware/pad.rb +8 -2
- data/lib/middleware/prefix.rb +6 -2
- data/lib/middleware/reformat.rb +6 -3
- data/lib/middleware/scaler.rb +6 -2
- data/lib/middleware/shift.rb +7 -2
- data/lib/middleware/slipper.rb +6 -2
- data/lib/middleware/start_trim.rb +6 -6
- data/lib/pipeline/base.rb +34 -38
- data/lib/tracksperanto.rb +18 -1
- data/lib/tracksperanto/format_detector.rb +26 -26
- data/lib/tracksperanto/parameters.rb +56 -0
- data/lib/tracksperanto/yield_non_empty.rb +15 -0
- data/test/import/test_nuke_import.rb +16 -1
- data/test/middleware/test_crop_middleware.rb +5 -0
- data/test/middleware/test_flip_middleware.rb +4 -19
- data/test/middleware/test_flop_middleware.rb +4 -9
- data/test/middleware/test_golden_middleware.rb +3 -10
- data/test/middleware/test_length_cutoff_middleware.rb +5 -0
- data/test/middleware/test_lerp_middleware.rb +6 -20
- data/test/middleware/test_lint_middleware.rb +5 -0
- data/test/middleware/test_move_to_first_frame_middleware.rb +38 -0
- data/test/middleware/test_pad_middleware.rb +5 -0
- data/test/middleware/test_prefix.rb +4 -0
- data/test/middleware/test_reformat_middleware.rb +3 -2
- data/test/middleware/test_scaler_middleware.rb +5 -0
- data/test/middleware/test_shift_middleware.rb +5 -0
- data/test/middleware/test_slip_middleware.rb +5 -0
- data/test/middleware/test_start_trim_middleware.rb +3 -9
- data/test/test_cli.rb +3 -3
- data/test/test_format_detector.rb +1 -1
- data/test/test_parameters.rb +38 -0
- data/test/test_tracksperanto.rb +10 -0
- data/test/test_yield_non_empty.rb +11 -0
- data/tracksperanto.gemspec +11 -5
- metadata +27 -21
data/lib/middleware/prefix.rb
CHANGED
@@ -2,8 +2,12 @@
|
|
2
2
|
# This middleware prepends the names of the trackers passing through it with a prefix
|
3
3
|
# and an underscore
|
4
4
|
class Tracksperanto::Middleware::Prefix < Tracksperanto::Middleware::Base
|
5
|
-
|
6
|
-
|
5
|
+
|
6
|
+
parameter :prefix, :cast => :string, :desc => "The prefix to apply", :default => "trk_"
|
7
|
+
|
8
|
+
def self.action_description
|
9
|
+
"Prefix tracker names with text"
|
10
|
+
end
|
7
11
|
|
8
12
|
def start_tracker_segment(tracker_name)
|
9
13
|
prefixed_name = [prefix.gsub(/_$/, ''), tracker_name]
|
data/lib/middleware/reformat.rb
CHANGED
@@ -5,9 +5,12 @@ require File.dirname(__FILE__) + '/scaler'
|
|
5
5
|
# applying proxy tracks to full-res images
|
6
6
|
class Tracksperanto::Middleware::Reformat < Tracksperanto::Middleware::Base
|
7
7
|
|
8
|
-
|
9
|
-
|
10
|
-
|
8
|
+
parameter :width, :cast => :int, :desc => "New comp width in px", :default => 1080
|
9
|
+
parameter :height, :cast => :int, :desc => "New comp height in px", :default => 1080
|
10
|
+
|
11
|
+
def self.action_description
|
12
|
+
"Reformat the comp together with it's trackers to conform to a specific format"
|
13
|
+
end
|
11
14
|
|
12
15
|
# Called on export start
|
13
16
|
def start_export( img_width, img_height)
|
data/lib/middleware/scaler.rb
CHANGED
@@ -3,8 +3,12 @@
|
|
3
3
|
class Tracksperanto::Middleware::Scaler < Tracksperanto::Middleware::Base
|
4
4
|
DEFAULT_FACTOR = 1
|
5
5
|
|
6
|
-
|
7
|
-
|
6
|
+
parameter :x_factor, :cast => :float, :desc => "Factor to scale by", :default => DEFAULT_FACTOR
|
7
|
+
parameter :y_factor, :cast => :float, :desc => "Factor to scale by", :default => 0.5
|
8
|
+
|
9
|
+
def self.action_description
|
10
|
+
"Scale the comp by a specified factor"
|
11
|
+
end
|
8
12
|
|
9
13
|
# Called on export start
|
10
14
|
def start_export( img_width, img_height)
|
data/lib/middleware/shift.rb
CHANGED
@@ -1,8 +1,13 @@
|
|
1
1
|
# -*- encoding : utf-8 -*-
|
2
2
|
# This middleware moves the keyframs by a preset number of pixels
|
3
3
|
class Tracksperanto::Middleware::Shift < Tracksperanto::Middleware::Base
|
4
|
-
|
5
|
-
|
4
|
+
|
5
|
+
parameter :x_shift, :cast => :float, :desc => "Amount of horizontal shift (in px)", :default => 0
|
6
|
+
parameter :y_shift, :cast => :float, :desc => "Amount of vertical shift (in px)", :default => 0
|
7
|
+
|
8
|
+
def self.action_description
|
9
|
+
"Move all the trackers by a specified number of pixels"
|
10
|
+
end
|
6
11
|
|
7
12
|
def export_point(frame, float_x, float_y, float_residual)
|
8
13
|
super(frame, float_x + @x_shift.to_f, float_y + @y_shift.to_f, float_residual)
|
data/lib/middleware/slipper.rb
CHANGED
@@ -2,8 +2,12 @@
|
|
2
2
|
# Slips the keyframe positions by a specific integer amount of frames, positive values slip forward (later in time). Useful if you just edited some stuff onto
|
3
3
|
# the beginning if your sequence and need to extend your tracks.
|
4
4
|
class Tracksperanto::Middleware::Slipper < Tracksperanto::Middleware::Base
|
5
|
-
|
6
|
-
|
5
|
+
|
6
|
+
parameter :slip, :cast => :int, :desc => "Number of frames to slip related to the current frames", :default => 0
|
7
|
+
|
8
|
+
def self.action_description
|
9
|
+
"Slip all the tracker keyframes in time"
|
10
|
+
end
|
7
11
|
|
8
12
|
def export_point(frame, float_x, float_y, float_residual)
|
9
13
|
super(frame + @slip.to_i, float_x, float_y, float_residual)
|
@@ -1,17 +1,17 @@
|
|
1
1
|
# -*- encoding : utf-8 -*-
|
2
2
|
# This middleware removes all keyframes before frame 0, and skips trackers entirely if they are all before frame 0
|
3
3
|
class Tracksperanto::Middleware::StartTrim < Tracksperanto::Middleware::Base
|
4
|
-
|
4
|
+
|
5
|
+
def self.action_description
|
6
|
+
"Remove all the keyframes that are on frames below 1"
|
7
|
+
end
|
5
8
|
|
6
9
|
def start_export( img_width, img_height)
|
7
|
-
|
8
|
-
@exporter = Tracksperanto::Middleware::LengthCutoff.new(@exporter, :min_length => 1) # Ensure at least one keyframe
|
9
|
-
end
|
10
|
-
|
10
|
+
@exporter = Tracksperanto::Middleware::LengthCutoff.new(@exporter, :min_length => 1) # Ensure at least one keyframe
|
11
11
|
super
|
12
12
|
end
|
13
13
|
|
14
14
|
def export_point(frame, float_x, float_y, float_residual)
|
15
|
-
return super unless
|
15
|
+
return super unless frame < 0
|
16
16
|
end
|
17
17
|
end
|
data/lib/pipeline/base.rb
CHANGED
@@ -161,49 +161,45 @@ module Tracksperanto::Pipeline
|
|
161
161
|
|
162
162
|
@ios.push(io_with_progress)
|
163
163
|
|
164
|
-
|
164
|
+
importer.io = io_with_progress
|
165
|
+
obuf = Obuf.new(Tracksperanto::YieldNonEmpty.new(importer))
|
165
166
|
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
# Use the width and height provided by the parser itself
|
179
|
-
exporter.start_export(importer.width, importer.height)
|
167
|
+
report_progress(percent_complete = 50.0, "Validating #{obuf.size} imported trackers")
|
168
|
+
raise NoTrackersRecoveredError if obuf.size.zero?
|
169
|
+
|
170
|
+
report_progress(percent_complete, "Starting export")
|
171
|
+
|
172
|
+
percent_per_tracker = (100.0 - percent_complete) / obuf.size
|
173
|
+
|
174
|
+
# Use the width and height provided by the parser itself
|
175
|
+
exporter.start_export(importer.width, importer.height)
|
176
|
+
|
177
|
+
# Now send each tracker through the middleware chain
|
178
|
+
obuf.each_with_index do | t, tracker_idx |
|
180
179
|
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
exporter.
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
percent_complete += kf_weight,
|
192
|
-
"Writing keyframe #{idx+1} of #{t.name.inspect}, #{@accumulator.size - tracker_idx} trackers to go"
|
193
|
-
)
|
194
|
-
end
|
195
|
-
exporter.end_tracker_segment
|
180
|
+
kf_weight = percent_per_tracker / t.keyframes.length
|
181
|
+
points += 1
|
182
|
+
exporter.start_tracker_segment(t.name)
|
183
|
+
t.each_with_index do | kf, idx |
|
184
|
+
keyframes += 1
|
185
|
+
exporter.export_point(kf.frame, kf.abs_x, kf.abs_y, kf.residual)
|
186
|
+
report_progress(
|
187
|
+
percent_complete += kf_weight,
|
188
|
+
"Writing keyframe #{idx+1} of #{t.name.inspect}, #{obuf.size - tracker_idx} trackers to go"
|
189
|
+
)
|
196
190
|
end
|
197
|
-
exporter.
|
191
|
+
exporter.end_tracker_segment
|
192
|
+
end
|
193
|
+
exporter.end_export
|
194
|
+
|
195
|
+
report_progress(100.0, "Wrote #{points} points and #{keyframes} keyframes")
|
198
196
|
|
199
|
-
|
197
|
+
obuf.clear
|
200
198
|
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
@ios.clear
|
206
|
-
end
|
199
|
+
@ios.map!{|e| e.close! rescue e.close }
|
200
|
+
@ios.clear
|
201
|
+
|
202
|
+
return [points, keyframes]
|
207
203
|
end
|
208
204
|
|
209
205
|
# Setup output files and return a single output
|
data/lib/tracksperanto.rb
CHANGED
@@ -3,7 +3,7 @@
|
|
3
3
|
|
4
4
|
module Tracksperanto
|
5
5
|
PATH = File.expand_path(File.dirname(__FILE__))
|
6
|
-
VERSION = '2.9.
|
6
|
+
VERSION = '2.9.6'
|
7
7
|
|
8
8
|
module Import; end
|
9
9
|
module Export; end
|
@@ -38,6 +38,21 @@ module Tracksperanto
|
|
38
38
|
def middleware_names
|
39
39
|
middlewares.map{|e| e.const_name }
|
40
40
|
end
|
41
|
+
|
42
|
+
def exporters
|
43
|
+
sort_on_human_name(@exporters)
|
44
|
+
end
|
45
|
+
|
46
|
+
def importers
|
47
|
+
sort_on_human_name(@importers)
|
48
|
+
end
|
49
|
+
|
50
|
+
private
|
51
|
+
|
52
|
+
def sort_on_human_name(array)
|
53
|
+
array.sort!{|a, b| a.human_name <=> b.human_name }
|
54
|
+
array
|
55
|
+
end
|
41
56
|
end
|
42
57
|
|
43
58
|
self.exporters, self.importers, self.middlewares = [], [], []
|
@@ -86,6 +101,8 @@ end
|
|
86
101
|
simple_export
|
87
102
|
uv_coordinates
|
88
103
|
buffering_reader
|
104
|
+
parameters
|
105
|
+
yield_non_empty
|
89
106
|
).each do | submodule |
|
90
107
|
require File.join(Tracksperanto::PATH, "tracksperanto", submodule)
|
91
108
|
end
|
@@ -8,32 +8,32 @@ class Tracksperanto::FormatDetector
|
|
8
8
|
freeze
|
9
9
|
end
|
10
10
|
|
11
|
+
# Tells if an importer has been found for this file
|
12
|
+
def match?
|
13
|
+
!!@importer_klass
|
14
|
+
end
|
15
|
+
|
16
|
+
# Returns the importer if there is one
|
17
|
+
def importer_klass
|
18
|
+
@importer_klass
|
19
|
+
end
|
20
|
+
|
21
|
+
# Tells if comp size needs to be provided
|
22
|
+
def auto_size?
|
23
|
+
match? ? importer_klass.autodetects_size? : false
|
24
|
+
end
|
25
|
+
|
26
|
+
# Returns the human name of the importer
|
27
|
+
def human_importer_name
|
28
|
+
match? ? importer_klass.human_name : "Unknown format"
|
29
|
+
end
|
30
|
+
|
11
31
|
private
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
32
|
+
|
33
|
+
def perform_detection(for_path)
|
34
|
+
return unless (for_path && !for_path.to_s.empty?)
|
35
|
+
ext = File.extname(for_path.downcase)
|
36
|
+
@importer_klass = Tracksperanto.importers.find{ |i| i.distinct_file_ext == ext }
|
37
|
+
end
|
17
38
|
|
18
|
-
public
|
19
|
-
|
20
|
-
# Tells if an importer has been found for this extension
|
21
|
-
def match?
|
22
|
-
!!@importer_klass
|
23
|
-
end
|
24
|
-
|
25
|
-
# Returns the importer if there is one
|
26
|
-
def importer_klass
|
27
|
-
@importer_klass
|
28
|
-
end
|
29
|
-
|
30
|
-
# Tells if comp size needs to be provided
|
31
|
-
def auto_size?
|
32
|
-
match? ? importer_klass.autodetects_size? : false
|
33
|
-
end
|
34
|
-
|
35
|
-
# Returns the human name of the importer
|
36
|
-
def human_importer_name
|
37
|
-
match? ? importer_klass.human_name : "Unknown format"
|
38
|
-
end
|
39
39
|
end
|
@@ -0,0 +1,56 @@
|
|
1
|
+
module Tracksperanto::Parameters
|
2
|
+
|
3
|
+
def self.included(into)
|
4
|
+
into.extend(self)
|
5
|
+
super
|
6
|
+
end
|
7
|
+
|
8
|
+
class Parameter
|
9
|
+
include Tracksperanto::BlockInit
|
10
|
+
|
11
|
+
# The name of the paramenter and the related object attribute
|
12
|
+
attr_accessor :name
|
13
|
+
|
14
|
+
# Whether the attribute is required
|
15
|
+
attr_accessor :required
|
16
|
+
|
17
|
+
# Default value of the attribute
|
18
|
+
attr_accessor :default
|
19
|
+
|
20
|
+
# The cast for the attribute (like :int or :float)
|
21
|
+
attr_accessor :cast
|
22
|
+
|
23
|
+
# Attribute description for the UI
|
24
|
+
attr_accessor :desc
|
25
|
+
|
26
|
+
def apply_to(to_class)
|
27
|
+
to_class.send(:attr_accessor, name)
|
28
|
+
|
29
|
+
if cast
|
30
|
+
cast_call = "cast_to_#{cast}"
|
31
|
+
to_class.send(cast_call, name)
|
32
|
+
end
|
33
|
+
|
34
|
+
if required
|
35
|
+
to_class.safe_reader name
|
36
|
+
end
|
37
|
+
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
# Defines a parameter, options conform to the Parameter class.
|
42
|
+
# The parameter will of course add an attr_accessor to your class for the specified parameter,
|
43
|
+
# but it will also
|
44
|
+
def parameter(name, options = {})
|
45
|
+
options = {:name => name}.merge(options)
|
46
|
+
param = Parameter.new(options)
|
47
|
+
parameters.push(param)
|
48
|
+
param.apply_to(self)
|
49
|
+
end
|
50
|
+
|
51
|
+
# Returns the array of the parameters defined for this class
|
52
|
+
def parameters
|
53
|
+
@ui_parameters ||= []
|
54
|
+
@ui_parameters
|
55
|
+
end
|
56
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
# An Enumerable wrapper that will only yield non-empty elements
|
2
|
+
class Tracksperanto::YieldNonEmpty
|
3
|
+
|
4
|
+
include Enumerable
|
5
|
+
|
6
|
+
def initialize(obj)
|
7
|
+
@obj = obj
|
8
|
+
end
|
9
|
+
|
10
|
+
def each
|
11
|
+
@obj.each do | item |
|
12
|
+
yield(item) unless item.empty?
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -6,7 +6,7 @@ class NukeImportTest < Test::Unit::TestCase
|
|
6
6
|
|
7
7
|
def test_introspects_properly
|
8
8
|
i = Tracksperanto::Import::NukeScript
|
9
|
-
assert_equal "Nuke .nk script file", i.human_name
|
9
|
+
assert_equal "Nuke .nk script file with Tracker or Reconcile3D nodes", i.human_name
|
10
10
|
assert !i.autodetects_size?
|
11
11
|
end
|
12
12
|
|
@@ -20,6 +20,21 @@ class NukeImportTest < Test::Unit::TestCase
|
|
20
20
|
assert_equal 45, trackers.length
|
21
21
|
end
|
22
22
|
|
23
|
+
|
24
|
+
def test_parsing_from_reconciles
|
25
|
+
fixture = File.open(File.dirname(__FILE__) + '/samples/nuke/reconciles.nk')
|
26
|
+
|
27
|
+
parser = Tracksperanto::Import::NukeScript.new(:io => fixture)
|
28
|
+
parser.width = 2048
|
29
|
+
parser.height = 1176
|
30
|
+
|
31
|
+
trackers = parser.to_a.reject{|e| e.empty? }
|
32
|
+
|
33
|
+
assert_equal 5, trackers.length
|
34
|
+
assert_equal 128, trackers[0].length
|
35
|
+
end
|
36
|
+
|
37
|
+
|
23
38
|
def test_parsing_from_nuke
|
24
39
|
fixture = File.open(File.dirname(__FILE__) + '/samples/nuke/one_tracker_with_break.nk')
|
25
40
|
|
@@ -2,6 +2,11 @@
|
|
2
2
|
require File.expand_path(File.dirname(__FILE__)) + '/../helper'
|
3
3
|
|
4
4
|
class CropMiddlewareTest < Test::Unit::TestCase
|
5
|
+
|
6
|
+
def test_action_description
|
7
|
+
assert_equal "Crop or pad the image by a specified number of pixels", Tracksperanto::Middleware::Crop.action_description
|
8
|
+
end
|
9
|
+
|
5
10
|
def test_crop_supports_hash_init
|
6
11
|
receiver = flexmock
|
7
12
|
m = Tracksperanto::Middleware::Crop.new(receiver, :left => 13, :right => 0, :top => 25)
|
@@ -2,14 +2,9 @@
|
|
2
2
|
require File.expand_path(File.dirname(__FILE__)) + '/../helper'
|
3
3
|
|
4
4
|
class FlipMiddlewareTest < Test::Unit::TestCase
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
m = Tracksperanto::Middleware::Flip.new(receiver)
|
9
|
-
assert !m.enabled
|
10
|
-
|
11
|
-
m = Tracksperanto::Middleware::Flip.new(receiver, :enabled => true)
|
12
|
-
assert m.enabled
|
5
|
+
|
6
|
+
def test_action_description
|
7
|
+
assert_equal "Mirrors all the tracker paths horizontally", Tracksperanto::Middleware::Flip.action_description
|
13
8
|
end
|
14
9
|
|
15
10
|
def test_export_with_enabled_flip
|
@@ -17,17 +12,7 @@ class FlipMiddlewareTest < Test::Unit::TestCase
|
|
17
12
|
receiver.should_receive(:start_export).once.with(110, 120)
|
18
13
|
receiver.should_receive(:export_point).once.with(1, 100, 95, 0)
|
19
14
|
|
20
|
-
m = Tracksperanto::Middleware::Flip.new(receiver
|
21
|
-
m.start_export(110, 120)
|
22
|
-
m.export_point(1, 10, 95, 0)
|
23
|
-
end
|
24
|
-
|
25
|
-
def test_export_with_disabled_flip
|
26
|
-
receiver = flexmock(:exporter)
|
27
|
-
receiver.should_receive(:start_export).once.with(110, 120)
|
28
|
-
receiver.should_receive(:export_point).once.with(1, 10, 95, 0)
|
29
|
-
|
30
|
-
m = Tracksperanto::Middleware::Flip.new(receiver, :enabled => false)
|
15
|
+
m = Tracksperanto::Middleware::Flip.new(receiver)
|
31
16
|
m.start_export(110, 120)
|
32
17
|
m.export_point(1, 10, 95, 0)
|
33
18
|
end
|