flame_channel_parser 3.0.0 → 4.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (47) hide show
  1. data/.travis.yml +4 -0
  2. data/Gemfile +10 -0
  3. data/History.txt +5 -0
  4. data/README.rdoc +4 -2
  5. data/Rakefile +23 -10
  6. data/bin/{bake_flame_timewarp → framecurve_from_flame} +5 -1
  7. data/bin/framecurve_to_flame +22 -0
  8. data/flame_channel_parser.gemspec +130 -0
  9. data/lib/builder.rb +86 -0
  10. data/lib/flame_channel_parser.rb +31 -4
  11. data/lib/framecurve_writers/base.rb +49 -0
  12. data/lib/framecurve_writers/batch_timewarp.rb +41 -0
  13. data/lib/framecurve_writers/kronos.rb +23 -0
  14. data/lib/framecurve_writers/softfx_timewarp.rb +82 -0
  15. data/lib/framecurve_writers/templates/BatchTW.xml +118 -0
  16. data/lib/framecurve_writers/templates/SampleKronos.F_Kronos +376 -0
  17. data/lib/framecurve_writers/templates/TW_Sample.timewarp +79 -0
  18. data/lib/framecurve_writers/templates/key.xml +10 -0
  19. data/lib/timewarp_extractor.rb +18 -2
  20. data/lib/xml_parser.rb +90 -0
  21. data/test/helper.rb +18 -0
  22. data/test/snaps/BatchTimewar_proper.xml +157 -0
  23. data/test/snaps/BatchTimewarp_ext1.timewarp_node +1 -0
  24. data/test/test_base_timewarp_writer.rb +22 -0
  25. data/test/test_batch_timewarp_writer.rb +18 -0
  26. data/test/test_channel.rb +1 -2
  27. data/test/test_cli.rb +14 -13
  28. data/test/test_cli_framecurve_to_flame.rb +45 -0
  29. data/test/test_cli_timewarp_extractor.rb +19 -9
  30. data/test/test_extractor.rb +1 -3
  31. data/test/test_flame_builder.rb +68 -0
  32. data/test/test_flame_channel_parser.rb +2 -2
  33. data/test/test_interpolator.rb +15 -5
  34. data/test/test_key.rb +2 -2
  35. data/test/test_kronos_timewarp_writer.rb +16 -0
  36. data/test/test_segments.rb +1 -2
  37. data/test/test_softfx_timewarp_writer.rb +16 -0
  38. data/test/test_timewarp_extractor.rb +2 -4
  39. data/test/test_xml_setup.rb +37 -0
  40. data/test/timewarp_examples/TW_16_010_v01.output.txt +430 -428
  41. data/test/timewarp_examples/simple.framecurve.txt +32 -0
  42. data/test/timewarp_export_samples/BatchTW.timewarp_node +145 -0
  43. data/test/timewarp_export_samples/Kronos.F_Kronos +403 -0
  44. data/test/timewarp_export_samples/SoftFX.timewarp +81 -0
  45. metadata +127 -168
  46. data/.gemtest +0 -0
  47. data/Manifest.txt +0 -52
@@ -0,0 +1,4 @@
1
+ rvm:
2
+ - 1.8.7
3
+ - 1.9.2
4
+ - 1.9.3
data/Gemfile ADDED
@@ -0,0 +1,10 @@
1
+ source :rubygems
2
+
3
+ gem "update_hints", "~> 1.0"
4
+ gem "framecurve", "~> 1.0.1"
5
+
6
+ group :development do
7
+ gem "jeweler"
8
+ gem "rake"
9
+ gem "cli_test", "~>1.0"
10
+ end
@@ -1,3 +1,8 @@
1
+ === 4.0.0 / 2011-09-11
2
+
3
+ * Integrate the Framecurve library. Parse TO framecurve as well as FROM to all supported timewarpers
4
+ * Support new XML batch node setups
5
+
1
6
  === 3.0.0 / 2011-09-11
2
7
 
3
8
  * Allow for channels to be passed to a block instead of being collected into an array
