cyberarm_engine 0.24.4 → 0.24.5
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.
- checksums.yaml +4 -4
- data/.gitignore +8 -8
- data/.rubocop.yml +7 -7
- data/.travis.yml +5 -5
- data/Gemfile +6 -6
- data/Gemfile.lock +24 -0
- data/LICENSE.txt +21 -21
- data/README.md +74 -74
- data/Rakefile +10 -10
- data/assets/shaders/fragment/g_buffer.glsl +30 -30
- data/assets/shaders/fragment/lighting.glsl +115 -69
- data/assets/shaders/include/light_struct.glsl +11 -11
- data/assets/shaders/include/material_struct.glsl +16 -16
- data/assets/shaders/vertex/g_buffer.glsl +28 -28
- data/assets/shaders/vertex/lighting.glsl +24 -24
- data/bin/console +14 -14
- data/bin/setup +8 -8
- data/cyberarm_engine.gemspec +36 -36
- data/lib/cyberarm_engine/animator.rb +219 -219
- data/lib/cyberarm_engine/background.rb +180 -179
- data/lib/cyberarm_engine/background_image.rb +93 -93
- data/lib/cyberarm_engine/background_nine_slice.rb +142 -142
- data/lib/cyberarm_engine/bounding_box.rb +150 -150
- data/lib/cyberarm_engine/builtin/intro_state.rb +130 -130
- data/lib/cyberarm_engine/cache/download_manager.rb +123 -123
- data/lib/cyberarm_engine/cache.rb +4 -4
- data/lib/cyberarm_engine/common.rb +128 -128
- data/lib/cyberarm_engine/config_file.rb +46 -46
- data/lib/cyberarm_engine/console/command.rb +157 -157
- data/lib/cyberarm_engine/console/commands/help_command.rb +43 -43
- data/lib/cyberarm_engine/console/subcommand.rb +99 -99
- data/lib/cyberarm_engine/console.rb +248 -248
- data/lib/cyberarm_engine/game_object.rb +244 -244
- data/lib/cyberarm_engine/game_state.rb +124 -124
- data/lib/cyberarm_engine/gosu_ext/draw_arc.rb +97 -97
- data/lib/cyberarm_engine/gosu_ext/draw_circle.rb +30 -30
- data/lib/cyberarm_engine/gosu_ext/draw_path.rb +17 -17
- data/lib/cyberarm_engine/model/material.rb +21 -21
- data/lib/cyberarm_engine/model/{model_object.rb → mesh.rb} +131 -131
- data/lib/cyberarm_engine/model/parser.rb +74 -74
- data/lib/cyberarm_engine/model/parsers/collada_parser.rb +138 -138
- data/lib/cyberarm_engine/model/parsers/wavefront_parser.rb +154 -154
- data/lib/cyberarm_engine/model.rb +216 -213
- data/lib/cyberarm_engine/model_cache.rb +31 -31
- data/lib/cyberarm_engine/notification.rb +82 -82
- data/lib/cyberarm_engine/notification_manager.rb +241 -241
- data/lib/cyberarm_engine/opengl/light.rb +52 -50
- data/lib/cyberarm_engine/opengl/orthographic_camera.rb +46 -46
- data/lib/cyberarm_engine/opengl/perspective_camera.rb +41 -38
- data/lib/cyberarm_engine/opengl/renderer/bounding_box_renderer.rb +249 -249
- data/lib/cyberarm_engine/opengl/renderer/g_buffer.rb +167 -165
- data/lib/cyberarm_engine/opengl/renderer/opengl_renderer.rb +307 -304
- data/lib/cyberarm_engine/opengl/renderer/renderer.rb +33 -33
- data/lib/cyberarm_engine/opengl/shader.rb +408 -406
- data/lib/cyberarm_engine/opengl/texture.rb +69 -69
- data/lib/cyberarm_engine/opengl.rb +53 -40
- data/lib/cyberarm_engine/ray.rb +56 -56
- data/lib/cyberarm_engine/stats.rb +200 -200
- data/lib/cyberarm_engine/text.rb +260 -260
- data/lib/cyberarm_engine/timer.rb +23 -23
- data/lib/cyberarm_engine/transform.rb +296 -296
- data/lib/cyberarm_engine/trees/aabb_node.rb +126 -0
- data/lib/cyberarm_engine/trees/aabb_tree.rb +55 -0
- data/lib/cyberarm_engine/trees/aabb_tree_debug.rb +29 -0
- data/lib/cyberarm_engine/ui/border_canvas.rb +102 -102
- data/lib/cyberarm_engine/ui/dsl.rb +142 -142
- data/lib/cyberarm_engine/ui/element.rb +662 -662
- data/lib/cyberarm_engine/ui/elements/button.rb +100 -100
- data/lib/cyberarm_engine/ui/elements/check_box.rb +54 -54
- data/lib/cyberarm_engine/ui/elements/container.rb +404 -404
- data/lib/cyberarm_engine/ui/elements/edit_box.rb +179 -179
- data/lib/cyberarm_engine/ui/elements/edit_line.rb +297 -297
- data/lib/cyberarm_engine/ui/elements/flow.rb +15 -15
- data/lib/cyberarm_engine/ui/elements/image.rb +72 -72
- data/lib/cyberarm_engine/ui/elements/list_box.rb +79 -79
- data/lib/cyberarm_engine/ui/elements/menu.rb +27 -27
- data/lib/cyberarm_engine/ui/elements/menu_item.rb +6 -6
- data/lib/cyberarm_engine/ui/elements/progress.rb +93 -93
- data/lib/cyberarm_engine/ui/elements/radio.rb +6 -6
- data/lib/cyberarm_engine/ui/elements/slider.rb +107 -107
- data/lib/cyberarm_engine/ui/elements/stack.rb +11 -11
- data/lib/cyberarm_engine/ui/elements/text_block.rb +216 -216
- data/lib/cyberarm_engine/ui/elements/toggle_button.rb +67 -67
- data/lib/cyberarm_engine/ui/event.rb +54 -54
- data/lib/cyberarm_engine/ui/gui_state.rb +321 -321
- data/lib/cyberarm_engine/ui/style.rb +50 -50
- data/lib/cyberarm_engine/ui/theme.rb +225 -225
- data/lib/cyberarm_engine/vector.rb +312 -312
- data/lib/cyberarm_engine/version.rb +4 -4
- data/lib/cyberarm_engine/window.rb +195 -195
- data/lib/cyberarm_engine.rb +70 -78
- data/mrbgem.rake +29 -29
- metadata +8 -7
@@ -1,662 +1,662 @@
|
|
1
|
-
module CyberarmEngine
|
2
|
-
class Element
|
3
|
-
include Theme
|
4
|
-
include Event
|
5
|
-
include Common
|
6
|
-
|
7
|
-
attr_accessor :x, :y, :z, :tip, :element_visible
|
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.key?(:focus) ? false : @options[:focus]
|
17
|
-
@enabled = !@options.key?(:enabled) ? true : @options[:enabled]
|
18
|
-
@visible = !@options.key?(:visible) ? 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
|
-
@element_visible = true
|
28
|
-
|
29
|
-
@x = @style.x
|
30
|
-
@y = @style.y
|
31
|
-
@z = @style.z
|
32
|
-
|
33
|
-
@old_width = 0
|
34
|
-
@old_height = 0
|
35
|
-
@width = 0
|
36
|
-
@height = 0
|
37
|
-
|
38
|
-
@style.width = default(:width) || nil
|
39
|
-
@style.height = default(:height) || nil
|
40
|
-
|
41
|
-
@style.background_canvas = Background.new
|
42
|
-
@style.background_nine_slice_canvas = BackgroundNineSlice.new
|
43
|
-
@style.background_image_canvas = BackgroundImage.new
|
44
|
-
@style.border_canvas = BorderCanvas.new(element: self)
|
45
|
-
|
46
|
-
@style_event = :default
|
47
|
-
|
48
|
-
stylize
|
49
|
-
|
50
|
-
default_events
|
51
|
-
|
52
|
-
root.gui_state.request_focus(self) if @options[:autofocus]
|
53
|
-
end
|
54
|
-
|
55
|
-
def stylize
|
56
|
-
set_static_position
|
57
|
-
|
58
|
-
set_color
|
59
|
-
set_font
|
60
|
-
|
61
|
-
set_padding
|
62
|
-
set_margin
|
63
|
-
|
64
|
-
set_background
|
65
|
-
set_background_nine_slice
|
66
|
-
set_background_image
|
67
|
-
|
68
|
-
set_border_thickness
|
69
|
-
set_border_color
|
70
|
-
|
71
|
-
root.gui_state.request_repaint
|
72
|
-
end
|
73
|
-
|
74
|
-
def safe_style_fetch(key, fallback_key = nil)
|
75
|
-
# Attempt to return value for requested key
|
76
|
-
v = @style.hash.dig(@style_event, key)
|
77
|
-
return v if v
|
78
|
-
|
79
|
-
# Attempt to return overriding value
|
80
|
-
if fallback_key
|
81
|
-
v = @style.hash.dig(@style_event, fallback_key)
|
82
|
-
return v if v
|
83
|
-
end
|
84
|
-
|
85
|
-
# Fallback to default style
|
86
|
-
@style.hash.dig(:default, key) || default(key)
|
87
|
-
end
|
88
|
-
|
89
|
-
def set_static_position
|
90
|
-
@x = @style.x if @style.x != 0
|
91
|
-
@y = @style.y if @style.y != 0
|
92
|
-
end
|
93
|
-
|
94
|
-
def set_color
|
95
|
-
@style.color = safe_style_fetch(:color)
|
96
|
-
@text&.color = @style.color
|
97
|
-
end
|
98
|
-
|
99
|
-
def set_font
|
100
|
-
@text&.swap_font(safe_style_fetch(:text_size), safe_style_fetch(:font))
|
101
|
-
end
|
102
|
-
|
103
|
-
def set_background
|
104
|
-
@style.background = safe_style_fetch(:background)
|
105
|
-
|
106
|
-
@style.background_canvas.background = @style.background
|
107
|
-
end
|
108
|
-
|
109
|
-
def set_background_nine_slice
|
110
|
-
@style.background_nine_slice = safe_style_fetch(:background_nine_slice)
|
111
|
-
|
112
|
-
@style.background_nine_slice_mode = safe_style_fetch(:background_nine_slice_mode) || :stretch
|
113
|
-
@style.background_nine_slice_color = safe_style_fetch(:background_nine_slice_color) || Gosu::Color::WHITE
|
114
|
-
@style.background_nine_slice_canvas.color = @style.background_nine_slice_color
|
115
|
-
|
116
|
-
@style.background_nine_slice_from_edge = safe_style_fetch(:background_nine_slice_from_edge)
|
117
|
-
|
118
|
-
@style.background_nine_slice_left = safe_style_fetch(:background_nine_slice_left, :background_nine_slice_from_edge)
|
119
|
-
@style.background_nine_slice_top = safe_style_fetch(:background_nine_slice_top, :background_nine_slice_from_edge)
|
120
|
-
@style.background_nine_slice_right = safe_style_fetch(:background_nine_slice_right, :background_nine_slice_from_edge)
|
121
|
-
@style.background_nine_slice_bottom = safe_style_fetch(:background_nine_slice_bottom, :background_nine_slice_from_edge)
|
122
|
-
end
|
123
|
-
|
124
|
-
def set_background_image
|
125
|
-
@style.background_image = safe_style_fetch(:background_image)
|
126
|
-
@style.background_image_mode = safe_style_fetch(:background_image_mode) || :stretch
|
127
|
-
@style.background_image_color = safe_style_fetch(:background_image_color) || Gosu::Color::WHITE
|
128
|
-
@style.background_image_canvas.mode = @style.background_image_mode
|
129
|
-
@style.background_image_canvas.color = @style.background_image_color
|
130
|
-
end
|
131
|
-
|
132
|
-
def set_border_thickness
|
133
|
-
@style.border_thickness = safe_style_fetch(:border_thickness)
|
134
|
-
|
135
|
-
@style.border_thickness_left = safe_style_fetch(:border_thickness_left, :border_thickness)
|
136
|
-
@style.border_thickness_right = safe_style_fetch(:border_thickness_right, :border_thickness)
|
137
|
-
@style.border_thickness_top = safe_style_fetch(:border_thickness_top, :border_thickness)
|
138
|
-
@style.border_thickness_bottom = safe_style_fetch(:border_thickness_bottom, :border_thickness)
|
139
|
-
end
|
140
|
-
|
141
|
-
def set_border_color
|
142
|
-
@style.border_color = safe_style_fetch(:border_color)
|
143
|
-
|
144
|
-
@style.border_color_left = safe_style_fetch(:border_color_left, :border_color)
|
145
|
-
@style.border_color_right = safe_style_fetch(:border_color_right, :border_color)
|
146
|
-
@style.border_color_top = safe_style_fetch(:border_color_top, :border_color)
|
147
|
-
@style.border_color_bottom = safe_style_fetch(:border_color_bottom, :border_color)
|
148
|
-
|
149
|
-
@style.border_canvas.color = [
|
150
|
-
@style.border_color_top,
|
151
|
-
@style.border_color_right,
|
152
|
-
@style.border_color_bottom,
|
153
|
-
@style.border_color_left
|
154
|
-
]
|
155
|
-
end
|
156
|
-
|
157
|
-
def set_padding
|
158
|
-
@style.padding = safe_style_fetch(:padding)
|
159
|
-
|
160
|
-
@style.padding_left = safe_style_fetch(:padding_left, :padding)
|
161
|
-
@style.padding_right = safe_style_fetch(:padding_right, :padding)
|
162
|
-
@style.padding_top = safe_style_fetch(:padding_top, :padding)
|
163
|
-
@style.padding_bottom = safe_style_fetch(:padding_bottom, :padding)
|
164
|
-
end
|
165
|
-
|
166
|
-
def set_margin
|
167
|
-
@style.margin = safe_style_fetch(:margin)
|
168
|
-
|
169
|
-
@style.margin_left = safe_style_fetch(:margin_left, :margin)
|
170
|
-
@style.margin_right = safe_style_fetch(:margin_right, :margin)
|
171
|
-
@style.margin_top = safe_style_fetch(:margin_top, :margin)
|
172
|
-
@style.margin_bottom = safe_style_fetch(:margin_bottom, :margin)
|
173
|
-
end
|
174
|
-
|
175
|
-
def update_styles(event = :default)
|
176
|
-
old_width = width
|
177
|
-
old_height = height
|
178
|
-
|
179
|
-
@style_event = event
|
180
|
-
|
181
|
-
return if self.is_a?(ToolTip)
|
182
|
-
|
183
|
-
root.gui_state.request_recalculate if old_width != width || old_height != height
|
184
|
-
|
185
|
-
stylize
|
186
|
-
end
|
187
|
-
|
188
|
-
def default_events
|
189
|
-
%i[left middle right].each do |button|
|
190
|
-
event(:"#{button}_mouse_button")
|
191
|
-
event(:"released_#{button}_mouse_button")
|
192
|
-
event(:"clicked_#{button}_mouse_button")
|
193
|
-
event(:"holding_#{button}_mouse_button")
|
194
|
-
end
|
195
|
-
|
196
|
-
event(:mouse_wheel_up)
|
197
|
-
event(:mouse_wheel_down)
|
198
|
-
event(:scroll_jump_to_top)
|
199
|
-
event(:scroll_jump_to_end)
|
200
|
-
event(:scroll_page_up)
|
201
|
-
event(:scroll_page_down)
|
202
|
-
|
203
|
-
event(:enter)
|
204
|
-
event(:hover)
|
205
|
-
event(:leave)
|
206
|
-
|
207
|
-
event(:focus)
|
208
|
-
event(:blur)
|
209
|
-
|
210
|
-
event(:changed)
|
211
|
-
end
|
212
|
-
|
213
|
-
def enter(_sender)
|
214
|
-
@focus = false unless Gosu.button_down?(Gosu::MS_LEFT)
|
215
|
-
|
216
|
-
if !@enabled
|
217
|
-
update_styles(:disabled)
|
218
|
-
elsif @focus
|
219
|
-
update_styles(:active)
|
220
|
-
else
|
221
|
-
update_styles(:hover)
|
222
|
-
end
|
223
|
-
|
224
|
-
:handled
|
225
|
-
end
|
226
|
-
|
227
|
-
def left_mouse_button(_sender, _x, _y)
|
228
|
-
@focus = true
|
229
|
-
|
230
|
-
unless @enabled
|
231
|
-
update_styles(:disabled)
|
232
|
-
else
|
233
|
-
update_styles(:active)
|
234
|
-
end
|
235
|
-
|
236
|
-
window.current_state.focus = self
|
237
|
-
|
238
|
-
:handled
|
239
|
-
end
|
240
|
-
|
241
|
-
def released_left_mouse_button(sender, _x, _y)
|
242
|
-
enter(sender)
|
243
|
-
|
244
|
-
:handled
|
245
|
-
end
|
246
|
-
|
247
|
-
def clicked_left_mouse_button(_sender, _x, _y)
|
248
|
-
@block&.call(self) if @enabled && !self.is_a?(Container)
|
249
|
-
|
250
|
-
:handled
|
251
|
-
end
|
252
|
-
|
253
|
-
def leave(_sender)
|
254
|
-
if @enabled
|
255
|
-
update_styles
|
256
|
-
else
|
257
|
-
update_styles(:disabled)
|
258
|
-
end
|
259
|
-
|
260
|
-
:handled
|
261
|
-
end
|
262
|
-
|
263
|
-
def blur(_sender)
|
264
|
-
@focus = false
|
265
|
-
|
266
|
-
if @enabled
|
267
|
-
update_styles
|
268
|
-
else
|
269
|
-
update_styles(:disabled)
|
270
|
-
end
|
271
|
-
|
272
|
-
:handled
|
273
|
-
end
|
274
|
-
|
275
|
-
def enabled=(boolean)
|
276
|
-
root.gui_state.request_repaint if @enabled != boolean
|
277
|
-
|
278
|
-
@enabled = boolean
|
279
|
-
|
280
|
-
recalculate
|
281
|
-
|
282
|
-
@enabled
|
283
|
-
end
|
284
|
-
|
285
|
-
def enabled?
|
286
|
-
@enabled
|
287
|
-
end
|
288
|
-
|
289
|
-
def focused?
|
290
|
-
@focus
|
291
|
-
end
|
292
|
-
|
293
|
-
def visible?
|
294
|
-
@visible
|
295
|
-
end
|
296
|
-
|
297
|
-
def element_visible?
|
298
|
-
@element_visible
|
299
|
-
end
|
300
|
-
|
301
|
-
def toggle
|
302
|
-
@visible = !@visible
|
303
|
-
root.gui_state.request_recalculate
|
304
|
-
root.gui_state.request_repaint
|
305
|
-
end
|
306
|
-
|
307
|
-
def show
|
308
|
-
bool = visible?
|
309
|
-
@visible = true
|
310
|
-
root.gui_state.request_recalculate unless bool
|
311
|
-
root.gui_state.request_repaint unless bool
|
312
|
-
end
|
313
|
-
|
314
|
-
def hide
|
315
|
-
bool = visible?
|
316
|
-
@visible = false
|
317
|
-
root.gui_state.request_recalculate if bool
|
318
|
-
root.gui_state.request_repaint if bool
|
319
|
-
end
|
320
|
-
|
321
|
-
def draw
|
322
|
-
return unless visible?
|
323
|
-
return unless element_visible?
|
324
|
-
|
325
|
-
@style.background_canvas.draw
|
326
|
-
@style.background_nine_slice_canvas.draw
|
327
|
-
@style.background_image_canvas.draw
|
328
|
-
@style.border_canvas.draw
|
329
|
-
|
330
|
-
render
|
331
|
-
end
|
332
|
-
|
333
|
-
def debug_draw
|
334
|
-
return if CyberarmEngine.const_defined?("GUI_DEBUG_ONLY_ELEMENT") && self.class == GUI_DEBUG_ONLY_ELEMENT
|
335
|
-
|
336
|
-
Gosu.draw_line(
|
337
|
-
x, y, @debug_color,
|
338
|
-
x + outer_width, y, @debug_color,
|
339
|
-
Float::INFINITY
|
340
|
-
)
|
341
|
-
Gosu.draw_line(
|
342
|
-
x + outer_width, y, @debug_color,
|
343
|
-
x + outer_width, y + outer_height, @debug_color,
|
344
|
-
Float::INFINITY
|
345
|
-
)
|
346
|
-
Gosu.draw_line(
|
347
|
-
x + outer_width, y + outer_height, @debug_color,
|
348
|
-
x, y + outer_height, @debug_color,
|
349
|
-
Float::INFINITY
|
350
|
-
)
|
351
|
-
Gosu.draw_line(
|
352
|
-
x, y + outer_height, @debug_color,
|
353
|
-
x, y, @debug_color,
|
354
|
-
Float::INFINITY
|
355
|
-
)
|
356
|
-
end
|
357
|
-
|
358
|
-
def update
|
359
|
-
recalculate_if_size_changed
|
360
|
-
end
|
361
|
-
|
362
|
-
def button_down(id)
|
363
|
-
end
|
364
|
-
|
365
|
-
def button_up(id)
|
366
|
-
end
|
367
|
-
|
368
|
-
def draggable?(_button)
|
369
|
-
false
|
370
|
-
end
|
371
|
-
|
372
|
-
def render
|
373
|
-
end
|
374
|
-
|
375
|
-
def hit?(x, y)
|
376
|
-
x.between?(@x, @x + width) &&
|
377
|
-
y.between?(@y, @y + height)
|
378
|
-
end
|
379
|
-
|
380
|
-
def width
|
381
|
-
if visible?
|
382
|
-
inner_width + @width
|
383
|
-
else
|
384
|
-
0
|
385
|
-
end
|
386
|
-
end
|
387
|
-
|
388
|
-
def content_width
|
389
|
-
@width
|
390
|
-
end
|
391
|
-
|
392
|
-
def noncontent_width
|
393
|
-
(inner_width + outer_width) - width
|
394
|
-
end
|
395
|
-
|
396
|
-
def outer_width
|
397
|
-
@style.margin_left + width + @style.margin_right
|
398
|
-
end
|
399
|
-
|
400
|
-
def inner_width
|
401
|
-
(@style.border_thickness_left + @style.padding_left) + (@style.padding_right + @style.border_thickness_right)
|
402
|
-
end
|
403
|
-
|
404
|
-
def height
|
405
|
-
if visible?
|
406
|
-
inner_height + @height
|
407
|
-
else
|
408
|
-
0
|
409
|
-
end
|
410
|
-
end
|
411
|
-
|
412
|
-
def content_height
|
413
|
-
@height
|
414
|
-
end
|
415
|
-
|
416
|
-
def noncontent_height
|
417
|
-
(inner_height + outer_height) - height
|
418
|
-
end
|
419
|
-
|
420
|
-
def outer_height
|
421
|
-
@style.margin_top + height + @style.margin_bottom
|
422
|
-
end
|
423
|
-
|
424
|
-
def inner_height
|
425
|
-
(@style.border_thickness_top + @style.padding_top) + (@style.padding_bottom + @style.border_thickness_bottom)
|
426
|
-
end
|
427
|
-
|
428
|
-
def scroll_width
|
429
|
-
return @cached_scroll_width if @cached_scroll_width && is_a?(Container)
|
430
|
-
|
431
|
-
@cached_scroll_width = @children.sum(&:outer_width)
|
432
|
-
end
|
433
|
-
|
434
|
-
def scroll_height
|
435
|
-
return @cached_scroll_height if @cached_scroll_height && is_a?(Container)
|
436
|
-
|
437
|
-
if is_a?(CyberarmEngine::Element::Flow)
|
438
|
-
return 0 if @children.size.zero?
|
439
|
-
|
440
|
-
pairs_ = []
|
441
|
-
sorted_children_ = @children.sort_by(&:y)
|
442
|
-
a_ = []
|
443
|
-
y_position_ = sorted_children_.first.y
|
444
|
-
|
445
|
-
sorted_children_.each do |child|
|
446
|
-
unless child.y == y_position_
|
447
|
-
y_position_ = child.y
|
448
|
-
pairs_ << a_
|
449
|
-
a_ = []
|
450
|
-
end
|
451
|
-
|
452
|
-
a_ << child
|
453
|
-
end
|
454
|
-
|
455
|
-
pairs_ << a_ unless pairs_.last == a_
|
456
|
-
|
457
|
-
@cached_scroll_height = pairs_.sum { |pair| + @style.padding_top + @style.border_thickness_top + pair.map(&:outer_height).max } + @style.padding_bottom + @style.border_thickness_bottom
|
458
|
-
else
|
459
|
-
@cached_scroll_height = @style.padding_top + @style.border_thickness_top + @children.sum(&:outer_height) + @style.padding_bottom + @style.border_thickness_bottom
|
460
|
-
end
|
461
|
-
end
|
462
|
-
|
463
|
-
def max_scroll_width
|
464
|
-
(scroll_width - outer_width).positive? ? scroll_width - outer_width : scroll_width
|
465
|
-
end
|
466
|
-
|
467
|
-
def max_scroll_height
|
468
|
-
(scroll_height - outer_height).positive? ? scroll_height - outer_height : scroll_height
|
469
|
-
end
|
470
|
-
|
471
|
-
def dimensional_size(size, dimension)
|
472
|
-
raise "dimension must be either :width or :height" unless %i[width height].include?(dimension)
|
473
|
-
|
474
|
-
new_size = if size.is_a?(Float) && size.between?(0.0, 1.0)
|
475
|
-
(@parent.send(:"content_#{dimension}") * size).floor - send(:"noncontent_#{dimension}").floor
|
476
|
-
else
|
477
|
-
size
|
478
|
-
end
|
479
|
-
|
480
|
-
# Handle fill behavior
|
481
|
-
if @parent && @style.fill &&
|
482
|
-
(dimension == :width && @parent.is_a?(Flow) ||
|
483
|
-
dimension == :height && @parent.is_a?(Stack))
|
484
|
-
new_size = space_available_width - noncontent_width if dimension == :width && @parent.is_a?(Flow)
|
485
|
-
new_size = space_available_height - noncontent_height if dimension == :height && @parent.is_a?(Stack)
|
486
|
-
end
|
487
|
-
|
488
|
-
return @style.send(:"min_#{dimension}") if @style.send(:"min_#{dimension}") && new_size.to_f < @style.send(:"min_#{dimension}")
|
489
|
-
return @style.send(:"max_#{dimension}") if @style.send(:"max_#{dimension}") && new_size.to_f > @style.send(:"max_#{dimension}")
|
490
|
-
|
491
|
-
new_size
|
492
|
-
end
|
493
|
-
|
494
|
-
def space_available_width
|
495
|
-
# TODO: This may get expensive if there are a lot of children, probably should cache it somehow
|
496
|
-
fill_siblings = @parent.children.select { |c| c.style.fill }.count.to_f # include self since we're dividing
|
497
|
-
|
498
|
-
available_space = ((@parent.content_width - (@parent.children.reject { |c| c.style.fill }).map(&:outer_width).sum) / fill_siblings)
|
499
|
-
(available_space.nan? || available_space.infinite?) ? 0 : available_space.floor # The parent element might not have its dimensions, yet.
|
500
|
-
end
|
501
|
-
|
502
|
-
def space_available_height
|
503
|
-
# TODO: This may get expensive if there are a lot of children, probably should cache it somehow
|
504
|
-
fill_siblings = @parent.children.select { |c| c.style.fill }.count.to_f # include self since we're dividing
|
505
|
-
|
506
|
-
available_space = ((@parent.content_height - (@parent.children.reject { |c| c.style.fill }).map(&:outer_height).sum) / fill_siblings)
|
507
|
-
(available_space.nan? || available_space.infinite?) ? 0 : available_space.floor # The parent element might not have its dimensions, yet.
|
508
|
-
end
|
509
|
-
|
510
|
-
def background=(_background)
|
511
|
-
root.gui_state.request_repaint
|
512
|
-
|
513
|
-
@style.background_canvas.background = _background
|
514
|
-
update_background
|
515
|
-
end
|
516
|
-
|
517
|
-
def update_background
|
518
|
-
@style.background_canvas.x = @x
|
519
|
-
@style.background_canvas.y = @y
|
520
|
-
@style.background_canvas.z = @z
|
521
|
-
@style.background_canvas.width = width
|
522
|
-
@style.background_canvas.height = height
|
523
|
-
|
524
|
-
@style.background_canvas.update
|
525
|
-
update_background_nine_slice
|
526
|
-
update_background_image
|
527
|
-
@style.border_canvas.update
|
528
|
-
end
|
529
|
-
|
530
|
-
def background_nine_slice=(_image_path)
|
531
|
-
root.gui_state.request_repaint
|
532
|
-
|
533
|
-
@style.background_nine_slice_canvas.image = _image_path
|
534
|
-
update_background_nine_slice
|
535
|
-
end
|
536
|
-
|
537
|
-
def update_background_nine_slice
|
538
|
-
@style.background_nine_slice_canvas.x = @x
|
539
|
-
@style.background_nine_slice_canvas.y = @y
|
540
|
-
@style.background_nine_slice_canvas.z = @z
|
541
|
-
@style.background_nine_slice_canvas.width = width
|
542
|
-
@style.background_nine_slice_canvas.height = height
|
543
|
-
|
544
|
-
@style.background_nine_slice_canvas.mode = @style.background_nine_slice_mode
|
545
|
-
|
546
|
-
@style.background_nine_slice_canvas.color = @style.background_nine_slice_color
|
547
|
-
|
548
|
-
@style.background_nine_slice_canvas.left = @style.background_nine_slice_left
|
549
|
-
@style.background_nine_slice_canvas.top = @style.background_nine_slice_top
|
550
|
-
@style.background_nine_slice_canvas.right = @style.background_nine_slice_right
|
551
|
-
@style.background_nine_slice_canvas.bottom = @style.background_nine_slice_bottom
|
552
|
-
|
553
|
-
@style.background_nine_slice_canvas.image = @style.background_nine_slice
|
554
|
-
end
|
555
|
-
|
556
|
-
def background_image=(image_path)
|
557
|
-
root.gui_state.request_repaint
|
558
|
-
|
559
|
-
@style.background_image = image_path.is_a?(Gosu::Image) ? image_path : get_image(image_path)
|
560
|
-
update_background_image
|
561
|
-
end
|
562
|
-
|
563
|
-
def update_background_image
|
564
|
-
@style.background_image_canvas.x = @x
|
565
|
-
@style.background_image_canvas.y = @y
|
566
|
-
@style.background_image_canvas.z = @z
|
567
|
-
@style.background_image_canvas.width = width
|
568
|
-
@style.background_image_canvas.height = height
|
569
|
-
|
570
|
-
@style.background_image_canvas.mode = @style.background_image_mode
|
571
|
-
@style.background_image_canvas.color = @style.background_image_color
|
572
|
-
|
573
|
-
@style.background_image_canvas.image = @style.background_image
|
574
|
-
end
|
575
|
-
|
576
|
-
def recalculate_if_size_changed
|
577
|
-
if @parent && !is_a?(ToolTip) && (@old_width != width || @old_height != height)
|
578
|
-
root.gui_state.request_recalculate
|
579
|
-
|
580
|
-
@old_width = width
|
581
|
-
@old_height = height
|
582
|
-
end
|
583
|
-
end
|
584
|
-
|
585
|
-
def root
|
586
|
-
return self if is_root?
|
587
|
-
|
588
|
-
unless @root && @root.parent.nil?
|
589
|
-
@root = parent
|
590
|
-
|
591
|
-
loop do
|
592
|
-
break unless @root&.parent
|
593
|
-
|
594
|
-
@root = @root.parent
|
595
|
-
end
|
596
|
-
end
|
597
|
-
|
598
|
-
@root
|
599
|
-
end
|
600
|
-
|
601
|
-
def is_root?
|
602
|
-
@gui_state != nil
|
603
|
-
end
|
604
|
-
|
605
|
-
def child_of?(element)
|
606
|
-
return element == self if is_root?
|
607
|
-
return false unless element.is_a?(Container)
|
608
|
-
return true if element.children.find { |child| child == self }
|
609
|
-
|
610
|
-
element.children.find { |child| child.child_of?(element) if child.is_a?(Container) }
|
611
|
-
end
|
612
|
-
|
613
|
-
def parent_of?(element)
|
614
|
-
return false if element == self
|
615
|
-
return false unless is_a?(Container)
|
616
|
-
return true if @children.find { |child| child == element }
|
617
|
-
|
618
|
-
@children.find { |child| child.parent_of?(element) if child.is_a?(Container) }
|
619
|
-
end
|
620
|
-
|
621
|
-
def focus(_)
|
622
|
-
warn "#{self.class}#focus was not overridden!"
|
623
|
-
|
624
|
-
:handled
|
625
|
-
end
|
626
|
-
|
627
|
-
def recalculate
|
628
|
-
old_width = width
|
629
|
-
old_height = height
|
630
|
-
|
631
|
-
stylize
|
632
|
-
layout
|
633
|
-
|
634
|
-
root.gui_state.request_recalculate if @parent && !is_a?(ToolTip) && (width != old_width || height != old_height)
|
635
|
-
root.gui_state.request_repaint if width != old_width || height != old_height
|
636
|
-
|
637
|
-
root.gui_state.menu.recalculate if root.gui_state.menu && root.gui_state.menu.parent == self
|
638
|
-
end
|
639
|
-
|
640
|
-
def layout
|
641
|
-
end
|
642
|
-
|
643
|
-
def reposition
|
644
|
-
end
|
645
|
-
|
646
|
-
def value
|
647
|
-
raise "#{self.class}#value was not overridden!"
|
648
|
-
end
|
649
|
-
|
650
|
-
def value=(_value)
|
651
|
-
raise "#{self.class}#value= was not overridden!"
|
652
|
-
end
|
653
|
-
|
654
|
-
def to_s
|
655
|
-
"#{self.class} x=#{x} y=#{y} width=#{width} height=#{height} value=#{value.is_a?(String) ? "\"#{value}\"" : value}"
|
656
|
-
end
|
657
|
-
|
658
|
-
def inspect
|
659
|
-
to_s
|
660
|
-
end
|
661
|
-
end
|
662
|
-
end
|
1
|
+
module CyberarmEngine
|
2
|
+
class Element
|
3
|
+
include Theme
|
4
|
+
include Event
|
5
|
+
include Common
|
6
|
+
|
7
|
+
attr_accessor :x, :y, :z, :tip, :element_visible
|
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.key?(:focus) ? false : @options[:focus]
|
17
|
+
@enabled = !@options.key?(:enabled) ? true : @options[:enabled]
|
18
|
+
@visible = !@options.key?(:visible) ? 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
|
+
@element_visible = true
|
28
|
+
|
29
|
+
@x = @style.x
|
30
|
+
@y = @style.y
|
31
|
+
@z = @style.z
|
32
|
+
|
33
|
+
@old_width = 0
|
34
|
+
@old_height = 0
|
35
|
+
@width = 0
|
36
|
+
@height = 0
|
37
|
+
|
38
|
+
@style.width = default(:width) || nil
|
39
|
+
@style.height = default(:height) || nil
|
40
|
+
|
41
|
+
@style.background_canvas = Background.new
|
42
|
+
@style.background_nine_slice_canvas = BackgroundNineSlice.new
|
43
|
+
@style.background_image_canvas = BackgroundImage.new
|
44
|
+
@style.border_canvas = BorderCanvas.new(element: self)
|
45
|
+
|
46
|
+
@style_event = :default
|
47
|
+
|
48
|
+
stylize
|
49
|
+
|
50
|
+
default_events
|
51
|
+
|
52
|
+
root.gui_state.request_focus(self) if @options[:autofocus]
|
53
|
+
end
|
54
|
+
|
55
|
+
def stylize
|
56
|
+
set_static_position
|
57
|
+
|
58
|
+
set_color
|
59
|
+
set_font
|
60
|
+
|
61
|
+
set_padding
|
62
|
+
set_margin
|
63
|
+
|
64
|
+
set_background
|
65
|
+
set_background_nine_slice
|
66
|
+
set_background_image
|
67
|
+
|
68
|
+
set_border_thickness
|
69
|
+
set_border_color
|
70
|
+
|
71
|
+
root.gui_state.request_repaint
|
72
|
+
end
|
73
|
+
|
74
|
+
def safe_style_fetch(key, fallback_key = nil)
|
75
|
+
# Attempt to return value for requested key
|
76
|
+
v = @style.hash.dig(@style_event, key)
|
77
|
+
return v if v
|
78
|
+
|
79
|
+
# Attempt to return overriding value
|
80
|
+
if fallback_key
|
81
|
+
v = @style.hash.dig(@style_event, fallback_key)
|
82
|
+
return v if v
|
83
|
+
end
|
84
|
+
|
85
|
+
# Fallback to default style
|
86
|
+
@style.hash.dig(:default, key) || default(key)
|
87
|
+
end
|
88
|
+
|
89
|
+
def set_static_position
|
90
|
+
@x = @style.x if @style.x != 0
|
91
|
+
@y = @style.y if @style.y != 0
|
92
|
+
end
|
93
|
+
|
94
|
+
def set_color
|
95
|
+
@style.color = safe_style_fetch(:color)
|
96
|
+
@text&.color = @style.color
|
97
|
+
end
|
98
|
+
|
99
|
+
def set_font
|
100
|
+
@text&.swap_font(safe_style_fetch(:text_size), safe_style_fetch(:font))
|
101
|
+
end
|
102
|
+
|
103
|
+
def set_background
|
104
|
+
@style.background = safe_style_fetch(:background)
|
105
|
+
|
106
|
+
@style.background_canvas.background = @style.background
|
107
|
+
end
|
108
|
+
|
109
|
+
def set_background_nine_slice
|
110
|
+
@style.background_nine_slice = safe_style_fetch(:background_nine_slice)
|
111
|
+
|
112
|
+
@style.background_nine_slice_mode = safe_style_fetch(:background_nine_slice_mode) || :stretch
|
113
|
+
@style.background_nine_slice_color = safe_style_fetch(:background_nine_slice_color) || Gosu::Color::WHITE
|
114
|
+
@style.background_nine_slice_canvas.color = @style.background_nine_slice_color
|
115
|
+
|
116
|
+
@style.background_nine_slice_from_edge = safe_style_fetch(:background_nine_slice_from_edge)
|
117
|
+
|
118
|
+
@style.background_nine_slice_left = safe_style_fetch(:background_nine_slice_left, :background_nine_slice_from_edge)
|
119
|
+
@style.background_nine_slice_top = safe_style_fetch(:background_nine_slice_top, :background_nine_slice_from_edge)
|
120
|
+
@style.background_nine_slice_right = safe_style_fetch(:background_nine_slice_right, :background_nine_slice_from_edge)
|
121
|
+
@style.background_nine_slice_bottom = safe_style_fetch(:background_nine_slice_bottom, :background_nine_slice_from_edge)
|
122
|
+
end
|
123
|
+
|
124
|
+
def set_background_image
|
125
|
+
@style.background_image = safe_style_fetch(:background_image)
|
126
|
+
@style.background_image_mode = safe_style_fetch(:background_image_mode) || :stretch
|
127
|
+
@style.background_image_color = safe_style_fetch(:background_image_color) || Gosu::Color::WHITE
|
128
|
+
@style.background_image_canvas.mode = @style.background_image_mode
|
129
|
+
@style.background_image_canvas.color = @style.background_image_color
|
130
|
+
end
|
131
|
+
|
132
|
+
def set_border_thickness
|
133
|
+
@style.border_thickness = safe_style_fetch(:border_thickness)
|
134
|
+
|
135
|
+
@style.border_thickness_left = safe_style_fetch(:border_thickness_left, :border_thickness)
|
136
|
+
@style.border_thickness_right = safe_style_fetch(:border_thickness_right, :border_thickness)
|
137
|
+
@style.border_thickness_top = safe_style_fetch(:border_thickness_top, :border_thickness)
|
138
|
+
@style.border_thickness_bottom = safe_style_fetch(:border_thickness_bottom, :border_thickness)
|
139
|
+
end
|
140
|
+
|
141
|
+
def set_border_color
|
142
|
+
@style.border_color = safe_style_fetch(:border_color)
|
143
|
+
|
144
|
+
@style.border_color_left = safe_style_fetch(:border_color_left, :border_color)
|
145
|
+
@style.border_color_right = safe_style_fetch(:border_color_right, :border_color)
|
146
|
+
@style.border_color_top = safe_style_fetch(:border_color_top, :border_color)
|
147
|
+
@style.border_color_bottom = safe_style_fetch(:border_color_bottom, :border_color)
|
148
|
+
|
149
|
+
@style.border_canvas.color = [
|
150
|
+
@style.border_color_top,
|
151
|
+
@style.border_color_right,
|
152
|
+
@style.border_color_bottom,
|
153
|
+
@style.border_color_left
|
154
|
+
]
|
155
|
+
end
|
156
|
+
|
157
|
+
def set_padding
|
158
|
+
@style.padding = safe_style_fetch(:padding)
|
159
|
+
|
160
|
+
@style.padding_left = safe_style_fetch(:padding_left, :padding)
|
161
|
+
@style.padding_right = safe_style_fetch(:padding_right, :padding)
|
162
|
+
@style.padding_top = safe_style_fetch(:padding_top, :padding)
|
163
|
+
@style.padding_bottom = safe_style_fetch(:padding_bottom, :padding)
|
164
|
+
end
|
165
|
+
|
166
|
+
def set_margin
|
167
|
+
@style.margin = safe_style_fetch(:margin)
|
168
|
+
|
169
|
+
@style.margin_left = safe_style_fetch(:margin_left, :margin)
|
170
|
+
@style.margin_right = safe_style_fetch(:margin_right, :margin)
|
171
|
+
@style.margin_top = safe_style_fetch(:margin_top, :margin)
|
172
|
+
@style.margin_bottom = safe_style_fetch(:margin_bottom, :margin)
|
173
|
+
end
|
174
|
+
|
175
|
+
def update_styles(event = :default)
|
176
|
+
old_width = width
|
177
|
+
old_height = height
|
178
|
+
|
179
|
+
@style_event = event
|
180
|
+
|
181
|
+
return if self.is_a?(ToolTip)
|
182
|
+
|
183
|
+
root.gui_state.request_recalculate if old_width != width || old_height != height
|
184
|
+
|
185
|
+
stylize
|
186
|
+
end
|
187
|
+
|
188
|
+
def default_events
|
189
|
+
%i[left middle right].each do |button|
|
190
|
+
event(:"#{button}_mouse_button")
|
191
|
+
event(:"released_#{button}_mouse_button")
|
192
|
+
event(:"clicked_#{button}_mouse_button")
|
193
|
+
event(:"holding_#{button}_mouse_button")
|
194
|
+
end
|
195
|
+
|
196
|
+
event(:mouse_wheel_up)
|
197
|
+
event(:mouse_wheel_down)
|
198
|
+
event(:scroll_jump_to_top)
|
199
|
+
event(:scroll_jump_to_end)
|
200
|
+
event(:scroll_page_up)
|
201
|
+
event(:scroll_page_down)
|
202
|
+
|
203
|
+
event(:enter)
|
204
|
+
event(:hover)
|
205
|
+
event(:leave)
|
206
|
+
|
207
|
+
event(:focus)
|
208
|
+
event(:blur)
|
209
|
+
|
210
|
+
event(:changed)
|
211
|
+
end
|
212
|
+
|
213
|
+
def enter(_sender)
|
214
|
+
@focus = false unless Gosu.button_down?(Gosu::MS_LEFT)
|
215
|
+
|
216
|
+
if !@enabled
|
217
|
+
update_styles(:disabled)
|
218
|
+
elsif @focus
|
219
|
+
update_styles(:active)
|
220
|
+
else
|
221
|
+
update_styles(:hover)
|
222
|
+
end
|
223
|
+
|
224
|
+
:handled
|
225
|
+
end
|
226
|
+
|
227
|
+
def left_mouse_button(_sender, _x, _y)
|
228
|
+
@focus = true
|
229
|
+
|
230
|
+
unless @enabled
|
231
|
+
update_styles(:disabled)
|
232
|
+
else
|
233
|
+
update_styles(:active)
|
234
|
+
end
|
235
|
+
|
236
|
+
window.current_state.focus = self
|
237
|
+
|
238
|
+
:handled
|
239
|
+
end
|
240
|
+
|
241
|
+
def released_left_mouse_button(sender, _x, _y)
|
242
|
+
enter(sender)
|
243
|
+
|
244
|
+
:handled
|
245
|
+
end
|
246
|
+
|
247
|
+
def clicked_left_mouse_button(_sender, _x, _y)
|
248
|
+
@block&.call(self) if @enabled && !self.is_a?(Container)
|
249
|
+
|
250
|
+
:handled
|
251
|
+
end
|
252
|
+
|
253
|
+
def leave(_sender)
|
254
|
+
if @enabled
|
255
|
+
update_styles
|
256
|
+
else
|
257
|
+
update_styles(:disabled)
|
258
|
+
end
|
259
|
+
|
260
|
+
:handled
|
261
|
+
end
|
262
|
+
|
263
|
+
def blur(_sender)
|
264
|
+
@focus = false
|
265
|
+
|
266
|
+
if @enabled
|
267
|
+
update_styles
|
268
|
+
else
|
269
|
+
update_styles(:disabled)
|
270
|
+
end
|
271
|
+
|
272
|
+
:handled
|
273
|
+
end
|
274
|
+
|
275
|
+
def enabled=(boolean)
|
276
|
+
root.gui_state.request_repaint if @enabled != boolean
|
277
|
+
|
278
|
+
@enabled = boolean
|
279
|
+
|
280
|
+
recalculate
|
281
|
+
|
282
|
+
@enabled
|
283
|
+
end
|
284
|
+
|
285
|
+
def enabled?
|
286
|
+
@enabled
|
287
|
+
end
|
288
|
+
|
289
|
+
def focused?
|
290
|
+
@focus
|
291
|
+
end
|
292
|
+
|
293
|
+
def visible?
|
294
|
+
@visible
|
295
|
+
end
|
296
|
+
|
297
|
+
def element_visible?
|
298
|
+
@element_visible
|
299
|
+
end
|
300
|
+
|
301
|
+
def toggle
|
302
|
+
@visible = !@visible
|
303
|
+
root.gui_state.request_recalculate
|
304
|
+
root.gui_state.request_repaint
|
305
|
+
end
|
306
|
+
|
307
|
+
def show
|
308
|
+
bool = visible?
|
309
|
+
@visible = true
|
310
|
+
root.gui_state.request_recalculate unless bool
|
311
|
+
root.gui_state.request_repaint unless bool
|
312
|
+
end
|
313
|
+
|
314
|
+
def hide
|
315
|
+
bool = visible?
|
316
|
+
@visible = false
|
317
|
+
root.gui_state.request_recalculate if bool
|
318
|
+
root.gui_state.request_repaint if bool
|
319
|
+
end
|
320
|
+
|
321
|
+
def draw
|
322
|
+
return unless visible?
|
323
|
+
return unless element_visible?
|
324
|
+
|
325
|
+
@style.background_canvas.draw
|
326
|
+
@style.background_nine_slice_canvas.draw
|
327
|
+
@style.background_image_canvas.draw
|
328
|
+
@style.border_canvas.draw
|
329
|
+
|
330
|
+
render
|
331
|
+
end
|
332
|
+
|
333
|
+
def debug_draw
|
334
|
+
return if CyberarmEngine.const_defined?("GUI_DEBUG_ONLY_ELEMENT") && self.class == GUI_DEBUG_ONLY_ELEMENT
|
335
|
+
|
336
|
+
Gosu.draw_line(
|
337
|
+
x, y, @debug_color,
|
338
|
+
x + outer_width, y, @debug_color,
|
339
|
+
Float::INFINITY
|
340
|
+
)
|
341
|
+
Gosu.draw_line(
|
342
|
+
x + outer_width, y, @debug_color,
|
343
|
+
x + outer_width, y + outer_height, @debug_color,
|
344
|
+
Float::INFINITY
|
345
|
+
)
|
346
|
+
Gosu.draw_line(
|
347
|
+
x + outer_width, y + outer_height, @debug_color,
|
348
|
+
x, y + outer_height, @debug_color,
|
349
|
+
Float::INFINITY
|
350
|
+
)
|
351
|
+
Gosu.draw_line(
|
352
|
+
x, y + outer_height, @debug_color,
|
353
|
+
x, y, @debug_color,
|
354
|
+
Float::INFINITY
|
355
|
+
)
|
356
|
+
end
|
357
|
+
|
358
|
+
def update
|
359
|
+
recalculate_if_size_changed
|
360
|
+
end
|
361
|
+
|
362
|
+
def button_down(id)
|
363
|
+
end
|
364
|
+
|
365
|
+
def button_up(id)
|
366
|
+
end
|
367
|
+
|
368
|
+
def draggable?(_button)
|
369
|
+
false
|
370
|
+
end
|
371
|
+
|
372
|
+
def render
|
373
|
+
end
|
374
|
+
|
375
|
+
def hit?(x, y)
|
376
|
+
x.between?(@x, @x + width) &&
|
377
|
+
y.between?(@y, @y + height)
|
378
|
+
end
|
379
|
+
|
380
|
+
def width
|
381
|
+
if visible?
|
382
|
+
inner_width + @width
|
383
|
+
else
|
384
|
+
0
|
385
|
+
end
|
386
|
+
end
|
387
|
+
|
388
|
+
def content_width
|
389
|
+
@width
|
390
|
+
end
|
391
|
+
|
392
|
+
def noncontent_width
|
393
|
+
(inner_width + outer_width) - width
|
394
|
+
end
|
395
|
+
|
396
|
+
def outer_width
|
397
|
+
@style.margin_left + width + @style.margin_right
|
398
|
+
end
|
399
|
+
|
400
|
+
def inner_width
|
401
|
+
(@style.border_thickness_left + @style.padding_left) + (@style.padding_right + @style.border_thickness_right)
|
402
|
+
end
|
403
|
+
|
404
|
+
def height
|
405
|
+
if visible?
|
406
|
+
inner_height + @height
|
407
|
+
else
|
408
|
+
0
|
409
|
+
end
|
410
|
+
end
|
411
|
+
|
412
|
+
def content_height
|
413
|
+
@height
|
414
|
+
end
|
415
|
+
|
416
|
+
def noncontent_height
|
417
|
+
(inner_height + outer_height) - height
|
418
|
+
end
|
419
|
+
|
420
|
+
def outer_height
|
421
|
+
@style.margin_top + height + @style.margin_bottom
|
422
|
+
end
|
423
|
+
|
424
|
+
def inner_height
|
425
|
+
(@style.border_thickness_top + @style.padding_top) + (@style.padding_bottom + @style.border_thickness_bottom)
|
426
|
+
end
|
427
|
+
|
428
|
+
def scroll_width
|
429
|
+
return @cached_scroll_width if @cached_scroll_width && is_a?(Container)
|
430
|
+
|
431
|
+
@cached_scroll_width = @children.sum(&:outer_width)
|
432
|
+
end
|
433
|
+
|
434
|
+
def scroll_height
|
435
|
+
return @cached_scroll_height if @cached_scroll_height && is_a?(Container)
|
436
|
+
|
437
|
+
if is_a?(CyberarmEngine::Element::Flow)
|
438
|
+
return 0 if @children.size.zero?
|
439
|
+
|
440
|
+
pairs_ = []
|
441
|
+
sorted_children_ = @children.sort_by(&:y)
|
442
|
+
a_ = []
|
443
|
+
y_position_ = sorted_children_.first.y
|
444
|
+
|
445
|
+
sorted_children_.each do |child|
|
446
|
+
unless child.y == y_position_
|
447
|
+
y_position_ = child.y
|
448
|
+
pairs_ << a_
|
449
|
+
a_ = []
|
450
|
+
end
|
451
|
+
|
452
|
+
a_ << child
|
453
|
+
end
|
454
|
+
|
455
|
+
pairs_ << a_ unless pairs_.last == a_
|
456
|
+
|
457
|
+
@cached_scroll_height = pairs_.sum { |pair| + @style.padding_top + @style.border_thickness_top + pair.map(&:outer_height).max } + @style.padding_bottom + @style.border_thickness_bottom
|
458
|
+
else
|
459
|
+
@cached_scroll_height = @style.padding_top + @style.border_thickness_top + @children.sum(&:outer_height) + @style.padding_bottom + @style.border_thickness_bottom
|
460
|
+
end
|
461
|
+
end
|
462
|
+
|
463
|
+
def max_scroll_width
|
464
|
+
(scroll_width - outer_width).positive? ? scroll_width - outer_width : scroll_width
|
465
|
+
end
|
466
|
+
|
467
|
+
def max_scroll_height
|
468
|
+
(scroll_height - outer_height).positive? ? scroll_height - outer_height : scroll_height
|
469
|
+
end
|
470
|
+
|
471
|
+
def dimensional_size(size, dimension)
|
472
|
+
raise "dimension must be either :width or :height" unless %i[width height].include?(dimension)
|
473
|
+
|
474
|
+
new_size = if size.is_a?(Float) && size.between?(0.0, 1.0)
|
475
|
+
(@parent.send(:"content_#{dimension}") * size).floor - send(:"noncontent_#{dimension}").floor
|
476
|
+
else
|
477
|
+
size
|
478
|
+
end
|
479
|
+
|
480
|
+
# Handle fill behavior
|
481
|
+
if @parent && @style.fill &&
|
482
|
+
(dimension == :width && @parent.is_a?(Flow) ||
|
483
|
+
dimension == :height && @parent.is_a?(Stack))
|
484
|
+
new_size = space_available_width - noncontent_width if dimension == :width && @parent.is_a?(Flow)
|
485
|
+
new_size = space_available_height - noncontent_height if dimension == :height && @parent.is_a?(Stack)
|
486
|
+
end
|
487
|
+
|
488
|
+
return @style.send(:"min_#{dimension}") if @style.send(:"min_#{dimension}") && new_size.to_f < @style.send(:"min_#{dimension}")
|
489
|
+
return @style.send(:"max_#{dimension}") if @style.send(:"max_#{dimension}") && new_size.to_f > @style.send(:"max_#{dimension}")
|
490
|
+
|
491
|
+
new_size
|
492
|
+
end
|
493
|
+
|
494
|
+
def space_available_width
|
495
|
+
# TODO: This may get expensive if there are a lot of children, probably should cache it somehow
|
496
|
+
fill_siblings = @parent.children.select { |c| c.style.fill }.count.to_f # include self since we're dividing
|
497
|
+
|
498
|
+
available_space = ((@parent.content_width - (@parent.children.reject { |c| c.style.fill }).map(&:outer_width).sum) / fill_siblings)
|
499
|
+
(available_space.nan? || available_space.infinite?) ? 0 : available_space.floor # The parent element might not have its dimensions, yet.
|
500
|
+
end
|
501
|
+
|
502
|
+
def space_available_height
|
503
|
+
# TODO: This may get expensive if there are a lot of children, probably should cache it somehow
|
504
|
+
fill_siblings = @parent.children.select { |c| c.style.fill }.count.to_f # include self since we're dividing
|
505
|
+
|
506
|
+
available_space = ((@parent.content_height - (@parent.children.reject { |c| c.style.fill }).map(&:outer_height).sum) / fill_siblings)
|
507
|
+
(available_space.nan? || available_space.infinite?) ? 0 : available_space.floor # The parent element might not have its dimensions, yet.
|
508
|
+
end
|
509
|
+
|
510
|
+
def background=(_background)
|
511
|
+
root.gui_state.request_repaint
|
512
|
+
|
513
|
+
@style.background_canvas.background = _background
|
514
|
+
update_background
|
515
|
+
end
|
516
|
+
|
517
|
+
def update_background
|
518
|
+
@style.background_canvas.x = @x
|
519
|
+
@style.background_canvas.y = @y
|
520
|
+
@style.background_canvas.z = @z
|
521
|
+
@style.background_canvas.width = width
|
522
|
+
@style.background_canvas.height = height
|
523
|
+
|
524
|
+
@style.background_canvas.update
|
525
|
+
update_background_nine_slice
|
526
|
+
update_background_image
|
527
|
+
@style.border_canvas.update
|
528
|
+
end
|
529
|
+
|
530
|
+
def background_nine_slice=(_image_path)
|
531
|
+
root.gui_state.request_repaint
|
532
|
+
|
533
|
+
@style.background_nine_slice_canvas.image = _image_path
|
534
|
+
update_background_nine_slice
|
535
|
+
end
|
536
|
+
|
537
|
+
def update_background_nine_slice
|
538
|
+
@style.background_nine_slice_canvas.x = @x
|
539
|
+
@style.background_nine_slice_canvas.y = @y
|
540
|
+
@style.background_nine_slice_canvas.z = @z
|
541
|
+
@style.background_nine_slice_canvas.width = width
|
542
|
+
@style.background_nine_slice_canvas.height = height
|
543
|
+
|
544
|
+
@style.background_nine_slice_canvas.mode = @style.background_nine_slice_mode
|
545
|
+
|
546
|
+
@style.background_nine_slice_canvas.color = @style.background_nine_slice_color
|
547
|
+
|
548
|
+
@style.background_nine_slice_canvas.left = @style.background_nine_slice_left
|
549
|
+
@style.background_nine_slice_canvas.top = @style.background_nine_slice_top
|
550
|
+
@style.background_nine_slice_canvas.right = @style.background_nine_slice_right
|
551
|
+
@style.background_nine_slice_canvas.bottom = @style.background_nine_slice_bottom
|
552
|
+
|
553
|
+
@style.background_nine_slice_canvas.image = @style.background_nine_slice
|
554
|
+
end
|
555
|
+
|
556
|
+
def background_image=(image_path)
|
557
|
+
root.gui_state.request_repaint
|
558
|
+
|
559
|
+
@style.background_image = image_path.is_a?(Gosu::Image) ? image_path : get_image(image_path)
|
560
|
+
update_background_image
|
561
|
+
end
|
562
|
+
|
563
|
+
def update_background_image
|
564
|
+
@style.background_image_canvas.x = @x
|
565
|
+
@style.background_image_canvas.y = @y
|
566
|
+
@style.background_image_canvas.z = @z
|
567
|
+
@style.background_image_canvas.width = width
|
568
|
+
@style.background_image_canvas.height = height
|
569
|
+
|
570
|
+
@style.background_image_canvas.mode = @style.background_image_mode
|
571
|
+
@style.background_image_canvas.color = @style.background_image_color
|
572
|
+
|
573
|
+
@style.background_image_canvas.image = @style.background_image
|
574
|
+
end
|
575
|
+
|
576
|
+
def recalculate_if_size_changed
|
577
|
+
if @parent && !is_a?(ToolTip) && (@old_width != width || @old_height != height)
|
578
|
+
root.gui_state.request_recalculate
|
579
|
+
|
580
|
+
@old_width = width
|
581
|
+
@old_height = height
|
582
|
+
end
|
583
|
+
end
|
584
|
+
|
585
|
+
def root
|
586
|
+
return self if is_root?
|
587
|
+
|
588
|
+
unless @root && @root.parent.nil?
|
589
|
+
@root = parent
|
590
|
+
|
591
|
+
loop do
|
592
|
+
break unless @root&.parent
|
593
|
+
|
594
|
+
@root = @root.parent
|
595
|
+
end
|
596
|
+
end
|
597
|
+
|
598
|
+
@root
|
599
|
+
end
|
600
|
+
|
601
|
+
def is_root?
|
602
|
+
@gui_state != nil
|
603
|
+
end
|
604
|
+
|
605
|
+
def child_of?(element)
|
606
|
+
return element == self if is_root?
|
607
|
+
return false unless element.is_a?(Container)
|
608
|
+
return true if element.children.find { |child| child == self }
|
609
|
+
|
610
|
+
element.children.find { |child| child.child_of?(element) if child.is_a?(Container) }
|
611
|
+
end
|
612
|
+
|
613
|
+
def parent_of?(element)
|
614
|
+
return false if element == self
|
615
|
+
return false unless is_a?(Container)
|
616
|
+
return true if @children.find { |child| child == element }
|
617
|
+
|
618
|
+
@children.find { |child| child.parent_of?(element) if child.is_a?(Container) }
|
619
|
+
end
|
620
|
+
|
621
|
+
def focus(_)
|
622
|
+
warn "#{self.class}#focus was not overridden!"
|
623
|
+
|
624
|
+
:handled
|
625
|
+
end
|
626
|
+
|
627
|
+
def recalculate
|
628
|
+
old_width = width
|
629
|
+
old_height = height
|
630
|
+
|
631
|
+
stylize
|
632
|
+
layout
|
633
|
+
|
634
|
+
root.gui_state.request_recalculate if @parent && !is_a?(ToolTip) && (width != old_width || height != old_height)
|
635
|
+
root.gui_state.request_repaint if width != old_width || height != old_height
|
636
|
+
|
637
|
+
root.gui_state.menu.recalculate if root.gui_state.menu && root.gui_state.menu.parent == self
|
638
|
+
end
|
639
|
+
|
640
|
+
def layout
|
641
|
+
end
|
642
|
+
|
643
|
+
def reposition
|
644
|
+
end
|
645
|
+
|
646
|
+
def value
|
647
|
+
raise "#{self.class}#value was not overridden!"
|
648
|
+
end
|
649
|
+
|
650
|
+
def value=(_value)
|
651
|
+
raise "#{self.class}#value= was not overridden!"
|
652
|
+
end
|
653
|
+
|
654
|
+
def to_s
|
655
|
+
"#{self.class} x=#{x} y=#{y} width=#{width} height=#{height} value=#{value.is_a?(String) ? "\"#{value}\"" : value}"
|
656
|
+
end
|
657
|
+
|
658
|
+
def inspect
|
659
|
+
to_s
|
660
|
+
end
|
661
|
+
end
|
662
|
+
end
|