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
@@ -4,43 +4,122 @@ module CyberarmEngine
4
4
  def initialize(text, options = {}, block = nil)
5
5
  super(options, block)
6
6
 
7
- @text = Text.new(text, font: @options[:font], z: @z, color: @options[:color], size: @options[:text_size], shadow: @options[:text_shadow])
7
+ @text = Text.new(
8
+ text, font: @options[:font], z: @z, color: @options[:color],
9
+ size: @options[:text_size], shadow: @options[:text_shadow],
10
+ shadow_size: @options[:text_shadow_size],
11
+ shadow_color: @options[:text_shadow_color]
12
+ )
13
+
14
+ @raw_text = text
8
15
  end
9
16
 
10
17
  def render
11
18
  @text.draw
12
19
  end
13
20
 
14
- def clicked_left_mouse_button(sender, x, y)
15
- @block.call(self) if @block
21
+ def clicked_left_mouse_button(_sender, _x, _y)
22
+ @block&.call(self)
16
23
 
17
24
  # return :handled
18
25
  end
19
26
 
20
27
  def recalculate
21
- @width, @height = 0, 0
28
+ @width = 0
29
+ @height = 0
30
+
31
+ _width = dimensional_size(@style.width, :width)
32
+ _height = dimensional_size(@style.height, :height)
22
33
 
23
- _width = dimensional_size(@style.width, :width)
24
- _height= dimensional_size(@style.height,:height)
34
+ handle_text_wrapping(_width)
25
35
 
26
- @width = _width ? _width : @text.width.round
27
- @height= _height ? _height : @text.height.round
36
+ @width = _width || @text.width.round
37
+ @height = _height || @text.height.round
28
38
 
29
- @text.x = @style.border_thickness_left + @style.padding_left + @x
30
- @text.y = @style.border_thickness_top + @style.padding_top + @y
39
+ @text.y = @style.border_thickness_top + @style.padding_top + @y
31
40
  @text.z = @z + 3
32
41
 
42
+ if (text_alignment = @options[:text_align])
43
+ case text_alignment
44
+ when :left
45
+ @text.x = @style.border_thickness_left + @style.padding_left + @x
46
+ when :center
47
+ @text.x = if @text.width <= outer_width
48
+ @x + outer_width / 2 - @text.width / 2
49
+ else # Act as left aligned
50
+ @style.border_thickness_left + @style.padding_left + @x
51
+ end
52
+ when :right
53
+ @text.x = @x + outer_width - (@text.width + @style.border_thickness_right + @style.padding_right)
54
+ end
55
+ end
56
+
33
57
  update_background
34
58
  end
35
59
 
60
+ def handle_text_wrapping(max_width)
61
+ max_width ||= @parent&.width
62
+ max_width ||= @x - (window.width + noncontent_width)
63
+ wrap_behavior = style.text_wrap
64
+ copy = @raw_text.to_s.dup
65
+
66
+ if max_width >= line_width(copy[0]) && line_width(copy) > max_width && wrap_behavior != :none
67
+ breaks = []
68
+ line_start = 0
69
+ line_end = copy.length
70
+
71
+ while line_start != copy.length
72
+ if line_width(copy[line_start...line_end]) > max_width
73
+ line_end = ((line_end - line_start) / 2.0)
74
+ elsif line_end < copy.length && line_width(copy[line_start...line_end + 1]) < max_width
75
+ # To small, grow!
76
+ # TODO: find a more efficient way
77
+ line_end += 1
78
+
79
+ else # FOUND IT!
80
+ entering_line_end = line_end.floor
81
+ max_reach = line_end.floor - line_start < 63 ? line_end.floor - line_start : 63
82
+ reach = 0
83
+
84
+ if wrap_behavior == :word_wrap
85
+ max_reach.times do |i|
86
+ reach = i
87
+ break if copy[line_end.floor - i].to_s.match(/[[:punct:]]| /)
88
+ end
89
+
90
+ puts "Max width: #{max_width}/#{line_width(@raw_text)} Reach: {#{reach}/#{max_reach}} Line Start: #{line_start}/#{line_end.floor} (#{copy.length}|#{@raw_text.length}) [#{entering_line_end}] '#{copy}' {#{copy[line_start...line_end]}}"
91
+ line_end = line_end.floor - reach + 1 if reach != max_reach # Add +1 to walk in front of punctuation
92
+ end
93
+
94
+ breaks << line_end.floor
95
+ line_start = line_end.floor
96
+ line_end = copy.length
97
+
98
+ break if entering_line_end == copy.length || reach == max_reach
99
+ end
100
+ end
101
+
102
+ breaks.each_with_index do |pos, index|
103
+ copy.insert(pos + index, "\n") if pos + index >= 0 && pos + index < copy.length
104
+ end
105
+ end
106
+
107
+ @text.text = copy
108
+ end
109
+
110
+ def line_width(text)
111
+ (@x + @text.textobject.markup_width(text) + noncontent_width)
112
+ end
113
+
36
114
  def value
