cyberarm_engine 0.14.0 → 0.15.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 (64) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +8 -0
  3. data/Gemfile +1 -1
  4. data/Rakefile +1 -1
  5. data/assets/textures/default.png +0 -0
  6. data/cyberarm_engine.gemspec +10 -8
  7. data/lib/cyberarm_engine.rb +13 -2
  8. data/lib/cyberarm_engine/animator.rb +6 -4
  9. data/lib/cyberarm_engine/background.rb +19 -15
  10. data/lib/cyberarm_engine/background_nine_slice.rb +125 -0
  11. data/lib/cyberarm_engine/bounding_box.rb +18 -18
  12. data/lib/cyberarm_engine/cache.rb +4 -0
  13. data/lib/cyberarm_engine/cache/download_manager.rb +121 -0
  14. data/lib/cyberarm_engine/common.rb +13 -13
  15. data/lib/cyberarm_engine/config_file.rb +2 -2
  16. data/lib/cyberarm_engine/game_object.rb +63 -72
  17. data/lib/cyberarm_engine/game_state.rb +6 -3
  18. data/lib/cyberarm_engine/model.rb +207 -0
  19. data/lib/cyberarm_engine/model/material.rb +21 -0
  20. data/lib/cyberarm_engine/model/model_object.rb +131 -0
  21. data/lib/cyberarm_engine/model/parser.rb +74 -0
  22. data/lib/cyberarm_engine/model/parsers/collada_parser.rb +138 -0
  23. data/lib/cyberarm_engine/model/parsers/wavefront_parser.rb +154 -0
  24. data/lib/cyberarm_engine/model_cache.rb +31 -0
  25. data/lib/cyberarm_engine/opengl.rb +28 -0
  26. data/lib/cyberarm_engine/opengl/light.rb +50 -0
  27. data/lib/cyberarm_engine/opengl/orthographic_camera.rb +46 -0
  28. data/lib/cyberarm_engine/opengl/perspective_camera.rb +38 -0
  29. data/lib/cyberarm_engine/opengl/renderer/bounding_box_renderer.rb +249 -0
  30. data/lib/cyberarm_engine/opengl/renderer/g_buffer.rb +164 -0
  31. data/lib/cyberarm_engine/opengl/renderer/opengl_renderer.rb +289 -0
  32. data/lib/cyberarm_engine/opengl/renderer/renderer.rb +22 -0
  33. data/lib/cyberarm_engine/{shader.rb → opengl/shader.rb} +51 -43
  34. data/lib/cyberarm_engine/opengl/texture.rb +69 -0
  35. data/lib/cyberarm_engine/ray.rb +5 -5
  36. data/lib/cyberarm_engine/stats.rb +2 -2
  37. data/lib/cyberarm_engine/text.rb +41 -27
  38. data/lib/cyberarm_engine/timer.rb +1 -1
  39. data/lib/cyberarm_engine/transform.rb +43 -20
  40. data/lib/cyberarm_engine/ui/border_canvas.rb +4 -3
  41. data/lib/cyberarm_engine/ui/dsl.rb +25 -11
  42. data/lib/cyberarm_engine/ui/element.rb +30 -20
  43. data/lib/cyberarm_engine/ui/elements/button.rb +86 -16
  44. data/lib/cyberarm_engine/ui/elements/check_box.rb +1 -1
  45. data/lib/cyberarm_engine/ui/elements/container.rb +44 -20
  46. data/lib/cyberarm_engine/ui/elements/edit_box.rb +175 -2
  47. data/lib/cyberarm_engine/ui/elements/edit_line.rb +121 -37
  48. data/lib/cyberarm_engine/ui/elements/flow.rb +1 -1
  49. data/lib/cyberarm_engine/ui/elements/image.rb +12 -9
  50. data/lib/cyberarm_engine/ui/elements/label.rb +93 -14
  51. data/lib/cyberarm_engine/ui/elements/list_box.rb +64 -2
  52. data/lib/cyberarm_engine/ui/elements/progress.rb +5 -5
  53. data/lib/cyberarm_engine/ui/elements/radio.rb +1 -1
  54. data/lib/cyberarm_engine/ui/elements/slider.rb +13 -16
  55. data/lib/cyberarm_engine/ui/elements/stack.rb +1 -1
  56. data/lib/cyberarm_engine/ui/elements/toggle_button.rb +27 -19
  57. data/lib/cyberarm_engine/ui/event.rb +7 -7
  58. data/lib/cyberarm_engine/ui/gui_state.rb +44 -10
  59. data/lib/cyberarm_engine/ui/style.rb +10 -9
  60. data/lib/cyberarm_engine/ui/theme.rb +28 -20
  61. data/lib/cyberarm_engine/vector.rb +33 -30
  62. data/lib/cyberarm_engine/version.rb +2 -2
  63. data/lib/cyberarm_engine/window.rb +27 -18
  64. metadata +65 -15
