cyberarm_engine 0.14.0 → 0.18.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 (68) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +8 -0
  3. data/Gemfile +1 -1
  4. data/README.md +5 -4
  5. data/Rakefile +1 -1
  6. data/assets/textures/default.png +0 -0
  7. data/assets/textures/logo.png +0 -0
  8. data/cyberarm_engine.gemspec +11 -9
  9. data/lib/cyberarm_engine.rb +19 -7
  10. data/lib/cyberarm_engine/animator.rb +13 -11
  11. data/lib/cyberarm_engine/background.rb +19 -15
  12. data/lib/cyberarm_engine/background_nine_slice.rb +125 -0
  13. data/lib/cyberarm_engine/bounding_box.rb +18 -18
  14. data/lib/cyberarm_engine/builtin/intro_state.rb +128 -0
  15. data/lib/cyberarm_engine/cache.rb +4 -0
  16. data/lib/cyberarm_engine/cache/download_manager.rb +121 -0
  17. data/lib/cyberarm_engine/common.rb +18 -13
  18. data/lib/cyberarm_engine/config_file.rb +2 -2
  19. data/lib/cyberarm_engine/game_object.rb +63 -72
  20. data/lib/cyberarm_engine/game_state.rb +11 -3
  21. data/lib/cyberarm_engine/model.rb +207 -0
  22. data/lib/cyberarm_engine/model/material.rb +21 -0
  23. data/lib/cyberarm_engine/model/model_object.rb +131 -0
  24. data/lib/cyberarm_engine/model/parser.rb +74 -0
  25. data/lib/cyberarm_engine/model/parsers/collada_parser.rb +138 -0
  26. data/lib/cyberarm_engine/model/parsers/wavefront_parser.rb +154 -0
  27. data/lib/cyberarm_engine/model_cache.rb +31 -0
  28. data/lib/cyberarm_engine/opengl.rb +28 -0
  29. data/lib/cyberarm_engine/opengl/light.rb +50 -0
  30. data/lib/cyberarm_engine/opengl/orthographic_camera.rb +46 -0
  31. data/lib/cyberarm_engine/opengl/perspective_camera.rb +38 -0
  32. data/lib/cyberarm_engine/opengl/renderer/bounding_box_renderer.rb +249 -0
  33. data/lib/cyberarm_engine/opengl/renderer/g_buffer.rb +164 -0
  34. data/lib/cyberarm_engine/opengl/renderer/opengl_renderer.rb +289 -0
  35. data/lib/cyberarm_engine/opengl/renderer/renderer.rb +22 -0
  36. data/lib/cyberarm_engine/{shader.rb → opengl/shader.rb} +51 -43
  37. data/lib/cyberarm_engine/opengl/texture.rb +69 -0
  38. data/lib/cyberarm_engine/ray.rb +5 -5
  39. data/lib/cyberarm_engine/stats.rb +2 -2
  40. data/lib/cyberarm_engine/text.rb +51 -27
  41. data/lib/cyberarm_engine/timer.rb +1 -1
  42. data/lib/cyberarm_engine/transform.rb +43 -20
  43. data/lib/cyberarm_engine/ui/border_canvas.rb +4 -3
  44. data/lib/cyberarm_engine/ui/dsl.rb +45 -12
  45. data/lib/cyberarm_engine/ui/element.rb +211 -61
  46. data/lib/cyberarm_engine/ui/elements/button.rb +72 -42
  47. data/lib/cyberarm_engine/ui/elements/check_box.rb +5 -2
  48. data/lib/cyberarm_engine/ui/elements/container.rb +81 -29
  49. data/lib/cyberarm_engine/ui/elements/edit_box.rb +175 -2
  50. data/lib/cyberarm_engine/ui/elements/edit_line.rb +139 -48
  51. data/lib/cyberarm_engine/ui/elements/flow.rb +1 -1
  52. data/lib/cyberarm_engine/ui/elements/image.rb +32 -12
  53. data/lib/cyberarm_engine/ui/elements/list_box.rb +78 -2
  54. data/lib/cyberarm_engine/ui/elements/progress.rb +5 -5
  55. data/lib/cyberarm_engine/ui/elements/radio.rb +1 -1
  56. data/lib/cyberarm_engine/ui/elements/slider.rb +13 -16
  57. data/lib/cyberarm_engine/ui/elements/stack.rb +1 -1
  58. data/lib/cyberarm_engine/ui/elements/text_block.rb +153 -0
  59. data/lib/cyberarm_engine/ui/elements/toggle_button.rb +27 -19
  60. data/lib/cyberarm_engine/ui/event.rb +7 -7
  61. data/lib/cyberarm_engine/ui/gui_state.rb +88 -16
  62. data/lib/cyberarm_engine/ui/style.rb +23 -11
  63. data/lib/cyberarm_engine/ui/theme.rb +95 -21
  64. data/lib/cyberarm_engine/vector.rb +33 -30
  65. data/lib/cyberarm_engine/version.rb +2 -2
  66. data/lib/cyberarm_engine/window.rb +35 -18
  67. metadata +70 -18
  68. data/lib/cyberarm_engine/ui/elements/label.rb +0 -52
