cyberarm_engine 0.13.0 → 0.17.0

Sign up to get free protection for your applications and to get access to all the features.
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