cyberarm_engine 0.12.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 (66) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +8 -0
  3. data/Gemfile +1 -1
  4. data/README.md +33 -3
  5. data/Rakefile +1 -1
  6. data/assets/textures/default.png +0 -0
  7. data/cyberarm_engine.gemspec +11 -8
  8. data/lib/cyberarm_engine.rb +24 -4
  9. data/lib/cyberarm_engine/animator.rb +56 -0
  10. data/lib/cyberarm_engine/background.rb +19 -15
  11. data/lib/cyberarm_engine/background_nine_slice.rb +125 -0
  12. data/lib/cyberarm_engine/bounding_box.rb +18 -18
  13. data/lib/cyberarm_engine/cache.rb +4 -0
  14. data/lib/cyberarm_engine/cache/download_manager.rb +121 -0
  15. data/lib/cyberarm_engine/common.rb +16 -16
  16. data/lib/cyberarm_engine/config_file.rb +46 -0
  17. data/lib/cyberarm_engine/game_object.rb +63 -72
  18. data/lib/cyberarm_engine/game_state.rb +7 -4
  19. data/lib/cyberarm_engine/model.rb +207 -0
  20. data/lib/cyberarm_engine/model/material.rb +21 -0
  21. data/lib/cyberarm_engine/model/model_object.rb +131 -0
  22. data/lib/cyberarm_engine/model/parser.rb +74 -0
  23. data/lib/cyberarm_engine/model/parsers/collada_parser.rb +138 -0
  24. data/lib/cyberarm_engine/model/parsers/wavefront_parser.rb +154 -0
  25. data/lib/cyberarm_engine/model_cache.rb +31 -0
  26. data/lib/cyberarm_engine/opengl.rb +28 -0
  27. data/lib/cyberarm_engine/opengl/light.rb +50 -0
  28. data/lib/cyberarm_engine/opengl/orthographic_camera.rb +46 -0
  29. data/lib/cyberarm_engine/opengl/perspective_camera.rb +38 -0
  30. data/lib/cyberarm_engine/opengl/renderer/bounding_box_renderer.rb +249 -0
  31. data/lib/cyberarm_engine/opengl/renderer/g_buffer.rb +164 -0
  32. data/lib/cyberarm_engine/opengl/renderer/opengl_renderer.rb +289 -0
  33. data/lib/cyberarm_engine/opengl/renderer/renderer.rb +22 -0
  34. data/lib/cyberarm_engine/opengl/shader.rb +406 -0
  35. data/lib/cyberarm_engine/opengl/texture.rb +69 -0
  36. data/lib/cyberarm_engine/ray.rb +5 -5
  37. data/lib/cyberarm_engine/stats.rb +21 -0
  38. data/lib/cyberarm_engine/text.rb +45 -31
  39. data/lib/cyberarm_engine/timer.rb +1 -1
  40. data/lib/cyberarm_engine/transform.rb +221 -9
  41. data/lib/cyberarm_engine/ui/border_canvas.rb +4 -3
  42. data/lib/cyberarm_engine/ui/dsl.rb +68 -50
  43. data/lib/cyberarm_engine/ui/element.rb +57 -18
  44. data/lib/cyberarm_engine/ui/elements/button.rb +86 -16
  45. data/lib/cyberarm_engine/ui/elements/check_box.rb +24 -32
  46. data/lib/cyberarm_engine/ui/elements/container.rb +88 -24
  47. data/lib/cyberarm_engine/ui/elements/edit_box.rb +179 -0
  48. data/lib/cyberarm_engine/ui/elements/edit_line.rb +180 -27
  49. data/lib/cyberarm_engine/ui/elements/flow.rb +1 -3
  50. data/lib/cyberarm_engine/ui/elements/image.rb +12 -9
  51. data/lib/cyberarm_engine/ui/elements/label.rb +96 -15
  52. data/lib/cyberarm_engine/ui/elements/list_box.rb +68 -0
  53. data/lib/cyberarm_engine/ui/elements/progress.rb +6 -5
  54. data/lib/cyberarm_engine/ui/elements/radio.rb +6 -0
  55. data/lib/cyberarm_engine/ui/elements/slider.rb +104 -0
  56. data/lib/cyberarm_engine/ui/elements/stack.rb +1 -3
  57. data/lib/cyberarm_engine/ui/elements/toggle_button.rb +40 -31
  58. data/lib/cyberarm_engine/ui/event.rb +8 -7
  59. data/lib/cyberarm_engine/ui/gui_state.rb +89 -6
  60. data/lib/cyberarm_engine/ui/style.rb +10 -9
  61. data/lib/cyberarm_engine/ui/theme.rb +39 -21
  62. data/lib/cyberarm_engine/vector.rb +132 -38
  63. data/lib/cyberarm_engine/version.rb +2 -2
  64. data/lib/cyberarm_engine/{engine.rb → window.rb} +30 -19
  65. metadata +87 -16
  66. data/lib/cyberarm_engine/shader.rb +0 -205
