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
@@ -0,0 +1,68 @@
1
+ module CyberarmEngine
2
+ class Element
3
+ class ListBox < Button
4
+ attr_accessor :items
5
+ attr_reader :choose
6
+
7
+ def initialize(options = {}, block = nil)
8
+ @items = options[:items] || []
9
+ @choose = options[:choose] || @items.first
10
+
11
+ super(@choose, options, block)
12
+
13
+ @style.background_canvas.background = default(:background)
14
+
15
+ # TODO: "Clean Up" into own class?
16
+ @menu = Stack.new(parent: parent, width: @options[:width], theme: @options[:theme])
17
+ @menu.define_singleton_method(:recalculate_menu) do
18
+ @x = @__list_box.x
19
+ @y = @__list_box.y + @__list_box.height
20
+ end
21
+ @menu.instance_variable_set(:"@__list_box", self)
22
+
23
+ def @menu.recalculate
24
+ super
25
+ recalculate_menu
26
+ end
27
+ end
28
+
29
+ def choose=(item)
30
+ valid = @items.detect { |i| i == item }
31
+ return unless valid # TODO: Throw an error?
32
+
33
+ @choose = item
34
+
35
+ self.value = item.to_s
36
+
37
+ recalculate
38
+ end
39
+
40
+ def released_left_mouse_button(_sender, _x, _y)
41
+ show_menu
42
+
43
+ :handled
44
+ end
45
+
46
+ def show_menu
47
+ @menu.clear
48
+ @items.each do |item|
49
+ [@block]
50
+ block = proc { self.choose = item; @block.call(item) if @block }
51
+ b = Button.new(item,
52
+ { parent: @menu, width: 1.0, theme: @options[:theme], margin: 0, border_color: 0x00ffffff }, block)
53
+
54
+ @menu.add(b)
55
+ end
56
+ recalculate
57
+
58
+ root.gui_state.show_menu(@menu)
59
+ end
60
+
61
+ def recalculate
62
+ super
63
+
64
+ @menu.recalculate
65
+ end
66
+ end
67
+ end
68
+ end
@@ -5,7 +5,7 @@ module CyberarmEngine
5
5
  super(options, block)
6
6
 
7
7
  @fraction_background = Background.new(background: @style.fraction_background)
8
- self.value = options[:fraction] ? options[:fraction] : 0.0
8
+ self.value = options[:fraction] || 0.0
9
9
  end
10
10
 
11
11
  def render
@@ -14,9 +14,9 @@ module CyberarmEngine
14
14
 
15
15
  def recalculate
16
16
  _width = dimensional_size(@style.width, :width)
17
- _height= dimensional_size(@style.height,:height)
17
+ _height = dimensional_size(@style.height, :height)
18
18
  @width = _width
19
- @height= _height
19
+ @height = _height
20
20
 
21
21
  update_background
22
22
  end
@@ -43,8 +43,9 @@ module CyberarmEngine
43
43
  @fraction = decimal.clamp(0.0, 1.0)
44
44
  update_background
45
45
 
46
- return @fraction
46
+ publish(:changed, @fraction)
47
+ @fraction
47
48
  end
48
49
  end
49
50
  end
