slidefield 0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +22 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +674 -0
- data/README.md +254 -0
- data/Rakefile +7 -0
- data/bin/slidefield +89 -0
- data/examples/complete/assets/K2.jpg +0 -0
- data/examples/complete/assets/gobi.jpg +0 -0
- data/examples/complete/assets/mount_everest.jpg +0 -0
- data/examples/complete/assets/sahara.jpg +0 -0
- data/examples/complete/main.sfp +7 -0
- data/examples/complete/slides/deserts.sfi +19 -0
- data/examples/complete/slides/mountains.sfi +25 -0
- data/examples/complete/templates.sfi +95 -0
- data/examples/complete/variables.sfi +6 -0
- data/examples/minimal/main.sfp +43 -0
- data/examples/minimal/ruby-logo.png +0 -0
- data/lib/slidefield/animator.rb +104 -0
- data/lib/slidefield/errors.rb +6 -0
- data/lib/slidefield/interpreter.rb +414 -0
- data/lib/slidefield/object_data.rb +78 -0
- data/lib/slidefield/object_manager.rb +29 -0
- data/lib/slidefield/object_rules.rb +79 -0
- data/lib/slidefield/objects/_base.rb +29 -0
- data/lib/slidefield/objects/_root.rb +10 -0
- data/lib/slidefield/objects/animation.rb +10 -0
- data/lib/slidefield/objects/debug.rb +18 -0
- data/lib/slidefield/objects/image.rb +47 -0
- data/lib/slidefield/objects/include.rb +9 -0
- data/lib/slidefield/objects/layout.rb +10 -0
- data/lib/slidefield/objects/rect.rb +44 -0
- data/lib/slidefield/objects/slide.rb +43 -0
- data/lib/slidefield/objects/song.rb +31 -0
- data/lib/slidefield/objects/text.rb +57 -0
- data/lib/slidefield/parser.rb +99 -0
- data/lib/slidefield/version.rb +3 -0
- data/lib/slidefield/viewer.rb +89 -0
- data/lib/slidefield.rb +27 -0
- data/slidefield.gemspec +27 -0
- data/test/helper.rb +11 -0
- data/test/resources/include_sub.sfp +1 -0
- data/test/resources/parse_error.sfp +1 -0
- data/test/resources/recursive_include.sfp +1 -0
- data/test/resources/sub/include_parent.sfp +1 -0
- data/test/resources/unclosed_object.sfp +2 -0
- data/test/resources/unknown_object.sfp +1 -0
- data/test/resources/wrong_template.sfp +4 -0
- data/test/test_animator.rb +244 -0
- data/test/test_examples.rb +29 -0
- data/test/test_interpreter.rb +1766 -0
- data/test/test_object_data.rb +108 -0
- data/test/test_object_manager.rb +48 -0
- data/test/test_object_rules.rb +87 -0
- data/test/test_parser.rb +408 -0
- metadata +199 -0
data/README.md
ADDED
@@ -0,0 +1,254 @@
|
|
1
|
+
# SlideField
|
2
|
+
|
3
|
+
**A presentation software that reads plain text files written in its own
|
4
|
+
interpreted language.**
|
5
|
+
|
6
|
+
## Installation
|
7
|
+
|
8
|
+
Requirements: ruby, sdl, sdl_ttf, freeimage
|
9
|
+
|
10
|
+
$ gem install slidefield
|
11
|
+
|
12
|
+
|
13
|
+
## Usage
|
14
|
+
|
15
|
+
$ slidefield [options] [file ...]
|
16
|
+
|
17
|
+
### Comments
|
18
|
+
|
19
|
+
% single-line comment
|
20
|
+
%{ multi-line
|
21
|
+
comment %}
|
22
|
+
|
23
|
+
### Variables
|
24
|
+
|
25
|
+
A variable can only be created once inside each object (with the `=` operator).
|
26
|
+
However they can be modified freely using any other available operator.
|
27
|
+
The type of the variable cannot be changed after the variable creation.
|
28
|
+
|
29
|
+
variable = value
|
30
|
+
variable += value
|
31
|
+
variable -= value
|
32
|
+
variable *= value
|
33
|
+
variable /= value
|
34
|
+
|
35
|
+
|
36
|
+
### Value types
|
37
|
+
|
38
|
+
Integers:
|
39
|
+
|
40
|
+
variable = 42
|
41
|
+
variable += 2 % add
|
42
|
+
variable -= 10 % subtract
|
43
|
+
variable *= 6 % multiply
|
44
|
+
variable /= 10 % divide
|
45
|
+
% variable is 20
|
46
|
+
|
47
|
+
Character strings:
|
48
|
+
|
49
|
+
variable = "hello"
|
50
|
+
variable += " world!\n" % append
|
51
|
+
variable -= "!" % remove the bang
|
52
|
+
variable *= "3" % multiply by 3
|
53
|
+
% variable is "hello world\nhello world\nhello world\n"
|
54
|
+
|
55
|
+
Size or point coordinates:
|
56
|
+
|
57
|
+
variable = 2x4
|
58
|
+
variable += 100x80 % add
|
59
|
+
variable -= 10x0 % subtract
|
60
|
+
variable *= 3x4 % multiply
|
61
|
+
variable /= 2x2 % divide
|
62
|
+
% variable is 138x168
|
63
|
+
|
64
|
+
Colors (red, blue, green & alpha in hexadecimal notation):
|
65
|
+
|
66
|
+
variable = #C0FF33FF
|
67
|
+
variable += #03003300 % add
|
68
|
+
variable -= #0C240055 % subtract
|
69
|
+
% variable is #B7DB66AA
|
70
|
+
|
71
|
+
Booleans:
|
72
|
+
|
73
|
+
variable = :true
|
74
|
+
opposite = :false
|
75
|
+
|
76
|
+
Variables can also store custom objects. See the 'Templates' section below.
|
77
|
+
|
78
|
+
### Objects
|
79
|
+
|
80
|
+
Variables are bound to the object in which they are created into.
|
81
|
+
Most SlideField object have reserved variables ("*properties*")
|
82
|
+
with a predefined type.
|
83
|
+
All properties are mandatory unless otherwise specified.
|
84
|
+
|
85
|
+
Nested objects inherit their parent's variables.
|
86
|
+
All slide objects (marked as such in the list below) can be infinitely nested.
|
87
|
+
|
88
|
+
% Syntax:
|
89
|
+
\object_name
|
90
|
+
\object_name { ... }
|
91
|
+
\object_name value
|
92
|
+
\object_name value { ... }
|
93
|
+
|
94
|
+
The shortcut syntax `\object value` assigns `value` to the first property
|
95
|
+
compatible with the value's type.
|
96
|
+
|
97
|
+
### Object List
|
98
|
+
|
99
|
+
**(Anywhere)** Load another file at the current location:
|
100
|
+
|
101
|
+
\include "relative/path/to/file.sfp"
|
102
|
+
\include {
|
103
|
+
source = "relative/path/to/file.sfp"
|
104
|
+
}
|
105
|
+
|
106
|
+
**(Anywhere)** Print debug information about any value to standard output:
|
107
|
+
|
108
|
+
\debug any_value
|
109
|
+
|
110
|
+
**(Top-level, required, maximum 1)** Configure the output window:
|
111
|
+
|
112
|
+
\layout 1920x1080
|
113
|
+
\layout {
|
114
|
+
size = 1920x1080
|
115
|
+
fullscreen = :true % optional
|
116
|
+
}
|
117
|
+
|
118
|
+
**(Top-level, required)** Create a slide:
|
119
|
+
|
120
|
+
\slide { ... }
|
121
|
+
|
122
|
+
**(Slide)** Animation between slides:
|
123
|
+
|
124
|
+
\animation "fade" { ... }
|
125
|
+
\animation {
|
126
|
+
name = "fade"
|
127
|
+
%{
|
128
|
+
other possible values are:
|
129
|
+
name = "slide right"
|
130
|
+
name = "slide left"
|
131
|
+
name = "slide down"
|
132
|
+
name = "slide up"
|
133
|
+
name = "zoom"
|
134
|
+
%}
|
135
|
+
duration = 400 % in ms (optional)
|
136
|
+
}
|
137
|
+
*Note: The animation is applied only to nested objects.*
|
138
|
+
|
139
|
+
**(Slide)** Add an image:
|
140
|
+
|
141
|
+
\image "relative/path/to/image.png"
|
142
|
+
\image {
|
143
|
+
source = "relative/path/to/image.png"
|
144
|
+
size = 0x0 % automatic if 0 (optional)
|
145
|
+
color = #FFFFFFFF % color filter (optional)
|
146
|
+
position = 0x0 % optional
|
147
|
+
z_order = 0 % optional
|
148
|
+
}
|
149
|
+
|
150
|
+
**(Slide)** Add a rectangle:
|
151
|
+
|
152
|
+
\rect 100x100
|
153
|
+
\rect {
|
154
|
+
size = 100x100
|
155
|
+
fill = #FFFFFFFF % optional
|
156
|
+
position = 0x0 % optional
|
157
|
+
z_order = 0 % optional
|
158
|
+
}
|
159
|
+
|
160
|
+
**(Slide)** Play an audio file:
|
161
|
+
|
162
|
+
\song "relative/path/to/audio.ogg"
|
163
|
+
\song {
|
164
|
+
source = "relative/path/to/audio.ogg"
|
165
|
+
volume = 100 % optional
|
166
|
+
loop = :true % optional
|
167
|
+
}
|
168
|
+
|
169
|
+
**(Slide)** Add text:
|
170
|
+
|
171
|
+
\text "Hello World!"
|
172
|
+
\text {
|
173
|
+
content = "Hello World!"
|
174
|
+
color = #FFFFFFFF % optional
|
175
|
+
font = "sans" % font name or relative font path (optional)
|
176
|
+
% font = "./my_font.ttf"
|
177
|
+
height = 20 % font height in pixels (optional)
|
178
|
+
width = 0 % maximum width (automatic if 0, optional)
|
179
|
+
spacing = 0 % line spacing (optional)
|
180
|
+
align = "left" % optional
|
181
|
+
%{
|
182
|
+
other possible values are:
|
183
|
+
align = "right"
|
184
|
+
align = "center"
|
185
|
+
align = "justify"
|
186
|
+
%}
|
187
|
+
position = 0x0 % optional
|
188
|
+
z_order = 0 % optional
|
189
|
+
}
|
190
|
+
|
191
|
+
### Filters
|
192
|
+
Filters are like methods in an object-oriented programming language.
|
193
|
+
They can be chained infinitely.
|
194
|
+
|
195
|
+
variable = (filter)value
|
196
|
+
variable = (second_filter)(first_filter)value
|
197
|
+
|
198
|
+
Point to integer:
|
199
|
+
|
200
|
+
point = 1920x1080
|
201
|
+
x = (x)point
|
202
|
+
% x is 1920
|
203
|
+
|
204
|
+
y = (y)point
|
205
|
+
% y is 1080
|
206
|
+
|
207
|
+
Integer to point:
|
208
|
+
|
209
|
+
point = (x)1920
|
210
|
+
% point is 1920x0
|
211
|
+
|
212
|
+
point += (y)1080
|
213
|
+
% point is 1920x1080
|
214
|
+
|
215
|
+
Line count:
|
216
|
+
|
217
|
+
lines = (lines)"Lorem\nIpsum"
|
218
|
+
% lines is 2
|
219
|
+
|
220
|
+
### Templates
|
221
|
+
Custom objects can be created using templates.
|
222
|
+
|
223
|
+
template_name = \object_name { ... }
|
224
|
+
\&template_name
|
225
|
+
|
226
|
+
% creation
|
227
|
+
slide_template = \slide {
|
228
|
+
\image background { size = 1920x1080; }
|
229
|
+
\text title { height = 72; }
|
230
|
+
}
|
231
|
+
|
232
|
+
% usage
|
233
|
+
\&slide_template {
|
234
|
+
title = "Hello World!"
|
235
|
+
background = "relative/path/to/image.png"
|
236
|
+
}
|
237
|
+
|
238
|
+
Equivalent of the above example without using templates:
|
239
|
+
|
240
|
+
\slide {
|
241
|
+
title = "Hello World!"
|
242
|
+
background = "relative/path/to/image.png"
|
243
|
+
\image background { size = 1920x1080; }
|
244
|
+
\text title { height = 72; }
|
245
|
+
}
|
246
|
+
|
247
|
+
## Contributing
|
248
|
+
|
249
|
+
1. [Fork it](https://bitbucket.org/cfi30/slidefield/fork)
|
250
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
251
|
+
3. Test your changes (`rake`)
|
252
|
+
4. Commit your changes (`git commit -am 'Add some feature'`)
|
253
|
+
5. Push to the branch (`git push origin my-new-feature`)
|
254
|
+
6. Create new Pull Request
|
data/Rakefile
ADDED
data/bin/slidefield
ADDED
@@ -0,0 +1,89 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# This program is free software: you can redistribute it and/or modify
|
3
|
+
# it under the terms of the GNU General Public License as published by
|
4
|
+
# the Free Software Foundation, either version 3 of the License, or
|
5
|
+
# (at your option) any later version.
|
6
|
+
#
|
7
|
+
# This program is distributed in the hope that it will be useful,
|
8
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
9
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
10
|
+
# GNU General Public License for more details.
|
11
|
+
#
|
12
|
+
# You should have received a copy of the GNU General Public License
|
13
|
+
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
14
|
+
|
15
|
+
require 'slidefield'
|
16
|
+
require 'optparse'
|
17
|
+
|
18
|
+
def parse_opts
|
19
|
+
options = []
|
20
|
+
|
21
|
+
OptionParser.new do |opts|
|
22
|
+
opts.program_name = "SlideField"
|
23
|
+
opts.version = SlideField::VERSION
|
24
|
+
opts.banner = "Usage: slidefield [options] [file ...]"
|
25
|
+
|
26
|
+
opts.on '-c', '--check', "Check input only" do
|
27
|
+
options << :check
|
28
|
+
end
|
29
|
+
|
30
|
+
opts.on_tail '-v', '--version', "Show version number and copyright" do
|
31
|
+
puts opts.ver
|
32
|
+
puts <<GPL
|
33
|
+
Copyright (C) 2014 by Christian Fillion
|
34
|
+
|
35
|
+
This program is free software; you can redistribute it and/or
|
36
|
+
modify it under the terms of the GNU General Public License as
|
37
|
+
published by the Free Software Foundation, either version 3 of
|
38
|
+
the License, or (at your option) any later version.
|
39
|
+
|
40
|
+
This program is distributed in the hope that it will be useful,
|
41
|
+
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
42
|
+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
43
|
+
General Public License for more details.
|
44
|
+
GPL
|
45
|
+
exit
|
46
|
+
end
|
47
|
+
|
48
|
+
opts.on_tail '-h', '--help', "Show this message" do
|
49
|
+
puts opts.help
|
50
|
+
exit
|
51
|
+
end
|
52
|
+
end.parse!
|
53
|
+
|
54
|
+
options
|
55
|
+
end
|
56
|
+
|
57
|
+
begin
|
58
|
+
begin
|
59
|
+
options = parse_opts
|
60
|
+
rescue OptionParser::InvalidOption => e
|
61
|
+
raise SlideField::Error, e
|
62
|
+
end
|
63
|
+
|
64
|
+
files = ARGV
|
65
|
+
|
66
|
+
# read from standard input by default
|
67
|
+
files << '-' if files.empty?
|
68
|
+
|
69
|
+
files.each {|file|
|
70
|
+
interpreter = SlideField::Interpreter.new
|
71
|
+
if '-' == file
|
72
|
+
interpreter.run_string STDIN.read
|
73
|
+
else
|
74
|
+
path = File.absolute_path file
|
75
|
+
interpreter.run_file path
|
76
|
+
end
|
77
|
+
|
78
|
+
next if options.include? :check
|
79
|
+
|
80
|
+
project_root = interpreter.root
|
81
|
+
viewer = SlideField::Viewer.new project_root
|
82
|
+
viewer.caption = project_root.context
|
83
|
+
viewer.show
|
84
|
+
}
|
85
|
+
rescue SlideField::Error => e
|
86
|
+
warn "#{e.class}: #{e}"
|
87
|
+
rescue Interrupt
|
88
|
+
puts
|
89
|
+
end
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
@@ -0,0 +1,19 @@
|
|
1
|
+
\&slide_tpl {
|
2
|
+
title = "Sahara"
|
3
|
+
|
4
|
+
infos = "<b>Area:</b> 9,400,000 km²\n"
|
5
|
+
infos += "<b>Notes:</b> The world's hottest desert"
|
6
|
+
|
7
|
+
background_src = "../assets/sahara.jpg"
|
8
|
+
background_link = "https://en.wikipedia.org/wiki/File:Sahara_satellite_hires.jpg"
|
9
|
+
}
|
10
|
+
|
11
|
+
\&slide_tpl {
|
12
|
+
title = "Gobi"
|
13
|
+
|
14
|
+
infos = "<b>Area:</b> 1,295,000 km²\n"
|
15
|
+
infos += "<b>Notes:</b> The expansion of the Gobi is\nattributed mostly to human activities"
|
16
|
+
|
17
|
+
background_src = "../assets/gobi.jpg"
|
18
|
+
background_link = "https://en.wikipedia.org/wiki/File:Khongoryn_Els,_Gurvansaikhan_NP,_Gobi_desert,_Mongolia.jpg"
|
19
|
+
}
|
@@ -0,0 +1,25 @@
|
|
1
|
+
\&slide_tpl {
|
2
|
+
title = "Mount Everest"
|
3
|
+
|
4
|
+
infos = "<b>Country:</b> Nepal\n"
|
5
|
+
infos += "<b>Elevation:</b> 8,848 m\n"
|
6
|
+
infos += "<b>First ascent:</b> 29 May 1953\n"
|
7
|
+
infos += "<b>Easiest route:</b> South Col\n"
|
8
|
+
infos += "<b>Notes:</b> Earth's highest mountain"
|
9
|
+
|
10
|
+
background_src = "../assets/mount_everest.jpg"
|
11
|
+
background_link = "https://en.wikipedia.org/wiki/File:Mount_Everest_as_seen_from_Drukair2_PLW_edit.jpg"
|
12
|
+
}
|
13
|
+
|
14
|
+
\&slide_tpl {
|
15
|
+
title = "K2"
|
16
|
+
|
17
|
+
infos = "<b>Country:</b> Pakistan\n"
|
18
|
+
infos += "<b>Elevation:</b> 8,611 m\n"
|
19
|
+
infos += "<b>First ascent:</b> 31 July 1954\n"
|
20
|
+
infos += "<b>Easiest route:</b> Abruzzi Spur\n"
|
21
|
+
infos += "<b>Notes:</b> The mountain was first\nsurveyed by a European team in 1856"
|
22
|
+
|
23
|
+
background_src = "../assets/K2.jpg"
|
24
|
+
background_link = "https://en.wikipedia.org/wiki/File:K2_2006b.jpg"
|
25
|
+
}
|
@@ -0,0 +1,95 @@
|
|
1
|
+
background_tpl = \image {
|
2
|
+
size = layout_size
|
3
|
+
}
|
4
|
+
|
5
|
+
title_tpl = \text {
|
6
|
+
color = #FFFFFFFF
|
7
|
+
font = title_font
|
8
|
+
height = 100
|
9
|
+
position = 100x70
|
10
|
+
z_order = 1
|
11
|
+
|
12
|
+
% support alignment
|
13
|
+
x = (x)position
|
14
|
+
x *= 2
|
15
|
+
width = (x)layout_size
|
16
|
+
width -= x
|
17
|
+
|
18
|
+
% shadow
|
19
|
+
\text #00000099 {
|
20
|
+
position += 2x2
|
21
|
+
z_order -= 1
|
22
|
+
}
|
23
|
+
}
|
24
|
+
|
25
|
+
infobox_tpl = \rect {
|
26
|
+
padding = 10
|
27
|
+
text_height = 40
|
28
|
+
z_order = 1
|
29
|
+
|
30
|
+
box_height = (lines)content
|
31
|
+
box_height *= text_height
|
32
|
+
box_height += padding
|
33
|
+
|
34
|
+
size = 650x0
|
35
|
+
size += (y)box_height
|
36
|
+
|
37
|
+
position = layout_size
|
38
|
+
position -= size
|
39
|
+
position /= 2x1
|
40
|
+
position -= 0x100
|
41
|
+
|
42
|
+
fill = #FFFFFF69
|
43
|
+
|
44
|
+
\text {
|
45
|
+
position += (x)padding
|
46
|
+
position += (y)padding
|
47
|
+
|
48
|
+
height = text_height
|
49
|
+
color = #011010FF
|
50
|
+
font = info_font
|
51
|
+
|
52
|
+
% shadow
|
53
|
+
\text {
|
54
|
+
position += 1x1
|
55
|
+
color = #FFFFFF99
|
56
|
+
z_order -= 1
|
57
|
+
}
|
58
|
+
}
|
59
|
+
}
|
60
|
+
|
61
|
+
credit_tpl = \text {
|
62
|
+
position = 10x-30
|
63
|
+
position += (y)(y)layout_size
|
64
|
+
|
65
|
+
color = #FFFFFFFF
|
66
|
+
z_order = 1
|
67
|
+
|
68
|
+
\text {
|
69
|
+
position += 1x1
|
70
|
+
color = #000000FF
|
71
|
+
z_order -= 1
|
72
|
+
}
|
73
|
+
}
|
74
|
+
|
75
|
+
slide_tpl = \slide {
|
76
|
+
\animation "fade" {
|
77
|
+
\&background_tpl background_src
|
78
|
+
}
|
79
|
+
|
80
|
+
\&title_tpl {
|
81
|
+
content = "<b>"
|
82
|
+
content += title
|
83
|
+
}
|
84
|
+
|
85
|
+
\animation "slide left" {
|
86
|
+
\&infobox_tpl {
|
87
|
+
content = infos
|
88
|
+
}
|
89
|
+
}
|
90
|
+
|
91
|
+
\&credit_tpl {
|
92
|
+
content = "<b>Photo Credit:</b> "
|
93
|
+
content += background_link
|
94
|
+
}
|
95
|
+
}
|
@@ -0,0 +1,43 @@
|
|
1
|
+
layout_size = 1366x768
|
2
|
+
|
3
|
+
\layout layout_size
|
4
|
+
|
5
|
+
\slide {
|
6
|
+
\text "Hello World!" { height = 50; }
|
7
|
+
\text "Press <b>Enter</b> to display the next slide" {
|
8
|
+
position = 0x50
|
9
|
+
}
|
10
|
+
}
|
11
|
+
|
12
|
+
\slide {
|
13
|
+
\text "Second Slide"
|
14
|
+
\text "Press <b>Backspace</b> to return to the previous slide" {
|
15
|
+
position = 0x30
|
16
|
+
width = 200
|
17
|
+
}
|
18
|
+
|
19
|
+
\text "This example contains 3 slides.\n(Press <b>Enter</b> again)" {
|
20
|
+
position = 0x70
|
21
|
+
width = (x)layout_size
|
22
|
+
align = "right"
|
23
|
+
}
|
24
|
+
}
|
25
|
+
|
26
|
+
\slide {
|
27
|
+
\rect {
|
28
|
+
fill = #FFFFFFFF % RRGGBBAA
|
29
|
+
size = layout_size
|
30
|
+
}
|
31
|
+
|
32
|
+
\image "ruby-logo.png" {
|
33
|
+
position = layout_size
|
34
|
+
position -= 62x62
|
35
|
+
position /= 2x2
|
36
|
+
}
|
37
|
+
|
38
|
+
\text {
|
39
|
+
content = "Last Slide\nPress <b>Escape</b> to quit"
|
40
|
+
color = #000000FF
|
41
|
+
font = "monospace"
|
42
|
+
}
|
43
|
+
}
|
Binary file
|
@@ -0,0 +1,104 @@
|
|
1
|
+
class SlideField::Animator
|
2
|
+
attr_accessor :current, :forward
|
3
|
+
|
4
|
+
def initialize(layout_size)
|
5
|
+
@layout_size = layout_size
|
6
|
+
reset
|
7
|
+
end
|
8
|
+
|
9
|
+
def need_redraw?
|
10
|
+
@animations.each {|k,v| return true if v.enabled }
|
11
|
+
@animations.empty?
|
12
|
+
end
|
13
|
+
|
14
|
+
def reset
|
15
|
+
@animations = {}
|
16
|
+
end
|
17
|
+
|
18
|
+
def frame(*args)
|
19
|
+
struct = Struct.new :time, :current?, :forward?
|
20
|
+
@frame = struct.new *args
|
21
|
+
yield
|
22
|
+
@frame = nil
|
23
|
+
end
|
24
|
+
|
25
|
+
def transform(obj)
|
26
|
+
raise "Can not animate outside a frame" unless @frame
|
27
|
+
|
28
|
+
tr_struct = Struct.new :skip_draw?, :x_offset, :y_offset, :scale, :opacity
|
29
|
+
tr = tr_struct.new false, 0, 0, 1.0, 1.0
|
30
|
+
|
31
|
+
anim = animation_for obj.ancestor(:animation)
|
32
|
+
|
33
|
+
# no animation
|
34
|
+
return tr if anim.nil?
|
35
|
+
|
36
|
+
elapsed = @frame.time - anim.start_time
|
37
|
+
position = elapsed / anim.duration
|
38
|
+
anim.enabled = false if position > 1.0
|
39
|
+
|
40
|
+
# animation finished
|
41
|
+
unless anim.enabled
|
42
|
+
tr[:skip_draw?] = !@frame.current? # don't draw the previous slide anymore
|
43
|
+
return tr
|
44
|
+
end
|
45
|
+
|
46
|
+
width, height = @layout_size
|
47
|
+
|
48
|
+
case anim.name
|
49
|
+
when "fade"
|
50
|
+
if @frame.current?
|
51
|
+
tr.opacity = position
|
52
|
+
else
|
53
|
+
tr.opacity = 1.0 - position
|
54
|
+
end
|
55
|
+
when "slide right"
|
56
|
+
tr.x_offset = slide_offset position, width, false
|
57
|
+
when "slide left"
|
58
|
+
tr.x_offset = slide_offset position, width, true
|
59
|
+
when "slide down"
|
60
|
+
tr.y_offset = slide_offset position, height, false
|
61
|
+
when "slide up"
|
62
|
+
tr.y_offset = slide_offset position, height, true
|
63
|
+
when "zoom"
|
64
|
+
if @frame.current?
|
65
|
+
tr.scale = position
|
66
|
+
else
|
67
|
+
tr.scale = 1.0 - position
|
68
|
+
end
|
69
|
+
else
|
70
|
+
# the validator has missed ?!
|
71
|
+
# TODO: validate at interpret time
|
72
|
+
raise SlideField::RuntimeError,
|
73
|
+
"Unsupported animation '#{anim.name}'"
|
74
|
+
end
|
75
|
+
|
76
|
+
tr
|
77
|
+
end
|
78
|
+
|
79
|
+
private
|
80
|
+
def animation_for(data)
|
81
|
+
return @animations[data] if @animations.has_key? data
|
82
|
+
|
83
|
+
anim_struct = Struct.new :enabled, :start_time, :name, :duration
|
84
|
+
anim = anim_struct.new false, 0.0, '', 0
|
85
|
+
|
86
|
+
if data
|
87
|
+
anim.enabled = true
|
88
|
+
anim.start_time = @frame.time.to_f
|
89
|
+
anim.name = data.get :name
|
90
|
+
anim.duration = data.get :duration
|
91
|
+
end
|
92
|
+
|
93
|
+
@animations[data] = anim
|
94
|
+
end
|
95
|
+
|
96
|
+
def slide_offset(position, size, inverse)
|
97
|
+
inverse = !inverse unless @frame.forward?
|
98
|
+
|
99
|
+
offset = size * position
|
100
|
+
offset -= size if @frame.current?
|
101
|
+
offset = 0 - offset if inverse
|
102
|
+
offset
|
103
|
+
end
|
104
|
+
end
|