cyberarm_engine 0.25.0 → 0.25.1

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 (94) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +8 -8
  3. data/.rubocop.yml +7 -7
  4. data/.travis.yml +5 -5
  5. data/Gemfile +6 -6
  6. data/Gemfile.lock +25 -25
  7. data/LICENSE.txt +21 -21
  8. data/README.md +74 -74
  9. data/Rakefile +10 -10
  10. data/assets/shaders/fragment/g_buffer.glsl +30 -30
  11. data/assets/shaders/fragment/lighting.glsl +115 -115
  12. data/assets/shaders/include/light_struct.glsl +11 -11
  13. data/assets/shaders/include/material_struct.glsl +16 -16
  14. data/assets/shaders/vertex/g_buffer.glsl +28 -28
  15. data/assets/shaders/vertex/lighting.glsl +24 -24
  16. data/bin/console +14 -14
  17. data/bin/setup +8 -8
  18. data/cyberarm_engine.gemspec +36 -36
  19. data/lib/cyberarm_engine/animator.rb +219 -219
  20. data/lib/cyberarm_engine/background.rb +158 -158
  21. data/lib/cyberarm_engine/background_image.rb +93 -93
  22. data/lib/cyberarm_engine/background_nine_slice.rb +142 -142
  23. data/lib/cyberarm_engine/bounding_box.rb +150 -150
  24. data/lib/cyberarm_engine/builtin/intro_state.rb +130 -130
  25. data/lib/cyberarm_engine/cache/download_manager.rb +123 -123
  26. data/lib/cyberarm_engine/cache.rb +4 -4
  27. data/lib/cyberarm_engine/common.rb +131 -131
  28. data/lib/cyberarm_engine/config_file.rb +46 -46
  29. data/lib/cyberarm_engine/console/command.rb +157 -157
  30. data/lib/cyberarm_engine/console/commands/help_command.rb +43 -43
  31. data/lib/cyberarm_engine/console/subcommand.rb +99 -99
  32. data/lib/cyberarm_engine/console.rb +248 -248
  33. data/lib/cyberarm_engine/game_object.rb +244 -244
  34. data/lib/cyberarm_engine/game_state.rb +124 -124
  35. data/lib/cyberarm_engine/gosu_ext/draw_arc.rb +111 -111
  36. data/lib/cyberarm_engine/gosu_ext/draw_circle.rb +30 -30
  37. data/lib/cyberarm_engine/gosu_ext/draw_path.rb +17 -17
  38. data/lib/cyberarm_engine/model/material.rb +21 -21
  39. data/lib/cyberarm_engine/model/mesh.rb +131 -131
  40. data/lib/cyberarm_engine/model/parser.rb +74 -74
  41. data/lib/cyberarm_engine/model/parsers/collada_parser.rb +138 -138
  42. data/lib/cyberarm_engine/model/parsers/wavefront_parser.rb +154 -154
  43. data/lib/cyberarm_engine/model.rb +216 -216
  44. data/lib/cyberarm_engine/model_cache.rb +31 -31
  45. data/lib/cyberarm_engine/notification.rb +82 -82
  46. data/lib/cyberarm_engine/notification_manager.rb +241 -241
  47. data/lib/cyberarm_engine/opengl/light.rb +52 -52
  48. data/lib/cyberarm_engine/opengl/orthographic_camera.rb +46 -46
  49. data/lib/cyberarm_engine/opengl/perspective_camera.rb +41 -41
  50. data/lib/cyberarm_engine/opengl/renderer/bounding_box_renderer.rb +249 -249
  51. data/lib/cyberarm_engine/opengl/renderer/g_buffer.rb +167 -167
  52. data/lib/cyberarm_engine/opengl/renderer/opengl_renderer.rb +307 -307
  53. data/lib/cyberarm_engine/opengl/renderer/renderer.rb +33 -33
  54. data/lib/cyberarm_engine/opengl/shader.rb +408 -408
  55. data/lib/cyberarm_engine/opengl/texture.rb +69 -69
  56. data/lib/cyberarm_engine/opengl.rb +53 -53
  57. data/lib/cyberarm_engine/ray.rb +56 -56
  58. data/lib/cyberarm_engine/result.rb +20 -0
  59. data/lib/cyberarm_engine/stats.rb +200 -200
  60. data/lib/cyberarm_engine/text.rb +260 -260
  61. data/lib/cyberarm_engine/timer.rb +23 -23
  62. data/lib/cyberarm_engine/transform.rb +296 -296
  63. data/lib/cyberarm_engine/trees/aabb_node.rb +126 -126
  64. data/lib/cyberarm_engine/trees/aabb_tree.rb +55 -55
  65. data/lib/cyberarm_engine/trees/aabb_tree_debug.rb +29 -29
  66. data/lib/cyberarm_engine/ui/border_canvas.rb +102 -102
  67. data/lib/cyberarm_engine/ui/dsl.rb +142 -142
  68. data/lib/cyberarm_engine/ui/element.rb +662 -662
  69. data/lib/cyberarm_engine/ui/elements/button.rb +100 -100
  70. data/lib/cyberarm_engine/ui/elements/check_box.rb +54 -54
  71. data/lib/cyberarm_engine/ui/elements/container.rb +407 -407
  72. data/lib/cyberarm_engine/ui/elements/edit_box.rb +179 -179
  73. data/lib/cyberarm_engine/ui/elements/edit_line.rb +297 -297
  74. data/lib/cyberarm_engine/ui/elements/flow.rb +15 -15
  75. data/lib/cyberarm_engine/ui/elements/image.rb +72 -72
  76. data/lib/cyberarm_engine/ui/elements/list_box.rb +79 -79
  77. data/lib/cyberarm_engine/ui/elements/menu.rb +27 -27
  78. data/lib/cyberarm_engine/ui/elements/menu_item.rb +6 -6
  79. data/lib/cyberarm_engine/ui/elements/progress.rb +93 -93
  80. data/lib/cyberarm_engine/ui/elements/radio.rb +6 -6
  81. data/lib/cyberarm_engine/ui/elements/slider.rb +107 -107
  82. data/lib/cyberarm_engine/ui/elements/stack.rb +11 -11
  83. data/lib/cyberarm_engine/ui/elements/text_block.rb +222 -222
  84. data/lib/cyberarm_engine/ui/elements/toggle_button.rb +67 -67
  85. data/lib/cyberarm_engine/ui/event.rb +54 -54
  86. data/lib/cyberarm_engine/ui/gui_state.rb +326 -326
  87. data/lib/cyberarm_engine/ui/style.rb +61 -61
  88. data/lib/cyberarm_engine/ui/theme.rb +225 -225
  89. data/lib/cyberarm_engine/vector.rb +312 -312
  90. data/lib/cyberarm_engine/version.rb +4 -4
  91. data/lib/cyberarm_engine/window.rb +195 -195
  92. data/lib/cyberarm_engine.rb +77 -76
  93. data/mrbgem.rake +29 -29
  94. metadata +4 -3