@@ -18,9 +18,11 @@ To just bake a specific channel, use the bake_flame_channel binary.
18
18
 
19
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
20
 
21
- If you just need to process a timewarp, use the bake_flame_timewarp which autodetects most of the settings by itself
21
+ If you just need to process a timewarp, use the bake_flame_timewarp which autodetects most of the settings by itself and gives you a nice .framecurve.txt file
22
22
 
23
- $bake_flame_timewarp /usr/discreet/projects/BZO/timewarp/s02_tw.timewarp > /mnt/3d/curves/shot2_tw.framecurve.txt
23
+ $framecurve_from_flame /usr/discreet/projects/BZO/timewarp/s02_tw.timewarp
24
+
25
+ This will create a framecurve file called s02_tw.timewarp.framecurve.txt next to the setup
24
26
 
25
27
  To use the library:
26
28
 
data/Rakefile CHANGED
@@ -1,17 +1,30 @@
1
1
  # -*- ruby -*-
2
2
 
3
3
  require 'rubygems'
4
- require 'hoe'
4
+ require 'jeweler'
5
+ require './lib/flame_channel_parser'
5
6
 
6
- Hoe::RUBY_FLAGS.gsub!(/^\-w/, '') # No thanks undefined ivar warnings
7
- Hoe.spec 'flame_channel_parser' do | p |
8
- p.developer('Julik Tarkhanov', 'me@julik.nl')
9
-
10
- p.readme_file = 'README.rdoc'
11
- p.extra_rdoc_files = FileList['*.rdoc'] + FileList['*.txt']
12
- p.extra_deps = {"update_hints" => ">=0" }
13
- p.extra_dev_deps = {"cli_test" => "~> 1.0.0" }
14
- p.clean_globs = File.read(".gitignore").split("\n")
7
+ Jeweler::Tasks.new do |gem|
8
+ gem.version = FlameChannelParser::VERSION
9
+ gem.name = "flame_channel_parser"
10
+ gem.summary = "A parser/interpolator for Flame/Smoke animation curves"
11
+ gem.description = "Reads and interpolates animation channels in IFFS setups"
12
+ gem.email = "me@julik.nl"
13
+ gem.homepage = "http://guerilla-di.org/flame-channel-parser/"
14
+ gem.authors = ["Julik Tarkhanov"]
15
+ gem.license = 'MIT'
15
16
  end
16
17
 
18
+ Jeweler::RubygemsDotOrgTasks.new
19
+
20
+ require 'rake/testtask'
21
+ desc "Run all tests"
22
+ Rake::TestTask.new("test") do |t|
23
+ t.libs << "test"
24
+ t.pattern = 'test/**/test_*.rb'
25
+ t.verbose = true
26
+ end
27
+
28
+ task :default => [ :test ]
29
+
17
30
  # vim: syntax=ruby
@@ -28,6 +28,10 @@ unless File.exist?(setup_path)
28
28
  exit -1
29
29
  end
30
30
 
31
- FlameChannelParser::TimewarpExtractor.new.extract(setup_path, options)
31
+ # Setup the destination
32
+ destination_path = setup_path.gsub(/\.(\w+)$/, '.framecurve.txt')
33
+ File.open(destination_path, "wb") do | f |
34
+ FlameChannelParser::TimewarpExtractor.new.extract(setup_path, options.merge(:destination => f))
35
+ end
32
36
 
33
37
  UpdateHints.version_check("flame_channel_parser", FlameChannelParser::VERSION, $stderr)
