cyberarm_engine 0.13.0 → 0.17.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (73) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +8 -8
  3. data/.rubocop.yml +8 -0
  4. data/.travis.yml +5 -5
  5. data/Gemfile +6 -6
  6. data/LICENSE.txt +21 -21
  7. data/README.md +73 -43
  8. data/Rakefile +10 -10
  9. data/assets/textures/default.png +0 -0
  10. data/bin/console +14 -14
  11. data/bin/setup +8 -8
  12. data/cyberarm_engine.gemspec +39 -36
  13. data/lib/cyberarm_engine.rb +64 -47
  14. data/lib/cyberarm_engine/animator.rb +56 -54
  15. data/lib/cyberarm_engine/background.rb +179 -175
  16. data/lib/cyberarm_engine/background_nine_slice.rb +125 -0
  17. data/lib/cyberarm_engine/bounding_box.rb +150 -150
  18. data/lib/cyberarm_engine/cache.rb +4 -0
  19. data/lib/cyberarm_engine/cache/download_manager.rb +121 -0
  20. data/lib/cyberarm_engine/common.rb +96 -96
  21. data/lib/cyberarm_engine/config_file.rb +46 -0
  22. data/lib/cyberarm_engine/game_object.rb +248 -257
  23. data/lib/cyberarm_engine/game_state.rb +92 -89
  24. data/lib/cyberarm_engine/model.rb +207 -0
  25. data/lib/cyberarm_engine/model/material.rb +21 -0
  26. data/lib/cyberarm_engine/model/model_object.rb +131 -0
  27. data/lib/cyberarm_engine/model/parser.rb +74 -0
  28. data/lib/cyberarm_engine/model/parsers/collada_parser.rb +138 -0
  29. data/lib/cyberarm_engine/model/parsers/wavefront_parser.rb +154 -0
  30. data/lib/cyberarm_engine/model_cache.rb +31 -0
  31. data/lib/cyberarm_engine/opengl.rb +28 -0
  32. data/lib/cyberarm_engine/opengl/light.rb +50 -0
  33. data/lib/cyberarm_engine/opengl/orthographic_camera.rb +46 -0
  34. data/lib/cyberarm_engine/opengl/perspective_camera.rb +38 -0
  35. data/lib/cyberarm_engine/opengl/renderer/bounding_box_renderer.rb +249 -0
  36. data/lib/cyberarm_engine/opengl/renderer/g_buffer.rb +164 -0
  37. data/lib/cyberarm_engine/opengl/renderer/opengl_renderer.rb +289 -0
  38. data/lib/cyberarm_engine/opengl/renderer/renderer.rb +22 -0
  39. data/lib/cyberarm_engine/opengl/shader.rb +406 -0
  40. data/lib/cyberarm_engine/opengl/texture.rb +69 -0
  41. data/lib/cyberarm_engine/ray.rb +56 -56
  42. data/lib/cyberarm_engine/stats.rb +21 -0
  43. data/lib/cyberarm_engine/text.rb +160 -146
  44. data/lib/cyberarm_engine/timer.rb +23 -23
  45. data/lib/cyberarm_engine/transform.rb +296 -273
  46. data/lib/cyberarm_engine/ui/border_canvas.rb +102 -101
  47. data/lib/cyberarm_engine/ui/dsl.rb +138 -99
  48. data/lib/cyberarm_engine/ui/element.rb +315 -276
  49. data/lib/cyberarm_engine/ui/elements/button.rb +160 -67
  50. data/lib/cyberarm_engine/ui/elements/check_box.rb +51 -59
  51. data/lib/cyberarm_engine/ui/elements/container.rb +256 -176
  52. data/lib/cyberarm_engine/ui/elements/edit_box.rb +179 -0
  53. data/lib/cyberarm_engine/ui/elements/edit_line.rb +262 -172
  54. data/lib/cyberarm_engine/ui/elements/flow.rb +15 -17
  55. data/lib/cyberarm_engine/ui/elements/image.rb +72 -52
  56. data/lib/cyberarm_engine/ui/elements/label.rb +156 -50
  57. data/lib/cyberarm_engine/ui/elements/list_box.rb +82 -0
  58. data/lib/cyberarm_engine/ui/elements/progress.rb +51 -50
  59. data/lib/cyberarm_engine/ui/elements/radio.rb +6 -0
  60. data/lib/cyberarm_engine/ui/elements/slider.rb +104 -0
  61. data/lib/cyberarm_engine/ui/elements/stack.rb +11 -13
  62. data/lib/cyberarm_engine/ui/elements/text_block.rb +156 -0
  63. data/lib/cyberarm_engine/ui/elements/toggle_button.rb +65 -56
  64. data/lib/cyberarm_engine/ui/event.rb +47 -47
  65. data/lib/cyberarm_engine/ui/gui_state.rb +226 -135
  66. data/lib/cyberarm_engine/ui/style.rb +38 -37
  67. data/lib/cyberarm_engine/ui/theme.rb +182 -120
  68. data/lib/cyberarm_engine/vector.rb +293 -203
  69. data/lib/cyberarm_engine/version.rb +4 -4
  70. data/lib/cyberarm_engine/{engine.rb → window.rb} +114 -101
  71. metadata +88 -18
  72. data/lib/cyberarm_engine/gosu_ext/circle.rb +0 -9
  73. data/lib/cyberarm_engine/shader.rb +0 -262