37
- @text.text
115
+ @raw_text
38
116
  end
39
117
 
40
118
  def value=(value)
41
- @text.text = value
119
+ @raw_text = value.to_s.chomp
42
120
 
43
- old_width, old_height = width, height
121
+ old_width = width
122
+ old_height = height
44
123
  recalculate
45
124
 
46
125
  root.gui_state.request_recalculate if old_width != width || old_height != height
@@ -49,4 +128,4 @@ module CyberarmEngine
49
128
  end
50
129
  end
51
130
  end
52
- end
131
+ end
@@ -1,6 +1,68 @@
1
1
  module CyberarmEngine
2
2
  class Element
3
- class ListBox < 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
4
66
  end
5
67
  end
6
- 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
@@ -44,8 +44,8 @@ module CyberarmEngine
44
44
  update_background
45
45
 
46
46
  publish(:changed, @fraction)
47
- return @fraction
47
+ @fraction
48
48
  end
49
49
  end
50
50
  end
51
- end
51
+ end
@@ -3,4 +3,4 @@ module CyberarmEngine
3
3
  class Radio < Element
4
4
  end
5
5
  end
6
- end
6
+ end
@@ -9,13 +9,13 @@ module CyberarmEngine
9
9
  event(:drag_update)
10
10
  event(:end_drag)
11
11
 
12
- subscribe :begin_drag do |sender, x, y, button|
12
+ subscribe :begin_drag do |_sender, x, y, _button|
13
13
  @drag_start_pos = Vector.new(x, y)
14
14
 
15
15
  :handled
16
16
  end
17
17
 
18
- subscribe :drag_update do |sender, x, y, button|
18
+ subscribe :drag_update do |_sender, x, y, _button|
19
19
  @parent.handle_dragged_to(x, y)
20
20
 
21
21
  :handled
@@ -33,21 +33,22 @@ module CyberarmEngine
33
33
  end
34
34
  end
35
35
 
36
- attr_reader :range, :step_size
36
+ attr_reader :range, :step_size, :value
37
+
37
38
  def initialize(options = {}, block = nil)
38
39
  super(options, block)
39
40
 
40
- @range = @options[:range] ? @options[:range] : 0.0..1.0
41
- @step_size = @options[:step] ? @options[:step] : 0.1
42
- @value = @options[:value] ? @options[:value] : (@range.first + @range.last) / 2
41
+ @range = @options[:range] || (0.0..1.0)
42
+ @step_size = @options[:step] || 0.1
43
+ @value = @options[:value] || (@range.first + @range.last) / 2
43
44
 
44
45
  @handle = Handle.new("", parent: self, width: 8, height: 1.0) { close }
45
- self.add(@handle)
46
+ add(@handle)
46
47
  end
47
48
 
48
49
  def recalculate
49
50
  _width = dimensional_size(@style.width, :width)
50
- _height= dimensional_size(@style.height,:height)
51
+ _height = dimensional_size(@style.height, :height)
51
52
 
52
53
  @width = _width
53
54
  @height = _height
@@ -61,7 +62,7 @@ module CyberarmEngine
61
62
 
62
63
  def position_handle
63
64
  @handle.x = @x + @style.padding_left + @style.border_thickness_left +
64
- ((content_width - @handle.outer_width) * (@value - @range.min) / (@range.max - @range.min).to_f)
65
+ ((content_width - @handle.outer_width) * (@value - @range.min) / (@range.max - @range.min).to_f)
65
66
 