@@ -1,6 +1,179 @@
1
1
  module CyberarmEngine
2
2
  class Element
3
- class EditBox < 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
4
177
  end
5
178
  end
6
- end
179
+ end
@@ -2,28 +2,41 @@ module CyberarmEngine
2
2
  class Element
3
3
  class EditLine < Button
4
4
  def initialize(text, options = {}, block = nil)
5
+ @filter = options.delete(:filter)
5
6
  super(text, options, block)
6
7
 
7
8
  @type = default(:type)
8
9
 
9
10
  @caret_width = default(:caret_width)
10
- @caret_height= @text.height
11
+ @caret_height = @text.textobject.height
11
12
  @caret_color = default(:caret_color)
12
13
  @caret_interval = default(:caret_interval)
13
14
  @caret_last_interval = Gosu.milliseconds
14
- @show_caret = true
15
+ @show_caret = true
15
16
 
16
17
  @text_input = Gosu::TextInput.new
17
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
18
28
 
19
29
  @offset_x = 0
30
+ @offset_y = 0
20
31
 
21
- return self
32
+ event(:begin_drag)
33
+ event(:drag_update)
34
+ event(:end_drag)
22
35
  end
23
36
 
24
37
  def render
25
- Gosu.clip_to(@text.x, @text.y, @style.width, @text.height) do
26
- Gosu.translate(-@offset_x, 0) do
38
+ Gosu.clip_to(@text.x, @text.y, @width, @height) do
39
+ Gosu.translate(-@offset_x, -@offset_y) do
27
40
  draw_selection
28
41
  draw_caret if @focus && @show_caret
29
42
  draw_text
@@ -31,6 +44,10 @@ module CyberarmEngine
31
44
  end
32
45
  end
33
46
 
47
+ def draw_text
48
+ @text.draw(:draw_text)
49
+ end
50
+
34
51
  def draw_caret
35
52
  Gosu.draw_rect(caret_position, @text.y, @caret_width, @caret_height, @caret_color, @z)
36
53
  end
@@ -42,10 +59,16 @@ module CyberarmEngine
42
59
  end
43
60
 
44
61
  def update
45
- if @type == :password
46
- @text.text = default(:password_character) * @text_input.text.length
47
- else
48
- @text.text = @text_input.text
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
+
71
+ publish(:changed, value)
49
72
  end
50
73
 
51
74
  if Gosu.milliseconds >= @caret_last_interval + @caret_interval
@@ -57,15 +80,60 @@ module CyberarmEngine
57
80
  keep_caret_visible
58
81
  end
