cyberarm_engine 0.13.0 → 0.17.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.
Files changed (73) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +8 -8
  3. data/.rubocop.yml +8 -0
  4. data/.travis.yml +5 -5
  5. data/Gemfile +6 -6
  6. data/LICENSE.txt +21 -21
  7. data/README.md +73 -43
  8. data/Rakefile +10 -10
  9. data/assets/textures/default.png +0 -0
  10. data/bin/console +14 -14
  11. data/bin/setup +8 -8
  12. data/cyberarm_engine.gemspec +39 -36
  13. data/lib/cyberarm_engine.rb +64 -47
  14. data/lib/cyberarm_engine/animator.rb +56 -54
  15. data/lib/cyberarm_engine/background.rb +179 -175
  16. data/lib/cyberarm_engine/background_nine_slice.rb +125 -0
  17. data/lib/cyberarm_engine/bounding_box.rb +150 -150
  18. data/lib/cyberarm_engine/cache.rb +4 -0
  19. data/lib/cyberarm_engine/cache/download_manager.rb +121 -0
  20. data/lib/cyberarm_engine/common.rb +96 -96
  21. data/lib/cyberarm_engine/config_file.rb +46 -0
  22. data/lib/cyberarm_engine/game_object.rb +248 -257
  23. data/lib/cyberarm_engine/game_state.rb +92 -89
  24. data/lib/cyberarm_engine/model.rb +207 -0
  25. data/lib/cyberarm_engine/model/material.rb +21 -0
  26. data/lib/cyberarm_engine/model/model_object.rb +131 -0
  27. data/lib/cyberarm_engine/model/parser.rb +74 -0
  28. data/lib/cyberarm_engine/model/parsers/collada_parser.rb +138 -0
  29. data/lib/cyberarm_engine/model/parsers/wavefront_parser.rb +154 -0
  30. data/lib/cyberarm_engine/model_cache.rb +31 -0
  31. data/lib/cyberarm_engine/opengl.rb +28 -0
  32. data/lib/cyberarm_engine/opengl/light.rb +50 -0
  33. data/lib/cyberarm_engine/opengl/orthographic_camera.rb +46 -0
  34. data/lib/cyberarm_engine/opengl/perspective_camera.rb +38 -0
  35. data/lib/cyberarm_engine/opengl/renderer/bounding_box_renderer.rb +249 -0
  36. data/lib/cyberarm_engine/opengl/renderer/g_buffer.rb +164 -0
  37. data/lib/cyberarm_engine/opengl/renderer/opengl_renderer.rb +289 -0
  38. data/lib/cyberarm_engine/opengl/renderer/renderer.rb +22 -0
  39. data/lib/cyberarm_engine/opengl/shader.rb +406 -0
  40. data/lib/cyberarm_engine/opengl/texture.rb +69 -0
  41. data/lib/cyberarm_engine/ray.rb +56 -56
  42. data/lib/cyberarm_engine/stats.rb +21 -0
  43. data/lib/cyberarm_engine/text.rb +160 -146
  44. data/lib/cyberarm_engine/timer.rb +23 -23
  45. data/lib/cyberarm_engine/transform.rb +296 -273
  46. data/lib/cyberarm_engine/ui/border_canvas.rb +102 -101
  47. data/lib/cyberarm_engine/ui/dsl.rb +138 -99
  48. data/lib/cyberarm_engine/ui/element.rb +315 -276
  49. data/lib/cyberarm_engine/ui/elements/button.rb +160 -67
  50. data/lib/cyberarm_engine/ui/elements/check_box.rb +51 -59
  51. data/lib/cyberarm_engine/ui/elements/container.rb +256 -176
  52. data/lib/cyberarm_engine/ui/elements/edit_box.rb +179 -0
  53. data/lib/cyberarm_engine/ui/elements/edit_line.rb +262 -172
  54. data/lib/cyberarm_engine/ui/elements/flow.rb +15 -17
  55. data/lib/cyberarm_engine/ui/elements/image.rb +72 -52
  56. data/lib/cyberarm_engine/ui/elements/label.rb +156 -50
  57. data/lib/cyberarm_engine/ui/elements/list_box.rb +82 -0
  58. data/lib/cyberarm_engine/ui/elements/progress.rb +51 -50
  59. data/lib/cyberarm_engine/ui/elements/radio.rb +6 -0
  60. data/lib/cyberarm_engine/ui/elements/slider.rb +104 -0
  61. data/lib/cyberarm_engine/ui/elements/stack.rb +11 -13
  62. data/lib/cyberarm_engine/ui/elements/text_block.rb +156 -0
  63. data/lib/cyberarm_engine/ui/elements/toggle_button.rb +65 -56
  64. data/lib/cyberarm_engine/ui/event.rb +47 -47
  65. data/lib/cyberarm_engine/ui/gui_state.rb +226 -135
  66. data/lib/cyberarm_engine/ui/style.rb +38 -37
  67. data/lib/cyberarm_engine/ui/theme.rb +182 -120
  68. data/lib/cyberarm_engine/vector.rb +293 -203
  69. data/lib/cyberarm_engine/version.rb +4 -4
  70. data/lib/cyberarm_engine/{engine.rb → window.rb} +114 -101
  71. metadata +88 -18
  72. data/lib/cyberarm_engine/gosu_ext/circle.rb +0 -9
  73. data/lib/cyberarm_engine/shader.rb +0 -262
