cyberarm_engine 0.19.0 → 0.19.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (74) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +8 -8
  3. data/.rubocop.yml +7 -7
  4. data/.travis.yml +5 -5
  5. data/Gemfile +6 -6
  6. data/LICENSE.txt +21 -21
  7. data/README.md +74 -74
  8. data/Rakefile +10 -10
  9. data/bin/console +14 -14
  10. data/bin/setup +8 -8
  11. data/cyberarm_engine.gemspec +39 -39
  12. data/lib/cyberarm_engine/animator.rb +219 -219
  13. data/lib/cyberarm_engine/background.rb +179 -179
  14. data/lib/cyberarm_engine/background_nine_slice.rb +142 -142
  15. data/lib/cyberarm_engine/bounding_box.rb +150 -150
  16. data/lib/cyberarm_engine/builtin/intro_state.rb +130 -130
  17. data/lib/cyberarm_engine/cache/download_manager.rb +121 -121
  18. data/lib/cyberarm_engine/cache.rb +4 -4
  19. data/lib/cyberarm_engine/common.rb +113 -113
  20. data/lib/cyberarm_engine/config_file.rb +46 -46
  21. data/lib/cyberarm_engine/console/command.rb +157 -157
  22. data/lib/cyberarm_engine/console/commands/help_command.rb +43 -43
  23. data/lib/cyberarm_engine/console/subcommand.rb +99 -99
  24. data/lib/cyberarm_engine/console.rb +248 -248
  25. data/lib/cyberarm_engine/game_object.rb +248 -248
  26. data/lib/cyberarm_engine/game_state.rb +97 -97
  27. data/lib/cyberarm_engine/model/material.rb +21 -21
  28. data/lib/cyberarm_engine/model/model_object.rb +131 -131
  29. data/lib/cyberarm_engine/model/parser.rb +74 -74
  30. data/lib/cyberarm_engine/model/parsers/collada_parser.rb +138 -138
  31. data/lib/cyberarm_engine/model/parsers/wavefront_parser.rb +154 -154
  32. data/lib/cyberarm_engine/model.rb +212 -212
  33. data/lib/cyberarm_engine/model_cache.rb +31 -31
  34. data/lib/cyberarm_engine/opengl/light.rb +50 -50
  35. data/lib/cyberarm_engine/opengl/orthographic_camera.rb +46 -46
  36. data/lib/cyberarm_engine/opengl/perspective_camera.rb +38 -38
  37. data/lib/cyberarm_engine/opengl/renderer/bounding_box_renderer.rb +249 -249
  38. data/lib/cyberarm_engine/opengl/renderer/g_buffer.rb +164 -164
  39. data/lib/cyberarm_engine/opengl/renderer/opengl_renderer.rb +298 -298
  40. data/lib/cyberarm_engine/opengl/renderer/renderer.rb +22 -22
  41. data/lib/cyberarm_engine/opengl/shader.rb +406 -406
  42. data/lib/cyberarm_engine/opengl/texture.rb +69 -69
  43. data/lib/cyberarm_engine/opengl.rb +28 -28
  44. data/lib/cyberarm_engine/ray.rb +56 -56
  45. data/lib/cyberarm_engine/stats.rb +21 -21
  46. data/lib/cyberarm_engine/text.rb +197 -197
  47. data/lib/cyberarm_engine/timer.rb +23 -23
  48. data/lib/cyberarm_engine/transform.rb +296 -296
  49. data/lib/cyberarm_engine/ui/border_canvas.rb +102 -102
  50. data/lib/cyberarm_engine/ui/dsl.rb +139 -139
  51. data/lib/cyberarm_engine/ui/element.rb +488 -488
  52. data/lib/cyberarm_engine/ui/elements/button.rb +97 -97
  53. data/lib/cyberarm_engine/ui/elements/check_box.rb +54 -54
  54. data/lib/cyberarm_engine/ui/elements/container.rb +256 -256
  55. data/lib/cyberarm_engine/ui/elements/edit_box.rb +179 -179
  56. data/lib/cyberarm_engine/ui/elements/edit_line.rb +263 -263
  57. data/lib/cyberarm_engine/ui/elements/flow.rb +15 -15
  58. data/lib/cyberarm_engine/ui/elements/image.rb +72 -72
  59. data/lib/cyberarm_engine/ui/elements/list_box.rb +88 -82
  60. data/lib/cyberarm_engine/ui/elements/progress.rb +51 -51
  61. data/lib/cyberarm_engine/ui/elements/radio.rb +6 -6
  62. data/lib/cyberarm_engine/ui/elements/slider.rb +104 -104
  63. data/lib/cyberarm_engine/ui/elements/stack.rb +11 -11
  64. data/lib/cyberarm_engine/ui/elements/text_block.rb +162 -162
  65. data/lib/cyberarm_engine/ui/elements/toggle_button.rb +65 -65
  66. data/lib/cyberarm_engine/ui/event.rb +54 -54
  67. data/lib/cyberarm_engine/ui/gui_state.rb +256 -256
  68. data/lib/cyberarm_engine/ui/style.rb +49 -49
  69. data/lib/cyberarm_engine/ui/theme.rb +207 -207
  70. data/lib/cyberarm_engine/vector.rb +293 -293
  71. data/lib/cyberarm_engine/version.rb +4 -4
  72. data/lib/cyberarm_engine/window.rb +120 -120
  73. data/lib/cyberarm_engine.rb +71 -71
  74. metadata +3 -3