59
82
 
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
83
+ def button_down(id)
84
+ handle_keyboard_shortcuts(id)
85
+ end
86
+
87
+ def handle_keyboard_shortcuts(id)
88
+ return unless @focus && @enabled
89
+
90
+ if Gosu.button_down?(Gosu::KB_LEFT_CONTROL) || Gosu.button_down?(Gosu::KB_RIGHT_CONTROL)
91
+ case id
92
+ when Gosu::KB_A
93
+ @text_input.selection_start = 0
94
+ @text_input.caret_pos = @text_input.text.length
95
+
96
+ when Gosu::KB_C
97
+ if @text_input.selection_start < @text_input.caret_pos
98
+ Clipboard.copy(@text_input.text[@text_input.selection_start...@text_input.caret_pos])
99
+ else
100
+ Clipboard.copy(@text_input.text[@text_input.caret_pos...@text_input.selection_start])
101
+ end
102
+
103
+ when Gosu::KB_X
104
+ chars = @text_input.text.chars
105
+
106
+ if @text_input.selection_start < @text_input.caret_pos
107
+ Clipboard.copy(@text_input.text[@text_input.selection_start...@text_input.caret_pos])
108
+ chars.slice!(@text_input.selection_start, @text_input.caret_pos)
109
+ else
110
+ Clipboard.copy(@text_input.text[@text_input.caret_pos...@text_input.selection_start])
111
+ chars.slice!(@text_input.caret_pos, @text_input.selection_start)
112
+ end
113
+
114
+ @text_input.text = chars.join
115
+
116
+ when Gosu::KB_V
117
+ if instance_of?(EditLine) # EditLine assumes a single line of text
118
+ @text_input.text = @text_input.text.insert(@text_input.caret_pos,
119
+ Clipboard.paste.encode("UTF-8").gsub("\n", ""))
120
+ else
121
+ @text_input.text = @text_input.text.insert(@text_input.caret_pos, Clipboard.paste.encode("UTF-8"))
122
+ end
65
123
  end
66
124
  end
125
+ end
126
+
127
+ def caret_position_under_mouse(mouse_x)
128
+ 1.upto(@text.text.length) do |i|
129
+ return i - 1 if mouse_x < @text.x - @offset_x + @text.width(@text.text[0...i])
130
+ end
131
+
132
+ @text_input.text.length
133
+ end
67
134
 
68
- @text_input.caret_pos = @text_input.selection_start = @text_input.text.length
135
+ def move_caret_to_mouse(mouse_x, _mouse_y)
136
+ @text_input.caret_pos = @text_input.selection_start = caret_position_under_mouse(mouse_x)
69
137
  end
70
138
 
71
139
  def keep_caret_visible
@@ -74,25 +142,21 @@ module CyberarmEngine
74
142
  @last_text ||= "/\\"
75
143
  @last_pos ||= -1
76
144
 
77
- puts "caret pos: #{caret_pos}, width: #{@width}, offset: #{@offset_x}" if (@last_text != @text.text) || (@last_pos != caret_pos)
78
-
79
145
  @last_text = @text.text
80
146
  @last_pos = caret_pos
81
147
 
82
-
83
148
  if caret_pos.between?(@offset_x, @width + @offset_x)
84
149
  # Do nothing
85
150
 
86
151
  elsif caret_pos < @offset_x
87
- if caret_pos > @width
88
- @offset_x = caret_pos + @width
89
- else
90
- @offset_x = 0
91
- end
152
+ @offset_x = if caret_pos > @width
153
+ caret_pos + @width
154
+ else
155
+ 0
156
+ end
92
157
 
93
158
  elsif caret_pos > @width
94
159
  @offset_x = caret_pos - @width
95
- puts "triggered"
96
160
 
97
161
  else
98
162
  # Reset to Zero
@@ -110,9 +174,9 @@ module CyberarmEngine
110
174
 
111
175
  def text_input_position_for(method)
112
176
  if @type == :password
113
- @text.x + @text.width(default(:password_character) * @text_input.text[0..@text_input.send(method)].length)
177
+ @text.x + @text.width(default(:password_character) * @text_input.text[0...@text_input.send(method)].length)
114
178
  else
115
- @text.x + @text.width(@text_input.text[0..@text_input.send(method)])
179
+ @text.x + @text.width(@text_input.text[0...@text_input.send(method)])
116
180
  end
117
181
  end
118
182
 
@@ -123,12 +187,12 @@ module CyberarmEngine
123
187
  @caret_last_interval = Gosu.milliseconds
124
188
  @show_caret = true
125
189
 
126
- move_caret_to_mouse(x)
190
+ move_caret_to_mouse(x, y)
127
191
 
