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,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