cyberarm_engine 0.12.0 → 0.15.0

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