50
- end
51
+ end
@@ -0,0 +1,6 @@
1
+ module CyberarmEngine
2
+ class Element
3
+ class Radio < Element
4
+ end
5
+ end
6
+ end
@@ -0,0 +1,104 @@
1
+ module CyberarmEngine
2
+ class Element
3
+ class Slider < Container
4
+ class Handle < Button
5
+ def initialize(*args)
6
+ super(*args)
7
+
8
+ event(:begin_drag)
9
+ event(:drag_update)
10
+ event(:end_drag)
11
+
12
+ subscribe :begin_drag do |_sender, x, y, _button|
13
+ @drag_start_pos = Vector.new(x, y)
14
+
15
+ :handled
16
+ end
17
+
18
+ subscribe :drag_update do |_sender, x, y, _button|
19
+ @parent.handle_dragged_to(x, y)
20
+
21
+ :handled
22
+ end
23
+
24
+ subscribe :end_drag do
25
+ @drag_start_pos = nil
26
+
27
+ :handled
28
+ end
29
+ end
30
+
31
+ def draggable?(button)
32
+ button == :left
33
+ end
34
+ end
35
+
36
+ attr_reader :range, :step_size, :value
37
+
38
+ def initialize(options = {}, block = nil)
39
+ super(options, block)
40
+
41
+ @range = @options[:range] || (0.0..1.0)
42
+ @step_size = @options[:step] || 0.1
43
+ @value = @options[:value] || (@range.first + @range.last) / 2
44
+
45
+ @handle = Handle.new("", parent: self, width: 8, height: 1.0) { close }
46
+ add(@handle)
47
+ end
48
+
49
+ def recalculate
50
+ _width = dimensional_size(@style.width, :width)
51
+ _height = dimensional_size(@style.height, :height)
52
+
53
+ @width = _width
54
+ @height = _height
55
+
56
+ position_handle
57
+ @handle.recalculate
58
+ @handle.update_background
59
+
60
+ update_background
61
+ end
62
+
63
+ def position_handle
64
+ @handle.x = @x + @style.padding_left + @style.border_thickness_left +
65
+ ((content_width - @handle.outer_width) * (@value - @range.min) / (@range.max - @range.min).to_f)
66
+
67
+ @handle.y = @y + @style.border_thickness_top + @style.padding_top
68
+ end
69
+
70
+ def draw
71
+ super
72
+
73
+ @handle.draw
74
+ end
75
+
76
+ def update
77
+ super
78
+
79
+ @tip = value.to_s
80
+ @handle.tip = @tip
81
+ end
82
+
83
+ def holding_left_mouse_button(_sender, x, y)
84
+ handle_dragged_to(x, y)
85
+
86
+ :handled
87
+ end
88
+
89
+ def handle_dragged_to(x, _y)
90
+ @ratio = ((x - @handle.width / 2) - @x) / (content_width - @handle.outer_width)
91
+
92
+ self.value = @ratio.clamp(0.0, 1.0) * (@range.max - @range.min) + @range.min
93
+ end
94
+
95
+ def value=(n)
96
+ @value = n
97
+ position_handle
98
+ @handle.recalculate
99
+
100
+ publish(:changed, @value)
101
+ end
102
+ end
103
+ end
104
+ end
@@ -1,8 +1,6 @@
1
1
  module CyberarmEngine
2
2
  class Element
3
3
  class Stack < Container
4
- include Common
5
-
6
4
  def layout
7
5
  @children.each do |child|
8
6
  move_to_next_line(child)
@@ -10,4 +8,4 @@ module CyberarmEngine
10
8
  end
11
9
  end
12
10
  end
13
- end
11
+ end
@@ -1,56 +1,65 @@
1
1
  module CyberarmEngine
2
2
  class Element
3
3
  class ToggleButton < Button
4
- attr_reader :toggled
4
+ attr_reader :toggled, :value
5
5
 
6
6
  def initialize(options, block = nil)
7
- super(options[:checkmark], options, block)
8
- @toggled = options[:toggled] || false
9
- if @toggled
10
- @text.text = @options[:checkmark]
7
+ if options.dig(:theme, :ToggleButton, :checkmark_image)
8
+ options[:theme][:ToggleButton][:image_width] ||= options[:theme][:Label][:text_size]
9
+ super(get_image(options.dig(:theme, :ToggleButton, :checkmark_image)), options, block)
10
+
11
+ @_image = @image
11
12
  else
12
- @text.text = ""
13
+ super(options[:checkmark], options, block)
13
14
  end
14
15
 
15
- return self
16
- end
16
+ @value = options[:checked] || false
17
17
 
18
- def toggled=(boolean)
19
- @toggled = !boolean
20
- toggle
18
+ if @value
19
+ @image = @_image if @_image
20
+ @raw_text = @options[:checkmark]
21
+ else
22
+ @image = nil
23
+ @raw_text = ""
24
+ end
21
25
  end
22
26
 
23
- def clicked_left_mouse_button(sender, x, y)
24
- toggle
27
+ def clicked_left_mouse_button(_sender, _x, _y)
28
+ self.value = !@value
25
29
 
26
30
  @block.call(self) if @block
27
31
 
28
- return :handled
29
- end
30
-
31
- def toggle
32
- if @toggled
33
- @toggled = false
34
- @text.text = ""
35
- else
36
- @toggled = true
37
- @text.text = @options[:checkmark]
38
- end
32
+ :handled
39
33
  end
40
34
 
41
35
  def recalculate
42
36
  super
37
+ return if @image
38
+
39
+ _width = dimensional_size(@style.width, :width)
40
+ _height = dimensional_size(@style.height, :height)
41
+
42
+ @width = _width || @text.textobject.text_width(@options[:checkmark])
43
+ @height = _height || @text.height
43
44
 
44
- _width = dimensional_size(@style.width, :width)
45
- _height= dimensional_size(@style.height,:height)
46
- @width = _width ? _width : @text.textobject.text_width(@options[:checkmark])
47
- @height = _height ? _height : @text.height
48
45
  update_background
49
46
  end
50
47
 
