flame_channel_parser 1.1.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,73 @@
1
+ require "test/unit"
2
+
3
+ class TestFlameChannelParser < Test::Unit::TestCase
4
+ D = 0.0001
5
+
6
+ def test_parsing_baked_timewarp_from_2011
7
+ data = File.open(File.dirname(__FILE__) + "/snaps/TW.timewarp")
8
+ chan = FlameChannelParser.parse(data).find{|c| c.name == "Timing/Timing"}
9
+ assert_equal 816, chan.length
10
+ assert_equal 1, chan[0].frame
11
+ assert_equal 816, chan[-1].frame
12
+ end
13
+
14
+ def test_parsing
15
+ data = File.open(File.dirname(__FILE__) + "/sample_channel.dat")
16
+ channels = FlameChannelParser.parse(data)
17
+ assert_kind_of Array, channels
18
+ assert_equal 1, channels.length, "Should find one channel"
19
+
20
+ assert_kind_of FlameChannelParser::Parser2011::ChannelBlock, channels[0]
21
+
22
+ ch = channels[0]
23
+ assert_equal 4, ch.length
24
+
25
+ peculiar_key = ch[1]
26
+ assert_in_delta D, 858.177, peculiar_key.value
27
+ assert_in_delta D, 2.31503, peculiar_key.left_slope
28
+ assert_in_delta D, 2.31503, peculiar_key.right_slope
29
+ assert_equal :constant, peculiar_key.interpolation
30
+ end
31
+
32
+ def test_action
33
+ f = File.open(File.dirname(__FILE__) + "/snaps/FLEM_curves_example.action")
34
+ channels = FlameChannelParser.parse(f)
35
+
36
+ assert_kind_of Array, channels
37
+ assert_equal 65, channels.length, "Should find 65 channels"
38
+ channels.reject!{|c| c.length < 2 }
39
+ assert_equal 2, channels.length, "Should have 2 channels with more than 2 keyframes"
40
+ last_chan = channels[-1]
41
+ assert_equal "position/y", last_chan.name
42
+ assert_equal 6, last_chan.length
43
+ end
44
+
45
+ def test_action_from_2012
46
+ f = File.open(File.dirname(__FILE__) + "/snaps/FLEM_advanced_curve_example_FL2012.action")
47
+ channels = FlameChannelParser.parse(f)
48
+
49
+ assert_kind_of Array, channels
50
+ assert_equal 65, channels.length, "Should find 65 channels"
51
+ channels.reject!{|c| c.length < 2 }
52
+ assert_equal 2, channels.length, "Should have 2 channels with more than 2 keyframes"
53
+
54
+ last_chan = channels[-1]
55
+ assert_equal "position/y", last_chan.name
56
+ assert_equal 9, last_chan.length
57
+ end
58
+
59
+ def test_action_migrated_to_2012
60
+ f = File.open(File.dirname(__FILE__) + "/snaps/FLEM_curves_example_migrated_to_2012.action")
61
+ channels = FlameChannelParser.parse(f)
62
+
63
+ assert_kind_of Array, channels
64
+ assert_equal 65, channels.length, "Should find 65 channels"
65
+ channels.reject!{|c| c.length < 2 }
66
+ assert_equal 2, channels.length, "Should have 2 channels with more than 2 keyframes"
67
+
68
+ last_chan = channels[-1]
69
+ assert_equal "position/y", last_chan.name
70
+ assert_equal 6, last_chan.length
71
+ end
72
+
73
+ end
@@ -0,0 +1,89 @@
1
+ require "test/unit"
2
+ require "stringio"
3
+
4
+ require File.dirname(__FILE__) + "/../lib/flame_channel_parser"
5
+
6
+ class TestInterpolator < Test::Unit::TestCase
7
+ DELTA = 0.05
8
+
9
+ def assert_same_interpolation(range, ref_channel, sample_channel)
10
+ ref_i, sample_i = [ref_channel, sample_channel].map{|c| FlameChannelParser::Interpolator.new(c) }
11
+
12
+ value_tuples = range.map do |f|
13
+ [f, ref_i.sample_at(f), sample_i.sample_at(f)]
14
+ end
15
+
16
+ begin
17
+ value_tuples.each do | frame, ref, actual |
18
+ assert_in_delta ref, actual, DELTA, "At #{frame} interpolated value should be in delta"
19
+ end
20
+ rescue Test::Unit::AssertionFailedError => e
21
+ STDERR.puts "Curves were not the same so I will now copy the two curves to the clipboard"
22
+ # This is handy for plotting
23
+ IO.popen("pbcopy", "w") do | buf |
24
+ range.map{|f| buf.puts "%03f\t%03f" % [ref_i.sample_at(f), sample_i.sample_at(f)] }
25
+ end
26
+ raise e
27
+ end
28
+ end
29
+
30
+ def test_channel_with_constants
31
+ data = File.open(File.dirname(__FILE__) + "/channel_with_constants.dat")
32
+ constants = FlameChannelParser.parse(data).find{|c| c.name == "constants"}
33
+ interp = FlameChannelParser::Interpolator.new(constants)
34
+
35
+ vs = [770.41, 770.41, 770.41, 770.41, 770.41, 770.41, 770.41, 770.41, 770.41, 770.41, 770.41, 770.41, 770.41, 770.41, 770.41, 770.41, 770.41, 770.41, 770.41, 770.41, 770.41, 770.41, 770.41, 770.41, 770.41, 770.41, 770.41, 770.41, 770.41, 770.41, 770.41, 770.41, 770.41, 770.41, 770.41, 770.41, 770.41, 770.41, 770.41, 770.41, 770.41, 770.41, 770.41, 770.41, 770.41, 770.41, 770.41, 770.41, 770.41, 858.177, 858.177, 858.177, 858.177, 858.177, 858.177, 858.177, 858.177, 858.177, 858.177, 858.177, 858.177, 858.177, 858.177, 858.177, 858.177, 858.177, 858.177, 858.177, 858.177, 858.177, 858.177, 858.177, 858.177, 858.177, 858.177, 858.177, 858.177, 858.177, 858.177, 939.407, 939.407, 939.407, 939.407, 939.407, 939.407, 939.407, 939.407, 939.407, 939.407, 939.407, 939.407, 939.407, 939.407, 939.407, 939.407, 939.407, 939.407, 939.407, 939.407, 939.407, 939.407, 939.407, 939.407, 939.407, 939.407, 939.407, 939.407, 939.407, 939.407, 939.407, 939.407, 939.407, 939.407, 939.407, 939.407, 939.407, 939.407, 939.407, 939.407, 939.407, 1017.36, 1017.36]
36
+
37
+ values = (-5..116).map{|f| interp.sample_at(f) }
38
+ assert_equal vs, values
39
+ end
40
+
41
+ def test_baked_timewarp_from_2011
42
+ data = File.open(File.dirname(__FILE__) + "/snaps/TW.timewarp")
43
+ chan = FlameChannelParser.parse(data).find{|c| c.name == "Timing/Timing"}
44
+ sampler = FlameChannelParser::Interpolator.new(chan)
45
+
46
+ assert_equal 1, sampler.first_defined_frame
47
+ assert_equal 816, sampler.last_defined_frame
48
+ end
49
+
50
+ def test_simple_setup_from_2011
51
+ data = File.open(File.dirname(__FILE__) + "/snaps/FLEM_curves_example.action")
52
+ channels_in_action = FlameChannelParser::Parser2011.new.parse(data)
53
+ channels_in_action.reject!{|c| c.length < 4 }
54
+
55
+ reference = channels_in_action.find{|c| c.name == "position/x" && c.length > 2}
56
+ sampled = channels_in_action.find{|c| c.name == "position/y" && c.length > 2}
57
+ assert_same_interpolation(1..200, reference, sampled)
58
+ end
59
+
60
+ def test_broken_tangents_setup_from_2011
61
+ data = File.open(File.dirname(__FILE__) + "/snaps/FLEM_BrokenTangents.action")
62
+ channels_in_action = FlameChannelParser.parse(data)
63
+ channels_in_action.reject!{|c| c.length < 4 }
64
+
65
+ reference = channels_in_action.find{|c| c.name == "position/x" }
66
+ sampled = channels_in_action.find{|c| c.name == "position/y" }
67
+ assert_same_interpolation(1..200, reference, sampled)
68
+ end
69
+
70
+ def test_setup_moved_from_2011_to_2012_parses_the_same
71
+ data = File.open(File.dirname(__FILE__) + "/snaps/FLEM_curves_example.action")
72
+ data_2012 = File.open(File.dirname(__FILE__) + "/snaps/FLEM_curves_example_migrated_to_2012.action")
73
+
74
+ ref = FlameChannelParser.parse(data).find{|e| e.name == "position/x" && e.length > 12 }
75
+ sampled = FlameChannelParser.parse(data_2012).find{|e| e.name == "position/y" && e.length > 5 }
76
+
77
+ assert_same_interpolation(1..200, ref, sampled)
78
+ end
79
+
80
+ def test_setup_from_2012_with_beziers
81
+ data = File.open(File.dirname(__FILE__) + "/snaps/FLEM_advanced_curve_example_FL2012.action")
82
+ channels_in_action = FlameChannelParser.parse(data)
83
+ channels_in_action.reject!{|c| c.length < 4 }
84
+
85
+ reference = channels_in_action.find{|c| c.name == "position/x" && c.length > 2 }
86
+ sampled = channels_in_action.find{|c| c.name == "position/y" && c.length > 2 }
87
+ assert_same_interpolation(1..330, reference, sampled)
88
+ end
89
+ end
@@ -0,0 +1,261 @@
1
+ require "test/unit"
2
+ require File.dirname(__FILE__) + "/../lib/flame_channel_parser"
3
+
4
+ D = 0.001
5
+
6
+ include FlameChannelParser::Segments
7
+
8
+ class TestConstantFunction < Test::Unit::TestCase
9
+ def test_segment
10
+ seg = ConstantFunction.new(123.4)
11
+ assert seg.defines?(-1), "The segment should define this frame"
12
+ assert seg.defines?(4567), "The segment should define this frame"
13
+ assert_equal 123.4, seg.value_at(123), "This is the segment's constant value"
14
+ end
15
+ end
16
+
17
+
18
+ class TestConstantSegment < Test::Unit::TestCase
19
+ def test_segment
20
+ seg = ConstantSegment.new(12, 25, 2.5)
21
+
22
+ assert !seg.defines?(11), "This frame is outside the segment"
23
+ assert !seg.defines?(26), "This frame is outside the segment"
24
+ assert seg.defines?(12), "Frame 12 defined"
25
+ assert seg.defines?(24), "Frame 24 defined"
26
+
27
+ assert_equal 2.5, seg.value_at(11)
28
+ assert_equal 2.5, seg.value_at(14)
29
+ assert_equal 2.5, seg.value_at(26)
30
+ end
31
+ end
32
+
33
+ class TestBezierSegment < Test::Unit::TestCase
34
+ D = 0.001
35
+
36
+ def test_segment
37
+ seg = BezierSegment.new(
38
+ frame_from = 117,
39
+ frame_to = 149,
40
+ value_from = 1.23907006,
41
+ value_to = 258.239014,
42
+ handle_left_x = 117.25,
43
+ handle_left_y = 4.76008224,
44
+ handle_right_x = 138.333328,
45
+ handle_right_y = 258.398254
46
+ )
47
+ assert seg.defines?(117)
48
+ assert !seg.defines?(149)
49
+ assert !seg.defines?(151)
50
+ assert !seg.defines?(116)
51
+
52
+ assert_in_delta 1.23907006, seg.value_at(25), D
53
+ assert_in_delta 24.7679917574603, seg.value_at(119), D
54
+ end
55
+ end
56
+
57
+ class TestLinearSegment < Test::Unit::TestCase
58
+ def test_segment
59
+ seg = LinearSegment.new(12, 25, 2.5, 4.5)
60
+
61
+ assert !seg.defines?(11), "This frame is outside the segment"
62
+ assert !seg.defines?(26), "This frame is outside the segment"
63
+ assert seg.defines?(12), "Frame 12 defined"
64
+ assert seg.defines?(24), "Frame 24 defined"
65
+
66
+ assert_in_delta 2.8076, seg.value_at(14), D
67
+ assert_in_delta 2.9615, seg.value_at(15), D
68
+ end
69
+ end
70
+
71
+
72
+ class TestConstantPrepolate < Test::Unit::TestCase
73
+ def test_segment
74
+ seg = ConstantPrepolate.new(12, 234.5)
75
+ assert seg.defines?(11)
76
+ assert !seg.defines?(12)
77
+ assert !seg.defines?(13)
78
+ assert seg.defines?(-1234)
79
+ assert_equal 234.5, seg.value_at(12)
80
+ end
81
+ end
82
+
83
+ class TestHermiteSegment < Test::Unit::TestCase
84
+ def test_last_curve_segment
85
+ refdata = %w(
86
+ 258.239
87
+ 257.937
88
+ 257.074
89
+ 255.674
90
+ 253.759
91
+ 251.352
92
+ 248.476
93
+ 245.152
94
+ 241.405
95
+ 237.255
96
+ 232.727
97
+ 227.842
98
+ 222.624
99
+ 217.094
100
+ 211.276
101
+ 205.192
102
+ 198.865
103
+ 192.317
104
+ 185.571
105
+ 178.65
106
+ 171.576
107
+ 164.372
108
+ 157.06
109
+ 149.664
110
+ 142.205
111
+ 134.707
112
+ 127.192
113
+ 119.683
114
+ 112.202
115
+ 104.772
116
+ 97.4151
117
+ 90.1547
118
+ 83.0132
119
+ 76.0132
120
+ 69.1772
121
+ 62.528
122
+ 56.0881
123
+ 49.8802
124
+ 43.9269
125
+ 38.2508
126
+ 32.8746
127
+ 27.8209
128
+ 23.1124
129
+ 18.7715
130
+ 14.8212
131
+ 11.2838
132
+ 8.18198
133
+ 5.53853
134
+ 3.37598
135
+ 1.71692
136
+ 0.584045
137
+ 0.0
138
+ ).map{|e| e.to_f }
139
+
140
+ herm = HermiteSegment.new(
141
+ time_from = 149,
142
+ time_to = 200,
143
+ value1 = 258.239,
144
+ value2 = 0,
145
+ tangent1 = -0.0149286,
146
+ tangent2 = -0.302127
147
+ )
148
+
149
+ interpolated = (149..200).map(&herm.method(:value_at))
150
+
151
+ refdata.zip(interpolated).each do | ref, actual |
152
+ assert_in_delta ref, actual, D, "Interpolated value should be in delta"
153
+ end
154
+ end
155
+
156
+ def test_first_curve_segment
157
+ refdata = %w(
158
+ 222.919
159
+ 222.543
160
+ 221.735
161
+ 220.506
162
+ 218.867
163
+ 216.83
164
+ 214.406
165
+ 211.608
166
+ 208.445
167
+ 204.931
168
+ 201.075
169
+ 196.89
170
+ 192.387
171
+ 187.578
172
+ 182.473
173
+ 177.085
174
+ 171.425
175
+ 165.503
176
+ 159.333
177
+ 152.924
178
+ 146.29
179
+ 139.44
180
+ 132.386
181
+ 125.141
182
+ 117.715
183
+ 110.119
184
+ 102.366
185
+ 94.4661
186
+ 86.4316
187
+ 78.2735
188
+ 70.0034
189
+ 61.6327
190
+ 53.1728
191
+ 44.6353
192
+ 36.0314
193
+ 27.3727
194
+ 18.6705
195
+ 9.93645
196
+ 1.18185
197
+ -7.58185
198
+ -16.3432
199
+ -25.0907
200
+ -33.813
201
+ -42.4985
202
+ -51.136
203
+ -59.714
204
+ -68.2209
205
+ -76.6454
206
+ -84.9759
207
+ -93.2012
208
+ -101.31
209
+ -109.29
210
+ -117.131
211
+ -124.82
212
+ -132.347
213
+ -139.7
214
+ -146.868
215
+ -153.839
216
+ -160.601
217
+ -167.144
218
+ -173.456
219
+ -179.525
220
+ -185.34
221
+ -190.889
222
+ -196.162
223
+ -201.146
224
+ -205.83
225
+ -210.204
226
+ -214.254
227
+ -217.97
228
+ -221.341
229
+ -224.355
230
+ -227.0
231
+ ).map{|e| e.to_f }
232
+
233
+ herm = HermiteSegment.new(
234
+ time_from = 22,
235
+ time_to = 94,
236
+ value1 = 222.919,
237
+ value2 = -227.0,
238
+ tangent1 = -0.156017,
239
+ tangent2 = -2.45723
240
+ )
241
+
242
+ interpolated = (22..94).map(&herm.method(:value_at))
243
+
244
+ (22..94).to_a.zip(refdata, interpolated).each do | frame, ref, actual |
245
+ assert_in_delta ref, actual, D, "At #{frame} Interpolated value should be in delta"
246
+ end
247
+ end
248
+ end
249
+
250
+ class TestLinearPrepolate < Test::Unit::TestCase
251
+ def test_fail
252
+ flunk
253
+ end
254
+ end
255
+
256
+ class TestLinearExtrapolate < Test::Unit::TestCase
257
+ def test_fail
258
+ flunk
259
+ end
260
+ end
261
+
metadata ADDED
@@ -0,0 +1,115 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: flame_channel_parser
3
+ version: !ruby/object:Gem::Version
4
+ hash: 17
5
+ prerelease:
6
+ segments:
7
+ - 1
8
+ - 1
9
+ - 1
10
+ version: 1.1.1
11
+ platform: ruby
12
+ authors:
13
+ - Julik Tarkhanov
14
+ autorequire:
15
+ bindir: bin
16
+ cert_chain: []
17
+
18
+ date: 2011-05-17 00:00:00 +02:00
19
+ default_executable:
20
+ dependencies:
21
+ - !ruby/object:Gem::Dependency
22
+ name: hoe
23
+ prerelease: false
24
+ requirement: &id001 !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ">="
28
+ - !ruby/object:Gem::Version
29
+ hash: 41
30
+ segments:
31
+ - 2
32
+ - 9
33
+ - 1
34
+ version: 2.9.1
35
+ type: :development
36
+ version_requirements: *id001
37
+ description: Includes a small library for parsing and baking anmation curves made on Discrodesk Floke/Inflinto, also known as flame.
38
+ email:
39
+ - me@julik.nl
40
+ executables: []
41
+
42
+ extensions: []
43
+
44
+ extra_rdoc_files:
45
+ - History.txt
46
+ - Manifest.txt
47
+ - README.rdoc
48
+ files:
49
+ - .autotest
50
+ - History.txt
51
+ - Manifest.txt
52
+ - README.rdoc
53
+ - Rakefile
54
+ - lib/flame_channel_parser.rb
55
+ - lib/interpolator.rb
56
+ - lib/parser_2011.rb
57
+ - lib/parser_2012.rb
58
+ - lib/segments.rb
59
+ - plots.numbers
60
+ - plots_2012.numbers
61
+ - test/baked.csv
62
+ - test/channel_with_constants.dat
63
+ - test/curve.csv
64
+ - test/sample_channel.dat
65
+ - test/snaps/FLEM_BrokenTangents.action
66
+ - test/snaps/FLEM_advanced_curve.png
67
+ - test/snaps/FLEM_advanced_curve_example_FL2012.action
68
+ - test/snaps/FLEM_baked_curve.png
69
+ - test/snaps/FLEM_curves_example.action
70
+ - test/snaps/FLEM_curves_example_migrated_to_2012.action
71
+ - test/snaps/FLEM_std_curve.png
72
+ - test/snaps/TW.timewarp
73
+ - test/test_flame_channel_parser.rb
74
+ - test/test_interpolator.rb
75
+ - test/test_segments.rb
76
+ - .gemtest
77
+ has_rdoc: true
78
+ homepage: http://guerilla-di.org/flame-channel-parser
79
+ licenses: []
80
+
81
+ post_install_message:
82
+ rdoc_options:
83
+ - --main
84
+ - README.rdoc
85
+ require_paths:
86
+ - lib
87
+ required_ruby_version: !ruby/object:Gem::Requirement
88
+ none: false
89
+ requirements:
90
+ - - ">="
91
+ - !ruby/object:Gem::Version
92
+ hash: 3
93
+ segments:
94
+ - 0
95
+ version: "0"
96
+ required_rubygems_version: !ruby/object:Gem::Requirement
97
+ none: false
98
+ requirements:
99
+ - - ">="
100
+ - !ruby/object:Gem::Version
101
+ hash: 3
102
+ segments:
103
+ - 0
104
+ version: "0"
105
+ requirements: []
106
+
107
+ rubyforge_project: flame_channel_parser
108
+ rubygems_version: 1.4.1
109
+ signing_key:
110
+ specification_version: 3
111
+ summary: Includes a small library for parsing and baking anmation curves made on Discrodesk Floke/Inflinto, also known as flame.
112
+ test_files:
113
+ - test/test_flame_channel_parser.rb
114
+ - test/test_interpolator.rb
115
+ - test/test_segments.rb