Added support for 9 sliced backgrounds in UI, fixed events not propagating to subscribers if element threw :handled in its own event handler

This commit is contained in:
2021-06-04 03:00:31 +00:00
parent bd54fafc3f
commit cdee6548e3
4 changed files with 92 additions and 29 deletions

View File

@@ -23,6 +23,7 @@ require_relative "cyberarm_engine/vector"
require_relative "cyberarm_engine/transform"
require_relative "cyberarm_engine/ray"
require_relative "cyberarm_engine/background"
require_relative "cyberarm_engine/background_nine_slice"
require_relative "cyberarm_engine/animator"
require_relative "cyberarm_engine/text"

View File

@@ -1,10 +1,11 @@
module CyberarmEngine
class BackgroundNineSlice
include CyberarmEngine::Common
attr_accessor :x, :y, :z, :width, :height
attr_accessor :x, :y, :z, :width, :height, :left, :top, :right, :bottom, :mode, :color
attr_reader :image
def initialize(image_path:, x: 0, y: 0, z: 0, width: 64, height: 64, mode: :tiled, left: 4, top: 4, right: 56, bottom: 56)
@image = get_image(image_path)
def initialize(image_path: nil, x: 0, y: 0, z: 0, width: 0, height: 0, mode: :tiled, left: 1, top: 1, right: 1, bottom: 1, color: Gosu::Color::WHITE)
@image = get_image(image_path) if image_path
@x = x
@y = y
@@ -20,10 +21,20 @@ module CyberarmEngine
@right = right
@bottom = bottom
nine_slice
@color = color
nine_slice if @image
end
def image=(image_path)
old_image = @image
@image = image_path ? get_image(image_path) : image_path
nine_slice if @image && old_image != @image
end
def nine_slice
# pp [@left, @top, @right, @bottom, @image.width]
@segment_top_left = @image.subimage(0, 0, @left, @top)
@segment_top_right = @image.subimage(@image.width - @right, 0, @right, @top)
@@ -56,71 +67,73 @@ module CyberarmEngine
end
def width_scale
scale = (@width - (@image.width - (@left + @right))).to_f / (@image.width - (@left + @right))
scale = (@width.to_f - (@left + @right)) / (@image.width - (@left + @right))
scale.abs
end
def height_scale
scale = (@height - (@image.height - (@top + @bottom))).to_f / (@image.height - (@top + @bottom))
scale = (@height - (@top + @bottom)).to_f / (@image.height - (@top + @bottom))
scale.abs
end
def draw
return unless @image && @segment_top_left
@mode == :tiled ? draw_tiled : draw_stretched
end
def draw_stretched
@segment_top_left.draw(@x, @y, @z)
@segment_top.draw(@x + @segment_top_left.width, @y, @z, width_scale) # SCALE X
@segment_top_right.draw((@x + @width) - @segment_top_right.width, @y, @z)
@segment_top_left.draw(@x, @y, @z, 1, 1, @color)
@segment_top.draw(@x + @segment_top_left.width, @y, @z, width_scale, 1, @color) # SCALE X
@segment_top_right.draw((@x + @width) - @segment_top_right.width, @y, @z, 1, 1, @color)
@segment_right.draw((@x + @width) - @segment_right.width, @y + @top, @z, 1, height_scale) # SCALE Y
@segment_bottom_right.draw((@x + @width) - @segment_bottom_right.width, @y + @height - @segment_bottom_right.height, @z)
@segment_bottom.draw(@x + @segment_bottom_left.width, (@y + @height) - @segment_bottom.height, @z, width_scale) # SCALE X
@segment_bottom_left.draw(@x, (@y + @height) - @segment_bottom_left.height, @z)
@segment_left.draw(@x, @y + @top, @z, 1, height_scale) # SCALE Y
@segment_middle.draw(@x + @segment_top_left.width, @y + @segment_top.height, @z, width_scale, height_scale) # SCALE X and SCALE Y
@segment_right.draw((@x + @width) - @segment_right.width, @y + @top, @z, 1, height_scale, @color) # SCALE Y
@segment_bottom_right.draw((@x + @width) - @segment_bottom_right.width, @y + @height - @segment_bottom_right.height, @z, 1, 1, @color)
@segment_bottom.draw(@x + @segment_bottom_left.width, (@y + @height) - @segment_bottom.height, @z, width_scale, 1, @color) # SCALE X
@segment_bottom_left.draw(@x, (@y + @height) - @segment_bottom_left.height, @z, 1, 1, @color)
@segment_left.draw(@x, @y + @top, @z, 1, height_scale, @color) # SCALE Y
@segment_middle.draw(@x + @segment_top_left.width, @y + @segment_top.height, @z, width_scale, height_scale, @color) # SCALE X and SCALE Y
end
def draw_tiled
@segment_top_left.draw(@x, @y, @z)
@segment_top_left.draw(@x, @y, @z, 1, 1, @color)
p [width_scale, height_scale]
# p [width_scale, height_scale]
Gosu.clip_to(@x + @segment_top_left.width, @y, @segment_top.width * width_scale, @segment_top.height) do
width_scale.ceil.times do |i|
@segment_top.draw(@x + @segment_top_left.width + (@segment_top.width * i), @y, @z) # SCALE X
@segment_top.draw(@x + @segment_top_left.width + (@segment_top.width * i), @y, @z, 1, 1, @color) # SCALE X
end
end
@segment_top_right.draw((@x + @width) - @segment_top_right.width, @y, @z)
@segment_top_right.draw((@x + @width) - @segment_top_right.width, @y, @z, 1, 1, @color)
Gosu.clip_to(@x + @width - @segment_top_right.width, @y + @top, @segment_right.width, @segment_right.height * height_scale) do
height_scale.ceil.times do |i|
@segment_right.draw((@x + @width) - @segment_right.width, @y + @top + (@segment_right.height * i), @z) # SCALE Y
@segment_right.draw((@x + @width) - @segment_right.width, @y + @top + (@segment_right.height * i), @z, 1, 1, @color) # SCALE Y
end
end
@segment_bottom_right.draw((@x + @width) - @segment_bottom_right.width, @y + @height - @segment_bottom_right.height, @z)
@segment_bottom_right.draw((@x + @width) - @segment_bottom_right.width, @y + @height - @segment_bottom_right.height, @z, 1, 1, @color)
Gosu.clip_to(@x + @segment_top_left.width, @y + @height - @segment_bottom.height, @segment_top.width * width_scale, @segment_bottom.height) do
width_scale.ceil.times do |i|
@segment_bottom.draw(@x + @segment_bottom_left.width + (@segment_bottom.width * i), (@y + @height) - @segment_bottom.height, @z) # SCALE X
@segment_bottom.draw(@x + @segment_bottom_left.width + (@segment_bottom.width * i), (@y + @height) - @segment_bottom.height, @z, 1, 1, @color) # SCALE X
end
end
@segment_bottom_left.draw(@x, (@y + @height) - @segment_bottom_left.height, @z)
@segment_bottom_left.draw(@x, (@y + @height) - @segment_bottom_left.height, @z, 1, 1, @color)
Gosu.clip_to(@x, @y + @top, @segment_left.width, @segment_left.height * height_scale) do
height_scale.ceil.times do |i|
@segment_left.draw(@x, @y + @top + (@segment_left.height * i), @z) # SCALE Y
@segment_left.draw(@x, @y + @top + (@segment_left.height * i), @z, 1, 1, @color) # SCALE Y
end
end
Gosu.clip_to(@x + @segment_top_left.width, @y + @segment_top.height, @width - (@segment_left.width + @segment_right.width), @height - (@segment_top.height + @segment_bottom.height)) do
height_scale.ceil.times do |y|
width_scale.ceil.times do |x|
@segment_middle.draw(@x + @segment_top_left.width + (@segment_middle.width * x), @y + @segment_top.height + (@segment_middle.height * y), @z) # SCALE X and SCALE Y
@segment_middle.draw(@x + @segment_top_left.width + (@segment_middle.width * x), @y + @segment_top.height + (@segment_middle.height * y), @z, 1, 1, @color) # SCALE X and SCALE Y
end
end
end

