diff --git a/lib/cyberarm_engine/text.rb b/lib/cyberarm_engine/text.rb index 318532f..f1d4c72 100644 --- a/lib/cyberarm_engine/text.rb +++ b/lib/cyberarm_engine/text.rb @@ -115,22 +115,23 @@ module CyberarmEngine if @shadow && !ARGV.join.include?("--no-shadow") shadow_alpha = @color.alpha <= 30 ? @color.alpha : @shadow_alpha shadow_color = @shadow_color ? @shadow_color : Gosu::Color.rgba(@color.red, @color.green, @color.blue, shadow_alpha) + white = Gosu::Color::WHITE _x = @shadow_size _y = @shadow_size @rendered_shadow ||= Gosu.render((self.width+(shadow_size*2)).ceil, (self.height+(@shadow_size*2)).ceil) do - @textobject.send(method, @text, _x-@shadow_size, _y, @z) - @textobject.send(method, @text, _x-@shadow_size, _y-@shadow_size, @z) + @textobject.send(method, @text, _x-@shadow_size, _y, @z, @factor_x, @factor_y, white, :add) + @textobject.send(method, @text, _x-@shadow_size, _y-@shadow_size, @z, @factor_x, @factor_y, white, :add) - @textobject.send(method, @text, _x, _y-@shadow_size, @z, @factor_x) - @textobject.send(method, @text, _x+@shadow_size, _y-@shadow_size, @z) + @textobject.send(method, @text, _x, _y-@shadow_size, @z, @factor_x, @factor_y, white, :add) + @textobject.send(method, @text, _x+@shadow_size, _y-@shadow_size, @z, @factor_x, @factor_y, white, :add) - @textobject.send(method, @text, _x, _y+@shadow_size, @z) - @textobject.send(method, @text, _x-@shadow_size, _y+@shadow_size, @z) + @textobject.send(method, @text, _x, _y+@shadow_size, @z, @factor_x, @factor_y, white, :add) + @textobject.send(method, @text, _x-@shadow_size, _y+@shadow_size, @z, @factor_x, @factor_y, white, :add) - @textobject.send(method, @text, _x+@shadow_size, _y, @z) - @textobject.send(method, @text, _x+@shadow_size, _y+@shadow_size, @z) + @textobject.send(method, @text, _x+@shadow_size, _y, @z, @factor_x, @factor_y, white, :add) + @textobject.send(method, @text, _x+@shadow_size, _y+@shadow_size, @z, @factor_x, @factor_y, white, :add) end @rendered_shadow.draw(@x-@shadow_size, @y-@shadow_size, @z, @factor_x, @factor_y, shadow_color) end diff --git a/lib/cyberarm_engine/ui/element.rb b/lib/cyberarm_engine/ui/element.rb index 9fcb6d4..ab9a5b0 100644 --- a/lib/cyberarm_engine/ui/element.rb +++ b/lib/cyberarm_engine/ui/element.rb @@ -226,16 +226,15 @@ module CyberarmEngine (@style.border_thickness_top + @style.padding_top) + (@style.padding_bottom + @style.border_thickness_bottom) end - private def dimensional_size(size, dimension) + def dimensional_size(size, dimension) raise "dimension must be either :width or :height" unless dimension == :width || dimension == :height + if size && size.is_a?(Numeric) if size.between?(0.0, 1.0) ((@parent.send(:"content_#{dimension}") - self.send(:"noncontent_#{dimension}")) * size).round else size end - else - nil end end diff --git a/lib/cyberarm_engine/ui/elements/label.rb b/lib/cyberarm_engine/ui/elements/label.rb index 0b8e196..0c671b9 100644 --- a/lib/cyberarm_engine/ui/elements/label.rb +++ b/lib/cyberarm_engine/ui/elements/label.rb @@ -10,6 +10,8 @@ module CyberarmEngine shadow_size: @options[:text_shadow_size], shadow_color: @options[:text_shadow_color] ) + + @raw_text = text end def render @@ -17,24 +19,27 @@ module CyberarmEngine end def clicked_left_mouse_button(sender, x, y) - @block.call(self) if @block + @block&.call(self) # return :handled end def recalculate - @width, @height = 0, 0 + @width = 0 + @height = 0 - _width = dimensional_size(@style.width, :width) - _height= dimensional_size(@style.height,:height) + _width = dimensional_size(@style.width, :width) + _height = dimensional_size(@style.height, :height) - @width = _width ? _width : @text.width.round - @height= _height ? _height : @text.height.round + handle_text_wrapping(_width) - @text.y = @style.border_thickness_top + @style.padding_top + @y + @width = _width || @text.width.round + @height = _height || @text.height.round + + @text.y = @style.border_thickness_top + @style.padding_top + @y @text.z = @z + 3 - if text_alignment = @options[:text_align] + if (text_alignment = @options[:text_align]) case text_alignment when :left @text.x = @style.border_thickness_left + @style.padding_left + @x @@ -52,14 +57,69 @@ module CyberarmEngine update_background end + def handle_text_wrapping(max_width) + max_width ||= @parent&.width + max_width ||= @x - (window.width + noncontent_width) + wrap_behavior = style.text_wrap + copy = @raw_text.to_s.dup + + if max_width >= line_width(copy[0]) && line_width(copy) > max_width && wrap_behavior != :none + breaks = [] + line_start = 0 + line_end = copy.length + + while line_start != copy.length + if line_width(copy[line_start...line_end]) > max_width + line_end = ((line_end - line_start) / 2.0) + elsif line_end < copy.length && line_width(copy[line_start...line_end + 1]) < max_width + # To small, grow! + # TODO: find a more efficient way + line_end += 1 + + else # FOUND IT! + entering_line_end = line_end.floor + max_reach = line_end.floor - line_start < 63 ? line_end.floor - line_start : 63 + reach = 0 + + if wrap_behavior == :word_wrap + max_reach.times do |i| + reach = i + break if copy[line_end.floor - i].to_s.match(/[[:punct:]]|[ ]/) + end + + 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]}}" + line_end = line_end.floor - reach + 1 if reach != max_reach # Add +1 to walk in front of punctuation + end + + breaks << line_end.floor + line_start = line_end.floor + line_end = copy.length + + break if entering_line_end == copy.length || reach == max_reach + end + end + + breaks.each_with_index do |pos, index| + copy.insert(pos + index, "\n") if pos + index >= 0 && pos + index < copy.length + end + end + + @text.text = copy + end + + def line_width(text) + (@x + @text.textobject.markup_width(text) + noncontent_width) + end + def value - @text.text + @raw_text end def value=(value) - @text.text = value + @raw_text = value.to_s.chomp - old_width, old_height = width, height + old_width = width + old_height = height recalculate root.gui_state.request_recalculate if old_width != width || old_height != height diff --git a/lib/cyberarm_engine/ui/elements/toggle_button.rb b/lib/cyberarm_engine/ui/elements/toggle_button.rb index a18b60d..939de54 100644 --- a/lib/cyberarm_engine/ui/elements/toggle_button.rb +++ b/lib/cyberarm_engine/ui/elements/toggle_button.rb @@ -17,13 +17,11 @@ module CyberarmEngine if @value @image = @_image if @_image - @text.text = @options[:checkmark] + @raw_text = @options[:checkmark] else @image = nil - @text.text = "" + @raw_text = "" end - - return self end def clicked_left_mouse_button(sender, x, y) @@ -35,19 +33,16 @@ module CyberarmEngine end def recalculate - if @image - super - else - super + super + return if @image - _width = dimensional_size(@style.width, :width) - _height= dimensional_size(@style.height,:height) + _width = dimensional_size(@style.width, :width) + _height = dimensional_size(@style.height, :height) - @width = _width ? _width : @text.textobject.text_width(@options[:checkmark]) - @height = _height ? _height : @text.height + @width = _width || @text.textobject.text_width(@options[:checkmark]) + @height = _height || @text.height - update_background - end + update_background end def value @@ -59,10 +54,10 @@ module CyberarmEngine if boolean @image = @_image if @_image - @text.text = @options[:checkmark] + @raw_text = @options[:checkmark] else @image = nil - @text.text = "" + @raw_text = "" end recalculate diff --git a/lib/cyberarm_engine/ui/gui_state.rb b/lib/cyberarm_engine/ui/gui_state.rb index a09d900..14d357f 100644 --- a/lib/cyberarm_engine/ui/gui_state.rb +++ b/lib/cyberarm_engine/ui/gui_state.rb @@ -51,7 +51,8 @@ module CyberarmEngine @menu.draw end - if @tip.text.length > 0 + if @tip.text.length.positive? + Gosu.flush Gosu.draw_rect(@tip.x - 2, @tip.y - 2, @tip.width + 4, @tip.height + 4, 0xff020202, Float::INFINITY) @tip.draw end @@ -66,11 +67,11 @@ module CyberarmEngine @pending_recalculate_request = false end - @menu.update if @menu + @menu&.update super new_mouse_over = @menu.hit_element?(window.mouse_x, window.mouse_y) if @menu - new_mouse_over = @root_container.hit_element?(window.mouse_x, window.mouse_y) unless new_mouse_over + new_mouse_over ||= @root_container.hit_element?(window.mouse_x, window.mouse_y) if new_mouse_over new_mouse_over.publish(:enter) if new_mouse_over != @mouse_over diff --git a/lib/cyberarm_engine/ui/theme.rb b/lib/cyberarm_engine/ui/theme.rb index 686672d..504b271 100644 --- a/lib/cyberarm_engine/ui/theme.rb +++ b/lib/cyberarm_engine/ui/theme.rb @@ -51,29 +51,30 @@ module CyberarmEngine y: 0, z: 30, - width: nil, + width: nil, height: nil, - color: Gosu::Color::WHITE, + color: Gosu::Color::WHITE, background: Gosu::Color::NONE, - margin: 0, - padding: 0, + margin: 0, + padding: 0, border_thickness: 0, border_color: Gosu::Color::NONE, - border_radius: 0, + border_radius: 0 }, Button: { # < Label - margin: 1, - padding: 4, + margin: 1, + padding: 4, border_thickness: 1, border_color: ["ffd59674".hex, "ffff8746".hex], border_radius: 0, background: ["ffc75e61".to_i(16), "ffe26623".to_i(16)], text_align: :center, + text_wrap: :none, hover: { color: Gosu::Color.rgb(200,200,200), - background: ["ffB23E41".to_i(16), "ffFF7C00".to_i(16)], + background: ["ffB23E41".to_i(16), "ffFF7C00".to_i(16)] }, active: { @@ -90,7 +91,7 @@ module CyberarmEngine caret_color: Gosu::Color::WHITE, caret_interval: 500, selection_color: Gosu::Color.rgba(255, 128, 50, 200), - text_align: :left, + text_align: :left }, Image: { # < Element @@ -99,12 +100,13 @@ module CyberarmEngine }, Label: { # < Element - text_size: 28, - text_shadow: false, - text_align: :left, - font: "Arial", - margin: 0, - padding: 2 + text_size: 28, + text_wrap: :none, # :word_wrap, :break_word, :none + text_shadow: false, + text_align: :left, + font: "Arial", + margin: 0, + padding: 2 }, ToggleButton: { # < Button diff --git a/lib/cyberarm_engine/window.rb b/lib/cyberarm_engine/window.rb index 3bc8011..4512317 100644 --- a/lib/cyberarm_engine/window.rb +++ b/lib/cyberarm_engine/window.rb @@ -16,10 +16,10 @@ module CyberarmEngine $window.last_frame_time/1000.0 end - def initialize(width: 800, height: 600, fullscreen: false, update_interval: 1000.0/60, resizable: false) + def initialize(width: 800, height: 600, fullscreen: false, update_interval: 1000.0/60, resizable: false, borderless: false) @show_cursor = false - super(width, height, fullscreen: fullscreen, update_interval: update_interval, resizable: resizable) + super(width, height, fullscreen: fullscreen, update_interval: update_interval, resizable: resizable, borderless: borderless) $window = self @last_frame_time = Gosu.milliseconds-1 @current_frame_time = Gosu.milliseconds