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.
Files changed (56) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +22 -0
  3. data/Gemfile +4 -0
  4. data/LICENSE.txt +674 -0
  5. data/README.md +254 -0
  6. data/Rakefile +7 -0
  7. data/bin/slidefield +89 -0
  8. data/examples/complete/assets/K2.jpg +0 -0
  9. data/examples/complete/assets/gobi.jpg +0 -0
  10. data/examples/complete/assets/mount_everest.jpg +0 -0
  11. data/examples/complete/assets/sahara.jpg +0 -0
  12. data/examples/complete/main.sfp +7 -0
  13. data/examples/complete/slides/deserts.sfi +19 -0
  14. data/examples/complete/slides/mountains.sfi +25 -0
  15. data/examples/complete/templates.sfi +95 -0
  16. data/examples/complete/variables.sfi +6 -0
  17. data/examples/minimal/main.sfp +43 -0
  18. data/examples/minimal/ruby-logo.png +0 -0
  19. data/lib/slidefield/animator.rb +104 -0
  20. data/lib/slidefield/errors.rb +6 -0
  21. data/lib/slidefield/interpreter.rb +414 -0
  22. data/lib/slidefield/object_data.rb +78 -0
  23. data/lib/slidefield/object_manager.rb +29 -0
  24. data/lib/slidefield/object_rules.rb +79 -0
  25. data/lib/slidefield/objects/_base.rb +29 -0
  26. data/lib/slidefield/objects/_root.rb +10 -0
  27. data/lib/slidefield/objects/animation.rb +10 -0
  28. data/lib/slidefield/objects/debug.rb +18 -0
  29. data/lib/slidefield/objects/image.rb +47 -0
  30. data/lib/slidefield/objects/include.rb +9 -0
  31. data/lib/slidefield/objects/layout.rb +10 -0
  32. data/lib/slidefield/objects/rect.rb +44 -0
  33. data/lib/slidefield/objects/slide.rb +43 -0
  34. data/lib/slidefield/objects/song.rb +31 -0
  35. data/lib/slidefield/objects/text.rb +57 -0
  36. data/lib/slidefield/parser.rb +99 -0
  37. data/lib/slidefield/version.rb +3 -0
  38. data/lib/slidefield/viewer.rb +89 -0
  39. data/lib/slidefield.rb +27 -0
  40. data/slidefield.gemspec +27 -0
  41. data/test/helper.rb +11 -0
  42. data/test/resources/include_sub.sfp +1 -0
  43. data/test/resources/parse_error.sfp +1 -0
  44. data/test/resources/recursive_include.sfp +1 -0
  45. data/test/resources/sub/include_parent.sfp +1 -0
  46. data/test/resources/unclosed_object.sfp +2 -0
  47. data/test/resources/unknown_object.sfp +1 -0
  48. data/test/resources/wrong_template.sfp +4 -0
  49. data/test/test_animator.rb +244 -0
  50. data/test/test_examples.rb +29 -0
  51. data/test/test_interpreter.rb +1766 -0
  52. data/test/test_object_data.rb +108 -0
  53. data/test/test_object_manager.rb +48 -0
  54. data/test/test_object_rules.rb +87 -0
  55. data/test/test_parser.rb +408 -0
  56. 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,9 @@
1
+ module SlideField::ObjectRules
2
+ class Include < Base
3
+ def rules
4
+ property :source, :string
5
+
6
+ # don't call super
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,10 @@
1
+ module SlideField::ObjectRules
2
+ class Layout < Base
3
+ def rules
4
+ property :size, :point
5
+ property :fullscreen, :boolean, true
6
+
7
+ super
8
+ end
9
+ end
10
+ 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,3 @@
1
+ module SlideField
2
+ VERSION = "0.1"
3
+ 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'
@@ -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,11 @@
1
+ require 'slidefield'
2
+ require 'minitest/autorun'
3
+
4
+ # use awesome_print for objects diff
5
+ module MiniTest
6
+ module Assertions
7
+ def mu_pp(obj)
8
+ obj.awesome_inspect
9
+ end
10
+ end
11
+ end
@@ -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,2 @@
1
+ \slide {
2
+ variable = "value"
@@ -0,0 +1 @@
1
+ \this_object_does_not_exist
@@ -0,0 +1,4 @@
1
+ wrong_template = \slide {
2
+ % error does not exist
3
+ trigger = error
4
+ }