@@ -2,13 +2,32 @@ module CyberarmEngine
2
2
  class Element
3
3
  class CheckBox < Flow
4
4
  def initialize(text, options, block = nil)
5
- super({}, block = nil)
5
+ super(options, block)
6
6
  options[:toggled] = options[:checked]
7
7
 
8
8
  @toggle_button = ToggleButton.new(options)
9
9
  @label = Label.new(text, options)
10
10
 
11
- define_label_singletons
11
+ @label.subscribe(:holding_left_mouse_button) do |sender, x, y|
12
+ @toggle_button.left_mouse_button(sender, x, y)
13
+ end
14
+
15
+ @label.subscribe(:released_left_mouse_button) do |sender, x, y|
16
+ @toggle_button.released_left_mouse_button(sender, x, y)
17
+ end
18
+
19
+ @label.subscribe(:clicked_left_mouse_button) do |sender, x, y|
20
+ @toggle_button.clicked_left_mouse_button(sender, x, y)
21
+ publish(:changed, @toggle_button.value)
22
+ end
23
+
24
+ @label.subscribe(:enter) do |sender|
25
+ @toggle_button.enter(sender)
26
+ end
27
+
28
+ @label.subscribe(:leave) do |sender|
29
+ @toggle_button.leave(sender)
30
+ end
12
31
 
13
32
  add(@toggle_button)
14
33
  add(@label)
@@ -24,36 +43,9 @@ module CyberarmEngine
24
43
  end
25
44
 
26
45
  def value=(bool)
27
- @toggle_button.vlaue = bool
28
- end
29
-
30
- def define_label_singletons
31
- @label.define_singleton_method(:_toggle_button) do |button|
32
- @_toggle_button = button
33
- end
34
-
35
- @label._toggle_button(@toggle_button)
36
-
37
- @label.define_singleton_method(:holding_left_mouse_button) do |sender, x, y|
38
- @_toggle_button.left_mouse_button(sender, x, y)
39
- end
40
-
41
- @label.define_singleton_method(:released_left_mouse_button) do |sender, x, y|
42
- @_toggle_button.released_left_mouse_button(sender, x, y)
43
- end
44
-
45
- @label.define_singleton_method(:clicked_left_mouse_button) do |sender, x, y|
46
- @_toggle_button.clicked_left_mouse_button(sender, x, y)
47
- end
48
-
49
- @label.define_singleton_method(:enter) do |sender|
50
- @_toggle_button.enter(sender)
51
- end
52
-
53
- @label.define_singleton_method(:leave) do |sender|
54
- @_toggle_button.leave(sender)
55
- end
46
+ @toggle_button.value = bool
47
+ publish(:changed, @toggle_button.value)
56
48
  end
57
49
  end
58
50
  end
59
- end
51
+ end
@@ -4,14 +4,14 @@ module CyberarmEngine
4
4
  include Common