66
67
  @handle.y = @y + @style.border_thickness_top + @style.padding_top
67
68
  end
@@ -79,22 +80,18 @@ module CyberarmEngine
79
80
  @handle.tip = @tip
80
81
  end
81
82
 
82
- def holding_left_mouse_button(sender, x, y)
83
+ def holding_left_mouse_button(_sender, x, y)
83
84
  handle_dragged_to(x, y)
84
85
 
85
86
  :handled
86
87
  end
87
88
 
88
- def handle_dragged_to(x, y)
89
+ def handle_dragged_to(x, _y)
89
90
  @ratio = ((x - @handle.width / 2) - @x) / (content_width - @handle.outer_width)
90
91
 
91
92
  self.value = @ratio.clamp(0.0, 1.0) * (@range.max - @range.min) + @range.min
92
93
  end
93
94
 
94
- def value
95
- @value
96
- end
97
-
98
95
  def value=(n)
99
96
  @value = n
100
97
  position_handle
@@ -104,4 +101,4 @@ module CyberarmEngine
104
101
  end
105
102
  end
106
103
  end
107
- end
104
+ end
@@ -8,4 +8,4 @@ module CyberarmEngine
8
8
  end
9
9
  end
10
10
  end
11
- end
11
+ end
@@ -1,51 +1,59 @@
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)
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
12
+ else
13
+ super(options[:checkmark], options, block)
14
+ end
15
+
8
16
  @value = options[:checked] || false
17
+
9
18
  if @value
10
- @text.text = @options[:checkmark]
19
+ @image = @_image if @_image
20
+ @raw_text = @options[:checkmark]
11
21
  else
12
- @text.text = ""
22
+ @image = nil
23
+ @raw_text = ""
13
24
  end
14
-
15
- return self
16
25
  end
17
26
 
18
- def clicked_left_mouse_button(sender, x, y)
27
+ def clicked_left_mouse_button(_sender, _x, _y)
19
28
  self.value = !@value
20
29
 
21
30
  @block.call(self) if @block
22
31
 
23
- return :handled
32
+ :handled
24
33
  end
25
34
 
26
35
  def recalculate
27
36
  super
37
+ return if @image
28
38
 
29
- _width = dimensional_size(@style.width, :width)
30
- _height= dimensional_size(@style.height,:height)
39
+ _width = dimensional_size(@style.width, :width)
40
+ _height = dimensional_size(@style.height, :height)
31
41
 
32
- @width = _width ? _width : @text.textobject.text_width(@options[:checkmark])
33
- @height = _height ? _height : @text.height
42
+ @width = _width || @text.textobject.text_width(@options[:checkmark])
43
+ @height = _height || @text.height
34
44
 
35
45
  update_background
36
46
  end
37
47
 
38
- def value
39
- @value
40
- end
41
-
42
48
  def value=(boolean)
43
49
  @value = boolean
44
50
 
45
51
  if boolean
46
- @text.text = @options[:checkmark]
52
+ @image = @_image if @_image
53
+ @raw_text = @options[:checkmark]
47
54
  else
48
- @text.text = ""
55
+ @image = nil
56
+ @raw_text = ""
49
57
  end
50
58
 
51
59
  recalculate
@@ -54,4 +62,4 @@ module CyberarmEngine
54
62
  end
55
63
  end
56
64
  end
57
- end
65
+ end
@@ -15,20 +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
24
  parent.publish(event, *args) if parent
27
- return nil
25
+ nil
28
26
  end
29
27
 
30
28
  def event(event)
31
- @event_handler ||= Hash.new
29
+ @event_handler ||= {}
32
30
  @event_handler[event] ||= []
33
31
  end
34
32
  end
@@ -37,11 +35,13 @@ module CyberarmEngine
37
35
  attr_reader :publisher, :event, :handler
38
36
 
39
37
  def initialize(publisher, event, handler)
40
- @publisher, @event, @handler = publisher, event, handler
38
+ @publisher = publisher
39
+ @event = event
40
+ @handler = handler
41
41
  end
42
42
 
43
43
  def unsubscribe
44
44
  @publisher.unsubscribe(self)
45
45
  end
46
46
  end
47
- end
47
+ end