@@ -1,17 +1,15 @@
1
- module CyberarmEngine
2
- class Element
3
- class Flow < Container
4
- include Common
5
-
6
- def layout
7
- @children.each do |child|
8
- if fits_on_line?(child)
9
- position_on_current_line(child)
10
- else
11
- position_on_next_line(child)
12
- end
13
- end
14
- end
15
- end
16
- end
17
- end
1
+ module CyberarmEngine
2
+ class Element
3
+ class Flow < Container
4
+ def layout
5
+ @children.each do |child|
6
+ if fits_on_line?(child)
7
+ position_on_current_line(child)
8
+ else
9
+ position_on_next_line(child)
10
+ end
11
+ end
12
+ end
13
+ end
14
+ end
15
+ end
@@ -1,52 +1,72 @@
1
- module CyberarmEngine
2
- class Element
3
- class Image < Element
4
- def initialize(path, options = {}, block = nil)
5
- super(options, block)
6
- @path = path
7
-
8
- @image = Gosu::Image.new(path, retro: @options[:image_retro])
9
- @scale_x, @scale_y = 1, 1
10
- end
11
-
12
- def render
13
- @image.draw(
14
- @style.border_thickness_left + @style.padding_left + @x,
15
- @style.border_thickness_top + @style.padding_top + @y,
16
- @z + 2,
17
- @scale_x, @scale_y) # TODO: Add color support?
18
- end
19
-
20
- def clicked_left_mouse_button(sender, x, y)
21
- @block.call(self) if @block
22
-
23
- return :handled
24
- end
25
-
26
- def recalculate
27
- _width = dimensional_size(@style.width, :width)
28
- _height= dimensional_size(@style.height,:height)
29
-
30
- if _width && _height
31
- @scale_x = _width.to_f / @image.width
32
- @scale_y = _height.to_f / @image.height
33
- elsif _width
34
- @scale_x = _width.to_f / @image.width
35
- @scale_y = @scale_x
36
- elsif _height
37
- @scale_y = _height.to_f / @image.height
38
- @scale_x = @scale_y
39
- else
40
- @scale_x, @scale_y = 1, 1
41
- end
42
-
43
- @width = _width ? _width : @image.width.round * @scale_x
44
- @height= _height ? _height : @image.height.round * @scale_y
45
- end
46
-
47
- def value
48
- @path
49
- end
50
- end
51
- end
52
- end
1
+ module CyberarmEngine
2
+ class Element
3
+ class Image < Element
4
+ def initialize(path_or_image, options = {}, block = nil)
5
+ super(options, block)
6
+ @path = path_or_image if path_or_image.is_a?(String)
7
+
8
+ @image = Gosu::Image.new(path_or_image, retro: @options[:retro], tileable: @options[:tileable]) if @path
9
+ @image = path_or_image unless @path
10
+
11
+ @scale_x = 1
12
+ @scale_y = 1
13
+ end
14
+
15
+ def render
16
+ @image.draw(
17
+ @style.border_thickness_left + @style.padding_left + @x,
18
+ @style.border_thickness_top + @style.padding_top + @y,
19
+ @z + 2,
20
+ @scale_x, @scale_y, @style.color
21
+ )
22
+ end
23
+
24
+ def clicked_left_mouse_button(_sender, _x, _y)
25
+ @block.call(self) if @block
26
+
27
+ :handled
28
+ end
29
+
30
+ def recalculate
31
+ _width = dimensional_size(@style.width, :width)
32
+ _height = dimensional_size(@style.height, :height)
33
+
34
+ if _width && _height
35
+ @scale_x = _width.to_f / @image.width
36
+ @scale_y = _height.to_f / @image.height
37
+ elsif _width
38
+ @scale_x = _width.to_f / @image.width
39
+ @scale_y = @scale_x
40
+ elsif _height
41
+ @scale_y = _height.to_f / @image.height
42
+ @scale_x = @scale_y
43
+ else
44
+ @scale_x = 1
45
+ @scale_y = 1
46
+ end
47
+
48
+ @width = _width || @image.width.round * @scale_x
49
+ @height = _height || @image.height.round * @scale_y
50
+
51
+ update_background
52
+ end
53
+
54
+ def value
55
+ @image
56
+ end
57
+
58
+ def value=(path_or_image, retro: false, tileable: false)
59
+ @path = path_or_image if path_or_image.is_a?(String)
60
+
61
+ @image = Gosu::Image.new(path_or_image, retro: retro, tileable: tileable) if @path
62
+ @image = path_or_image unless @path
63
+
64
+ recalculate
65
+ end
66
+
67
+ def path
68
+ @path
69
+ end
70
+ end
71
+ end
72
+ end
@@ -1,50 +1,156 @@
1
- module CyberarmEngine
2
- class Element
3
- class Label < Element
4
- def initialize(text, options = {}, block = nil)
5
- super(options, block)
6
-
7
- @text = Text.new(text, font: @options[:font], z: @z, color: @options[:color], size: @options[:text_size], shadow: @options[:text_shadow])
8
- end
9
-
10
- def render
11
- @text.draw
12
- end
13
-
14
- def clicked_left_mouse_button(sender, x, y)
15
- @block.call(self) if @block
16
-
17
- return :handled
18
- end
19
-
20
- def recalculate
21
- @width, @height = 0, 0
22
-
23
- _width = dimensional_size(@style.width, :width)
24
- _height= dimensional_size(@style.height,:height)
25
-
26
- @width = _width ? _width : @text.width.round
27
- @height= _height ? _height : @text.height.round
28
-
29
- @text.x = @style.border_thickness_left + @style.padding_left + @x
30
- @text.y = @style.border_thickness_top + @style.padding_top + @y
31
- @text.z = @z + 3
32
-
33
- update_background
34
- end
35
-
36
- def value
37
- @text.text
38
- end
39
-
40
- def value=(value)
41
- @text.text = value
42
-
43
- old_width, old_height = width, height
44
- recalculate
45
-
46
- root.gui_state.request_recalculate if old_width != width || old_height != height
47
- end
48
- end
49
- end
50
- end
1
+ module CyberarmEngine
2
+ class Element
3
+ class TextBlock < Element
4
+ def initialize(text, options = {}, block = nil)
5
+ super(options, block)
6
+
7
+ @text = Text.new(
8
+ text, font: @options[:font], z: @z, color: @options[:color],
9
+ size: @options[:text_size], shadow: @options[:text_shadow],
10
+ shadow_size: @options[:text_shadow_size],
11
+ shadow_color: @options[:text_shadow_color]
12
+ )
13
+
14
+ @raw_text = text
15
+ end
16
+
17
+ def render
18
+ @text.draw
19
+ end
20
+
21
+ def clicked_left_mouse_button(_sender, _x, _y)
22
+ @block&.call(self) if @enabled
23
+
24
+ # return :handled
25
+ end
26
+
27
+ def recalculate
28
+ @width = 0
29
+ @height = 0
30
+
31
+ _width = dimensional_size(@style.width, :width)
32
+ _height = dimensional_size(@style.height, :height)
33
+
34
+ handle_text_wrapping(_width)
35
+
36
+ @width = _width || @text.width.round
37
+ @height = _height || @text.height.round
38
+
39
+ @text.y = @style.border_thickness_top + @style.padding_top + @y
40
+ @text.z = @z + 3
41
+
42
+ if (text_alignment = @options[:text_align])
43
+ case text_alignment
44
+ when :left
45
+ @text.x = @style.border_thickness_left + @style.padding_left + @x
46
+ when :center
47
+ @text.x = if @text.width <= outer_width
48
+ @x + outer_width / 2 - @text.width / 2
49
+ else # Act as left aligned
50
+ @style.border_thickness_left + @style.padding_left + @x
51
+ end
52
+ when :right
53
+ @text.x = @x + outer_width - (@text.width + @style.border_thickness_right + @style.padding_right)
54
+ end
55
+ end
56
+
57
+ update_background
58
+ end
59
+
60
+ def handle_text_wrapping(max_width)
61
+ max_width ||= @parent&.width
62
+ max_width ||= @x - (window.width + noncontent_width)
63
+ wrap_behavior = style.text_wrap
64
+ copy = @raw_text.to_s.dup
65
+
66
+ if max_width >= line_width(copy[0]) && line_width(copy) > max_width && wrap_behavior != :none
67
+ breaks = []
68
+ line_start = 0
69
+ line_end = copy.length
70
+
71
+ while line_start != copy.length
72
+ if line_width(copy[line_start...line_end]) > max_width
73
+ line_end = ((line_end - line_start) / 2.0)
74
+ elsif line_end < copy.length && line_width(copy[line_start...line_end + 1]) < max_width
75
+ # To small, grow!
76
+ # TODO: find a more efficient way
77
+ line_end += 1
78
+
79
+ else # FOUND IT!
80
+ entering_line_end = line_end.floor
81
+ max_reach = line_end.floor - line_start < 63 ? line_end.floor - line_start : 63
82
+ reach = 0
83
+
84
+ if wrap_behavior == :word_wrap
85
+ max_reach.times do |i|
86
+ reach = i
87
+ break if copy[line_end.floor - i].to_s.match(/[[:punct:]]| /)
88
+ end
89
+
90
+ puts "Max width: #{max_width}/#{line_width(@raw_text)} Reach: {#{reach}/#{max_reach}} Line Start: #{line_start}/#{line_end.floor} (#{copy.length}|#{@raw_text.length}) [#{entering_line_end}] '#{copy}' {#{copy[line_start...line_end]}}"
91
+ line_end = line_end.floor - reach + 1 if reach != max_reach # Add +1 to walk in front of punctuation
92
+ end
93
+
94
+ breaks << line_end.floor
95
+ line_start = line_end.floor
96
+ line_end = copy.length
97
+
98
+ break if entering_line_end == copy.length || reach == max_reach
99
+ end
100
+ end
101
+
102
+ breaks.each_with_index do |pos, index|
103
+ copy.insert(pos + index, "\n") if pos + index >= 0 && pos + index < copy.length
104
+ end
105
+ end
106
+
107
+ @text.text = copy
108
+ end
109
+
110
+ def line_width(text)
111
+ (@x + @text.textobject.markup_width(text) + noncontent_width)
112
+ end
113
+
114
+ def value
115
+ @raw_text
116
+ end
117
+
118
+ def value=(value)
119
+ @raw_text = value.to_s.chomp
120
+
121
+ old_width = width
122
+ old_height = height
123
+ recalculate
124
+
125
+ root.gui_state.request_recalculate if old_width != width || old_height != height
126
+
127
+ publish(:changed, self.value)
128
+ end
129
+ end
130
+
131
+ class Banner < TextBlock
132
+ end
133
+
134
+ class Title < TextBlock
135
+ end
136
+
137
+ class Subtitle < TextBlock
138
+ end
139
+
140
+ class Tagline < TextBlock
141
+ end
142
+
143
+ class Caption < TextBlock
144
+ end
145
+
146
+ class Para < TextBlock
147
+ end
148
+
149
+ class Inscription < TextBlock
150
+ end
151
+
152
+ # TODO: Remove in version 0.16.0+
153
+ class Label < TextBlock
154
+ end
155
+ end
156
+ end
@@ -0,0 +1,82 @@
1
+ module CyberarmEngine
2
+ class Element
3
+ class ListBox < Button
4
+ attr_accessor :items
5
+ attr_reader :choose
6
+
7
+ def initialize(options = {}, block = nil)
8
+ @items = options[:items] || []
9
+ @choose = options[:choose] || @items.first
10
+
11
+ super(@choose, options, block)
12
+
13
+ @style.background_canvas.background = default(:background)
14
+
15
+ # TODO: "Clean Up" into own class?
16
+ @menu = Stack.new(parent: parent, width: @options[:width], theme: @options[:theme])
17
+ @menu.define_singleton_method(:recalculate_menu) do
18
+ @x = @__list_box.x
19
+ @y = @__list_box.y + @__list_box.height
20
+ end
21
+ @menu.instance_variable_set(:"@__list_box", self)
22
+
23
+ def @menu.recalculate
24
+ super
25
+
26
+ recalculate_menu
27
+ end
28
+
29
+ self.choose = @choose
30
+ end
31
+
32
+ def choose=(item)
33
+ valid = @items.detect { |i| i == item }
34
+ raise "Invalid value '#{item}' for choose, valid options were: #{@items.map { |i| "#{i.inspect}" }.join(", ")}" unless valid
35
+
36
+ @choose = item
37
+
38
+ self.value = item.to_s
39
+
40
+ recalculate
41
+ end
42
+
43
+ def released_left_mouse_button(_sender, _x, _y)
44
+ show_menu
45
+
46
+ :handled
47
+ end
48
+
49
+ def show_menu
50
+ @menu.clear
51
+
52
+ @items.each do |item|
53
+ btn = Button.new(
54
+ item,
55
+ {
56
+ parent: @menu,
57
+ width: 1.0,
58
+ theme: @options[:theme],
59
+ margin: 0,
60
+ border_color: 0x00ffffff
61
+ },
62
+ proc do
63
+ self.choose = item
64
+ @block&.call(item)
65
+ end
66
+ )
67
+
68
+ @menu.add(btn)
69
+ end
70
+ recalculate
71
+
72
+ root.gui_state.show_menu(@menu)
73
+ end
74
+
75
+ def recalculate
76
+ super
77
+
78
+ @menu.recalculate
79
+ end
80
+ end
81
+ end
82
+ end
@@ -1,50 +1,51 @@
1
- module CyberarmEngine
2
- class Element
3
- class Progress < Element
4
- def initialize(options = {}, block = nil)
5
- super(options, block)
6
-
7
- @fraction_background = Background.new(background: @style.fraction_background)
8
- self.value = options[:fraction] ? options[:fraction] : 0.0
9
- end
10
-
11
- def render
12
- @fraction_background.draw
13
- end
14
-
15
- def recalculate
16
- _width = dimensional_size(@style.width, :width)
17
- _height= dimensional_size(@style.height,:height)
18
- @width = _width
19
- @height= _height
20
-
21
- update_background
22
- end
23
-
24
- def update_background
25
- super
26
-
27
- @fraction_background.x = @style.border_thickness_left + @style.padding_left + @x
28
- @fraction_background.y = @style.border_thickness_top + @style.padding_top + @y
29
- @fraction_background.z = @z
30
- @fraction_background.width = @width * @fraction
31
- @fraction_background.height = @height
32
-
33
- @fraction_background.background = @style.fraction_background
34
- end
35
-
36
- def value
37
- @fraction
38
- end
39
-
40
- def value=(decimal)
41
- raise "value must be number" unless decimal.is_a?(Numeric)
42
-
43
- @fraction = decimal.clamp(0.0, 1.0)
44
- update_background
45
-
46
- return @fraction
47
- end
48
- end
49
- end
50
- end
1
+ module CyberarmEngine
2
+ class Element
3
+ class Progress < Element
4
+ def initialize(options = {}, block = nil)
5
+ super(options, block)
6
+
7
+ @fraction_background = Background.new(background: @style.fraction_background)
8
+ self.value = options[:fraction] || 0.0
9
+ end
10
+
11
+ def render
12
+ @fraction_background.draw
13
+ end
14
+
15
+ def recalculate
16
+ _width = dimensional_size(@style.width, :width)
17
+ _height = dimensional_size(@style.height, :height)
18
+ @width = _width
19
+ @height = _height
20
+
21
+ update_background
22
+ end
23
+
24
+ def update_background
25
+ super
26
+
27
+ @fraction_background.x = @style.border_thickness_left + @style.padding_left + @x
28
+ @fraction_background.y = @style.border_thickness_top + @style.padding_top + @y
29
+ @fraction_background.z = @z
30
+ @fraction_background.width = @width * @fraction
31
+ @fraction_background.height = @height
32
+
33
+ @fraction_background.background = @style.fraction_background
34
+ end
35
+
36
+ def value
37
+ @fraction
38
+ end
39
+
40
+ def value=(decimal)
41
+ raise "value must be number" unless decimal.is_a?(Numeric)
42
+
43
+ @fraction = decimal.clamp(0.0, 1.0)
44
+ update_background
45
+
46
+ publish(:changed, @fraction)
47
+ @fraction
48
+ end
49
+ end
50
+ end
51
+ end