@@ -0,0 +1,22 @@
1
+ #!/usr/bin/env ruby
2
+ require File.expand_path(File.dirname(__FILE__)) + '/../lib/flame_channel_parser'
3
+ require 'optparse'
4
+ require "update_hints"
5
+
6
+ op = OptionParser.new
7
+ op.banner = "Usage: framecurve_to_flame /usr/discreet/projects/ExpensiveDildo/timewarp/shot2_tw.framecurve.txt"
8
+ op.parse!
9
+
10
+ fc_path = ARGV.shift
11
+ fail("No input file path provided.") unless fc_path
12
+ fail("File %s does not exist." % fc_path) unless File.exist?(fc_path)
13
+
14
+ curve = Framecurve::Parser.new.parse(fc_path)
15
+ FlameChannelParser::FramecurveWriters::Base.with_each_writer do | writer_class |
16
+ filename = [fc_path, writer_class.extension].join
17
+ File.open(filename, "wb") do | f |
18
+ writer_class.new.run_export_from_framecurve(f, curve)
19
+ end
20
+ end
21
+
22
+ UpdateHints.version_check("flame_channel_parser", FlameChannelParser::VERSION, $stderr)
@@ -0,0 +1,130 @@
1
+ # Generated by jeweler
2
+ # DO NOT EDIT THIS FILE DIRECTLY
3
+ # Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
4
+ # -*- encoding: utf-8 -*-
5
+
6
+ Gem::Specification.new do |s|
7
+ s.name = "flame_channel_parser"
8
+ s.version = "4.0.0"
9
+
10
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
+ s.authors = ["Julik Tarkhanov"]
12
+ s.date = "2011-12-30"
13
+ s.description = "Reads and interpolates animation channels in IFFS setups"
14
+ s.email = "me@julik.nl"
15
+ s.executables = ["bake_flame_channel", "framecurve_from_flame", "framecurve_to_flame"]
16
+ s.extra_rdoc_files = [
17
+ "README.rdoc"
18
+ ]
19
+ s.files = [
20
+ ".autotest",
21
+ ".travis.yml",
22
+ "Gemfile",
23
+ "History.txt",
24
+ "README.rdoc",
25
+ "Rakefile",
26
+ "bin/bake_flame_channel",
27
+ "bin/framecurve_from_flame",
28
+ "bin/framecurve_to_flame",
29
+ "flame_channel_parser.gemspec",
30
+ "lib/builder.rb",
31
+ "lib/channel.rb",
32
+ "lib/extractor.rb",
33
+ "lib/flame_channel_parser.rb",
34
+ "lib/framecurve_writers/base.rb",
35
+ "lib/framecurve_writers/batch_timewarp.rb",
36
+ "lib/framecurve_writers/kronos.rb",
37
+ "lib/framecurve_writers/softfx_timewarp.rb",
38
+ "lib/framecurve_writers/templates/BatchTW.xml",
39
+ "lib/framecurve_writers/templates/SampleKronos.F_Kronos",
40
+ "lib/framecurve_writers/templates/TW_Sample.timewarp",
41
+ "lib/framecurve_writers/templates/key.xml",
42
+ "lib/interpolator.rb",
43
+ "lib/key.rb",
44
+ "lib/parser.rb",
45
+ "lib/segments.rb",
46
+ "lib/timewarp_extractor.rb",
47
+ "lib/xml_parser.rb",
48
+ "test/channel_with_constants.dat",
49
+ "test/helper.rb",
50
+ "test/sample_channel.dat",
51
+ "test/snaps/BatchTimewar_proper.xml",
52
+ "test/snaps/BatchTimewarp_ext1.timewarp_node",
53
+ "test/snaps/Cycle_and_revcycle.action",
54
+ "test/snaps/FLEM_BrokenTangents.action",
55
+ "test/snaps/FLEM_advanced_curve.png",
56
+ "test/snaps/FLEM_advanced_curve_example_FL2012.action",
57
+ "test/snaps/FLEM_baked_curve.png",
58
+ "test/snaps/FLEM_curves_example.action",
59
+ "test/snaps/FLEM_curves_example_migrated_to_2012.action",
60
+ "test/snaps/FLEM_std_curve.png",
61
+ "test/snaps/RefT_Steadicam.timewarp",
62
+ "test/snaps/RefT_Steadicam_Baked.timewarp",
63
+ "test/snaps/RefT_Steadicam_Extraction.txt",
64
+ "test/snaps/RefT_Steadicam_Extraction_F19_to_347.txt",
65
+ "test/snaps/RefT_Steadicam_TwoKFs.timewarp",
66
+ "test/snaps/RefT_Steadicam_TwoKFs_AnotherSlope.timewarp",
67
+ "test/snaps/RefT_Steadicam_TwoKFs_HermiteAtBegin.timewarp",
68
+ "test/snaps/TW.timewarp",
69
+ "test/snaps/TW_015_010_v03.timewarp",
70
+ "test/snaps/TW_SingleFrameExtrapolated_from2011.timewarp",
71
+ "test/snaps/TW_TEST.F_Kronos",
72
+ "test/snaps/timewarp_where_interp_fails_at_end.timewarp",
73
+ "test/test_base_timewarp_writer.rb",
74
+ "test/test_batch_timewarp_writer.rb",
75
+ "test/test_channel.rb",
76
+ "test/test_cli.rb",
77
+ "test/test_cli_framecurve_to_flame.rb",
78
+ "test/test_cli_timewarp_extractor.rb",
79
+ "test/test_extractor.rb",
80
+ "test/test_flame_builder.rb",
81
+ "test/test_flame_channel_parser.rb",
82
+ "test/test_interpolator.rb",
83
+ "test/test_key.rb",
84
+ "test/test_kronos_timewarp_writer.rb",
85
+ "test/test_segments.rb",
86
+ "test/test_softfx_timewarp_writer.rb",
87
+ "test/test_timewarp_extractor.rb",
88
+ "test/test_xml_setup.rb",
89
+ "test/timewarp_examples/TW_015_010_v01_Baked.timewarp",
90
+ "test/timewarp_examples/TW_016_010_v01.timewarp",
91
+ "test/timewarp_examples/TW_016_010_v01_Baked.timewarp",
92
+ "test/timewarp_examples/TW_16_010_v01.output.txt",
93
+ "test/timewarp_examples/TW_TEST.F_Kronos",
94
+ "test/timewarp_examples/output.txt",
95
+ "test/timewarp_examples/simple.framecurve.txt",
96
+ "test/timewarp_export_samples/BatchTW.timewarp_node",
97
+ "test/timewarp_export_samples/Kronos.F_Kronos",
98
+ "test/timewarp_export_samples/SoftFX.timewarp"
99
+ ]
100
+ s.homepage = "http://guerilla-di.org/flame-channel-parser/"
101
+ s.licenses = ["MIT"]
102
+ s.require_paths = ["lib"]
103
+ s.rubygems_version = "1.8.11"
104
+ s.summary = "A parser/interpolator for Flame/Smoke animation curves"
105
+
106
+ if s.respond_to? :specification_version then
107
+ s.specification_version = 3
108
+
109
+ if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
110
+ s.add_runtime_dependency(%q<update_hints>, ["~> 1.0"])
111
+ s.add_runtime_dependency(%q<framecurve>, ["~> 1.0.1"])
112
+ s.add_development_dependency(%q<jeweler>, [">= 0"])
113
+ s.add_development_dependency(%q<rake>, [">= 0"])
114
+ s.add_development_dependency(%q<cli_test>, ["~> 1.0"])
115
+ else
116
+ s.add_dependency(%q<update_hints>, ["~> 1.0"])
117
+ s.add_dependency(%q<framecurve>, ["~> 1.0.1"])
118
+ s.add_dependency(%q<jeweler>, [">= 0"])
119
+ s.add_dependency(%q<rake>, [">= 0"])
120
+ s.add_dependency(%q<cli_test>, ["~> 1.0"])
121
+ end
122
+ else
123
+ s.add_dependency(%q<update_hints>, ["~> 1.0"])
124
+ s.add_dependency(%q<framecurve>, ["~> 1.0.1"])
125
+ s.add_dependency(%q<jeweler>, [">= 0"])
126
+ s.add_dependency(%q<rake>, [">= 0"])
127
+ s.add_dependency(%q<cli_test>, ["~> 1.0"])
128
+ end
129
+ end
130
+
@@ -0,0 +1,86 @@
1
+ # A Builder-like class for exporting Flame setups
2
+ class FlameChannelParser::Builder #< BasicObject
3
+ INDENT = "\t"
4
+
5
+ def initialize(io, indent = 0)
6
+ @io, @indent = io, indent
7
+ end
8
+
9
+ # Writes a block of values delimited by "End" terminators.
10
+ # Will yield a nested Builder objectg which
11
+ def write_block!(name, value = nil, &blk)
12
+ value.nil? ? write_loose!(name) : write_tuple!(name, value)
13
+ yield(self.class.new(@io, @indent + 1))
14
+ @io.puts(INDENT * (@indent + 1) + "End")
15
+ end
16
+
17
+ # Write an unterminated block of values
18
+ def write_unterminated_block!(name, value = nil, &blk)
19
+ value.nil? ? write_loose!(name) : write_tuple!(name, value)
20
+ yield(self.class.new(@io, @indent + 1))
21
+ end
22
+
23
+ # Write a tuple of "Parameter Value", like "Frame 13"
24
+ def write_tuple!(key, value)
25
+ @io.puts("%s%s %s" % [INDENT * @indent, __camelize(key), __flameize(value)])
26
+ end
27
+
28
+ # Write a number of linebreaks
29
+ def write_loose!(value)
30
+ @io.puts("%s%s" % [INDENT * @indent, __camelize(value)])
31
+ end
32
+
33
+ # Write a number of linebreaks
34
+ def linebreak!(how_many = 1)
35
+ @io.write("\n" * how_many)
36
+ end
37
+
38
+ # Write a color hash with the right order of values
39
+ def color_hash!(name, red, green, blue)
40
+ write_unterminated_block!(name) do | b |
41
+ b.red(red)
42
+ b.green(green)
43
+ b.blue(blue)
44
+ end
45
+ end
46
+
47
+ # Append the text passed to the setup. The appended
48
+ # lines will be prepended by the indent of the current builder
49
+ def <<(some_verbatim_string)
50
+ some_verbatim_string.split("\n").each do | line |
51
+ @io.puts(["\t" * @indent, line].join)
52
+ end
53
+ end
54
+
55
+ private
56
+
57
+ def method_missing(meth, arg = nil)
58
+ if block_given?
59
+ write_block!(meth, arg) {|c| yield(c) }
60
+ else
61
+ if arg.nil?
62
+ write_loose!(meth)
63
+ else
64
+ write_tuple!(meth, arg)
65
+ end
66
+ end
67
+ end
68
+
69
+ def __camelize(s)
70
+ @@camelizations ||= {}
71
+ @@camelizations[s] ||= s.to_s.gsub(/(^|_)(.)/) { $2.upcase }
72
+ end
73
+
74
+ def __flameize(v)
75
+ case v
76
+ when Float
77
+ "%.3f" % v
78
+ when TrueClass
79
+ "yes"
80
+ when FalseClass
81
+ "no"
82
+ else
83
+ v.to_s
84
+ end
85
+ end
86
+ end
@@ -1,18 +1,45 @@
1
1
  module FlameChannelParser
