flame_channel_parser 3.0.0 → 4.0.0
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/.travis.yml +4 -0
- data/Gemfile +10 -0
- data/History.txt +5 -0
- data/README.rdoc +4 -2
- data/Rakefile +23 -10
- data/bin/{bake_flame_timewarp → framecurve_from_flame} +5 -1
- data/bin/framecurve_to_flame +22 -0
- data/flame_channel_parser.gemspec +130 -0
- data/lib/builder.rb +86 -0
- data/lib/flame_channel_parser.rb +31 -4
- data/lib/framecurve_writers/base.rb +49 -0
- data/lib/framecurve_writers/batch_timewarp.rb +41 -0
- data/lib/framecurve_writers/kronos.rb +23 -0
- data/lib/framecurve_writers/softfx_timewarp.rb +82 -0
- data/lib/framecurve_writers/templates/BatchTW.xml +118 -0
- data/lib/framecurve_writers/templates/SampleKronos.F_Kronos +376 -0
- data/lib/framecurve_writers/templates/TW_Sample.timewarp +79 -0
- data/lib/framecurve_writers/templates/key.xml +10 -0
- data/lib/timewarp_extractor.rb +18 -2
- data/lib/xml_parser.rb +90 -0
- data/test/helper.rb +18 -0
- data/test/snaps/BatchTimewar_proper.xml +157 -0
- data/test/snaps/BatchTimewarp_ext1.timewarp_node +1 -0
- data/test/test_base_timewarp_writer.rb +22 -0
- data/test/test_batch_timewarp_writer.rb +18 -0
- data/test/test_channel.rb +1 -2
- data/test/test_cli.rb +14 -13
- data/test/test_cli_framecurve_to_flame.rb +45 -0
- data/test/test_cli_timewarp_extractor.rb +19 -9
- data/test/test_extractor.rb +1 -3
- data/test/test_flame_builder.rb +68 -0
- data/test/test_flame_channel_parser.rb +2 -2
- data/test/test_interpolator.rb +15 -5
- data/test/test_key.rb +2 -2
- data/test/test_kronos_timewarp_writer.rb +16 -0
- data/test/test_segments.rb +1 -2
- data/test/test_softfx_timewarp_writer.rb +16 -0
- data/test/test_timewarp_extractor.rb +2 -4
- data/test/test_xml_setup.rb +37 -0
- data/test/timewarp_examples/TW_16_010_v01.output.txt +430 -428
- data/test/timewarp_examples/simple.framecurve.txt +32 -0
- data/test/timewarp_export_samples/BatchTW.timewarp_node +145 -0
- data/test/timewarp_export_samples/Kronos.F_Kronos +403 -0
- data/test/timewarp_export_samples/SoftFX.timewarp +81 -0
- metadata +127 -168
- data/.gemtest +0 -0
- data/Manifest.txt +0 -52
data/.travis.yml
ADDED
data/Gemfile
ADDED
data/History.txt
CHANGED
@@ -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
|
data/README.rdoc
CHANGED
@@ -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
|
-
$
|
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 '
|
4
|
+
require 'jeweler'
|
5
|
+
require './lib/flame_channel_parser'
|
5
6
|
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
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
|
-
|
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
|
+
|
data/lib/builder.rb
ADDED
@@ -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
|
data/lib/flame_channel_parser.rb
CHANGED
@@ -1,18 +1,45 @@
|
|
1
1
|
module FlameChannelParser
|
2
|
-
VERSION = '
|
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
|
-
|
12
|
+
c.new.parse(io, &Proc.new)
|
10
13
|
else
|
11
|
-
|
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
|