5
5
 
6
6
  attr_accessor :stroke_color, :fill_color
7
- attr_reader :children, :gui_state
8
- attr_reader :scroll_x, :scroll_y
7
+ attr_reader :children, :gui_state, :scroll_x, :scroll_y
9
8
 
10
9
  def initialize(options = {}, block = nil)
11
10
  @gui_state = options.delete(:gui_state)
12
11
  super
13
12
 
14
- @scroll_x, @scroll_y = 0, 0
13
+ @scroll_x = 0
14
+ @scroll_y = 0
15
15
  @scroll_speed = 10
16
16
 
17
17
  @text_color = options[:color]
@@ -22,19 +22,57 @@ module CyberarmEngine
22
22
  def build
23
23
  @block.call(self) if @block
24
24
 
25
- recalculate
25
+ root.gui_state.request_recalculate
26
26
  end
27
27
 
28
28
  def add(element)
29
29
  @children << element
30
30
 
31
- recalculate
31
+ root.gui_state.request_recalculate
32
+ end
33
+
34
+ def clear(&block)
35
+ @children.clear
36
+
37
+ old_container = $__current_container__
38
+
39
+ $__current_container__ = self
40
+ block.call(self) if block
41
+
42
+ $__current_container__ = old_container
43
+
44
+ root.gui_state.request_recalculate
32
45
  end
33
46
 
34
47
  def render
35
48
  Gosu.clip_to(@x, @y, width, height) do
36
49
  @children.each(&:draw)
37
50
  end
51
+
52
+ if false # DEBUG
53
+ Gosu.flush
54
+
55
+ Gosu.draw_line(
56
+ x, y, Gosu::Color::RED,
57
+ x + outer_width, y, Gosu::Color::RED,
58
+ Float::INFINITY
59
+ )
60
+ Gosu.draw_line(
61
+ x + outer_width, y, Gosu::Color::RED,
62
+ x + outer_width, y + outer_height, Gosu::Color::RED,
63
+ Float::INFINITY
64
+ )
65
+ Gosu.draw_line(
66
+ x + outer_width, y + outer_height, Gosu::Color::RED,
67
+ x, y + outer_height, Gosu::Color::RED,
68
+ Float::INFINITY
69
+ )
70
+ Gosu.draw_line(
71
+ x, outer_height, Gosu::Color::RED,
72
+ x, y, Gosu::Color::RED,
73
+ Float::INFINITY
74
+ )
75
+ end
38
76
  end
39
77
 
40
78
  def update
@@ -43,6 +81,8 @@ module CyberarmEngine
43
81
 
44
82
  def hit_element?(x, y)
45
83
  @children.reverse_each do |child|
84
+ next unless child.visible?
85
+
46
86
  case child
47
87
  when Container
48
88
  if element = child.hit_element?(x, y)
@@ -59,6 +99,9 @@ module CyberarmEngine
59
99
  def recalculate
60
100
  @current_position = Vector.new(@style.margin_left + @style.padding_left, @style.margin_top + @style.padding_top)
61
101
  return unless visible?
102
+
103
+ Stats.increment(:gui_recalculations_last_frame, 1)
104
+
62
105
  stylize
63
106
 
64
107
  layout
@@ -67,24 +110,26 @@ module CyberarmEngine
67
110
  @width = @style.width = window.width
68
111
  @height = @style.height = window.height
69
112
  else
70
- @width, @height = 0, 0
113
+ @width = 0
114
+ @height = 0
71
115
 
72
116
  _width = dimensional_size(@style.width, :width)
73
- _height= dimensional_size(@style.height,:height)
117
+ _height = dimensional_size(@style.height, :height)
74
118
 
75
- @width = _width ? _width : (@children.map {|c| c.x + c.outer_width }.max || 0).round
76
- @height = _height ? _height : (@children.map {|c| c.y + c.outer_height}.max || 0).round
119
+ @width = _width || (@children.map { |c| c.x + c.outer_width }.max || 0).round
120
+ @height = _height || (@children.map { |c| c.y + c.outer_height }.max || 0).round
77
121
  end
