flame_channel_parser 4.0.2 → 4.1.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +14 -0
- data/.travis.yml +6 -1
- data/Gemfile +2 -9
- data/History.txt +4 -0
- data/{README.rdoc → README.md} +33 -14
- data/Rakefile +3 -21
- data/bin/bake_flame_channel +1 -1
- data/bin/flame_channel_inspect +26 -0
- data/flame_channel_parser.gemspec +11 -113
- data/lib/flame_channel_parser.rb +3 -2
- data/lib/flame_channel_parser/version.rb +3 -0
- data/lib/inspector.rb +74 -0
- data/lib/xml_parser.rb +11 -12
- data/test/stabilizer_examples/2014_cornerpin_points.stabilizer +16835 -0
- data/test/test_flame_channel_parser.rb +0 -1
- data/test/test_inspector.rb +39 -0
- data/test/test_inspector_ref_output_stabilizer.txt +76 -0
- data/test/test_inspector_ref_output_timewarp.txt +10 -0
- data/test/test_interpolator.rb +11 -3
- metadata +59 -38
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 63ea2d0b36c71708aed053a7e899fe45a90144f09a76a539bfde0fa75cebdbba
|
4
|
+
data.tar.gz: a28e90fce5c379defb431679b1593f5e9b1a02e1a69ac492b8312066bc1eb86e
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 7b6359fb57c03a67a048c2679efddff22d1ced66ec00bc93a34fc8a0965a17eb0af749baa3b66423542775e6442d1cf61d509f784c69b8ea46303acbea9cbb95
|
7
|
+
data.tar.gz: caf1e909f3f2f8078218c230e6fc3f882fc2df70fb64b0f8f3e9ce8550314b67b12c401e68c4da541547af01b29e1b56aaef90e260c00f9397474554f42ccfc6
|
data/.gitignore
ADDED
data/.travis.yml
CHANGED
data/Gemfile
CHANGED
data/History.txt
CHANGED
data/{README.rdoc → README.md}
RENAMED
@@ -1,29 +1,48 @@
|
|
1
|
-
|
1
|
+
# flame_channel_parser
|
2
2
|
|
3
|
-
|
3
|
+
[![Build Status](https://travis-ci.org/guerilla-di/flame_channel_parser.svg?branch=master)](https://travis-ci.org/guerilla-di/flame_channel_parser)
|
4
4
|
|
5
|
-
|
5
|
+
Flame is a compositing powerhouse, and it's animation tools are extremely good for quickly prototyping things in front of clients. However, once you want to pull your
|
6
|
+
animation into other packages it can get troublesome, since only Action nodes currently support any kind of export (and it's FBX, and it's only partial).
|
7
|
+
`flame_channel_parser` alleviates the problem - it can load **any** Flame setup file (an `.action` file, or a `.stabilizer` file, or any file created by one of your
|
8
|
+
Sparks - like Kronos timewarps for examople) and extract arbitrary animation curves as tables of frames and values.
|
6
9
|
|
7
|
-
|
10
|
+
This gem includes a small library for extracting, parsing and baking animation curves made on Discrodesk Floke/Inflinto, also known as flame.
|
8
11
|
Thanks to Marijn Eken, Philippe Soeiro and Andre Gagnon for their support and advice.
|
9
12
|
|
10
|
-
|
13
|
+
## Features:
|
11
14
|
|
12
15
|
* All extrapolation and interpolation methods are supported (yes two keyframes with tangents across 2000 frames will do!)
|
13
16
|
* Expressions on channels won't be evaluated (obviously!)
|
14
17
|
|
15
|
-
|
18
|
+
## Synopsis
|
19
|
+
|
20
|
+
To examing what channels your setup contains, use the flame_channel_inspect_binary
|
21
|
+
|
22
|
+
$flame_channel_inspect /usr/discreet/projects/BZO/timewarp/s02_tw.timewarp
|
16
23
|
|
17
24
|
To just bake a specific channel, use the bake_flame_channel binary.
|
18
25
|
|
19
26
|
$bake_flame_channel --channel Timing/Timing -e 123 /usr/discreet/projects/BZO/timewarp/s02_tw.timewarp > /mnt/3d/curves/shot2_tw.framecurve.txt
|
20
27
|
|
21
|
-
If you just need to
|
28
|
+
If you just need to extract a framecurve file (http://framecurve.org) from a timewarp, use the framecurve_from_flame which autodetects most of the settings by itself and gives you a nice .framecurve.txt file
|
22
29
|
|
23
30
|
$framecurve_from_flame /usr/discreet/projects/BZO/timewarp/s02_tw.timewarp
|
24
|
-
|
31
|
+
|
25
32
|
This will create a framecurve file called s02_tw.timewarp.framecurve.txt next to the setup
|
26
33
|
|
34
|
+
The reverse is true for framecurve_to_flame
|
35
|
+
|
36
|
+
$framecurve_from_flame /usr/discreet/projects/BZO/timewarp/s02_tw.framecurve.txt
|
37
|
+
|
38
|
+
will create setup files for use with both Timewarp modules and the Kronos spark.
|
39
|
+
|
40
|
+
The bonuses are of course in the details - **flame_channel_parser** is a meticulous
|
41
|
+
bitch and will faithfully replicate all the tricky things you can do to your animation curves to give them more _oomph_ - like broken tangents, two keyframes on
|
42
|
+
500 frames with wild oscillations, looping and linear extrapolations, constant interpolations for jumps and so on. In short, this will _interpolate_ your
|
43
|
+
animation channel and extract it frame by frame, so all the animation is intact. **No keyframe baking is necessary** for the Flame operator to do.
|
44
|
+
Of course it supports both varieties of Flame setups - the newer 2012 ones as good as the old 9.0 - 2011 ones.
|
45
|
+
|
27
46
|
To use the library:
|
28
47
|
|
29
48
|
require "flame_channel_parser"
|
@@ -46,19 +65,19 @@ To use the library:
|
|
46
65
|
p interpolator.value_at(frame_in_setup)
|
47
66
|
end
|
48
67
|
|
49
|
-
|
68
|
+
## Requirements
|
50
69
|
|
51
|
-
* Ruby 1.8.
|
70
|
+
* Ruby 1.8.7 and above
|
52
71
|
|
53
|
-
|
72
|
+
## Installation
|
54
73
|
|
55
|
-
|
74
|
+
$gem install flame_channel_parser
|
56
75
|
|
57
|
-
|
76
|
+
## License
|
58
77
|
|
59
78
|
(The MIT License)
|
60
79
|
|
61
|
-
Copyright (c) 2011 Julik Tarkhanov
|
80
|
+
Copyright (c) 2011-2015 Julik Tarkhanov
|
62
81
|
|
63
82
|
Permission is hereby granted, free of charge, to any person obtaining
|
64
83
|
a copy of this software and associated documentation files (the
|
data/Rakefile
CHANGED
@@ -1,23 +1,6 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
require 'rubygems'
|
4
|
-
require 'jeweler'
|
5
|
-
require './lib/flame_channel_parser'
|
6
|
-
|
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'
|
16
|
-
end
|
17
|
-
|
18
|
-
Jeweler::RubygemsDotOrgTasks.new
|
19
|
-
|
1
|
+
require "bundler/gem_tasks"
|
20
2
|
require 'rake/testtask'
|
3
|
+
|
21
4
|
desc "Run all tests"
|
22
5
|
Rake::TestTask.new("test") do |t|
|
23
6
|
t.libs << "test"
|
@@ -25,6 +8,5 @@ Rake::TestTask.new("test") do |t|
|
|
25
8
|
t.verbose = true
|
26
9
|
end
|
27
10
|
|
11
|
+
# Automatically update the LICENSE
|
28
12
|
task :default => [ :test ]
|
29
|
-
|
30
|
-
# vim: syntax=ruby
|
data/bin/bake_flame_channel
CHANGED
@@ -10,7 +10,7 @@
|
|
10
10
|
# == Author
|
11
11
|
# Julik <me@julik.nl>
|
12
12
|
|
13
|
-
require File.expand_path(File.dirname(__FILE__)) + '/../lib/flame_channel_parser'
|
13
|
+
require File.expand_path(File.dirname(__FILE__)) + '/../lib/flame_channel_parser'
|
14
14
|
require 'optparse'
|
15
15
|
require 'rubygems'
|
16
16
|
require "update_hints"
|
@@ -0,0 +1,26 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# == Synopsis
|
3
|
+
#
|
4
|
+
# Shows a list of animation channels in the given Flame setup file
|
5
|
+
#
|
6
|
+
# == Usage
|
7
|
+
#
|
8
|
+
# flame_channel_inspect /usr/discreet/projects/Luxury/timewarp/shot2_tw.timewarp
|
9
|
+
#
|
10
|
+
# == Author
|
11
|
+
# Julik <me@julik.nl>
|
12
|
+
|
13
|
+
require File.expand_path(File.dirname(__FILE__)) + '/../lib/flame_channel_parser'
|
14
|
+
require 'rubygems'
|
15
|
+
require "update_hints"
|
16
|
+
|
17
|
+
setup_path = ARGV.shift
|
18
|
+
fail "No input file path provided." unless setup_path
|
19
|
+
fail "File does not exist." unless File.exist?(setup_path)
|
20
|
+
|
21
|
+
parser = FlameChannelParser::Parser.new
|
22
|
+
File.open(setup_path, "r") do | f |
|
23
|
+
channels = parser.parse(f)
|
24
|
+
tree = FlameChannelParser::Inspector.new(channels)
|
25
|
+
tree.pretty_print
|
26
|
+
end
|
@@ -1,131 +1,29 @@
|
|
1
|
-
# Generated by jeweler
|
2
|
-
# DO NOT EDIT THIS FILE DIRECTLY
|
3
|
-
# Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
|
4
1
|
# -*- encoding: utf-8 -*-
|
5
|
-
|
2
|
+
require File.dirname(__FILE__) + '/lib/flame_channel_parser/version'
|
6
3
|
Gem::Specification.new do |s|
|
7
4
|
s.name = "flame_channel_parser"
|
8
|
-
s.version =
|
5
|
+
s.version = FlameChannelParser::VERSION
|
9
6
|
|
10
7
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
8
|
s.authors = ["Julik Tarkhanov"]
|
12
|
-
s.date = "
|
9
|
+
s.date = Time.now.utc.strftime("%Y-%m-%d")
|
13
10
|
s.description = "Reads and interpolates animation channels in IFFS setups"
|
14
11
|
s.email = "me@julik.nl"
|
15
12
|
s.executables = ["bake_flame_channel", "framecurve_from_flame", "framecurve_to_flame"]
|
16
13
|
s.extra_rdoc_files = [
|
17
|
-
"README.
|
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_bake_flame_channel_binary.rb",
|
74
|
-
"test/test_base_timewarp_writer.rb",
|
75
|
-
"test/test_batch_timewarp_writer.rb",
|
76
|
-
"test/test_channel.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_examples/tw_batch_out.framecurve.txt",
|
97
|
-
"test/timewarp_export_samples/BatchTW.timewarp_node",
|
98
|
-
"test/timewarp_export_samples/Kronos.F_Kronos",
|
99
|
-
"test/timewarp_export_samples/SoftFX.timewarp"
|
14
|
+
"README.md"
|
100
15
|
]
|
16
|
+
s.files = `git ls-files -z`.split("\x0")
|
101
17
|
s.homepage = "http://guerilla-di.org/flame-channel-parser/"
|
102
18
|
s.licenses = ["MIT"]
|
103
19
|
s.require_paths = ["lib"]
|
104
20
|
s.rubygems_version = "1.8.11"
|
105
21
|
s.summary = "A parser/interpolator for Flame/Smoke animation curves"
|
106
22
|
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
s.add_development_dependency(%q<jeweler>, [">= 0"])
|
114
|
-
s.add_development_dependency(%q<rake>, [">= 0"])
|
115
|
-
s.add_development_dependency(%q<cli_test>, ["~> 1.0"])
|
116
|
-
else
|
117
|
-
s.add_dependency(%q<update_hints>, ["~> 1.0"])
|
118
|
-
s.add_dependency(%q<framecurve>, ["~> 1.0.1"])
|
119
|
-
s.add_dependency(%q<jeweler>, [">= 0"])
|
120
|
-
s.add_dependency(%q<rake>, [">= 0"])
|
121
|
-
s.add_dependency(%q<cli_test>, ["~> 1.0"])
|
122
|
-
end
|
123
|
-
else
|
124
|
-
s.add_dependency(%q<update_hints>, ["~> 1.0"])
|
125
|
-
s.add_dependency(%q<framecurve>, ["~> 1.0.1"])
|
126
|
-
s.add_dependency(%q<jeweler>, [">= 0"])
|
127
|
-
s.add_dependency(%q<rake>, [">= 0"])
|
128
|
-
s.add_dependency(%q<cli_test>, ["~> 1.0"])
|
129
|
-
end
|
23
|
+
s.specification_version = 3
|
24
|
+
s.add_runtime_dependency("update_hints", ["~> 1.0"])
|
25
|
+
s.add_runtime_dependency("framecurve", ["~> 2"])
|
26
|
+
s.add_development_dependency("rake", [">= 0"])
|
27
|
+
s.add_development_dependency("cli_test", ["~> 1.0"])
|
28
|
+
s.add_development_dependency("test-unit")
|
130
29
|
end
|
131
|
-
|
data/lib/flame_channel_parser.rb
CHANGED
@@ -1,5 +1,6 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/flame_channel_parser/version'
|
2
|
+
|
1
3
|
module FlameChannelParser
|
2
|
-
VERSION = '4.0.2'
|
3
4
|
|
4
5
|
module FramecurveWriters; end
|
5
6
|
|
@@ -37,7 +38,7 @@ module FlameChannelParser
|
|
37
38
|
end
|
38
39
|
|
39
40
|
%w(
|
40
|
-
key channel parser segments interpolator extractor timewarp_extractor builder xml_parser
|
41
|
+
key channel parser segments interpolator extractor timewarp_extractor builder xml_parser inspector
|
41
42
|
).each {|f| require File.expand_path(File.dirname(__FILE__) + "/" + f ) }
|
42
43
|
|
43
44
|
%w(
|
data/lib/inspector.rb
ADDED
@@ -0,0 +1,74 @@
|
|
1
|
+
# Prints out a viewable tree of channel metadata. Useful when you need to inspect comparable setups
|
2
|
+
# for small differentces in channel ordering and animation.
|
3
|
+
class FlameChannelParser::Inspector
|
4
|
+
|
5
|
+
def initialize(channels_arr)
|
6
|
+
@branches = OH.new
|
7
|
+
channels_arr.each {|c| cluster(c) }
|
8
|
+
end
|
9
|
+
|
10
|
+
def pretty_print(output = $stdout)
|
11
|
+
@out = output
|
12
|
+
print_branch(@branches, initial_indent = 0)
|
13
|
+
end
|
14
|
+
|
15
|
+
private
|
16
|
+
|
17
|
+
class OH < Hash # It sucks to be Ruby 1.8-compatible sometimes.
|
18
|
+
def initialize
|
19
|
+
super
|
20
|
+
@keys_in_order = []
|
21
|
+
end
|
22
|
+
|
23
|
+
def []=(k, v)
|
24
|
+
@keys_in_order.delete(k)
|
25
|
+
@keys_in_order << k
|
26
|
+
super(k, v)
|
27
|
+
end
|
28
|
+
|
29
|
+
def each_pair
|
30
|
+
@keys_in_order.each {|k| yield(k, self[k]) }
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
def puts(string)
|
35
|
+
@out.puts(string)
|
36
|
+
end
|
37
|
+
|
38
|
+
def print_branch(branch, indent)
|
39
|
+
branch.each_pair do | k, v|
|
40
|
+
if v.is_a?(Hash)
|
41
|
+
puts((" " * indent) + k)
|
42
|
+
print_branch(v, indent + 1)
|
43
|
+
else
|
44
|
+
puts((" " * indent) + k + " - " + channel_metadata(v))
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
def channel_metadata(channel)
|
50
|
+
if channel.length.zero?
|
51
|
+
"no animations, value %s" % [channel.base_value]
|
52
|
+
elsif channel.length > 1
|
53
|
+
first_key = channel[0].frame
|
54
|
+
last_key = channel[-1].frame
|
55
|
+
"animated, %d keys, first at %d last at %d" % [channel.length, first_key, last_key]
|
56
|
+
else
|
57
|
+
first_key = channel[0].frame
|
58
|
+
"animated, 1 key at %d, value %s" % [first_key, channel[0].value]
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
def cluster(channel)
|
63
|
+
path_parts = channel.name.split('/')
|
64
|
+
leaf_name = path_parts.pop
|
65
|
+
|
66
|
+
current = @branches
|
67
|
+
path_parts.each do | path_part |
|
68
|
+
current[path_part] ||= OH.new
|
69
|
+
current = current[path_part]
|
70
|
+
end
|
71
|
+
current[leaf_name] = channel
|
72
|
+
end
|
73
|
+
|
74
|
+
end
|