flame_channel_parser 1.3.0 → 1.3.1
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 +4 -0
- data/README.rdoc +7 -1
- data/bin/bake_flame_channel +5 -5
- data/lib/extractor.rb +13 -6
- data/lib/flame_channel_parser.rb +1 -1
- data/lib/segments.rb +8 -5
- data/test/test_extractor.rb +24 -2
- metadata +4 -4
data/History.txt
CHANGED
data/README.rdoc
CHANGED
@@ -14,9 +14,15 @@ Thanks to Marijn Eken, Philippe Soeiro and Andre Gagnon for their support and ad
|
|
14
14
|
|
15
15
|
== SYNOPSIS:
|
16
16
|
|
17
|
-
|
17
|
+
To just bake a specific channel, use the bake_flame_channel binary.
|
18
|
+
|
19
|
+
$ bake_flame_channel --channel \"Timing/Timing\" -e 123 /usr/discreet/projects/BZO/timewarp/s02_tw.timewarp > /mnt/3d/curves/shot2_tw.framecurve.txt
|
20
|
+
|
21
|
+
To use the library:
|
18
22
|
|
19
23
|
require "flame_channel_parser"
|
24
|
+
|
25
|
+
# Parse the setup into channels
|
20
26
|
channels = File.open("TW_Setup.timewarp") do | f |
|
21
27
|
FlameChannelParser.parse(f)
|
22
28
|
end
|
data/bin/bake_flame_channel
CHANGED
@@ -6,16 +6,16 @@ options = {}
|
|
6
6
|
|
7
7
|
op = OptionParser.new
|
8
8
|
op.banner = "Usage: bake_flame_channel --channel \"Timing/Timing\" -e 123 /usr/discreet/projects/Luxury/timewarp/shot2_tw.timewarp > /mnt/3d/curves/shot2_tw.framecurve.txt\n" +
|
9
|
-
"The output file can be used as Time+Value ASCII input for Nuke
|
9
|
+
"The output file can be used as Time+Value ASCII input for Nuke " +
|
10
10
|
"or parsed with any simple script"
|
11
11
|
op.on(" -c", "--channel CHANNEL_NAME", String,
|
12
|
-
"Select the channel to bake (for example in Timewarp setups the useful one is Timing/Timing)"
|
12
|
+
"Select the channel to bake (for example in Timewarp setups the useful one is Timing/Timing)."
|
13
13
|
) {|chan| options[:channel] = chan }
|
14
14
|
op.on(" -s", "--startframe FRAME", Integer,
|
15
|
-
"Bake the curve from this specific frame onwards (defaults to the first keyframe in the setup"
|
15
|
+
"Bake the curve from this specific frame onwards (defaults to the first keyframe in the setup)"
|
16
16
|
) {|from| options[:start_frame] = from }
|
17
17
|
op.on(" -e", "--endframe FRAME", Integer,
|
18
|
-
"Bake the curve upto this specific frame (defaults to the last keyframe in the setup"
|
18
|
+
"Bake the curve upto this specific frame (defaults to the last keyframe in the setup)"
|
19
19
|
) {|upto| options[:end_frame] = upto }
|
20
20
|
op.on(" -f", "--to-file FILENAME", String,
|
21
21
|
"Write the curve to a file at this path instead of printing it to STDOUT"
|
@@ -23,7 +23,7 @@ op.on(" -f", "--to-file FILENAME", String,
|
|
23
23
|
|
24
24
|
op.parse!
|
25
25
|
setup_path = ARGV.shift
|
26
|
-
raise "No input file path provided" unless setup_path
|
26
|
+
raise "No input file path provided. Please see bake_flame_channel --help for usage information" unless setup_path
|
27
27
|
|
28
28
|
FlameChannelParser::Extractor.new.extract(setup_path, options)
|
29
29
|
options[:destination].close if options[:destination].respond_to?(:close)
|
data/lib/extractor.rb
CHANGED
@@ -1,22 +1,25 @@
|
|
1
1
|
# Extracts and bakes a specific animation channel
|
2
2
|
class FlameChannelParser::Extractor
|
3
3
|
|
4
|
-
|
4
|
+
DEFAULT_CHANNEL_TO_EXTRACT = "Timing/Timing"
|
5
|
+
DEFAULTS = {:destination => $stdout, :start_frame => nil, :end_frame => nil, :channel => DEFAULT_CHANNEL_TO_EXTRACT }
|
5
6
|
|
6
7
|
# Raised when a channel is not found in the setup file
|
7
|
-
class ChannelNotFoundError < RuntimeError
|
8
|
-
|
8
|
+
class ChannelNotFoundError < RuntimeError; end
|
9
|
+
|
10
|
+
# Raised when you try to autodetect the length of a channel that has no keyframes
|
11
|
+
class NoKeyframesError < RuntimeError; end
|
9
12
|
|
10
13
|
# Pass the path to Flame setup here and you will get the timewarp curve on STDOUT
|
11
14
|
def self.extract(path, options = {})
|
12
15
|
options = DEFAULTS.merge(options)
|
13
16
|
File.open(path) do | f |
|
14
17
|
channels = FlameChannelParser.parse(f)
|
15
|
-
selected_channel = channels.find{|c| options[:channel] == c.
|
18
|
+
selected_channel = channels.find{|c| options[:channel] == c.path }
|
16
19
|
unless selected_channel
|
17
|
-
message = "Channel
|
20
|
+
message = "Channel #{options[:channel]} not found in this setup (set the channel with the --channel option). Found other channels though:"
|
18
21
|
message << "\n"
|
19
|
-
message += channels.map{|c| c.
|
22
|
+
message += channels.map{|c| "\t%s\n" % c.path }.join
|
20
23
|
raise ChannelNotFoundError, message
|
21
24
|
end
|
22
25
|
|
@@ -31,6 +34,10 @@ class FlameChannelParser::Extractor
|
|
31
34
|
|
32
35
|
from_frame = start_frame || interpolator.first_defined_frame
|
33
36
|
to_frame = end_frame || interpolator.last_defined_frame
|
37
|
+
unless (from_frame && to_frame)
|
38
|
+
raise NoKeyframesError, "This channel probably has no animation so there is no way to automatically tell how many keyframes it has. " +
|
39
|
+
"Please set the start and end frame explicitly."
|
40
|
+
end
|
34
41
|
|
35
42
|
(from_frame..to_frame).each do | frame |
|
36
43
|
to_io.puts("%d\t%.5f" % [frame, interpolator.sample_at(frame)])
|
data/lib/flame_channel_parser.rb
CHANGED
data/lib/segments.rb
CHANGED
@@ -1,6 +1,8 @@
|
|
1
1
|
require "matrix"
|
2
2
|
|
3
|
-
|
3
|
+
|
4
|
+
# :nodoc:
|
5
|
+
module FlameChannelParser::Segments
|
4
6
|
|
5
7
|
# This segment just stays on the value of it's keyframe
|
6
8
|
class ConstantSegment
|
@@ -92,14 +94,14 @@ module FlameChannelParser::Segments
|
|
92
94
|
|
93
95
|
end
|
94
96
|
|
95
|
-
Point = Struct.new(:x, :y, :tanx, :tany)
|
96
|
-
|
97
97
|
class BezierSegment < LinearSegment
|
98
|
+
Pt = Struct.new(:x, :y, :tanx, :tany)
|
99
|
+
|
98
100
|
def initialize(x1, x2, y1, y2, t1x, t1y, t2x, t2y)
|
99
101
|
@start_frame, @end_frame = x1, x2
|
100
102
|
|
101
|
-
@a =
|
102
|
-
@b =
|
103
|
+
@a = Pt.new(x1, y1, t1x, t1y)
|
104
|
+
@b = Pt.new(x2, y2, t2x, t2y)
|
103
105
|
end
|
104
106
|
|
105
107
|
def value_at(frame)
|
@@ -254,3 +256,4 @@ module FlameChannelParser::Segments
|
|
254
256
|
end
|
255
257
|
end
|
256
258
|
|
259
|
+
# :nodoc:
|
data/test/test_extractor.rb
CHANGED
@@ -4,23 +4,45 @@ require "stringio"
|
|
4
4
|
require File.dirname(__FILE__) + "/../lib/flame_channel_parser"
|
5
5
|
|
6
6
|
class TestExtractor < Test::Unit::TestCase
|
7
|
-
def
|
7
|
+
def test_basic_operation
|
8
8
|
io = StringIO.new
|
9
9
|
FlameChannelParser::Extractor.extract(File.dirname(__FILE__) + "/snaps/RefT_Steadicam.timewarp", :destination => io)
|
10
10
|
assert_equal File.read(File.dirname(__FILE__) + "/snaps/RefT_Steadicam_Extraction.txt"), io.string
|
11
11
|
end
|
12
12
|
|
13
|
+
def test_channel_selection_by_path_raises_with_not_animated_channel_and_no_start_and_end
|
14
|
+
io = StringIO.new
|
15
|
+
ops = {:destination => io, :channel => "axis1/position/z"}
|
16
|
+
assert_raise(FlameChannelParser::Extractor::NoKeyframesError) do
|
17
|
+
FlameChannelParser::Extractor.extract(File.dirname(__FILE__) + "/snaps/FLEM_curves_example_migrated_to_2012.action", ops)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
def test_channel_selection_by_path_outputs_properly
|
22
|
+
io = StringIO.new
|
23
|
+
ops = {:destination => io, :channel => "axis1/position/y"}
|
24
|
+
FlameChannelParser::Extractor.extract(File.dirname(__FILE__) + "/snaps/FLEM_curves_example_migrated_to_2012.action", ops)
|
25
|
+
assert_match /12 -101.80433/, io.string
|
26
|
+
end
|
27
|
+
|
28
|
+
|
13
29
|
def test_frame_overrides
|
14
30
|
io = StringIO.new
|
15
31
|
o = {:destination => io, :start_frame => 19, :end_frame => 347 }
|
16
32
|
FlameChannelParser::Extractor.extract(File.dirname(__FILE__) + "/snaps/RefT_Steadicam.timewarp", o)
|
17
|
-
|
18
33
|
assert_equal File.read(File.dirname(__FILE__) + "/snaps/RefT_Steadicam_Extraction_F19_to_347.txt"), io.string
|
19
34
|
end
|
20
35
|
|
36
|
+
def test_constant_channels_need_domain_of_definition_on_time
|
37
|
+
assert_raise(FlameChannelParser::Extractor::NoKeyframesError) do
|
38
|
+
FlameChannelParser::Extractor.extract(File.dirname(__FILE__) + "/snaps/RefT_Steadicam.timewarp", :channel => "Mix/Mix")
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
21
42
|
def test_raises_on_Missing_channel
|
22
43
|
assert_raise(FlameChannelParser::Extractor::ChannelNotFoundError) do
|
23
44
|
FlameChannelParser::Extractor.extract(File.dirname(__FILE__) + "/snaps/RefT_Steadicam.timewarp", :channel => "foo/bar")
|
24
45
|
end
|
25
46
|
end
|
47
|
+
|
26
48
|
end
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: flame_channel_parser
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 25
|
5
5
|
prerelease:
|
6
6
|
segments:
|
7
7
|
- 1
|
8
8
|
- 3
|
9
|
-
-
|
10
|
-
version: 1.3.
|
9
|
+
- 1
|
10
|
+
version: 1.3.1
|
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-
|
18
|
+
date: 2011-06-03 00:00:00 +02:00
|
19
19
|
default_executable:
|
20
20
|
dependencies:
|
21
21
|
- !ruby/object:Gem::Dependency
|