Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Blit a 9 sliced source bitmap atlas to a target width and height
# Add to a Sprite object, or derivative
# Assumes self.bitmap has been set to the desired target width and height
def blt_9slice(args={})
args = {
src_bitmap: nil,
:frame_width => { # Can also be a number to be used for all corners
:top_left => 5,
:top_right => :top_left,
:mid_left => :top_left,
:mid_right => :top_left,
:btm_left => :top_left,
:btm_right => :top_left
},
:frame_height => { # Can also be a number to be used for all corners
:top_left => 5,
:top_right => :top_left,
:mid_top => :top_left,
:mid_btm => :top_left,
:btm_left => :top_left,
:btm_right => :top_left
}
}.merge(args)
# Set src_bitmap for convenience
src_bitmap = args[:src_bitmap]
# Set width and height params for each frame / corner
tl_f_width = tl_f_height = tr_f_width = tr_f_height = ml_f_width = mr_f_width = mt_f_height = mb_f_height = bl_f_width = bl_f_height = br_f_width = br_f_height = 0
# Go through hash params and find values or set defaults
[:top_left, :top_right, :mid_left, :mid_right, :mid_top, :mid_btm, :btm_left, :btm_right].each do |frame|
if args[:frame_width].is_a? Numeric
width = args[:frame_width]
else
width = args[:frame_width][frame]
# Reference other arg value if symbols
width = args[:frame_width][width] if width.is_a? Symbol
# If no value, set default to top left
width = args[:frame_width][:top_left] unless width
end
if args[:frame_height].is_a? Numeric
height = args[:frame_height]
else
height = args[:frame_height][frame]
# Reference other arg value if symbols
height = args[:frame_height][height] if height.is_a? Symbol
# If no value, set default to top left
height = args[:frame_height][:top_left] unless height
end
case frame
when :top_left
tl_f_width = width
tl_f_height = height
when :top_right
tr_f_width = width
tr_f_height = height
when :mid_left
ml_f_width = width
when :mid_right
mr_f_width = width
when :mid_top
mt_f_height = height
when :mid_btm
mb_f_height = height
when :btm_left
bl_f_width = width
bl_f_height = height
when :btm_right
br_f_width = width
br_f_height = height
end
end
# Rects for copying sections of src_bitmap
# Top
tl_frame = Rect.new(0, 0, tl_f_width, tl_f_height)
t_frame = Rect.new(tl_f_width, 0, src_bitmap.width - (tl_f_width + tr_f_width), mt_f_height)
tr_frame = Rect.new(src_bitmap.width - tr_f_width, 0, tr_f_width, tr_f_height)
# Middle
ml_frame = Rect.new(0, tl_f_height, ml_f_width, src_bitmap.height - (tl_f_height + bl_f_height))
m_bg = Rect.new(ml_frame.width, ml_frame.y, src_bitmap.width - (ml_f_width + mr_f_width), ml_frame.height)
mr_frame = Rect.new(src_bitmap.width - mr_f_width, tr_f_height, mr_f_width, ml_frame.height)
# Bottom
bl_frame = Rect.new(0, src_bitmap.height - bl_f_height, bl_f_width, bl_f_height)
b_frame = Rect.new(bl_f_width, src_bitmap.height - mb_f_height, src_bitmap.width - (bl_f_width + br_f_width), mb_f_height)
br_frame = Rect.new(src_bitmap.width - br_f_width, src_bitmap.height - br_f_height, br_f_width, br_f_height)
# Diffs
width_diff = (self.width.to_f / m_bg.width).ceil
height_diff = (self.height.to_f / m_bg.height).ceil
# First blt fill
fill_width = self.width - (ml_f_width + mr_f_width)
fill_height = self.height - (mt_f_height + mb_f_height)
m_bg_width = m_bg.width
m_bg_height = m_bg.height
width_diff.times do |hn|
total_width = m_bg.width * (hn+1)
m_bg.width -= total_width - fill_width if total_width > fill_width
m_bg.height = m_bg_height # Reset on horizontal pass
height_diff.times do |vn|
total_height = m_bg.height * (vn+1)
m_bg.height -= total_height - fill_height if total_height > fill_height
self.bitmap.blt(tl_f_width + (m_bg_width * hn), tl_f_height + (m_bg_height * vn), src_bitmap, m_bg)
end
end
# Top left frame
self.bitmap.blt(0, 0, src_bitmap, tl_frame)
# Top frame
mid_width = self.width - (tl_f_width + tr_f_width)
t_frame_width = t_frame.width
width_diff.times do |n|
total_width = t_frame.width * (n+1)
t_frame.width -= total_width - mid_width if total_width > mid_width
self.bitmap.blt(tl_f_width + (t_frame_width * n), 0, src_bitmap, t_frame)
end
# Top right frame
self.bitmap.blt(self.width - tr_frame.width, tr_frame.y, src_bitmap, tr_frame)
# Mid left frame
mid_height = self.height - (tl_f_height + bl_f_height)
ml_frame_height = ml_frame.height
height_diff.times do |n|
total_height = ml_frame.height * (n+1)
ml_frame.height -= total_height - mid_height if total_height > mid_height
self.bitmap.blt(0, tl_f_height + (ml_frame_height * n), src_bitmap, ml_frame)
end
# Mid right frame
mid_height = self.height - (tr_f_height + br_f_height)
mr_frame_height = mr_frame.height
height_diff.times do |n|
total_height = mr_frame.height * (n+1)
mr_frame.height -= total_height - fill_height if total_height > fill_height
self.bitmap.blt(self.width - mr_frame.width, tr_f_height + (mr_frame_height * n), src_bitmap, mr_frame)
end
# Bottom left frame
self.bitmap.blt(0, self.height - bl_f_height, src_bitmap, bl_frame)
# Bottom frame
mid_width = self.width - (bl_f_width + br_f_width)
b_frame_width = b_frame.width
width_diff.times do |n|
total_width = b_frame.width * (n+1)
b_frame.width -= total_width - mid_width if total_width > mid_width
self.bitmap.blt(bl_f_width + (b_frame_width * n), self.height - b_frame.height, src_bitmap, b_frame)
end
# Bottom right frame
self.bitmap.blt(self.width - br_frame.width, self.height - br_frame.height, src_bitmap, br_frame)
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.