cyberarm_engine 0.25.0 → 0.30.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (118) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +9 -8
  3. data/.rubocop.yml +7 -7
  4. data/.travis.yml +5 -5
  5. data/Gemfile +6 -6
  6. data/Gemfile.lock +37 -25
  7. data/LICENSE.txt +21 -21
  8. data/README.md +74 -74
  9. data/Rakefile +10 -10
  10. data/assets/shaders/fragment/g_buffer.glsl +30 -30
  11. data/assets/shaders/fragment/lighting.glsl +115 -115
  12. data/assets/shaders/include/light_struct.glsl +11 -11
  13. data/assets/shaders/include/material_struct.glsl +16 -16
  14. data/assets/shaders/vertex/g_buffer.glsl +28 -28
  15. data/assets/shaders/vertex/lighting.glsl +24 -24
  16. data/assets/textures/ui/circle.png +0 -0
  17. data/assets/textures/ui/circle_small.png +0 -0
  18. data/assets/textures/ui/rounded.png +0 -0
  19. data/assets/textures/ui/rounded_bottom.png +0 -0
  20. data/assets/textures/ui/rounded_left.png +0 -0
  21. data/assets/textures/ui/rounded_left_bottom.png +0 -0
  22. data/assets/textures/ui/rounded_left_top.png +0 -0
  23. data/assets/textures/ui/rounded_right.png +0 -0
  24. data/assets/textures/ui/rounded_right_bottom.png +0 -0
  25. data/assets/textures/ui/rounded_right_top.png +0 -0
  26. data/assets/textures/ui/rounded_small.png +0 -0
  27. data/assets/textures/ui/rounded_tiny.png +0 -0
  28. data/assets/textures/ui/rounded_top.png +0 -0
  29. data/assets/textures/ui/square.png +0 -0
  30. data/bin/console +14 -14
  31. data/bin/setup +8 -8
  32. data/cyberarm_engine.gemspec +35 -36
  33. data/lib/cyberarm_engine/animator.rb +219 -219
  34. data/lib/cyberarm_engine/background.rb +156 -158
  35. data/lib/cyberarm_engine/background_image.rb +93 -93
  36. data/lib/cyberarm_engine/background_nine_slice.rb +182 -142
  37. data/lib/cyberarm_engine/bounding_box.rb +150 -150
  38. data/lib/cyberarm_engine/builtin/intro_state.rb +130 -130
  39. data/lib/cyberarm_engine/cache/download_manager.rb +123 -123
  40. data/lib/cyberarm_engine/cache.rb +4 -4
  41. data/lib/cyberarm_engine/common.rb +133 -131
  42. data/lib/cyberarm_engine/config_file.rb +46 -46
  43. data/lib/cyberarm_engine/console/command.rb +157 -157
  44. data/lib/cyberarm_engine/console/commands/help_command.rb +43 -43
  45. data/lib/cyberarm_engine/console/subcommand.rb +99 -99
  46. data/lib/cyberarm_engine/console.rb +248 -248
  47. data/lib/cyberarm_engine/event_bus.rb +39 -0
  48. data/lib/cyberarm_engine/game_object.rb +244 -244
  49. data/lib/cyberarm_engine/game_state.rb +134 -124
  50. data/lib/cyberarm_engine/gosu_ext/draw_arc.rb +111 -111
  51. data/lib/cyberarm_engine/gosu_ext/draw_circle.rb +30 -30
  52. data/lib/cyberarm_engine/gosu_ext/draw_path.rb +17 -17
  53. data/lib/cyberarm_engine/model/material.rb +21 -21
  54. data/lib/cyberarm_engine/model/mesh.rb +131 -131
  55. data/lib/cyberarm_engine/model/parser.rb +74 -74
  56. data/lib/cyberarm_engine/model/parsers/collada_parser.rb +138 -138
  57. data/lib/cyberarm_engine/model/parsers/wavefront_parser.rb +154 -154
  58. data/lib/cyberarm_engine/model.rb +216 -216
  59. data/lib/cyberarm_engine/model_cache.rb +31 -31
  60. data/lib/cyberarm_engine/notification.rb +82 -82
  61. data/lib/cyberarm_engine/notification_manager.rb +241 -241
  62. data/lib/cyberarm_engine/opengl/light.rb +52 -52
  63. data/lib/cyberarm_engine/opengl/orthographic_camera.rb +46 -46
  64. data/lib/cyberarm_engine/opengl/perspective_camera.rb +41 -41
  65. data/lib/cyberarm_engine/opengl/renderer/bounding_box_renderer.rb +249 -249
  66. data/lib/cyberarm_engine/opengl/renderer/g_buffer.rb +167 -167
  67. data/lib/cyberarm_engine/opengl/renderer/opengl_renderer.rb +307 -307
  68. data/lib/cyberarm_engine/opengl/renderer/renderer.rb +33 -33
  69. data/lib/cyberarm_engine/opengl/shader.rb +408 -408
  70. data/lib/cyberarm_engine/opengl/texture.rb +69 -69
  71. data/lib/cyberarm_engine/opengl.rb +53 -53
  72. data/lib/cyberarm_engine/pathfinding/graph.rb +64 -0
  73. data/lib/cyberarm_engine/pathfinding/graph_search.rb +6 -0
  74. data/lib/cyberarm_engine/pathfinding/graph_searches/astar_search.rb +6 -0
  75. data/lib/cyberarm_engine/pathfinding/graph_searches/breadth_first_search.rb +27 -0
  76. data/lib/cyberarm_engine/pathfinding/graph_searches/dijkstra_search.rb +6 -0
  77. data/lib/cyberarm_engine/pathfinding/graphs/grid.rb +52 -0
  78. data/lib/cyberarm_engine/ray.rb +56 -56
  79. data/lib/cyberarm_engine/result.rb +19 -0
  80. data/lib/cyberarm_engine/stats.rb +200 -200
  81. data/lib/cyberarm_engine/text.rb +288 -260
  82. data/lib/cyberarm_engine/timer.rb +27 -23
  83. data/lib/cyberarm_engine/transform.rb +296 -296
  84. data/lib/cyberarm_engine/trees/aabb_node.rb +126 -126
  85. data/lib/cyberarm_engine/trees/aabb_tree.rb +55 -55
  86. data/lib/cyberarm_engine/trees/aabb_tree_debug.rb +29 -29
  87. data/lib/cyberarm_engine/ui/border_canvas.rb +102 -102
  88. data/lib/cyberarm_engine/ui/dialog.rb +24 -0
  89. data/lib/cyberarm_engine/ui/dsl.rb +170 -142
  90. data/lib/cyberarm_engine/ui/element.rb +664 -662
  91. data/lib/cyberarm_engine/ui/elements/button.rb +99 -100
  92. data/lib/cyberarm_engine/ui/elements/check_box.rb +58 -54
  93. data/lib/cyberarm_engine/ui/elements/container.rb +413 -407
  94. data/lib/cyberarm_engine/ui/elements/edit_box.rb +200 -179
  95. data/lib/cyberarm_engine/ui/elements/edit_line.rb +299 -297
  96. data/lib/cyberarm_engine/ui/elements/flow.rb +15 -15
  97. data/lib/cyberarm_engine/ui/elements/image.rb +78 -72
  98. data/lib/cyberarm_engine/ui/elements/list_box.rb +79 -79
  99. data/lib/cyberarm_engine/ui/elements/menu.rb +27 -27
  100. data/lib/cyberarm_engine/ui/elements/menu_item.rb +6 -6
  101. data/lib/cyberarm_engine/ui/elements/progress.rb +95 -93
  102. data/lib/cyberarm_engine/ui/elements/radio.rb +6 -6
  103. data/lib/cyberarm_engine/ui/elements/slider.rb +111 -107
  104. data/lib/cyberarm_engine/ui/elements/stack.rb +11 -11
  105. data/lib/cyberarm_engine/ui/elements/text_block.rb +236 -222
  106. data/lib/cyberarm_engine/ui/elements/toggle_button.rb +71 -67
  107. data/lib/cyberarm_engine/ui/elements/widget.rb +45 -0
  108. data/lib/cyberarm_engine/ui/event.rb +54 -54
  109. data/lib/cyberarm_engine/ui/gui_state.rb +402 -326
  110. data/lib/cyberarm_engine/ui/page.rb +39 -0
  111. data/lib/cyberarm_engine/ui/style.rb +94 -61
  112. data/lib/cyberarm_engine/ui/theme.rb +237 -225
  113. data/lib/cyberarm_engine/vector.rb +312 -312
  114. data/lib/cyberarm_engine/version.rb +4 -4
  115. data/lib/cyberarm_engine/window.rb +234 -195
  116. data/lib/cyberarm_engine.rb +88 -76
  117. data/mrbgem.rake +29 -29
  118. metadata +30 -5