@@ -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
@@ -0,0 +1,153 @@
1
+ module CyberarmEngine
2
+ class Element
3
+ class TextBlock < Element
4
+ def initialize(text, options = {}, block = nil)
5
+ super(options, block)
6
+
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
15
+ end
16
+
17
+ def render
18
+ @text.draw
19
+ end
20
+
21
+ def recalculate
22
+ @width = 0
23
+ @height = 0
24
+
25
+ _width = dimensional_size(@style.width, :width)
26
+ _height = dimensional_size(@style.height, :height)
27
+
28
+ handle_text_wrapping(_width)
29
+
30
+ @width = _width || @text.width.round
31
+ @height = _height || @text.height.round
32
+
33
+ @text.y = @style.border_thickness_top + @style.padding_top + @y
34
+ @text.z = @z + 3
35
+
36
+ if (text_alignment = @options[:text_align])
37
+ case text_alignment
38
+ when :left
39
+ @text.x = @style.border_thickness_left + @style.padding_left + @x
40
+ when :center
41
+ @text.x = if @text.width <= outer_width
42
+ @x + outer_width / 2 - @text.width / 2
43
+ else # Act as left aligned
44
+ @style.border_thickness_left + @style.padding_left + @x
45
+ end
46
+ when :right
47
+ @text.x = @x + outer_width - (@text.width + @style.border_thickness_right + @style.padding_right)
48
+ end
49
+ end
50
+
51
+ update_background
52
+ end
53
+
54
+ def handle_text_wrapping(max_width)
55
+ max_width ||= @parent&.width
56
+ max_width ||= @x - (window.width + noncontent_width)
57
+ wrap_behavior = style.text_wrap
58
+ copy = @raw_text.to_s.dup
59
+
60
+ if line_width(copy[0]) <= max_width && line_width(copy) > max_width && wrap_behavior != :none
61
+ breaks = []
62
+ line_start = 0
63
+ line_end = copy.length
64
+
65
+ while line_start != copy.length
66
+ if line_width(copy[line_start...line_end]) > max_width
67
+ line_end = ((line_end - line_start) / 2.0)
68
+ line_end = 1.0 if line_end <= 1
69
+ elsif line_end < copy.length && line_width(copy[line_start...line_end + 1]) < max_width
70
+ # To small, grow!
71
+ # TODO: find a more efficient way
72
+ line_end += 1
73
+
74
+ else # FOUND IT!
75
+ entering_line_end = line_end.floor
76
+ max_reach = line_end.floor - line_start < 63 ? line_end.floor - line_start : 63
77
+ reach = 0
78
+
79
+ if wrap_behavior == :word_wrap
80
+ max_reach.times do |i|
81
+ reach = i
82
+ break if copy[line_end.floor - i].to_s.match(/[[:punct:]]| /)
83
+ end
84
+
85
+ # 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]}}"
86
+ line_end = line_end.floor - reach + 1 if reach != max_reach # Add +1 to walk in front of punctuation
87
+ end
88
+
89
+ breaks << line_end.floor
90
+ line_start = line_end.floor
91
+ line_end = copy.length
92
+
93
+ break if entering_line_end == copy.length || reach == max_reach
94
+ end
95
+ end
96
+
97
+ breaks.each_with_index do |pos, index|
98
+ copy.insert(pos + index, "\n") if pos + index >= 0 && pos + index < copy.length
99
+ end
100
+ end
101
+
102
+ @text.text = copy
103
+ end
104
+
105
+ def line_width(text)
106
+ (@text.textobject.markup_width(text) + noncontent_width)
107
+ end
108
+
109
+ def value
110
+ @raw_text
111
+ end
112
+
113
+ def value=(value)
114
+ @raw_text = value.to_s.chomp
115
+
116
+ old_width = width
117
+ old_height = height
118
+ recalculate
119
+
120
+ root.gui_state.request_recalculate if old_width != width || old_height != height
121
+
122
+ publish(:changed, self.value)
123
+ end
124
+ end
125
+
126
+ class Banner < TextBlock
127
+ end
128
+
129
+ class Title < TextBlock
130
+ end
131
+
132
+ class Subtitle < TextBlock
133
+ end
134
+
135
+ class Tagline < TextBlock
136
+ end
137
+
138
+ class Caption < TextBlock
139
+ end
140
+
141
+ class Para < TextBlock
142
+ end
143
+
144
+ class Inscription < TextBlock
145
+ end
146
+
147
+ class ToolTip < TextBlock
148
+ end
149
+
150
+ class Link < TextBlock
151
+ end
152
+ end
153
+ 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
@@ -17,22 +17,28 @@ module CyberarmEngine
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
25
28
 
