tef-animation 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/README.md +6 -0
- data/lib/tef/Animation/Animatable.rb +213 -0
- data/lib/tef/Animation/Animation_Handler.rb +180 -0
- data/lib/tef/Animation/Color.rb +112 -0
- data/lib/tef/Animation/Coordinate.rb +49 -0
- data/lib/tef/Animation/Eyes.rb +21 -0
- data/lib/tef/Animation/Value.rb +133 -0
- data/lib/tef/ParameterStack/Override.rb +66 -0
- data/lib/tef/ParameterStack/Stack.rb +149 -0
- data/lib/tef/ProgramSelection/ProgramID.rb +56 -0
- data/lib/tef/ProgramSelection/ProgramSelector.rb +76 -0
- data/lib/tef/ProgramSelection/SequenceCollection.rb +75 -0
- data/lib/tef/ProgramSelection/SoundCollection.rb +108 -0
- data/lib/tef/Sequencing/BaseSequence.rb +72 -0
- data/lib/tef/Sequencing/EventCollector.rb +127 -0
- data/lib/tef/Sequencing/SequencePlayer.rb +91 -0
- data/lib/tef/Sequencing/Sheet.rb +33 -0
- data/lib/tef/Sequencing/SheetSequence.rb +138 -0
- data/lib/tef/animation.rb +11 -0
- metadata +105 -0
@@ -0,0 +1,49 @@
|
|
1
|
+
|
2
|
+
$coordinate_def ||= {
|
3
|
+
x: 0,
|
4
|
+
y: 1,
|
5
|
+
}
|
6
|
+
|
7
|
+
module TEF
|
8
|
+
module Animation
|
9
|
+
class Coordinate
|
10
|
+
$coordinate_def.each do |c, id|
|
11
|
+
define_method(c.to_s) do
|
12
|
+
@animatable_attributes[c]
|
13
|
+
end
|
14
|
+
|
15
|
+
define_method("#{c}=") do |arg|
|
16
|
+
if arg.is_a? Numeric
|
17
|
+
@animatable_attributes[c].add = arg
|
18
|
+
else
|
19
|
+
@animatable_attributes[c].from = arg
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
def initialize(start_offset)
|
25
|
+
@animatable_attributes = {}
|
26
|
+
|
27
|
+
$coordinate_def.each do |key, v|
|
28
|
+
@animatable_attributes[key] = Value.new(v + start_offset)
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
def animatable_attributes
|
33
|
+
@animatable_attributes.values
|
34
|
+
end
|
35
|
+
|
36
|
+
def configure(data)
|
37
|
+
raise ArgumentError, 'Coordinate config must be a hash!' unless data.is_a? Hash
|
38
|
+
|
39
|
+
data.each do |key, value|
|
40
|
+
coord = @animatable_attributes[key]
|
41
|
+
|
42
|
+
raise ArgumentError, "Coordinate #{key} does not exist!" unless coord
|
43
|
+
|
44
|
+
coord.configure value
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
|
2
|
+
require_relative 'Animatable.rb'
|
3
|
+
|
4
|
+
module TEF
|
5
|
+
module Animation
|
6
|
+
class Eye < Animatable
|
7
|
+
animatable_color :outer_color, 0
|
8
|
+
animatable_color :inner_color, 1
|
9
|
+
|
10
|
+
animatable_attr :iris_x, 0x10
|
11
|
+
animatable_attr :iris_y, 0x11
|
12
|
+
animatable_attr :top, 0x12
|
13
|
+
animatable_attr :bottom, 0x13
|
14
|
+
animatable_attr :eye_closure, 0x14
|
15
|
+
|
16
|
+
def initialize()
|
17
|
+
super();
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,133 @@
|
|
1
|
+
|
2
|
+
|
3
|
+
module TEF
|
4
|
+
module Animation
|
5
|
+
class Value
|
6
|
+
PARAM_TYPES = [:add, :multiply, :dampen, :delay, :from, :jump, :velocity];
|
7
|
+
|
8
|
+
attr_reader :ID
|
9
|
+
|
10
|
+
attr_reader :module_id
|
11
|
+
|
12
|
+
def initialize(value_num)
|
13
|
+
@ID = value_num;
|
14
|
+
|
15
|
+
@current = Hash.new(0);
|
16
|
+
@changes = {}
|
17
|
+
|
18
|
+
@is_animated = false;
|
19
|
+
end
|
20
|
+
|
21
|
+
def module_id=(new_id)
|
22
|
+
@module_id = new_id
|
23
|
+
|
24
|
+
PARAM_TYPES.each do |key|
|
25
|
+
@changes[:key] = true if @current[key] != 0
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
def total_id()
|
30
|
+
"#{@module_id}V#{@ID.to_s(16)}"
|
31
|
+
end
|
32
|
+
|
33
|
+
def generic_set(key, value)
|
34
|
+
raise ArgumentError, 'Key does not exist!' unless PARAM_TYPES.include? key
|
35
|
+
raise ArgumentError, "Input must be numeric!" unless value.is_a? Numeric
|
36
|
+
|
37
|
+
return if (value == @current[key] && ![:jump, :velocity].include?(key))
|
38
|
+
|
39
|
+
if [:multiply, :dampen, :delay].include? key
|
40
|
+
@is_animated = true
|
41
|
+
end
|
42
|
+
|
43
|
+
@current[key] = value
|
44
|
+
@changes[key] = true
|
45
|
+
end
|
46
|
+
|
47
|
+
[:jump, :velocity, :add, :multiply, :dampen, :delay].each do |key|
|
48
|
+
define_method(key.to_s) do
|
49
|
+
@current[key]
|
50
|
+
end
|
51
|
+
|
52
|
+
define_method("#{key}=") do |input|
|
53
|
+
generic_set key, input
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
def configure(data)
|
58
|
+
if data.is_a? Numeric
|
59
|
+
self.add = data
|
60
|
+
elsif data.is_a? Hash
|
61
|
+
data.each do |key, value|
|
62
|
+
generic_set key, value
|
63
|
+
end
|
64
|
+
else
|
65
|
+
self.from = data;
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
def from() return @current[:from] end
|
70
|
+
|
71
|
+
def from=(target)
|
72
|
+
if target.is_a? Value
|
73
|
+
target = target.total_id
|
74
|
+
end
|
75
|
+
|
76
|
+
if target.nil?
|
77
|
+
target = 'S0M0V0'
|
78
|
+
end
|
79
|
+
|
80
|
+
unless target =~ /^S[\d]{1,3}M[\da-f]{1,3}V\d+$/
|
81
|
+
raise ArgumentError, 'Target must be a valid Animation Value'
|
82
|
+
end
|
83
|
+
|
84
|
+
return if target == @current[:from]
|
85
|
+
|
86
|
+
@current[:from] = target
|
87
|
+
@changes[:from] = true
|
88
|
+
@is_animated = true
|
89
|
+
end
|
90
|
+
|
91
|
+
def has_changes?
|
92
|
+
return !@changes.empty?
|
93
|
+
end
|
94
|
+
|
95
|
+
private def rcut(value)
|
96
|
+
value.to_s.gsub(/(\.)0+$/, '')
|
97
|
+
end
|
98
|
+
|
99
|
+
def set_string()
|
100
|
+
return nil unless has_changes?
|
101
|
+
|
102
|
+
if !@is_animated
|
103
|
+
return nil unless @changes[:add]
|
104
|
+
|
105
|
+
out_str = "J#{rcut(@current[:add])};"
|
106
|
+
|
107
|
+
@changes = {}
|
108
|
+
|
109
|
+
return out_str
|
110
|
+
end
|
111
|
+
|
112
|
+
out_str = [];
|
113
|
+
|
114
|
+
out_str << "J#{rcut(@current[:jump])}" if @changes[:jump]
|
115
|
+
out_str << "V#{rcut(@current[:velocity])}" if @changes[:velocity]
|
116
|
+
|
117
|
+
out_str << @current[:from] if @changes[:from]
|
118
|
+
|
119
|
+
config_strs = [];
|
120
|
+
config_strs_out = [];
|
121
|
+
[:add, :multiply, :dampen, :delay].each do |k|
|
122
|
+
config_strs << rcut(@current[k])
|
123
|
+
|
124
|
+
config_strs_out = config_strs.dup if @changes[k]
|
125
|
+
end
|
126
|
+
|
127
|
+
@changes = {}
|
128
|
+
|
129
|
+
(out_str + config_strs_out).join(' ') + ';'
|
130
|
+
end
|
131
|
+
end
|
132
|
+
end
|
133
|
+
end
|
@@ -0,0 +1,66 @@
|
|
1
|
+
|
2
|
+
require_relative 'Stack.rb'
|
3
|
+
|
4
|
+
module TEF
|
5
|
+
module ParameterStack
|
6
|
+
class Override
|
7
|
+
include Comparable
|
8
|
+
|
9
|
+
attr_reader :level
|
10
|
+
|
11
|
+
def initialize(stack, init_level = 0)
|
12
|
+
raise ArgumentError, 'Handler must be CoreStack!' unless stack.is_a? Stack
|
13
|
+
|
14
|
+
@stack = stack
|
15
|
+
|
16
|
+
@level = init_level;
|
17
|
+
@overrides = {}
|
18
|
+
|
19
|
+
@valid_until = nil;
|
20
|
+
|
21
|
+
@stack.add_override self
|
22
|
+
end
|
23
|
+
|
24
|
+
def [](key)
|
25
|
+
@overrides[key]
|
26
|
+
end
|
27
|
+
|
28
|
+
def []=(key, new_value)
|
29
|
+
return if @overrides[key] == new_value
|
30
|
+
|
31
|
+
if new_value.nil?
|
32
|
+
delete(key)
|
33
|
+
return
|
34
|
+
end
|
35
|
+
|
36
|
+
@overrides[key] = new_value
|
37
|
+
@stack.override_claims self, key
|
38
|
+
end
|
39
|
+
|
40
|
+
def include?(key)
|
41
|
+
@overrides.include? key
|
42
|
+
end
|
43
|
+
def keys
|
44
|
+
@overrides.keys
|
45
|
+
end
|
46
|
+
|
47
|
+
def delete(key)
|
48
|
+
return unless @overrides.include? key
|
49
|
+
@overrides.delete key
|
50
|
+
|
51
|
+
return unless @stack.active_overrides[key] == self
|
52
|
+
|
53
|
+
@stack.recompute_single key
|
54
|
+
end
|
55
|
+
|
56
|
+
def destroy!
|
57
|
+
@stack.remove_override self
|
58
|
+
end
|
59
|
+
|
60
|
+
def <=>(other)
|
61
|
+
return @level <=> other.level if other.level != @level
|
62
|
+
return self.hash <=> other.hash
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
@@ -0,0 +1,149 @@
|
|
1
|
+
|
2
|
+
require_relative 'Override.rb'
|
3
|
+
|
4
|
+
module TEF
|
5
|
+
module ParameterStack
|
6
|
+
class Stack
|
7
|
+
attr_reader :changes
|
8
|
+
attr_reader :active_overrides
|
9
|
+
|
10
|
+
def initialize()
|
11
|
+
@current_values = {}
|
12
|
+
@active_overrides = {}
|
13
|
+
|
14
|
+
@changes = {}
|
15
|
+
|
16
|
+
@override_list_mutex = Mutex.new()
|
17
|
+
@override_list = []
|
18
|
+
|
19
|
+
@recompute_blocks = []
|
20
|
+
@value_change_blocks = []
|
21
|
+
|
22
|
+
@default_override = Override.new(self, -1);
|
23
|
+
end
|
24
|
+
|
25
|
+
def [](key)
|
26
|
+
@current_values[key]
|
27
|
+
end
|
28
|
+
def []=(key, value)
|
29
|
+
@default_override[key] = value
|
30
|
+
end
|
31
|
+
def keys
|
32
|
+
@current_values.keys
|
33
|
+
end
|
34
|
+
|
35
|
+
def on_recompute(*keys, &block)
|
36
|
+
@recompute_blocks << {
|
37
|
+
block: block,
|
38
|
+
keys: keys
|
39
|
+
}
|
40
|
+
end
|
41
|
+
|
42
|
+
def on_change(*filters, &block)
|
43
|
+
filters = nil if filters.empty?
|
44
|
+
|
45
|
+
@value_change_blocks << {
|
46
|
+
block: block,
|
47
|
+
filters: filters
|
48
|
+
}
|
49
|
+
end
|
50
|
+
|
51
|
+
private def mark_key_change(key)
|
52
|
+
@changes[key] = true
|
53
|
+
|
54
|
+
@recompute_blocks.each do |block_cfg|
|
55
|
+
next unless block_cfg[:keys].include? key
|
56
|
+
block_cfg[:block].call(key, @current_values[key])
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
def override_claims(override, key)
|
61
|
+
return if !(@active_overrides[key].nil?) && (@active_overrides[key] > override)
|
62
|
+
|
63
|
+
@active_overrides[key] = override;
|
64
|
+
value = override[key];
|
65
|
+
|
66
|
+
return if @current_values[key] == value
|
67
|
+
|
68
|
+
@current_values[key] = value
|
69
|
+
mark_key_change key
|
70
|
+
end
|
71
|
+
|
72
|
+
def recompute_single(key)
|
73
|
+
old_value = @current_values[key]
|
74
|
+
|
75
|
+
found_override = false;
|
76
|
+
|
77
|
+
@override_list_mutex.synchronize do
|
78
|
+
@override_list.each do |override|
|
79
|
+
next unless override.include? key
|
80
|
+
|
81
|
+
@active_overrides[key] = override;
|
82
|
+
@current_values[key] = override[key];
|
83
|
+
|
84
|
+
found_override = true;
|
85
|
+
|
86
|
+
break;
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
if !found_override
|
91
|
+
@current_values.delete key
|
92
|
+
@active_overrides.delete key
|
93
|
+
end
|
94
|
+
|
95
|
+
mark_key_change key if old_value != @current_values[key]
|
96
|
+
end
|
97
|
+
|
98
|
+
def recompute(keys)
|
99
|
+
keys.each do |key|
|
100
|
+
recompute_single key
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
private def keys_match_filters(keys, filters)
|
105
|
+
return true if filters.nil?
|
106
|
+
|
107
|
+
filters = [filters] unless filters.is_a? Array
|
108
|
+
|
109
|
+
filters.each do |filter|
|
110
|
+
keys.each do |key|
|
111
|
+
return true if filter.is_a?(Regexp) && key =~ filter
|
112
|
+
return true if filter.is_a?(String) && key == filter
|
113
|
+
end
|
114
|
+
end
|
115
|
+
|
116
|
+
return false
|
117
|
+
end
|
118
|
+
|
119
|
+
def process_changes()
|
120
|
+
change_list = @changes.keys
|
121
|
+
|
122
|
+
@value_change_blocks.each do |block_cfg|
|
123
|
+
next unless keys_match_filters change_list, block_cfg[:filters]
|
124
|
+
|
125
|
+
block_cfg[:block].call()
|
126
|
+
end
|
127
|
+
|
128
|
+
@changes = {}
|
129
|
+
end
|
130
|
+
|
131
|
+
def add_override(override)
|
132
|
+
@override_list_mutex.synchronize do
|
133
|
+
@override_list << override unless @override_list.include? override
|
134
|
+
@override_list.sort!
|
135
|
+
end
|
136
|
+
end
|
137
|
+
|
138
|
+
def remove_override(override)
|
139
|
+
return unless @override_list.include? override
|
140
|
+
|
141
|
+
@override_list_mutex.synchronize do
|
142
|
+
@override_list.delete override
|
143
|
+
end
|
144
|
+
|
145
|
+
recompute override.keys
|
146
|
+
end
|
147
|
+
end
|
148
|
+
end
|
149
|
+
end
|
@@ -0,0 +1,56 @@
|
|
1
|
+
|
2
|
+
|
3
|
+
module TEF
|
4
|
+
module ProgramSelection
|
5
|
+
class ID
|
6
|
+
attr_reader :title
|
7
|
+
attr_reader :groups
|
8
|
+
attr_reader :variant
|
9
|
+
|
10
|
+
attr_reader :hash
|
11
|
+
|
12
|
+
def initialize(title, groups, variant)
|
13
|
+
@title = title;
|
14
|
+
@groups = groups.sort
|
15
|
+
@variant = variant
|
16
|
+
|
17
|
+
@hash = @title.hash ^ @groups.hash ^ @variant.hash
|
18
|
+
end
|
19
|
+
|
20
|
+
def ==(other)
|
21
|
+
if other.is_a? String
|
22
|
+
@title == other
|
23
|
+
elsif other.is_a? ID
|
24
|
+
return false if @title != other.title
|
25
|
+
return false if @variant != other.variant
|
26
|
+
return false if @groups != other.groups
|
27
|
+
|
28
|
+
true
|
29
|
+
end
|
30
|
+
end
|
31
|
+
alias eql? ==
|
32
|
+
|
33
|
+
def <=>(other)
|
34
|
+
tsort = (@title <=> other.title)
|
35
|
+
return tsort unless tsort.zero?
|
36
|
+
|
37
|
+
gsort = (@groups <=> other.groups)
|
38
|
+
return gsort unless gsort.zero?
|
39
|
+
|
40
|
+
@variant <=> other.variant
|
41
|
+
end
|
42
|
+
|
43
|
+
def get_scoring(group_weights)
|
44
|
+
score = 0;
|
45
|
+
|
46
|
+
@groups.each do |g|
|
47
|
+
if weight = group_weights[g]
|
48
|
+
score += weight
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
score
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|