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 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