26
- @tip = CyberarmEngine::Text.new("", size: 22, z: Float::INFINITY)
27
29
  @menu = nil
28
30
  @min_drag_distance = 0
29
31
  @mouse_pos = Vector.new
30
32
  end
31
33
 
34
+ def post_setup
35
+ @tip = Element::ToolTip.new("", parent: @root_container, z: Float::INFINITY, theme: current_theme)
36
+ end
37
+
32
38
  # throws :blur event to focused element and sets GuiState focused element
33
39
  # Does NOT throw :focus event at element or set element as focused
34
40
  def focus=(element)
35
- @focus.publish(:blur) if @focus and element && @focus != element
41
+ @focus.publish(:blur) if @focus && element && @focus != element
36
42
  @focus = element
37
43
  end
38
44
 
@@ -43,22 +49,45 @@ module CyberarmEngine
43
49
  def draw
44
50
  super
45
51
 
46
- if @tip.text.length > 0
47
- Gosu.draw_rect(@tip.x - 2, @tip.y - 2, @tip.width + 4, @tip.height + 4, 0xff020202, Float::INFINITY)
52
+ if @menu
53
+ Gosu.flush
54
+ @menu.draw
55
+ end
56
+
57
+ if @tip.value.length.positive?
58
+ Gosu.flush
48
59
  @tip.draw
49
60
  end
61
+
62
+ if defined?(GUI_DEBUG)
63
+ Gosu.flush
64
+
65
+ @root_container.debug_draw
66
+ end
50
67
  end
51
68
 
52
69
  def update
53
70
  if @pending_recalculate_request
54
71
  @root_container.recalculate
55
72
  @root_container.recalculate
73
+ @root_container.recalculate
74
+
56
75
  @pending_recalculate_request = false
57
76
  end
58
77
 
78
+ if @pending_focus_request
79
+ @pending_focus_request = false
80
+
81
+ self.focus = @pending_focus_element
82
+ @pending_focus_element.publish(:focus)
83
+ end
84
+
85
+ @menu&.update
59
86
  super
60
87
 
61
- new_mouse_over = @root_container.hit_element?(window.mouse_x, window.mouse_y)
88
+ new_mouse_over = @menu.hit_element?(window.mouse_x, window.mouse_y) if @menu
89
+ new_mouse_over ||= @root_container.hit_element?(window.mouse_x, window.mouse_y)
90
+
62
91
  if new_mouse_over
63
92
  new_mouse_over.publish(:enter) if new_mouse_over != @mouse_over
64
93
  new_mouse_over.publish(:hover)
@@ -73,10 +102,17 @@ module CyberarmEngine
73
102
 
74
103
  if Vector.new(window.mouse_x, window.mouse_y) == @last_mouse_pos
75
104
  if @mouse_over && (Gosu.milliseconds - @mouse_moved_at) > tool_tip_delay
76
- @tip.text = @mouse_over.tip if @mouse_over
77
- @tip.x, @tip.y = window.mouse_x - @tip.width / 2, window.mouse_y - @tip.height - 4
105
+ @tip.value = @mouse_over.tip if @mouse_over
106
+ @tip.x = window.mouse_x - @tip.width / 2
107
+ @tip.x = 0 if @tip.x < 0
108
+ @tip.x = window.width - @tip.width if @tip.x + @tip.width > window.width
109
+ @tip.y = window.mouse_y - (@tip.height + 5)
110
+ @tip.y = 0 if @tip.y < 0
111
+ @tip.y = window.height - @tip.height if @tip.y + @tip.height > window.height
112
+ @tip.update
113
+ @tip.recalculate
78
114
  else
79
- @tip.text = ""
115
+ @tip.value = ""
80
116
  end
81
117
  else
