346 lines
9.0 KiB
Lua
346 lines
9.0 KiB
Lua
local assert = assert
|
|
local ipairs = ipairs
|
|
local next = next
|
|
local pairs = pairs
|
|
local select = select
|
|
|
|
local function Mixin(object, ...)
|
|
for i = 1, select("#", ...) do
|
|
local mixin = select(i, ...);
|
|
for k, v in pairs(mixin) do
|
|
object[k] = v;
|
|
end
|
|
end
|
|
|
|
return object;
|
|
end
|
|
|
|
local function CreateFromMixins(...)
|
|
return Mixin({}, ...)
|
|
end
|
|
|
|
local function nop()
|
|
end
|
|
|
|
ObjectPoolMixin = {};
|
|
|
|
function ObjectPoolMixin:OnLoad(creationFunc, resetterFunc)
|
|
self.creationFunc = creationFunc;
|
|
self.resetterFunc = resetterFunc;
|
|
|
|
self.activeObjects = {};
|
|
self.inactiveObjects = {};
|
|
|
|
self.numActiveObjects = 0;
|
|
end
|
|
|
|
function ObjectPoolMixin:Acquire()
|
|
local numInactiveObjects = #self.inactiveObjects;
|
|
if numInactiveObjects > 0 then
|
|
local obj = self.inactiveObjects[numInactiveObjects];
|
|
self.activeObjects[obj] = true;
|
|
self.numActiveObjects = self.numActiveObjects + 1;
|
|
self.inactiveObjects[numInactiveObjects] = nil;
|
|
return obj, false;
|
|
end
|
|
|
|
local newObj = self.creationFunc(self);
|
|
if self.resetterFunc then
|
|
self.resetterFunc(self, newObj);
|
|
end
|
|
self.activeObjects[newObj] = true;
|
|
self.numActiveObjects = self.numActiveObjects + 1;
|
|
return newObj, true;
|
|
end
|
|
|
|
function ObjectPoolMixin:Release(obj)
|
|
if self:IsActive(obj) then
|
|
self.inactiveObjects[#self.inactiveObjects + 1] = obj;
|
|
self.activeObjects[obj] = nil;
|
|
self.numActiveObjects = self.numActiveObjects - 1;
|
|
if self.resetterFunc then
|
|
self.resetterFunc(self, obj);
|
|
end
|
|
|
|
return true;
|
|
end
|
|
|
|
return false;
|
|
end
|
|
|
|
function ObjectPoolMixin:ReleaseAll()
|
|
for obj in pairs(self.activeObjects) do
|
|
self:Release(obj);
|
|
end
|
|
end
|
|
|
|
function ObjectPoolMixin:EnumerateActive()
|
|
return pairs(self.activeObjects);
|
|
end
|
|
|
|
function ObjectPoolMixin:GetNextActive(current)
|
|
return (next(self.activeObjects, current));
|
|
end
|
|
|
|
function ObjectPoolMixin:IsActive(object)
|
|
return (self.activeObjects[object] ~= nil);
|
|
end
|
|
|
|
function ObjectPoolMixin:GetNumActive()
|
|
return self.numActiveObjects;
|
|
end
|
|
|
|
function ObjectPoolMixin:EnumerateInactive()
|
|
return ipairs(self.inactiveObjects);
|
|
end
|
|
|
|
function CreateObjectPool(creationFunc, resetterFunc)
|
|
local objectPool = CreateFromMixins(ObjectPoolMixin);
|
|
objectPool:OnLoad(creationFunc, resetterFunc);
|
|
return objectPool;
|
|
end
|
|
|
|
FramePoolMixin = CreateFromMixins(ObjectPoolMixin);
|
|
|
|
local function FramePoolFactory(framePool)
|
|
return CreateFrame(framePool.frameType, nil, framePool.parent, framePool.frameTemplate);
|
|
end
|
|
|
|
local function ForbiddenFramePoolFactory(framePool)
|
|
return CreateForbiddenFrame(framePool.frameType, nil, framePool.parent, framePool.frameTemplate);
|
|
end
|
|
|
|
function FramePoolMixin:OnLoad(frameType, parent, frameTemplate, resetterFunc, forbidden)
|
|
if forbidden then
|
|
ObjectPoolMixin.OnLoad(self, ForbiddenFramePoolFactory, resetterFunc);
|
|
else
|
|
ObjectPoolMixin.OnLoad(self, FramePoolFactory, resetterFunc);
|
|
end
|
|
self.frameType = frameType;
|
|
self.parent = parent;
|
|
self.frameTemplate = frameTemplate;
|
|
end
|
|
|
|
function FramePoolMixin:GetTemplate()
|
|
return self.frameTemplate;
|
|
end
|
|
|
|
function FramePool_Hide(framePool, frame)
|
|
frame:Hide();
|
|
end
|
|
|
|
function FramePool_HideAndClearAnchors(framePool, frame)
|
|
frame:Hide();
|
|
frame:ClearAllPoints();
|
|
end
|
|
|
|
function CreateFramePool(frameType, parent, frameTemplate, resetterFunc, forbidden)
|
|
local framePool = CreateFromMixins(FramePoolMixin);
|
|
framePool:OnLoad(frameType, parent, frameTemplate, resetterFunc or FramePool_HideAndClearAnchors, forbidden);
|
|
return framePool;
|
|
end
|
|
|
|
TexturePoolMixin = CreateFromMixins(ObjectPoolMixin);
|
|
|
|
local function TexturePoolFactory(texturePool)
|
|
return texturePool.parent:CreateTexture(nil, texturePool.layer, texturePool.textureTemplate);
|
|
end
|
|
|
|
function TexturePoolMixin:OnLoad(parent, layer, textureTemplate, resetterFunc)
|
|
ObjectPoolMixin.OnLoad(self, TexturePoolFactory, resetterFunc);
|
|
self.parent = parent;
|
|
self.layer = layer;
|
|
self.textureTemplate = textureTemplate;
|
|
end
|
|
|
|
TexturePool_Hide = FramePool_Hide;
|
|
TexturePool_HideAndClearAnchors = FramePool_HideAndClearAnchors;
|
|
|
|
function CreateTexturePool(parent, layer, textureTemplate, resetterFunc)
|
|
local texturePool = CreateFromMixins(TexturePoolMixin);
|
|
texturePool:OnLoad(parent, layer, textureTemplate, resetterFunc or TexturePool_HideAndClearAnchors);
|
|
return texturePool;
|
|
end
|
|
|
|
FontStringPoolMixin = CreateFromMixins(ObjectPoolMixin);
|
|
|
|
local function FontStringPoolFactory(fontStringPool)
|
|
return fontStringPool.parent:CreateFontString(nil, fontStringPool.layer, fontStringPool.fontStringTemplate);
|
|
end
|
|
|
|
function FontStringPoolMixin:OnLoad(parent, layer, fontStringTemplate, resetterFunc)
|
|
ObjectPoolMixin.OnLoad(self, FontStringPoolFactory, resetterFunc);
|
|
self.parent = parent;
|
|
self.layer = layer;
|
|
self.fontStringTemplate = fontStringTemplate;
|
|
end
|
|
|
|
FontStringPool_Hide = FramePool_Hide;
|
|
FontStringPool_HideAndClearAnchors = FramePool_HideAndClearAnchors;
|
|
|
|
function CreateFontStringPool(parent, layer, fontStringTemplate, resetterFunc)
|
|
local fontStringPool = CreateFromMixins(FontStringPoolMixin);
|
|
fontStringPool:OnLoad(parent, layer, fontStringTemplate, resetterFunc or FontStringPool_HideAndClearAnchors);
|
|
return fontStringPool;
|
|
end
|
|
|
|
ActorPoolMixin = CreateFromMixins(ObjectPoolMixin);
|
|
|
|
local function ActorPoolFactory(actorPool)
|
|
return actorPool.parent:CreateActor(nil, actorPool.actorTemplate);
|
|
end
|
|
|
|
function ActorPoolMixin:OnLoad(parent, actorTemplate, resetterFunc)
|
|
ObjectPoolMixin.OnLoad(self, ActorPoolFactory, resetterFunc);
|
|
self.parent = parent;
|
|
self.actorTemplate = actorTemplate;
|
|
end
|
|
|
|
ActorPool_Hide = FramePool_Hide;
|
|
function ActorPool_HideAndClearModel(actorPool, actor)
|
|
actor:ClearModel();
|
|
actor:Hide();
|
|
end
|
|
|
|
function CreateActorPool(parent, actorTemplate, resetterFunc)
|
|
local actorPool = CreateFromMixins(ActorPoolMixin);
|
|
actorPool:OnLoad(parent, actorTemplate, resetterFunc or ActorPool_HideAndClearModel);
|
|
return actorPool;
|
|
end
|
|
|
|
FramePoolCollectionMixin = {};
|
|
|
|
function CreateFramePoolCollection()
|
|
local poolCollection = CreateFromMixins(FramePoolCollectionMixin);
|
|
poolCollection:OnLoad();
|
|
return poolCollection;
|
|
end
|
|
|
|
function FramePoolCollectionMixin:OnLoad()
|
|
self.pools = {};
|
|
end
|
|
|
|
function FramePoolCollectionMixin:GetNumActive()
|
|
local numTotalActive = 0;
|
|
for _, pool in pairs(self.pools) do
|
|
numTotalActive = numTotalActive + pool:GetNumActive();
|
|
end
|
|
return numTotalActive;
|
|
end
|
|
|
|
function FramePoolCollectionMixin:GetOrCreatePool(frameType, parent, template, resetterFunc, forbidden)
|
|
local pool = self:GetPool(template);
|
|
if not pool then
|
|
pool = self:CreatePool(frameType, parent, template, resetterFunc, forbidden);
|
|
end
|
|
return pool;
|
|
end
|
|
|
|
function FramePoolCollectionMixin:CreatePool(frameType, parent, template, resetterFunc, forbidden)
|
|
assert(self:GetPool(template) == nil);
|
|
local pool = CreateFramePool(frameType, parent, template, resetterFunc, forbidden);
|
|
self.pools[template] = pool;
|
|
return pool;
|
|
end
|
|
|
|
function FramePoolCollectionMixin:GetPool(template)
|
|
return self.pools[template];
|
|
end
|
|
|
|
function FramePoolCollectionMixin:Acquire(template)
|
|
local pool = self:GetPool(template);
|
|
assert(pool);
|
|
return pool:Acquire();
|
|
end
|
|
|
|
function FramePoolCollectionMixin:Release(object)
|
|
for _, pool in pairs(self.pools) do
|
|
if pool:Release(object) then
|
|
-- Found it! Just return
|
|
return;
|
|
end
|
|
end
|
|
|
|
-- Huh, we didn't find that object
|
|
assert(false);
|
|
end
|
|
|
|
function FramePoolCollectionMixin:ReleaseAllByTemplate(template)
|
|
local pool = self:GetPool(template);
|
|
if pool then
|
|
pool:ReleaseAll();
|
|
end
|
|
end
|
|
|
|
function FramePoolCollectionMixin:ReleaseAll()
|
|
for key, pool in pairs(self.pools) do
|
|
pool:ReleaseAll();
|
|
end
|
|
end
|
|
|
|
function FramePoolCollectionMixin:EnumerateActiveByTemplate(template)
|
|
local pool = self:GetPool(template);
|
|
if pool then
|
|
return pool:EnumerateActive();
|
|
end
|
|
|
|
return nop;
|
|
end
|
|
|
|
function FramePoolCollectionMixin:EnumerateActive()
|
|
local currentPoolKey, currentPool = next(self.pools, nil);
|
|
local currentObject = nil;
|
|
return function()
|
|
if currentPool then
|
|
currentObject = currentPool:GetNextActive(currentObject);
|
|
while not currentObject do
|
|
currentPoolKey, currentPool = next(self.pools, currentPoolKey);
|
|
if currentPool then
|
|
currentObject = currentPool:GetNextActive();
|
|
else
|
|
break;
|
|
end
|
|
end
|
|
end
|
|
|
|
return currentObject;
|
|
end, nil;
|
|
end
|
|
|
|
FixedSizeFramePoolCollectionMixin = CreateFromMixins(FramePoolCollectionMixin);
|
|
|
|
function CreateFixedSizeFramePoolCollection()
|
|
local poolCollection = CreateFromMixins(FixedSizeFramePoolCollectionMixin);
|
|
poolCollection:OnLoad();
|
|
return poolCollection;
|
|
end
|
|
|
|
function FixedSizeFramePoolCollectionMixin:OnLoad()
|
|
FramePoolCollectionMixin.OnLoad(self);
|
|
self.sizes = {};
|
|
end
|
|
|
|
function FixedSizeFramePoolCollectionMixin:CreatePool(frameType, parent, template, resetterFunc, forbidden, maxPoolSize, preallocate)
|
|
local pool = FramePoolCollectionMixin.CreatePool(self, frameType, parent, template, resetterFunc, forbidden);
|
|
|
|
if preallocate then
|
|
for i = 1, maxPoolSize do
|
|
pool:Acquire();
|
|
end
|
|
pool:ReleaseAll();
|
|
end
|
|
|
|
self.sizes[template] = maxPoolSize;
|
|
|
|
return pool;
|
|
end
|
|
|
|
function FixedSizeFramePoolCollectionMixin:Acquire(template)
|
|
local pool = self:GetPool(template);
|
|
assert(pool);
|
|
|
|
if pool:GetNumActive() < self.sizes[template] then
|
|
return pool:Acquire();
|
|
end
|
|
return nil;
|
|
end |