Tweaks to BitmapCache

This commit is contained in:
Maruno17
2021-02-08 19:25:54 +00:00
parent 0c7aab530d
commit 8b5b9d5fc4

View File

@@ -2,34 +2,35 @@ class Hangup < Exception; end
def strsplit(str,re) def strsplit(str, re)
ret=[] ret = []
tstr=str tstr = str
while re=~tstr while re = ~tstr
ret[ret.length]=$~.pre_match ret[ret.length] = $~.pre_match
tstr=$~.post_match tstr = $~.post_match
end end
ret[ret.length]=tstr if ret.length ret[ret.length] = tstr if ret.length
return ret return ret
end end
def canonicalize(c) def canonicalize(c)
csplit = strsplit(c,/[\/\\]/) csplit = strsplit(c, /[\/\\]/)
pos = -1 pos = -1
ret = [] ret = []
retstr = "" retstr = ""
for x in csplit for x in csplit
if x=="." if x == ".."
elsif x==".." if pos >= 0
ret.delete_at(pos) if pos>=0 ret.delete_at(pos)
pos -= 1 pos -= 1
else end
elsif x != "."
ret.push(x) ret.push(x)
pos += 1 pos += 1
end end
end end
for i in 0...ret.length for i in 0...ret.length
retstr += "/" if i>0 retstr += "/" if i > 0
retstr += ret[i] retstr += ret[i]
end end
return retstr return retstr
@@ -38,6 +39,7 @@ end
##################################################################### #####################################################################
# TODO: Delete this class in Ruby 2+.
class WeakRef class WeakRef
@@id_map = {} @@id_map = {}
@@id_rev_map = {} @@id_rev_map = {}
@@ -91,6 +93,7 @@ end
# TODO: Delete this class in Ruby 2+.
class WeakHashtable class WeakHashtable
include Enumerable include Enumerable
@@ -123,73 +126,29 @@ class WeakHashtable
end end
def [](key) def [](key)
o=@hash[key] o = @hash[key]
return o if !o return o if !o
if o.weakref_alive? if o.weakref_alive?
o=o.__getobj__ o = o.__getobj__
else else
@hash.delete(key) @hash.delete(key)
o=nil o = nil
end end
return o return o
end end
def []=(key,o) def []=(key, o)
if o!=nil o = WeakRef.new(o) if o != nil
o=WeakRef.new(o) @hash[key] = o
end
@hash[key]=o
end end
end end
# Cache from RPG Maker VX library
module Cache
def self.system(x,hue=0)
BitmapCache.load_bitmap("Graphics/System/"+x,hue, true)
end
def self.character(x,hue=0)
BitmapCache.load_bitmap("Graphics/Characters/"+x,hue, true)
end
def self.picture(x,hue=0)
BitmapCache.load_bitmap("Graphics/Pictures/"+x,hue, true)
end
def self.animation(x,hue=0)
BitmapCache.load_bitmap("Graphics/Animations/"+x,hue, true)
end
def self.battler(x,hue=0)
BitmapCache.load_bitmap("Graphics/Battlers/"+x,hue, true)
end
def self.face(x,hue=0)
BitmapCache.load_bitmap("Graphics/Faces/"+x,hue, true)
end
def self.parallax(x,hue=0)
BitmapCache.load_bitmap("Graphics/Parallaxes/"+x,hue, true)
end
def self.clear
BitmapCache.clear()
end
def self.load_bitmap(dir,name,hue=0)
BitmapCache.load_bitmap(dir+name,hue, true)
end
end
# RPG::Cache from RPG Maker XP library
module RPG module RPG
module Cache module Cache
def self.load_bitmap(folder_name, filename, hue = 0) def self.load_bitmap(folder_name, filename, hue = 0)
BitmapCache.load_bitmap(folder_name+filename.to_s,hue, true) BitmapCache.load_bitmap(folder_name + filename.to_s, hue, true)
end end
def self.animation(filename, hue) def self.animation(filename, hue)
@@ -245,7 +204,7 @@ module RPG
end end
def self.tile(filename, tile_id, hue) def self.tile(filename, tile_id, hue)
BitmapCache.tile(filename,tile_id,hue) BitmapCache.tile(filename, tile_id, hue)
end end
def self.clear def self.clear
@@ -259,53 +218,52 @@ end
class BitmapWrapper < Bitmap class BitmapWrapper < Bitmap
attr_reader :refcount attr_reader :refcount
@@disposedBitmaps={}
@@keys={}
def dispose def dispose
return if self.disposed? return if self.disposed?
@refcount-=1 @refcount -= 1
super if @refcount==0 super if @refcount == 0
end end
def initialize(*arg) def initialize(*arg)
super super
@refcount=1 @refcount = 1
end end
def resetRef def resetRef
@refcount=1 @refcount = 1
end end
def copy def copy
bm=self.clone bm = self.clone
bm.resetRef bm.resetRef
return bm return bm
end end
def addRef def addRef
@refcount+=1 @refcount += 1
end end
end end
module BitmapCache module BitmapCache
# TODO: Replace this with the commented line in Ruby 2+.
@cache = WeakHashtable.new @cache = WeakHashtable.new
# @cache = ObjectSpace::WeakMap.new
def self.fromCache(i) def self.fromCache(i)
return nil if !@cache.include?(i) return nil if !@cache.include?(i)
obj=@cache[i] obj = @cache[i]
return nil if obj && obj.disposed? return nil if obj && obj.disposed?
return obj return obj
end end
def self.setKey(key,obj) def self.setKey(key, obj)
@cache[key]=obj @cache[key] = obj
end end
def self.debug def self.debug
File.open("bitmapcache2.txt","wb") { |f| File.open("bitmapcache2.txt", "wb") { |f|
for i in @cache.keys for i in @cache.keys
k = fromCache(i) k = fromCache(i)
if !k if !k
@@ -321,31 +279,33 @@ module BitmapCache
def self.load_bitmap(path, hue = 0, failsafe = false) def self.load_bitmap(path, hue = 0, failsafe = false)
cached = true cached = true
path = canonicalize(path) path = -canonicalize(path) # Creates a frozen string from the path, to ensure identical paths are treated as identical.
objPath = fromCache(path) objPath = fromCache(path)
if !objPath if !objPath
@cleancounter = ((@cleancounter || 0) + 1)%10 # TODO: Delete this in Ruby 2+.
@cleancounter = ((@cleancounter || 0) + 1) % 10
if @cleancounter == 0 if @cleancounter == 0
for i in @cache.keys for i in @cache.keys
@cache.delete(i) if !fromCache(i) @cache.delete(i) if !fromCache(i)
end end
end end
# TODO: Up to here.
begin begin
bm = BitmapWrapper.new(path) bm = BitmapWrapper.new(path)
rescue Hangup rescue Hangup
begin begin
bm = BitmapWrapper.new(path) bm = BitmapWrapper.new(path)
rescue rescue
raise _INTL("Failed to load the bitmap located at: {1}",path) if !failsafe raise _INTL("Failed to load the bitmap located at: {1}", path) if !failsafe
bm = BitmapWrapper.new(32,32) bm = BitmapWrapper.new(32, 32)
end end
rescue rescue
raise _INTL("Failed to load the bitmap located at: {1}",path) if !failsafe raise _INTL("Failed to load the bitmap located at: {1}", path) if !failsafe
bm = BitmapWrapper.new(32,32) bm = BitmapWrapper.new(32, 32)
end end
objPath = bm objPath = bm
@cache[path] = objPath @cache[path] = objPath
cached=false cached = false
end end
if hue == 0 if hue == 0
objPath.addRef if cached objPath.addRef if cached
@@ -355,7 +315,7 @@ module BitmapCache
objKey = fromCache(key) objKey = fromCache(key)
if !objKey if !objKey
bitmap = objPath.copy bitmap = objPath.copy
bitmap.hue_change(hue) if hue!=0 bitmap.hue_change(hue) if hue != 0
objKey = bitmap objKey = bitmap
@cache[key] = objKey @cache[key] = objKey
else else
@@ -366,71 +326,71 @@ module BitmapCache
end end
def self.animation(filename, hue) def self.animation(filename, hue)
self.load_bitmap("Graphics/Animations/"+filename, hue) self.load_bitmap("Graphics/Animations/" + filename, hue)
end end
def self.autotile(filename) def self.autotile(filename)
self.load_bitmap("Graphics/Autotiles/"+ filename) self.load_bitmap("Graphics/Autotiles/" + filename)
end end
def self.battleback(filename) def self.battleback(filename)
self.load_bitmap("Graphics/Battlebacks/"+ filename) self.load_bitmap("Graphics/Battlebacks/" + filename)
end end
def self.battler(filename, hue) def self.battler(filename, hue)
self.load_bitmap("Graphics/Battlers/"+ filename, hue) self.load_bitmap("Graphics/Battlers/" + filename, hue)
end end
def self.character(filename, hue) def self.character(filename, hue)
self.load_bitmap("Graphics/Characters/"+ filename, hue) self.load_bitmap("Graphics/Characters/" + filename, hue)
end end
def self.fog(filename, hue) def self.fog(filename, hue)
self.load_bitmap("Graphics/Fogs/"+ filename, hue) self.load_bitmap("Graphics/Fogs/" + filename, hue)
end end
def self.gameover(filename) def self.gameover(filename)
self.load_bitmap("Graphics/Gameovers/"+ filename) self.load_bitmap("Graphics/Gameovers/" + filename)
end end
def self.icon(filename) def self.icon(filename)
self.load_bitmap("Graphics/Icons/"+ filename) self.load_bitmap("Graphics/Icons/" + filename)
end end
def self.panorama(filename, hue) def self.panorama(filename, hue)
self.load_bitmap("Graphics/Panoramas/"+ filename, hue) self.load_bitmap("Graphics/Panoramas/" + filename, hue)
end end
def self.picture(filename) def self.picture(filename)
self.load_bitmap("Graphics/Pictures/"+ filename) self.load_bitmap("Graphics/Pictures/" + filename)
end end
def self.tileset(filename) def self.tileset(filename)
self.load_bitmap("Graphics/Tilesets/"+ filename) self.load_bitmap("Graphics/Tilesets/" + filename)
end end
def self.title(filename) def self.title(filename)
self.load_bitmap("Graphics/Titles/"+ filename) self.load_bitmap("Graphics/Titles/" + filename)
end end
def self.windowskin(filename) def self.windowskin(filename)
self.load_bitmap("Graphics/Windowskins/"+ filename) self.load_bitmap("Graphics/Windowskins/" + filename)
end end
def self.tileEx(filename, tile_id, hue) def self.tileEx(filename, tile_id, hue)
key = [filename, tile_id, hue] key = [filename, tile_id, hue]
objKey=fromCache(key) objKey = fromCache(key)
if !objKey if !objKey
bitmap=BitmapWrapper.new(32, 32) bitmap = BitmapWrapper.new(Game_Map::TILE_WIDTH, Game_Map::TILE_HEIGHT)
x = (tile_id - 384) % 8 * 32 x = (tile_id - 384) % 8 * 32
y = (tile_id - 384) / 8 * 32 y = (tile_id - 384) / 8 * 32
rect = Rect.new(x, y, 32, 32) rect = Rect.new(x, y, Game_Map::TILE_WIDTH, Game_Map::TILE_HEIGHT)
tileset = yield(filename) tileset = yield(filename)
bitmap.blt(0, 0, tileset, rect) bitmap.blt(0, 0, tileset, rect)
tileset.dispose tileset.dispose
bitmap.hue_change(hue) if hue!=0 bitmap.hue_change(hue) if hue != 0
objKey=bitmap objKey = bitmap
@cache[key]=objKey @cache[key] = objKey
else else
objKey.addRef objKey.addRef
end end
@@ -438,11 +398,13 @@ module BitmapCache
end end
def self.tile(filename, tile_id, hue) def self.tile(filename, tile_id, hue)
return self.tileEx(filename, tile_id,hue) { |f| self.tileset(f) } return self.tileEx(filename, tile_id, hue) { |f| self.tileset(f) }
end end
def self.clear def self.clear
@cache = {} # TODO: Replace this with the commented line in Ruby 2+.
@cache.clear
# @cache = ObjectSpace::WeakMap.new
GC.start GC.start
end end
end end