tracksperanto 1.7.4 → 1.7.5
Sign up to get free protection for your applications and to get access to all the features.
- data/History.txt +4 -0
- data/Manifest.txt +2 -0
- data/bin/tracksperanto +13 -7
- data/lib/export/syntheyes.rb +4 -4
- data/lib/import/shake_grammar/lexer.rb +4 -2
- data/lib/pipeline/base.rb +16 -3
- data/lib/tracksperanto.rb +4 -5
- data/lib/tracksperanto/ext_io.rb +3 -3
- data/lib/tracksperanto/progressive_io.rb +79 -0
- data/test/test_progressive_io.rb +119 -0
- metadata +5 -2
data/History.txt
CHANGED
data/Manifest.txt
CHANGED
@@ -46,6 +46,7 @@ lib/tracksperanto/const_name.rb
|
|
46
46
|
lib/tracksperanto/ext_io.rb
|
47
47
|
lib/tracksperanto/format_detector.rb
|
48
48
|
lib/tracksperanto/keyframe.rb
|
49
|
+
lib/tracksperanto/progressive_io.rb
|
49
50
|
lib/tracksperanto/safety.rb
|
50
51
|
lib/tracksperanto/simple_export.rb
|
51
52
|
lib/tracksperanto/tracker.rb
|
@@ -129,6 +130,7 @@ test/test_const_name.rb
|
|
129
130
|
test/test_extio.rb
|
130
131
|
test/test_format_detector.rb
|
131
132
|
test/test_keyframe.rb
|
133
|
+
test/test_progressive_io.rb
|
132
134
|
test/test_simple_export.rb
|
133
135
|
test/test_tracker.rb
|
134
136
|
test/test_tracksperanto.rb
|
data/bin/tracksperanto
CHANGED
@@ -92,7 +92,6 @@ end
|
|
92
92
|
input_file = ARGV.pop
|
93
93
|
if !input_file
|
94
94
|
STDERR.puts "No input file provided - should be the last argument"
|
95
|
-
puts parser
|
96
95
|
exit(-1)
|
97
96
|
end
|
98
97
|
|
@@ -100,20 +99,26 @@ class Spinner
|
|
100
99
|
RING = ['|', '/', '-', '\\', '|', '/', '-', '\\']
|
101
100
|
|
102
101
|
def initialize
|
103
|
-
@counter = 0
|
104
|
-
@last_message_length = 0
|
102
|
+
@counter, @last_len = 0, 0
|
105
103
|
end
|
106
104
|
|
107
105
|
def spin(percent, msg)
|
108
106
|
current = RING[(@counter += 1) % RING.length]
|
109
107
|
output = " [%s %d%%]" % [current, percent]
|
110
|
-
STDOUT.write(output + "\r" * output.length)
|
108
|
+
STDOUT.write(output + ("\r" * output.length))
|
111
109
|
STDOUT.flush
|
110
|
+
@last_len = output.length
|
111
|
+
end
|
112
|
+
|
113
|
+
def finish(with_message = '')
|
114
|
+
STDOUT.write("\r" * @last_len.to_i)
|
115
|
+
STDOUT.flush
|
116
|
+
STDOUT.puts(with_message)
|
112
117
|
end
|
113
118
|
end
|
114
119
|
|
115
|
-
|
116
|
-
pipe
|
120
|
+
spinner = Spinner.new
|
121
|
+
pipe = Tracksperanto::Pipeline::Base.new(:progress_block => spinner.method(:spin).to_proc)
|
117
122
|
|
118
123
|
if sole_format
|
119
124
|
begin
|
@@ -137,4 +142,5 @@ pipe.run(input_file, :pix_w => width, :pix_h => height, :parser => reader_klass)
|
|
137
142
|
lerpm.enabled = lerp
|
138
143
|
len.min_length = length_gate
|
139
144
|
end
|
140
|
-
|
145
|
+
|
146
|
+
spinner.finish("Converted #{pipe.converted_points} trackers with #{pipe.converted_keyframes} keys")
|
data/lib/export/syntheyes.rb
CHANGED
@@ -25,7 +25,7 @@ class Tracksperanto::Export::SynthEyes < Tracksperanto::Export::Base
|
|
25
25
|
end
|
26
26
|
|
27
27
|
def start_tracker_segment(tracker_name)
|
28
|
-
@
|
28
|
+
@last_registered_frame, @tracker_name = nil, tracker_name
|
29
29
|
end
|
30
30
|
|
31
31
|
def export_point(frame, abs_float_x, abs_float_y, float_residual)
|
@@ -38,14 +38,14 @@ class Tracksperanto::Export::SynthEyes < Tracksperanto::Export::Base
|
|
38
38
|
# It's very important that we provide an outcome code for Syntheyes. Regular keyframes get
|
39
39
|
# STATUS_STD, and after a gap we have to signal STATUS_REENABLE, otherwise this might bust solves
|
40
40
|
def get_outcome_code(frame)
|
41
|
-
outcome = if @
|
41
|
+
outcome = if @last_registered_frame.nil?
|
42
42
|
STATUS_KF
|
43
|
-
elsif @
|
43
|
+
elsif @last_registered_frame != (frame - 1)
|
44
44
|
STATUS_REENABLE
|
45
45
|
else
|
46
46
|
STATUS_STD
|
47
47
|
end
|
48
|
-
@
|
48
|
+
@last_registered_frame = frame
|
49
49
|
outcome
|
50
50
|
end
|
51
51
|
end
|
@@ -12,6 +12,8 @@ module Tracksperanto::ShakeGrammar
|
|
12
12
|
attr_reader :sentinel
|
13
13
|
|
14
14
|
STOP_TOKEN = :__stop #:nodoc:
|
15
|
+
MAX_BUFFER_SIZE = 32000
|
16
|
+
MAX_STACK_DEPTH = 127
|
15
17
|
|
16
18
|
# The first argument is the IO handle to the data of the Shake script.
|
17
19
|
# The second argument is a "sentinel" that is going to be passed
|
@@ -42,11 +44,11 @@ module Tracksperanto::ShakeGrammar
|
|
42
44
|
|
43
45
|
c = @io.read(1)
|
44
46
|
|
45
|
-
if @buf.length >
|
47
|
+
if @buf.length > MAX_BUFFER_SIZE # Wrong format and the buffer is filled up, bail
|
46
48
|
raise WrongInput, "Buffer overflow at 32K, this is definitely not a Shake script"
|
47
49
|
end
|
48
50
|
|
49
|
-
if @stack_depth >
|
51
|
+
if @stack_depth > MAX_STACK_DEPTH # Wrong format - parentheses overload
|
50
52
|
raise WrongInput, "Stack overflow at level 128, this is probably a LISP program uploaded by accident"
|
51
53
|
end
|
52
54
|
|
data/lib/pipeline/base.rb
CHANGED
@@ -13,6 +13,8 @@
|
|
13
13
|
# and setup outputs for all supported export formats.
|
14
14
|
class Tracksperanto::Pipeline::Base
|
15
15
|
|
16
|
+
include Tracksperanto::BlockInit
|
17
|
+
|
16
18
|
# How many points have been converted. In general, the pipeline does not preserve the parsed tracker objects
|
17
19
|
# after they have been exported
|
18
20
|
attr_reader :converted_points
|
@@ -83,16 +85,27 @@ class Tracksperanto::Pipeline::Base
|
|
83
85
|
# If a block is passed, the block will receive the percent complete and the last
|
84
86
|
# status message that you can pass back to the UI
|
85
87
|
def run_export(tracker_data_io, parser, processor)
|
86
|
-
@ios << tracker_data_io
|
87
|
-
|
88
88
|
points, keyframes, percent_complete = 0, 0, 0.0
|
89
89
|
|
90
90
|
yield(percent_complete, "Starting the parser") if block_given?
|
91
|
+
|
92
|
+
# Report progress from the parser
|
91
93
|
parser.progress_block = lambda do | message |
|
92
94
|
yield(percent_complete, message) if block_given?
|
93
95
|
end
|
94
96
|
|
95
|
-
|
97
|
+
# Wrap the input in a progressive IO
|
98
|
+
io_with_progress = Tracksperanto::ProgressiveIO.new(tracker_data_io)
|
99
|
+
@ios << io_with_progress
|
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 |
|
105
|
+
percent_complete = (50.0 / of_total) * offset
|
106
|
+
end
|
107
|
+
|
108
|
+
trackers = parser.parse(io_with_progress)
|
96
109
|
|
97
110
|
validate_trackers!(trackers)
|
98
111
|
|
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.7.
|
7
|
+
VERSION = '1.7.5'
|
8
8
|
|
9
9
|
module Import; end
|
10
10
|
module Export; end
|
@@ -42,8 +42,7 @@ module Tracksperanto
|
|
42
42
|
# Case-insensitive search for an export module by name
|
43
43
|
def self.get_exporter(name)
|
44
44
|
exporters.each do | x |
|
45
|
-
|
46
|
-
return x if normalized_name == name.downcase
|
45
|
+
return x if x.const_name.downcase == name.downcase
|
47
46
|
end
|
48
47
|
|
49
48
|
raise NameError, "Unknown exporter #{name}"
|
@@ -52,8 +51,7 @@ module Tracksperanto
|
|
52
51
|
# Case-insensitive search for an export module by name
|
53
52
|
def self.get_importer(name)
|
54
53
|
importers.each do | x |
|
55
|
-
|
56
|
-
return x if normalized_name == name.downcase
|
54
|
+
return x if x.const_name.downcase == name.downcase
|
57
55
|
end
|
58
56
|
|
59
57
|
raise NameError, "Unknown importer #{name}"
|
@@ -70,6 +68,7 @@ end
|
|
70
68
|
tracker
|
71
69
|
format_detector
|
72
70
|
ext_io
|
71
|
+
progressive_io
|
73
72
|
simple_export
|
74
73
|
uv_coordinates
|
75
74
|
).each do | submodule |
|
data/lib/tracksperanto/ext_io.rb
CHANGED
@@ -1,17 +1,17 @@
|
|
1
1
|
# Many importers use this as a standard. This works like a wrapper for any
|
2
|
-
# IO object with a couple extra methods added
|
2
|
+
# IO object with a couple extra methods added.
|
3
3
|
class Tracksperanto::ExtIO < DelegateClass(IO)
|
4
4
|
def initialize(with)
|
5
5
|
__setobj__ with
|
6
6
|
end
|
7
7
|
|
8
8
|
def gets_and_strip
|
9
|
-
s =
|
9
|
+
s = gets
|
10
10
|
s ? s.strip : nil
|
11
11
|
end
|
12
12
|
|
13
13
|
def gets_non_empty
|
14
|
-
line =
|
14
|
+
line = gets
|
15
15
|
return nil if line.nil?
|
16
16
|
s = line.strip
|
17
17
|
return gets_non_empty if s.empty?
|
@@ -0,0 +1,79 @@
|
|
1
|
+
# Used for IO objects that need to report the current offset at each operation that changes the said offset
|
2
|
+
# (useful for building progress bars that report on a file read operation)
|
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
|
7
|
+
|
8
|
+
# Get or set the total size of the contained IO. If the passed IO is a File object
|
9
|
+
# the size will be preset automatically
|
10
|
+
attr_accessor :total_size
|
11
|
+
|
12
|
+
def initialize(with_file)
|
13
|
+
__setobj__(with_file)
|
14
|
+
@total_size = with_file.stat.size if with_file.respond_to?(:stat)
|
15
|
+
end
|
16
|
+
|
17
|
+
def each(sep_string = $/, &blk)
|
18
|
+
# Report offset at each call of the iterator
|
19
|
+
result = super(sep_string) do | line |
|
20
|
+
yield(line)
|
21
|
+
notify_read
|
22
|
+
end
|
23
|
+
end
|
24
|
+
alias_method :each_line, :each
|
25
|
+
|
26
|
+
def each_byte(&blk)
|
27
|
+
# Report offset at each call of the iterator
|
28
|
+
super { |b| yield(b); notify_read }
|
29
|
+
end
|
30
|
+
|
31
|
+
def getc
|
32
|
+
returning(super) { notify_read }
|
33
|
+
end
|
34
|
+
|
35
|
+
def gets
|
36
|
+
returning(super) { notify_read }
|
37
|
+
end
|
38
|
+
|
39
|
+
def read(*a)
|
40
|
+
returning(super) { notify_read }
|
41
|
+
end
|
42
|
+
|
43
|
+
def readbytes(*a)
|
44
|
+
returning(super) { notify_read }
|
45
|
+
end
|
46
|
+
|
47
|
+
def readchar
|
48
|
+
returning(super) { notify_read }
|
49
|
+
end
|
50
|
+
|
51
|
+
def readline(*a)
|
52
|
+
returning(super) { notify_read }
|
53
|
+
end
|
54
|
+
|
55
|
+
def readlines(*a)
|
56
|
+
returning(super) { notify_read }
|
57
|
+
end
|
58
|
+
|
59
|
+
def seek(*a)
|
60
|
+
returning(super) { notify_read }
|
61
|
+
end
|
62
|
+
|
63
|
+
def ungetc(*a)
|
64
|
+
returning(super) { notify_read }
|
65
|
+
end
|
66
|
+
|
67
|
+
def pos=(p)
|
68
|
+
returning(super) { notify_read }
|
69
|
+
end
|
70
|
+
|
71
|
+
private
|
72
|
+
def returning(r)
|
73
|
+
yield; r
|
74
|
+
end
|
75
|
+
|
76
|
+
def notify_read
|
77
|
+
@progress_block.call(pos, @total_size) if @progress_block
|
78
|
+
end
|
79
|
+
end
|
@@ -0,0 +1,119 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/helper'
|
2
|
+
|
3
|
+
class TestProgressiveIO < Test::Unit::TestCase
|
4
|
+
|
5
|
+
def e(s)
|
6
|
+
|
7
|
+
# Make a mock File object from a string
|
8
|
+
io = StringIO.new(s)
|
9
|
+
mock_stat = flexmock(:size => s.length)
|
10
|
+
flexmock(io).should_receive(:stat).and_return(mock_stat)
|
11
|
+
|
12
|
+
Tracksperanto::ProgressiveIO.new(io)
|
13
|
+
end
|
14
|
+
|
15
|
+
def test_each
|
16
|
+
io, messages = e("Mary\nHad\nA little\nLamb"), []
|
17
|
+
|
18
|
+
io.progress_block = lambda do | offset, total |
|
19
|
+
messages.push([offset, total])
|
20
|
+
end
|
21
|
+
|
22
|
+
lines = []
|
23
|
+
io.each {|line| lines.push(line) }
|
24
|
+
assert_equal ["Mary\n", "Had\n", "A little\n", "Lamb"], lines
|
25
|
+
assert_equal [[5, 22], [9, 22], [18, 22], [22, 22]], messages
|
26
|
+
end
|
27
|
+
|
28
|
+
def test_each_byte
|
29
|
+
io, messages = e("123"), []
|
30
|
+
|
31
|
+
io.progress_block = lambda do | offset, total |
|
32
|
+
messages.push([offset, total])
|
33
|
+
end
|
34
|
+
|
35
|
+
bytes = []
|
36
|
+
io.each_byte{|s| bytes << s }
|
37
|
+
assert_equal [49, 50, 51], bytes
|
38
|
+
assert_equal [[1, 3], [2, 3], [3, 3]], messages
|
39
|
+
end
|
40
|
+
|
41
|
+
def test_getc
|
42
|
+
io = e("123")
|
43
|
+
io.progress_block = lambda do | offset, total |
|
44
|
+
assert_equal [1, 3], [offset, total]
|
45
|
+
end
|
46
|
+
assert_equal 49, io.getc
|
47
|
+
end
|
48
|
+
|
49
|
+
def test_gets
|
50
|
+
io = e("Mary\nHad\nA little\nLamb")
|
51
|
+
io.progress_block = lambda do | offset, total |
|
52
|
+
assert_equal [5, 22], [offset, total]
|
53
|
+
end
|
54
|
+
assert_equal "Mary\n", io.gets
|
55
|
+
end
|
56
|
+
|
57
|
+
def test_read
|
58
|
+
io = e("Mary\nHad\nA little\nLamb")
|
59
|
+
io.progress_block = lambda do | offset, total |
|
60
|
+
assert_equal [15, 22], [offset, total]
|
61
|
+
end
|
62
|
+
assert_equal "Mary\nHad\nA litt", io.read(15)
|
63
|
+
end
|
64
|
+
|
65
|
+
def test_readchar
|
66
|
+
io = e("123")
|
67
|
+
io.progress_block = lambda do | offset, total |
|
68
|
+
assert_equal [1, 3], [offset, total]
|
69
|
+
end
|
70
|
+
assert_equal 49, io.readchar
|
71
|
+
end
|
72
|
+
|
73
|
+
def test_readline
|
74
|
+
io = e("Mary\nHad\nA little\nLamb")
|
75
|
+
io.progress_block = lambda do | offset, total |
|
76
|
+
assert_equal [5, 22], [offset, total]
|
77
|
+
end
|
78
|
+
assert_equal "Mary\n", io.readline
|
79
|
+
end
|
80
|
+
|
81
|
+
def test_readlines
|
82
|
+
io = e("Mary\nHad\nA little\nLamb")
|
83
|
+
m = []
|
84
|
+
io.progress_block = lambda do | offset, total |
|
85
|
+
m.push([offset, total])
|
86
|
+
end
|
87
|
+
|
88
|
+
assert_equal ["Mary\n", "Had\n", "A little\n", "Lamb"], io.readlines
|
89
|
+
assert_equal [[22, 22]], m
|
90
|
+
end
|
91
|
+
|
92
|
+
def test_seek
|
93
|
+
io = e("Mary\nHad\nA little\nLamb")
|
94
|
+
io.progress_block = lambda do | offset, total |
|
95
|
+
assert_equal [6, 22], [offset, total]
|
96
|
+
end
|
97
|
+
io.seek(6)
|
98
|
+
end
|
99
|
+
|
100
|
+
def test_ungetc
|
101
|
+
io = e("Mary\nHad\nA little\nLamb")
|
102
|
+
m = []
|
103
|
+
io.progress_block = lambda do | offset, total |
|
104
|
+
m.push([offset, total])
|
105
|
+
end
|
106
|
+
|
107
|
+
io.getc
|
108
|
+
io.ungetc(2)
|
109
|
+
assert_equal [[1, 22], [0, 22]], m
|
110
|
+
end
|
111
|
+
|
112
|
+
def test_poseq
|
113
|
+
io = e("Mary\nHad\nA little\nLamb")
|
114
|
+
io.progress_block = lambda do | offset, total |
|
115
|
+
assert_equal [2, 22], [offset, total]
|
116
|
+
end
|
117
|
+
io.pos = 2
|
118
|
+
end
|
119
|
+
end
|
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.7.
|
4
|
+
version: 1.7.5
|
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-02-
|
12
|
+
date: 2010-02-17 00:00:00 +01:00
|
13
13
|
default_executable:
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
@@ -93,6 +93,7 @@ files:
|
|
93
93
|
- lib/tracksperanto/ext_io.rb
|
94
94
|
- lib/tracksperanto/format_detector.rb
|
95
95
|
- lib/tracksperanto/keyframe.rb
|
96
|
+
- lib/tracksperanto/progressive_io.rb
|
96
97
|
- lib/tracksperanto/safety.rb
|
97
98
|
- lib/tracksperanto/simple_export.rb
|
98
99
|
- lib/tracksperanto/tracker.rb
|
@@ -176,6 +177,7 @@ files:
|
|
176
177
|
- test/test_extio.rb
|
177
178
|
- test/test_format_detector.rb
|
178
179
|
- test/test_keyframe.rb
|
180
|
+
- test/test_progressive_io.rb
|
179
181
|
- test/test_simple_export.rb
|
180
182
|
- test/test_tracker.rb
|
181
183
|
- test/test_tracksperanto.rb
|
@@ -244,6 +246,7 @@ test_files:
|
|
244
246
|
- test/test_extio.rb
|
245
247
|
- test/test_format_detector.rb
|
246
248
|
- test/test_keyframe.rb
|
249
|
+
- test/test_progressive_io.rb
|
247
250
|
- test/test_simple_export.rb
|
248
251
|
- test/test_tracker.rb
|
249
252
|
- test/test_tracksperanto.rb
|