@@ -1,488 +1,488 @@
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
- @debug_color = @options[:debug_color].nil? ? Gosu::Color::RED : @options[:debug_color]
22
-
23
- @style = Style.new(options)
24
-
25
- @root ||= nil
26
- @gui_state ||= nil
27
-
28
- @x = @style.x
29
- @y = @style.y
30
- @z = @style.z
31
-
32
- @width = 0
33
- @height = 0
34
-
35
- @style.width = default(:width) || nil
36
- @style.height = default(:height) || nil
37
-
38
- @style.background_canvas = Background.new
39
- @style.background_nine_slice_canvas = BackgroundNineSlice.new
40
- @style.border_canvas = BorderCanvas.new(element: self)
41
-
42
- @style_event = :default
43
-
44
- stylize
45
-
46
- default_events
47
-
48
- root.gui_state.request_focus(self) if @options[:autofocus]
49
- end
50
-
51
- def stylize
52
- set_static_position
53
-
54
- set_padding
55
- set_margin
56
-
57
- set_background
58
- set_background_nine_slice
59
-
60
- set_border_thickness
61
- set_border_color
62
- end
63
-
64
- def safe_style_fetch(*args)
65
- @style.hash.dig(@style_event, *args) || @style.hash.dig(:default, *args) || default(*args)
66
- end
67
-
68
- def set_static_position
69
- @x = @style.x if @style.x != 0
70
- @y = @style.y if @style.y != 0
71
- end
72
-
73
- def set_background
74
- @style.background = safe_style_fetch(:background)
75
-
76
- @style.background_canvas.background = @style.background
77
- end
78
-
79
- def set_background_nine_slice
80
- @style.background_nine_slice = safe_style_fetch(:background_nine_slice)
81
-
82
- @style.background_nine_slice_mode = safe_style_fetch(:background_nine_slice_mode) || :stretch
83
- @style.background_nine_slice_color = safe_style_fetch(:background_nine_slice_color) || Gosu::Color::WHITE
84
- @style.background_nine_slice_canvas.color = @style.background_nine_slice_color
85
-
86
- @style.background_nine_slice_from_edge = safe_style_fetch(:background_nine_slice_from_edge)
87
-
88
- @style.background_nine_slice_left = safe_style_fetch(:background_nine_slice_left) || @style.background_nine_slice_from_edge
89
- @style.background_nine_slice_top = safe_style_fetch(:background_nine_slice_top) || @style.background_nine_slice_from_edge
90
- @style.background_nine_slice_right = safe_style_fetch(:background_nine_slice_right) || @style.background_nine_slice_from_edge
91
- @style.background_nine_slice_bottom = safe_style_fetch(:background_nine_slice_bottom) || @style.background_nine_slice_from_edge
92
- end
93
-
94
- def set_border_thickness
95
- @style.border_thickness = safe_style_fetch(:border_thickness)
96
-
97
- @style.border_thickness_left = safe_style_fetch(:border_thickness_left) || @style.border_thickness
98
- @style.border_thickness_right = safe_style_fetch(:border_thickness_right) || @style.border_thickness
99
- @style.border_thickness_top = safe_style_fetch(:border_thickness_top) || @style.border_thickness
100
- @style.border_thickness_bottom = safe_style_fetch(:border_thickness_bottom) || @style.border_thickness
101
- end
102
-
103
- def set_border_color
104
- @style.border_color = safe_style_fetch(:border_color)
105
-
106
- @style.border_color_left = safe_style_fetch(:border_color_left) || @style.border_color
107
- @style.border_color_right = safe_style_fetch(:border_color_right) || @style.border_color
108
- @style.border_color_top = safe_style_fetch(:border_color_top) || @style.border_color
109
- @style.border_color_bottom = safe_style_fetch(:border_color_bottom) || @style.border_color
110
-
111
- @style.border_canvas.color = [
112
- @style.border_color_top,
113
- @style.border_color_right,
114
- @style.border_color_bottom,
115
- @style.border_color_left
116
- ]
117
- end
118
-
119
- def set_padding
120
- @style.padding = safe_style_fetch(:padding)
121
-
122
- @style.padding_left = safe_style_fetch(:padding_left) || @style.padding
123
- @style.padding_right = safe_style_fetch(:padding_right) || @style.padding
124
- @style.padding_top = safe_style_fetch(:padding_top) || @style.padding
125
- @style.padding_bottom = safe_style_fetch(:padding_bottom) || @style.padding
126
- end
127
-
128
- def set_margin
129
- @style.margin = safe_style_fetch(:margin)
130
-
131
- @style.margin_left = safe_style_fetch(:margin_left) || @style.margin
132
- @style.margin_right = safe_style_fetch(:margin_right) || @style.margin
133
- @style.margin_top = safe_style_fetch(:margin_top) || @style.margin
134
- @style.margin_bottom = safe_style_fetch(:margin_bottom) || @style.margin
135
- end
136
-
137
- def update_styles(event = :default)
138
- old_width = width
139
- old_height = height
140
-
141
- _style = @style.send(event)
142
- @style_event = event
143
-
144
- if @text.is_a?(CyberarmEngine::Text)
145
- @text.color = _style&.dig(:color) || @style.default[:color]
146
- @text.swap_font(_style&.dig(:text_size) || @style.default[:text_size], _style&.dig(:font) || @style.default[:font])
147
- end
148
-
149
- return if self.is_a?(ToolTip)
150
-
151
- if old_width != width || old_height != height
152
- (root&.gui_state || @gui_state).request_recalculate
153
- else
154
- stylize
155
- end
156
- end
157
-
158
- def default_events
159
- %i[left middle right].each do |button|
160
- event(:"#{button}_mouse_button")
161
- event(:"released_#{button}_mouse_button")
162
- event(:"clicked_#{button}_mouse_button")
163
- event(:"holding_#{button}_mouse_button")
164
- end
165
-
166
- event(:mouse_wheel_up)
167
- event(:mouse_wheel_down)
168
-
169
- event(:enter)
170
- event(:hover)
171
- event(:leave)
172
-
173
- event(:focus)
174
- event(:blur)
175
-
176
- event(:changed)
177
- end
178
-
179
- def enter(_sender)
180
- @focus = false unless window.button_down?(Gosu::MsLeft)
181
-
182
- if !@enabled
183
- update_styles(:disabled)
184
- elsif @focus
185
- update_styles(:active)
186
- else
187
- update_styles(:hover)
188
- end
189
-
190
- :handled
191
- end
192
-
193
- def left_mouse_button(_sender, _x, _y)
194
- @focus = true
195
-
196
- unless @enabled
197
- update_styles(:disabled)
198
- else
199
- update_styles(:active)
200
- end
201
-
202
- window.current_state.focus = self
203
-
204
- :handled
205
- end
206
-
207
- def released_left_mouse_button(sender, _x, _y)
208
- enter(sender)
209
-
210
- :handled
211
- end
212
-
213
- def clicked_left_mouse_button(_sender, _x, _y)
214
- @block&.call(self) if @enabled && !self.is_a?(Container)
215
-
216
- :handled
217
- end
218
-
219
- def leave(_sender)
220
- if @enabled
221
- update_styles
222
- else
223
- update_styles(:disabled)
224
- end
225
-
226
- :handled
227
- end
228
-
229
- def blur(_sender)
230
- @focus = false
231
-
232
- if @enabled
233
- update_styles
234
- else
235
- update_styles(:disabled)
236
- end
237
-
238
- :handled
239
- end
240
-
241
- def enabled?
242
- @enabled
243
- end
244
-
245
- def visible?
246
- @visible
247
- end
248
-
249
- def toggle
250
- @visible = !@visible
251
- root.gui_state.request_recalculate
252
- end
253
-
254
- def show
255
- bool = visible?
256
- @visible = true
257
- root.gui_state.request_recalculate unless bool
258
- end
259
-
260
- def hide
261
- bool = visible?
262
- @visible = false
263
- root.gui_state.request_recalculate if bool
264
- end
265
-
266
- def draw
267
- return unless visible?
268
-
269
- @style.background_canvas.draw
270
- @style.background_nine_slice_canvas.draw
271
- @style.border_canvas.draw
272
-
273
- Gosu.clip_to(@x, @y, width, height) do
274
- render
275
- end
276
- end
277
-
278
- def debug_draw
279
- return if defined?(GUI_DEBUG_ONLY_ELEMENT) && self.class == GUI_DEBUG_ONLY_ELEMENT
280
-
281
- Gosu.draw_line(
282
- x, y, @debug_color,
283
- x + outer_width, y, @debug_color,
284
- Float::INFINITY
285
- )
286
- Gosu.draw_line(
287
- x + outer_width, y, @debug_color,
288
- x + outer_width, y + outer_height, @debug_color,
289
- Float::INFINITY
290
- )
291
- Gosu.draw_line(
292
- x + outer_width, y + outer_height, @debug_color,
293
- x, y + outer_height, @debug_color,
294
- Float::INFINITY
295
- )
296
- Gosu.draw_line(
297
- x, outer_height, @debug_color,
298
- x, y, @debug_color,
299
- Float::INFINITY
300
- )
301
- end
302
-
303
- def update
304
- end
305
-
306
- def button_down(id)
307
- end
308
-
309
- def button_up(id)
310
- end
311
-
312
- def draggable?(_button)
313
- false
314
- end
315
-
316
- def render
317
- end
318
-
319
- def hit?(x, y)
320
- x.between?(@x, @x + width) &&
321
- y.between?(@y, @y + height)
322
- end
323
-
324
- def width
325
- if visible?
326
- inner_width + @width
327
- else
328
- 0
329
- end
330
- end
331
-
332
- def content_width
333
- @width
334
- end
335
-
336
- def noncontent_width
337
- (inner_width + outer_width) - width
338
- end
339
-
340
- def outer_width
341
- @style.margin_left + width + @style.margin_right
342
- end
343
-
344
- def inner_width
345
- (@style.border_thickness_left + @style.padding_left) + (@style.padding_right + @style.border_thickness_right)
346
- end
347
-
348
- def height
349
- if visible?
350
- inner_height + @height
351
- else
352
- 0
353
- end
354
- end
355
-
356
- def content_height
357
- @height
358
- end
359
-
360
- def noncontent_height
361
- (inner_height + outer_height) - height
362
- end
363
-
364
- def outer_height
365
- @style.margin_top + height + @style.margin_bottom
366
- end
367
-
368
- def inner_height
369
- (@style.border_thickness_top + @style.padding_top) + (@style.padding_bottom + @style.border_thickness_bottom)
370
- end
371
-
372
- def scroll_width
373
- @children.sum(&:width) + noncontent_width
374
- end
375
-
376
- def scroll_height
377
- @children.sum(&:height) + noncontent_height
378
- end
379
-
380
- def max_scroll_width
381
- scroll_width - width
382
- end
383
-
384
- def max_scroll_height
385
- scroll_height - height
386
- end
387
-
388
- def dimensional_size(size, dimension)
389
- raise "dimension must be either :width or :height" unless %i[width height].include?(dimension)
390
-
391
- if size.is_a?(Numeric) && size.between?(0.0, 1.0)
392
- (@parent.send(:"content_#{dimension}") * size).round - send(:"noncontent_#{dimension}").round
393
- else
394
- size
395
- end
396
- end
397
-
398
- def background=(_background)
399
- @style.background_canvas.background = _background
400
- update_background
401
- end
402
-
403
- def update_background
404
- @style.background_canvas.x = @x
405
- @style.background_canvas.y = @y
406
- @style.background_canvas.z = @z
407
- @style.background_canvas.width = width
408
- @style.background_canvas.height = height
409
-
410
- @style.background_canvas.update
411
- update_background_nine_slice
412
- @style.border_canvas.update
413
- end
414
-
415
- def background_nine_slice=(_image_path)
416
- @style.background_nine_slice_canvas.image = _image_path
417
- update_background_nine_slice
418
- end
419
-
420
- def update_background_nine_slice
421
- @style.background_nine_slice_canvas.x = @x
422
- @style.background_nine_slice_canvas.y = @y
423
- @style.background_nine_slice_canvas.z = @z
424
- @style.background_nine_slice_canvas.width = width
425
- @style.background_nine_slice_canvas.height = height
426
-
427
- @style.background_nine_slice_canvas.mode = @style.background_nine_slice_mode
428
-
429
- @style.background_nine_slice_canvas.color = @style.background_nine_slice_color
430
-
431
- @style.background_nine_slice_canvas.left = @style.background_nine_slice_left
432
- @style.background_nine_slice_canvas.top = @style.background_nine_slice_top
433
- @style.background_nine_slice_canvas.right = @style.background_nine_slice_right
434
- @style.background_nine_slice_canvas.bottom = @style.background_nine_slice_bottom
435
-
436
- @style.background_nine_slice_canvas.image = @style.background_nine_slice
437
- end
438
-
439
- def root
440
- return self if is_root?
441
-
442
- unless @root && @root.parent.nil?
443
- @root = parent
444
-
445
- loop do
446
- break unless @root&.parent
447
-
448
- @root = @root.parent
449
- end
450
- end
451
-
452
- @root
453
- end
454
-
455
- def is_root?
456
- @gui_state != nil
457
- end
458
-
459
- def focus(_)
460
- warn "#{self.class}#focus was not overridden!"
461
-
462
- :handled
463
- end
464
-
465
- def recalculate
466
- raise "#{self.class}#recalculate was not overridden!"
467
- end
468
-
469
- def reposition
470
- end
471
-
472
- def value
473
- raise "#{self.class}#value was not overridden!"
474
- end
475
-
476
- def value=(_value)
477
- raise "#{self.class}#value= was not overridden!"
478
- end
479
-
480
- def to_s
481
- "#{self.class} x=#{x} y=#{y} width=#{width} height=#{height} value=#{value.is_a?(String) ? "\"#{value}\"" : value}"
482
- end
483
-
484
- def inspect
485
- to_s
486
- end
487
- end
488
- 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
+ @debug_color = @options[:debug_color].nil? ? Gosu::Color::RED : @options[:debug_color]
22
+
23
+ @style = Style.new(options)
24
+
25
+ @root ||= nil
26
+ @gui_state ||= nil
27
+
28
+ @x = @style.x
29
+ @y = @style.y
30
+ @z = @style.z
31
+
32
+ @width = 0
33
+ @height = 0
34
+
35
+ @style.width = default(:width) || nil
36
+ @style.height = default(:height) || nil
37
+
38
+ @style.background_canvas = Background.new
39
+ @style.background_nine_slice_canvas = BackgroundNineSlice.new
40
+ @style.border_canvas = BorderCanvas.new(element: self)
41
+
42
+ @style_event = :default
43
+
44
+ stylize
45
+
46
+ default_events
47
+
48
+ root.gui_state.request_focus(self) if @options[:autofocus]
49
+ end
50
+
51
+ def stylize
52
+ set_static_position
53
+
54
+ set_padding
55
+ set_margin
56
+
57
+ set_background
58
+ set_background_nine_slice
59
+
60
+ set_border_thickness
61
+ set_border_color
62
+ end
63
+
64
+ def safe_style_fetch(*args)
65
+ @style.hash.dig(@style_event, *args) || @style.hash.dig(:default, *args) || default(*args)
66
+ end
67
+
68
+ def set_static_position
69
+ @x = @style.x if @style.x != 0
70
+ @y = @style.y if @style.y != 0
71
+ end
72
+
73
+ def set_background
74
+ @style.background = safe_style_fetch(:background)
75
+
76
+ @style.background_canvas.background = @style.background
77
+ end
78
+
79
+ def set_background_nine_slice
80
+ @style.background_nine_slice = safe_style_fetch(:background_nine_slice)
81
+
82
+ @style.background_nine_slice_mode = safe_style_fetch(:background_nine_slice_mode) || :stretch
83
+ @style.background_nine_slice_color = safe_style_fetch(:background_nine_slice_color) || Gosu::Color::WHITE
84
+ @style.background_nine_slice_canvas.color = @style.background_nine_slice_color
85
+
86
+ @style.background_nine_slice_from_edge = safe_style_fetch(:background_nine_slice_from_edge)
87
+
88
+ @style.background_nine_slice_left = safe_style_fetch(:background_nine_slice_left) || @style.background_nine_slice_from_edge
89
+ @style.background_nine_slice_top = safe_style_fetch(:background_nine_slice_top) || @style.background_nine_slice_from_edge
90
+ @style.background_nine_slice_right = safe_style_fetch(:background_nine_slice_right) || @style.background_nine_slice_from_edge
91
+ @style.background_nine_slice_bottom = safe_style_fetch(:background_nine_slice_bottom) || @style.background_nine_slice_from_edge
92
+ end
93
+
94
+ def set_border_thickness
95
+ @style.border_thickness = safe_style_fetch(:border_thickness)
96
+
97
+ @style.border_thickness_left = safe_style_fetch(:border_thickness_left) || @style.border_thickness
98
+ @style.border_thickness_right = safe_style_fetch(:border_thickness_right) || @style.border_thickness
99
+ @style.border_thickness_top = safe_style_fetch(:border_thickness_top) || @style.border_thickness
100
+ @style.border_thickness_bottom = safe_style_fetch(:border_thickness_bottom) || @style.border_thickness
101
+ end
102
+
103
+ def set_border_color
104
+ @style.border_color = safe_style_fetch(:border_color)
105
+
106
+ @style.border_color_left = safe_style_fetch(:border_color_left) || @style.border_color
107
+ @style.border_color_right = safe_style_fetch(:border_color_right) || @style.border_color
108
+ @style.border_color_top = safe_style_fetch(:border_color_top) || @style.border_color
109
+ @style.border_color_bottom = safe_style_fetch(:border_color_bottom) || @style.border_color
110
+
111
+ @style.border_canvas.color = [
112
+ @style.border_color_top,
113
+ @style.border_color_right,
114
+ @style.border_color_bottom,
115
+ @style.border_color_left
116
+ ]
117
+ end
118
+
119
+ def set_padding
120
+ @style.padding = safe_style_fetch(:padding)
121
+
122
+ @style.padding_left = safe_style_fetch(:padding_left) || @style.padding
123
+ @style.padding_right = safe_style_fetch(:padding_right) || @style.padding
124
+ @style.padding_top = safe_style_fetch(:padding_top) || @style.padding
125
+ @style.padding_bottom = safe_style_fetch(:padding_bottom) || @style.padding
126
+ end
127
+
128
+ def set_margin
129
+ @style.margin = safe_style_fetch(:margin)
130
+
131
+ @style.margin_left = safe_style_fetch(:margin_left) || @style.margin
132
+ @style.margin_right = safe_style_fetch(:margin_right) || @style.margin
133
+ @style.margin_top = safe_style_fetch(:margin_top) || @style.margin
134
+ @style.margin_bottom = safe_style_fetch(:margin_bottom) || @style.margin
135
+ end
136
+
137
+ def update_styles(event = :default)
138
+ old_width = width
139
+ old_height = height
140
+
141
+ _style = @style.send(event)
142
+ @style_event = event
143
+
144
+ if @text.is_a?(CyberarmEngine::Text)
145
+ @text.color = _style&.dig(:color) || @style.default[:color]
146
+ @text.swap_font(_style&.dig(:text_size) || @style.default[:text_size], _style&.dig(:font) || @style.default[:font])
147
+ end
148
+
149
+ return if self.is_a?(ToolTip)
150
+
151
+ if old_width != width || old_height != height
152
+ (root&.gui_state || @gui_state).request_recalculate
153
+ else
154
+ stylize
155
+ end
156
+ end
157
+
158
+ def default_events
159
+ %i[left middle right].each do |button|
160
+ event(:"#{button}_mouse_button")
161
+ event(:"released_#{button}_mouse_button")
162
+ event(:"clicked_#{button}_mouse_button")
163
+ event(:"holding_#{button}_mouse_button")
164
+ end
165
+
166
+ event(:mouse_wheel_up)
167
+ event(:mouse_wheel_down)
168
+
169
+ event(:enter)
170
+ event(:hover)
171
+ event(:leave)
172
+
173
+ event(:focus)
174
+ event(:blur)
175
+
176
+ event(:changed)
177
+ end
178
+
179
+ def enter(_sender)
180
+ @focus = false unless window.button_down?(Gosu::MsLeft)
181
+
182
+ if !@enabled
183
+ update_styles(:disabled)
184
+ elsif @focus
185
+ update_styles(:active)
186
+ else
187
+ update_styles(:hover)
188
+ end
189
+
190
+ :handled
191
+ end
192
+
193
+ def left_mouse_button(_sender, _x, _y)
194
+ @focus = true
195
+
196
+ unless @enabled
197
+ update_styles(:disabled)
198
+ else
199
+ update_styles(:active)
200
+ end
201
+
202
+ window.current_state.focus = self
203
+
204
+ :handled
205
+ end
206
+
207
+ def released_left_mouse_button(sender, _x, _y)
208
+ enter(sender)
209
+
210
+ :handled
211
+ end
212
+
213
+ def clicked_left_mouse_button(_sender, _x, _y)
214
+ @block&.call(self) if @enabled && !self.is_a?(Container)
215
+
216
+ :handled
217
+ end
218
+
219
+ def leave(_sender)
220
+ if @enabled
221
+ update_styles
222
+ else
223
+ update_styles(:disabled)
224
+ end
225
+
226
+ :handled
227
+ end
228
+
229
+ def blur(_sender)
230
+ @focus = false
231
+
232
+ if @enabled
233
+ update_styles
234
+ else
235
+ update_styles(:disabled)
236
+ end
237
+
238
+ :handled
239
+ end
240
+
241
+ def enabled?
242
+ @enabled
243
+ end
244
+
245
+ def visible?
246
+ @visible
247
+ end
248
+
249
+ def toggle
250
+ @visible = !@visible
251
+ root.gui_state.request_recalculate
252
+ end
253
+
254
+ def show
255
+ bool = visible?
256
+ @visible = true
257
+ root.gui_state.request_recalculate unless bool
258
+ end
259
+
260
+ def hide
261
+ bool = visible?
262
+ @visible = false
263
+ root.gui_state.request_recalculate if bool
264
+ end
265
+
266
+ def draw
267
+ return unless visible?
268
+
269
+ @style.background_canvas.draw
270
+ @style.background_nine_slice_canvas.draw
271
+ @style.border_canvas.draw
272
+
273
+ Gosu.clip_to(@x, @y, width, height) do
274
+ render
275
+ end
276
+ end
277
+
278
+ def debug_draw
279
+ return if defined?(GUI_DEBUG_ONLY_ELEMENT) && self.class == GUI_DEBUG_ONLY_ELEMENT
280
+
281
+ Gosu.draw_line(
282
+ x, y, @debug_color,
283
+ x + outer_width, y, @debug_color,
284
+ Float::INFINITY
285
+ )
286
+ Gosu.draw_line(
287
+ x + outer_width, y, @debug_color,
288
+ x + outer_width, y + outer_height, @debug_color,
289
+ Float::INFINITY
290
+ )
291
+ Gosu.draw_line(
292
+ x + outer_width, y + outer_height, @debug_color,
293
+ x, y + outer_height, @debug_color,
294
+ Float::INFINITY
295
+ )
296
+ Gosu.draw_line(
297
+ x, outer_height, @debug_color,
298
+ x, y, @debug_color,
299
+ Float::INFINITY
300
+ )
301
+ end
302
+
303
+ def update
304
+ end
305
+
306
+ def button_down(id)
307
+ end
308
+
309
+ def button_up(id)
310
+ end
311
+
312
+ def draggable?(_button)
313
+ false
314
+ end
315
+
316
+ def render
317
+ end
318
+
319
+ def hit?(x, y)
320
+ x.between?(@x, @x + width) &&
321
+ y.between?(@y, @y + height)
322
+ end
323
+
324
+ def width
325
+ if visible?
326
+ inner_width + @width
327
+ else
328
+ 0
329
+ end
330
+ end
331
+
332
+ def content_width
333
+ @width
334
+ end
335
+
336
+ def noncontent_width
337
+ (inner_width + outer_width) - width
338
+ end
339
+
340
+ def outer_width
341
+ @style.margin_left + width + @style.margin_right
342
+ end
343
+
344
+ def inner_width
345
+ (@style.border_thickness_left + @style.padding_left) + (@style.padding_right + @style.border_thickness_right)
346
+ end
347
+
348
+ def height
349
+ if visible?
350
+ inner_height + @height
351
+ else
352
+ 0
353
+ end
354
+ end
355
+
356
+ def content_height
357
+ @height
358
+ end
359
+
360
+ def noncontent_height
361
+ (inner_height + outer_height) - height
362
+ end
363
+
364
+ def outer_height
365
+ @style.margin_top + height + @style.margin_bottom
366
+ end
367
+
368
+ def inner_height
369
+ (@style.border_thickness_top + @style.padding_top) + (@style.padding_bottom + @style.border_thickness_bottom)
370
+ end
371
+
372
+ def scroll_width
373
+ @children.sum(&:width) + noncontent_width
374
+ end
375
+
376
+ def scroll_height
377
+ @children.sum(&:height) + noncontent_height
378
+ end
379
+
380
+ def max_scroll_width
381
+ scroll_width - width
382
+ end
383
+
384
+ def max_scroll_height
385
+ scroll_height - height
386
+ end
387
+
388
+ def dimensional_size(size, dimension)
389
+ raise "dimension must be either :width or :height" unless %i[width height].include?(dimension)
390
+
391
+ if size.is_a?(Numeric) && size.between?(0.0, 1.0)
392
+ (@parent.send(:"content_#{dimension}") * size).round - send(:"noncontent_#{dimension}").round
393
+ else
394
+ size
395
+ end
396
+ end
397
+
398
+ def background=(_background)
399
+ @style.background_canvas.background = _background
400
+ update_background
401
+ end
402
+
403
+ def update_background
404
+ @style.background_canvas.x = @x
405
+ @style.background_canvas.y = @y
406
+ @style.background_canvas.z = @z
407
+ @style.background_canvas.width = width
408
+ @style.background_canvas.height = height
409
+
410
+ @style.background_canvas.update
411
+ update_background_nine_slice
412
+ @style.border_canvas.update
413
+ end
414
+
415
+ def background_nine_slice=(_image_path)
416
+ @style.background_nine_slice_canvas.image = _image_path
417
+ update_background_nine_slice
418
+ end
419
+
420
+ def update_background_nine_slice
421
+ @style.background_nine_slice_canvas.x = @x
422
+ @style.background_nine_slice_canvas.y = @y
423
+ @style.background_nine_slice_canvas.z = @z
424
+ @style.background_nine_slice_canvas.width = width
425
+ @style.background_nine_slice_canvas.height = height
426
+
427
+ @style.background_nine_slice_canvas.mode = @style.background_nine_slice_mode
428
+
429
+ @style.background_nine_slice_canvas.color = @style.background_nine_slice_color
430
+
431
+ @style.background_nine_slice_canvas.left = @style.background_nine_slice_left
432
+ @style.background_nine_slice_canvas.top = @style.background_nine_slice_top
433
+ @style.background_nine_slice_canvas.right = @style.background_nine_slice_right
434
+ @style.background_nine_slice_canvas.bottom = @style.background_nine_slice_bottom
435
+
436
+ @style.background_nine_slice_canvas.image = @style.background_nine_slice
437
+ end
438
+
439
+ def root
440
+ return self if is_root?
441
+
442
+ unless @root && @root.parent.nil?
443
+ @root = parent
444
+
445
+ loop do
446
+ break unless @root&.parent
447
+
448
+ @root = @root.parent
449
+ end
450
+ end
451
+
452
+ @root
453
+ end
454
+
455
+ def is_root?
456
+ @gui_state != nil
457
+ end
458
+
459
+ def focus(_)
460
+ warn "#{self.class}#focus was not overridden!"
461
+
462
+ :handled
463
+ end
464
+
465
+ def recalculate
466
+ raise "#{self.class}#recalculate was not overridden!"
467
+ end
468
+
469
+ def reposition
470
+ end
471
+
472
+ def value
473
+ raise "#{self.class}#value was not overridden!"
474
+ end
475
+
476
+ def value=(_value)
477
+ raise "#{self.class}#value= was not overridden!"
478
+ end
479
+
480
+ def to_s
481
+ "#{self.class} x=#{x} y=#{y} width=#{width} height=#{height} value=#{value.is_a?(String) ? "\"#{value}\"" : value}"
482
+ end
483
+
484
+ def inspect
485
+ to_s
486
+ end
487
+ end
488
+ end