128
- return :handled
192
+ :handled
129
193
  end
130
194
 
131
- def enter(sender)
195
+ def enter(_sender)
132
196
  if @focus
133
197
  @style.background_canvas.background = default(:active, :background)
134
198
  @text.color = default(:active, :color)
@@ -137,24 +201,44 @@ module CyberarmEngine
137
201
  @text.color = default(:hover, :color)
138
202
  end
139
203
 
140
- return :handled
204
+ :handled
141
205
  end
142
206
 
143
207
  def leave(sender)
144
- unless @focus
145
- super
146
- end
208
+ super unless @focus
147
209
 
148
- return :handled
210
+ :handled
149
211
  end
150
212
 
151
- def blur(sender)
213
+ def blur(_sender)
152
214
  @focus = false
153
215
  @style.background_canvas.background = default(:background)
154
216
  @text.color = default(:color)
155
217
  window.text_input = nil
156
218
 
157
- return :handled
219
+ :handled
220
+ end
221
+
222
+ def draggable?(button)
223
+ button == :left
224
+ end
225
+
226
+ def begin_drag(_sender, x, _y, _button)
227
+ @drag_start = x
228
+ @offset_drag_start = @offset_x
229
+ @drag_caret_position = @text_input.caret_pos
230
+
231
+ :handled
232
+ end
233
+
234
+ def drag_update(_sender, x, _y, _button)
235
+ @text_input.caret_pos = caret_position_under_mouse(x)
236
+
237
+ :handled
238
+ end
239
+
240
+ def end_drag(_sender, _x, _y, _button)
241
+ :handled
158
242
  end
159
243
 
160
244
  def recalculate
@@ -169,4 +253,4 @@ module CyberarmEngine
169
253
  end
170
254
  end
171
255
  end
172
- end
256
+ end
@@ -12,4 +12,4 @@ module CyberarmEngine
12
12
  end
13
13
  end
14
14
  end
15
- end
15
+ end
@@ -6,7 +6,8 @@ module CyberarmEngine
6
6
  @path = path
7
7
 
8
8
  @image = Gosu::Image.new(path, retro: @options[:image_retro])
9
- @scale_x, @scale_y = 1, 1
9
+ @scale_x = 1
10
+ @scale_y = 1
10
11
  end
11
12
 
12
13
  def render
@@ -14,18 +15,19 @@ module CyberarmEngine
14
15
  @style.border_thickness_left + @style.padding_left + @x,
15
16
  @style.border_thickness_top + @style.padding_top + @y,
16
17
  @z + 2,
17
- @scale_x, @scale_y) # TODO: Add color support?
18
+ @scale_x, @scale_y, @style.color
19
+ )
18
20
  end
19
21
 
20
- def clicked_left_mouse_button(sender, x, y)
22
+ def clicked_left_mouse_button(_sender, _x, _y)
21
23
  @block.call(self) if @block
22
24
 
23
- return :handled
25
+ :handled
24
26
  end
25
27
 
26
28
  def recalculate
27
29
  _width = dimensional_size(@style.width, :width)
28
- _height= dimensional_size(@style.height,:height)
30
+ _height = dimensional_size(@style.height, :height)
29
31
 
30
32
  if _width && _height
31
33
  @scale_x = _width.to_f / @image.width
@@ -37,11 +39,12 @@ module CyberarmEngine
37
39
  @scale_y = _height.to_f / @image.height
38
40
  @scale_x = @scale_y
39
41
  else
40
- @scale_x, @scale_y = 1, 1
42
+ @scale_x = 1
43
+ @scale_y = 1
41
44
  end
42
45
 
43
- @width = _width ? _width : @image.width.round * @scale_x
44
- @height= _height ? _height : @image.height.round * @scale_y
46
+ @width = _width || @image.width.round * @scale_x
47
+ @height = _height || @image.height.round * @scale_y
45
48
  end
46
49
 
47
50
  def value
@@ -49,4 +52,4 @@ module CyberarmEngine
49
52
  end
50
53
  end
51
54
  end
52
- end
55
+ end