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,101 +1,102 @@
1
- module CyberarmEngine
2
- class BorderCanvas
3
- attr_reader :element, :top, :right, :bottom, :left
4
- def initialize(element:)
5
- @element = element
6
-
7
- @top = Background.new
8
- @right = Background.new
9
- @bottom = Background.new
10
- @left = Background.new
11
- end
12
-
13
- def color=(color)
14
- if color.is_a?(Numeric)
15
- @top.background = color
16
- @right.background = color
17
- @bottom.background = color
18
- @left.background = color
19
-
20
- elsif color.is_a?(Gosu::Color)
21
- @top.background = color
22
- @right.background = color
23
- @bottom.background = color
24
- @left.background = color
25
-
26
- elsif color.is_a?(Array)
27
- if color.size == 1
28
- color=color.first
29
-
30
- elsif color.size == 2
31
- @top.background = color.first
32
- @right.background = color.first
33
- @bottom.background = color.last
34
- @left.background = color.last
35
-
36
- elsif color.size == 4
37
- @top.background = color[0]
38
- @right.background = color[1]
39
- @bottom.background = color[2]
40
- @left.background = color[3]
41
- else
42
- raise ArgumentError, "color array was empty or had wrong number of elements (expected 2 or 4 elements)"
43
- end
44
-
45
- elsif color.is_a?(Hash)
46
- @top.background = color[:top]
47
- @right.background = color[:right]
48
- @bottom.background = color[:bottom]
49
- @left.background = color[:left]
50
- else
51
- raise ArgumentError, "color '#{color}' of type '#{color.class}' was not able to be processed"
52
- end
53
- end
54
-
55
- def draw
56
- @top.draw
57
- @right.draw
58
- @bottom.draw
59
- @left.draw
60
- end
61
-
62
- def update
63
- # TOP
64
- @top.x = @element.x# + @element.border_thickness_left
65
- @top.y = @element.y
66
- @top.z = @element.z
67
-
68
- @top.width = @element.width
69
- @top.height = @element.style.border_thickness_top
70
-
71
- # RIGHT
72
- @right.x = @element.x + @element.width
73
- @right.y = @element.y + @element.style.border_thickness_top
74
- @right.z = @element.z
75
-
76
- @right.width = -@element.style.border_thickness_right
77
- @right.height = @element.height - @element.style.border_thickness_top
78
-
79
- # BOTTOM
80
- @bottom.x = @element.x
81
- @bottom.y = @element.y + @element.height
82
- @bottom.z = @element.z
83
-
84
- @bottom.width = @element.width - @element.style.border_thickness_right
85
- @bottom.height = -@element.style.border_thickness_bottom
86
-
87
- # LEFT
88
- @left.x = @element.x
89
- @left.y = @element.y
90
- @left.z = @element.z
91
-
92
- @left.width = @element.style.border_thickness_left
93
- @left.height = @element.height - @element.style.border_thickness_bottom
94
-
95
- @top.update
96
- @right.update
97
- @bottom.update
98
- @left.update
99
- end
100
- end
101
- end
1
+ module CyberarmEngine
2
+ class BorderCanvas
3
+ attr_reader :element, :top, :right, :bottom, :left
4
+
5
+ def initialize(element:)
6
+ @element = element
7
+
8
+ @top = Background.new
9
+ @right = Background.new
10
+ @bottom = Background.new
11
+ @left = Background.new
12
+ end
13
+
14
+ def color=(color)
15
+ if color.is_a?(Numeric)
16
+ @top.background = color
17
+ @right.background = color
18
+ @bottom.background = color
19
+ @left.background = color
20
+
21
+ elsif color.is_a?(Gosu::Color)
22
+ @top.background = color
23
+ @right.background = color
24
+ @bottom.background = color
25
+ @left.background = color
26
+
27
+ elsif color.is_a?(Array)
28
+ if color.size == 1
29
+ color = color.first
30
+
31
+ elsif color.size == 2
32
+ @top.background = color.first
33
+ @right.background = color.first
34
+ @bottom.background = color.last
35
+ @left.background = color.last
36
+
37
+ elsif color.size == 4
38
+ @top.background = color[0]
39
+ @right.background = color[1]
40
+ @bottom.background = color[2]
41
+ @left.background = color[3]
42
+ else
43
+ raise ArgumentError, "color array was empty or had wrong number of elements (expected 2 or 4 elements)"
44
+ end
45
+
46
+ elsif color.is_a?(Hash)
47
+ @top.background = color[:top]
48
+ @right.background = color[:right]
49
+ @bottom.background = color[:bottom]
50
+ @left.background = color[:left]
51
+ else
52
+ raise ArgumentError, "color '#{color}' of type '#{color.class}' was not able to be processed"
53
+ end
54
+ end
55
+
56
+ def draw
57
+ @top.draw
58
+ @right.draw
59
+ @bottom.draw
60
+ @left.draw
61
+ end
62
+
63
+ def update
64
+ # TOP
65
+ @top.x = @element.x # + @element.border_thickness_left
66
+ @top.y = @element.y
67
+ @top.z = @element.z
68
+
69
+ @top.width = @element.width
70
+ @top.height = @element.style.border_thickness_top
71
+
72
+ # RIGHT
73
+ @right.x = @element.x + @element.width
74
+ @right.y = @element.y + @element.style.border_thickness_top
75
+ @right.z = @element.z
76
+
77
+ @right.width = -@element.style.border_thickness_right
78
+ @right.height = @element.height - @element.style.border_thickness_top
79
+
80
+ # BOTTOM
81
+ @bottom.x = @element.x
82
+ @bottom.y = @element.y + @element.height
83
+ @bottom.z = @element.z
84
+
85
+ @bottom.width = @element.width - @element.style.border_thickness_right
86
+ @bottom.height = -@element.style.border_thickness_bottom
87
+
88
+ # LEFT
89
+ @left.x = @element.x
90
+ @left.y = @element.y
91
+ @left.z = @element.z
92
+
93
+ @left.width = @element.style.border_thickness_left
94
+ @left.height = @element.height - @element.style.border_thickness_bottom
95
+
96
+ @top.update
97
+ @right.update
98
+ @bottom.update
99
+ @left.update
100
+ end
101
+ end
102
+ end
@@ -1,99 +1,138 @@
1
- module CyberarmEngine
2
- module DSL
3
- def flow(options = {}, &block)
4
- container(CyberarmEngine::Element::Flow, options, &block)
5
- end
6
-
7
- def stack(options = {}, &block)
8
- container(CyberarmEngine::Element::Stack, options, &block)
9
- end
10
-
11
- def label(text, options = {}, &block)
12
- options[:parent] = element_parent
13
- options[:theme] = current_theme
14
-
15
- add_element( Element::Label.new(text, options, block) )
16
- end
17
-
18
- def button(text, options = {}, &block)
19
- options[:parent] = element_parent
20
- options[:theme] = current_theme
21
-
22
- add_element( Element::Button.new(text, options, block) { if block.is_a?(Proc); block.call; end } )
23
- end
24
-
25
- def edit_line(text, options = {}, &block)
26
- options[:parent] = element_parent
27
- options[:theme] = current_theme
28
-
29
- add_element( Element::EditLine.new(text, options, block) )
30
- end
31
-
32
- def toggle_button(options = {}, &block)
33
- options[:parent] = element_parent
34
- options[:theme] = current_theme
35
-
36
- add_element( Element::ToggleButton.new(options, block) )
37
- end
38
-
39
- def check_box(text, options = {}, &block)
40
- options[:parent] = element_parent
41
- options[:theme] = current_theme
42
-
43
- add_element( Element::CheckBox.new(text, options, block) )
44
- end
45
-
46
- def image(path, options = {}, &block)
47
- options[:parent] = element_parent
48
- options[:theme] = current_theme
49
-
50
- add_element( Element::Image.new(path, options, block) )
51
- end
52
-
53
- def progress(options = {}, &block)
54
- options[:parent] = element_parent
55
- options[:theme] = current_theme
56
-
57
- add_element( Element::Progress.new(options, block) )
58
- end
59
-
60
- def background(color = Gosu::Color::NONE)
61
- element_parent.style.background = color
62
- end
63
-
64
- def theme(theme)
65
- element_parent.options[:theme] = theme
66
- end
67
-
68
- def current_theme
69
- element_parent.options[:theme]
70
- end
71
-
72
- private def add_element(element)
73
- element_parent.add(element)
74
-
75
- return element
76
- end
77
-
78
- private def element_parent
79
- $__current_container__
80
- end
81
-
82
- private def container(klass, options = {}, &block)
83
- options[:parent] = element_parent
84
- options[:theme] = current_theme
85
-
86
- _container = klass.new(options, block)
87
-
88
- old_parent = element_parent
89
- $__current_container__ = _container
90
-
91
- _container.build
92
- _container.parent.add(_container)
93
-
94
- $__current_container__ = old_parent
95
-
96
- return _container
97
- end
98
- end
99
- end
1
+ module CyberarmEngine
2
+ module DSL
3
+ def flow(options = {}, &block)
4
+ container(CyberarmEngine::Element::Flow, options, &block)
5
+ end
6
+
7
+ def stack(options = {}, &block)
8
+ container(CyberarmEngine::Element::Stack, options, &block)
9
+ end
10
+
11
+ # TODO: Remove in version 0.16.0+
12
+ def label(text, options = {}, &block)
13
+ options[:parent] = element_parent
14
+ options[:theme] = current_theme
15
+
16
+ add_element(Element::TextBlock.new(text, options, block))
17
+ end
18
+
19
+ [
20
+ "Banner",
21
+ "Title",
22
+ "Subtitle",
23
+ "Tagline",
24
+ "Caption",
25
+ "Para",
26
+ "Inscription"
27
+ ].each do |const|
28
+ define_method(:"#{const.downcase}") do |text, options = {}, &block|
29
+ options[:parent] = element_parent
30
+ options[:theme] = current_theme
31
+
32
+ add_element(Element.const_get(const).new(text, options, block))
33
+ end
34
+ end
35
+
36
+ def button(text, options = {}, &block)
37
+ options[:parent] = element_parent
38
+ options[:theme] = current_theme
39
+
40
+ add_element(Element::Button.new(text, options, block) { block.call if block.is_a?(Proc) })
41
+ end
42
+
43
+ def list_box(options = {}, &block)
44
+ options[:parent] = element_parent
45
+ options[:theme] = current_theme
46
+
47
+ add_element(Element::ListBox.new(options, block) { block.call if block.is_a?(Proc) })
48
+ end
49
+
50
+ def edit_line(text, options = {}, &block)
51
+ options[:parent] = element_parent
52
+ options[:theme] = current_theme
53
+
54
+ add_element(Element::EditLine.new(text, options, block))
55
+ end
56
+
57
+ def edit_box(text, options = {}, &block)
58
+ options[:parent] = element_parent
59
+ options[:theme] = current_theme
60
+
61
+ add_element(Element::EditBox.new(text, options, block))
62
+ end
63
+
64
+ def toggle_button(options = {}, &block)
65
+ options[:parent] = element_parent
66
+ options[:theme] = current_theme
67
+
68
+ add_element(Element::ToggleButton.new(options, block))
69
+ end
70
+
71
+ def check_box(text, options = {}, &block)
72
+ options[:parent] = element_parent
73
+ options[:theme] = current_theme
74
+
75
+ add_element(Element::CheckBox.new(text, options, block))
76
+ end
77
+
78
+ def image(path, options = {}, &block)
79
+ options[:parent] = element_parent
80
+ options[:theme] = current_theme
81
+
82
+ add_element(Element::Image.new(path, options, block))
83
+ end
84
+
85
+ def progress(options = {}, &block)
86
+ options[:parent] = element_parent
87
+ options[:theme] = current_theme
88
+
89
+ add_element(Element::Progress.new(options, block))
90
+ end
91
+
92
+ def slider(options = {}, &block)
93
+ options[:parent] = element_parent
94
+ options[:theme] = current_theme
95
+
96
+ add_element(Element::Slider.new(options, block))
97
+ end
98
+
99
+ def background(color = Gosu::Color::NONE)
100
+ element_parent.style.background = color
101
+ end
102
+
103
+ def theme(theme)
104
+ element_parent.options[:theme] = theme
105
+ end
106
+
107
+ def current_theme
108
+ element_parent.options[:theme]
109
+ end
110
+
111
+ private def add_element(element)
112
+ element_parent.add(element)
113
+
114
+ element
115
+ end
116
+
117
+ private def element_parent
118
+ $__current_container__
119
+ end
120
+
121
+ private def container(klass, options = {}, &block)
122
+ options[:parent] = element_parent
123
+ options[:theme] = current_theme
124
+
125
+ _container = klass.new(options, block)
126
+
127
+ old_parent = element_parent
128
+ $__current_container__ = _container
129
+
130
+ _container.build
131
+ _container.parent.add(_container)
132
+
133
+ $__current_container__ = old_parent
134
+
135
+ _container
136
+ end
137
+ end
138
+ end
@@ -1,276 +1,315 @@
1
- module CyberarmEngine
2
- class Element
3
- include Theme
4
- include Event
5
- include Common
6
-
7
- attr_accessor :x, :y, :z, :enabled
8
- attr_reader :parent, :options, :style, :event_handler, :background_canvas, :border_canvas
9
-
10
- def initialize(options = {}, block = nil)
11
- @parent = options.delete(:parent) # parent Container (i.e. flow/stack)
12
- options = theme_defaults(options)
13
- @options = options
14
- @block = block
15
-
16
- @focus = false
17
- @enabled = true
18
- @visible = true
19
-
20
- @style = Style.new(options)
21
-
22
- @x = @style.x
23
- @y = @style.y
24
- @z = @style.z
25
-
26
- @width = 0
27
- @height = 0
28
-
29
- @fixed_x = @x if @x != 0
30
- @fixed_y = @y if @y != 0
31
-
32
- @style.width = default(:width) || nil
33
- @style.height = default(:height) || nil
34
-
35
- @style.background_canvas = Background.new
36
- @style.border_canvas = BorderCanvas.new(element: self)
37
-
38
- stylize
39
-
40
- default_events
41
- end
42
-
43
- def stylize
44
- set_border_thickness(@style.border_thickness)
45
-
46
- set_padding(@style.padding)
47
-
48
- set_margin(@style.margin)
49
-
50
- set_background(@style.background)
51
- set_border_color(@style.border_color)
52
- end
53
-
54
- def set_background(background)
55
- @style.background = background
56
- @style.background_canvas.background = background
57
- end
58
-
59
- def set_border_thickness(border_thickness)
60
- @style.border_thickness = border_thickness
61
-
62
- @style.border_thickness_left = default(:border_thickness_left) || @style.border_thickness
63
- @style.border_thickness_right = default(:border_thickness_right) || @style.border_thickness
64
- @style.border_thickness_top = default(:border_thickness_top) || @style.border_thickness
65
- @style.border_thickness_bottom = default(:border_thickness_bottom) || @style.border_thickness
66
- end
67
-
68
- def set_border_color(color)
69
- @style.border_color = color
70
-
71
- @style.border_color_left = default(:border_color_left) || @style.border_color
72
- @style.border_color_right = default(:border_color_right) || @style.border_color
73
- @style.border_color_top = default(:border_color_top) || @style.border_color
74
- @style.border_color_bottom = default(:border_color_bottom) || @style.border_color
75
-
76
- @style.border_canvas.color = color
77
- end
78
-
79
- def set_padding(padding)
80
- @style.padding = padding
81
-
82
- @style.padding_left = default(:padding_left) || @style.padding
83
- @style.padding_right = default(:padding_right) || @style.padding
84
- @style.padding_top = default(:padding_top) || @style.padding
85
- @style.padding_bottom = default(:padding_bottom) || @style.padding
86
- end
87
-
88
- def set_margin(margin)
89
- @style.margin = margin
90
-
91
- @style.margin_left = default(:margin_left) || @style.margin
92
- @style.margin_right = default(:margin_right) || @style.margin
93
- @style.margin_top = default(:margin_top) || @style.margin
94
- @style.margin_bottom = default(:margin_bottom) || @style.margin
95
- end
96
-
97
- def default_events
98
- [:left, :middle, :right].each do |button|
99
- event(:"#{button}_mouse_button")
100
- event(:"released_#{button}_mouse_button")
101
- event(:"clicked_#{button}_mouse_button")
102
- event(:"holding_#{button}_mouse_button")
103
- end
104
-
105
- event(:mouse_wheel_up)
106
- event(:mouse_wheel_down)
107
-
108
- event(:enter)
109
- event(:hover)
110
- event(:leave)
111
-
112
- event(:blur)
113
- end
114
-
115
- def enabled?
116
- @enabled
117
- end
118
-
119
- def visible?
120
- @visible
121
- end
122
-
123
- def toggle
124
- @visible = !@visible
125
- root.gui_state.request_recalculate
126
- end
127
-
128
- def show
129
- @visible = true
130
- root.gui_state.request_recalculate
131
- end
132
-
133
- def hide
134
- @visible = false
135
- root.gui_state.request_recalculate
136
- end
137
-
138
- def draw
139
- return unless @visible
140
-
141
- @style.background_canvas.draw
142
- @style.border_canvas.draw
143
- render
144
- end
145
-
146
- def update
147
- end
148
-
149
- def button_down(id)
150
- end
151
-
152
- def button_up(id)
153
- end
154
-
155
- def render
156
- end
157
-
158
- def hit?(x, y)
159
- x.between?(@x, @x + width) &&
160
- y.between?(@y, @y + height)
161
- end
162
-
163
- def width
164
- if visible?
165
- inner_width + @width
166
- else
167
- 0
168
- end
169
- end
170
-
171
- def content_width
172
- @width
173
- end
174
-
175
- def noncontent_width
176
- (inner_width + outer_width) - width
177
- end
178
-
179
- def outer_width
180
- @style.margin_left + width + @style.margin_right
181
- end
182
-
183
- def inner_width
184
- (@style.border_thickness_left + @style.padding_left) + (@style.padding_right + @style.border_thickness_right)
185
- end
186
-
187
- def height
188
- if visible?
189
- inner_height + @height
190
- else
191
- 0
192
- end
193
- end
194
-
195
- def content_height
196
- @height
197
- end
198
-
199
- def noncontent_height
200
- (inner_height + outer_height) - height
201
- end
202
-
203
- def outer_height
204
- @style.margin_top + height + @style.margin_bottom
205
- end
206
-
207
- def inner_height
208
- (@style.border_thickness_top + @style.padding_top) + (@style.padding_bottom + @style.border_thickness_bottom)
209
- end
210
-
211
- private def dimensional_size(size, dimension)
212
- raise "dimension must be either :width or :height" unless dimension == :width || dimension == :height
213
- if size && size.is_a?(Numeric)
214
- if size.between?(0.0, 1.0)
215
- ((@parent.send(:"content_#{dimension}") - self.send(:"noncontent_#{dimension}") - 1) * size).round
216
- else
217
- size
218
- end
219
- else
220
- nil
221
- end
222
- end
223
-
224
- def background=(_background)
225
- @style.background_canvas.background=(_background)
226
- update_background
227
- end
228
-
229
- def update_background
230
- @style.background_canvas.x = @x
231
- @style.background_canvas.y = @y
232
- @style.background_canvas.z = @z
233
- @style.background_canvas.width = width
234
- @style.background_canvas.height = height
235
-
236
- @style.background_canvas.update
237
-
238
- @style.border_canvas.update
239
- end
240
-
241
- def root
242
- unless @root && @root.parent.nil?
243
- @root = parent
244
-
245
- loop do
246
- if @root.parent.nil?
247
- break
248
- else
249
- @root = @root.parent
250
- end
251
- end
252
- end
253
-
254
- @root
255
- end
256
-
257
- def is_root?
258
- @gui_state != nil
259
- end
260
-
261
- def recalculate
262
- raise "#{self.class}#recalculate was not overridden!"
263
- end
264
-
265
- def reposition
266
- end
267
-
268
- def value
269
- raise "#{self.class}#value was not overridden!"
270
- end
271
-
272
- def value=(value)
273
- raise "#{self.class}#value= was not overridden!"
274
- end
275
- end
276
- end
1
+ module CyberarmEngine
2
+ class Element
3
+ include Theme
4
+ include Event
5
+ include Common
6
+
7
+ attr_accessor :x, :y, :z, :enabled, :tip
8
+ attr_reader :parent, :options, :style, :event_handler, :background_canvas, :border_canvas
9
+
10
+ def initialize(options = {}, block = nil)
11
+ @parent = options.delete(:parent) # parent Container (i.e. flow/stack)
12
+ options = theme_defaults(options)
13
+ @options = options
14
+ @block = block
15
+
16
+ @focus = @options[:focus].nil? ? false : @options[:focus]
17
+ @enabled = @options[:enabled].nil? ? true : @options[:enabled]
18
+ @visible = @options[:visible].nil? ? true : @options[:visible]
19
+ @tip = @options[:tip] || ""
20
+
21
+ @style = Style.new(options)
22
+
23
+ @root ||= nil
24
+ @gui_state ||= nil
25
+
26
+ @x = @style.x
27
+ @y = @style.y
28
+ @z = @style.z
29
+
30
+ @width = 0
31
+ @height = 0
32
+
33
+ @style.width = default(:width) || nil
34
+ @style.height = default(:height) || nil
35
+
36
+ @style.background_canvas = Background.new
37
+ @style.border_canvas = BorderCanvas.new(element: self)
38
+
39
+ stylize
40
+
41
+ default_events
42
+ end
43
+
44
+ def stylize
45
+ set_static_position
46
+ set_border_thickness(@style.border_thickness)
47
+
48
+ set_padding(@style.padding)
49
+
50
+ set_margin(@style.margin)
51
+
52
+ set_background(@style.background)
53
+ set_border_color(@style.border_color)
54
+ end
55
+
56
+ def set_static_position
57
+ @x = @style.x if @style.x != 0
58
+ @y = @style.y if @style.y != 0
59
+ end
60
+
61
+ def set_background(background)
62
+ @style.background = background
63
+ @style.background_canvas.background = background
64
+ end
65
+
66
+ def set_border_thickness(border_thickness)
67
+ @style.border_thickness = border_thickness
68
+
69
+ @style.border_thickness_left = default(:border_thickness_left) || @style.border_thickness
70
+ @style.border_thickness_right = default(:border_thickness_right) || @style.border_thickness
71
+ @style.border_thickness_top = default(:border_thickness_top) || @style.border_thickness
72
+ @style.border_thickness_bottom = default(:border_thickness_bottom) || @style.border_thickness
73
+ end
74
+
75
+ def set_border_color(color)
76
+ @style.border_color = color
77
+
78
+ @style.border_color_left = default(:border_color_left) || @style.border_color
79
+ @style.border_color_right = default(:border_color_right) || @style.border_color
80
+ @style.border_color_top = default(:border_color_top) || @style.border_color
81
+ @style.border_color_bottom = default(:border_color_bottom) || @style.border_color
82
+
83
+ @style.border_canvas.color = color
84
+ end
85
+
86
+ def set_padding(padding)
87
+ @style.padding = padding
88
+
89
+ @style.padding_left = default(:padding_left) || @style.padding
90
+ @style.padding_right = default(:padding_right) || @style.padding
91
+ @style.padding_top = default(:padding_top) || @style.padding
92
+ @style.padding_bottom = default(:padding_bottom) || @style.padding
93
+ end
94
+
95
+ def set_margin(margin)
96
+ @style.margin = margin
97
+
98
+ @style.margin_left = default(:margin_left) || @style.margin
99
+ @style.margin_right = default(:margin_right) || @style.margin
100
+ @style.margin_top = default(:margin_top) || @style.margin
101
+ @style.margin_bottom = default(:margin_bottom) || @style.margin
102
+ end
103
+
104
+ def default_events
105
+ %i[left middle right].each do |button|
106
+ event(:"#{button}_mouse_button")
107
+ event(:"released_#{button}_mouse_button")
108
+ event(:"clicked_#{button}_mouse_button")
109
+ event(:"holding_#{button}_mouse_button")
110
+ end
111
+
112
+ event(:mouse_wheel_up)
113
+ event(:mouse_wheel_down)
114
+
115
+ event(:enter)
116
+ event(:hover)
117
+ event(:leave)
118
+
119
+ event(:blur)
120
+
121
+ event(:changed)
122
+ end
123
+
124
+ def enabled?
125
+ @enabled
126
+ end
127
+
128
+ def visible?
129
+ @visible
130
+ end
131
+
132
+ def toggle
133
+ @visible = !@visible
134
+ root.gui_state.request_recalculate
135
+ end
136
+
137
+ def show
138
+ bool = visible?
139
+ @visible = true
140
+ root.gui_state.request_recalculate unless bool
141
+ end
142
+
143
+ def hide
144
+ bool = visible?
145
+ @visible = false
146
+ root.gui_state.request_recalculate if bool
147
+ end
148
+
149
+ def draw
150
+ return unless visible?
151
+
152
+ @style.background_canvas.draw
153
+ @style.border_canvas.draw
154
+
155
+ Gosu.clip_to(@x, @y, width, height) do
156
+ render
157
+ end
158
+ end
159
+
160
+ def update
161
+ end
162
+
163
+ def button_down(id)
164
+ end
165
+
166
+ def button_up(id)
167
+ end
168
+
169
+ def draggable?(_button)
170
+ false
171
+ end
172
+
173
+ def render
174
+ end
175
+
176
+ def hit?(x, y)
177
+ x.between?(@x, @x + width) &&
178
+ y.between?(@y, @y + height)
179
+ end
180
+
181
+ def width
182
+ if visible?
183
+ inner_width + @width
184
+ else
185
+ 0
186
+ end
187
+ end
188
+
189
+ def content_width
190
+ @width
191
+ end
192
+
193
+ def noncontent_width
194
+ (inner_width + outer_width) - width
195
+ end
196
+
197
+ def outer_width
198
+ @style.margin_left + width + @style.margin_right
199
+ end
200
+
201
+ def inner_width
202
+ (@style.border_thickness_left + @style.padding_left) + (@style.padding_right + @style.border_thickness_right)
203
+ end
204
+
205
+ def height
206
+ if visible?
207
+ inner_height + @height
208
+ else
209
+ 0
210
+ end
211
+ end
212
+
213
+ def content_height
214
+ @height
215
+ end
216
+
217
+ def noncontent_height
218
+ (inner_height + outer_height) - height
219
+ end
220
+
221
+ def outer_height
222
+ @style.margin_top + height + @style.margin_bottom
223
+ end
224
+
225
+ def inner_height
226
+ (@style.border_thickness_top + @style.padding_top) + (@style.padding_bottom + @style.border_thickness_bottom)
227
+ end
228
+
229
+ def scroll_width
230
+ @children.sum { |c| c.width } + noncontent_width
231
+ end
232
+
233
+ def scroll_height
234
+ @children.sum { |c| c.height } + noncontent_height
235
+ end
236
+
237
+ def max_scroll_width
238
+ scroll_width - width
239
+ end
240
+
241
+ def max_scroll_height
242
+ scroll_height - height
243
+ end
244
+
245
+ def dimensional_size(size, dimension)
246
+ raise "dimension must be either :width or :height" unless %i[width height].include?(dimension)
247
+
248
+ if size && size.is_a?(Numeric)
249
+ if size.between?(0.0, 1.0)
250
+ ((@parent.send(:"content_#{dimension}") - send(:"noncontent_#{dimension}")) * size).round
251
+ else
252
+ size
253
+ end
254
+ end
255
+ end
256
+
257
+ def background=(_background)
258
+ @style.background_canvas.background = (_background)
259
+ update_background
260
+ end
261
+
262
+ def update_background
263
+ @style.background_canvas.x = @x
264
+ @style.background_canvas.y = @y
265
+ @style.background_canvas.z = @z
266
+ @style.background_canvas.width = width
267
+ @style.background_canvas.height = height
268
+
269
+ @style.background_canvas.update
270
+
271
+ @style.border_canvas.update
272
+ end
273
+
274
+ def root
275
+ return self if is_root?
276
+
277
+ unless @root && @root.parent.nil?
278
+ @root = parent
279
+
280
+ loop do
281
+ if @root.parent.nil?
282
+ break
283
+ else
284
+ @root = @root.parent
285
+ end
286
+ end
287
+ end
288
+
289
+ @root
290
+ end
291
+
292
+ def is_root?
293
+ @gui_state != nil
294
+ end
295
+
296
+ def recalculate
297
+ raise "#{self.class}#recalculate was not overridden!"
298
+ end
299
+
300
+ def reposition
301
+ end
302
+
303
+ def value
304
+ raise "#{self.class}#value was not overridden!"
305
+ end
306
+
307
+ def value=(_value)
308
+ raise "#{self.class}#value= was not overridden!"
309
+ end
310
+
311
+ def to_s
312
+ "#{self.class} x=#{x} y=#{y} width=#{width} height=#{height} value=#{value.is_a?(String) ? "\"#{value}\"" : value}"
313
+ end
314
+ end
315
+ end