82
118
  @mouse_moved_at = Gosu.milliseconds
@@ -85,14 +121,17 @@ module CyberarmEngine
85
121
  @last_mouse_pos = Vector.new(window.mouse_x, window.mouse_y)
86
122
  @mouse_pos = @last_mouse_pos.clone
87
123
 
88
- request_recalculate if @active_width != window.width || @active_height != window.height
124
+ if @active_width != window.width || @active_height != window.height
125
+ request_recalculate
126
+ @root_container.publish(:window_size_changed)
127
+ end
89
128
 
90
129
  @active_width = window.width
91
130
  @active_height = window.height
92
131
  end
93
132
 
94
133
  def tool_tip_delay
95
- 500 # ms
134
+ 250 # ms
96
135
  end
97
136
 
98
137
  def button_down(id)
@@ -108,6 +147,8 @@ module CyberarmEngine
108
147
  when Gosu::KbF5
109
148
  request_recalculate
110
149
  end
150
+
151
+ @focus.button_down(id) if @focus.respond_to?(:button_down)
111
152
  end
112
153
 
113
154
  def button_up(id)
@@ -125,9 +166,13 @@ module CyberarmEngine
125
166
  when Gosu::MsWheelDown
126
167
  redirect_mouse_wheel(:down)
127
168
  end
169
+
170
+ @focus.button_up(id) if @focus.respond_to?(:button_up)
128
171
  end
129
172
 
130
173
  def redirect_mouse_button(button)
174
+ hide_menu unless @menu && (@menu == @mouse_over) || (@mouse_over&.parent == @menu)
175
+
131
176
  if @focus && @mouse_over != @focus
132
177
  @focus.publish(:blur)
133
178
  @focus = nil
@@ -145,9 +190,14 @@ module CyberarmEngine
145
190
  end
146
191
 
147
192
  def redirect_released_mouse_button(button)
193
+ hide_menu if @menu && (@menu == @mouse_over) || (@mouse_over&.parent == @menu)
194
+
148
195
  if @mouse_over
149
196
  @mouse_over.publish(:"released_#{button}_mouse_button", window.mouse_x, window.mouse_y)
150
- @mouse_over.publish(:"clicked_#{button}_mouse_button", window.mouse_x, window.mouse_y) if @mouse_over == @mouse_down_on[button]
197
+ if @mouse_over == @mouse_down_on[button]
198
+ @mouse_over.publish(:"clicked_#{button}_mouse_button", window.mouse_x,
199
+ window.mouse_y)
200
+ end
151
201
  end
152
202
 
153
203
  if @dragging_element
@@ -162,13 +212,13 @@ module CyberarmEngine
162
212
  def redirect_holding_mouse_button(button)
163
213
  if !@dragging_element && @mouse_down_on[button] && @mouse_down_on[button].draggable?(button) && @mouse_pos.distance(@mouse_down_position[button]) > @min_drag_distance
164
214
  @dragging_element = @mouse_down_on[button]
165
- @dragging_element.publish(:"begin_drag", window.mouse_x, window.mouse_y, button)
215
+ @dragging_element.publish(:begin_drag, window.mouse_x, window.mouse_y, button)
166
216
  end
167
217
 
168
218
  if @dragging_element
169
- @dragging_element.publish(:"drag_update", window.mouse_x, window.mouse_y, button) if @dragging_element
170
- else
171
- @mouse_over.publish(:"holding_#{button}_mouse_button", window.mouse_x, window.mouse_y) if @mouse_over
219
+ @dragging_element.publish(:drag_update, window.mouse_x, window.mouse_y, button) if @dragging_element
220
+ elsif @mouse_over
221
+ @mouse_over.publish(:"holding_#{button}_mouse_button", window.mouse_x, window.mouse_y)
172
222
  end
173
223
  end
174
224
 
@@ -180,5 +230,27 @@ module CyberarmEngine
180
230
  def request_recalculate
181
231
  @pending_recalculate_request = true
182
232
  end
233
+
234
+ def request_focus(element)
235
+ @pending_focus_request = true
236
+ @pending_focus_element = element
237
+ end
238
+
239
+ def show_menu(list_box)
240
+ @menu = list_box
241
+ end
242
+
243
+ def hide_menu
244
+ @menu = nil
245
+ end
246
+
247
+ def to_s
248
+ # "#{self.class} children=#{@children.map { |c| c.to_s }}"
249
+ @root_container.to_s
250
+ end
251
+
252
+ def inspect
253
+ to_s
254
+ end
183
255
  end
184
- end
256
+ end