51
- def value
52
- @toggled
48
+ def value=(boolean)
49
+ @value = boolean
50
+
51
+ if boolean
52
+ @image = @_image if @_image
53
+ @raw_text = @options[:checkmark]
54
+ else
55
+ @image = nil
56
+ @raw_text = ""
57
+ end
58
+
59
+ recalculate
60
+
61
+ publish(:changed, @value)
53
62
  end
54
63
  end
55
64
  end
56
- end
65
+ end
@@ -15,19 +15,18 @@ module CyberarmEngine
15
15
 
16
16
  return unless enabled?
17
17
 
18
- if respond_to?(event)
19
- return :handled if send(event, self, *args) == :handled
20
- end
18
+ return :handled if respond_to?(event) && (send(event, self, *args) == :handled)
21
19
 
22
20
  @event_handler[event].reverse_each do |handler|
23
21
  return :handled if handler.call(self, *args) == :handled
24
22
  end
25
23
 
26
- return nil
24
+ parent.publish(event, *args) if parent
25
+ nil
27
26
  end
28
27
 
29
28
  def event(event)
30
- @event_handler ||= Hash.new
29
+ @event_handler ||= {}
31
30
  @event_handler[event] ||= []
32
31
  end
33
32
  end
@@ -36,11 +35,13 @@ module CyberarmEngine
36
35
  attr_reader :publisher, :event, :handler
37
36
 
38
37
  def initialize(publisher, event, handler)
39
- @publisher, @event, @handler = publisher, event, handler
38
+ @publisher = publisher
39
+ @event = event
40
+ @handler = handler
40
41
  end
41
42
 
42
43
  def unsubscribe
43
44
  @publisher.unsubscribe(self)
44
45
  end
45
46
  end
46
- end
47
+ end
@@ -12,22 +12,30 @@ module CyberarmEngine
12
12
 
13
13
  @root_container = Element::Stack.new(gui_state: self)
14
14
  @game_objects << @root_container
15
- @containers = [@root_container]
15
+ $__current_container__ = @root_container
16
16
 
17
17
  @active_width = window.width
18
18
  @active_height = window.height
19
19
 
20
+ @menu = nil
20
21
  @focus = nil
21
22
  @mouse_over = nil
22
23
  @mouse_down_on = {}
23
24
  @mouse_down_position = {}
25
+ @last_mouse_pos = nil
26
+ @dragging_element = nil
24
27
  @pending_recalculate_request = false
28
+
29
+ @tip = CyberarmEngine::Text.new("", size: 22, z: Float::INFINITY)
30
+ @menu = nil
31
+ @min_drag_distance = 0
32
+ @mouse_pos = Vector.new
25
33
  end
26
34
 
27
35
  # throws :blur event to focused element and sets GuiState focused element
28
36
  # Does NOT throw :focus event at element or set element as focused
29
37
  def focus=(element)
30
- @focus.publish(:blur) if @focus and element && @focus != element
38
+ @focus.publish(:blur) if @focus && element && @focus != element
31
39
  @focus = element
32
40
  end
33
41
 
@@ -35,15 +43,36 @@ module CyberarmEngine
35
43
  @focus
36
44
  end
37
45
 
46
+ def draw
47
+ super
48
+
49
+ if @menu
50
+ Gosu.flush
51
+ @menu.draw
52
+ end
53
+
54
+ if @tip.text.length.positive?
55
+ Gosu.flush
56
+ Gosu.draw_rect(@tip.x - 2, @tip.y - 2, @tip.width + 4, @tip.height + 4, 0xff020202, Float::INFINITY)
57
+ @tip.draw
58
+ end
59
+ end
60
+
38
61
  def update
39
62
  if @pending_recalculate_request
40
63
  @root_container.recalculate
64
+ @root_container.recalculate
65
+ @root_container.recalculate
66
+
41
67
  @pending_recalculate_request = false
42
68
  end
43
69
 
70
+ @menu&.update
44
71
  super
45
72
 
46
- new_mouse_over = @root_container.hit_element?(window.mouse_x, window.mouse_y)
73
+ new_mouse_over = @menu.hit_element?(window.mouse_x, window.mouse_y) if @menu
74
+ new_mouse_over ||= @root_container.hit_element?(window.mouse_x, window.mouse_y)
75
+
47
76
  if new_mouse_over
48
77
  new_mouse_over.publish(:enter) if new_mouse_over != @mouse_over
49
78
  new_mouse_over.publish(:hover)
@@ -56,12 +85,31 @@ module CyberarmEngine
56
85
  redirect_holding_mouse_button(:middle) if @mouse_over && Gosu.button_down?(Gosu::MsMiddle)
57
86
  redirect_holding_mouse_button(:right) if @mouse_over && Gosu.button_down?(Gosu::MsRight)