@@ -1,248 +1,248 @@
1
- # frozen_string_literal: true
2
-
3
- module CyberarmEngine
4
- class Console
5
- Z = 100_000
6
- PADDING = 2
7
- include Common
8
-
9
- attr_reader :text_input
10
-
11
- def initialize(font: Gosu.default_font_name)
12
- @text_input = Gosu::TextInput.new
13
- @width = window.width / 4 * 3
14
- @height = window.height / 4 * 3
15
-
16
- @input = Text.new("", x: 4, y: @height - (PADDING * 2), z: Console::Z + 1, font: font)
17
- @input.y -= @input.height
18
-
19
- @history = Text.new("", x: 4, z: Console::Z + 1, font: font, border: true, border_color: Gosu::Color::BLACK)
20
- update_history_y
21
-
22
- @command_history = []
23
- @command_history_index = 0
24
-
25
- @memory = ""
26
-
27
- @background_color = Gosu::Color.rgba(0, 0, 0, 200)
28
- @foreground_color = Gosu::Color.rgba(100, 100, 100, 100)
29
- @input_color = Gosu::Color.rgba(100, 100, 100, 200)
30
-
31
- @showing_cursor = false
32
- @active_text_input = nil
33
-
34
- @show_caret = true
35
- @caret_last_change = Gosu.milliseconds
36
- @caret_interval = 250
37
- @caret_color = Gosu::Color::WHITE
38
- @selection_color = Gosu::Color.new(0x5522ff22)
39
- end
40
-
41
- def draw
42
- # Background/Border
43
- draw_rect(0, 0, @width, @height, @background_color, Console::Z)
44
- # Foregound/History
45
- draw_rect(PADDING, PADDING, @width - (PADDING * 2), @height - (PADDING * 2), @foreground_color, Console::Z)
46
- # Text bar
47
- draw_rect(2, @input.y, @width - (PADDING * 2), @input.height, @input_color, Console::Z)
48
-
49
- @history.draw
50
- @input.draw
51
- # Caret
52
- if @show_caret
53
- draw_rect(@input.x + caret_from_left, @input.y, Console::PADDING, @input.height, @caret_color, Console::Z + 2)
54
- end
55
- # Caret selection
56
- if caret_start != caret_end
57
- if caret_start < @text_input.selection_start
58
- draw_rect(@input.x + caret_from_left, @input.y, caret_selection_width, @input.height, @selection_color, Console::Z)
59
- else
60
- draw_rect((@input.x + caret_from_left) - caret_selection_width, @input.y, caret_selection_width, @input.height, @selection_color, Console::Z)
61
- end
62
- end
63
- end
64
-
65
- def caret_from_left
66
- return 0 if @text_input.caret_pos.zero?
67
-
68
- @input.textobject.text_width(@text_input.text[0..@text_input.caret_pos - 1])
69
- end
70
-
71
- def caret_selection_width
72
- @input.textobject.text_width(@text_input.text[caret_start..(caret_end - 1)])
73
- end
74
-
75
- def caret_pos
76
- @text_input.caret_pos
77
- end
78
-
79
- def caret_start
80
- @text_input.selection_start < @text_input.caret_pos ? @text_input.selection_start : @text_input.caret_pos
81
- end
82
-
83
- def caret_end
84
- @text_input.selection_start > @text_input.caret_pos ? @text_input.selection_start : @text_input.caret_pos
85
- end
86
-
87
- def update
88
- if Gosu.milliseconds - @caret_last_change >= @caret_interval
89
- @caret_last_change = Gosu.milliseconds
90
- @show_caret = !@show_caret
91
- end
92
-
93
- if @width != window.width || @height != @height
94
- @width = window.width / 4 * 3
95
- @height = window.height / 4 * 3
96
-
97
- @input.y = @height - (PADDING * 2 + @input.height)
98
- update_history_y
99
- end
100
-
101
- @input.text = @text_input.text
102
- end
103
-
104
- def button_down(id)
105
- case id
106
- when Gosu::KB_ENTER, Gosu::KB_RETURN
107
- return unless @text_input.text.length.positive?
108
-
109
- @history.text += "\n<c=999999>> #{@text_input.text}</c>"
110
- @command_history << @text_input.text
111
- @command_history_index = @command_history.size
112
- update_history_y
113
- handle_command
114
- @text_input.text = ""
115
-
116
- when Gosu::KB_UP
117
- @command_history_index -= 1
118
- @command_history_index = 0 if @command_history_index.negative?
119
- @text_input.text = @command_history[@command_history_index]
120
-
121
- when Gosu::KB_DOWN
122
- @command_history_index += 1
123
- if @command_history_index > @command_history.size - 1
124
- @text_input.text = "" unless @command_history_index > @command_history.size
125
- @command_history_index = @command_history.size
126
- else
127
- @text_input.text = @command_history[@command_history_index]
128
- end
129
-
130
- when Gosu::KB_TAB
131
- split = @text_input.text.split(" ")
132
-
133
- if !@text_input.text.end_with?(" ") && split.size == 1
134
- list = abbrev_search(Console::Command.list_commands.map { |cmd| cmd.command.to_s }, @text_input.text)
135
-
136
- if list.size == 1
137
- @text_input.text = "#{list.first} "
138
- elsif list.size.positive?
139
- stdin("\n#{list.map { |cmd| Console::Style.highlight(cmd) }.join(', ')}")
140
- end
141
- elsif split.size.positive? && cmd = Console::Command.find(split.first)
142
- cmd.autocomplete(self)
143
- end
144
-
145
- when Gosu::KB_BACKTICK
146
- # Remove backtick character from input
147
- @text_input.text = if @text_input.text.size > 1
148
- @text_input.text[0..@text_input.text.size - 2]
149
- else
150
- ""
151
- end
152
-
153
- # Copy
154
- when Gosu::KB_C
155
- if control_down? && shift_down?
156
- @memory = @text_input.text[caret_start..caret_end - 1] if caret_start != caret_end
157
- p @memory
158
- elsif control_down?
159
- @text_input.text = ""
160
- end
161
-
162
- # Paste
163
- when Gosu::KB_V
164
- if control_down? && shift_down?
165
- string = @text_input.text.chars.insert(caret_pos, @memory).join
166
- _caret_pos = caret_pos
167
- @text_input.text = string
168
- @text_input.caret_pos = _caret_pos + @memory.length
169
- @text_input.selection_start = _caret_pos + @memory.length
170
- end
171
-
172
- # Cut
173
- when Gosu::KB_X
174
- if control_down? && shift_down?
175
- @memory = @text_input.text[caret_start..caret_end - 1] if caret_start != caret_end
176
- string = @text_input.text.chars
177
- Array(caret_start..caret_end - 1).each_with_index do |i, j|
178
- string.delete_at(i - j)
179
- end
180
-
181
- @text_input.text = string.join
182
- end
183
-
184
- # Delete word to left of caret
185
- when Gosu::KB_W
186
- if control_down?
187
- split = @text_input.text.split(" ")
188
- split.delete(split.last)
189
- @text_input.text = split.join(" ")
190
- end
191
-
192
- # Clear history
193
- when Gosu::KB_L
194
- @history.text = "" if control_down?
195
- end
196
- end
197
-
198
- def button_up(id)
199
- end
200
-
201
- def update_history_y
202
- @history.y = @height - (PADDING * 2) - @input.height - (@history.text.lines.count * @history.textobject.height)
203
- end
204
-
205
- def handle_command
206
- string = @text_input.text
207
- split = string.split(" ")
208
- command = split.first
209
- arguments = split.length.positive? ? split[1..split.length - 1] : []
210
-
211
- CyberarmEngine::Console::Command.use(command, arguments, self)
212
- end
213
-
214
- def abbrev_search(array, text)
215
- return [] unless text.length.positive?
216
-
217
- list = []
218
- Abbrev.abbrev(array).each do |abbrev, value|
219
- next unless abbrev&.start_with?(text)
220
-
221
- list << value
222
- end
223
-
224
- list.uniq
225
- end
226
-
227
- def stdin(string)
228
- @history.text += "\n#{string}"
229
- update_history_y
230
- end
231
-
232
- def focus
233
- @active_text_input = window.text_input
234
- window.text_input = @text_input
235
-
236
- @showing_cursor = window.needs_cursor
237
- window.needs_cursor = true
238
-
239
- @show_caret = true
240
- @caret_last_change = Gosu.milliseconds
241
- end
242
-
243
- def blur
244
- window.text_input = @active_text_input
245
- window.needs_cursor = @showing_cursor
246
- end
247
- end
248
- end
1
+ # frozen_string_literal: true
2
+
3
+ module CyberarmEngine
4
+ class Console
5
+ Z = 100_000
6
+ PADDING = 2
7
+ include Common
8
+
9
+ attr_reader :text_input
10
+
11
+ def initialize(font: Gosu.default_font_name)
12
+ @text_input = Gosu::TextInput.new
13
+ @width = window.width / 4 * 3
14
+ @height = window.height / 4 * 3
15
+
16
+ @input = Text.new("", x: 4, y: @height - (PADDING * 2), z: Console::Z + 1, font: font)
17
+ @input.y -= @input.height
18
+
19
+ @history = Text.new("", x: 4, z: Console::Z + 1, font: font, border: true, border_color: Gosu::Color::BLACK)
20
+ update_history_y
21
+
22
+ @command_history = []
23
+ @command_history_index = 0
24
+
25
+ @memory = ""
26
+
27
+ @background_color = Gosu::Color.rgba(0, 0, 0, 200)
28
+ @foreground_color = Gosu::Color.rgba(100, 100, 100, 100)
29
+ @input_color = Gosu::Color.rgba(100, 100, 100, 200)
30
+
31
+ @showing_cursor = false
32
+ @active_text_input = nil
33
+
34
+ @show_caret = true
35
+ @caret_last_change = Gosu.milliseconds
36
+ @caret_interval = 250
37
+ @caret_color = Gosu::Color::WHITE
38
+ @selection_color = Gosu::Color.new(0x5522ff22)
39
+ end
40
+
41
+ def draw
42
+ # Background/Border
43
+ draw_rect(0, 0, @width, @height, @background_color, Console::Z)
44
+ # Foregound/History
45
+ draw_rect(PADDING, PADDING, @width - (PADDING * 2), @height - (PADDING * 2), @foreground_color, Console::Z)
46
+ # Text bar
47
+ draw_rect(2, @input.y, @width - (PADDING * 2), @input.height, @input_color, Console::Z)
48
+
49
+ @history.draw
50
+ @input.draw
51
+ # Caret
52
+ if @show_caret
53
+ draw_rect(@input.x + caret_from_left, @input.y, Console::PADDING, @input.height, @caret_color, Console::Z + 2)
54
+ end
55
+ # Caret selection
56
+ if caret_start != caret_end
57
+ if caret_start < @text_input.selection_start
58
+ draw_rect(@input.x + caret_from_left, @input.y, caret_selection_width, @input.height, @selection_color, Console::Z)
59
+ else
60
+ draw_rect((@input.x + caret_from_left) - caret_selection_width, @input.y, caret_selection_width, @input.height, @selection_color, Console::Z)
61
+ end
62
+ end
63
+ end
64
+
65
+ def caret_from_left
66
+ return 0 if @text_input.caret_pos.zero?
67
+
68
+ @input.textobject.text_width(@text_input.text[0..@text_input.caret_pos - 1])
69
+ end
70
+
71
+ def caret_selection_width
72
+ @input.textobject.text_width(@text_input.text[caret_start..(caret_end - 1)])
73
+ end
74
+
75
+ def caret_pos
76
+ @text_input.caret_pos
77
+ end
78
+
79
+ def caret_start
80
+ @text_input.selection_start < @text_input.caret_pos ? @text_input.selection_start : @text_input.caret_pos
81
+ end
82
+
83
+ def caret_end
84
+ @text_input.selection_start > @text_input.caret_pos ? @text_input.selection_start : @text_input.caret_pos
85
+ end
86
+
87
+ def update
88
+ if Gosu.milliseconds - @caret_last_change >= @caret_interval
89
+ @caret_last_change = Gosu.milliseconds
90
+ @show_caret = !@show_caret
91
+ end
92
+
93
+ if @width != window.width || @height != @height
94
+ @width = window.width / 4 * 3
95
+ @height = window.height / 4 * 3
96
+
97
+ @input.y = @height - (PADDING * 2 + @input.height)
98
+ update_history_y
99
+ end
100
+
101
+ @input.text = @text_input.text
102
+ end
103
+
104
+ def button_down(id)
105
+ case id
106
+ when Gosu::KB_ENTER, Gosu::KB_RETURN
107
+ return unless @text_input.text.length.positive?
108
+
109
+ @history.text += "\n<c=999999>> #{@text_input.text}</c>"
110
+ @command_history << @text_input.text
111
+ @command_history_index = @command_history.size
112
+ update_history_y
113
+ handle_command
114
+ @text_input.text = ""
115
+
116
+ when Gosu::KB_UP
117
+ @command_history_index -= 1
118
+ @command_history_index = 0 if @command_history_index.negative?
119
+ @text_input.text = @command_history[@command_history_index]
120
+
121
+ when Gosu::KB_DOWN
122
+ @command_history_index += 1
123
+ if @command_history_index > @command_history.size - 1
124
+ @text_input.text = "" unless @command_history_index > @command_history.size
125
+ @command_history_index = @command_history.size
126
+ else
127
+ @text_input.text = @command_history[@command_history_index]
128
+ end
129
+
130
+ when Gosu::KB_TAB
131
+ split = @text_input.text.split(" ")
132
+
133
+ if !@text_input.text.end_with?(" ") && split.size == 1
134
+ list = abbrev_search(Console::Command.list_commands.map { |cmd| cmd.command.to_s }, @text_input.text)
135
+
136
+ if list.size == 1
137
+ @text_input.text = "#{list.first} "
138
+ elsif list.size.positive?
139
+ stdin("\n#{list.map { |cmd| Console::Style.highlight(cmd) }.join(', ')}")
140
+ end
141
+ elsif split.size.positive? && cmd = Console::Command.find(split.first)
142
+ cmd.autocomplete(self)
143
+ end
144
+
145
+ when Gosu::KB_BACKTICK
146
+ # Remove backtick character from input
147
+ @text_input.text = if @text_input.text.size > 1
148
+ @text_input.text[0..@text_input.text.size - 2]
149
+ else
150
+ ""
151
+ end
152
+
153
+ # Copy
154
+ when Gosu::KB_C
155
+ if control_down? && shift_down?
156
+ @memory = @text_input.text[caret_start..caret_end - 1] if caret_start != caret_end
157
+ p @memory
158
+ elsif control_down?
159
+ @text_input.text = ""
160
+ end
161
+
162
+ # Paste
163
+ when Gosu::KB_V
164
+ if control_down? && shift_down?
165
+ string = @text_input.text.chars.insert(caret_pos, @memory).join
166
+ _caret_pos = caret_pos
167
+ @text_input.text = string
168
+ @text_input.caret_pos = _caret_pos + @memory.length
169
+ @text_input.selection_start = _caret_pos + @memory.length
170
+ end
171
+
172
+ # Cut
173
+ when Gosu::KB_X
174
+ if control_down? && shift_down?
175
+ @memory = @text_input.text[caret_start..caret_end - 1] if caret_start != caret_end
176
+ string = @text_input.text.chars
177
+ Array(caret_start..caret_end - 1).each_with_index do |i, j|
178
+ string.delete_at(i - j)
179
+ end
180
+
181
+ @text_input.text = string.join
182
+ end
183
+
184
+ # Delete word to left of caret
185
+ when Gosu::KB_W
186
+ if control_down?
187
+ split = @text_input.text.split(" ")
188
+ split.delete(split.last)
189
+ @text_input.text = split.join(" ")
190
+ end
191
+
192
+ # Clear history
193
+ when Gosu::KB_L
194
+ @history.text = "" if control_down?
195
+ end
196
+ end
197
+
198
+ def button_up(id)
199
+ end
200
+
201
+ def update_history_y
202
+ @history.y = @height - (PADDING * 2) - @input.height - (@history.text.lines.count * @history.textobject.height)
203
+ end
204
+
205
+ def handle_command
206
+ string = @text_input.text
207
+ split = string.split(" ")
208
+ command = split.first
209
+ arguments = split.length.positive? ? split[1..split.length - 1] : []
210
+
211
+ CyberarmEngine::Console::Command.use(command, arguments, self)
212
+ end
213
+
214
+ def abbrev_search(array, text)
215
+ return [] unless text.length.positive?
216
+
217
+ list = []
218
+ Abbrev.abbrev(array).each do |abbrev, value|
219
+ next unless abbrev&.start_with?(text)
220
+
221
+ list << value
222
+ end
223
+
224
+ list.uniq
225
+ end
226
+
227
+ def stdin(string)
228
+ @history.text += "\n#{string}"
229
+ update_history_y
230
+ end
231
+
232
+ def focus
233
+ @active_text_input = window.text_input
234
+ window.text_input = @text_input
235
+
236
+ @showing_cursor = window.needs_cursor
237
+ window.needs_cursor = true
238
+
239
+ @show_caret = true
240
+ @caret_last_change = Gosu.milliseconds
241
+ end
242
+
243
+ def blur
244
+ window.text_input = @active_text_input
245
+ window.needs_cursor = @showing_cursor
246
+ end
247
+ end
248
+ end
@@ -0,0 +1,39 @@
1
+ module CyberarmEngine
2
+ class EventBus
3
+ Subscriber = Data.define(:event, :listener, :method, :callback)
4
+ @subscribers = []
5
+
6
+ def self.subscribe(event, listener = nil, method = nil, &block)
7
+ raise "Subscriber cannot have both a method AND a callback block" if method && block_given?
8
+
9
+ subscriber = Subscriber.new(event, listener, method, block)
10
+ @subscribers << subscriber
11
+
12
+ subscriber
13
+ end
14
+
15
+ def self.unsubscribe(event, listener_or_subscriber)
16
+ @subscribers.delete_if { |s| s.event == event && (s == listener_or_subscriber || s.listener == listener_or_subscriber) }
17
+ end
18
+
19
+ def self.unsubscribe!(event)
20
+ @subscribers.delete_if { |s| s.event == event }
21
+ end
22
+
23
+ def self.announce(event, *payload)
24
+ subscribers = @subscribers.select { |s| s.event == event }
25
+
26
+ subscribers.each do |subscriber|
27
+ subscriber&.listener&.send(subscriber.method, *payload) if subscriber&.method
28
+ subscriber.callback&.call(*payload)
29
+ rescue StandardError => e
30
+ # TODO
31
+ warn "Failed to deliver event (#{event}) to listener (#{subscriber.inspect}): #{e}"
32
+ end
33
+ end
34
+
35
+ def self.publish(*args)
36
+ announce(*args)
37
+ end
38
+ end
39
+ end