View File

@@ -36,7 +36,8 @@ module CyberarmEngine
@style.height = default(:height) || nil
@style.background_canvas = Background.new
@style.border_canvas = BorderCanvas.new(element: self)
@style.background_nine_slice_canvas = BackgroundNineSlice.new
@style.border_canvas = BorderCanvas.new(element: self)
@style_event = :default
@@ -54,6 +55,7 @@ module CyberarmEngine
set_margin
set_background
set_background_nine_slice
set_border_thickness
set_border_color
@@ -74,6 +76,21 @@ module CyberarmEngine
@style.background_canvas.background = @style.background
end
def set_background_nine_slice
@style.background_nine_slice = safe_style_fetch(:background_nine_slice)
@style.background_nine_slice_mode = safe_style_fetch(:background_nine_slice_mode) || :stretch
@style.background_nine_slice_color = safe_style_fetch(:background_nine_slice_color) || Gosu::Color::WHITE
@style.background_nine_slice_canvas.color = @style.background_nine_slice_color
@style.background_nine_slice_from_edge = safe_style_fetch(:background_nine_slice_from_edge)
@style.background_nine_slice_left = safe_style_fetch(:background_nine_slice_left) || @style.background_nine_slice_from_edge
@style.background_nine_slice_top = safe_style_fetch(:background_nine_slice_top) || @style.background_nine_slice_from_edge
@style.background_nine_slice_right = safe_style_fetch(:background_nine_slice_right) || @style.background_nine_slice_from_edge
@style.background_nine_slice_bottom = safe_style_fetch(:background_nine_slice_bottom) || @style.background_nine_slice_from_edge
end
def set_border_thickness
@style.border_thickness = safe_style_fetch(:border_thickness)
@@ -250,6 +267,7 @@ module CyberarmEngine
return unless visible?
@style.background_canvas.draw
@style.background_nine_slice_canvas.draw
@style.border_canvas.draw
Gosu.clip_to(@x, @y, width, height) do
@@ -390,10 +408,34 @@ module CyberarmEngine
@style.background_canvas.height = height
@style.background_canvas.update
update_background_nine_slice
@style.border_canvas.update
end
def background_nine_slice=(_image_path)
@style.background_nine_slice_canvas.image = _image_path
update_background_nine_slice
end
def update_background_nine_slice
@style.background_nine_slice_canvas.x = @x
@style.background_nine_slice_canvas.y = @y
@style.background_nine_slice_canvas.z = @z
@style.background_nine_slice_canvas.width = width
@style.background_nine_slice_canvas.height = height
@style.background_nine_slice_canvas.mode = @style.background_nine_slice_mode
@style.background_nine_slice_canvas.color = @style.background_nine_slice_color
@style.background_nine_slice_canvas.left = @style.background_nine_slice_left
@style.background_nine_slice_canvas.top = @style.background_nine_slice_top
@style.background_nine_slice_canvas.right = @style.background_nine_slice_right
@style.background_nine_slice_canvas.bottom = @style.background_nine_slice_bottom
@style.background_nine_slice_canvas.image = @style.background_nine_slice
end
def root
return self if is_root?

View File

@@ -15,12 +15,19 @@ module CyberarmEngine
return unless enabled?
return :handled if respond_to?(event) && (send(event, self, *args) == :handled)
was_handled = false
was_handled = true if respond_to?(event) && (send(event, self, *args) == :handled)
@event_handler[event].reverse_each do |handler|
return :handled if handler.call(self, *args) == :handled
if handler.call(self, *args) == :handled
was_handled = true
break
end
end
return :handled if was_handled
parent.publish(event, *args) if parent
nil
end