78
122
 
79
-
80
123
  # Move child to parent after positioning
81
124
  @children.each do |child|
82
- child.x += @x
83
- child.y += @y
125
+ child.x += (@x + @style.border_thickness_left) - style.margin_left
126
+ child.y += (@y + @style.border_thickness_top) - style.margin_top
84
127
 
85
128
  child.stylize
86
129
  child.recalculate
87
130
  child.reposition # TODO: Implement top,bottom,left,center, and right positioning
131
+
132
+ Stats.increment(:gui_recalculations_last_frame, 1)
88
133
  end
89
134
 
90
135
  update_background
@@ -95,32 +140,36 @@ module CyberarmEngine
95
140
  end
96
141
 
97
142
  def max_width
98
- @max_width ? @max_width : window.width - (@parent ? @parent.style.margin_right + @style.margin_right : @style.margin_right)
143
+ _width = dimensional_size(@style.width, :width)
144
+ if _width
145
+ outer_width
146
+ else
147
+ window.width - (@parent ? @parent.style.margin_right + @style.margin_right : @style.margin_right)
148
+ end
99
149
  end
100
150
 
101
151
  def fits_on_line?(element) # Flow
152
+ p [@options[:id], @width] if @options[:id]
102
153
  @current_position.x + element.outer_width <= max_width &&
103
- @current_position.x + element.outer_width <= window.width
154
+ @current_position.x + element.outer_width <= window.width
104
155
  end
105
156
 
106
157
  def position_on_current_line(element) # Flow
107
158
  element.x = element.style.margin_left + @current_position.x
108
159
  element.y = element.style.margin_top + @current_position.y
109
160
 
110
- element.recalculate
111
-
112
161
  @current_position.x += element.outer_width
113
162
  @current_position.x = @style.margin_left if @current_position.x >= max_width
114
163
  end
115
164
 
116
- def tallest_neighbor(querier, y_position) # Flow
165
+ def tallest_neighbor(querier, _y_position) # Flow
117
166
  response = querier
118
167
  @children.each do |child|
119
168
  response = child if child.outer_height > response.outer_height
120
169
  break if child == querier
121
170
  end
122
171
 
123
- return response
172
+ response
124
173
  end
125
174
 
126
175
  def position_on_next_line(child) # Flow
@@ -130,8 +179,6 @@ module CyberarmEngine
130
179
  child.x = child.style.margin_left + @current_position.x
131
180
  child.y = child.style.margin_top + @current_position.y
132
181
 
133
- child.recalculate
134
-
135
182
  @current_position.x += child.outer_width
136
183
  end
137
184
 
@@ -139,8 +186,6 @@ module CyberarmEngine
139
186
  element.x = element.style.margin_left + @current_position.x
140
187
  element.y = element.style.margin_top + @current_position.y
141
188
 
142
- element.recalculate
143
-
144
189
  @current_position.y += element.outer_height
145
190
  end
146
191
 
@@ -155,8 +200,27 @@ module CyberarmEngine
155
200
  # end
156
201
 
157
202
  def value
158
- @children.map {|c| c.class}.join(", ")
203
+ @children.map { |c| c.class }.join(", ")
204
+ end
205
+
206
+ def to_s
207
+ "#{self.class} x=#{x} y=#{y} width=#{width} height=#{height} children=#{@children.size}"
208
+ end
209
+
210
+ def write_tree(indent = "", _index = 0)
211
+ puts self
212
+
213
+ indent += " "
214
+ @children.each_with_index do |child, i|
215
+ print "#{indent}#{i}: "
216
+
217
+ if child.is_a?(Container)
218
+ child.write_tree(indent)
219
+ else
220
+ puts child
221
+ end
222
+ end
159
223
  end
160
224
  end
161
225
  end
162
- end
226
+ end
@@ -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