cyberarm_engine 0.14.0 → 0.15.0

Sign up to get free protection for your applications and to get access to all the features.
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