mirror of
https://github.com/infinitefusion/infinitefusion-e18.git
synced 2025-12-08 05:34:58 +00:00
6.6 update
This commit is contained in:
167
Data/Scripts/007_Objects and windows/001_RPG_Cache.rb
Normal file
167
Data/Scripts/007_Objects and windows/001_RPG_Cache.rb
Normal file
@@ -0,0 +1,167 @@
|
||||
class Hangup < Exception; end
|
||||
|
||||
|
||||
|
||||
module RPG
|
||||
module Cache
|
||||
def self.debug
|
||||
t = Time.now
|
||||
filename = t.strftime("%H %M %S.%L.txt")
|
||||
File.open("cache_" + filename, "wb") { |f|
|
||||
@cache.each do |key, value|
|
||||
if !value
|
||||
f.write("#{key} (nil)\r\n")
|
||||
elsif value.disposed?
|
||||
f.write("#{key} (disposed)\r\n")
|
||||
else
|
||||
f.write("#{key} (#{value.refcount}, #{value.width}x#{value.height})\r\n")
|
||||
end
|
||||
end
|
||||
}
|
||||
end
|
||||
|
||||
def self.setKey(key, obj)
|
||||
@cache[key] = obj
|
||||
end
|
||||
|
||||
def self.fromCache(i)
|
||||
return nil if !@cache.include?(i)
|
||||
obj = @cache[i]
|
||||
return nil if obj && obj.disposed?
|
||||
return obj
|
||||
end
|
||||
|
||||
def self.need_clearing()
|
||||
return @cache.size >= 100
|
||||
end
|
||||
|
||||
|
||||
def self.load_bitmap(folder_name, filename, hue = 0)
|
||||
path = folder_name + filename
|
||||
cached = true
|
||||
ret = fromCache(path)
|
||||
if !ret
|
||||
if filename == ""
|
||||
ret = BitmapWrapper.new(32, 32)
|
||||
else
|
||||
ret = BitmapWrapper.new(path)
|
||||
end
|
||||
@cache[path] = ret
|
||||
cached = false
|
||||
end
|
||||
if hue == 0
|
||||
ret.addRef if cached
|
||||
return ret
|
||||
end
|
||||
key = [path, hue]
|
||||
ret2 = fromCache(key)
|
||||
if ret2
|
||||
ret2.addRef
|
||||
else
|
||||
ret2 = ret.copy
|
||||
ret2.hue_change(hue)
|
||||
@cache[key] = ret2
|
||||
end
|
||||
return ret2
|
||||
end
|
||||
|
||||
def self.load_bitmap_path(path, hue = 0)
|
||||
cached = true
|
||||
ret = fromCache(path)
|
||||
if !ret
|
||||
if path == ""
|
||||
ret = BitmapWrapper.new(32, 32)
|
||||
else
|
||||
ret = BitmapWrapper.new(path)
|
||||
end
|
||||
@cache[path] = ret
|
||||
cached = false
|
||||
end
|
||||
if hue == 0
|
||||
ret.addRef if cached
|
||||
return ret
|
||||
end
|
||||
key = [path, hue]
|
||||
ret2 = fromCache(key)
|
||||
if ret2
|
||||
ret2.addRef
|
||||
else
|
||||
ret2 = ret.copy
|
||||
ret2.hue_change(hue)
|
||||
@cache[key] = ret2
|
||||
end
|
||||
return ret2
|
||||
end
|
||||
|
||||
def self.tileEx(filename, tile_id, hue, width = 1, height = 1)
|
||||
key = [filename, tile_id, hue, width, height]
|
||||
ret = fromCache(key)
|
||||
if ret
|
||||
ret.addRef
|
||||
else
|
||||
ret = BitmapWrapper.new(32 * width, 32 * height)
|
||||
x = (tile_id - 384) % 8 * 32
|
||||
y = (((tile_id - 384) / 8) - height + 1) * 32
|
||||
tileset = yield(filename)
|
||||
ret.blt(0, 0, tileset, Rect.new(x, y, 32 * width, 32 * height))
|
||||
tileset.dispose
|
||||
ret.hue_change(hue) if hue != 0
|
||||
@cache[key] = ret
|
||||
end
|
||||
return ret
|
||||
end
|
||||
|
||||
def self.tile(filename, tile_id, hue)
|
||||
return self.tileEx(filename, tile_id, hue) { |f| self.tileset(f) }
|
||||
end
|
||||
|
||||
def self.transition(filename)
|
||||
self.load_bitmap("Graphics/Transitions/", filename)
|
||||
end
|
||||
|
||||
def self.retain(folder_name, filename = "", hue = 0)
|
||||
path = folder_name + filename
|
||||
ret = fromCache(path)
|
||||
if hue > 0
|
||||
key = [path, hue]
|
||||
ret2 = fromCache(key)
|
||||
if ret2
|
||||
ret2.never_dispose = true
|
||||
return
|
||||
end
|
||||
end
|
||||
ret.never_dispose = true if ret
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
|
||||
class BitmapWrapper < Bitmap
|
||||
attr_reader :refcount
|
||||
attr_accessor :never_dispose
|
||||
def dispose
|
||||
return if self.disposed?
|
||||
@refcount -= 1
|
||||
super if @refcount <= 0 && !never_dispose
|
||||
end
|
||||
|
||||
def initialize(*arg)
|
||||
super
|
||||
@refcount = 1
|
||||
end
|
||||
|
||||
def resetRef
|
||||
@refcount = 1
|
||||
end
|
||||
|
||||
def copy
|
||||
bm = self.clone
|
||||
bm.resetRef
|
||||
return bm
|
||||
end
|
||||
|
||||
def addRef
|
||||
@refcount += 1
|
||||
end
|
||||
end
|
||||
818
Data/Scripts/007_Objects and windows/002_MessageConfig.rb
Normal file
818
Data/Scripts/007_Objects and windows/002_MessageConfig.rb
Normal file
@@ -0,0 +1,818 @@
|
||||
module MessageConfig
|
||||
LIGHT_TEXT_MAIN_COLOR = Color.new(248, 248, 248)
|
||||
LIGHT_TEXT_SHADOW_COLOR = Color.new(72, 80, 88)
|
||||
DARK_TEXT_MAIN_COLOR = Color.new(80, 80, 88)
|
||||
DARK_TEXT_SHADOW_COLOR = Color.new(160, 160, 168)
|
||||
|
||||
BLUE_TEXT_MAIN_COLOR = Color.new(35, 130, 200)
|
||||
BLUE_TEXT_SHADOW_COLOR = Color.new(20, 75, 115)
|
||||
|
||||
FONT_NAME = "Power Green"
|
||||
FONT_SIZE = 29
|
||||
SMALL_FONT_NAME = "Power Green Small"
|
||||
SMALL_FONT_SIZE = 25
|
||||
NARROW_FONT_NAME = "Power Green Narrow"
|
||||
NARROW_FONT_SIZE = 29
|
||||
|
||||
BUBBLE_TEXT_BASE = Color.new(248,248,248)#(72,80,88)#DIALOG
|
||||
BUBBLE_TEXT_SHADOW= Color.new(166,160,151)
|
||||
|
||||
# 0 = Pause cursor is displayed at end of text
|
||||
# 1 = Pause cursor is displayed at bottom right
|
||||
# 2 = Pause cursor is displayed at lower middle side
|
||||
CURSOR_POSITION = 1
|
||||
WINDOW_OPACITY = 255
|
||||
TEXT_SPEED = nil # can be positive to wait frames or negative to
|
||||
# show multiple characters in a single frame
|
||||
@@systemFrame = nil
|
||||
@@defaultTextSkin = nil
|
||||
@@textSpeed = nil
|
||||
@@systemFont = nil
|
||||
@@smallFont = nil
|
||||
@@narrowFont = nil
|
||||
|
||||
def self.pbDefaultSystemFrame
|
||||
if $PokemonSystem
|
||||
return pbResolveBitmap("Graphics/Windowskins/" + Settings::MENU_WINDOWSKINS[$PokemonSystem.frame]) || ""
|
||||
else
|
||||
return pbResolveBitmap("Graphics/Windowskins/" + Settings::MENU_WINDOWSKINS[0]) || ""
|
||||
end
|
||||
end
|
||||
|
||||
def self.pbDefaultSpeechFrame
|
||||
if $PokemonSystem
|
||||
return pbResolveBitmap("Graphics/Windowskins/" + Settings::SPEECH_WINDOWSKINS[$PokemonSystem.textskin]) || ""
|
||||
else
|
||||
return pbResolveBitmap("Graphics/Windowskins/" + Settings::SPEECH_WINDOWSKINS[0]) || ""
|
||||
end
|
||||
end
|
||||
|
||||
def self.pbDefaultWindowskin
|
||||
skin=($data_system) ? $data_system.windowskin_name : nil
|
||||
if skin && skin!=""
|
||||
skin=pbResolveBitmap("Graphics/Windowskins/"+skin) || ""
|
||||
end
|
||||
skin=pbResolveBitmap("Graphics/System/Window") if nil_or_empty?(skin)
|
||||
skin=pbResolveBitmap("Graphics/Windowskins/001-Blue01") if nil_or_empty?(skin)
|
||||
return skin || ""
|
||||
end
|
||||
|
||||
def self.pbGetSystemFrame
|
||||
if !@@systemFrame
|
||||
skin=MessageConfig.pbDefaultSystemFrame
|
||||
skin=MessageConfig.pbDefaultWindowskin if nil_or_empty?(skin)
|
||||
@@systemFrame=skin || ""
|
||||
end
|
||||
return @@systemFrame
|
||||
end
|
||||
|
||||
def self.pbGetSpeechFrame
|
||||
if !@@defaultTextSkin
|
||||
skin=MessageConfig.pbDefaultSpeechFrame
|
||||
skin=MessageConfig.pbDefaultWindowskin if nil_or_empty?(skin)
|
||||
@@defaultTextSkin=skin || ""
|
||||
end
|
||||
return @@defaultTextSkin
|
||||
end
|
||||
|
||||
def self.pbSetSystemFrame(value)
|
||||
@@systemFrame=pbResolveBitmap(value) || ""
|
||||
end
|
||||
|
||||
def self.pbSetSpeechFrame(value)
|
||||
@@defaultTextSkin=pbResolveBitmap(value) || ""
|
||||
end
|
||||
|
||||
#-----------------------------------------------------------------------------
|
||||
|
||||
def self.pbDefaultTextSpeed
|
||||
return ($PokemonSystem) ? pbSettingToTextSpeed($PokemonSystem.textspeed) : pbSettingToTextSpeed(nil)
|
||||
end
|
||||
|
||||
def self.pbGetTextSpeed
|
||||
@@textSpeed=pbDefaultTextSpeed if !@@textSpeed
|
||||
return @@textSpeed
|
||||
end
|
||||
|
||||
def self.pbSetTextSpeed(value)
|
||||
@@textSpeed=value
|
||||
end
|
||||
|
||||
def self.pbSettingToTextSpeed(speed)
|
||||
case speed
|
||||
when 0 then return 1
|
||||
when 1 then return -3
|
||||
when 2 then return -999
|
||||
end
|
||||
return TEXT_SPEED || 1
|
||||
end
|
||||
|
||||
#-----------------------------------------------------------------------------
|
||||
|
||||
def self.pbDefaultSystemFontName
|
||||
return MessageConfig.pbTryFonts(FONT_NAME)
|
||||
end
|
||||
|
||||
def self.pbDefaultSmallFontName
|
||||
return MessageConfig.pbTryFonts(SMALL_FONT_NAME)
|
||||
end
|
||||
|
||||
def self.pbDefaultNarrowFontName
|
||||
return MessageConfig.pbTryFonts(NARROW_FONT_NAME)
|
||||
end
|
||||
|
||||
def self.pbGetSystemFontName
|
||||
@@systemFont = pbDefaultSystemFontName if !@@systemFont
|
||||
return @@systemFont
|
||||
end
|
||||
|
||||
def self.pbGetSmallFontName
|
||||
@@smallFont = pbDefaultSmallFontName if !@@smallFont
|
||||
return @@smallFont
|
||||
end
|
||||
|
||||
def self.pbGetNarrowFontName
|
||||
@@narrowFont = pbDefaultNarrowFontName if !@@narrowFont
|
||||
return @@narrowFont
|
||||
end
|
||||
|
||||
def self.pbSetSystemFontName(value)
|
||||
@@systemFont = MessageConfig.pbTryFonts(value)
|
||||
@@systemFont = MessageConfig.pbDefaultSystemFontName if @@systemFont == ""
|
||||
end
|
||||
|
||||
def self.pbSetSmallFontName(value)
|
||||
@@smallFont = MessageConfig.pbTryFonts(value)
|
||||
@@smallFont = MessageConfig.pbDefaultSmallFontName if @@smallFont == ""
|
||||
end
|
||||
|
||||
def self.pbSetNarrowFontName(value)
|
||||
@@narrowFont = MessageConfig.pbTryFonts(value)
|
||||
@@narrowFont = MessageConfig.pbDefaultNarrowFontName if @@narrowFont == ""
|
||||
end
|
||||
|
||||
def self.pbTryFonts(*args)
|
||||
for a in args
|
||||
next if !a
|
||||
if a.is_a?(String)
|
||||
return a if Font.exist?(a)
|
||||
elsif a.is_a?(Array)
|
||||
for aa in a
|
||||
ret = MessageConfig.pbTryFonts(aa)
|
||||
return ret if ret != ""
|
||||
end
|
||||
end
|
||||
end
|
||||
return ""
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
|
||||
#===============================================================================
|
||||
# Position a window
|
||||
#===============================================================================
|
||||
def pbBottomRight(window)
|
||||
window.x=Graphics.width-window.width
|
||||
window.y=Graphics.height-window.height
|
||||
end
|
||||
|
||||
def pbBottomLeft(window)
|
||||
window.x=0
|
||||
window.y=Graphics.height-window.height
|
||||
end
|
||||
|
||||
def pbBottomLeftLines(window,lines,width=nil)
|
||||
window.x=0
|
||||
window.width=width ? width : Graphics.width
|
||||
window.height=(window.borderY rescue 32)+lines*32
|
||||
window.y=Graphics.height-window.height
|
||||
end
|
||||
|
||||
def pbPositionFaceWindow(facewindow,msgwindow)
|
||||
return if !facewindow
|
||||
if msgwindow
|
||||
if facewindow.height<=msgwindow.height
|
||||
facewindow.y=msgwindow.y
|
||||
else
|
||||
facewindow.y=msgwindow.y+msgwindow.height-facewindow.height
|
||||
end
|
||||
facewindow.x=Graphics.width-facewindow.width
|
||||
msgwindow.x=0
|
||||
msgwindow.width=Graphics.width-facewindow.width
|
||||
else
|
||||
facewindow.height=Graphics.height if facewindow.height>Graphics.height
|
||||
facewindow.x=0
|
||||
facewindow.y=0
|
||||
end
|
||||
end
|
||||
|
||||
def pbPositionNearMsgWindow(cmdwindow,msgwindow,side, x_offset=nil,y_offset=nil)
|
||||
return if !cmdwindow
|
||||
if msgwindow
|
||||
height=[cmdwindow.height,Graphics.height-msgwindow.height].min
|
||||
if cmdwindow.height!=height
|
||||
cmdwindow.height=height
|
||||
end
|
||||
cmdwindow.y=msgwindow.y-cmdwindow.height
|
||||
if cmdwindow.y<0
|
||||
cmdwindow.y=msgwindow.y+msgwindow.height
|
||||
if cmdwindow.y+cmdwindow.height>Graphics.height
|
||||
cmdwindow.y=msgwindow.y-cmdwindow.height
|
||||
end
|
||||
end
|
||||
case side
|
||||
when :left
|
||||
cmdwindow.x=msgwindow.x
|
||||
when :right
|
||||
cmdwindow.x=msgwindow.x+msgwindow.width-cmdwindow.width
|
||||
else
|
||||
cmdwindow.x=msgwindow.x+msgwindow.width-cmdwindow.width
|
||||
end
|
||||
else
|
||||
cmdwindow.height=Graphics.height if cmdwindow.height>Graphics.height
|
||||
cmdwindow.x=0
|
||||
cmdwindow.y=0
|
||||
end
|
||||
cmdwindow.x+= x_offset if x_offset
|
||||
cmdwindow.y+= y_offset if y_offset
|
||||
|
||||
|
||||
end
|
||||
|
||||
# internal function
|
||||
def pbRepositionMessageWindow(msgwindow, linecount=2)
|
||||
msgwindow.height=32*linecount+msgwindow.borderY
|
||||
msgwindow.y=(Graphics.height)-(msgwindow.height)
|
||||
if $game_system && $game_system.respond_to?("message_position")
|
||||
case $game_system.message_position
|
||||
when 0 # up
|
||||
msgwindow.y=0
|
||||
when 1 # middle
|
||||
msgwindow.y=(Graphics.height/2)-(msgwindow.height/2)
|
||||
when 2
|
||||
msgwindow.y=(Graphics.height)-(msgwindow.height)
|
||||
end
|
||||
end
|
||||
if $game_system && $game_system.respond_to?("message_frame")
|
||||
if $game_system.message_frame != 0
|
||||
msgwindow.opacity = 0
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# internal function
|
||||
def pbUpdateMsgWindowPos(msgwindow,event,eventChanged=false)
|
||||
if event
|
||||
if eventChanged
|
||||
msgwindow.resizeToFit2(msgwindow.text,Graphics.width*2/3,msgwindow.height)
|
||||
end
|
||||
msgwindow.y=event.screen_y-48-msgwindow.height
|
||||
if msgwindow.y<0
|
||||
msgwindow.y=event.screen_y+24
|
||||
end
|
||||
msgwindow.x=event.screen_x-(msgwindow.width/2)
|
||||
msgwindow.x=0 if msgwindow.x<0
|
||||
if msgwindow.x>Graphics.width-msgwindow.width
|
||||
msgwindow.x=Graphics.width-msgwindow.width
|
||||
end
|
||||
else
|
||||
curwidth=msgwindow.width
|
||||
if curwidth!=Graphics.width
|
||||
msgwindow.width=Graphics.width
|
||||
msgwindow.width=Graphics.width
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
#===============================================================================
|
||||
# Determine the colour of a background
|
||||
#===============================================================================
|
||||
def isDarkBackground(background,rect=nil)
|
||||
return true if !background || background.disposed?
|
||||
rect = background.rect if !rect
|
||||
return true if rect.width<=0 || rect.height<=0
|
||||
xSeg = (rect.width/16)
|
||||
xLoop = (xSeg==0) ? 1 : 16
|
||||
xStart = (xSeg==0) ? rect.x+(rect.width/2) : rect.x+xSeg/2
|
||||
ySeg = (rect.height/16)
|
||||
yLoop = (ySeg==0) ? 1 : 16
|
||||
yStart = (ySeg==0) ? rect.y+(rect.height/2) : rect.y+ySeg/2
|
||||
count = 0
|
||||
y = yStart
|
||||
r = 0; g = 0; b = 0
|
||||
yLoop.times do
|
||||
x = xStart
|
||||
xLoop.times do
|
||||
clr = background.get_pixel(x,y)
|
||||
if clr.alpha!=0
|
||||
r += clr.red
|
||||
g += clr.green
|
||||
b += clr.blue
|
||||
count += 1
|
||||
end
|
||||
x += xSeg
|
||||
end
|
||||
y += ySeg
|
||||
end
|
||||
return true if count==0
|
||||
r /= count
|
||||
g /= count
|
||||
b /= count
|
||||
return (r*0.299+g*0.587+b*0.114)<160
|
||||
end
|
||||
|
||||
def isDarkWindowskin(windowskin)
|
||||
if $PokemonTemp.speechbubble_bubble
|
||||
return false if $PokemonTemp.speechbubble_bubble > 0
|
||||
end
|
||||
return true if !windowskin || windowskin.disposed?
|
||||
if windowskin.width==192 && windowskin.height==128
|
||||
return isDarkBackground(windowskin,Rect.new(0,0,128,128))
|
||||
elsif windowskin.width==128 && windowskin.height==128
|
||||
return isDarkBackground(windowskin,Rect.new(0,0,64,64))
|
||||
elsif windowskin.width==96 && windowskin.height==48
|
||||
return isDarkBackground(windowskin,Rect.new(32,16,16,16))
|
||||
else
|
||||
clr = windowskin.get_pixel(windowskin.width/2, windowskin.height/2)
|
||||
return (clr.red*0.299+clr.green*0.587+clr.blue*0.114)<160
|
||||
end
|
||||
end
|
||||
|
||||
#===============================================================================
|
||||
# Determine which text colours to use based on the darkness of the background
|
||||
#===============================================================================
|
||||
def getSkinColor(windowskin,color,isDarkSkin)
|
||||
if !windowskin || windowskin.disposed? ||
|
||||
windowskin.width!=128 || windowskin.height!=128
|
||||
# Base color, shadow color (these are reversed on dark windowskins)
|
||||
textcolors = [
|
||||
"0070F8","78B8E8", # 1 Blue
|
||||
"E82010","F8A8B8", # 2 Red
|
||||
"60B048","B0D090", # 3 Green
|
||||
"48D8D8","A8E0E0", # 4 Cyan
|
||||
"D038B8","E8A0E0", # 5 Magenta
|
||||
"E8D020","F8E888", # 6 Yellow
|
||||
"A0A0A8","D0D0D8", # 7 Grey
|
||||
"F0F0F8","C8C8D0", # 8 White
|
||||
"9040E8","B8A8E0", # 9 Purple
|
||||
"F89818","F8C898", # 10 Orange
|
||||
colorToRgb32(MessageConfig::DARK_TEXT_MAIN_COLOR),
|
||||
colorToRgb32(MessageConfig::DARK_TEXT_SHADOW_COLOR), # 11 Dark default
|
||||
colorToRgb32(MessageConfig::LIGHT_TEXT_MAIN_COLOR),
|
||||
colorToRgb32(MessageConfig::LIGHT_TEXT_SHADOW_COLOR) # 12 Light default
|
||||
]
|
||||
if color==0 || color>textcolors.length/2 # No special colour, use default
|
||||
if isDarkSkin # Dark background, light text
|
||||
return shadowc3tag(MessageConfig::LIGHT_TEXT_MAIN_COLOR, MessageConfig::LIGHT_TEXT_SHADOW_COLOR)
|
||||
end
|
||||
# Light background, dark text
|
||||
return shadowc3tag(MessageConfig::DARK_TEXT_MAIN_COLOR, MessageConfig::DARK_TEXT_SHADOW_COLOR)
|
||||
end
|
||||
# Special colour as listed above
|
||||
if isDarkSkin && color!=12 # Dark background, light text
|
||||
return sprintf("<c3=%s,%s>",textcolors[2*(color-1)+1],textcolors[2*(color-1)])
|
||||
end
|
||||
# Light background, dark text
|
||||
return sprintf("<c3=%s,%s>",textcolors[2*(color-1)],textcolors[2*(color-1)+1])
|
||||
else # VX windowskin
|
||||
color = 0 if color>=32
|
||||
x = 64 + (color % 8) * 8
|
||||
y = 96 + (color / 8) * 8
|
||||
pixel = windowskin.get_pixel(x, y)
|
||||
return shadowctagFromColor(pixel)
|
||||
end
|
||||
end
|
||||
|
||||
def getDefaultTextColors(windowskin)
|
||||
if !windowskin || windowskin.disposed? ||
|
||||
windowskin.width!=128 || windowskin.height!=128
|
||||
if isDarkWindowskin(windowskin)
|
||||
return [MessageConfig::LIGHT_TEXT_MAIN_COLOR, MessageConfig::LIGHT_TEXT_SHADOW_COLOR] # White
|
||||
else
|
||||
return [MessageConfig::DARK_TEXT_MAIN_COLOR, MessageConfig::DARK_TEXT_SHADOW_COLOR] # Dark gray
|
||||
end
|
||||
else # VX windowskin
|
||||
color = windowskin.get_pixel(64, 96)
|
||||
shadow = nil
|
||||
isDark = (color.red+color.green+color.blue)/3 < 128
|
||||
if isDark
|
||||
shadow = Color.new(color.red+64,color.green+64,color.blue+64)
|
||||
else
|
||||
shadow = Color.new(color.red-64,color.green-64,color.blue-64)
|
||||
end
|
||||
return [color,shadow]
|
||||
end
|
||||
end
|
||||
|
||||
#===============================================================================
|
||||
# Makes sure a bitmap exists
|
||||
#===============================================================================
|
||||
def pbDoEnsureBitmap(bitmap,dwidth,dheight)
|
||||
if !bitmap || bitmap.disposed? || bitmap.width<dwidth || bitmap.height<dheight
|
||||
oldfont = (bitmap && !bitmap.disposed?) ? bitmap.font : nil
|
||||
bitmap.dispose if bitmap
|
||||
bitmap = Bitmap.new([1,dwidth].max,[1,dheight].max)
|
||||
(oldfont) ? bitmap.font = oldfont : pbSetSystemFont(bitmap)
|
||||
bitmap.font.shadow = false if bitmap.font && bitmap.font.respond_to?("shadow")
|
||||
end
|
||||
return bitmap
|
||||
end
|
||||
|
||||
#===============================================================================
|
||||
# Set a bitmap's font
|
||||
#===============================================================================
|
||||
# Sets a bitmap's font to the system font.
|
||||
def pbSetSystemFont(bitmap)
|
||||
bitmap.font.name = MessageConfig.pbGetSystemFontName
|
||||
bitmap.font.size = MessageConfig::FONT_SIZE
|
||||
end
|
||||
|
||||
# Sets a bitmap's font to the system small font.
|
||||
def pbSetSmallFont(bitmap)
|
||||
bitmap.font.name = MessageConfig.pbGetSmallFontName
|
||||
bitmap.font.size = MessageConfig::SMALL_FONT_SIZE
|
||||
end
|
||||
|
||||
# Sets a bitmap's font to the system narrow font.
|
||||
def pbSetNarrowFont(bitmap)
|
||||
bitmap.font.name = MessageConfig.pbGetNarrowFontName
|
||||
bitmap.font.size = MessageConfig::NARROW_FONT_SIZE
|
||||
end
|
||||
|
||||
#===============================================================================
|
||||
# Blend colours, set the colour of all bitmaps in a sprite hash
|
||||
#===============================================================================
|
||||
def pbAlphaBlend(dstColor,srcColor)
|
||||
r=(255*(srcColor.red-dstColor.red)/255)+dstColor.red
|
||||
g=(255*(srcColor.green-dstColor.green)/255)+dstColor.green
|
||||
b=(255*(srcColor.blue-dstColor.blue)/255)+dstColor.blue
|
||||
a=(255*(srcColor.alpha-dstColor.alpha)/255)+dstColor.alpha
|
||||
return Color.new(r,g,b,a)
|
||||
end
|
||||
|
||||
def pbSrcOver(dstColor,srcColor)
|
||||
er=srcColor.red*srcColor.alpha/255
|
||||
eg=srcColor.green*srcColor.alpha/255
|
||||
eb=srcColor.blue*srcColor.alpha/255
|
||||
iea=255-srcColor.alpha
|
||||
cr=dstColor.red*dstColor.alpha/255
|
||||
cg=dstColor.green*dstColor.alpha/255
|
||||
cb=dstColor.blue*dstColor.alpha/255
|
||||
ica=255-dstColor.alpha
|
||||
a=255-(iea*ica)/255
|
||||
r=(iea*cr)/255+er
|
||||
g=(iea*cg)/255+eg
|
||||
b=(iea*cb)/255+eb
|
||||
r=(a==0) ? 0 : r*255/a
|
||||
g=(a==0) ? 0 : g*255/a
|
||||
b=(a==0) ? 0 : b*255/a
|
||||
return Color.new(r,g,b,a)
|
||||
end
|
||||
|
||||
def pbSetSpritesToColor(sprites,color)
|
||||
return if !sprites || !color
|
||||
colors={}
|
||||
for i in sprites
|
||||
next if !i[1] || pbDisposed?(i[1])
|
||||
colors[i[0]]=i[1].color.clone
|
||||
i[1].color=pbSrcOver(i[1].color,color)
|
||||
end
|
||||
Graphics.update
|
||||
Input.update
|
||||
for i in colors
|
||||
next if !sprites[i[0]]
|
||||
sprites[i[0]].color=i[1]
|
||||
end
|
||||
end
|
||||
|
||||
#===============================================================================
|
||||
# Update and dispose sprite hashes
|
||||
#===============================================================================
|
||||
def using(window)
|
||||
begin
|
||||
yield if block_given?
|
||||
ensure
|
||||
window.dispose
|
||||
end
|
||||
end
|
||||
|
||||
def pbUpdateSpriteHash(windows)
|
||||
for i in windows
|
||||
window=i[1]
|
||||
if window
|
||||
if window.is_a?(Sprite) || window.is_a?(Window)
|
||||
window.update if !pbDisposed?(window)
|
||||
elsif window.is_a?(Plane)
|
||||
begin
|
||||
window.update if !window.disposed?
|
||||
rescue NoMethodError
|
||||
end
|
||||
elsif window.respond_to?("update")
|
||||
begin
|
||||
window.update
|
||||
rescue RGSSError
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# Disposes all objects in the specified hash.
|
||||
def pbDisposeSpriteHash(sprites)
|
||||
return if !sprites
|
||||
for i in sprites.keys
|
||||
pbDisposeSprite(sprites,i)
|
||||
end
|
||||
sprites.clear
|
||||
end
|
||||
|
||||
# Disposes the specified graphics object within the specified hash. Basically
|
||||
# like: sprites[id].dispose
|
||||
def pbDisposeSprite(sprites,id)
|
||||
sprite = sprites[id]
|
||||
sprite.dispose if sprite && !pbDisposed?(sprite)
|
||||
sprites[id] = nil
|
||||
end
|
||||
|
||||
def pbDisposed?(x)
|
||||
return true if !x
|
||||
return x.disposed? if !x.is_a?(Viewport)
|
||||
begin
|
||||
x.rect = x.rect
|
||||
rescue
|
||||
return true
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
#===============================================================================
|
||||
# Fades and window activations for sprite hashes
|
||||
#===============================================================================
|
||||
def pbPushFade
|
||||
$game_temp.fadestate = [$game_temp.fadestate+1,0].max if $game_temp
|
||||
end
|
||||
|
||||
def pbPopFade
|
||||
$game_temp.fadestate = [$game_temp.fadestate-1,0].max if $game_temp
|
||||
end
|
||||
|
||||
def pbIsFaded?
|
||||
return ($game_temp) ? $game_temp.fadestate>0 : false
|
||||
end
|
||||
|
||||
# pbFadeOutIn(z) { block }
|
||||
# Fades out the screen before a block is run and fades it back in after the
|
||||
# block exits. z indicates the z-coordinate of the viewport used for this effect
|
||||
def pbFadeOutIn(z=99999,nofadeout=false)
|
||||
col=Color.new(0,0,0,0)
|
||||
viewport=Viewport.new(0,0,Graphics.width,Graphics.height)
|
||||
viewport.z=z
|
||||
numFrames = (Graphics.frame_rate*Settings::FADEOUT_SPEED).floor
|
||||
alphaDiff = (255.0/numFrames).ceil
|
||||
for j in 0..numFrames
|
||||
col.set(0,0,0,j*alphaDiff)
|
||||
viewport.color=col
|
||||
Graphics.update
|
||||
Input.update
|
||||
end
|
||||
pbPushFade
|
||||
begin
|
||||
yield if block_given?
|
||||
ensure
|
||||
pbPopFade
|
||||
if !nofadeout
|
||||
for j in 0..numFrames
|
||||
col.set(0,0,0,(numFrames-j)*alphaDiff)
|
||||
viewport.color=col
|
||||
Graphics.update
|
||||
Input.update
|
||||
end
|
||||
end
|
||||
viewport.dispose
|
||||
end
|
||||
end
|
||||
|
||||
def pbFadeOutInWithUpdate(z,sprites,nofadeout=false)
|
||||
col=Color.new(0,0,0,0)
|
||||
viewport=Viewport.new(0,0,Graphics.width,Graphics.height)
|
||||
viewport.z=z
|
||||
numFrames = (Graphics.frame_rate*Settings::FADEOUT_SPEED).floor
|
||||
alphaDiff = (255.0/numFrames).ceil
|
||||
for j in 0..numFrames
|
||||
col.set(0,0,0,j*alphaDiff)
|
||||
viewport.color=col
|
||||
pbUpdateSpriteHash(sprites)
|
||||
Graphics.update
|
||||
Input.update
|
||||
end
|
||||
pbPushFade
|
||||
begin
|
||||
yield if block_given?
|
||||
ensure
|
||||
pbPopFade
|
||||
if !nofadeout
|
||||
for j in 0..numFrames
|
||||
col.set(0,0,0,(numFrames-j)*alphaDiff)
|
||||
viewport.color=col
|
||||
pbUpdateSpriteHash(sprites)
|
||||
Graphics.update
|
||||
Input.update
|
||||
end
|
||||
end
|
||||
viewport.dispose
|
||||
end
|
||||
end
|
||||
|
||||
# Similar to pbFadeOutIn, but pauses the music as it fades out.
|
||||
# Requires scripts "Audio" (for bgm_pause) and "SpriteWindow" (for pbFadeOutIn).
|
||||
def pbFadeOutInWithMusic(zViewport=99999)
|
||||
playingBGS = $game_system.getPlayingBGS
|
||||
playingBGM = $game_system.getPlayingBGM
|
||||
$game_system.bgm_pause(1.0)
|
||||
$game_system.bgs_pause(1.0)
|
||||
pos = $game_system.bgm_position
|
||||
pbFadeOutIn(zViewport) {
|
||||
yield
|
||||
$game_system.bgm_position = pos
|
||||
$game_system.bgm_resume(playingBGM)
|
||||
$game_system.bgs_resume(playingBGS)
|
||||
}
|
||||
end
|
||||
|
||||
def pbFadeOutAndHide(sprites)
|
||||
visiblesprites = {}
|
||||
numFrames = (Graphics.frame_rate*Settings::FADEOUT_SPEED).floor
|
||||
alphaDiff = (255.0/numFrames).ceil
|
||||
pbDeactivateWindows(sprites) {
|
||||
for j in 0..numFrames
|
||||
pbSetSpritesToColor(sprites,Color.new(0,0,0,j*alphaDiff))
|
||||
(block_given?) ? yield : pbUpdateSpriteHash(sprites)
|
||||
end
|
||||
}
|
||||
for i in sprites
|
||||
next if !i[1]
|
||||
next if pbDisposed?(i[1])
|
||||
visiblesprites[i[0]] = true if i[1].visible
|
||||
i[1].visible = false
|
||||
end
|
||||
return visiblesprites
|
||||
end
|
||||
|
||||
def pbFadeInAndShow(sprites,visiblesprites=nil)
|
||||
if visiblesprites
|
||||
for i in visiblesprites
|
||||
if i[1] && sprites[i[0]] && !pbDisposed?(sprites[i[0]])
|
||||
sprites[i[0]].visible = true
|
||||
end
|
||||
end
|
||||
end
|
||||
numFrames = (Graphics.frame_rate*Settings::FADEOUT_SPEED).floor
|
||||
alphaDiff = (255.0/numFrames).ceil
|
||||
pbDeactivateWindows(sprites) {
|
||||
for j in 0..numFrames
|
||||
pbSetSpritesToColor(sprites,Color.new(0,0,0,((numFrames-j)*alphaDiff)))
|
||||
(block_given?) ? yield : pbUpdateSpriteHash(sprites)
|
||||
end
|
||||
}
|
||||
end
|
||||
|
||||
# Restores which windows are active for the given sprite hash.
|
||||
# _activeStatuses_ is the result of a previous call to pbActivateWindows
|
||||
def pbRestoreActivations(sprites,activeStatuses)
|
||||
return if !sprites || !activeStatuses
|
||||
for k in activeStatuses.keys
|
||||
if sprites[k] && sprites[k].is_a?(Window) && !pbDisposed?(sprites[k])
|
||||
sprites[k].active=activeStatuses[k] ? true : false
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# Deactivates all windows. If a code block is given, deactivates all windows,
|
||||
# runs the code in the block, and reactivates them.
|
||||
def pbDeactivateWindows(sprites)
|
||||
if block_given?
|
||||
pbActivateWindow(sprites,nil) { yield }
|
||||
else
|
||||
pbActivateWindow(sprites,nil)
|
||||
end
|
||||
end
|
||||
|
||||
# Activates a specific window of a sprite hash. _key_ is the key of the window
|
||||
# in the sprite hash. If a code block is given, deactivates all windows except
|
||||
# the specified window, runs the code in the block, and reactivates them.
|
||||
def pbActivateWindow(sprites,key)
|
||||
return if !sprites
|
||||
activeStatuses={}
|
||||
for i in sprites
|
||||
if i[1] && i[1].is_a?(Window) && !pbDisposed?(i[1])
|
||||
activeStatuses[i[0]]=i[1].active
|
||||
i[1].active=(i[0]==key)
|
||||
end
|
||||
end
|
||||
if block_given?
|
||||
begin
|
||||
yield
|
||||
ensure
|
||||
pbRestoreActivations(sprites,activeStatuses)
|
||||
end
|
||||
return {}
|
||||
else
|
||||
return activeStatuses
|
||||
end
|
||||
end
|
||||
|
||||
#===============================================================================
|
||||
# Create background planes for a sprite hash
|
||||
#===============================================================================
|
||||
# Adds a background to the sprite hash.
|
||||
# _planename_ is the hash key of the background.
|
||||
# _background_ is a filename within the Graphics/Pictures/ folder and can be
|
||||
# an animated image.
|
||||
# _viewport_ is a viewport to place the background in.
|
||||
def addBackgroundPlane(sprites,planename,background,viewport=nil)
|
||||
sprites[planename]=AnimatedPlane.new(viewport)
|
||||
bitmapName=pbResolveBitmap("Graphics/Pictures/#{background}")
|
||||
if bitmapName==nil
|
||||
# Plane should exist in any case
|
||||
sprites[planename].bitmap=nil
|
||||
sprites[planename].visible=false
|
||||
else
|
||||
sprites[planename].setBitmap(bitmapName)
|
||||
for spr in sprites.values
|
||||
if spr.is_a?(Window)
|
||||
spr.windowskin=nil
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# Adds a background to the sprite hash.
|
||||
# _planename_ is the hash key of the background.
|
||||
# _background_ is a filename within the Graphics/Pictures/ folder and can be
|
||||
# an animated image.
|
||||
# _color_ is the color to use if the background can't be found.
|
||||
# _viewport_ is a viewport to place the background in.
|
||||
def addBackgroundOrColoredPlane(sprites,planename,background,color,viewport=nil)
|
||||
bitmapName=pbResolveBitmap("Graphics/Pictures/#{background}")
|
||||
if bitmapName==nil
|
||||
# Plane should exist in any case
|
||||
sprites[planename]=ColoredPlane.new(color,@viewport)
|
||||
else
|
||||
sprites[planename]=AnimatedPlane.new(viewport)
|
||||
sprites[planename].setBitmap(bitmapName)
|
||||
for spr in sprites.values
|
||||
if spr.is_a?(Window)
|
||||
spr.windowskin=nil
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
|
||||
#===============================================================================
|
||||
# Ensure required method definitions
|
||||
#===============================================================================
|
||||
module Graphics
|
||||
if !self.respond_to?("width")
|
||||
def self.width; return 640; end
|
||||
end
|
||||
if !self.respond_to?("height")
|
||||
def self.height; return 480; end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
|
||||
if !defined?(_INTL)
|
||||
def _INTL(*args)
|
||||
string=args[0].clone
|
||||
for i in 1...args.length
|
||||
string.gsub!(/\{#{i}\}/,"#{args[i]}")
|
||||
end
|
||||
return string
|
||||
end
|
||||
end
|
||||
|
||||
if !defined?(_ISPRINTF)
|
||||
def _ISPRINTF(*args)
|
||||
string=args[0].clone
|
||||
for i in 1...args.length
|
||||
string.gsub!(/\{#{i}\:([^\}]+?)\}/) { |m|
|
||||
next sprintf("%"+$1,args[i])
|
||||
}
|
||||
end
|
||||
return string
|
||||
end
|
||||
end
|
||||
|
||||
if !defined?(_MAPINTL)
|
||||
def _MAPINTL(*args)
|
||||
string=args[1].clone
|
||||
for i in 2...args.length
|
||||
string.gsub!(/\{#{i}\}/,"#{args[i+1]}")
|
||||
end
|
||||
return string
|
||||
end
|
||||
end
|
||||
604
Data/Scripts/007_Objects and windows/003_Window.rb
Normal file
604
Data/Scripts/007_Objects and windows/003_Window.rb
Normal file
@@ -0,0 +1,604 @@
|
||||
class WindowCursorRect < Rect
|
||||
def initialize(window)
|
||||
super(0, 0, 0, 0)
|
||||
@window = window
|
||||
end
|
||||
|
||||
def empty
|
||||
return unless needs_update?(0, 0, 0, 0)
|
||||
|
||||
set(0, 0, 0, 0)
|
||||
end
|
||||
|
||||
def empty?
|
||||
return self.x == 0 && self.y == 0 && self.width == 0 && self.height == 0
|
||||
end
|
||||
|
||||
def set(x, y, width, height)
|
||||
return unless needs_update?(x, y, width, height)
|
||||
|
||||
super(x, y, width, height)
|
||||
|
||||
@window.width = @window.width
|
||||
end
|
||||
|
||||
def height=(value)
|
||||
super(value)
|
||||
@window.width = @window.width
|
||||
end
|
||||
|
||||
def width=(value)
|
||||
super(value)
|
||||
@window.width = @window.width
|
||||
end
|
||||
|
||||
def x=(value)
|
||||
super(value)
|
||||
@window.width = @window.width
|
||||
end
|
||||
|
||||
def y=(value)
|
||||
super(value)
|
||||
@window.width = @window.width
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def needs_update?(x, y, width, height)
|
||||
return self.x != x || self.y != y || self.width != width || self.height != height
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
class Window
|
||||
attr_reader :tone
|
||||
attr_reader :color
|
||||
attr_reader :blend_type
|
||||
attr_reader :contents_blend_type
|
||||
attr_reader :viewport
|
||||
attr_reader :contents
|
||||
attr_reader :ox
|
||||
attr_reader :oy
|
||||
attr_reader :x
|
||||
attr_reader :y
|
||||
attr_reader :z
|
||||
attr_reader :width
|
||||
attr_reader :active
|
||||
attr_reader :pause
|
||||
attr_reader :height
|
||||
attr_reader :opacity
|
||||
attr_reader :back_opacity
|
||||
attr_reader :contents_opacity
|
||||
attr_reader :visible
|
||||
attr_reader :cursor_rect
|
||||
attr_reader :openness
|
||||
attr_reader :stretch
|
||||
|
||||
def windowskin
|
||||
@_windowskin
|
||||
end
|
||||
|
||||
def initialize(viewport=nil)
|
||||
@sprites={}
|
||||
@spritekeys=[
|
||||
"back",
|
||||
"corner0","side0","scroll0",
|
||||
"corner1","side1","scroll1",
|
||||
"corner2","side2","scroll2",
|
||||
"corner3","side3","scroll3",
|
||||
"cursor","contents","pause"
|
||||
]
|
||||
@sidebitmaps=[nil,nil,nil,nil]
|
||||
@cursorbitmap=nil
|
||||
@bgbitmap=nil
|
||||
@viewport=viewport
|
||||
for i in @spritekeys
|
||||
@sprites[i]=Sprite.new(@viewport)
|
||||
end
|
||||
@disposed=false
|
||||
@tone=Tone.new(0,0,0)
|
||||
@color=Color.new(0,0,0,0)
|
||||
@blankcontents=Bitmap.new(1,1) # RGSS2 requires this
|
||||
@contents=@blankcontents
|
||||
@_windowskin=nil
|
||||
@rpgvx=false # Set to true to emulate RPGVX windows
|
||||
@x=0
|
||||
@y=0
|
||||
@width=0
|
||||
@openness=255
|
||||
@height=0
|
||||
@ox=0
|
||||
@oy=0
|
||||
@z=0
|
||||
@stretch=true
|
||||
@visible=true
|
||||
@active=true
|
||||
@blend_type=0
|
||||
@contents_blend_type=0
|
||||
@opacity=255
|
||||
@back_opacity=255
|
||||
@contents_opacity=255
|
||||
@cursor_rect=WindowCursorRect.new(self)
|
||||
@cursorblink=0
|
||||
@cursoropacity=255
|
||||
@pause=false
|
||||
@pauseopacity=255
|
||||
@pauseframe=0
|
||||
privRefresh(true)
|
||||
end
|
||||
|
||||
def dispose
|
||||
if !self.disposed?
|
||||
for i in @sprites
|
||||
i[1].dispose if i[1]
|
||||
@sprites[i[0]]=nil
|
||||
end
|
||||
for i in 0...@sidebitmaps.length
|
||||
@sidebitmaps[i].dispose if @sidebitmaps[i]
|
||||
@sidebitmaps[i]=nil
|
||||
end
|
||||
@blankcontents.dispose
|
||||
@cursorbitmap.dispose if @cursorbitmap
|
||||
@backbitmap.dispose if @backbitmap
|
||||
@sprites.clear
|
||||
@sidebitmaps.clear
|
||||
@_windowskin=nil
|
||||
@_contents=nil
|
||||
@disposed=true
|
||||
end
|
||||
end
|
||||
|
||||
def openness=(value)
|
||||
@openness=value
|
||||
@openness=0 if @openness<0
|
||||
@openness=255 if @openness>255
|
||||
privRefresh
|
||||
end
|
||||
|
||||
def stretch=(value)
|
||||
@stretch=value
|
||||
privRefresh(true)
|
||||
end
|
||||
|
||||
def visible=(value)
|
||||
@visible=value
|
||||
privRefresh
|
||||
end
|
||||
|
||||
def viewport=(value)
|
||||
@viewport=value
|
||||
for i in @spritekeys
|
||||
@sprites[i].dispose
|
||||
if @sprites[i].is_a?(Sprite)
|
||||
@sprites[i]=Sprite.new(@viewport)
|
||||
else
|
||||
@sprites[i]=nil
|
||||
end
|
||||
end
|
||||
privRefresh(true)
|
||||
end
|
||||
|
||||
def z=(value)
|
||||
@z=value
|
||||
privRefresh
|
||||
end
|
||||
|
||||
def disposed?
|
||||
return @disposed
|
||||
end
|
||||
|
||||
def contents=(value)
|
||||
@contents=value
|
||||
privRefresh
|
||||
end
|
||||
|
||||
def windowskin=(value)
|
||||
@_windowskin=value
|
||||
if value && value.is_a?(Bitmap) && !value.disposed? && value.width==128
|
||||
@rpgvx=true
|
||||
else
|
||||
@rpgvx=false
|
||||
end
|
||||
privRefresh(true)
|
||||
end
|
||||
|
||||
def ox=(value)
|
||||
@ox=value
|
||||
privRefresh
|
||||
end
|
||||
|
||||
def active=(value)
|
||||
@active=value
|
||||
privRefresh(true)
|
||||
end
|
||||
|
||||
def cursor_rect=(value)
|
||||
if !value
|
||||
@cursor_rect.empty
|
||||
else
|
||||
@cursor_rect.set(value.x,value.y,value.width,value.height)
|
||||
end
|
||||
end
|
||||
|
||||
def oy=(value)
|
||||
@oy=value
|
||||
privRefresh
|
||||
end
|
||||
|
||||
def width=(value)
|
||||
@width=value
|
||||
privRefresh(true)
|
||||
end
|
||||
|
||||
def height=(value)
|
||||
@height=value
|
||||
privRefresh(true)
|
||||
end
|
||||
|
||||
def pause=(value)
|
||||
@pause=value
|
||||
@pauseopacity=0 if !value
|
||||
privRefresh
|
||||
end
|
||||
|
||||
def x=(value)
|
||||
@x=value
|
||||
privRefresh
|
||||
end
|
||||
|
||||
def y=(value)
|
||||
@y=value
|
||||
privRefresh
|
||||
end
|
||||
|
||||
def opacity=(value)
|
||||
@opacity=value
|
||||
@opacity=0 if @opacity<0
|
||||
@opacity=255 if @opacity>255
|
||||
privRefresh
|
||||
end
|
||||
|
||||
def back_opacity=(value)
|
||||
@back_opacity=value
|
||||
@back_opacity=0 if @back_opacity<0
|
||||
@back_opacity=255 if @back_opacity>255
|
||||
privRefresh
|
||||
end
|
||||
|
||||
def contents_opacity=(value)
|
||||
@contents_opacity=value
|
||||
@contents_opacity=0 if @contents_opacity<0
|
||||
@contents_opacity=255 if @contents_opacity>255
|
||||
privRefresh
|
||||
end
|
||||
|
||||
def tone=(value)
|
||||
@tone=value
|
||||
privRefresh
|
||||
end
|
||||
|
||||
def color=(value)
|
||||
@color=value
|
||||
privRefresh
|
||||
end
|
||||
|
||||
def blend_type=(value)
|
||||
@blend_type=value
|
||||
privRefresh
|
||||
end
|
||||
|
||||
def flash(color,duration)
|
||||
return if disposed?
|
||||
for i in @sprites
|
||||
i[1].flash(color,duration)
|
||||
end
|
||||
end
|
||||
|
||||
def update
|
||||
return if disposed?
|
||||
mustchange=false
|
||||
if @active
|
||||
if @cursorblink==0
|
||||
@cursoropacity-=8
|
||||
@cursorblink=1 if @cursoropacity<=128
|
||||
else
|
||||
@cursoropacity+=8
|
||||
@cursorblink=0 if @cursoropacity>=255
|
||||
end
|
||||
mustchange=true if !@cursor_rect.empty?
|
||||
else
|
||||
mustchange=true if @cursoropacity!=128
|
||||
@cursoropacity=128
|
||||
end
|
||||
if @pause
|
||||
@pauseframe=(Graphics.frame_count / 8) % 4
|
||||
@pauseopacity=[@pauseopacity+64,255].min
|
||||
mustchange=true
|
||||
end
|
||||
privRefresh if mustchange
|
||||
for i in @sprites
|
||||
i[1].update
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def ensureBitmap(bitmap,dwidth,dheight)
|
||||
if !bitmap||bitmap.disposed?||bitmap.width<dwidth||bitmap.height<dheight
|
||||
bitmap.dispose if bitmap
|
||||
bitmap=Bitmap.new([1,dwidth].max,[1,dheight].max)
|
||||
end
|
||||
return bitmap
|
||||
end
|
||||
|
||||
def tileBitmap(dstbitmap,dstrect,srcbitmap,srcrect)
|
||||
return if !srcbitmap || srcbitmap.disposed?
|
||||
left=dstrect.x
|
||||
top=dstrect.y
|
||||
y=0;loop do break unless y<dstrect.height
|
||||
x=0;loop do break unless x<dstrect.width
|
||||
dstbitmap.blt(x+left,y+top,srcbitmap,srcrect)
|
||||
x+=srcrect.width
|
||||
end
|
||||
y+=srcrect.height
|
||||
end
|
||||
end
|
||||
|
||||
def privRefresh(changeBitmap=false)
|
||||
return if self.disposed?
|
||||
backopac=self.back_opacity*self.opacity/255
|
||||
contopac=self.contents_opacity
|
||||
cursoropac=@cursoropacity*contopac/255
|
||||
for i in 0...4
|
||||
@sprites["corner#{i}"].bitmap=@_windowskin
|
||||
@sprites["scroll#{i}"].bitmap=@_windowskin
|
||||
end
|
||||
@sprites["pause"].bitmap=@_windowskin
|
||||
@sprites["contents"].bitmap=@contents
|
||||
if @_windowskin && !@_windowskin.disposed?
|
||||
for i in 0...4
|
||||
@sprites["corner#{i}"].opacity=@opacity
|
||||
@sprites["corner#{i}"].tone=@tone
|
||||
@sprites["corner#{i}"].color=@color
|
||||
@sprites["corner#{i}"].blend_type=@blend_type
|
||||
@sprites["corner#{i}"].visible=@visible
|
||||
@sprites["side#{i}"].opacity=@opacity
|
||||
@sprites["side#{i}"].tone=@tone
|
||||
@sprites["side#{i}"].color=@color
|
||||
@sprites["side#{i}"].blend_type=@blend_type
|
||||
@sprites["side#{i}"].visible=@visible
|
||||
@sprites["scroll#{i}"].opacity=@opacity
|
||||
@sprites["scroll#{i}"].tone=@tone
|
||||
@sprites["scroll#{i}"].blend_type=@blend_type
|
||||
@sprites["scroll#{i}"].color=@color
|
||||
@sprites["scroll#{i}"].visible=@visible
|
||||
end
|
||||
for i in ["back","cursor","pause","contents"]
|
||||
@sprites[i].color=@color
|
||||
@sprites[i].tone=@tone
|
||||
@sprites[i].blend_type=@blend_type
|
||||
end
|
||||
@sprites["contents"].blend_type=@contents_blend_type
|
||||
@sprites["back"].opacity=backopac
|
||||
@sprites["contents"].opacity=contopac
|
||||
@sprites["cursor"].opacity=cursoropac
|
||||
@sprites["pause"].opacity=@pauseopacity
|
||||
@sprites["back"].visible=@visible
|
||||
@sprites["contents"].visible=@visible && @openness==255
|
||||
@sprites["pause"].visible=@visible && @pause
|
||||
@sprites["cursor"].visible=@visible && @openness==255
|
||||
hascontents=(@contents && !@contents.disposed?)
|
||||
@sprites["scroll0"].visible = @visible && hascontents && @oy > 0
|
||||
@sprites["scroll1"].visible = @visible && hascontents && @ox > 0
|
||||
@sprites["scroll2"].visible = @visible && hascontents &&
|
||||
(@contents.width - @ox) > @width-32
|
||||
@sprites["scroll3"].visible = @visible && hascontents &&
|
||||
(@contents.height - @oy) > @height-32
|
||||
else
|
||||
for i in 0...4
|
||||
@sprites["corner#{i}"].visible=false
|
||||
@sprites["side#{i}"].visible=false
|
||||
@sprites["scroll#{i}"].visible=false
|
||||
end
|
||||
@sprites["contents"].visible=@visible && @openness==255
|
||||
@sprites["contents"].color=@color
|
||||
@sprites["contents"].tone=@tone
|
||||
@sprites["contents"].blend_type=@contents_blend_type
|
||||
@sprites["contents"].opacity=contopac
|
||||
@sprites["back"].visible=false
|
||||
@sprites["pause"].visible=false
|
||||
@sprites["cursor"].visible=false
|
||||
end
|
||||
for i in @sprites
|
||||
i[1].z=@z
|
||||
end
|
||||
if @rpgvx
|
||||
@sprites["cursor"].z=@z # For Compatibility
|
||||
@sprites["contents"].z=@z # For Compatibility
|
||||
@sprites["pause"].z=@z # For Compatibility
|
||||
else
|
||||
@sprites["cursor"].z=@z+1 # For Compatibility
|
||||
@sprites["contents"].z=@z+2 # For Compatibility
|
||||
@sprites["pause"].z=@z+2 # For Compatibility
|
||||
end
|
||||
if @rpgvx
|
||||
trimX=64
|
||||
trimY=0
|
||||
backRect=Rect.new(0,0,64,64)
|
||||
blindsRect=Rect.new(0,64,64,64)
|
||||
else
|
||||
trimX=128
|
||||
trimY=0
|
||||
backRect=Rect.new(0,0,128,128)
|
||||
blindsRect=nil
|
||||
end
|
||||
@sprites["corner0"].src_rect.set(trimX,trimY+0,16,16);
|
||||
@sprites["corner1"].src_rect.set(trimX+48,trimY+0,16,16);
|
||||
@sprites["corner2"].src_rect.set(trimX,trimY+48,16,16);
|
||||
@sprites["corner3"].src_rect.set(trimX+48,trimY+48,16,16);
|
||||
@sprites["scroll0"].src_rect.set(trimX+24, trimY+16, 16, 8) # up
|
||||
@sprites["scroll3"].src_rect.set(trimX+24, trimY+40, 16, 8) # down
|
||||
@sprites["scroll1"].src_rect.set(trimX+16, trimY+24, 8, 16) # left
|
||||
@sprites["scroll2"].src_rect.set(trimX+40, trimY+24, 8, 16) # right
|
||||
cursorX=trimX
|
||||
cursorY=trimY+64
|
||||
sideRects=[
|
||||
Rect.new(trimX+16,trimY+0,32,16),
|
||||
Rect.new(trimX,trimY+16,16,32),
|
||||
Rect.new(trimX+48,trimY+16,16,32),
|
||||
Rect.new(trimX+16,trimY+48,32,16)
|
||||
]
|
||||
if @width>32 && @height>32
|
||||
@sprites["contents"].src_rect.set(@ox,@oy,@width-32,@height-32)
|
||||
else
|
||||
@sprites["contents"].src_rect.set(0,0,0,0)
|
||||
end
|
||||
pauseRects=[
|
||||
trimX+32,trimY+64,
|
||||
trimX+48,trimY+64,
|
||||
trimX+32,trimY+80,
|
||||
trimX+48,trimY+80,
|
||||
]
|
||||
pauseWidth=16
|
||||
pauseHeight=16
|
||||
@sprites["pause"].src_rect.set(
|
||||
pauseRects[@pauseframe*2],
|
||||
pauseRects[@pauseframe*2+1],
|
||||
pauseWidth,pauseHeight
|
||||
)
|
||||
@sprites["pause"].x=@x+(@width/2)-(pauseWidth/2)
|
||||
@sprites["pause"].y=@y+@height-16 # 16 refers to skin margin
|
||||
@sprites["contents"].x=@x+16
|
||||
@sprites["contents"].y=@y+16
|
||||
@sprites["corner0"].x=@x
|
||||
@sprites["corner0"].y=@y
|
||||
@sprites["corner1"].x=@x+@width-16
|
||||
@sprites["corner1"].y=@y
|
||||
@sprites["corner2"].x=@x
|
||||
@sprites["corner2"].y=@y+@height-16
|
||||
@sprites["corner3"].x=@x+@width-16
|
||||
@sprites["corner3"].y=@y+@height-16
|
||||
@sprites["side0"].x=@x+16
|
||||
@sprites["side0"].y=@y
|
||||
@sprites["side1"].x=@x
|
||||
@sprites["side1"].y=@y+16
|
||||
@sprites["side2"].x=@x+@width-16
|
||||
@sprites["side2"].y=@y+16
|
||||
@sprites["side3"].x=@x+16
|
||||
@sprites["side3"].y=@y+@height-16
|
||||
@sprites["scroll0"].x = @x+@width / 2 - 8
|
||||
@sprites["scroll0"].y = @y+8
|
||||
@sprites["scroll1"].x = @x+8
|
||||
@sprites["scroll1"].y = @y+@height / 2 - 8
|
||||
@sprites["scroll2"].x = @x+@width - 16
|
||||
@sprites["scroll2"].y = @y+@height / 2 - 8
|
||||
@sprites["scroll3"].x = @x+@width / 2 - 8
|
||||
@sprites["scroll3"].y = @y+@height - 16
|
||||
@sprites["back"].x=@x+2
|
||||
@sprites["back"].y=@y+2
|
||||
@sprites["cursor"].x=@x+16+@cursor_rect.x
|
||||
@sprites["cursor"].y=@y+16+@cursor_rect.y
|
||||
if changeBitmap && @_windowskin && !@_windowskin.disposed?
|
||||
width=@cursor_rect.width
|
||||
height=@cursor_rect.height
|
||||
if width > 0 && height > 0
|
||||
cursorrects=[
|
||||
# sides
|
||||
Rect.new(cursorX+2, cursorY+0, 28, 2),
|
||||
Rect.new(cursorX+0, cursorY+2, 2, 28),
|
||||
Rect.new(cursorX+30, cursorY+2, 2, 28),
|
||||
Rect.new(cursorX+2, cursorY+30, 28, 2),
|
||||
# corners
|
||||
Rect.new(cursorX+0, cursorY+0, 2, 2),
|
||||
Rect.new(cursorX+30, cursorY+0, 2, 2),
|
||||
Rect.new(cursorX+0, cursorY+30, 2, 2),
|
||||
Rect.new(cursorX+30, cursorY+30, 2, 2),
|
||||
# back
|
||||
Rect.new(cursorX+2, cursorY+2, 28, 28)
|
||||
]
|
||||
margin=2
|
||||
fullmargin=4
|
||||
@cursorbitmap = ensureBitmap(@cursorbitmap, width, height)
|
||||
@cursorbitmap.clear
|
||||
@sprites["cursor"].bitmap=@cursorbitmap
|
||||
@sprites["cursor"].src_rect.set(0,0,width,height)
|
||||
rect = Rect.new(margin,margin,
|
||||
width - fullmargin, height - fullmargin)
|
||||
@cursorbitmap.stretch_blt(rect, @_windowskin, cursorrects[8])
|
||||
@cursorbitmap.blt(0, 0, @_windowskin, cursorrects[4])# top left
|
||||
@cursorbitmap.blt(width-margin, 0, @_windowskin, cursorrects[5]) # top right
|
||||
@cursorbitmap.blt(0, height-margin, @_windowskin, cursorrects[6]) # bottom right
|
||||
@cursorbitmap.blt(width-margin, height-margin, @_windowskin, cursorrects[7]) # bottom left
|
||||
rect = Rect.new(margin, 0,
|
||||
width - fullmargin, margin)
|
||||
@cursorbitmap.stretch_blt(rect, @_windowskin, cursorrects[0])
|
||||
rect = Rect.new(0, margin,
|
||||
margin, height - fullmargin)
|
||||
@cursorbitmap.stretch_blt(rect, @_windowskin, cursorrects[1])
|
||||
rect = Rect.new(width - margin, margin,
|
||||
margin, height - fullmargin)
|
||||
@cursorbitmap.stretch_blt(rect, @_windowskin, cursorrects[2])
|
||||
rect = Rect.new(margin, height-margin,
|
||||
width - fullmargin, margin)
|
||||
@cursorbitmap.stretch_blt(rect, @_windowskin, cursorrects[3])
|
||||
else
|
||||
@sprites["cursor"].visible=false
|
||||
@sprites["cursor"].src_rect.set(0,0,0,0)
|
||||
end
|
||||
for i in 0...4
|
||||
dwidth = (i==0 || i==3) ? @width-32 : 16
|
||||
dheight = (i==0 || i==3) ? 16 : @height-32
|
||||
@sidebitmaps[i]=ensureBitmap(@sidebitmaps[i],dwidth,dheight)
|
||||
@sprites["side#{i}"].bitmap=@sidebitmaps[i]
|
||||
@sprites["side#{i}"].src_rect.set(0,0,dwidth,dheight)
|
||||
@sidebitmaps[i].clear
|
||||
if sideRects[i].width>0 && sideRects[i].height>0
|
||||
@sidebitmaps[i].stretch_blt(@sprites["side#{i}"].src_rect,
|
||||
@_windowskin,sideRects[i])
|
||||
end
|
||||
end
|
||||
backwidth=@width-4
|
||||
backheight=@height-4
|
||||
if backwidth>0 && backheight>0
|
||||
@backbitmap=ensureBitmap(@backbitmap,backwidth,backheight)
|
||||
@sprites["back"].bitmap=@backbitmap
|
||||
@sprites["back"].src_rect.set(0,0,backwidth,backheight)
|
||||
@backbitmap.clear
|
||||
if @stretch
|
||||
@backbitmap.stretch_blt(@sprites["back"].src_rect,@_windowskin,backRect)
|
||||
else
|
||||
tileBitmap(@backbitmap,@sprites["back"].src_rect,@_windowskin,backRect)
|
||||
end
|
||||
if blindsRect
|
||||
tileBitmap(@backbitmap,@sprites["back"].src_rect,@_windowskin,blindsRect)
|
||||
end
|
||||
else
|
||||
@sprites["back"].visible=false
|
||||
@sprites["back"].src_rect.set(0,0,0,0)
|
||||
end
|
||||
end
|
||||
if @openness!=255
|
||||
opn=@openness/255.0
|
||||
for k in @spritekeys
|
||||
sprite=@sprites[k]
|
||||
ratio=(@height<=0) ? 0 : (sprite.y-@y)*1.0/@height
|
||||
sprite.zoom_y=opn
|
||||
sprite.oy=0
|
||||
sprite.y=(@y+(@height/2.0)+(@height*ratio*opn)-(@height/2*opn)).floor
|
||||
end
|
||||
else
|
||||
for k in @spritekeys
|
||||
sprite=@sprites[k]
|
||||
sprite.zoom_y=1.0
|
||||
end
|
||||
end
|
||||
i=0
|
||||
# Ensure Z order
|
||||
for k in @spritekeys
|
||||
sprite=@sprites[k]
|
||||
y=sprite.y
|
||||
sprite.y=i
|
||||
sprite.oy=(sprite.zoom_y<=0) ? 0 : (i-y)/sprite.zoom_y
|
||||
end
|
||||
end
|
||||
end
|
||||
936
Data/Scripts/007_Objects and windows/004_SpriteWindow.rb
Normal file
936
Data/Scripts/007_Objects and windows/004_SpriteWindow.rb
Normal file
@@ -0,0 +1,936 @@
|
||||
#===============================================================================
|
||||
# SpriteWindow is a class based on Window which emulates Window's functionality.
|
||||
# This class is necessary in order to change the viewport of windows (with
|
||||
# viewport=) and to make windows fade in and out (with tone=).
|
||||
#===============================================================================
|
||||
class SpriteWindow < Window
|
||||
attr_reader :tone
|
||||
attr_reader :color
|
||||
attr_reader :viewport
|
||||
attr_reader :contents
|
||||
attr_reader :ox
|
||||
attr_reader :oy
|
||||
attr_reader :x
|
||||
attr_reader :y
|
||||
attr_reader :z
|
||||
attr_reader :zoom_x
|
||||
attr_reader :zoom_y
|
||||
attr_reader :offset_x
|
||||
attr_reader :offset_y
|
||||
attr_reader :width
|
||||
attr_reader :active
|
||||
attr_reader :pause
|
||||
attr_reader :height
|
||||
attr_reader :opacity
|
||||
attr_reader :back_opacity
|
||||
attr_reader :contents_opacity
|
||||
attr_reader :visible
|
||||
attr_reader :cursor_rect
|
||||
attr_reader :contents_blend_type
|
||||
attr_reader :blend_type
|
||||
attr_reader :openness
|
||||
|
||||
def windowskin
|
||||
@_windowskin
|
||||
end
|
||||
|
||||
# Flags used to preserve compatibility
|
||||
# with RGSS/RGSS2's version of Window
|
||||
module CompatBits
|
||||
CorrectZ = 1
|
||||
ExpandBack = 2
|
||||
ShowScrollArrows = 4
|
||||
StretchSides = 8
|
||||
ShowPause = 16
|
||||
ShowCursor = 32
|
||||
end
|
||||
|
||||
attr_reader :compat
|
||||
|
||||
def compat=(value)
|
||||
@compat=value
|
||||
privRefresh(true)
|
||||
end
|
||||
|
||||
def initialize(viewport=nil)
|
||||
@sprites={}
|
||||
@spritekeys=[
|
||||
"back",
|
||||
"corner0","side0","scroll0",
|
||||
"corner1","side1","scroll1",
|
||||
"corner2","side2","scroll2",
|
||||
"corner3","side3","scroll3",
|
||||
"cursor","contents","pause"
|
||||
]
|
||||
@viewport=viewport
|
||||
@sidebitmaps=[nil,nil,nil,nil]
|
||||
@cursorbitmap=nil
|
||||
@bgbitmap=nil
|
||||
for i in @spritekeys
|
||||
@sprites[i]=Sprite.new(@viewport)
|
||||
end
|
||||
@disposed=false
|
||||
@tone=Tone.new(0,0,0)
|
||||
@color=Color.new(0,0,0,0)
|
||||
@blankcontents=Bitmap.new(1,1) # RGSS2 requires this
|
||||
@contents=@blankcontents
|
||||
@_windowskin=nil
|
||||
@rpgvx=false
|
||||
@compat=CompatBits::ExpandBack|CompatBits::StretchSides
|
||||
@x=0
|
||||
@y=0
|
||||
@width=0
|
||||
@height=0
|
||||
@offset_x=0
|
||||
@offset_y=0
|
||||
@zoom_x=1.0
|
||||
@zoom_y=1.0
|
||||
@ox=0
|
||||
@oy=0
|
||||
@z=0
|
||||
@stretch=true
|
||||
@visible=true
|
||||
@active=true
|
||||
@openness=255
|
||||
@opacity=255
|
||||
@back_opacity=255
|
||||
@blend_type=0
|
||||
@contents_blend_type=0
|
||||
@contents_opacity=255
|
||||
@cursor_rect=WindowCursorRect.new(self)
|
||||
@cursorblink=0
|
||||
@cursoropacity=255
|
||||
@pause=false
|
||||
@pauseframe=0
|
||||
@flash=0
|
||||
@pauseopacity=0
|
||||
@skinformat=0
|
||||
@skinrect=Rect.new(0,0,0,0)
|
||||
@trim=[16,16,16,16]
|
||||
privRefresh(true)
|
||||
end
|
||||
|
||||
def dispose
|
||||
if !self.disposed?
|
||||
for i in @sprites
|
||||
i[1].dispose if i[1]
|
||||
@sprites[i[0]]=nil
|
||||
end
|
||||
for i in 0...@sidebitmaps.length
|
||||
@sidebitmaps[i].dispose if @sidebitmaps[i]
|
||||
@sidebitmaps[i]=nil
|
||||
end
|
||||
@blankcontents.dispose
|
||||
@cursorbitmap.dispose if @cursorbitmap
|
||||
@backbitmap.dispose if @backbitmap
|
||||
@sprites.clear
|
||||
@sidebitmaps.clear
|
||||
@_windowskin=nil
|
||||
@disposed=true
|
||||
end
|
||||
end
|
||||
|
||||
def stretch=(value)
|
||||
@stretch=value
|
||||
privRefresh(true)
|
||||
end
|
||||
|
||||
def visible=(value)
|
||||
@visible=value
|
||||
privRefresh
|
||||
end
|
||||
|
||||
def viewport=(value)
|
||||
@viewport=value
|
||||
for i in @spritekeys
|
||||
@sprites[i].dispose if @sprites[i]
|
||||
end
|
||||
for i in @spritekeys
|
||||
if @sprites[i].is_a?(Sprite)
|
||||
@sprites[i]=Sprite.new(@viewport)
|
||||
else
|
||||
@sprites[i]=nil
|
||||
end
|
||||
end
|
||||
privRefresh(true)
|
||||
end
|
||||
|
||||
def z=(value)
|
||||
@z=value
|
||||
privRefresh
|
||||
end
|
||||
|
||||
def disposed?
|
||||
return @disposed
|
||||
end
|
||||
|
||||
def contents=(value)
|
||||
if @contents!=value
|
||||
@contents=value
|
||||
privRefresh if @visible
|
||||
end
|
||||
end
|
||||
|
||||
def ox=(value)
|
||||
if @ox!=value
|
||||
@ox=value
|
||||
privRefresh if @visible
|
||||
end
|
||||
end
|
||||
|
||||
def oy=(value)
|
||||
if @oy!=value
|
||||
@oy=value
|
||||
privRefresh if @visible
|
||||
end
|
||||
end
|
||||
|
||||
def active=(value)
|
||||
@active=value
|
||||
privRefresh(true)
|
||||
end
|
||||
|
||||
def cursor_rect=(value)
|
||||
if !value
|
||||
@cursor_rect.empty
|
||||
else
|
||||
@cursor_rect.set(value.x,value.y,value.width,value.height)
|
||||
end
|
||||
end
|
||||
|
||||
def openness=(value)
|
||||
@openness=value
|
||||
@openness=0 if @openness<0
|
||||
@openness=255 if @openness>255
|
||||
privRefresh
|
||||
end
|
||||
|
||||
def width=(value)
|
||||
@width=value
|
||||
privRefresh(true)
|
||||
end
|
||||
|
||||
def height=(value)
|
||||
@height=value
|
||||
privRefresh(true)
|
||||
end
|
||||
|
||||
def pause=(value)
|
||||
@pause=value
|
||||
@pauseopacity=0 if !value
|
||||
privRefresh if @visible
|
||||
end
|
||||
|
||||
def x=(value)
|
||||
@x=value
|
||||
privRefresh if @visible
|
||||
end
|
||||
|
||||
def y=(value)
|
||||
@y=value
|
||||
privRefresh if @visible
|
||||
end
|
||||
|
||||
def zoom_x=(value)
|
||||
@zoom_x=value
|
||||
privRefresh if @visible
|
||||
end
|
||||
|
||||
def zoom_y=(value)
|
||||
@zoom_y=value
|
||||
privRefresh if @visible
|
||||
end
|
||||
|
||||
def offset_x=(value)
|
||||
@x=value
|
||||
privRefresh if @visible
|
||||
end
|
||||
|
||||
def offset_y=(value)
|
||||
@y=value
|
||||
privRefresh if @visible
|
||||
end
|
||||
|
||||
def opacity=(value)
|
||||
@opacity=value
|
||||
@opacity=0 if @opacity<0
|
||||
@opacity=255 if @opacity>255
|
||||
privRefresh if @visible
|
||||
end
|
||||
|
||||
def back_opacity=(value)
|
||||
@back_opacity=value
|
||||
@back_opacity=0 if @back_opacity<0
|
||||
@back_opacity=255 if @back_opacity>255
|
||||
privRefresh if @visible
|
||||
end
|
||||
|
||||
def contents_opacity=(value)
|
||||
@contents_opacity=value
|
||||
@contents_opacity=0 if @contents_opacity<0
|
||||
@contents_opacity=255 if @contents_opacity>255
|
||||
privRefresh if @visible
|
||||
end
|
||||
|
||||
def tone=(value)
|
||||
@tone=value
|
||||
privRefresh if @visible
|
||||
end
|
||||
|
||||
def color=(value)
|
||||
@color=value
|
||||
privRefresh if @visible
|
||||
end
|
||||
|
||||
def blend_type=(value)
|
||||
@blend_type=value
|
||||
privRefresh if @visible
|
||||
end
|
||||
|
||||
def flash(color,duration)
|
||||
return if disposed?
|
||||
@flash=duration+1
|
||||
for i in @sprites
|
||||
i[1].flash(color,duration)
|
||||
end
|
||||
end
|
||||
|
||||
def update
|
||||
return if disposed?
|
||||
mustchange=false
|
||||
if @active
|
||||
if @cursorblink==0
|
||||
@cursoropacity-=8
|
||||
@cursorblink=1 if @cursoropacity<=128
|
||||
else
|
||||
@cursoropacity+=8
|
||||
@cursorblink=0 if @cursoropacity>=255
|
||||
end
|
||||
privRefreshCursor
|
||||
else
|
||||
@cursoropacity=128
|
||||
privRefreshCursor
|
||||
end
|
||||
if @pause
|
||||
oldpauseframe=@pauseframe
|
||||
oldpauseopacity=@pauseopacity
|
||||
@pauseframe=(Graphics.frame_count / 8) % 4
|
||||
@pauseopacity=[@pauseopacity+64,255].min
|
||||
mustchange=@pauseframe!=oldpauseframe || @pauseopacity!=oldpauseopacity
|
||||
end
|
||||
privRefresh if mustchange
|
||||
if @flash>0
|
||||
for i in @sprites.values
|
||||
i.update
|
||||
end
|
||||
@flash-=1
|
||||
end
|
||||
end
|
||||
|
||||
#############
|
||||
attr_reader :skinformat
|
||||
attr_reader :skinrect
|
||||
|
||||
def loadSkinFile(_file)
|
||||
if (self.windowskin.width==80 || self.windowskin.width==96) &&
|
||||
self.windowskin.height==48
|
||||
# Body = X, Y, width, height of body rectangle within windowskin
|
||||
@skinrect.set(32,16,16,16)
|
||||
# Trim = X, Y, width, height of trim rectangle within windowskin
|
||||
@trim=[32,16,16,16]
|
||||
elsif self.windowskin.width==80 && self.windowskin.height==80
|
||||
@skinrect.set(32,32,16,16)
|
||||
@trim=[32,16,16,48]
|
||||
end
|
||||
end
|
||||
|
||||
def windowskin=(value)
|
||||
oldSkinWidth=(@_windowskin && !@_windowskin.disposed?) ? @_windowskin.width : -1
|
||||
oldSkinHeight=(@_windowskin && !@_windowskin.disposed?) ? @_windowskin.height : -1
|
||||
@_windowskin=value
|
||||
if @skinformat==1
|
||||
@rpgvx=false
|
||||
if @_windowskin && !@_windowskin.disposed?
|
||||
if @_windowskin.width!=oldSkinWidth || @_windowskin.height!=oldSkinHeight
|
||||
# Update skinrect and trim if windowskin's dimensions have changed
|
||||
@skinrect.set((@_windowskin.width-16)/2,(@_windowskin.height-16)/2,16,16)
|
||||
@trim=[@skinrect.x,@skinrect.y,@skinrect.x,@skinrect.y]
|
||||
end
|
||||
else
|
||||
@skinrect.set(16,16,16,16)
|
||||
@trim=[16,16,16,16]
|
||||
end
|
||||
else
|
||||
if value && value.is_a?(Bitmap) && !value.disposed? && value.width==128
|
||||
@rpgvx=true
|
||||
else
|
||||
@rpgvx=false
|
||||
end
|
||||
@trim=[16,16,16,16]
|
||||
end
|
||||
privRefresh(true)
|
||||
end
|
||||
|
||||
def skinrect=(value)
|
||||
@skinrect=value
|
||||
privRefresh
|
||||
end
|
||||
|
||||
def skinformat=(value)
|
||||
if @skinformat!=value
|
||||
@skinformat=value
|
||||
privRefresh(true)
|
||||
end
|
||||
end
|
||||
|
||||
def borderX
|
||||
return 32 if !@trim || skinformat==0
|
||||
if @_windowskin && !@_windowskin.disposed?
|
||||
return @trim[0]+(@_windowskin.width-@trim[2]-@trim[0])
|
||||
end
|
||||
return 32
|
||||
end
|
||||
|
||||
def borderY
|
||||
return 32 if !@trim || skinformat==0
|
||||
if @_windowskin && !@_windowskin.disposed?
|
||||
return @trim[1]+(@_windowskin.height-@trim[3]-@trim[1])
|
||||
end
|
||||
return 32
|
||||
end
|
||||
|
||||
def leftEdge; self.startX; end
|
||||
def topEdge; self.startY; end
|
||||
def rightEdge; self.borderX-self.leftEdge; end
|
||||
def bottomEdge; self.borderY-self.topEdge; end
|
||||
|
||||
def startX
|
||||
return !@trim || skinformat==0 ? 16 : @trim[0]
|
||||
end
|
||||
|
||||
def startY
|
||||
return !@trim || skinformat==0 ? 16 : @trim[1]
|
||||
end
|
||||
|
||||
def endX
|
||||
return !@trim || skinformat==0 ? 16 : @trim[2]
|
||||
end
|
||||
|
||||
def endY
|
||||
return !@trim || skinformat==0 ? 16 : @trim[3]
|
||||
end
|
||||
|
||||
def startX=(value)
|
||||
@trim[0]=value
|
||||
privRefresh
|
||||
end
|
||||
|
||||
def startY=(value)
|
||||
@trim[1]=value
|
||||
privRefresh
|
||||
end
|
||||
|
||||
def endX=(value)
|
||||
@trim[2]=value
|
||||
privRefresh
|
||||
end
|
||||
|
||||
def endY=(value)
|
||||
@trim[3]=value
|
||||
privRefresh
|
||||
end
|
||||
|
||||
#############
|
||||
private
|
||||
|
||||
def ensureBitmap(bitmap,dwidth,dheight)
|
||||
if !bitmap||bitmap.disposed?||bitmap.width<dwidth||bitmap.height<dheight
|
||||
bitmap.dispose if bitmap
|
||||
bitmap=Bitmap.new([1,dwidth].max,[1,dheight].max)
|
||||
end
|
||||
return bitmap
|
||||
end
|
||||
|
||||
def tileBitmap(dstbitmap,dstrect,srcbitmap,srcrect)
|
||||
return if !srcbitmap || srcbitmap.disposed?
|
||||
left=dstrect.x
|
||||
top=dstrect.y
|
||||
y=0;loop do break unless y<dstrect.height
|
||||
x=0;loop do break unless x<dstrect.width
|
||||
dstbitmap.blt(x+left,y+top,srcbitmap,srcrect)
|
||||
x+=srcrect.width
|
||||
end
|
||||
y+=srcrect.height
|
||||
end
|
||||
end
|
||||
|
||||
def privRefreshCursor
|
||||
contopac=self.contents_opacity
|
||||
cursoropac=@cursoropacity*contopac/255
|
||||
@sprites["cursor"].opacity=cursoropac
|
||||
end
|
||||
|
||||
def privRefresh(changeBitmap=false)
|
||||
return if !self || self.disposed?
|
||||
backopac=self.back_opacity*self.opacity/255
|
||||
contopac=self.contents_opacity
|
||||
cursoropac=@cursoropacity*contopac/255
|
||||
haveskin=@_windowskin && !@_windowskin.disposed?
|
||||
for i in 0...4
|
||||
@sprites["corner#{i}"].bitmap=@_windowskin
|
||||
@sprites["scroll#{i}"].bitmap=@_windowskin
|
||||
end
|
||||
@sprites["pause"].bitmap=@_windowskin
|
||||
@sprites["contents"].bitmap=@contents
|
||||
if haveskin
|
||||
for i in 0...4
|
||||
@sprites["corner#{i}"].opacity=@opacity
|
||||
@sprites["corner#{i}"].tone=@tone
|
||||
@sprites["corner#{i}"].color=@color
|
||||
@sprites["corner#{i}"].visible=@visible
|
||||
@sprites["corner#{i}"].blend_type=@blend_type
|
||||
@sprites["side#{i}"].opacity=@opacity
|
||||
@sprites["side#{i}"].tone=@tone
|
||||
@sprites["side#{i}"].color=@color
|
||||
@sprites["side#{i}"].blend_type=@blend_type
|
||||
@sprites["side#{i}"].visible=@visible
|
||||
@sprites["scroll#{i}"].opacity=@opacity
|
||||
@sprites["scroll#{i}"].tone=@tone
|
||||
@sprites["scroll#{i}"].color=@color
|
||||
@sprites["scroll#{i}"].visible=@visible
|
||||
@sprites["scroll#{i}"].blend_type=@blend_type
|
||||
end
|
||||
for i in ["back","cursor","pause","contents"]
|
||||
@sprites[i].color=@color
|
||||
@sprites[i].tone=@tone
|
||||
@sprites[i].blend_type=@blend_type
|
||||
end
|
||||
@sprites["contents"].blend_type=@contents_blend_type
|
||||
@sprites["back"].opacity=backopac
|
||||
@sprites["contents"].opacity=contopac
|
||||
@sprites["cursor"].opacity=cursoropac
|
||||
@sprites["pause"].opacity=@pauseopacity
|
||||
supported=(@skinformat==0)
|
||||
hascontents=(@contents && !@contents.disposed?)
|
||||
@sprites["back"].visible=@visible
|
||||
@sprites["contents"].visible=@visible && @openness==255
|
||||
@sprites["pause"].visible=supported && @visible && @pause &&
|
||||
(@combat & CompatBits::ShowPause)
|
||||
@sprites["cursor"].visible=supported && @visible && @openness==255 &&
|
||||
(@combat & CompatBits::ShowCursor)
|
||||
@sprites["scroll0"].visible = false
|
||||
@sprites["scroll1"].visible = false
|
||||
@sprites["scroll2"].visible = false
|
||||
@sprites["scroll3"].visible = false
|
||||
else
|
||||
for i in 0...4
|
||||
@sprites["corner#{i}"].visible=false
|
||||
@sprites["side#{i}"].visible=false
|
||||
@sprites["scroll#{i}"].visible=false
|
||||
end
|
||||
@sprites["contents"].visible=@visible && @openness==255
|
||||
@sprites["contents"].color=@color
|
||||
@sprites["contents"].tone=@tone
|
||||
@sprites["contents"].blend_type=@contents_blend_type
|
||||
@sprites["contents"].opacity=contopac
|
||||
@sprites["back"].visible=false
|
||||
@sprites["pause"].visible=false
|
||||
@sprites["cursor"].visible=false
|
||||
end
|
||||
for i in @spritekeys
|
||||
@sprites[i].z=@z
|
||||
end
|
||||
if (@compat & CompatBits::CorrectZ)>0 && @skinformat==0 && !@rpgvx
|
||||
# Compatibility Mode: Cursor, pause, and contents have higher Z
|
||||
@sprites["cursor"].z=@z+1
|
||||
@sprites["contents"].z=@z+2
|
||||
@sprites["pause"].z=@z+2
|
||||
end
|
||||
if @skinformat==0
|
||||
startX=16
|
||||
startY=16
|
||||
endX=16
|
||||
endY=16
|
||||
trimStartX=16
|
||||
trimStartY=16
|
||||
trimWidth=32
|
||||
trimHeight=32
|
||||
if @rpgvx
|
||||
trimX=64
|
||||
trimY=0
|
||||
backRect=Rect.new(0,0,64,64)
|
||||
blindsRect=Rect.new(0,64,64,64)
|
||||
else
|
||||
trimX=128
|
||||
trimY=0
|
||||
backRect=Rect.new(0,0,128,128)
|
||||
blindsRect=nil
|
||||
end
|
||||
if @_windowskin && !@_windowskin.disposed?
|
||||
@sprites["corner0"].src_rect.set(trimX,trimY+0,16,16);
|
||||
@sprites["corner1"].src_rect.set(trimX+48,trimY+0,16,16);
|
||||
@sprites["corner2"].src_rect.set(trimX,trimY+48,16,16);
|
||||
@sprites["corner3"].src_rect.set(trimX+48,trimY+48,16,16);
|
||||
@sprites["scroll0"].src_rect.set(trimX+24, trimY+16, 16, 8) # up
|
||||
@sprites["scroll3"].src_rect.set(trimX+24, trimY+40, 16, 8) # down
|
||||
@sprites["scroll1"].src_rect.set(trimX+16, trimY+24, 8, 16) # left
|
||||
@sprites["scroll2"].src_rect.set(trimX+40, trimY+24, 8, 16) # right
|
||||
cursorX=trimX
|
||||
cursorY=trimY+64
|
||||
sideRects=[
|
||||
Rect.new(trimX+16,trimY+0,32,16),
|
||||
Rect.new(trimX,trimY+16,16,32),
|
||||
Rect.new(trimX+48,trimY+16,16,32),
|
||||
Rect.new(trimX+16,trimY+48,32,16)
|
||||
]
|
||||
pauseRects=[
|
||||
trimX+32,trimY+64,
|
||||
trimX+48,trimY+64,
|
||||
trimX+32,trimY+80,
|
||||
trimX+48,trimY+80,
|
||||
]
|
||||
pauseWidth=16
|
||||
pauseHeight=16
|
||||
@sprites["pause"].src_rect.set(
|
||||
pauseRects[@pauseframe*2],
|
||||
pauseRects[@pauseframe*2+1],
|
||||
pauseWidth,pauseHeight
|
||||
)
|
||||
end
|
||||
else
|
||||
trimStartX=@trim[0]
|
||||
trimStartY=@trim[1]
|
||||
trimWidth=@trim[0]+(@skinrect.width-@trim[2]+@trim[0])
|
||||
trimHeight=@trim[1]+(@skinrect.height-@trim[3]+@trim[1])
|
||||
if @_windowskin && !@_windowskin.disposed?
|
||||
# width of left end of window
|
||||
startX=@skinrect.x
|
||||
# width of top end of window
|
||||
startY=@skinrect.y
|
||||
cx=@skinrect.x+@skinrect.width # right side of BODY rect
|
||||
cy=@skinrect.y+@skinrect.height # bottom side of BODY rect
|
||||
# width of right end of window
|
||||
endX=(!@_windowskin || @_windowskin.disposed?) ? @skinrect.x : @_windowskin.width-cx
|
||||
# height of bottom end of window
|
||||
endY=(!@_windowskin || @_windowskin.disposed?) ? @skinrect.y : @_windowskin.height-cy
|
||||
@sprites["corner0"].src_rect.set(0,0,startX,startY);
|
||||
@sprites["corner1"].src_rect.set(cx,0,endX,startY);
|
||||
@sprites["corner2"].src_rect.set(0,cy,startX,endY);
|
||||
@sprites["corner3"].src_rect.set(cx,cy,endX,endY);
|
||||
backRect=Rect.new(@skinrect.x,@skinrect.y,
|
||||
@skinrect.width,@skinrect.height);
|
||||
blindsRect=nil
|
||||
sideRects=[
|
||||
Rect.new(startX,0,@skinrect.width,startY), # side0 (top)
|
||||
Rect.new(0,startY,startX,@skinrect.height), # side1 (left)
|
||||
Rect.new(cx,startY,endX,@skinrect.height), # side2 (right)
|
||||
Rect.new(startX,cy,@skinrect.width,endY) # side3 (bottom)
|
||||
]
|
||||
end
|
||||
end
|
||||
if @width>trimWidth && @height>trimHeight
|
||||
@sprites["contents"].src_rect.set(@ox,@oy,@width-trimWidth,@height-trimHeight)
|
||||
else
|
||||
@sprites["contents"].src_rect.set(0,0,0,0)
|
||||
end
|
||||
@sprites["contents"].x=@x+trimStartX
|
||||
@sprites["contents"].y=@y+trimStartY
|
||||
if (@compat & CompatBits::ShowScrollArrows)>0 && @skinformat==0
|
||||
# Compatibility mode: Make scroll arrows visible
|
||||
if @skinformat==0 && @_windowskin && !@_windowskin.disposed? &&
|
||||
@contents && !@contents.disposed?
|
||||
@sprites["scroll0"].visible = @visible && hascontents && @oy > 0
|
||||
@sprites["scroll1"].visible = @visible && hascontents && @ox > 0
|
||||
@sprites["scroll2"].visible = @visible && (@contents.width - @ox) > @width-trimWidth
|
||||
@sprites["scroll3"].visible = @visible && (@contents.height - @oy) > @height-trimHeight
|
||||
end
|
||||
end
|
||||
if @_windowskin && !@_windowskin.disposed?
|
||||
borderX=startX+endX
|
||||
borderY=startY+endY
|
||||
@sprites["corner0"].x=@x
|
||||
@sprites["corner0"].y=@y
|
||||
@sprites["corner1"].x=@x+@width-endX
|
||||
@sprites["corner1"].y=@y
|
||||
@sprites["corner2"].x=@x
|
||||
@sprites["corner2"].y=@y+@height-endY
|
||||
@sprites["corner3"].x=@x+@width-endX
|
||||
@sprites["corner3"].y=@y+@height-endY
|
||||
@sprites["side0"].x=@x+startX
|
||||
@sprites["side0"].y=@y
|
||||
@sprites["side1"].x=@x
|
||||
@sprites["side1"].y=@y+startY
|
||||
@sprites["side2"].x=@x+@width-endX
|
||||
@sprites["side2"].y=@y+startY
|
||||
@sprites["side3"].x=@x+startX
|
||||
@sprites["side3"].y=@y+@height-endY
|
||||
@sprites["scroll0"].x = @x+@width / 2 - 8
|
||||
@sprites["scroll0"].y = @y+8
|
||||
@sprites["scroll1"].x = @x+8
|
||||
@sprites["scroll1"].y = @y+@height / 2 - 8
|
||||
@sprites["scroll2"].x = @x+@width - 16
|
||||
@sprites["scroll2"].y = @y+@height / 2 - 8
|
||||
@sprites["scroll3"].x = @x+@width / 2 - 8
|
||||
@sprites["scroll3"].y = @y+@height - 16
|
||||
@sprites["cursor"].x=@x+startX+@cursor_rect.x
|
||||
@sprites["cursor"].y=@y+startY+@cursor_rect.y
|
||||
if (@compat & CompatBits::ExpandBack)>0 && @skinformat==0
|
||||
# Compatibility mode: Expand background
|
||||
@sprites["back"].x=@x+2
|
||||
@sprites["back"].y=@y+2
|
||||
else
|
||||
@sprites["back"].x=@x+startX
|
||||
@sprites["back"].y=@y+startY
|
||||
end
|
||||
end
|
||||
if changeBitmap && @_windowskin && !@_windowskin.disposed?
|
||||
if @skinformat==0
|
||||
@sprites["cursor"].x=@x+startX+@cursor_rect.x
|
||||
@sprites["cursor"].y=@y+startY+@cursor_rect.y
|
||||
width=@cursor_rect.width
|
||||
height=@cursor_rect.height
|
||||
if width > 0 && height > 0
|
||||
cursorrects=[
|
||||
# sides
|
||||
Rect.new(cursorX+2, cursorY+0, 28, 2),
|
||||
Rect.new(cursorX+0, cursorY+2, 2, 28),
|
||||
Rect.new(cursorX+30, cursorY+2, 2, 28),
|
||||
Rect.new(cursorX+2, cursorY+30, 28, 2),
|
||||
# corners
|
||||
Rect.new(cursorX+0, cursorY+0, 2, 2),
|
||||
Rect.new(cursorX+30, cursorY+0, 2, 2),
|
||||
Rect.new(cursorX+0, cursorY+30, 2, 2),
|
||||
Rect.new(cursorX+30, cursorY+30, 2, 2),
|
||||
# back
|
||||
Rect.new(cursorX+2, cursorY+2, 28, 28)
|
||||
]
|
||||
margin=2
|
||||
fullmargin=4
|
||||
@cursorbitmap = ensureBitmap(@cursorbitmap, width, height)
|
||||
@cursorbitmap.clear
|
||||
@sprites["cursor"].bitmap=@cursorbitmap
|
||||
@sprites["cursor"].src_rect.set(0,0,width,height)
|
||||
rect = Rect.new(margin,margin,width - fullmargin, height - fullmargin)
|
||||
@cursorbitmap.stretch_blt(rect, @_windowskin, cursorrects[8])
|
||||
@cursorbitmap.blt(0, 0, @_windowskin, cursorrects[4])# top left
|
||||
@cursorbitmap.blt(width-margin, 0, @_windowskin, cursorrects[5]) # top right
|
||||
@cursorbitmap.blt(0, height-margin, @_windowskin, cursorrects[6]) # bottom right
|
||||
@cursorbitmap.blt(width-margin, height-margin, @_windowskin, cursorrects[7]) # bottom left
|
||||
rect = Rect.new(margin, 0,width - fullmargin, margin)
|
||||
@cursorbitmap.stretch_blt(rect, @_windowskin, cursorrects[0])
|
||||
rect = Rect.new(0, margin,margin, height - fullmargin)
|
||||
@cursorbitmap.stretch_blt(rect, @_windowskin, cursorrects[1])
|
||||
rect = Rect.new(width - margin, margin, margin, height - fullmargin)
|
||||
@cursorbitmap.stretch_blt(rect, @_windowskin, cursorrects[2])
|
||||
rect = Rect.new(margin, height-margin, width - fullmargin, margin)
|
||||
@cursorbitmap.stretch_blt(rect, @_windowskin, cursorrects[3])
|
||||
else
|
||||
@sprites["cursor"].visible=false
|
||||
@sprites["cursor"].src_rect.set(0,0,0,0)
|
||||
end
|
||||
end
|
||||
for i in 0..3
|
||||
case i
|
||||
when 0
|
||||
dwidth = @width-startX-endX
|
||||
dheight = startY
|
||||
when 1
|
||||
dwidth = startX
|
||||
dheight = @height-startY-endY
|
||||
when 2
|
||||
dwidth = endX
|
||||
dheight = @height-startY-endY
|
||||
when 3
|
||||
dwidth = @width-startX-endX
|
||||
dheight = endY
|
||||
end
|
||||
@sidebitmaps[i]=ensureBitmap(@sidebitmaps[i],dwidth,dheight)
|
||||
@sprites["side#{i}"].bitmap=@sidebitmaps[i]
|
||||
@sprites["side#{i}"].src_rect.set(0,0,dwidth,dheight)
|
||||
@sidebitmaps[i].clear
|
||||
if sideRects[i].width>0 && sideRects[i].height>0
|
||||
if (@compat & CompatBits::StretchSides)>0 && @skinformat==0
|
||||
# Compatibility mode: Stretch sides
|
||||
@sidebitmaps[i].stretch_blt(@sprites["side#{i}"].src_rect,
|
||||
@_windowskin,sideRects[i])
|
||||
else
|
||||
tileBitmap(@sidebitmaps[i],@sprites["side#{i}"].src_rect,
|
||||
@_windowskin,sideRects[i])
|
||||
end
|
||||
end
|
||||
end
|
||||
if (@compat & CompatBits::ExpandBack)>0 && @skinformat==0
|
||||
# Compatibility mode: Expand background
|
||||
backwidth=@width-4
|
||||
backheight=@height-4
|
||||
else
|
||||
backwidth=@width-borderX
|
||||
backheight=@height-borderY
|
||||
end
|
||||
if backwidth>0 && backheight>0
|
||||
@backbitmap=ensureBitmap(@backbitmap,backwidth,backheight)
|
||||
@sprites["back"].bitmap=@backbitmap
|
||||
@sprites["back"].src_rect.set(0,0,backwidth,backheight)
|
||||
@backbitmap.clear
|
||||
if @stretch
|
||||
@backbitmap.stretch_blt(@sprites["back"].src_rect,@_windowskin,backRect)
|
||||
else
|
||||
tileBitmap(@backbitmap,@sprites["back"].src_rect,@_windowskin,backRect)
|
||||
end
|
||||
if blindsRect
|
||||
tileBitmap(@backbitmap,@sprites["back"].src_rect,@_windowskin,blindsRect)
|
||||
end
|
||||
else
|
||||
@sprites["back"].visible=false
|
||||
@sprites["back"].src_rect.set(0,0,0,0)
|
||||
end
|
||||
end
|
||||
if @openness!=255
|
||||
opn=@openness/255.0
|
||||
for k in @spritekeys
|
||||
sprite=@sprites[k]
|
||||
ratio=(@height<=0) ? 0 : (sprite.y-@y)*1.0/@height
|
||||
sprite.zoom_y=opn
|
||||
sprite.zoom_x=1.0
|
||||
sprite.oy=0
|
||||
sprite.y=(@y+(@height/2.0)+(@height*ratio*opn)-(@height/2*opn)).floor
|
||||
end
|
||||
else
|
||||
for k in @spritekeys
|
||||
sprite=@sprites[k]
|
||||
sprite.zoom_x=1.0
|
||||
sprite.zoom_y=1.0
|
||||
end
|
||||
end
|
||||
i=0
|
||||
# Ensure Z order
|
||||
for k in @spritekeys
|
||||
sprite=@sprites[k]
|
||||
y=sprite.y
|
||||
sprite.y=i
|
||||
sprite.oy=(sprite.zoom_y<=0) ? 0 : (i-y)/sprite.zoom_y
|
||||
sprite.zoom_x*=@zoom_x
|
||||
sprite.zoom_y*=@zoom_y
|
||||
sprite.x*=@zoom_x
|
||||
sprite.y*=@zoom_y
|
||||
sprite.x+=(@offset_x/sprite.zoom_x)
|
||||
sprite.y+=(@offset_y/sprite.zoom_y)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
|
||||
#===============================================================================
|
||||
#
|
||||
#===============================================================================
|
||||
class SpriteWindow_Base < SpriteWindow
|
||||
TEXTPADDING=4 # In pixels
|
||||
|
||||
def initialize(x, y, width, height)
|
||||
super()
|
||||
self.x = x
|
||||
self.y = y
|
||||
self.width = width
|
||||
self.height = height
|
||||
self.z = 100
|
||||
@curframe=MessageConfig.pbGetSystemFrame()
|
||||
@curfont=MessageConfig.pbGetSystemFontName()
|
||||
@sysframe=AnimatedBitmap.new(@curframe)
|
||||
RPG::Cache.retain(@curframe) if @curframe && !@curframe.empty?
|
||||
@customskin=nil
|
||||
__setWindowskin(@sysframe.bitmap)
|
||||
__resolveSystemFrame()
|
||||
pbSetSystemFont(self.contents) if self.contents
|
||||
end
|
||||
|
||||
def __setWindowskin(skin)
|
||||
if skin && (skin.width==192 && skin.height==128) || # RPGXP Windowskin
|
||||
(skin.width==128 && skin.height==128) # RPGVX Windowskin
|
||||
self.skinformat=0
|
||||
else
|
||||
self.skinformat=1
|
||||
end
|
||||
self.windowskin=skin
|
||||
end
|
||||
|
||||
def __resolveSystemFrame
|
||||
if self.skinformat==1
|
||||
if !@resolvedFrame
|
||||
@resolvedFrame=MessageConfig.pbGetSystemFrame()
|
||||
@resolvedFrame.sub!(/\.[^\.\/\\]+$/,"")
|
||||
end
|
||||
self.loadSkinFile("#{@resolvedFrame}.txt") if @resolvedFrame!=""
|
||||
end
|
||||
end
|
||||
|
||||
def setSkin(skin) # Filename of windowskin to apply. Supports XP, VX, and animated skins.
|
||||
@customskin.dispose if @customskin
|
||||
@customskin=nil
|
||||
resolvedName=pbResolveBitmap(skin)
|
||||
return if nil_or_empty?(resolvedName)
|
||||
@customskin=AnimatedBitmap.new(resolvedName)
|
||||
RPG::Cache.retain(resolvedName)
|
||||
__setWindowskin(@customskin.bitmap)
|
||||
if self.skinformat==1
|
||||
skinbase=resolvedName.sub(/\.[^\.\/\\]+$/,"")
|
||||
self.loadSkinFile("#{skinbase}.txt")
|
||||
end
|
||||
end
|
||||
|
||||
def setSystemFrame
|
||||
@customskin.dispose if @customskin
|
||||
@customskin=nil
|
||||
__setWindowskin(@sysframe.bitmap)
|
||||
__resolveSystemFrame()
|
||||
end
|
||||
|
||||
def update
|
||||
super
|
||||
if self.windowskin
|
||||
if @customskin
|
||||
if @customskin.totalFrames>1
|
||||
@customskin.update
|
||||
__setWindowskin(@customskin.bitmap)
|
||||
end
|
||||
elsif @sysframe
|
||||
if @sysframe.totalFrames>1
|
||||
@sysframe.update
|
||||
__setWindowskin(@sysframe.bitmap)
|
||||
end
|
||||
end
|
||||
end
|
||||
if @curframe!=MessageConfig.pbGetSystemFrame()
|
||||
@curframe=MessageConfig.pbGetSystemFrame()
|
||||
if @sysframe && !@customskin
|
||||
@sysframe.dispose if @sysframe
|
||||
@sysframe=AnimatedBitmap.new(@curframe)
|
||||
RPG::Cache.retain(@curframe) if @curframe && !@curframe.empty?
|
||||
@resolvedFrame=nil
|
||||
__setWindowskin(@sysframe.bitmap)
|
||||
__resolveSystemFrame()
|
||||
end
|
||||
begin
|
||||
refresh
|
||||
rescue NoMethodError
|
||||
end
|
||||
end
|
||||
if @curfont!=MessageConfig.pbGetSystemFontName()
|
||||
@curfont=MessageConfig.pbGetSystemFontName()
|
||||
if self.contents && !self.contents.disposed?
|
||||
pbSetSystemFont(self.contents)
|
||||
end
|
||||
begin
|
||||
refresh
|
||||
rescue NoMethodError
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def dispose
|
||||
self.contents.dispose if self.contents
|
||||
@sysframe.dispose
|
||||
@customskin.dispose if @customskin
|
||||
super
|
||||
end
|
||||
end
|
||||
1401
Data/Scripts/007_Objects and windows/005_SpriteWindow_text.rb
Normal file
1401
Data/Scripts/007_Objects and windows/005_SpriteWindow_text.rb
Normal file
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,123 @@
|
||||
#===============================================================================
|
||||
# Displays an icon bitmap in a window. Supports animated images.
|
||||
#===============================================================================
|
||||
class IconWindow < SpriteWindow_Base
|
||||
attr_reader :name
|
||||
|
||||
def initialize(x,y,width,height,viewport=nil)
|
||||
super(x,y,width,height)
|
||||
self.viewport=viewport
|
||||
self.contents=nil
|
||||
@name=""
|
||||
@_iconbitmap=nil
|
||||
end
|
||||
|
||||
def dispose
|
||||
clearBitmaps()
|
||||
super
|
||||
end
|
||||
|
||||
def update
|
||||
super
|
||||
if @_iconbitmap
|
||||
@_iconbitmap.update
|
||||
self.contents=@_iconbitmap.bitmap
|
||||
end
|
||||
end
|
||||
|
||||
def clearBitmaps
|
||||
@_iconbitmap.dispose if @_iconbitmap
|
||||
@_iconbitmap=nil
|
||||
self.contents=nil if !self.disposed?
|
||||
end
|
||||
|
||||
# Sets the icon's filename. Alias for setBitmap.
|
||||
def name=(value)
|
||||
setBitmap(value)
|
||||
end
|
||||
|
||||
# Sets the icon's filename.
|
||||
def setBitmap(file,hue=0)
|
||||
clearBitmaps()
|
||||
@name=file
|
||||
return if file==nil
|
||||
if file!=""
|
||||
@_iconbitmap=AnimatedBitmap.new(file,hue)
|
||||
# for compatibility
|
||||
self.contents=@_iconbitmap ? @_iconbitmap.bitmap : nil
|
||||
else
|
||||
@_iconbitmap=nil
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
|
||||
#===============================================================================
|
||||
# Displays an icon bitmap in a window. Supports animated images.
|
||||
# Accepts bitmaps and paths to bitmap files in its constructor.
|
||||
#===============================================================================
|
||||
class PictureWindow < SpriteWindow_Base
|
||||
def initialize(pathOrBitmap)
|
||||
super(0,0,32,32)
|
||||
self.viewport=viewport
|
||||
self.contents=nil
|
||||
@_iconbitmap=nil
|
||||
setBitmap(pathOrBitmap)
|
||||
end
|
||||
|
||||
def picture; @_iconbitmap; end
|
||||
|
||||
def dispose
|
||||
clearBitmaps()
|
||||
super
|
||||
end
|
||||
|
||||
def update
|
||||
super
|
||||
if @_iconbitmap
|
||||
if @_iconbitmap.is_a?(Bitmap)
|
||||
self.contents=@_iconbitmap
|
||||
else
|
||||
@_iconbitmap.update
|
||||
self.contents=@_iconbitmap.bitmap
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def clearBitmaps
|
||||
@_iconbitmap.dispose if @_iconbitmap
|
||||
@_iconbitmap=nil
|
||||
self.contents=nil if !self.disposed?
|
||||
end
|
||||
|
||||
# Sets the icon's bitmap or filename. (hue parameter
|
||||
# is ignored unless pathOrBitmap is a filename)
|
||||
def setBitmap(pathOrBitmap,hue=0)
|
||||
clearBitmaps()
|
||||
if pathOrBitmap!=nil && pathOrBitmap!=""
|
||||
if pathOrBitmap.is_a?(Bitmap)
|
||||
@_iconbitmap=pathOrBitmap
|
||||
self.contents=@_iconbitmap
|
||||
self.width=@_iconbitmap.width+self.borderX
|
||||
self.height=@_iconbitmap.height+self.borderY
|
||||
elsif pathOrBitmap.is_a?(AnimatedBitmap)
|
||||
@_iconbitmap=pathOrBitmap
|
||||
self.contents=@_iconbitmap.bitmap
|
||||
self.width=@_iconbitmap.bitmap.width+self.borderX
|
||||
self.height=@_iconbitmap.bitmap.height+self.borderY
|
||||
else
|
||||
@_iconbitmap=AnimatedBitmap.new(pathOrBitmap,hue)
|
||||
self.contents=@_iconbitmap ? @_iconbitmap.bitmap : nil
|
||||
self.width=@_iconbitmap ? @_iconbitmap.bitmap.width+self.borderX :
|
||||
32+self.borderX
|
||||
self.height=@_iconbitmap ? @_iconbitmap.bitmap.height+self.borderY :
|
||||
32+self.borderY
|
||||
end
|
||||
else
|
||||
@_iconbitmap=nil
|
||||
self.width=32+self.borderX
|
||||
self.height=32+self.borderY
|
||||
end
|
||||
end
|
||||
end
|
||||
496
Data/Scripts/007_Objects and windows/007_SpriteWrapper.rb
Normal file
496
Data/Scripts/007_Objects and windows/007_SpriteWrapper.rb
Normal file
@@ -0,0 +1,496 @@
|
||||
#===============================================================================
|
||||
# SpriteWrapper is a class which wraps (most of) Sprite's properties.
|
||||
#===============================================================================
|
||||
class SpriteWrapper
|
||||
def initialize(viewport = nil)
|
||||
@sprite = Sprite.new(viewport)
|
||||
end
|
||||
|
||||
def dispose
|
||||
@sprite.dispose;
|
||||
end
|
||||
|
||||
def disposed?
|
||||
return @sprite.disposed?;
|
||||
end
|
||||
|
||||
def viewport
|
||||
return @sprite.viewport;
|
||||
end
|
||||
|
||||
def flash(color, duration)
|
||||
; return @sprite.flash(color, duration);
|
||||
end
|
||||
|
||||
def update
|
||||
return @sprite.update;
|
||||
end
|
||||
|
||||
def x
|
||||
@sprite.x;
|
||||
end
|
||||
|
||||
def x=(value)
|
||||
; @sprite.x = value;
|
||||
end
|
||||
|
||||
def y
|
||||
@sprite.y;
|
||||
end
|
||||
|
||||
def y=(value)
|
||||
; @sprite.y = value;
|
||||
end
|
||||
|
||||
def bitmap
|
||||
@sprite.bitmap;
|
||||
end
|
||||
|
||||
def bitmap=(value)
|
||||
; @sprite.bitmap = value;
|
||||
end
|
||||
|
||||
def src_rect
|
||||
@sprite.src_rect;
|
||||
end
|
||||
|
||||
def src_rect=(value)
|
||||
; @sprite.src_rect = value;
|
||||
end
|
||||
|
||||
def visible
|
||||
@sprite.visible;
|
||||
end
|
||||
|
||||
def visible=(value)
|
||||
; @sprite.visible = value;
|
||||
end
|
||||
|
||||
def z
|
||||
@sprite.z;
|
||||
end
|
||||
|
||||
def z=(value)
|
||||
; @sprite.z = value;
|
||||
end
|
||||
|
||||
def ox
|
||||
@sprite.ox;
|
||||
end
|
||||
|
||||
def ox=(value)
|
||||
; @sprite.ox = value;
|
||||
end
|
||||
|
||||
def oy
|
||||
@sprite.oy;
|
||||
end
|
||||
|
||||
def oy=(value)
|
||||
; @sprite.oy = value;
|
||||
end
|
||||
|
||||
def zoom_x
|
||||
@sprite.zoom_x;
|
||||
end
|
||||
|
||||
def zoom_x=(value)
|
||||
; @sprite.zoom_x = value;
|
||||
end
|
||||
|
||||
def zoom_y
|
||||
@sprite.zoom_y;
|
||||
end
|
||||
|
||||
def zoom_y=(value)
|
||||
; @sprite.zoom_y = value;
|
||||
end
|
||||
|
||||
def angle
|
||||
@sprite.angle;
|
||||
end
|
||||
|
||||
def angle=(value)
|
||||
; @sprite.angle = value;
|
||||
end
|
||||
|
||||
def mirror
|
||||
@sprite.mirror;
|
||||
end
|
||||
|
||||
def mirror=(value)
|
||||
; @sprite.mirror = value;
|
||||
end
|
||||
|
||||
def bush_depth
|
||||
@sprite.bush_depth;
|
||||
end
|
||||
|
||||
def bush_depth=(value)
|
||||
; @sprite.bush_depth = value;
|
||||
end
|
||||
|
||||
def opacity
|
||||
@sprite.opacity;
|
||||
end
|
||||
|
||||
def opacity=(value)
|
||||
; @sprite.opacity = value;
|
||||
end
|
||||
|
||||
def blend_type
|
||||
@sprite.blend_type;
|
||||
end
|
||||
|
||||
def blend_type=(value)
|
||||
; @sprite.blend_type = value;
|
||||
end
|
||||
|
||||
def color
|
||||
@sprite.color;
|
||||
end
|
||||
|
||||
def color=(value)
|
||||
; @sprite.color = value;
|
||||
end
|
||||
|
||||
def tone
|
||||
@sprite.tone;
|
||||
end
|
||||
|
||||
def tone=(value)
|
||||
; @sprite.tone = value;
|
||||
end
|
||||
|
||||
def viewport=(value)
|
||||
return if self.viewport == value
|
||||
bitmap = @sprite.bitmap
|
||||
src_rect = @sprite.src_rect
|
||||
visible = @sprite.visible
|
||||
x = @sprite.x
|
||||
y = @sprite.y
|
||||
z = @sprite.z
|
||||
ox = @sprite.ox
|
||||
oy = @sprite.oy
|
||||
zoom_x = @sprite.zoom_x
|
||||
zoom_y = @sprite.zoom_y
|
||||
angle = @sprite.angle
|
||||
mirror = @sprite.mirror
|
||||
bush_depth = @sprite.bush_depth
|
||||
opacity = @sprite.opacity
|
||||
blend_type = @sprite.blend_type
|
||||
color = @sprite.color
|
||||
tone = @sprite.tone
|
||||
@sprite.dispose
|
||||
@sprite = Sprite.new(value)
|
||||
@sprite.bitmap = bitmap
|
||||
@sprite.src_rect = src_rect
|
||||
@sprite.visible = visible
|
||||
@sprite.x = x
|
||||
@sprite.y = y
|
||||
@sprite.z = z
|
||||
@sprite.ox = ox
|
||||
@sprite.oy = oy
|
||||
@sprite.zoom_x = zoom_x
|
||||
@sprite.zoom_y = zoom_y
|
||||
@sprite.angle = angle
|
||||
@sprite.mirror = mirror
|
||||
@sprite.bush_depth = bush_depth
|
||||
@sprite.opacity = opacity
|
||||
@sprite.blend_type = blend_type
|
||||
@sprite.color = color
|
||||
@sprite.tone = tone
|
||||
end
|
||||
end
|
||||
|
||||
#===============================================================================
|
||||
# Sprite class that maintains a bitmap of its own.
|
||||
# This bitmap can't be changed to a different one.
|
||||
#===============================================================================
|
||||
class BitmapSprite < SpriteWrapper
|
||||
def initialize(width, height, viewport = nil)
|
||||
super(viewport)
|
||||
self.bitmap = Bitmap.new(width, height)
|
||||
@initialized = true
|
||||
end
|
||||
|
||||
def bitmap=(value)
|
||||
super(value) if !@initialized
|
||||
end
|
||||
|
||||
def dispose
|
||||
self.bitmap.dispose if !self.disposed?
|
||||
super
|
||||
end
|
||||
end
|
||||
|
||||
#===============================================================================
|
||||
#
|
||||
#===============================================================================
|
||||
class AnimatedSprite < SpriteWrapper
|
||||
attr_reader :frame
|
||||
attr_reader :framewidth
|
||||
attr_reader :frameheight
|
||||
attr_reader :framecount
|
||||
attr_reader :animname
|
||||
attr_reader :playing
|
||||
|
||||
def initializeLong(animname, framecount, framewidth, frameheight, frameskip)
|
||||
@animname = pbBitmapName(animname)
|
||||
@realframes = 0
|
||||
@frameskip = [1, frameskip].max
|
||||
@frameskip *= Graphics.frame_rate / 20
|
||||
raise _INTL("Frame width is 0") if framewidth == 0
|
||||
raise _INTL("Frame height is 0") if frameheight == 0
|
||||
begin
|
||||
@animbitmap = AnimatedBitmap.new(animname).deanimate
|
||||
rescue
|
||||
@animbitmap = Bitmap.new(framewidth, frameheight)
|
||||
end
|
||||
if @animbitmap.width % framewidth != 0
|
||||
raise _INTL("Bitmap's width ({1}) is not a multiple of frame width ({2}) [Bitmap={3}]",
|
||||
@animbitmap.width, framewidth, animname)
|
||||
end
|
||||
if @animbitmap.height % frameheight != 0
|
||||
raise _INTL("Bitmap's height ({1}) is not a multiple of frame height ({2}) [Bitmap={3}]",
|
||||
@animbitmap.height, frameheight, animname)
|
||||
end
|
||||
@framecount = framecount
|
||||
@framewidth = framewidth
|
||||
@frameheight = frameheight
|
||||
@framesperrow = @animbitmap.width / @framewidth
|
||||
@playing = false
|
||||
self.bitmap = @animbitmap
|
||||
self.src_rect.width = @framewidth
|
||||
self.src_rect.height = @frameheight
|
||||
self.frame = 0
|
||||
end
|
||||
|
||||
# Shorter version of AnimationSprite. All frames are placed on a single row
|
||||
# of the bitmap, so that the width and height need not be defined beforehand
|
||||
def initializeShort(animname, framecount, frameskip)
|
||||
@animname = pbBitmapName(animname)
|
||||
@realframes = 0
|
||||
@frameskip = [1, frameskip].max
|
||||
@frameskip *= Graphics.frame_rate / 20
|
||||
begin
|
||||
@animbitmap = AnimatedBitmap.new(animname).deanimate
|
||||
rescue
|
||||
@animbitmap = Bitmap.new(framecount * 4, 32)
|
||||
end
|
||||
if @animbitmap.width % framecount != 0
|
||||
raise _INTL("Bitmap's width ({1}) is not a multiple of frame count ({2}) [Bitmap={3}]",
|
||||
@animbitmap.width, framewidth, animname)
|
||||
end
|
||||
@framecount = framecount
|
||||
@framewidth = @animbitmap.width / @framecount
|
||||
@frameheight = @animbitmap.height
|
||||
@framesperrow = framecount
|
||||
@playing = false
|
||||
self.bitmap = @animbitmap
|
||||
self.src_rect.width = @framewidth
|
||||
self.src_rect.height = @frameheight
|
||||
self.frame = 0
|
||||
end
|
||||
|
||||
def initialize(*args)
|
||||
if args.length == 1
|
||||
super(args[0][3])
|
||||
initializeShort(args[0][0], args[0][1], args[0][2])
|
||||
else
|
||||
super(args[5])
|
||||
initializeLong(args[0], args[1], args[2], args[3], args[4])
|
||||
end
|
||||
end
|
||||
|
||||
def self.create(animname, framecount, frameskip, viewport = nil)
|
||||
return self.new([animname, framecount, frameskip, viewport])
|
||||
end
|
||||
|
||||
def dispose
|
||||
return if disposed?
|
||||
@animbitmap.dispose
|
||||
@animbitmap = nil
|
||||
super
|
||||
end
|
||||
|
||||
def playing?
|
||||
return @playing
|
||||
end
|
||||
|
||||
def frame=(value)
|
||||
@frame = value
|
||||
@realframes = 0
|
||||
self.src_rect.x = @frame % @framesperrow * @framewidth
|
||||
self.src_rect.y = @frame / @framesperrow * @frameheight
|
||||
end
|
||||
|
||||
def start
|
||||
@playing = true
|
||||
@realframes = 0
|
||||
end
|
||||
|
||||
alias play start
|
||||
|
||||
def stop
|
||||
@playing = false
|
||||
end
|
||||
|
||||
def reset
|
||||
@frame=0
|
||||
@realframes = 0
|
||||
end
|
||||
|
||||
def update
|
||||
super
|
||||
if @playing
|
||||
@realframes += 1
|
||||
if @realframes == @frameskip
|
||||
@realframes = 0
|
||||
self.frame += 1
|
||||
self.frame %= self.framecount
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
#===============================================================================
|
||||
# Displays an icon bitmap in a sprite. Supports animated images.
|
||||
#===============================================================================
|
||||
class IconSprite < SpriteWrapper
|
||||
attr_reader :name
|
||||
def initialize(*args)
|
||||
if args.length == 0
|
||||
super(nil)
|
||||
self.bitmap = nil
|
||||
elsif args.length == 1
|
||||
super(args[0])
|
||||
self.bitmap = nil
|
||||
elsif args.length == 2
|
||||
super(nil)
|
||||
self.x = args[0]
|
||||
self.y = args[1]
|
||||
else
|
||||
super(args[2])
|
||||
self.x = args[0]
|
||||
self.y = args[1]
|
||||
end
|
||||
@name = ""
|
||||
@_iconbitmap = nil
|
||||
end
|
||||
|
||||
def dispose
|
||||
clearBitmaps()
|
||||
super
|
||||
end
|
||||
|
||||
# Sets the icon's filename. Alias for setBitmap.
|
||||
def name=(value)
|
||||
setBitmap(value)
|
||||
end
|
||||
|
||||
def setBitmapDirectly(bitmap)
|
||||
oldrc = self.src_rect
|
||||
clearBitmaps()
|
||||
@name = ""
|
||||
return if bitmap == nil
|
||||
@_iconbitmap = bitmap
|
||||
# for compatibility
|
||||
#
|
||||
self.bitmap = @_iconbitmap ? @_iconbitmap.bitmap : nil
|
||||
self.src_rect = oldrc
|
||||
end
|
||||
|
||||
def setColor(r = 0, g = 0, b = 0, a = 255)
|
||||
@_iconbitmap.pbSetColor(r,g,b,a)
|
||||
end
|
||||
|
||||
# Sets the icon's filename.
|
||||
def setBitmap(file, hue = 0)
|
||||
oldrc = self.src_rect
|
||||
clearBitmaps()
|
||||
@name = file
|
||||
return if file == nil
|
||||
if file != ""
|
||||
@_iconbitmap = AnimatedBitmap.new(file, hue)
|
||||
# for compatibility
|
||||
self.bitmap = @_iconbitmap ? @_iconbitmap.bitmap : nil
|
||||
self.src_rect = oldrc
|
||||
else
|
||||
@_iconbitmap = nil
|
||||
end
|
||||
end
|
||||
|
||||
def getBitmap
|
||||
return @_iconbitmap
|
||||
end
|
||||
|
||||
def clearBitmaps
|
||||
@_iconbitmap.dispose if @_iconbitmap
|
||||
@_iconbitmap = nil
|
||||
self.bitmap = nil if !self.disposed?
|
||||
end
|
||||
|
||||
def update
|
||||
super
|
||||
return if !@_iconbitmap
|
||||
@_iconbitmap.update
|
||||
if self.bitmap != @_iconbitmap.bitmap
|
||||
oldrc = self.src_rect
|
||||
self.bitmap = @_iconbitmap.bitmap
|
||||
self.src_rect = oldrc
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
end
|
||||
|
||||
#===============================================================================
|
||||
# Old GifSprite class, retained for compatibility
|
||||
#===============================================================================
|
||||
class GifSprite < IconSprite
|
||||
def initialize(path)
|
||||
super(0, 0)
|
||||
setBitmap(path)
|
||||
end
|
||||
end
|
||||
|
||||
#===============================================================================
|
||||
# SpriteWrapper that stores multiple bitmaps, and displays only one at once.
|
||||
#===============================================================================
|
||||
class ChangelingSprite < SpriteWrapper
|
||||
def initialize(x = 0, y = 0, viewport = nil)
|
||||
super(viewport)
|
||||
self.x = x
|
||||
self.y = y
|
||||
@bitmaps = {}
|
||||
@currentBitmap = nil
|
||||
end
|
||||
|
||||
def addBitmap(key, path)
|
||||
@bitmaps[key].dispose if @bitmaps[key]
|
||||
@bitmaps[key] = AnimatedBitmap.new(path)
|
||||
end
|
||||
|
||||
def changeBitmap(key)
|
||||
@currentBitmap = @bitmaps[key]
|
||||
self.bitmap = (@currentBitmap) ? @currentBitmap.bitmap : nil
|
||||
end
|
||||
|
||||
def dispose
|
||||
return if disposed?
|
||||
for bm in @bitmaps.values;
|
||||
bm.dispose;
|
||||
end
|
||||
@bitmaps.clear
|
||||
super
|
||||
end
|
||||
|
||||
def update
|
||||
return if disposed?
|
||||
for bm in @bitmaps.values;
|
||||
bm.update;
|
||||
end
|
||||
self.bitmap = (@currentBitmap) ? @currentBitmap.bitmap : nil
|
||||
end
|
||||
end
|
||||
360
Data/Scripts/007_Objects and windows/008_AnimatedBitmap.rb
Normal file
360
Data/Scripts/007_Objects and windows/008_AnimatedBitmap.rb
Normal file
@@ -0,0 +1,360 @@
|
||||
#===============================================================================
|
||||
#
|
||||
#===============================================================================
|
||||
|
||||
class AnimatedBitmap
|
||||
attr_reader :path
|
||||
attr_reader :filename
|
||||
|
||||
def initialize(file, hue = 0)
|
||||
raise "Filename is nil (missing graphic)." if file.nil?
|
||||
path = file
|
||||
filename = ""
|
||||
if file.last != '/' # Isn't just a directory
|
||||
split_file = file.split(/[\\\/]/)
|
||||
filename = split_file.pop
|
||||
path = split_file.join('/') + '/'
|
||||
end
|
||||
@filename = filename
|
||||
@path = path
|
||||
if filename[/^\[\d+(?:,\d+)?\]/] # Starts with 1 or 2 numbers in square brackets
|
||||
@bitmap = PngAnimatedBitmap.new(path, filename, hue)
|
||||
else
|
||||
@bitmap = GifBitmap.new(path, filename, hue)
|
||||
end
|
||||
end
|
||||
|
||||
def setup_from_bitmap(bitmap,hue=0)
|
||||
@path = ""
|
||||
@filename = ""
|
||||
@bitmap = GifBitmap.new("", '', hue)
|
||||
@bitmap.bitmap = bitmap;
|
||||
end
|
||||
|
||||
def self.from_bitmap(bitmap, hue=0)
|
||||
obj = allocate
|
||||
obj.send(:setup_from_bitmap, bitmap, hue)
|
||||
obj
|
||||
end
|
||||
|
||||
def pbSetColor(r = 0, g = 0, b = 0, a = 255)
|
||||
color = Color.new(r, g, b, a)
|
||||
pbSetColorValue(color)
|
||||
end
|
||||
|
||||
def pbSetColorValue(color)
|
||||
for i in 0..@bitmap.bitmap.width
|
||||
for j in 0..@bitmap.bitmap.height
|
||||
if @bitmap.bitmap.get_pixel(i, j).alpha != 0
|
||||
@bitmap.bitmap.set_pixel(i, j, color)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
def shiftColors(offset = 0)
|
||||
@bitmap.bitmap.hue_change(offset)
|
||||
end
|
||||
|
||||
def [](index)
|
||||
; @bitmap[index];
|
||||
end
|
||||
|
||||
def width
|
||||
@bitmap.bitmap.width;
|
||||
end
|
||||
|
||||
def height
|
||||
@bitmap.bitmap.height;
|
||||
end
|
||||
|
||||
def length
|
||||
@bitmap.length;
|
||||
end
|
||||
|
||||
def each
|
||||
@bitmap.each { |item| yield item };
|
||||
end
|
||||
|
||||
def bitmap
|
||||
@bitmap.bitmap;
|
||||
end
|
||||
|
||||
def bitmap=(bitmap)
|
||||
@bitmap.bitmap = bitmap;
|
||||
end
|
||||
|
||||
def currentIndex
|
||||
@bitmap.currentIndex;
|
||||
end
|
||||
|
||||
def totalFrames
|
||||
@bitmap.totalFrames;
|
||||
end
|
||||
|
||||
def disposed?
|
||||
@bitmap.disposed?;
|
||||
end
|
||||
|
||||
def update
|
||||
@bitmap.update;
|
||||
end
|
||||
|
||||
def dispose
|
||||
@bitmap.dispose;
|
||||
end
|
||||
|
||||
def deanimate
|
||||
@bitmap.deanimate;
|
||||
end
|
||||
|
||||
def copy
|
||||
@bitmap.copy;
|
||||
end
|
||||
|
||||
def scale_bitmap(scale)
|
||||
return if scale == 1
|
||||
new_width = @bitmap.bitmap.width * scale
|
||||
new_height = @bitmap.bitmap.height * scale
|
||||
|
||||
destination_rect = Rect.new(0, 0, new_width, new_height)
|
||||
source_rect = Rect.new(0, 0, @bitmap.bitmap.width, @bitmap.bitmap.height)
|
||||
new_bitmap = Bitmap.new(new_width, new_height)
|
||||
new_bitmap.stretch_blt(
|
||||
destination_rect,
|
||||
@bitmap.bitmap,
|
||||
source_rect
|
||||
)
|
||||
@bitmap.bitmap = new_bitmap
|
||||
end
|
||||
|
||||
# def mirror
|
||||
# for x in 0..@bitmap.bitmap.width / 2
|
||||
# for y in 0..@bitmap.bitmap.height - 2
|
||||
# temp = @bitmap.bitmap.get_pixel(x, y)
|
||||
# newPix = @bitmap.bitmap.get_pixel((@bitmap.bitmap.width - x), y)
|
||||
#
|
||||
# @bitmap.bitmap.set_pixel(x, y, newPix)
|
||||
# @bitmap.bitmap.set_pixel((@bitmap.bitmap.width - x), y, temp)
|
||||
# end
|
||||
# end
|
||||
# end
|
||||
|
||||
def mirror
|
||||
@bitmap.bitmap
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
|
||||
#===============================================================================
|
||||
#
|
||||
#===============================================================================
|
||||
class PngAnimatedBitmap
|
||||
attr_accessor :frames
|
||||
|
||||
# Creates an animated bitmap from a PNG file.
|
||||
def initialize(dir, filename, hue = 0)
|
||||
@frames = []
|
||||
@currentFrame = 0
|
||||
@framecount = 0
|
||||
panorama = RPG::Cache.load_bitmap(dir, filename, hue)
|
||||
if filename[/^\[(\d+)(?:,(\d+))?\]/] # Starts with 1 or 2 numbers in brackets
|
||||
# File has a frame count
|
||||
numFrames = $1.to_i
|
||||
delay = $2.to_i
|
||||
delay = 10 if delay == 0
|
||||
raise "Invalid frame count in #{filename}" if numFrames <= 0
|
||||
raise "Invalid frame delay in #{filename}" if delay <= 0
|
||||
if panorama.width % numFrames != 0
|
||||
raise "Bitmap's width (#{panorama.width}) is not divisible by frame count: #{filename}"
|
||||
end
|
||||
@frameDelay = delay
|
||||
subWidth = panorama.width / numFrames
|
||||
for i in 0...numFrames
|
||||
subBitmap = BitmapWrapper.new(subWidth, panorama.height)
|
||||
subBitmap.blt(0, 0, panorama, Rect.new(subWidth * i, 0, subWidth, panorama.height))
|
||||
@frames.push(subBitmap)
|
||||
end
|
||||
panorama.dispose
|
||||
else
|
||||
@frames = [panorama]
|
||||
end
|
||||
end
|
||||
|
||||
def [](index)
|
||||
return @frames[index]
|
||||
end
|
||||
|
||||
def width
|
||||
self.bitmap.width;
|
||||
end
|
||||
|
||||
def height
|
||||
self.bitmap.height;
|
||||
end
|
||||
|
||||
def deanimate
|
||||
for i in 1...@frames.length
|
||||
@frames[i].dispose
|
||||
end
|
||||
@frames = [@frames[0]]
|
||||
@currentFrame = 0
|
||||
return @frames[0]
|
||||
end
|
||||
|
||||
def bitmap
|
||||
return @frames[@currentFrame]
|
||||
end
|
||||
|
||||
def currentIndex
|
||||
return @currentFrame
|
||||
end
|
||||
|
||||
def frameDelay(_index)
|
||||
return @frameDelay
|
||||
end
|
||||
|
||||
def length
|
||||
return @frames.length
|
||||
end
|
||||
|
||||
def each
|
||||
@frames.each { |item| yield item }
|
||||
end
|
||||
|
||||
def totalFrames
|
||||
return @frameDelay * @frames.length
|
||||
end
|
||||
|
||||
def disposed?
|
||||
return @disposed
|
||||
end
|
||||
|
||||
def update
|
||||
return if disposed?
|
||||
if @frames.length > 1
|
||||
@framecount += 1
|
||||
if @framecount >= @frameDelay
|
||||
@framecount = 0
|
||||
@currentFrame += 1
|
||||
@currentFrame %= @frames.length
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def dispose
|
||||
if !@disposed
|
||||
@frames.each { |f| f.dispose }
|
||||
end
|
||||
@disposed = true
|
||||
end
|
||||
|
||||
def copy
|
||||
x = self.clone
|
||||
x.frames = x.frames.clone
|
||||
for i in 0...x.frames.length
|
||||
x.frames[i] = x.frames[i].copy
|
||||
end
|
||||
return x
|
||||
end
|
||||
end
|
||||
|
||||
#===============================================================================
|
||||
#
|
||||
#===============================================================================
|
||||
class GifBitmap
|
||||
attr_accessor :bitmap
|
||||
attr_reader :loaded_from_cache
|
||||
# Creates a bitmap from a GIF file. Can also load non-animated bitmaps.
|
||||
def initialize(dir, filename, hue = 0)
|
||||
@bitmap = nil
|
||||
@disposed = false
|
||||
@loaded_from_cache = false
|
||||
filename = "" if !filename
|
||||
begin
|
||||
@bitmap = RPG::Cache.load_bitmap(dir, filename, hue)
|
||||
@loaded_from_cache = true
|
||||
rescue
|
||||
@bitmap = nil
|
||||
end
|
||||
@bitmap = BitmapWrapper.new(32, 32) if @bitmap.nil?
|
||||
@bitmap.play if @bitmap&.animated?
|
||||
end
|
||||
|
||||
def [](_index)
|
||||
return @bitmap
|
||||
end
|
||||
|
||||
def deanimate
|
||||
@bitmap&.goto_and_stop(0) if @bitmap&.animated?
|
||||
return @bitmap
|
||||
end
|
||||
|
||||
def currentIndex
|
||||
return @bitmap&.current_frame || 0
|
||||
end
|
||||
|
||||
def length
|
||||
return @bitmap&.frame_count || 1
|
||||
end
|
||||
|
||||
def each
|
||||
yield @bitmap
|
||||
end
|
||||
|
||||
def totalFrames
|
||||
f_rate = @bitmap.frame_rate
|
||||
f_rate = 1 if f_rate.nil? || f_rate == 0
|
||||
return (@bitmap) ? (@bitmap.frame_count / f_rate).floor : 1
|
||||
end
|
||||
|
||||
def disposed?
|
||||
return @disposed
|
||||
end
|
||||
|
||||
def width
|
||||
return @bitmap&.width || 0
|
||||
end
|
||||
|
||||
def height
|
||||
return @bitmap&.height || 0
|
||||
end
|
||||
|
||||
# Gifs are animated automatically by mkxp-z. This function does nothing.
|
||||
def update; end
|
||||
|
||||
def dispose
|
||||
return if @disposed
|
||||
@bitmap.dispose
|
||||
@disposed = true
|
||||
end
|
||||
|
||||
def copy
|
||||
x = self.clone
|
||||
x.bitmap = @bitmap.copy if @bitmap
|
||||
return x
|
||||
end
|
||||
end
|
||||
|
||||
#===============================================================================
|
||||
#
|
||||
#===============================================================================
|
||||
def pbGetTileBitmap(filename, tile_id, hue, width = 1, height = 1)
|
||||
return RPG::Cache.tileEx(filename, tile_id, hue, width, height) { |f|
|
||||
AnimatedBitmap.new("Graphics/Tilesets/" + filename).deanimate
|
||||
}
|
||||
end
|
||||
|
||||
def pbGetTileset(name, hue = 0)
|
||||
return AnimatedBitmap.new("Graphics/Tilesets/" + name, hue).deanimate
|
||||
end
|
||||
|
||||
def pbGetAutotile(name, hue = 0)
|
||||
return AnimatedBitmap.new("Graphics/Autotiles/" + name, hue).deanimate
|
||||
end
|
||||
|
||||
def pbGetAnimation(name, hue = 0)
|
||||
return AnimatedBitmap.new("Graphics/Animations/" + name, hue).deanimate
|
||||
end
|
||||
230
Data/Scripts/007_Objects and windows/009_Planes.rb
Normal file
230
Data/Scripts/007_Objects and windows/009_Planes.rb
Normal file
@@ -0,0 +1,230 @@
|
||||
#===============================================================================
|
||||
#
|
||||
#===============================================================================
|
||||
class Plane
|
||||
def update; end
|
||||
def refresh; end
|
||||
end
|
||||
|
||||
|
||||
|
||||
#===============================================================================
|
||||
# This class works around a limitation that planes are always
|
||||
# 640 by 480 pixels in size regardless of the window's size.
|
||||
#===============================================================================
|
||||
class LargePlane < Plane
|
||||
attr_accessor :borderX
|
||||
attr_accessor :borderY
|
||||
|
||||
def initialize(viewport=nil)
|
||||
@__sprite=Sprite.new(viewport)
|
||||
@__disposed=false
|
||||
@__ox=0
|
||||
@__oy=0
|
||||
@__bitmap=nil
|
||||
@__visible=true
|
||||
@__sprite.visible=false
|
||||
@borderX=0
|
||||
@borderY=0
|
||||
end
|
||||
|
||||
def disposed?
|
||||
return @__disposed
|
||||
end
|
||||
|
||||
def dispose
|
||||
if !@__disposed
|
||||
@__sprite.bitmap.dispose if @__sprite.bitmap
|
||||
@__sprite.dispose
|
||||
@__sprite=nil
|
||||
@__bitmap=nil
|
||||
@__disposed=true
|
||||
end
|
||||
#super
|
||||
end
|
||||
|
||||
def ox; @__ox; end
|
||||
def oy; @__oy; end
|
||||
|
||||
def ox=(value);
|
||||
return if @__ox==value
|
||||
@__ox = value
|
||||
refresh
|
||||
end
|
||||
|
||||
def oy=(value);
|
||||
return if @__oy==value
|
||||
@__oy = value
|
||||
refresh
|
||||
end
|
||||
|
||||
def bitmap
|
||||
return @__bitmap
|
||||
end
|
||||
|
||||
def bitmap=(value)
|
||||
if value==nil
|
||||
if @__bitmap!=nil
|
||||
@__bitmap=nil
|
||||
@__sprite.visible=(@__visible && !@__bitmap.nil?)
|
||||
end
|
||||
elsif @__bitmap!=value && !value.disposed?
|
||||
@__bitmap=value
|
||||
refresh
|
||||
elsif value.disposed?
|
||||
if @__bitmap!=nil
|
||||
@__bitmap=nil
|
||||
@__sprite.visible=(@__visible && !@__bitmap.nil?)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def viewport; @__sprite.viewport; end
|
||||
def zoom_x; @__sprite.zoom_x; end
|
||||
def zoom_y; @__sprite.zoom_y; end
|
||||
def opacity; @__sprite.opacity; end
|
||||
def blend_type; @__sprite.blend_type; end
|
||||
def visible; @__visible; end
|
||||
def z; @__sprite.z; end
|
||||
def color; @__sprite.color; end
|
||||
def tone; @__sprite.tone; end
|
||||
|
||||
def zoom_x=(v);
|
||||
return if @__sprite.zoom_x==v
|
||||
@__sprite.zoom_x = v
|
||||
refresh
|
||||
end
|
||||
|
||||
def zoom_y=(v);
|
||||
return if @__sprite.zoom_y==v
|
||||
@__sprite.zoom_y = v
|
||||
refresh
|
||||
end
|
||||
|
||||
def opacity=(v); @__sprite.opacity=(v); end
|
||||
def blend_type=(v); @__sprite.blend_type=(v); end
|
||||
def visible=(v); @__visible=v; @__sprite.visible=(@__visible && !@__bitmap.nil?); end
|
||||
def z=(v); @__sprite.z=(v); end
|
||||
def color=(v); @__sprite.color=(v); end
|
||||
def tone=(v); @__sprite.tone=(v); end
|
||||
def update; ;end
|
||||
|
||||
def refresh
|
||||
@__sprite.visible = (@__visible && !@__bitmap.nil?)
|
||||
if @__bitmap
|
||||
if !@__bitmap.disposed?
|
||||
@__ox += @__bitmap.width*@__sprite.zoom_x if @__ox<0
|
||||
@__oy += @__bitmap.height*@__sprite.zoom_y if @__oy<0
|
||||
@__ox -= @__bitmap.width*@__sprite.zoom_x if @__ox>@__bitmap.width
|
||||
@__oy -= @__bitmap.height*@__sprite.zoom_y if @__oy>@__bitmap.height
|
||||
dwidth = (Graphics.width/@__sprite.zoom_x+@borderX).to_i # +2
|
||||
dheight = (Graphics.height/@__sprite.zoom_y+@borderY).to_i # +2
|
||||
@__sprite.bitmap = ensureBitmap(@__sprite.bitmap,dwidth,dheight)
|
||||
@__sprite.bitmap.clear
|
||||
tileBitmap(@__sprite.bitmap,@__bitmap,@__bitmap.rect)
|
||||
else
|
||||
@__sprite.visible = false
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def ensureBitmap(bitmap,dwidth,dheight)
|
||||
if !bitmap || bitmap.disposed? || bitmap.width<dwidth || bitmap.height<dheight
|
||||
bitmap.dispose if bitmap
|
||||
bitmap = Bitmap.new([1,dwidth].max,[1,dheight].max)
|
||||
end
|
||||
return bitmap
|
||||
end
|
||||
|
||||
def tileBitmap(dstbitmap,srcbitmap,srcrect)
|
||||
return if !srcbitmap || srcbitmap.disposed?
|
||||
dstrect = dstbitmap.rect
|
||||
left = (dstrect.x-@__ox/@__sprite.zoom_x).to_i
|
||||
top = (dstrect.y-@__oy/@__sprite.zoom_y).to_i
|
||||
while left>0; left -= srcbitmap.width; end
|
||||
while top>0; top -= srcbitmap.height; end
|
||||
y = top
|
||||
while y<dstrect.height
|
||||
x = left
|
||||
while x<dstrect.width
|
||||
dstbitmap.blt(x+@borderX,y+@borderY,srcbitmap,srcrect)
|
||||
x += srcrect.width
|
||||
end
|
||||
y += srcrect.height
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
|
||||
#===============================================================================
|
||||
# A plane class that displays a single color.
|
||||
#===============================================================================
|
||||
class ColoredPlane < LargePlane
|
||||
def initialize(color,viewport=nil)
|
||||
super(viewport)
|
||||
self.bitmap=Bitmap.new(32,32)
|
||||
setPlaneColor(color)
|
||||
end
|
||||
|
||||
def dispose
|
||||
self.bitmap.dispose if self.bitmap
|
||||
super
|
||||
end
|
||||
|
||||
def setPlaneColor(value)
|
||||
self.bitmap.fill_rect(0,0,self.bitmap.width,self.bitmap.height,value)
|
||||
self.refresh
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
|
||||
#===============================================================================
|
||||
# A plane class that supports animated images.
|
||||
#===============================================================================
|
||||
class AnimatedPlane < LargePlane
|
||||
def initialize(viewport)
|
||||
super(viewport)
|
||||
@bitmap=nil
|
||||
end
|
||||
|
||||
def dispose
|
||||
clearBitmaps()
|
||||
super
|
||||
end
|
||||
|
||||
def update
|
||||
super
|
||||
if @bitmap
|
||||
@bitmap.update
|
||||
self.bitmap=@bitmap.bitmap
|
||||
end
|
||||
end
|
||||
|
||||
def clearBitmaps
|
||||
@bitmap.dispose if @bitmap
|
||||
@bitmap=nil
|
||||
self.bitmap=nil if !self.disposed?
|
||||
end
|
||||
|
||||
def setPanorama(file, hue=0)
|
||||
clearBitmaps()
|
||||
return if file==nil
|
||||
@bitmap=AnimatedBitmap.new("Graphics/Panoramas/"+file,hue)
|
||||
end
|
||||
|
||||
def setFog(file, hue=0)
|
||||
clearBitmaps()
|
||||
return if file==nil
|
||||
@bitmap=AnimatedBitmap.new("Graphics/Fogs/"+file,hue)
|
||||
end
|
||||
|
||||
def setBitmap(file, hue=0)
|
||||
clearBitmaps()
|
||||
return if file==nil
|
||||
@bitmap=AnimatedBitmap.new(file,hue)
|
||||
end
|
||||
end
|
||||
1277
Data/Scripts/007_Objects and windows/010_DrawText.rb
Normal file
1277
Data/Scripts/007_Objects and windows/010_DrawText.rb
Normal file
File diff suppressed because it is too large
Load Diff
1057
Data/Scripts/007_Objects and windows/011_Messages.rb
Normal file
1057
Data/Scripts/007_Objects and windows/011_Messages.rb
Normal file
File diff suppressed because it is too large
Load Diff
564
Data/Scripts/007_Objects and windows/012_TextEntry.rb
Normal file
564
Data/Scripts/007_Objects and windows/012_TextEntry.rb
Normal file
@@ -0,0 +1,564 @@
|
||||
#===============================================================================
|
||||
#
|
||||
#===============================================================================
|
||||
class CharacterEntryHelper
|
||||
attr_reader :text
|
||||
attr_accessor :maxlength
|
||||
attr_reader :passwordChar
|
||||
attr_accessor :cursor
|
||||
|
||||
def initialize(text)
|
||||
@maxlength=-1
|
||||
@text=text
|
||||
@passwordChar=""
|
||||
@cursor=text.scan(/./m).length
|
||||
end
|
||||
|
||||
def text=(value)
|
||||
@text=value
|
||||
end
|
||||
|
||||
def textChars
|
||||
chars=text.scan(/./m)
|
||||
if @passwordChar!=""
|
||||
chars.length.times { |i| chars[i] = @passwordChar }
|
||||
end
|
||||
return chars
|
||||
end
|
||||
|
||||
def passwordChar=(value)
|
||||
@passwordChar=value ? value : ""
|
||||
end
|
||||
|
||||
def length
|
||||
return self.text.scan(/./m).length
|
||||
end
|
||||
|
||||
def canInsert?
|
||||
chars=self.text.scan(/./m)
|
||||
return false if @maxlength>=0 && chars.length>=@maxlength
|
||||
return true
|
||||
end
|
||||
|
||||
def insert(ch)
|
||||
chars=self.text.scan(/./m)
|
||||
return false if @maxlength>=0 && chars.length>=@maxlength
|
||||
chars.insert(@cursor,ch)
|
||||
@text=""
|
||||
for ch in chars
|
||||
@text+=ch if ch
|
||||
end
|
||||
@cursor+=1
|
||||
return true
|
||||
end
|
||||
|
||||
def canDelete?
|
||||
chars=self.text.scan(/./m)
|
||||
return false if chars.length<=0 || @cursor<=0
|
||||
return true
|
||||
end
|
||||
|
||||
def delete
|
||||
chars=self.text.scan(/./m)
|
||||
return false if chars.length<=0 || @cursor<=0
|
||||
chars.delete_at(@cursor-1)
|
||||
@text=""
|
||||
for ch in chars
|
||||
@text+=ch if ch
|
||||
end
|
||||
@cursor-=1
|
||||
return true
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def ensure
|
||||
return if @maxlength<0
|
||||
chars=self.text.scan(/./m)
|
||||
if chars.length>@maxlength && @maxlength>=0
|
||||
chars=chars[0,@maxlength]
|
||||
end
|
||||
@text=""
|
||||
for ch in chars
|
||||
@text+=ch if ch
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
|
||||
#===============================================================================
|
||||
#
|
||||
#===============================================================================
|
||||
class Window_TextEntry < SpriteWindow_Base
|
||||
def initialize(text,x,y,width,height,heading=nil,usedarkercolor=false)
|
||||
super(x,y,width,height)
|
||||
colors=getDefaultTextColors(self.windowskin)
|
||||
@baseColor=colors[0]
|
||||
@shadowColor=colors[1]
|
||||
if usedarkercolor
|
||||
@baseColor=Color.new(16,24,32)
|
||||
@shadowColor=Color.new(168,184,184)
|
||||
end
|
||||
@helper=CharacterEntryHelper.new(text)
|
||||
@heading=heading
|
||||
self.active=true
|
||||
@frame=0
|
||||
refresh
|
||||
end
|
||||
|
||||
def text
|
||||
@helper.text
|
||||
end
|
||||
|
||||
def maxlength
|
||||
@helper.maxlength
|
||||
end
|
||||
|
||||
def passwordChar
|
||||
@helper.passwordChar
|
||||
end
|
||||
|
||||
def text=(value)
|
||||
@helper.text=value
|
||||
self.refresh
|
||||
end
|
||||
|
||||
def passwordChar=(value)
|
||||
@helper.passwordChar=value
|
||||
refresh
|
||||
end
|
||||
|
||||
def maxlength=(value)
|
||||
@helper.maxlength=value
|
||||
self.refresh
|
||||
end
|
||||
|
||||
def insert(ch)
|
||||
if @helper.insert(ch)
|
||||
@frame=0
|
||||
self.refresh
|
||||
return true
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
def delete
|
||||
if @helper.delete
|
||||
@frame=0
|
||||
self.refresh
|
||||
return true
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
def update
|
||||
@frame += 1
|
||||
@frame %= 20
|
||||
self.refresh if (@frame%10)==0
|
||||
return if !self.active
|
||||
# Moving cursor
|
||||
if Input.repeat?(Input::LEFT) && Input.press?(Input::ACTION)
|
||||
if @helper.cursor > 0
|
||||
@helper.cursor -= 1
|
||||
@frame = 0
|
||||
self.refresh
|
||||
end
|
||||
elsif Input.repeat?(Input::RIGHT) && Input.press?(Input::ACTION)
|
||||
if @helper.cursor < self.text.scan(/./m).length
|
||||
@helper.cursor += 1
|
||||
@frame = 0
|
||||
self.refresh
|
||||
end
|
||||
elsif Input.repeat?(Input::BACK) # Backspace
|
||||
self.delete if @helper.cursor > 0
|
||||
end
|
||||
end
|
||||
|
||||
def refresh
|
||||
self.contents=pbDoEnsureBitmap(self.contents,self.width-self.borderX,
|
||||
self.height-self.borderY)
|
||||
bitmap=self.contents
|
||||
bitmap.clear
|
||||
x=0
|
||||
y=0
|
||||
if @heading
|
||||
textwidth=bitmap.text_size(@heading).width
|
||||
pbDrawShadowText(bitmap,x,y, textwidth+4, 32, @heading,@baseColor,@shadowColor)
|
||||
y+=32
|
||||
end
|
||||
x+=4
|
||||
width=self.width-self.borderX
|
||||
cursorcolor=Color.new(16,24,32)
|
||||
textscan=self.text.scan(/./m)
|
||||
scanlength=textscan.length
|
||||
@helper.cursor=scanlength if @helper.cursor>scanlength
|
||||
@helper.cursor=0 if @helper.cursor<0
|
||||
startpos=@helper.cursor
|
||||
fromcursor=0
|
||||
while (startpos>0)
|
||||
c=(@helper.passwordChar!="") ? @helper.passwordChar : textscan[startpos-1]
|
||||
fromcursor+=bitmap.text_size(c).width
|
||||
break if fromcursor>width-4
|
||||
startpos-=1
|
||||
end
|
||||
for i in startpos...scanlength
|
||||
c=(@helper.passwordChar!="") ? @helper.passwordChar : textscan[i]
|
||||
textwidth=bitmap.text_size(c).width
|
||||
next if c=="\n"
|
||||
# Draw text
|
||||
pbDrawShadowText(bitmap,x,y, textwidth+4, 32, c,@baseColor,@shadowColor)
|
||||
# Draw cursor if necessary
|
||||
if ((@frame/10)&1) == 0 && i==@helper.cursor
|
||||
bitmap.fill_rect(x,y+4,2,24,cursorcolor)
|
||||
end
|
||||
# Add x to drawn text width
|
||||
x += textwidth
|
||||
end
|
||||
if ((@frame/10)&1) == 0 && textscan.length==@helper.cursor
|
||||
bitmap.fill_rect(x,y+4,2,24,cursorcolor)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
|
||||
#===============================================================================
|
||||
#
|
||||
#===============================================================================
|
||||
class Window_TextEntry_Keyboard < Window_TextEntry
|
||||
def update
|
||||
@frame+=1
|
||||
@frame%=20
|
||||
self.refresh if ((@frame%10)==0)
|
||||
return if !self.active
|
||||
# Moving cursor
|
||||
if Input.triggerex?(:LEFT) || Input.repeatex?(:LEFT)
|
||||
if @helper.cursor > 0
|
||||
@helper.cursor-=1
|
||||
@frame=0
|
||||
self.refresh
|
||||
end
|
||||
return
|
||||
elsif Input.triggerex?(:RIGHT) || Input.repeatex?(:RIGHT)
|
||||
if @helper.cursor < self.text.scan(/./m).length
|
||||
@helper.cursor+=1
|
||||
@frame=0
|
||||
self.refresh
|
||||
end
|
||||
return
|
||||
elsif Input.triggerex?(:BACKSPACE) || Input.repeatex?(:BACKSPACE)
|
||||
self.delete if @helper.cursor>0
|
||||
return
|
||||
elsif Input.triggerex?(:RETURN) || Input.triggerex?(:ESCAPE)
|
||||
return
|
||||
end
|
||||
Input.gets.each_char { |c| insert(c) }
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
|
||||
#===============================================================================
|
||||
#
|
||||
#===============================================================================
|
||||
class Window_MultilineTextEntry < SpriteWindow_Base
|
||||
def initialize(text,x,y,width,height)
|
||||
super(x,y,width,height)
|
||||
colors=getDefaultTextColors(self.windowskin)
|
||||
@baseColor=colors[0]
|
||||
@shadowColor=colors[1]
|
||||
@helper=CharacterEntryHelper.new(text)
|
||||
@firstline=0
|
||||
@cursorLine=0
|
||||
@cursorColumn=0
|
||||
@frame=0
|
||||
self.active=true
|
||||
refresh
|
||||
end
|
||||
|
||||
attr_reader :baseColor
|
||||
attr_reader :shadowColor
|
||||
|
||||
def baseColor=(value)
|
||||
@baseColor=value
|
||||
refresh
|
||||
end
|
||||
|
||||
def shadowColor=(value)
|
||||
@shadowColor=value
|
||||
refresh
|
||||
end
|
||||
|
||||
def text
|
||||
@helper.text
|
||||
end
|
||||
|
||||
def maxlength
|
||||
@helper.maxlength
|
||||
end
|
||||
|
||||
def text=(value)
|
||||
@helper.text=value
|
||||
@textchars=nil
|
||||
self.refresh
|
||||
end
|
||||
|
||||
def maxlength=(value)
|
||||
@helper.maxlength=value
|
||||
@textchars=nil
|
||||
self.refresh
|
||||
end
|
||||
|
||||
def insert(ch)
|
||||
@helper.cursor=getPosFromLineAndColumn(@cursorLine,@cursorColumn)
|
||||
if @helper.insert(ch)
|
||||
@frame=0
|
||||
@textchars=nil
|
||||
moveCursor(0,1)
|
||||
self.refresh
|
||||
return true
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
def delete
|
||||
@helper.cursor=getPosFromLineAndColumn(@cursorLine,@cursorColumn)
|
||||
if @helper.delete
|
||||
@frame=0
|
||||
moveCursor(0,-1) # use old textchars
|
||||
@textchars=nil
|
||||
self.refresh
|
||||
return true
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
def getTextChars
|
||||
if !@textchars
|
||||
@textchars=getLineBrokenText(self.contents,@helper.text,
|
||||
self.contents.width,nil)
|
||||
end
|
||||
return @textchars
|
||||
end
|
||||
|
||||
def getTotalLines
|
||||
textchars=getTextChars
|
||||
return 1 if textchars.length==0
|
||||
tchar=textchars[textchars.length-1]
|
||||
return tchar[5]+1
|
||||
end
|
||||
|
||||
def getLineY(line)
|
||||
textchars=getTextChars
|
||||
return 0 if textchars.length==0
|
||||
totallines=getTotalLines()
|
||||
line=0 if line<0
|
||||
line=totallines-1 if line>=totallines
|
||||
maximumY=0
|
||||
for i in 0...textchars.length
|
||||
thisline=textchars[i][5]
|
||||
y=textchars[i][2]
|
||||
return y if thisline==line
|
||||
maximumY=y if maximumY<y
|
||||
end
|
||||
return maximumY
|
||||
end
|
||||
|
||||
def getColumnsInLine(line)
|
||||
textchars=getTextChars
|
||||
return 0 if textchars.length==0
|
||||
totallines=getTotalLines()
|
||||
line=0 if line<0
|
||||
line=totallines-1 if line>=totallines
|
||||
endpos=0
|
||||
for i in 0...textchars.length
|
||||
thisline=textchars[i][5]
|
||||
thislength=textchars[i][8]
|
||||
endpos+=thislength if thisline==line
|
||||
end
|
||||
return endpos
|
||||
end
|
||||
|
||||
def getPosFromLineAndColumn(line,column)
|
||||
textchars=getTextChars
|
||||
return 0 if textchars.length==0
|
||||
totallines=getTotalLines()
|
||||
line=0 if line<0
|
||||
line=totallines-1 if line>=totallines
|
||||
endpos=0
|
||||
for i in 0...textchars.length
|
||||
thisline=textchars[i][5]
|
||||
thispos=textchars[i][6]
|
||||
thiscolumn=textchars[i][7]
|
||||
thislength=textchars[i][8]
|
||||
if thisline==line
|
||||
endpos=thispos+thislength
|
||||
# echoln [endpos,thispos+(column-thiscolumn),textchars[i]]
|
||||
if column>=thiscolumn && column<=thiscolumn+thislength && thislength>0
|
||||
return thispos+(column-thiscolumn)
|
||||
end
|
||||
end
|
||||
end
|
||||
# if endpos==0
|
||||
# echoln [totallines,line,column]
|
||||
# echoln textchars
|
||||
# end
|
||||
# echoln "endpos=#{endpos}"
|
||||
return endpos
|
||||
end
|
||||
|
||||
def getLastVisibleLine
|
||||
getTextChars()
|
||||
textheight=[1,self.contents.text_size("X").height].max
|
||||
lastVisible=@firstline+((self.height-self.borderY)/textheight)-1
|
||||
return lastVisible
|
||||
end
|
||||
|
||||
def updateCursorPos(doRefresh)
|
||||
# Calculate new cursor position
|
||||
@helper.cursor=getPosFromLineAndColumn(@cursorLine,@cursorColumn)
|
||||
if doRefresh
|
||||
@frame=0
|
||||
self.refresh
|
||||
end
|
||||
@firstline=@cursorLine if @cursorLine<@firstline
|
||||
lastVisible=getLastVisibleLine()
|
||||
@firstline+=(@cursorLine-lastVisible) if @cursorLine>lastVisible
|
||||
end
|
||||
|
||||
def moveCursor(lineOffset, columnOffset)
|
||||
# Move column offset first, then lines (since column offset
|
||||
# can affect line offset)
|
||||
# echoln ["beforemoving",@cursorLine,@cursorColumn]
|
||||
totalColumns=getColumnsInLine(@cursorLine) # check current line
|
||||
totalLines=getTotalLines()
|
||||
oldCursorLine=@cursorLine
|
||||
oldCursorColumn=@cursorColumn
|
||||
@cursorColumn+=columnOffset
|
||||
if @cursorColumn<0 && @cursorLine>0
|
||||
# Will happen if cursor is moved left from the beginning of a line
|
||||
@cursorLine-=1
|
||||
@cursorColumn=getColumnsInLine(@cursorLine)
|
||||
elsif @cursorColumn>totalColumns && @cursorLine<totalLines-1
|
||||
# Will happen if cursor is moved right from the end of a line
|
||||
@cursorLine+=1
|
||||
@cursorColumn=0
|
||||
end
|
||||
# Ensure column bounds
|
||||
totalColumns=getColumnsInLine(@cursorLine)
|
||||
@cursorColumn=totalColumns if @cursorColumn>totalColumns
|
||||
@cursorColumn=0 if @cursorColumn<0 # totalColumns can be 0
|
||||
# Move line offset
|
||||
@cursorLine+=lineOffset
|
||||
@cursorLine=0 if @cursorLine<0
|
||||
@cursorLine=totalLines-1 if @cursorLine>=totalLines
|
||||
# Ensure column bounds again
|
||||
totalColumns=getColumnsInLine(@cursorLine)
|
||||
@cursorColumn=totalColumns if @cursorColumn>totalColumns
|
||||
@cursorColumn=0 if @cursorColumn<0 # totalColumns can be 0
|
||||
updateCursorPos(
|
||||
oldCursorLine!=@cursorLine ||
|
||||
oldCursorColumn!=@cursorColumn
|
||||
)
|
||||
# echoln ["aftermoving",@cursorLine,@cursorColumn]
|
||||
end
|
||||
|
||||
def update
|
||||
@frame+=1
|
||||
@frame%=20
|
||||
self.refresh if ((@frame%10)==0)
|
||||
return if !self.active
|
||||
# Moving cursor
|
||||
if Input.triggerex?(:UP) || Input.repeatex?(:UP)
|
||||
moveCursor(-1,0)
|
||||
return
|
||||
elsif Input.triggerex?(:DOWN) || Input.repeatex?(:DOWN)
|
||||
moveCursor(1,0)
|
||||
return
|
||||
elsif Input.triggerex?(:LEFT) || Input.repeatex?(:LEFT)
|
||||
moveCursor(0,-1)
|
||||
return
|
||||
elsif Input.triggerex?(:RIGHT) || Input.repeatex?(:RIGHT)
|
||||
moveCursor(0,1)
|
||||
return
|
||||
end
|
||||
if Input.press?(Input::CTRL) && Input.triggerex?(:HOME)
|
||||
# Move cursor to beginning
|
||||
@cursorLine=0
|
||||
@cursorColumn=0
|
||||
updateCursorPos(true)
|
||||
return
|
||||
elsif Input.press?(Input::CTRL) && Input.triggerex?(:END)
|
||||
# Move cursor to end
|
||||
@cursorLine=getTotalLines()-1
|
||||
@cursorColumn=getColumnsInLine(@cursorLine)
|
||||
updateCursorPos(true)
|
||||
return
|
||||
elsif Input.triggerex?(:RETURN) || Input.repeatex?(:RETURN)
|
||||
self.insert("\n")
|
||||
return
|
||||
elsif Input.triggerex?(:BACKSPACE) || Input.repeatex?(:BACKSPACE) # Backspace
|
||||
self.delete
|
||||
return
|
||||
end
|
||||
Input.gets.each_char{|c|insert(c)}
|
||||
end
|
||||
|
||||
def refresh
|
||||
newContents=pbDoEnsureBitmap(self.contents,self.width-self.borderX,
|
||||
self.height-self.borderY)
|
||||
@textchars=nil if self.contents!=newContents
|
||||
self.contents=newContents
|
||||
bitmap=self.contents
|
||||
bitmap.clear
|
||||
getTextChars
|
||||
height=self.height-self.borderY
|
||||
cursorcolor=Color.new(0,0,0)
|
||||
textchars=getTextChars()
|
||||
startY=getLineY(@firstline)
|
||||
for i in 0...textchars.length
|
||||
thisline=textchars[i][5]
|
||||
thiscolumn=textchars[i][7]
|
||||
thislength=textchars[i][8]
|
||||
textY=textchars[i][2]-startY
|
||||
# Don't draw lines before the first or zero-length segments
|
||||
next if thisline<@firstline || thislength==0
|
||||
# Don't draw lines beyond the window's height
|
||||
break if textY >= height
|
||||
c=textchars[i][0]
|
||||
# Don't draw spaces
|
||||
next if c==" "
|
||||
textwidth=textchars[i][3]+4 # add 4 to prevent draw_text from stretching text
|
||||
textheight=textchars[i][4]
|
||||
# Draw text
|
||||
pbDrawShadowText(bitmap, textchars[i][1], textY, textwidth, textheight, c, @baseColor, @shadowColor)
|
||||
end
|
||||
# Draw cursor
|
||||
if ((@frame/10)&1) == 0
|
||||
textheight=bitmap.text_size("X").height
|
||||
cursorY=(textheight*@cursorLine)-startY
|
||||
cursorX=0
|
||||
for i in 0...textchars.length
|
||||
thisline=textchars[i][5]
|
||||
thiscolumn=textchars[i][7]
|
||||
thislength=textchars[i][8]
|
||||
if thisline==@cursorLine && @cursorColumn>=thiscolumn &&
|
||||
@cursorColumn<=thiscolumn+thislength
|
||||
cursorY=textchars[i][2]-startY
|
||||
cursorX=textchars[i][1]
|
||||
textheight=textchars[i][4]
|
||||
posToCursor=@cursorColumn-thiscolumn
|
||||
if posToCursor>=0
|
||||
partialString=textchars[i][0].scan(/./m)[0,posToCursor].join("")
|
||||
cursorX+=bitmap.text_size(partialString).width
|
||||
end
|
||||
break
|
||||
end
|
||||
end
|
||||
cursorY+=4
|
||||
cursorHeight=[4,textheight-4,bitmap.text_size("X").height-4].max
|
||||
bitmap.fill_rect(cursorX,cursorY,2,cursorHeight,cursorcolor)
|
||||
end
|
||||
end
|
||||
end
|
||||
Reference in New Issue
Block a user