@@ -1,107 +1,107 @@
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 :value
37
- attr_accessor :range, :step_size
38
-
39
- def initialize(options = {}, block = nil)
40
- super(options, block)
41
-
42
- @range = @options[:range] || (0.0..1.0)
43
- @step_size = @options[:step] || 0.1
44
- @value = @options[:value] || (@range.first + @range.last) / 2
45
-
46
- @handle = Handle.new("", parent: self, theme: options[:theme], width: 8, height: 1.0) { close }
47
- add(@handle)
48
- end
49
-
50
- def recalculate
51
- _width = dimensional_size(@style.width, :width)
52
- _height = dimensional_size(@style.height, :height)
53
-
54
- @width = _width
55
- @height = _height
56
-
57
- position_handle
58
- @handle.recalculate
59
- @handle.update_background
60
-
61
- update_background
62
- end
63
-
64
- def position_handle
65
- @handle.x = @x + @handle.style.margin_left + @style.padding_left + @style.border_thickness_left +
66
- ((content_width - @handle.outer_width) * (@value - @range.min) / (@range.max - @range.min).to_f)
67
-
68
- @handle.y = @y + @handle.style.margin_top + @style.border_thickness_top + @style.padding_top
69
- end
70
-
71
- def draw
72
- super
73
-
74
- @handle.draw
75
- end
76
-
77
- def update
78
- super
79
-
80
- @tip = format("%.2f", value.to_f)
81
- @handle.tip = @tip
82
- end
83
-
84
- def holding_left_mouse_button(_sender, x, y)
85
- handle_dragged_to(x, y)
86
-
87
- :handled
88
- end
89
-
90
- def handle_dragged_to(x, _y)
91
- @ratio = ((x - @handle.width / 2.0) - @x) / (content_width - @handle.outer_width.to_f)
92
-
93
- self.value = @ratio.clamp(0.0, 1.0) * (@range.max - @range.min) + @range.min
94
- end
95
-
96
- def value=(n)
97
- @value = n
98
- position_handle
99
- @handle.recalculate
100
-
101
- root.gui_state.request_repaint
102
-
103
- publish(:changed, @value)
104
- end
105
- end
106
- end
107
- end
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 :value
37
+ attr_accessor :range, :step_size
38
+
39
+ def initialize(options = {}, block = nil)
40
+ super(options, block)
41
+
42
+ @range = @options[:range] || (0.0..1.0)
43
+ @step_size = @options[:step] || 0.1
44
+ @value = @options[:value] || (@range.first + @range.last) / 2
45
+
46
+ @handle = Handle.new("", parent: self, theme: options[:theme], width: 8, height: 1.0) { close }
47
+ add(@handle)
48
+ end
49
+
50
+ def recalculate
51
+ _width = dimensional_size(@style.width, :width)
52
+ _height = dimensional_size(@style.height, :height)
53
+
54
+ @width = _width
55
+ @height = _height
56
+
57
+ position_handle
58
+ @handle.recalculate
59
+ @handle.update_background
60
+
61
+ update_background
62
+ end
63
+
64
+ def position_handle
65
+ @handle.x = @x + @handle.style.margin_left + @style.padding_left + @style.border_thickness_left +
66
+ ((content_width - @handle.outer_width) * (@value - @range.min) / (@range.max - @range.min).to_f)
67
+
68
+ @handle.y = @y + @handle.style.margin_top + @style.border_thickness_top + @style.padding_top
69
+ end
70
+
71
+ def draw
72
+ super
73
+
74
+ @handle.draw
75
+ end
76
+
77
+ def update
78
+ super
79
+
80
+ @tip = format("%.2f", value.to_f)
81
+ @handle.tip = @tip
82
+ end
83
+
84
+ def holding_left_mouse_button(_sender, x, y)
85
+ handle_dragged_to(x, y)
86
+
87
+ :handled
88
+ end
89
+
90
+ def handle_dragged_to(x, _y)
91
+ @ratio = ((x - @handle.width / 2.0) - @x) / (content_width - @handle.outer_width.to_f)
92
+
93
+ self.value = @ratio.clamp(0.0, 1.0) * (@range.max - @range.min) + @range.min
94
+ end
95
+
96
+ def value=(n)
97
+ @value = n
98
+ position_handle
99
+ @handle.recalculate
100
+
101
+ root.gui_state.request_repaint
102
+
103
+ publish(:changed, @value)
104
+ end
105
+ end
106
+ end
107
+ end
@@ -1,11 +1,11 @@
1
- module CyberarmEngine
2
- class Element
3
- class Stack < Container
4
- def layout
5
- @children.each do |child|
6
- move_to_next_line(child)
7
- end
8
- end
9
- end
10
- end
11
- end
1
+ module CyberarmEngine
2
+ class Element
3
+ class Stack < Container
4
+ def layout
5
+ @children.each do |child|
6
+ move_to_next_line(child)
7
+ end
8
+ end
9
+ end
10
+ end
11
+ end
@@ -1,222 +1,222 @@
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
- static: @options[:text_static],
11
- shadow_size: @options[:text_shadow_size],
12
- shadow_color: @options[:text_shadow_color],
13
- border: @options[:text_border],
14
- border_size: @options[:text_border_size],
15
- border_color: @options[:text_border_color]
16
- )
17
-
18
- @raw_text = text
19
- @text_width = @text.width
20
- @text_height = @text.height
21
- end
22
-
23
- def update
24
- super
25
-
26
- if @text.textobject.name != safe_style_fetch(:font)
27
- set_font
28
- root.gui_state.request_recalculate
29
- end
30
- end
31
-
32
- def render
33
- # Gosu.clip_to is too expensive to always use so check if we actually need it.
34
- if @text_width > width || @text_height > height
35
- Gosu.clip_to(@x, @y, width, height) do
36
- @text.draw
37
- end
38
- else
39
- @text.draw
40
- end
41
- end
42
-
43
- def layout
44
- unless @enabled
45
- @text.color = @style.disabled[:color]
46
- else
47
- @text.color = @style.color
48
- end
49
-
50
- @width = 0
51
- @height = 0
52
-
53
- _width = dimensional_size(@style.width, :width)
54
- _height = dimensional_size(@style.height, :height)
55
-
56
- handle_text_wrapping(_width)
57
-
58
- # Update cached text width and height
59
- @text_width = @text.width
60
- @text_height = @text.height
61
-
62
- @width = _width || @text_width.floor
63
- @height = _height || @text_height.floor
64
-
65
- @text.y = @style.border_thickness_top + @style.padding_top + @y
66
- @text.z = @z + 3
67
-
68
- if (text_alignment = @options[:text_align] || @options[:text_h_align])
69
- case text_alignment
70
- when :left
71
- @text.x = @style.border_thickness_left + @style.padding_left + @x
72
- when :center
73
- @text.x = if @text_width <= width
74
- @x + width / 2 - @text_width / 2
75
- else # Act as left aligned
76
- @style.border_thickness_left + @style.padding_left + @x
77
- end
78
- when :right
79
- @text.x = @x + outer_width - (@text_width + @style.border_thickness_right + @style.padding_right)
80
- end
81
- end
82
-
83
- if (vertical_alignment = @options[:text_v_align])
84
- case vertical_alignment
85
- when :center
86
- @text.y = if @text_height <= height
87
- @y + height / 2 - @text_height / 2
88
- else
89
- @style.border_thickness_top + @style.padding_top + @y
90
- end
91
- when :bottom
92
- @text.y = @y + outer_height - (@text_height + @style.border_thickness_bottom + @style.padding_bottom)
93
- end
94
- end
95
-
96
- update_background
97
- end
98
-
99
- def handle_text_wrapping(max_width)
100
- max_width ||= @parent&.content_width
101
- max_width ||= @x - (window.width + noncontent_width)
102
- wrap_behavior = style.text_wrap
103
- copy = @raw_text.to_s.dup
104
-
105
- # Only perform text wrapping: if it is enabled, is possible to wrap, and text is too long to fit on one line
106
- if wrap_behavior != :none && line_width(copy[0]) <= max_width && line_width(copy) > max_width
107
- breaks = [] # list of indexes to insert a line break
108
- line_start = 0
109
- line_end = copy.length
110
-
111
- stalled = false
112
- stalled_interations = 0
113
- max_stalled_iterations = 10
114
- checked_copy_length = line_width(copy[line_start..line_end])
115
-
116
- # find length of lines
117
- while line_width(copy[line_start..line_end]) > max_width && stalled_interations < max_stalled_iterations
118
- search_start = line_start
119
- search_end = line_end
120
-
121
- # Perform a binary search to find length of line
122
- while search_start < search_end
123
- midpoint = ((search_start.to_f + search_end) / 2.0).floor
124
-
125
- if line_width(copy[line_start..midpoint]) > max_width
126
- search_end = midpoint
127
- else
128
- search_start = midpoint + 1
129
- end
130
- end
131
-
132
- if wrap_behavior == :word_wrap
133
- word_search_end = search_end
134
- failed = false
135
-
136
- until(copy[word_search_end].to_s.match(/[[:punct:]]| /))
137
- word_search_end -= 1
138
-
139
- if word_search_end <= 1 || word_search_end < line_start
140
- failed = true
141
- break
142
- end
143
- end
144
-
145
- line_start = failed ? search_end : word_search_end + 1 # walk in front of punctuation
146
- else
147
- line_start = search_end
148
- end
149
-
150
- breaks << line_start
151
-
152
- # Prevent locking up due to outer while loop text width < max_width check not being satisfied.
153
- stalled = checked_copy_length == line_width(copy[line_start..line_end])
154
- checked_copy_length = line_width(copy[line_start..line_end])
155
-
156
- stalled_interations += 1 if stalled
157
- stalled_interations = 0 unless stalled
158
- end
159
-
160
- breaks.each_with_index do |pos, index|
161
- copy.insert(pos + index, "\n") if pos + index >= 0 && pos + index < copy.length
162
- end
163
- end
164
-
165
- @text.text = copy
166
- end
167
-
168
- def line_width(text)
169
- (@text.textobject.markup_width(text.to_s) + noncontent_width)
170
- end
171
-
172
- def value
173
- @raw_text
174
- end
175
-
176
- def value=(value)
177
- old_value = @raw_text
178
- @raw_text = value.to_s.chomp
179
-
180
- old_width = width
181
- old_height = height
182
-
183
- if old_width != width || old_height != height
184
- root.gui_state.request_recalculate
185
- else
186
- recalculate
187
- end
188
-
189
- root.gui_state.request_repaint if old_value != @raw_text
190
-
191
- publish(:changed, self.value)
192
- end
193
- end
194
-
195
- class Banner < TextBlock
196
- end
197
-
198
- class Title < TextBlock
199
- end
200
-
201
- class Subtitle < TextBlock
202
- end
203
-
204
- class Tagline < TextBlock
205
- end
206
-
207
- class Caption < TextBlock
208
- end
209
-
210
- class Para < TextBlock
211
- end
212
-
213
- class Inscription < TextBlock
214
- end
215
-
216
- class ToolTip < TextBlock
217
- end
218
-
219
- class Link < TextBlock
220
- end
221
- end
222
- end
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
+ static: @options[:text_static],
11
+ shadow_size: @options[:text_shadow_size],
12
+ shadow_color: @options[:text_shadow_color],
13
+ border: @options[:text_border],
14
+ border_size: @options[:text_border_size],
15
+ border_color: @options[:text_border_color]
16
+ )
17
+
18
+ @raw_text = text
19
+ @text_width = @text.width
20
+ @text_height = @text.height
21
+ end
22
+
23
+ def update
24
+ super
25
+
26
+ if @text.textobject.name != safe_style_fetch(:font)
27
+ set_font
28
+ root.gui_state.request_recalculate
29
+ end
30
+ end
31
+
32
+ def render
33
+ # Gosu.clip_to is too expensive to always use so check if we actually need it.
34
+ if @text_width > width || @text_height > height
35
+ Gosu.clip_to(@x, @y, width, height) do
36
+ @text.draw
37
+ end
38
+ else
39
+ @text.draw
40
+ end
41
+ end
42
+
43
+ def layout
44
+ unless @enabled
45
+ @text.color = @style.disabled[:color]
46
+ else
47
+ @text.color = @style.color
48
+ end
49
+
50
+ @width = 0
51
+ @height = 0
52
+
53
+ _width = dimensional_size(@style.width, :width)
54
+ _height = dimensional_size(@style.height, :height)
55
+
56
+ handle_text_wrapping(_width)
57
+
58
+ # Update cached text width and height
59
+ @text_width = @text.width
60
+ @text_height = @text.height
61
+
62
+ @width = _width || @text_width.floor
63
+ @height = _height || @text_height.floor
64
+
65
+ @text.y = @style.border_thickness_top + @style.padding_top + @y
66
+ @text.z = @z + 3
67
+
68
+ if (text_alignment = @options[:text_align] || @options[:text_h_align])
69
+ case text_alignment
70
+ when :left
71
+ @text.x = @style.border_thickness_left + @style.padding_left + @x
72
+ when :center
73
+ @text.x = if @text_width <= width
74
+ @x + width / 2 - @text_width / 2
75
+ else # Act as left aligned
76
+ @style.border_thickness_left + @style.padding_left + @x
77
+ end
78
+ when :right
79
+ @text.x = @x + outer_width - (@text_width + @style.border_thickness_right + @style.padding_right)
80
+ end
81
+ end
82
+
83
+ if (vertical_alignment = @options[:text_v_align])
84
+ case vertical_alignment
85
+ when :center
86
+ @text.y = if @text_height <= height
87
+ @y + height / 2 - @text_height / 2
88
+ else
89
+ @style.border_thickness_top + @style.padding_top + @y
90
+ end
91
+ when :bottom
92
+ @text.y = @y + outer_height - (@text_height + @style.border_thickness_bottom + @style.padding_bottom)
93
+ end
94
+ end
95
+
96
+ update_background
97
+ end
98
+
99
+ def handle_text_wrapping(max_width)
100
+ max_width ||= @parent&.content_width
101
+ max_width ||= @x - (window.width + noncontent_width)
102
+ wrap_behavior = style.text_wrap
103
+ copy = @raw_text.to_s.dup
104
+
105
+ # Only perform text wrapping: if it is enabled, is possible to wrap, and text is too long to fit on one line
106
+ if wrap_behavior != :none && line_width(copy[0]) <= max_width && line_width(copy) > max_width
107
+ breaks = [] # list of indexes to insert a line break
108
+ line_start = 0
109
+ line_end = copy.length
110
+
111
+ stalled = false
112
+ stalled_interations = 0
113
+ max_stalled_iterations = 10
114
+ checked_copy_length = line_width(copy[line_start..line_end])
115
+
116
+ # find length of lines
117
+ while line_width(copy[line_start..line_end]) > max_width && stalled_interations < max_stalled_iterations
118
+ search_start = line_start
119
+ search_end = line_end
120
+
121
+ # Perform a binary search to find length of line
122
+ while search_start < search_end
123
+ midpoint = ((search_start.to_f + search_end) / 2.0).floor
124
+
125
+ if line_width(copy[line_start..midpoint]) > max_width
126
+ search_end = midpoint
127
+ else
128
+ search_start = midpoint + 1
129
+ end
130
+ end
131
+
132
+ if wrap_behavior == :word_wrap
133
+ word_search_end = search_end
134
+ failed = false
135
+
136
+ until(copy[word_search_end].to_s.match(/[[:punct:]]| /))
137
+ word_search_end -= 1
138
+
139
+ if word_search_end <= 1 || word_search_end < line_start
140
+ failed = true
141
+ break
142
+ end
143
+ end
144
+
145
+ line_start = failed ? search_end : word_search_end + 1 # walk in front of punctuation
146
+ else
147
+ line_start = search_end
148
+ end
149
+
150
+ breaks << line_start
151
+
152
+ # Prevent locking up due to outer while loop text width < max_width check not being satisfied.
153
+ stalled = checked_copy_length == line_width(copy[line_start..line_end])
154
+ checked_copy_length = line_width(copy[line_start..line_end])
155
+
156
+ stalled_interations += 1 if stalled
157
+ stalled_interations = 0 unless stalled
158
+ end
159
+
160
+ breaks.each_with_index do |pos, index|
161
+ copy.insert(pos + index, "\n") if pos + index >= 0 && pos + index < copy.length
162
+ end
163
+ end
164
+
165
+ @text.text = copy
166
+ end
167
+
168
+ def line_width(text)
169
+ (@text.textobject.markup_width(text.to_s) + noncontent_width)
170
+ end
171
+
172
+ def value
173
+ @raw_text
174
+ end
175
+
176
+ def value=(value)
177
+ old_value = @raw_text
178
+ @raw_text = value.to_s.chomp
179
+
180
+ old_width = width
181
+ old_height = height
182
+
183
+ if old_width != width || old_height != height
184
+ root.gui_state.request_recalculate
185
+ else
186
+ recalculate
187
+ end
188
+
189
+ root.gui_state.request_repaint if old_value != @raw_text
190
+
191
+ publish(:changed, self.value)
192
+ end
193
+ end
194
+
195
+ class Banner < TextBlock
196
+ end
197
+
198
+ class Title < TextBlock
199
+ end
200
+
201
+ class Subtitle < TextBlock
202
+ end
203
+
204
+ class Tagline < TextBlock
205
+ end
206
+
207
+ class Caption < TextBlock
208
+ end
209
+
210
+ class Para < TextBlock
211
+ end
212
+
213
+ class Inscription < TextBlock
214
+ end
215
+
216
+ class ToolTip < TextBlock
217
+ end
218
+
219
+ class Link < TextBlock
220
+ end
221
+ end
222
+ end