@@ -0,0 +1,179 @@
1
+ module CyberarmEngine
2
+ class Element
3
+ class EditBox < EditLine
4
+ def initialize(*args)
5
+ super(*args)
6
+
7
+ @active_line = 0
8
+
9
+ @repeatable_keys = [
10
+ {
11
+ key: Gosu::KB_UP,
12
+ down: false,
13
+ repeat_delay: 50,
14
+ last_repeat: 0,
15
+ action: proc { move(:up) }
16
+ },
17
+ {
18
+ key: Gosu::KB_DOWN,
19
+ down: false,
20
+ repeat_delay: 50,
21
+ last_repeat: 0,
22
+ action: proc { move(:down) }
23
+ }
24
+ ]
25
+ end
26
+
27
+ def update
28
+ super
29
+
30
+ caret_stay_left_of_last_newline
31
+ calculate_active_line
32
+
33
+ @repeatable_keys.each do |key|
34
+ if key[:down] && (Gosu.milliseconds > key[:last_repeat] + key[:repeat_delay])
35
+ key[:action].call
36
+ key[:last_repeat] = Gosu.milliseconds
37
+ end
38
+ end
39
+ end
40
+
41
+ def draw_caret
42
+ Gosu.draw_rect(caret_position, @text.y + @active_line * @text.textobject.height, @caret_width, @caret_height,
43
+ @caret_color, @z)
44
+ end
45
+
46
+ def draw_selection
47
+ selection_width = caret_position - selection_start_position
48
+
49
+ Gosu.draw_rect(selection_start_position, @text.y, selection_width, @text.textobject.height,
50
+ default(:selection_color), @z)
51
+ end
52
+
53
+ def text_input_position_for(_method)
54
+ line = @text_input.text[0...@text_input.caret_pos].lines.last
55
+ _x = @text.x + @offset_x
56
+
57
+ if @type == :password
58
+ _x + @text.width(default(:password_character) * line.length)
59
+ else
60
+ _x + @text.width(line)
61
+ end
62
+ end
63
+
64
+ def set_position(int)
65
+ int = 0 if int < 0
66
+ @text_input.selection_start = @text_input.caret_pos = int
67
+ end
68
+
69
+ def calculate_active_line
70
+ sub_text = @text_input.text[0...@text_input.caret_pos]
71
+ @active_line = sub_text.lines.size - 1
72
+ end
73
+
74
+ def caret_stay_left_of_last_newline
75
+ @text_input.text += "\n" unless @text_input.text.end_with?("\n")
76
+
77
+ eof = @text_input.text.chomp.length
78
+ set_position(eof) if @text_input.caret_pos > eof
79
+ end
80
+
81
+ def caret_position_under_mouse(mouse_x, mouse_y)
82
+ active_line = row_at(mouse_y)
83
+ right_offset = column_at(mouse_x, mouse_y)
84
+
85
+ buffer = @text_input.text.lines[0..active_line].join if active_line != 0
86
+ buffer = @text_input.text.lines.first if active_line == 0
87
+ line = buffer.lines.last
88
+
89
+ if buffer.chars.last == "\n"
90
+ (buffer.length - line.length) + right_offset - 1
91
+ else
92
+ (buffer.length - line.length) + right_offset
93
+ end
94
+ end
95
+
96
+ def move_caret_to_mouse(mouse_x, mouse_y)
97
+ set_position(caret_position_under_mouse(mouse_x, mouse_y))
98
+ end
99
+
100
+ def row_at(y)
101
+ ((y - @text.y) / @text.textobject.height).round
102
+ end
103
+
104
+ def column_at(x, y)
105
+ row = row_at(y)
106
+
107
+ buffer = @text_input.text.lines[0..row].join if row != 0
108
+ buffer = @text_input.text.lines.first if row == 0
109
+
110
+ line = @text_input.text.lines[row]
111
+ line ||= ""
112
+ column = 0
113
+
114
+ line.length.times do |_i|
115
+ break if @text.textobject.text_width(line[0...column]) >= (x - @text.x).clamp(0.0, Float::INFINITY)
116
+
117
+ column += 1
118
+ end
119
+
120
+ column
121
+ end
122
+
123
+ def button_down(id)
124
+ super
125
+
126
+ @repeatable_keys.detect do |key|
127
+ next unless key[:key] == id
128
+
129
+ key[:down] = true
130
+ key[:last_repeat] = Gosu.milliseconds + key[:repeat_delay]
131
+ return true
132
+ end
133
+
134
+ case id
135
+ when Gosu::KB_ENTER, Gosu::KB_RETURN
136
+ caret_pos = @text_input.caret_pos
137
+ @text_input.text = @text_input.text.insert(@text_input.caret_pos, "\n")
138
+ @text_input.caret_pos = @text_input.selection_start = caret_pos + 1
139
+ end
140
+ end
141
+
142
+ def button_up(id)
143
+ super
144
+
145
+ @repeatable_keys.detect do |key|
146
+ if key[:key] == id
147
+ key[:down] = false
148
+ return true
149
+ end
150
+ end
151
+ end
152
+
153
+ def move(direction)
154
+ pos = @text_input.caret_pos
155
+ line = nil
156
+
157
+ case direction
158
+ when :up
159
+ return if @active_line == 0
160
+ when :down
161
+ return if @active_line == @text_input.text.chomp.lines
162
+
163
+ text = @text_input.text.chomp.lines[0..@active_line].join("\n")
164
+ pos = text.length
165
+ end
166
+
167
+ set_position(pos)
168
+ end
169
+
170
+ def drag_update(_sender, x, y, _button)
171
+ int = caret_position_under_mouse(x, y)
172
+ int = 0 if int < 0
173
+ @text_input.caret_pos = int
174
+
175
+ :handled
176
+ end
177
+ end
178
+ end
179
+ end
@@ -1,172 +1,262 @@
1
- module CyberarmEngine
2
- class Element
3
- class EditLine < Button
4
- def initialize(text, options = {}, block = nil)
5
- super(text, options, block)
6
-
7
- @type = default(:type)
8
-
9
- @caret_width = default(:caret_width)
10
- @caret_height= @text.height
11
- @caret_color = default(:caret_color)
12
- @caret_interval = default(:caret_interval)
13
- @caret_last_interval = Gosu.milliseconds
14
- @show_caret = true
15
-
16
- @text_input = Gosu::TextInput.new
17
- @text_input.text = text
18
-
19
- @offset_x = 0
20
-
21
- return self
22
- end
23
-
24
- def render
25
- Gosu.clip_to(@text.x, @text.y, @style.width, @text.height) do
26
- Gosu.translate(-@offset_x, 0) do
27
- draw_selection
28
- draw_caret if @focus && @show_caret
29
- draw_text
30
- end
31
- end
32
- end
33
-
34
- def draw_caret
35
- Gosu.draw_rect(caret_position, @text.y, @caret_width, @caret_height, @caret_color, @z)
36
- end
37
-
38
- def draw_selection
39
- selection_width = caret_position - selection_start_position
40
-
41
- Gosu.draw_rect(selection_start_position, @text.y, selection_width, @text.height, default(:selection_color), @z)
42
- end
43
-
44
- def update
45
- if @type == :password
46
- @text.text = default(:password_character) * @text_input.text.length
47
- else
48
- @text.text = @text_input.text
49
- end
50
-
51
- if Gosu.milliseconds >= @caret_last_interval + @caret_interval
52
- @caret_last_interval = Gosu.milliseconds
53
-
54
- @show_caret = !@show_caret
55
- end
56
-
57
- keep_caret_visible
58
- end
59
-
60
- def move_caret_to_mouse(mouse_x)
61
- 1.upto(@text.text.length) do |i|
62
- if mouse_x < @text.x + @text.textobject.text_width(@text.text[0...i])
63
- @text_input.caret_pos = @text_input.selection_start = i - 1;
64
- return
65
- end
66
- end
67
-
68
- @text_input.caret_pos = @text_input.selection_start = @text_input.text.length
69
- end
70
-
71
- def keep_caret_visible
72
- caret_pos = (caret_position - @text.x) + @caret_width
73
-
74
- @last_text ||= "/\\"
75
- @last_pos ||= -1
76
-
77
- puts "caret pos: #{caret_pos}, width: #{@width}, offset: #{@offset_x}" if (@last_text != @text.text) || (@last_pos != caret_pos)
78
-
79
- @last_text = @text.text
80
- @last_pos = caret_pos
81
-
82
-
83
- if caret_pos.between?(@offset_x, @width + @offset_x)
84
- # Do nothing
85
-
86
- elsif caret_pos < @offset_x
87
- if caret_pos > @width
88
- @offset_x = caret_pos + @width
89
- else
90
- @offset_x = 0
91
- end
92
-
93
- elsif caret_pos > @width
94
- @offset_x = caret_pos - @width
95
- puts "triggered"
96
-
97
- else
98
- # Reset to Zero
99
- @offset_x = 0
100
- end
101
- end
102
-
103
- def left_mouse_button(sender, x, y)
104
- super
105
- window.text_input = @text_input
106
-
107
- @caret_last_interval = Gosu.milliseconds
108
- @show_caret = true
109
-
110
- move_caret_to_mouse(x)
111
-
112
- return :handled
113
- end
114
-
115
- def enter(sender)
116
- if @focus
117
- @style.background_canvas.background = default(:active, :background)
118
- @text.color = default(:active, :color)
119
- else
120
- @style.background_canvas.background = default(:hover, :background)
121
- @text.color = default(:hover, :color)
122
- end
123
-
124
- return :handled
125
- end
126
-
127
- def leave(sender)
128
- unless @focus
129
- super
130
- end
131
-
132
- return :handled
133
- end
134
-
135
- def blur(sender)
136
- @focus = false
137
- @style.background_canvas.background = default(:background)
138
- @text.color = default(:color)
139
- window.text_input = nil
140
-
141
- return :handled
142
- end
143
-
144
- def caret_position
145
- text_input_position_for(:caret_pos)
146
- end
147
-
148
- def selection_start_position
149
- text_input_position_for(:selection_start)
150
- end
151
-
152
- def text_input_position_for(method)
153
- if @type == :password
154
- @text.x + @text.textobject.text_width(default(:password_character) * @text_input.text[0..@text_input.send(method)].length)
155
- else
156
- @text.x + @text.textobject.text_width(@text_input.text[0..@text_input.send(method)])
157
- end
158
- end
159
-
160
- def recalculate
161
- super
162
-
163
- @width = dimensional_size(@style.width, :width) || default(:width)
164
- update_background
165
- end
166
-
167
- def value
168
- @text_input.text
169
- end
170
- end
171
- end
172
- end
1
+ module CyberarmEngine
2
+ class Element
3
+ class EditLine < Button
4
+ def initialize(text, options = {}, block = nil)
5
+ @filter = options.delete(:filter)
6
+ super(text, options, block)
7
+
8
+ @type = default(:type)
9
+
10
+ @caret_width = default(:caret_width)
11
+ @caret_height = @text.textobject.height
12
+ @caret_color = default(:caret_color)
13
+ @caret_interval = default(:caret_interval)
14
+ @caret_last_interval = Gosu.milliseconds
15
+ @show_caret = true
16
+
17
+ @text_input = Gosu::TextInput.new
18
+ @text_input.text = text
19
+ @last_text_value = text
20
+
21
+ if @filter && @filter.respond_to?(:call)
22
+ @text_input.instance_variable_set(:@filter, @filter)
23
+
24
+ def @text_input.filter(text_in)
25
+ @filter.call(text_in)
26
+ end
27
+ end
28
+
29
+ @offset_x = 0
30
+ @offset_y = 0
31
+
32
+ event(:begin_drag)
33
+ event(:drag_update)
34
+ event(:end_drag)
35
+ end
36
+
37
+ def render
38
+ Gosu.clip_to(@text.x, @text.y, @width, @height) do
39
+ Gosu.translate(-@offset_x, -@offset_y) do
40
+ draw_selection
41
+ draw_caret if @focus && @show_caret
42
+ draw_text
43
+ end
44
+ end
45
+ end
46
+
47
+ def draw_text
48
+ @text.draw(:draw_text)
49
+ end
50
+
51
+ def draw_caret
52
+ Gosu.draw_rect(caret_position, @text.y, @caret_width, @caret_height, @caret_color, @z)
53
+ end
54
+
55
+ def draw_selection
56
+ selection_width = caret_position - selection_start_position
57
+
58
+ Gosu.draw_rect(selection_start_position, @text.y, selection_width, @text.height, default(:selection_color), @z)
59
+ end
60
+
61
+ def update
62
+ @text.text = if @type == :password
63
+ default(:password_character) * @text_input.text.length
64
+ else
65
+ @text_input.text
66
+ end
67
+
68
+ if @last_text_value != value
69
+ @last_text_value = value
70
+ @show_caret = true
71
+ @caret_last_interval = Gosu.milliseconds
72
+
73
+ publish(:changed, value)
74
+ end
75
+
76
+ if Gosu.milliseconds >= @caret_last_interval + @caret_interval
77
+ @caret_last_interval = Gosu.milliseconds
78
+
79
+ @show_caret = !@show_caret
80
+ end
81
+
82
+ keep_caret_visible
83
+ end
84
+
85
+ def button_down(id)
86
+ handle_keyboard_shortcuts(id)
87
+ end
88
+
89
+ def handle_keyboard_shortcuts(id)
90
+ return unless @focus && @enabled
91
+
92
+ if Gosu.button_down?(Gosu::KB_LEFT_CONTROL) || Gosu.button_down?(Gosu::KB_RIGHT_CONTROL)
93
+ case id
94
+ when Gosu::KB_A
95
+ @text_input.selection_start = 0
96
+ @text_input.caret_pos = @text_input.text.length
97
+
98
+ when Gosu::KB_C
99
+ if @text_input.selection_start < @text_input.caret_pos
100
+ Clipboard.copy(@text_input.text[@text_input.selection_start...@text_input.caret_pos])
101
+ else
102
+ Clipboard.copy(@text_input.text[@text_input.caret_pos...@text_input.selection_start])
103
+ end
104
+
105
+ when Gosu::KB_X
106
+ chars = @text_input.text.chars
107
+
108
+ if @text_input.selection_start < @text_input.caret_pos
109
+ Clipboard.copy(@text_input.text[@text_input.selection_start...@text_input.caret_pos])
110
+ chars.slice!(@text_input.selection_start, @text_input.caret_pos)
111
+ else
112
+ Clipboard.copy(@text_input.text[@text_input.caret_pos...@text_input.selection_start])
113
+ chars.slice!(@text_input.caret_pos, @text_input.selection_start)
114
+ end
115
+
116
+ @text_input.text = chars.join
117
+
118
+ when Gosu::KB_V
119
+ if instance_of?(EditLine) # EditLine assumes a single line of text
120
+ @text_input.text = @text_input.text.insert(@text_input.caret_pos,
121
+ Clipboard.paste.encode("UTF-8").gsub("\n", ""))
122
+ else
123
+ @text_input.text = @text_input.text.insert(@text_input.caret_pos, Clipboard.paste.encode("UTF-8"))
124
+ end
125
+ end
126
+ end
127
+ end
128
+
129
+ def caret_position_under_mouse(mouse_x)
130
+ 1.upto(@text.text.length) do |i|
131
+ return i - 1 if mouse_x < @text.x - @offset_x + @text.width(@text.text[0...i])
132
+ end
133
+
134
+ @text_input.text.length
135
+ end
136
+
137
+ def move_caret_to_mouse(mouse_x, _mouse_y)
138
+ @text_input.caret_pos = @text_input.selection_start = caret_position_under_mouse(mouse_x)
139
+ end
140
+
141
+ def keep_caret_visible
142
+ caret_pos = (caret_position - @text.x) + @caret_width
143
+
144
+ @last_text ||= "/\\"
145
+ @last_pos ||= -1
146
+
147
+ @last_text = @text.text
148
+ @last_pos = caret_pos
149
+
150
+ if caret_pos.between?(@offset_x, @width + @offset_x)
151
+ # Do nothing
152
+
153
+ elsif caret_pos < @offset_x
154
+ @offset_x = if caret_pos > @width
155
+ caret_pos + @width
156
+ else
157
+ 0
158
+ end
159
+
160
+ elsif caret_pos > @width
161
+ @offset_x = caret_pos - @width
162
+
163
+ else
164
+ # Reset to Zero
165
+ @offset_x = 0
166
+ end
167
+ end
168
+
169
+ def caret_position
170
+ text_input_position_for(:caret_pos)
171
+ end
172
+
173
+ def selection_start_position
174
+ text_input_position_for(:selection_start)
175
+ end
176
+
177
+ def text_input_position_for(method)
178
+ if @type == :password
179
+ @text.x + @text.width(default(:password_character) * @text_input.text[0...@text_input.send(method)].length)
180
+ else
181
+ @text.x + @text.width(@text_input.text[0...@text_input.send(method)])
182
+ end
183
+ end
184
+
185
+ def left_mouse_button(sender, x, y)
186
+ super
187
+ window.text_input = @text_input
188
+
189
+ @caret_last_interval = Gosu.milliseconds
190
+ @show_caret = true
191
+
192
+ move_caret_to_mouse(x, y)
193
+
194
+ :handled
195
+ end
196
+
197
+ def enter(_sender)
198
+ if @focus
199
+ @style.background_canvas.background = default(:active, :background)
200
+ @text.color = default(:active, :color)
201
+ else
202
+ @style.background_canvas.background = default(:hover, :background)
203
+ @text.color = default(:hover, :color)
204
+ end
205
+
206
+ :handled
207
+ end
208
+
209
+ def leave(sender)
210
+ super unless @focus
211
+
212
+ :handled
213
+ end
214
+
215
+ def blur(_sender)
216
+ @focus = false
217
+ @style.background_canvas.background = default(:background)
218
+ @text.color = default(:color)
219
+ window.text_input = nil
220
+
221
+ :handled
222
+ end
223
+
224
+ def draggable?(button)
225
+ button == :left
226
+ end
227
+
228
+ def begin_drag(_sender, x, _y, _button)
229
+ @drag_start = x
230
+ @offset_drag_start = @offset_x
231
+ @drag_caret_position = @text_input.caret_pos
232
+
233
+ :handled
234
+ end
235
+
236
+ def drag_update(_sender, x, _y, _button)
237
+ @text_input.caret_pos = caret_position_under_mouse(x)
238
+
239
+ :handled
240
+ end
241
+
242
+ def end_drag(_sender, _x, _y, _button)
243
+ :handled
244
+ end
245
+
246
+ def recalculate
247
+ super
248
+
249
+ @width = dimensional_size(@style.width, :width) || default(:width)
250
+ update_background
251
+ end
252
+
253
+ def value
254
+ @text_input.text
255
+ end
256
+
257
+ def value=(string)
258
+ @text_input.text = string
259
+ end
260
+ end
261
+ end
262
+ end