flame_channel_parser 1.3.0 → 1.3.1

Sign up to get free protection for your applications and to get access to all the features.
data/History.txt CHANGED
@@ -1,3 +1,7 @@
1
+ === 1.3.1 / 2011-05-30
2
+
3
+ * Add minor fixes and imporvements to the curve extraction bin
4
+
1
5
  === 1.3.0 / 2011-05-20
2
6
 
3
7
  * Added the Extractor class that does simple per-frame baking to STDOUT
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
- Currently there is no application that you can use directly, the parser is now a library that you can use in your own scripts
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
@@ -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\n" +
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
- DEFAULTS = {:destination => $stdout, :start_frame => nil, :end_frame => nil, :channel => "Timing/Timing" }
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
- end
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.name }
18
+ selected_channel = channels.find{|c| options[:channel] == c.path }
16
19
  unless selected_channel
17
- message = "Channel not #{options[:channel]}found in this setup (set the channel with the --channel option). Found other channels though:"
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.name }.join("\n")
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)])
@@ -1,7 +1,7 @@
1
1
  require "delegate"
2
2
 
3
3
  module FlameChannelParser
4
- VERSION = '1.3.0'
4
+ VERSION = '1.3.1'
5
5
 
6
6
  # Parse a Flame setup into an array of ChannelBlock objects
7
7
  def self.parse(io)
data/lib/segments.rb CHANGED
@@ -1,6 +1,8 @@
1
1
  require "matrix"
2
2
 
3
- module FlameChannelParser::Segments
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 = Point.new(x1, y1, t1x, t1y)
102
- @b = Point.new(x2, y2, t2x, t2y)
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:
@@ -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 test_basic_op
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: 27
4
+ hash: 25
5
5
  prerelease:
6
6
  segments:
7
7
  - 1
8
8
  - 3
9
- - 0
10
- version: 1.3.0
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-05-25 00:00:00 +02:00
18
+ date: 2011-06-03 00:00:00 +02:00
19
19
  default_executable:
20
20
  dependencies:
21
21
  - !ruby/object:Gem::Dependency