58
87
 
88
+ if Vector.new(window.mouse_x, window.mouse_y) == @last_mouse_pos
89
+ if @mouse_over && (Gosu.milliseconds - @mouse_moved_at) > tool_tip_delay
90
+ @tip.text = @mouse_over.tip if @mouse_over
91
+ @tip.x = window.mouse_x - @tip.width / 2
92
+ @tip.y = window.mouse_y - @tip.height - 4
93
+ else
94
+ @tip.text = ""
95
+ end
96
+ else
97
+ @mouse_moved_at = Gosu.milliseconds
98
+ end
99
+
100
+ @last_mouse_pos = Vector.new(window.mouse_x, window.mouse_y)
101
+ @mouse_pos = @last_mouse_pos.clone
102
+
59
103
  request_recalculate if @active_width != window.width || @active_height != window.height
60
104
 
61
105
  @active_width = window.width
62
106
  @active_height = window.height
63
107
  end
64
108
 
109
+ def tool_tip_delay
110
+ 500 # ms
111
+ end
112
+
65
113
  def button_down(id)
66
114
  super
67
115
 
@@ -72,7 +120,11 @@ module CyberarmEngine
72
120
  redirect_mouse_button(:middle)
73
121
  when Gosu::MsRight
74
122
  redirect_mouse_button(:right)
123
+ when Gosu::KbF5
124
+ request_recalculate
75
125
  end
126
+
127
+ @focus.button_down(id) if @focus.respond_to?(:button_down)
76
128
  end
77
129
 
78
130
  def button_up(id)
@@ -90,9 +142,13 @@ module CyberarmEngine
90
142
  when Gosu::MsWheelDown
91
143
  redirect_mouse_wheel(:down)
92
144
  end
145
+
146
+ @focus.button_up(id) if @focus.respond_to?(:button_up)
93
147
  end
94
148
 
95
149
  def redirect_mouse_button(button)
150
+ hide_menu unless @menu && (@menu == @mouse_over) || (@mouse_over&.parent == @menu)
151
+
96
152
  if @focus && @mouse_over != @focus
97
153
  @focus.publish(:blur)
98
154
  @focus = nil
@@ -110,9 +166,19 @@ module CyberarmEngine
110
166
  end
111
167
 
112
168
  def redirect_released_mouse_button(button)
169
+ hide_menu if @menu && (@menu == @mouse_over) || (@mouse_over&.parent == @menu)
170
+
113
171
  if @mouse_over
114
172
  @mouse_over.publish(:"released_#{button}_mouse_button", window.mouse_x, window.mouse_y)
115
- @mouse_over.publish(:"clicked_#{button}_mouse_button", window.mouse_x, window.mouse_y) if @mouse_over == @mouse_down_on[button]
173
+ if @mouse_over == @mouse_down_on[button]
174
+ @mouse_over.publish(:"clicked_#{button}_mouse_button", window.mouse_x,
175
+ window.mouse_y)
176
+ end
177
+ end
178
+
179
+ if @dragging_element
180
+ @dragging_element.publish(:end_drag, window.mouse_x, window.mouse_y, button)
181
+ @dragging_element = nil
116
182
  end
117
183
 
118
184
  @mouse_down_position[button] = nil
@@ -120,7 +186,16 @@ module CyberarmEngine
120
186
  end
121
187
 
122
188
  def redirect_holding_mouse_button(button)
123
- @mouse_over.publish(:"holding_#{button}_mouse_button", window.mouse_x, window.mouse_y) if @mouse_over
189
+ if !@dragging_element && @mouse_down_on[button] && @mouse_down_on[button].draggable?(button) && @mouse_pos.distance(@mouse_down_position[button]) > @min_drag_distance
190
+ @dragging_element = @mouse_down_on[button]
191
+ @dragging_element.publish(:begin_drag, window.mouse_x, window.mouse_y, button)
192
+ end
193
+
194
+ if @dragging_element
195
+ @dragging_element.publish(:drag_update, window.mouse_x, window.mouse_y, button) if @dragging_element
196
+ elsif @mouse_over
197
+ @mouse_over.publish(:"holding_#{button}_mouse_button", window.mouse_x, window.mouse_y)
198
+ end
124
199
  end
125
200
 
126
201
  def redirect_mouse_wheel(button)
@@ -131,5 +206,13 @@ module CyberarmEngine
131
206
  def request_recalculate
132
207
  @pending_recalculate_request = true
133
208
  end
209
+
210
+ def show_menu(list_box)
211
+ @menu = list_box
212
+ end
213
+
214
+ def hide_menu
215
+ @menu = nil
216
+ end
134
217
  end
135
- end
218
+ end