slidefield 0.1
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/.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
@@ -0,0 +1,47 @@
|
|
1
|
+
module SlideField::ObjectRules
|
2
|
+
class Image < GBase
|
3
|
+
def rules
|
4
|
+
property :source, :string
|
5
|
+
property :size, :point, [0,0]
|
6
|
+
property :color, :color, [255, 255, 255, 255]
|
7
|
+
|
8
|
+
super
|
9
|
+
end
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
module SlideField::ObjectManager
|
14
|
+
class Image < Base
|
15
|
+
def load
|
16
|
+
@x, @y = @obj.get :position
|
17
|
+
@z = @obj.get :z_order
|
18
|
+
@color = Gosu::Color.rgba *@obj.get(:color)
|
19
|
+
|
20
|
+
source = File.expand_path @obj.get(:source), @obj.include_path
|
21
|
+
width, height = @obj.get :size
|
22
|
+
|
23
|
+
@image = Gosu::Image.new @window, source, true
|
24
|
+
width = @image.width if 0 == width
|
25
|
+
height = @image.height if 0 == height
|
26
|
+
|
27
|
+
@x_scale = width / @image.width.to_f
|
28
|
+
@y_scale = height / @image.height.to_f
|
29
|
+
end
|
30
|
+
|
31
|
+
def draw(animator)
|
32
|
+
tr = animator.transform @obj
|
33
|
+
return if tr.skip_draw?
|
34
|
+
|
35
|
+
x = @x + tr.x_offset
|
36
|
+
y = @y + tr.y_offset
|
37
|
+
|
38
|
+
x_scale = tr.scale * @x_scale
|
39
|
+
y_scale = tr.scale * @y_scale
|
40
|
+
|
41
|
+
color = @color.dup
|
42
|
+
color.alpha = tr.opacity * @color.alpha
|
43
|
+
|
44
|
+
@image.draw x, y, @z, x_scale, y_scale, color
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
module SlideField::ObjectRules
|
2
|
+
class Rect < GBase
|
3
|
+
def rules
|
4
|
+
property :size, :point
|
5
|
+
property :fill, :color, [255, 255, 255, 255]
|
6
|
+
|
7
|
+
super
|
8
|
+
end
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
module SlideField::ObjectManager
|
13
|
+
class Rect < Base
|
14
|
+
def load
|
15
|
+
@x, @y = @obj.get :position
|
16
|
+
@z = @obj.get :z_order
|
17
|
+
|
18
|
+
@width, @height = @obj.get :size
|
19
|
+
@fill = Gosu::Color.rgba *@obj.get(:fill)
|
20
|
+
end
|
21
|
+
|
22
|
+
def draw(animator)
|
23
|
+
tr = animator.transform @obj
|
24
|
+
return if tr.skip_draw?
|
25
|
+
|
26
|
+
x = @x + tr.x_offset
|
27
|
+
y = @y + tr.y_offset
|
28
|
+
|
29
|
+
width = @width * tr.scale
|
30
|
+
height = @height * tr.scale
|
31
|
+
|
32
|
+
color = @fill.dup
|
33
|
+
color.alpha = tr.opacity * @fill.alpha
|
34
|
+
|
35
|
+
@window.draw_quad(
|
36
|
+
x, y, color,
|
37
|
+
width + x, y, color,
|
38
|
+
x, height + y, color,
|
39
|
+
width + x, height + y, color,
|
40
|
+
@z
|
41
|
+
)
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
module SlideField::ObjectRules
|
2
|
+
class Slide < SBase; end
|
3
|
+
end
|
4
|
+
|
5
|
+
module SlideField::ObjectManager
|
6
|
+
class Slide < Base
|
7
|
+
def load
|
8
|
+
@children = []
|
9
|
+
add_children_of @obj
|
10
|
+
|
11
|
+
forward :load
|
12
|
+
end
|
13
|
+
|
14
|
+
def activate
|
15
|
+
forward :activate
|
16
|
+
end
|
17
|
+
|
18
|
+
def draw(animator)
|
19
|
+
forward :draw, animator
|
20
|
+
end
|
21
|
+
|
22
|
+
def deactivate
|
23
|
+
forward :deactivate
|
24
|
+
end
|
25
|
+
|
26
|
+
def unload
|
27
|
+
forward :unload
|
28
|
+
end
|
29
|
+
|
30
|
+
private
|
31
|
+
def add_children_of(obj)
|
32
|
+
obj.children.each {|c|
|
33
|
+
manager = SlideField::ObjectManager.new c, @window
|
34
|
+
@children << manager if manager
|
35
|
+
add_children_of c
|
36
|
+
}
|
37
|
+
end
|
38
|
+
|
39
|
+
def forward(event, *args)
|
40
|
+
@children.each {|c| c.execute event, *args }
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
module SlideField::ObjectRules
|
2
|
+
class Song < SBase
|
3
|
+
def rules
|
4
|
+
property :source, :string
|
5
|
+
property :volume, :integer, 100
|
6
|
+
property :loop, :boolean, true
|
7
|
+
|
8
|
+
super
|
9
|
+
end
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
module SlideField::ObjectManager
|
14
|
+
class Song < Base
|
15
|
+
def load
|
16
|
+
source = File.expand_path @obj.get(:source), @obj.include_path
|
17
|
+
@loop = @obj.get(:loop)
|
18
|
+
@volume = @obj.get(:volume) / 100.0
|
19
|
+
|
20
|
+
@song = Gosu::Sample.new @window, source
|
21
|
+
end
|
22
|
+
|
23
|
+
def activate
|
24
|
+
@instance = @song.play @volume, 1, @loop
|
25
|
+
end
|
26
|
+
|
27
|
+
def deactivate
|
28
|
+
@instance.stop
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,57 @@
|
|
1
|
+
module SlideField::ObjectRules
|
2
|
+
class Text < GBase
|
3
|
+
def rules
|
4
|
+
property :content, :string
|
5
|
+
property :color, :color, [255, 255, 255, 255]
|
6
|
+
property :font, :string, "sans"
|
7
|
+
property :height, :integer, 20
|
8
|
+
property :width, :integer, 0
|
9
|
+
property :spacing, :integer, 0
|
10
|
+
property :align, :string, "left"
|
11
|
+
|
12
|
+
super
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
module SlideField::ObjectManager
|
18
|
+
class Text < Base
|
19
|
+
def load
|
20
|
+
@x, @y = @obj.get :position
|
21
|
+
@z = @obj.get :z_order
|
22
|
+
@color = Gosu::Color.rgba *@obj.get(:color)
|
23
|
+
|
24
|
+
content = @obj.get :content
|
25
|
+
font = @obj.get :font
|
26
|
+
height = @obj.get :height
|
27
|
+
spacing = @obj.get :spacing
|
28
|
+
width = @obj.get :width
|
29
|
+
align = @obj.get(:align).to_sym
|
30
|
+
|
31
|
+
if font.include? '/'
|
32
|
+
font = File.expand_path font, @obj.include_path
|
33
|
+
end
|
34
|
+
|
35
|
+
if width < 1
|
36
|
+
# automatic width
|
37
|
+
temp = Gosu::Image.from_text @window, content, font, height
|
38
|
+
width = temp.width
|
39
|
+
end
|
40
|
+
|
41
|
+
@image = Gosu::Image.from_text @window, content, font, height, spacing, width, align
|
42
|
+
end
|
43
|
+
|
44
|
+
def draw(animator)
|
45
|
+
tr = animator.transform @obj
|
46
|
+
return if tr.skip_draw?
|
47
|
+
|
48
|
+
x = @x + tr.x_offset
|
49
|
+
y = @y + tr.y_offset
|
50
|
+
|
51
|
+
color = @color.dup
|
52
|
+
color.alpha = tr.opacity * @color.alpha
|
53
|
+
|
54
|
+
@image.draw x, y, @z, tr.scale, tr.scale, color
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
@@ -0,0 +1,99 @@
|
|
1
|
+
class SlideField::Parser < Parslet::Parser
|
2
|
+
rule(:space) { match["\x20\t"] }
|
3
|
+
rule(:spaces?) { space.repeat }
|
4
|
+
rule(:inline_spaces?) { (space | any_comment).repeat }
|
5
|
+
rule(:multi_spaces?) { (match('\s') | any_comment).repeat }
|
6
|
+
|
7
|
+
rule(:eof) { any.absent? }
|
8
|
+
rule(:crlf) { match['\r\n'].repeat(1) }
|
9
|
+
rule(:separator) { str(';') | crlf | eof }
|
10
|
+
rule(:line_comment) { str('%') >> str('{').absent? >> (crlf.absent? >> any).repeat }
|
11
|
+
rule(:multi_comment) { str('%{') >> (str('%}').absent? >> any).repeat >> str('%}') }
|
12
|
+
rule(:any_comment) { multi_comment | line_comment }
|
13
|
+
|
14
|
+
rule(:open) { multi_spaces? >> str('{') >> multi_spaces? }
|
15
|
+
rule(:close) { multi_spaces? >> str('}') }
|
16
|
+
|
17
|
+
rule(:assign) { str('=') }
|
18
|
+
rule(:add) { str('+=') }
|
19
|
+
rule(:subtract) { str('-=') }
|
20
|
+
rule(:multiply) { str('*=') }
|
21
|
+
rule(:divide) { str('/=') }
|
22
|
+
rule(:operator) {
|
23
|
+
inline_spaces? >> (
|
24
|
+
assign |
|
25
|
+
add |
|
26
|
+
subtract |
|
27
|
+
multiply |
|
28
|
+
divide
|
29
|
+
).as(:operator) >>
|
30
|
+
inline_spaces?
|
31
|
+
}
|
32
|
+
|
33
|
+
rule(:identifier) { match['a-zA-Z_'] >> match['a-zA-Z0-9_'].repeat }
|
34
|
+
rule(:integer) { str('-').maybe >> match('\\d').repeat(1) }
|
35
|
+
rule(:point) { integer >> str('x') >> integer }
|
36
|
+
rule(:color) { str('#') >> match['a-fA-F0-9'].repeat(8, 8) }
|
37
|
+
rule(:boolean) { str(':') >> (str('true') | str('false')) }
|
38
|
+
rule(:string) {
|
39
|
+
str('"') >> (
|
40
|
+
(str('\\') >> any) |
|
41
|
+
(str('"').absent? >> any)
|
42
|
+
).repeat >>
|
43
|
+
str('"')
|
44
|
+
}
|
45
|
+
|
46
|
+
rule(:filter) {
|
47
|
+
str('(') >> spaces? >> (
|
48
|
+
identifier.as(:name)
|
49
|
+
) >>
|
50
|
+
spaces? >> str(')') >>
|
51
|
+
inline_spaces?
|
52
|
+
}
|
53
|
+
rule(:value) {
|
54
|
+
filter.repeat.as(:filters) >>
|
55
|
+
(
|
56
|
+
identifier.as(:identifier) |
|
57
|
+
string.as(:string) |
|
58
|
+
point.as(:point) |
|
59
|
+
integer.as(:integer) |
|
60
|
+
color.as(:color) |
|
61
|
+
boolean.as(:boolean) |
|
62
|
+
object.as(:object)
|
63
|
+
)
|
64
|
+
}
|
65
|
+
|
66
|
+
rule(:assignment) { identifier.as(:variable) >> operator >> value.as(:value) }
|
67
|
+
rule(:object) {
|
68
|
+
str('\\') >>
|
69
|
+
str('&').as(:template).maybe >>
|
70
|
+
identifier.as(:type) >>
|
71
|
+
inline_spaces? >>
|
72
|
+
value.as(:value).maybe >>
|
73
|
+
(
|
74
|
+
open >>
|
75
|
+
statements.as(:body) >>
|
76
|
+
close
|
77
|
+
).maybe
|
78
|
+
}
|
79
|
+
|
80
|
+
rule(:expression) {
|
81
|
+
(
|
82
|
+
object.as(:object) |
|
83
|
+
assignment.as(:assignment)
|
84
|
+
) >>
|
85
|
+
inline_spaces? >>
|
86
|
+
separator
|
87
|
+
}
|
88
|
+
rule(:statement) {
|
89
|
+
spaces? >>
|
90
|
+
(
|
91
|
+
expression |
|
92
|
+
any_comment |
|
93
|
+
crlf
|
94
|
+
)
|
95
|
+
}
|
96
|
+
rule(:statements) { statement.repeat }
|
97
|
+
|
98
|
+
root(:statements)
|
99
|
+
end
|
@@ -0,0 +1,89 @@
|
|
1
|
+
class SlideField::Viewer < Gosu::Window
|
2
|
+
def initialize(project)
|
3
|
+
layout = project[:layout].first
|
4
|
+
layout_size = layout.get :size
|
5
|
+
fullscreen = layout.get :fullscreen
|
6
|
+
|
7
|
+
super *layout_size, fullscreen
|
8
|
+
|
9
|
+
@animator = SlideField::Animator.new layout_size
|
10
|
+
|
11
|
+
@slides = []
|
12
|
+
project[:slide].each {|slide_data|
|
13
|
+
manager = SlideField::ObjectManager.new slide_data, self
|
14
|
+
manager.load
|
15
|
+
@slides << manager
|
16
|
+
}
|
17
|
+
|
18
|
+
change_slide 0
|
19
|
+
end
|
20
|
+
|
21
|
+
def update
|
22
|
+
@time = Gosu::milliseconds
|
23
|
+
end
|
24
|
+
|
25
|
+
def draw
|
26
|
+
@animator.frame @time, true, @forward do
|
27
|
+
@slides[@current].draw @animator
|
28
|
+
end
|
29
|
+
|
30
|
+
# animate the previous slide
|
31
|
+
if @previous && @animator.need_redraw?
|
32
|
+
@animator.frame @time, false, @forward do
|
33
|
+
@slides[@previous].draw @animator
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
def needs_redraw?
|
39
|
+
@animator.need_redraw?
|
40
|
+
end
|
41
|
+
|
42
|
+
def button_down(id)
|
43
|
+
case id
|
44
|
+
when Gosu::KbHome
|
45
|
+
change_slide 0
|
46
|
+
when Gosu::KbEnd
|
47
|
+
change_slide @slides.length-1
|
48
|
+
when
|
49
|
+
Gosu::KbReturn,
|
50
|
+
Gosu::KbSpace,
|
51
|
+
Gosu::KbTab,
|
52
|
+
Gosu::KbRight,
|
53
|
+
Gosu::KbDown,
|
54
|
+
Gosu::KbPageDown,
|
55
|
+
Gosu::KbNumpadAdd
|
56
|
+
|
57
|
+
change_slide @current+1
|
58
|
+
when
|
59
|
+
Gosu::KbBackspace,
|
60
|
+
Gosu::KbLeft,
|
61
|
+
Gosu::KbUp,
|
62
|
+
Gosu::KbPageUp,
|
63
|
+
Gosu::KbNumpadSubtract
|
64
|
+
|
65
|
+
change_slide @current-1
|
66
|
+
when Gosu::KbEscape, Gosu::KbQ
|
67
|
+
close
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
private
|
72
|
+
def change_slide(index)
|
73
|
+
return if @current == index || index < 0 || index > @slides.length-1
|
74
|
+
|
75
|
+
@previous = @current
|
76
|
+
@current = index
|
77
|
+
|
78
|
+
if @previous
|
79
|
+
@slides[@previous].deactivate
|
80
|
+
@forward = @previous < @current
|
81
|
+
else
|
82
|
+
@forward = true
|
83
|
+
end
|
84
|
+
|
85
|
+
@slides[@current].activate
|
86
|
+
|
87
|
+
@animator.reset
|
88
|
+
end
|
89
|
+
end
|
data/lib/slidefield.rb
ADDED
@@ -0,0 +1,27 @@
|
|
1
|
+
require 'slidefield/version'
|
2
|
+
|
3
|
+
require 'ap'
|
4
|
+
require 'gosu'
|
5
|
+
require 'parslet'
|
6
|
+
require 'pathname'
|
7
|
+
|
8
|
+
require 'slidefield/animator'
|
9
|
+
require 'slidefield/errors'
|
10
|
+
require 'slidefield/interpreter'
|
11
|
+
require 'slidefield/object_data'
|
12
|
+
require 'slidefield/object_manager'
|
13
|
+
require 'slidefield/object_rules'
|
14
|
+
require 'slidefield/parser'
|
15
|
+
require 'slidefield/viewer'
|
16
|
+
|
17
|
+
require 'slidefield/objects/_base.rb'
|
18
|
+
require 'slidefield/objects/_root.rb'
|
19
|
+
require 'slidefield/objects/animation.rb'
|
20
|
+
require 'slidefield/objects/debug.rb'
|
21
|
+
require 'slidefield/objects/image.rb'
|
22
|
+
require 'slidefield/objects/include.rb'
|
23
|
+
require 'slidefield/objects/layout.rb'
|
24
|
+
require 'slidefield/objects/rect.rb'
|
25
|
+
require 'slidefield/objects/slide.rb'
|
26
|
+
require 'slidefield/objects/song.rb'
|
27
|
+
require 'slidefield/objects/text.rb'
|
data/slidefield.gemspec
ADDED
@@ -0,0 +1,27 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path '../lib', __FILE__
|
3
|
+
$LOAD_PATH.unshift lib unless $LOAD_PATH.include? lib
|
4
|
+
require 'slidefield/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "slidefield"
|
8
|
+
spec.version = SlideField::VERSION
|
9
|
+
spec.authors = ["cfi30"]
|
10
|
+
spec.email = ["slidefield@cfillion.tk"]
|
11
|
+
spec.summary = %q{A presentation software that reads plain text files written in its own interpreted language.}
|
12
|
+
spec.homepage = ""
|
13
|
+
spec.license = "GPL"
|
14
|
+
|
15
|
+
spec.files = `git ls-files -z`.split "\x0"
|
16
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename f }
|
17
|
+
spec.test_files = spec.files.grep %r{^(test|spec|features)/}
|
18
|
+
spec.require_paths = ["lib"]
|
19
|
+
|
20
|
+
spec.add_development_dependency 'bundler', '~> 1.6'
|
21
|
+
spec.add_development_dependency 'minitest', '~> 5.3'
|
22
|
+
spec.add_development_dependency 'rake'
|
23
|
+
|
24
|
+
spec.add_runtime_dependency 'awesome_print', '~> 1.2'
|
25
|
+
spec.add_runtime_dependency 'gosu', '~> 0.7'
|
26
|
+
spec.add_runtime_dependency 'parslet', '~> 1.6'
|
27
|
+
end
|
data/test/helper.rb
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
\include "sub/include_parent.sfp"
|
@@ -0,0 +1 @@
|
|
1
|
+
"
|
@@ -0,0 +1 @@
|
|
1
|
+
\include "recursive_include.sfp"
|
@@ -0,0 +1 @@
|
|
1
|
+
\include "../unknown_object.sfp"
|
@@ -0,0 +1 @@
|
|
1
|
+
\this_object_does_not_exist
|