2
- VERSION = '3.0.0'
2
+ VERSION = '4.0.0'
3
+
4
+ module FramecurveWriters; end
3
5
 
4
6
  # Parse a Flame setup into an array of Channel objects.
5
7
  # If a block is given to the method it will yield Channel
6
8
  # objects one by one instead of accumulating them into an array (useful for big setups)
7
9
  def self.parse(io)
10
+ c = get_parser_class(io)
8
11
  if block_given?
9
- Parser.new.parse(io, &Proc.new)
12
+ c.new.parse(io, &Proc.new)
10
13
  else
11
- Parser.new.parse(io)
14
+ c.new.parse(io)
12
15
  end
13
16
  end
17
+
18
+ # Parse a Flame setup at passed path. Will return the channels instead of yielding them
19
+ def self.parse_file_at(path)
20
+ File.open(path, &method(:parse))
21
+ end
22
+
23
+ private
24
+
25
+ # Returns the XML parser class for XML setups
26
+ def self.get_parser_class(for_io)
27
+ tokens = %w( <Setup> <?xml )
28
+ current = for_io.pos
29
+ tokens.each do | token |
30
+ for_io.rewind
31
+ return XMLParser if for_io.read(token.size) == token
32
+ end
33
+ return Parser
34
+ ensure
35
+ for_io.seek(current)
36
+ end
14
37
  end
