From 1a06a9fdaa79b5e3912abe8c3f37dcb3371ad473 Mon Sep 17 00:00:00 2001 From: Cyberarm Date: Fri, 1 Feb 2019 20:18:07 -0600 Subject: [PATCH] Added Image and Timer, Container and Element positioning and padding issues maybe fixed. --- lib/cyberarm_engine.rb | 2 + lib/cyberarm_engine/objects/timer.rb | 23 +++++ lib/cyberarm_engine/ui/button.rb | 2 +- lib/cyberarm_engine/ui/container.rb | 66 +++++++++----- lib/cyberarm_engine/ui/dsl.rb | 12 ++- lib/cyberarm_engine/ui/edit_line.rb | 127 +++++++++++---------------- lib/cyberarm_engine/ui/element.rb | 18 +++- lib/cyberarm_engine/ui/image.rb | 35 ++++++++ 8 files changed, 178 insertions(+), 107 deletions(-) create mode 100644 lib/cyberarm_engine/objects/timer.rb create mode 100644 lib/cyberarm_engine/ui/image.rb diff --git a/lib/cyberarm_engine.rb b/lib/cyberarm_engine.rb index ba19a9a..3fdf0cb 100644 --- a/lib/cyberarm_engine.rb +++ b/lib/cyberarm_engine.rb @@ -8,6 +8,7 @@ require_relative "cyberarm_engine/game_object" require_relative "cyberarm_engine/engine" require_relative "cyberarm_engine/objects/text" +require_relative "cyberarm_engine/objects/timer" require_relative "cyberarm_engine/objects/multi_line_text" require_relative "cyberarm_engine/ui/element" @@ -15,6 +16,7 @@ require_relative "cyberarm_engine/ui/label" require_relative "cyberarm_engine/ui/button" require_relative "cyberarm_engine/ui/check_box" require_relative "cyberarm_engine/ui/edit_line" +require_relative "cyberarm_engine/ui/image" require_relative "cyberarm_engine/ui/container" require_relative "cyberarm_engine/ui/flow" diff --git a/lib/cyberarm_engine/objects/timer.rb b/lib/cyberarm_engine/objects/timer.rb new file mode 100644 index 0000000..092dfc9 --- /dev/null +++ b/lib/cyberarm_engine/objects/timer.rb @@ -0,0 +1,23 @@ +module CyberarmEngine + class Timer + def initialize(interval, looping = true, &block) + @interval = interval + @looping = looping + @block = block + + @last_interval = Gosu.milliseconds + @triggered = false + end + + def update + return if !@looping && @triggered + + if Gosu.milliseconds >= @last_interval + @interval + @last_interval = Gosu.milliseconds + @triggered = true + + @block.call if @block + end + end + end +end \ No newline at end of file diff --git a/lib/cyberarm_engine/ui/button.rb b/lib/cyberarm_engine/ui/button.rb index 4d4eb8d..5f9058e 100644 --- a/lib/cyberarm_engine/ui/button.rb +++ b/lib/cyberarm_engine/ui/button.rb @@ -3,7 +3,7 @@ module CyberarmEngine def draw @text.draw - $window.draw_rect(relative_x, relative_y, width, height, @options[:background], @z+1) + $window.draw_rect(relative_x, relative_y, width, height, @options[:element_background], @z+1) if mouse_over? && $window.button_down?(Gosu::MsLeft) $window.draw_rect( diff --git a/lib/cyberarm_engine/ui/container.rb b/lib/cyberarm_engine/ui/container.rb index ee5c03d..1b06816 100644 --- a/lib/cyberarm_engine/ui/container.rb +++ b/lib/cyberarm_engine/ui/container.rb @@ -5,8 +5,11 @@ module CyberarmEngine attr_accessor :stroke_color, :fill_color, :background_color, :x, :y, :z, :width, :height attr_reader :elements, :children, :options attr_reader :scroll_x, :scroll_y, :internal_width, :internal_height + attr_reader :origin_x, :origin_y, :origin_width, :origin_height def initialize(options = {}, block = nil) + @parent = options[:parent] || nil + options = { x: 0, y: 0, z: 0, width: 0, height: 0 @@ -27,15 +30,16 @@ module CyberarmEngine raise "#{self.class} 'options' must be a Hash" unless options.is_a?(Hash) @x, @y, @z, @width, @height, @internal_width, @internal_height = x, y, z, width-x, height-y, width-x, height-y + @origin_x, @origin_x = @x, @x + @origin_width, @origin_height = @width, @height @scroll_x, @scroll_y = 0, 0 @scroll_speed = 10 @block = block @options = options - @parent = options[:parent] || nil - @text_color = options[:text_color] || Gosu::Color::WHITE - @background_color = Gosu::Color::NONE + @text_color = options[:text_color] || Element::THEME[:stroke] + @background_color = Element::THEME[:background] @elements = [] @children = [] @@ -65,11 +69,10 @@ module CyberarmEngine end def draw - Gosu.clip_to(@x, @y, @width, @height) do - raise "width and height are 0!" if @width == 0 && @height == 0 && Gosu.milliseconds > 1500 && @elements.size > 0 + Gosu.clip_to(@x, @y, @width + @spacing_x, @height + @spacing_y) do background - Gosu.translate(scroll_x, scroll_y) do + Gosu.translate(@scroll_x, @scroll_y) do @elements.each(&:draw) end end @@ -80,18 +83,18 @@ module CyberarmEngine end def button_up(id) - if $window.mouse_x.between?(@x, @x+@width) - if $window.mouse_y.between?(@y, @y+@height) + if $window.mouse_x.between?(@x, @x + @width) + if $window.mouse_y.between?(@y, @y + @height) case id when Gosu::MsWheelUp - @scroll_y+=@scroll_speed - @scroll_y = 0 if @scroll_y > 0 + @scroll_y += @scroll_speed + @scroll_y = 0 if @scroll_y > 0 when Gosu::MsWheelDown - @scroll_y-=@scroll_speed - if $window.height-@internal_height-y > 0 + @scroll_y -= @scroll_speed + if $window.height - @internal_height - @y > 0 @scroll_y = 0 else - @scroll_y = @height-@internal_height if @scroll_y <= @height-@internal_height + @scroll_y = @height - @internal_height if @scroll_y <= @height - @internal_height end end end @@ -113,7 +116,7 @@ module CyberarmEngine end def background - Gosu.draw_rect(@x, @y, @width, @height, @background_color, @z) + Gosu.draw_rect(@x, @y, @width + @spacing_x, @height + @spacing_y, @background_color, @z) end def recalculate @@ -123,8 +126,13 @@ module CyberarmEngine @packing_x = 0 @packing_y = 0 - @width = 0 - @height= 0 + @spacing_x = 0 + @spacing_y = 0 + + @spacer = 1 + + @width = @origin_width + @height= @origin_height @elements.each do |element| flow(element) if @mode == :flow @@ -132,29 +140,39 @@ module CyberarmEngine case @mode when :flow - @width += element.width - @height = element.height if element.height > @height + @width += element.width unless @origin_width.nonzero? + @height = element.height if element.height > @height unless @origin_height.nonzero? when :stack - @height += element.height - @width = element.width if element.width > @width + @width = element.width if element.width > @width unless @origin_width.nonzero? + @height += element.height unless @origin_height.nonzero? end end end def flow(element) element.x = @packing_x - element.y = 0 + if element.is_a?(Container) + element.y = @y + else + element.y = 0 + end element.recalculate - @packing_x += element.width + 1 + @packing_x += element.width + @spacer + @spacing_x += @spacer end def stack(element) - element.x = 0 + if element.is_a?(Container) + element.x = @x + else + element.x = 0 + end element.y = @packing_y element.recalculate - @packing_y += element.height + 1 + @packing_y += element.height + @spacer + @spacing_y += @spacer end end end \ No newline at end of file diff --git a/lib/cyberarm_engine/ui/dsl.rb b/lib/cyberarm_engine/ui/dsl.rb index a018536..0e32b8d 100644 --- a/lib/cyberarm_engine/ui/dsl.rb +++ b/lib/cyberarm_engine/ui/dsl.rb @@ -1,8 +1,8 @@ module CyberarmEngine module DSL def flow(options = {}, &block) - puts "Flow" options[:parent] = @containers.last + puts "Flow" _container = Flow.new(options, block) @containers << _container _container.build @@ -13,8 +13,8 @@ module CyberarmEngine end def stack(options = {}, &block) - puts "Stack" options[:parent] = @containers.last + puts "Stack" _container = Stack.new(options, block) @containers << _container _container.build @@ -56,6 +56,14 @@ module CyberarmEngine return _element end + def image(path, options = {}, &block) + options[:parent] = @containers.last + _element = Image.new(path, options, block) + @containers.last.add(_element) + + return _element + end + def background(color = Gosu::Color::NONE) @containers.last.background_color = color end diff --git a/lib/cyberarm_engine/ui/edit_line.rb b/lib/cyberarm_engine/ui/edit_line.rb index a2fd910..755aae1 100644 --- a/lib/cyberarm_engine/ui/edit_line.rb +++ b/lib/cyberarm_engine/ui/edit_line.rb @@ -1,107 +1,80 @@ module CyberarmEngine - class EditLine < Element - WIDTH = 200 - FOCUS_BACKGROUND_COLOR = Gosu::Color.rgb(150,150,144) - NO_FOCUS_BACKGROUND_COLOR = Gosu::Color.rgb(130,130,130) + class EditLine < Button + def initialize(text, options = {}, block = nil) + super(text, options, block) - attr_accessor :text, :x, :y, :width, :size, :color, :type, :focus - attr_reader :text_object, :text_input, :height + @type = @options[:type] || :plain - def initialize(text, options = {}) - @text = text - @x, @y= x, y - @width= width - @size = size - @color= color - @tooltip=tooltip - @type = type - @focus = false + @caret_width = @options[:caret_width] + @caret_height= @text.height + @caret_color = @options[:caret_color] + @caret_interval = @options[:caret_interval] + @caret_last_interval = Gosu.milliseconds + @show_caret = true - @text_object = Text.new(text, x: x, y: y, size: size, color: color, shadow: true) - @height = @text_object.height - @text_input = Gosu::TextInput.new - @text_input.text = @text - - @background_color = NO_FOCUS_BACKGROUND_COLOR - - @carot_ticks = 0 - @carot_width = 2.5 - @carot_height= @text_object.height - @carot_color = Gosu::Color.rgb(50,50,25) - @carot_show_ticks = 25 - @show_carot = true + @text_input = Gosu::TextInput.new + @text_input.text = text return self end - def text=(string) - @text = string - @text_input.text, @text_object.text = @text, @text - end - def draw - $window.draw_rect(x, y, width, height, Gosu::Color::BLACK) - $window.draw_rect(x+1, y+1, width-2, height-2, @background_color) - Gosu.clip_to(x, @text_object.y, width, @text_object.height) do - @text_object.draw + Gosu.clip_to(relative_x, relative_y, width, height) do + super - # Carot (Cursor) - $window.draw_rect((@x+@text_object.width)-@x_offset, @text_object.y, @carot_width, @carot_height, @carot_color) if @show_carot && @focus + Gosu.draw_rect(caret_position, @text.y, @caret_width, @caret_height, @caret_color, @z + 40) if @show_caret end - end def update - @text_object.y = @y+BUTTON_PADDING - - if (@text_object.width+@carot_width)-@width >= 0 - @x_offset = (@text_object.width+@carot_width)-@width + if @type == :password + @text.text = @options[:edit_line_password_character] * @text_input.text.length else - @x_offset = 0 + @text.text = @text_input.text end - @text = @text_object.text - @carot_ticks+=1 - if @carot_ticks >= @carot_show_ticks - if @show_carot - @show_carot = false - else - @show_carot = true + if Gosu.milliseconds >= @caret_last_interval + @caret_interval + @caret_last_interval = Gosu.milliseconds + + @show_caret = !@show_caret + end + end + + def button_up(id) + case id + when Gosu::MsLeft + if mouse_over? + @focus = !@focus + + if @focus + $window.text_input = @text_input + else + $window.text_input = nil + end + @block.call(self) if @block end - - @carot_ticks = 0 end + end - if @focus - @text_object.text = @text_input.text - $window.text_input = @text_input unless $window.text_input == @text_input - end - - if mouse_over? && $window.button_down?(Gosu::MsLeft) - @focus = true - @background_color = FOCUS_BACKGROUND_COLOR - end - if !mouse_over? && $window.button_down?(Gosu::MsLeft) - @focus = false - $window.text_input = nil - @background_color = NO_FOCUS_BACKGROUND_COLOR - end - - if @text_object.width >= @width - @text_object.x = self.fixed_x-@x_offset + def caret_position + if $window.text_input && $window.text_input == @text_input + if @type == :password + @text.x + @text.textobject.text_width(@options[:edit_line_password_character] * @text_input.text[0..@text_input.caret_pos].length) + else + @text.x + @text.textobject.text_width(@text_input.text[0..@text_input.caret_pos]) + end else - @text_object.x = self.fixed_x + 0 end end - def width(text_object = @text_object) - # text_object.textobject.text_width(text_object.text)+BUTTON_PADDING*2 - @width + def width + @options[:edit_line_width] end - def height(text_object = @text_object) - text_object.textobject.height+BUTTON_PADDING*2 + def value + @text_input.text end end end \ No newline at end of file diff --git a/lib/cyberarm_engine/ui/element.rb b/lib/cyberarm_engine/ui/element.rb index d9f3b06..e22e066 100644 --- a/lib/cyberarm_engine/ui/element.rb +++ b/lib/cyberarm_engine/ui/element.rb @@ -12,12 +12,14 @@ module CyberarmEngine THEME = { stroke: Gosu::Color::WHITE, fill: Gosu::Color::NONE, - background: Gosu::Color.rgb(12,12,12), - checkmark: "X", # ✓ + background: Gosu::Color::NONE, + checkmark: "√", # √ padding: 20, margin: 0, + element_background: Gosu::Color.rgb(12,12,12), + interactive_stroke: Gosu::Color::WHITE, interactive_active_stroke: Gosu::Color::GRAY, @@ -26,12 +28,20 @@ module CyberarmEngine interactive_active_background: Gosu::Color.rgb(50, 50, 50), interactive_border_size: 1, + edit_line_width: 200, + edit_line_password_character: "•", # • + caret_width: 2, + caret_color: Gosu::Color.rgb(50,50,25), + caret_interval: 500, + + image_retro: false, + text_size: 22, text_shadow: true, font: "Consolas" } - attr_accessor :x, :y, :z, :width, :height, :padding, :margin + attr_accessor :x, :y, :z, :width, :height, :padding, :margin, :focus def initialize(options = {}, block = nil) @parent = options[:parent] # parent Container (i.e. flow/stack) @@ -48,6 +58,8 @@ module CyberarmEngine @padding = options[:padding] @margin = options[:margin] + + @focus = false end def draw diff --git a/lib/cyberarm_engine/ui/image.rb b/lib/cyberarm_engine/ui/image.rb new file mode 100644 index 0000000..2b923a9 --- /dev/null +++ b/lib/cyberarm_engine/ui/image.rb @@ -0,0 +1,35 @@ +module CyberarmEngine + class Image < Element + def initialize(path, options = {}, block = nil) + super(options, block) + + @image = Gosu::Image.new(path, retro: @options[:image_retro]) + if @options[:width].nonzero? && @options[:height].nonzero? + @scale_x = @options[:width].to_f / @image.width + @scale_y = @options[:height].to_f / @image.height + elsif @options[:width].nonzero? + @scale_x = @options[:width].to_f / @image.width + @scale_y = @scale_x + elsif @options[:height].nonzero? + @scale_y = @options[:height].to_f / @image.height + @scale_x = @scale_y + else + @scale_x, @scale_y = 1, 1 + end + + raise "Scale X" unless @scale_x.is_a?(Numeric) + raise "Scale Y" unless @scale_y.is_a?(Numeric) + end + + def draw + $window.draw_rect(relative_x, relative_y, width, height, @options[:fill], @z+1) + + @image.draw(relative_x + @padding, relative_y + @padding, @z + 2, @scale_x, @scale_y) # TODO: Add color support? + end + + def recalculate + @width = @image.width * @scale_x + @height = @image.height * @scale_y + end + end +end \ No newline at end of file