#==============================================================================
# ** RGSS.Bitmap.draw
#------------------------------------------------------------------------------
# Description:
# ------------
# Methods created for the Bitmap class that handle general drawing functions.
# Functions include drawing parts of bitmaps and drawing stretched bitmaps.
#
# Method List:
# ------------
# Bitmap.default_blur_settings=
# Bitmap.default_blur_settings
# Bitmap.default_anim_sprite_settings=
# Bitmap.default_anim_sprite_settings
# blur_settings=
# blur_settings
# anim_sprite_settings=
# anim_sprite_settings
# draw_char_bar
# draw_line
# draw_box
# draw_circle
# draw_ellipse
# draw_polygon
# draw_gradient_polygon
# draw_anim_sprite
# draw_sprite
# draw_equipment
# crop_blt
# fit_blt
# full_blt
# full_fill
# scale_blt
# shade_section
# shade_gradient_section
#
# Modified Methods:
# -----------------
# initialize
#==============================================================================
MACL::Loaded << 'RGSS.Bitmap.draw'
#==============================================================================
# ** Bitmap
#==============================================================================
class Bitmap
#--------------------------------------------------------------------------
# * Class Variable Declaration
#--------------------------------------------------------------------------
class_accessor :default_blur_settings
class_accessor :default_anim_sprite_settings
#--------------------------------------------------------------------------
# * Class Variable Declaration
#--------------------------------------------------------------------------
Bitmap.default_blur_settings = Blur_Settings
Bitmap.default_anim_sprite_settings = Anim_Sprite_Settings
#--------------------------------------------------------------------------
# * Public Instance Variables
#--------------------------------------------------------------------------
attr_accessor :blur_settings
attr_accessor :anim_sprite_settings
#--------------------------------------------------------------------------
# * Alias Method
#--------------------------------------------------------------------------
alias_method :macl_bitmapdraw_init, :initialize
#--------------------------------------------------------------------------
# * Object Initialization
#--------------------------------------------------------------------------
def initialize(*args)
# Set draw settings
@blur_settings = Bitmap.default_blur_settings
@anim_sprite_settings = Bitmap.default_anim_sprite_settings
# Original Initialization
macl_bitmapdraw_init(*args)
end
#-------------------------------------------------------------------------
# * Name : Draw Char Bar
# Info : Draws a Character Bar
# Author : Trickster
# Call Info : Integer X, Y - Defines Position
# Integer Min, Max - Defines How filled the bar is
# Integer Width and height - Defines Dimensions
# String Start Content and Finish
#-------------------------------------------------------------------------
def draw_char_bar(x, y, min = 1, max = 1, width = nil, height = 32, start = '[',
content = '¦', finish = ']', color = Color.new(255, 255, 255))
# Get Width if width is nil
width = text_size(start + (content * max) + finish).width if width == nil
# save color
saved = font.color
# Set color
self.font.color = color
# Get Bar Text
bar_text = start + content * min.to_i
# Draw Bar Text
draw_text(x, y, width, height, bar_text)
# Draw Finish
draw_text(x, y, width, height, finish, 2)
# Restore Color
self.font.color = saved
end
#-------------------------------------------------------------------------
# * Name : Draw Line
# Info : Draws a line from x1,y1 to x2,y2
# Author : Caesar (Rewrote By Trickster)
# Call Info : Integer x1, y1, x2, y2 - Points of the line
# Integer width - Thickness of the line
# Color color - Color of the line
# Comments : uses the Digital Differential Analyzer Algorithm
#-------------------------------------------------------------------------
def draw_line(x1, y1, x2, y2, width = 1, color = Color.new(255, 255, 255))
# Return if width is less than or 0
return if width <= 0
# Reverse all parameters sent if 2 x is less than the first x
x1, x2, y1, y2 = x2, x1, y2, y1 if x2 < x1
# Get S (1/2 width)
s = width / 2.0
# If X Coordinates are equal
if x1 == x2
# Draw Vertical line
fill_rect(x1 - s, [y1, y2].min, width, (y2 - y1).abs, color)
# If Y Coordinates are equal
elsif y1 == y2
# Draw Horizontal line
fill_rect(x1, y1 - s, x2 - x1, width, color)
end
# Get Length
length = x2 - x1 < (y2 - y1).abs ? (y2 - y1).abs : x2 - x1
# Get Increments
x_increment, y_increment = (x2 - x1) / length.to_f, (y2 - y1) / length.to_f
# Get Current X and Y
x, y = x1, y1
# While Current X is less than end X
while x < x2
# Draw Box of width width and width height
fill_rect(x-s, y-s, width, width, color)
# Increment X and Y
x += x_increment
y += y_increment
end
end
#-------------------------------------------------------------------------
# * Name : Draw Box
# Info : Draws a Box
# Author : Trickster
# Call Info : Two to Four Arguments Rect Outer Rectangle to Draw Box
# Color color color to draw the box in
#-------------------------------------------------------------------------
def draw_box(outer, color, width = 1, height = 1)
fill_rect(outer, color)
inner = Rect.new(outer.x + width, outer.y + height, outer.width - width * 2,
outer.height - height * 2)
fill_rect(inner, Color.new(0, 0, 0, 0))
end
#-------------------------------------------------------------------------
# * Name : Draw Circle
# Info : Draws A Circle
# Author : SephirothSpawn
# Call Info : Integer X and Y Define Position Center Pt of Circle
# Integer Radius Radius of the Circle to Draw
# Color color Color of the circle to draw
#-------------------------------------------------------------------------
def draw_circle(x, y, radius, color = Color.new(255, 255, 255, 255))
# Starts From Left
for i in (x - radius)..(x + radius)
# Finds Distance From Center
sa = (x - i).abs
# Finds X Position
x_ = i < x ? x - sa : i == x ? x : x + sa
# Finds Top Vertical Portion
y_ = Integer((radius ** 2 - sa ** 2) ** 0.5)
# Draws Vertical Bar
self.fill_rect(x_, y - y_, 1, y_ * 2, color)
end
end
#-------------------------------------------------------------------------
# * Name : Draw Ellipse
# Info : Draws a Ellispse
# Author : SephirothSpawn
# Call Info : Four or Five Arguments
# Four Arguments: x, y, a, b
# x the center position of circle
# y the center position of circle
# a the distance from center to right side
# b the distance from center to top side
# Five Arguments: (as above) + color
# color the color of the circle drawn (defaults to white)
#-------------------------------------------------------------------------
def draw_ellipse(x, y, a, b, color = Color.new(255, 255, 255))
# Converts Each Argument to Float
x, y, a, b = x.to_f, y.to_f, a.to_f, b.to_f
# Gets Square of a and b values
a2, b2 = a * a, b * b
# If a is smaller or equal to b
if a <= b
# Draws Center Line
self.fill_rect(x, y - b, 1, b * 2, color)
# Pass from center to right side
for i in 1..a
# Gets Y Distance
y_ = Integer(Math.sqrt(b2 * (1 - (i ** 2) / a2)))
# Draws Lines on Each Side
self.fill_rect(x - i, y - y_, 1, y_ * 2, color)
self.fill_rect(x + i, y - y_, 1, y_ * 2, color)
end
# If b is smaller than b
else
# Draws Center Line
self.fill_rect(x - a, y, a * 2, 1, color)
# Pass from center to right side
for i in 1..b
# Gets X Distance
x_ = Integer(Math.sqrt(a2 * (1 - i ** 2 / b2)))
# Draws Lines on Top & Bottom
self.fill_rect(x - x_, y - i, x_ * 2, 1, color)
self.fill_rect(x - x_, y + i, x_ * 2, 1, color)
end
end
end
#-------------------------------------------------------------------------
# * Name : Draw Polygon
# Info : Draws a Polygon
# Author : Caesar (Rewrote By Trickster)
# Call Info : Array vertices - Points of the polygon
# Integer width - Thickness of the lines
# Color color - color to draw it in
# Boolean filled - false outline true filled
# Integer step - fill steps
# Comments : Example of vertices setup [[30, 80], [80, 80], [30, 60]]
#-------------------------------------------------------------------------
def draw_polygon(vertices, stroke = 1, color = Color.new(255, 255, 255),
filled = false, step = 1)
# Return if no width or not enough points
return if stroke <= 0 or vertices.size <= 2
# Get Count
count = vertices.size
# Get Points
x1, y1, x2, y2 = vertices[-1] + vertices[0]
# Draw Line
draw_line(x1, y1, x2, y2, stroke, color)
# Shade if filled
shade_section(cx, cy, x1, y1, x2, y2, stroke, step, color) if filled
# Run Through with next
vertices.each_with_next do |start, point|
# Get Points
x1, y1, x2, y2 = start + point
# Draw Line
draw_line(x1, y1, x2, y2, stroke, color)
# Shade if filled
shade_section(cx, cy, x1, y1, x2, y2, stroke, step, color) if filled
end
end
#-------------------------------------------------------------------------
# * Name : Draw Gradient Polygon
# Info : Draws a Gradient Polygon (Filled)
# Author : Caesar (Rewrote By Trickster)
# Call Info : Array vertices - Points of the polygon
# Integer width - Thickness of the lines
# Color color - color to draw it in
# Boolean filled - false outline true filled
# Integer step - fill steps
# Comments : Example of vertices setup [[30, 80], [80, 80], [30, 60]]
#-------------------------------------------------------------------------
def draw_gradient_polygon(cx, cy, vertices, stroke = 1,
start_color = Color.new(255, 255, 255), end_color = Color.new(0, 0, 0),
step = 1)
# Return if no width or not enough points
return if stroke <= 0 or vertices.size <= 2
# Get Count
count = vertices.size
# Get Points
x1, y1, x2, y2 = vertices[-1] + vertices[0]
# Draw Line
draw_line(x1, y1, x2, y2, stroke, end_color)
shade_gradient_section(cx, cy, x1, y1, x2, y2, 2, 1, start_color, end_color)
# Run Through with next
vertices.each_with_next do |start, point|
# Get Points
x1, y1, x2, y2 = start + point
# Draw Line
draw_line(x1, y1, x2, y2, stroke, end_color)
shade_gradient_section(cx, cy, x1, y1, x2, y2, 1, 0.4, start_color, end_color)
end
end
#-------------------------------------------------------------------------
# * Name : Draw Animated Sprite
# Info : Draws an Animated Sprite
# Author : SephirothSpawn
# Call Info : Six to Seven Arguments Integer x and y Defines Position
# Integer W and H Defines Dimensions
# String name Character Set Graphic
# Integer hue sets hue displacement
# Integer stance pose for character
#-------------------------------------------------------------------------
def draw_anim_sprite(x, y, w, h, name, hue, stance = 0)
# Gets Frame
frame = (Graphics.frame_count / @anim_sprite_settings['f']) %
@anim_sprite_settings['w']
# Draw Sprite
draw_sprite(x, y, w, h, name, hue, stance, frame)
end
#-------------------------------------------------------------------------
# * Name : Draw Sprite
# Info : Draws an Animated Sprite
# Author : SephirothSpawn
# Call Info : Six to Seven Arguments Integer x and y Defines Position
# Integer W and H Defines Dimensions
# String name Character Set Graphic
# Integer hue sets hue displacement
# Integer stance pose for character
# Integer frame frame of pose to show
#-------------------------------------------------------------------------
def draw_sprite(x, y, w, h, name, hue, stance = 0, frame = 0)
# Gets Bitmap
bitmap = RPG::Cache.character(name, hue)
# Bitmap Division
cw = bitmap.width / @anim_sprite_settings['w']
ch = bitmap.height / @anim_sprite_settings['h']
# Gets Animation Offsets
x_off, y_off = cw * frame, ch * stance
# Clears Area
self.fill_rect(Rect.new(x, y, w, h), Color.new(0, 0, 0, 0))
# Draws Bitmap
self.scale_blt(Rect.new(x, y, w, h), bitmap,
Rect.new(x_off, y_off, cw, ch))
end
#-------------------------------------------------------------------------
# * Name : Draw Equip
# Info : Draws Item or Equipment icon and name
# Author : SephirothSpawn
# Call Info : Three to Eight Arguments
# Item - RPG::Item, RPG::Weapon or RPG::Armor
# X - Position Icon & Text Being drawn
# Y - Position Icon & Test Being drawn
# W - Width for Icon & Text to be drawn in
# H - Height for Icon & Text to be drawn in (24 min)
# A - Alignment of text
# T - Type of icon to be used when nil item (See MACL Setup)
# Txt - Text when Item is nil
#-------------------------------------------------------------------------
def draw_equipment(i, x, y, w = 212, h = 32, a = 0, t = 0, txt = 'Nothing')
# If Nil Item
if i.nil?
# Gets Unequipped Bitmap & Font Color
bitmap = RPG::Cache.icon(Draw_Equipment_Icon_Settings[t])
c = Color.disabled
# If Item Exist
else
# Gets Bitmap, Font Color & Item Name
bitmap = RPG::Cache.icon(i.icon_name)
c, txt = Color.normal, i.name
end
# Sets Font Color, Draws Icon & Text
old_color = self.font.color.dup
self.blt(x + 4, y + (h - 24) / 2, bitmap, bitmap.rect, c.alpha)
self.font.color = c
self.draw_text(x + 32, y, w - 28, h, txt, a)
self.font.color = old_color
end
#-------------------------------------------------------------------------
# * Name : Crop BLT
# Info : Crops to Width and Height, if needed
# Author : Trickster
# Call Info : Five - Eight Arguments, Integer X and Y Define Position
# Integer Width and Height Defines Dimensions
# Bitmap bitmap bitmap to transfer
# Integer dir, part to crop
# Integer align, alignment (0:left, 1:center, 2:right)
# Integer opacity, opacity
#-------------------------------------------------------------------------
def crop_blt(x, y, width, height, bitmap, dir = 1, align = 1, opacity = 255)
# Get Width and Height
w, h = bitmap.width, bitmap.height
# If Can Fit
if w < width and h < height
# Branch By alignment
case align
when 1
# Add To Make it in the center
x += (width - w) / 2
when 2
# Add to Make it in the right
x += width - w
end
# Draw Bitmap
full_blt(x, y, bitmap, opacity)
# Return
return
end
# Get I and J (Position)
i, j = dir % 3, dir / 3
# Initialize Crop X and Crop Y (Left Top Align)
crop_x, crop_y = 0, 0
# Branch by Horizontal Position
case i
when 1
# Center Align
crop_x = (w - width) / 2
when 2
# Right Align
crop_x = w - width
end
# Branch by Vertical Position
case j
when 1
# Center Align
crop_y = (h - height) / 2
when 2
# Bottom Align
crop_y = h - height
end
# Draw Bitmap Cropped
blt(x, y, bitmap, Rect.new(crop_x, crop_y, width, height), opacity)
end
#-------------------------------------------------------------------------
# * Name : Fit BLT
# Info : Zooms to Width and Height, if needed
# Author : Trickster
# Call Info : Five-Seven Arguments, Integer X and Y Define Position
# Integer Width and Height Defines Dimensions
# Bitmap bitmap bitmap to transfer
# Integer opacity, opacity
# Integer Align, Alignment
#-------------------------------------------------------------------------
def fit_blt(x, y, width, height, bitmap, opacity = 255, align = 1)
# Get Width and Height
w, h = bitmap.width, bitmap.height
# If Width or Height is Greater
if w > width or h > height
# Get Conversion
conversion = w / h.to_f
# if Conversion is smaller than or 1
if conversion <= 1
# Get Zoom X and Y
zoom_x, zoom_y = width * conversion, height
else
# Get Zoom X and Y
zoom_x, zoom_y = width, height / conversion
end
# Branch By Align
case align
when 1
# Add To Make it in the center
x += (width - zoom_x) / 2
when 2
# Add to Make it in the right
x += width - zoom_x
end
# Get Destination Rect
dest_rect = Rect.new(x, y, zoom_x, zoom_y)
# Stretch to Fit
stretch_blt(dest_rect, bitmap, bitmap.rect, opacity)
else
# Branch By alignment
case align
when 1
# Add To Make it in the center
x += (width - w) / 2
when 2
# Add to Make it in the right
x += width - w
end
# Draw Bitmap
full_blt(x, y, bitmap, opacity)
end
end
#-------------------------------------------------------------------------
# Name : Full Block Transfer
# Info : Draws a Bitmap
# Author : Trickster
# Call Info : Three or Four Arguments
# Integer X and Y define position
# Bitmap bitmap is the bitmap to draw
# Integer Opacity is the transparency (defaults to 255)
# Comment : Lazy method for people who don't want to type bitmap.rect
#-------------------------------------------------------------------------
def full_blt(x, y, bitmap, opacity = 255)
blt(x, y, bitmap, bitmap.rect, opacity)
end
#-------------------------------------------------------------------------
# Name : Full Fill
# Info : Fills Whole Bitmap
# Author : Trickster
# Call Info : One Argument, Color color the color to be filled
# Comment : Lazy method for people who don't want to type bitmap.rect
#-------------------------------------------------------------------------
def full_fill(color)
fill_rect(rect, color)
end
#-------------------------------------------------------------------------
# * Name : Scale BLT
# Info : Scales Bitmap to fit Rectangle
# Author : SephirothSpawn
# Call Info : Two to Four Arguments
# Rect Dest_Rect - Destination Rectangle
# Bitmap Src_Bitmap - Source Bitmap
# Rect Src_Rect - Source Rectangle for Bitmap
# Integer Opacity - Opacity
#-------------------------------------------------------------------------
def scale_blt(dest_rect, src_bitmap, src_rect = src_bitmap.rect, o = 255)
w, h = src_rect.width, src_rect.height
scale = [w / dest_rect.width.to_f, h / dest_rect.height.to_f].max
ow, oh = (w / scale).to_i, (h / scale).to_i
ox, oy = (dest_rect.width - ow) / 2, (dest_rect.height - oh) / 2
stretch_blt(Rect.new(ox + dest_rect.x, oy + dest_rect.y, ow, oh),
src_bitmap, src_rect, o)
end
#-------------------------------------------------------------------------
# * Name : Shade Section
# Info : Shades a section from (cx,cy), (x1,y1), (x2,y2)
# Author : Trickster
# Call Info : Six to Nine Arguments
# Integer cx, cy, x1, y1, x2, y2 - Points
# Integer Thick - Line Thickness
# Integer Step - how many lines to draw (lower = higher accuracy)
# Color color - color to shade in
#-------------------------------------------------------------------------
def shade_section(cx, cy, x1, y1, x2, y2, thick = 1, step = 1,
color = Color.new(255, 255, 255))
# Reverse all parameters sent if 2 x is less than the first x
x1, x2, y1, y2 = x2, x1, y2, y1 if x2 < x1
# Get Slope
slope = (y2 - y1).to_f / (x2 - x1)
# If Slope is infinite
if slope.infinite?
y1.step(y2, step) {|y| draw_line(cx, cy, x1, y, thick, color)}
# If Slope is zero
elsif slope.zero?
x1.step(x2, step) {|x| draw_line(cx, cy, x, y1, thick, color)}
elsif not slope.nan?
# Get Y intercept
yint = y1 - slope * x1
x1.step(x2, step) {|x| draw_line(cx, cy, x, slope * x + yint, thick, color)}
end
end
#-------------------------------------------------------------------------
# * Name : Shade Gradient Section
# Info : Shades a section from (cx,cy), (x1,y1), (x2,y2) w/ gradient
# Author : Trickster
# Call Info : Six to Ten Arguments
# Integer cx, cy, x1, y1, x2, y2 - Points
# Integer Thick - Line Thickness
# Integer Step - how many lines to draw (lower = higher accuracy)
# Color start_color, end_color - Start and end colors
#-------------------------------------------------------------------------
def shade_gradient_section(cx, cy, x1, y1, x2, y2, thick = 1, step = 1,
start_color = Color.new(0, 0, 0), end_color = start_color)
# Reverse all parameters sent if 2 x is less than the first x
x1, x2, y1, y2 = x2, x1, y2, y1 if x2 < x1
# Get Slope
slope = (y2 - y1).to_f / (x2 - x1)
# If Slope is infinite
if slope.infinite?
y1.step(y2, step) {|y| draw_gradient_line(cx, cy, x1, y, thick, start_color, end_color)}
# If Slope is zero
elsif slope.zero?
x1.step(x2, step) {|x| draw_gradient_line(cx, cy, x, y1, thick, start_color, end_color)}
elsif not slope.nan?
# Get Y intercept
yint = y1 - slope * x1
x1.step(x2, step) {|x| draw_gradient_line(cx, cy, x, slope * x + yint, thick, start_color, end_color)}
end
end
end