15
38
 
16
39
  %w(
17
- key channel parser segments interpolator extractor timewarp_extractor
40
+ key channel parser segments interpolator extractor timewarp_extractor builder xml_parser
18
41
  ).each {|f| require File.expand_path(File.dirname(__FILE__) + "/" + f ) }
42
+
43
+ %w(
44
+ base softfx_timewarp batch_timewarp kronos
45
+ ).each {|f| require File.expand_path(File.dirname(__FILE__) + "/framecurve_writers/" + f ) }
@@ -0,0 +1,49 @@
1
+ # Writes out a framecurve setup
2
+ class FlameChannelParser::FramecurveWriters::Base
3
+ class KeyWriter
4
+ attr_reader :keys
5
+ def initialize
6
+ @keys = []
7
+ end
8
+
9
+ def key(at, value)
10
+ @keys.push([at.to_i,value.to_f])
11
+ end
12
+
13
+ end
14
+
15
+ def self.inherited(by)
16
+ @@writers ||= []
17
+ @@writers.push(by)
18
+ end
19
+
20
+ # Yields each defined writer class to the block
21
+ def self.with_each_writer
22
+ @@writers.each(&Proc.new)
23
+ end
24
+
25
+ # Should return the desired extension for the exported file
26
+ def self.extension
27
+ '.timewarp'
28
+ end
29
+
30
+ # Run the exporter writing the result to the passed IO. Will yield a KeyWriter
31
+ # to the caller for writing frames (call key(at, value) on it)
32
+ def run_export(io)
33
+ w = KeyWriter.new
34
+ yield(w)
35
+ w.keys.each do | at, value |
36
+ io.puts("%d %.5f" % [at, value])
37
+ end
38
+ end
39
+
40
+ # Run the exporter writing the result to it, and pulling framecurve frames from the passed Curve
41
+ # object
42
+ def run_export_from_framecurve(io, curve)
43
+ run_export(io) do | writer |
44
+ curve.to_materialized_curve.each_tuple do | t |
45
+ writer.key(t.at, t.value)
46
+ end
47
+ end
48
+ end
49
+ end
@@ -0,0 +1,41 @@
1
+ # Writes out a Batch timewarp node setup
2
+ class FlameChannelParser::FramecurveWriters::BatchTimewarp < FlameChannelParser::FramecurveWriters::SoftfxTimewarp
3
+
4
+ TEMPLATE = File.dirname(__FILE__) + "/templates/BatchTW.xml"
5
+ TEMPLATE_KEY = File.dirname(__FILE__) + "/templates/key.xml"
6
+
7
+ def self.extension
8
+ '.timewarp_node'
9
+ end
10
+
11
+ def run_export(io)
12
+ w = KeyWriter.new
13
+ yield(w)
14
+ keys = w.keys
15
+
16
+ keys_data = ''
17
+ keys.each_with_index do | k, idx |
18
+ keys_data << templatize(TEMPLATE_KEY, :frame => k[0].to_i, :value => k[1].to_f, :idx => idx)
19
+ end
20
+
21
+ # Whole range BOTH in the source and destination
22
+ used_frames = (keys.map{|k| k[1]} + keys.map{|k| k[0]}).sort
23
+ first_frame, last_frame = used_frames[0], used_frames[-1]
24
+
25
+ info = {:start_frame => first_frame, :last_frame => last_frame, :first_value => keys[0][1], :key_size => keys.size, :keys => keys_data }
26
+ io.write(templatize(TEMPLATE, info))
27
+ end
28
+
29
+ private
30
+ def templatize(file, hash)
31
+ t = File.read(file)
32
+ hash.each_pair do | pattern, value |
33
+ p = Regexp.escape('$%s' % pattern)
34
+ handle = Regexp.new(p, [Regexp::MULTILINE, Regexp::EXTENDED])
35
+ t.gsub!(handle, value.to_s)
36
+ end
37
+ raise "Not all substitutions done" if t.include?('$')
38
+
39
+ return t
40
+ end
41
+ end