tef-animation 0.1.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.
- 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
|