Pools.lua

Pools.lua (9.0.2.36710; unchanged since 9.0.1.36230)
  1. ---------------
  2. --NOTE - Please do not change this section without talking to Dan
  3. local _, tbl = ...;
  4. if tbl then
  5. tbl.SecureCapsuleGet = SecureCapsuleGet;
  6. local function Import(name)
  7. tbl[name] = tbl.SecureCapsuleGet(name);
  8. end
  9. Import("IsOnGlueScreen");
  10. if ( tbl.IsOnGlueScreen() ) then
  11. tbl._G = _G; --Allow us to explicitly access the global environment at the glue screens
  12. end
  13. setfenv(1, tbl);
  14. Import("pairs");
  15. Import("ipairs");
  16. Import("next");
  17. Import("CreateFrame");
  18. end
  19. ----------------
  20. ObjectPoolMixin = {};
  21. function ObjectPoolMixin:OnLoad(creationFunc, resetterFunc)
  22. self.creationFunc = creationFunc;
  23. self.resetterFunc = resetterFunc;
  24. self.activeObjects = {};
  25. self.inactiveObjects = {};
  26. self.numActiveObjects = 0;
  27. end
  28. function ObjectPoolMixin:Acquire()
  29. local numInactiveObjects = #self.inactiveObjects;
  30. if numInactiveObjects > 0 then
  31. local obj = self.inactiveObjects[numInactiveObjects];
  32. self.activeObjects[obj] = true;
  33. self.numActiveObjects = self.numActiveObjects + 1;
  34. self.inactiveObjects[numInactiveObjects] = nil;
  35. return obj, false;
  36. end
  37. local newObj = self.creationFunc(self);
  38. if self.resetterFunc then
  39. self.resetterFunc(self, newObj);
  40. end
  41. self.activeObjects[newObj] = true;
  42. self.numActiveObjects = self.numActiveObjects + 1;
  43. return newObj, true;
  44. end
  45. function ObjectPoolMixin:Release(obj)
  46. if self:IsActive(obj) then
  47. self.inactiveObjects[#self.inactiveObjects + 1] = obj;
  48. self.activeObjects[obj] = nil;
  49. self.numActiveObjects = self.numActiveObjects - 1;
  50. if self.resetterFunc then
  51. self.resetterFunc(self, obj);
  52. end
  53. return true;
  54. end
  55. return false;
  56. end
  57. function ObjectPoolMixin:ReleaseAll()
  58. for obj in pairs(self.activeObjects) do
  59. self:Release(obj);
  60. end
  61. end
  62. function ObjectPoolMixin:EnumerateActive()
  63. return pairs(self.activeObjects);
  64. end
  65. function ObjectPoolMixin:GetNextActive(current)
  66. return (next(self.activeObjects, current));
  67. end
  68. function ObjectPoolMixin:GetNextInactive(current)
  69. return (next(self.inactiveObjects, current));
  70. end
  71. function ObjectPoolMixin:IsActive(object)
  72. return (self.activeObjects[object] ~= nil);
  73. end
  74. function ObjectPoolMixin:GetNumActive()
  75. return self.numActiveObjects;
  76. end
  77. function ObjectPoolMixin:EnumerateInactive()
  78. return ipairs(self.inactiveObjects);
  79. end
  80. function CreateObjectPool(creationFunc, resetterFunc)
  81. local objectPool = CreateFromMixins(ObjectPoolMixin);
  82. objectPool:OnLoad(creationFunc, resetterFunc);
  83. return objectPool;
  84. end
  85. FramePoolMixin = CreateFromMixins(ObjectPoolMixin);
  86. local function FramePoolFactory(framePool)
  87. return CreateFrame(framePool.frameType, nil, framePool.parent, framePool.frameTemplate);
  88. end
  89. local function ForbiddenFramePoolFactory(framePool)
  90. return CreateForbiddenFrame(framePool.frameType, nil, framePool.parent, framePool.frameTemplate);
  91. end
  92. function FramePoolMixin:OnLoad(frameType, parent, frameTemplate, resetterFunc, forbidden)
  93. if forbidden then
  94. ObjectPoolMixin.OnLoad(self, ForbiddenFramePoolFactory, resetterFunc);
  95. else
  96. ObjectPoolMixin.OnLoad(self, FramePoolFactory, resetterFunc);
  97. end
  98. self.frameType = frameType;
  99. self.parent = parent;
  100. self.frameTemplate = frameTemplate;
  101. end
  102. function FramePoolMixin:GetTemplate()
  103. return self.frameTemplate;
  104. end
  105. function FramePool_Hide(framePool, frame)
  106. frame:Hide();
  107. end
  108. function FramePool_HideAndClearAnchors(framePool, frame)
  109. frame:Hide();
  110. frame:ClearAllPoints();
  111. end
  112. function CreateFramePool(frameType, parent, frameTemplate, resetterFunc, forbidden)
  113. local framePool = CreateFromMixins(FramePoolMixin);
  114. framePool:OnLoad(frameType, parent, frameTemplate, resetterFunc or FramePool_HideAndClearAnchors, forbidden);
  115. return framePool;
  116. end
  117. TexturePoolMixin = CreateFromMixins(ObjectPoolMixin);
  118. local function TexturePoolFactory(texturePool)
  119. return texturePool.parent:CreateTexture(nil, texturePool.layer, texturePool.textureTemplate, texturePool.subLayer);
  120. end
  121. function TexturePoolMixin:OnLoad(parent, layer, subLayer, textureTemplate, resetterFunc)
  122. ObjectPoolMixin.OnLoad(self, TexturePoolFactory, resetterFunc);
  123. self.parent = parent;
  124. self.layer = layer;
  125. self.subLayer = subLayer;
  126. self.textureTemplate = textureTemplate;
  127. end
  128. TexturePool_Hide = FramePool_Hide;
  129. TexturePool_HideAndClearAnchors = FramePool_HideAndClearAnchors;
  130. function CreateTexturePool(parent, layer, subLayer, textureTemplate, resetterFunc)
  131. local texturePool = CreateFromMixins(TexturePoolMixin);
  132. texturePool:OnLoad(parent, layer, subLayer, textureTemplate, resetterFunc or TexturePool_HideAndClearAnchors);
  133. return texturePool;
  134. end
  135. FontStringPoolMixin = CreateFromMixins(ObjectPoolMixin);
  136. local function FontStringPoolFactory(fontStringPool)
  137. return fontStringPool.parent:CreateFontString(nil, fontStringPool.layer, fontStringPool.fontStringTemplate, fontStringPool.subLayer);
  138. end
  139. function FontStringPoolMixin:OnLoad(parent, layer, subLayer, fontStringTemplate, resetterFunc)
  140. ObjectPoolMixin.OnLoad(self, FontStringPoolFactory, resetterFunc);
  141. self.parent = parent;
  142. self.layer = layer;
  143. self.subLayer = subLayer;
  144. self.fontStringTemplate = fontStringTemplate;
  145. end
  146. FontStringPool_Hide = FramePool_Hide;
  147. FontStringPool_HideAndClearAnchors = FramePool_HideAndClearAnchors;
  148. function CreateFontStringPool(parent, layer, subLayer, fontStringTemplate, resetterFunc)
  149. local fontStringPool = CreateFromMixins(FontStringPoolMixin);
  150. fontStringPool:OnLoad(parent, layer, subLayer, fontStringTemplate, resetterFunc or FontStringPool_HideAndClearAnchors);
  151. return fontStringPool;
  152. end
  153. ActorPoolMixin = CreateFromMixins(ObjectPoolMixin);
  154. local function ActorPoolFactory(actorPool)
  155. return actorPool.parent:CreateActor(nil, actorPool.actorTemplate);
  156. end
  157. function ActorPoolMixin:OnLoad(parent, actorTemplate, resetterFunc)
  158. ObjectPoolMixin.OnLoad(self, ActorPoolFactory, resetterFunc);
  159. self.parent = parent;
  160. self.actorTemplate = actorTemplate;
  161. end
  162. ActorPool_Hide = FramePool_Hide;
  163. function ActorPool_HideAndClearModel(actorPool, actor)
  164. actor:ClearModel();
  165. actor:Hide();
  166. end
  167. function CreateActorPool(parent, actorTemplate, resetterFunc)
  168. local actorPool = CreateFromMixins(ActorPoolMixin);
  169. actorPool:OnLoad(parent, actorTemplate, resetterFunc or ActorPool_HideAndClearModel);
  170. return actorPool;
  171. end
  172. FramePoolCollectionMixin = {};
  173. function CreateFramePoolCollection()
  174. local poolCollection = CreateFromMixins(FramePoolCollectionMixin);
  175. poolCollection:OnLoad();
  176. return poolCollection;
  177. end
  178. function FramePoolCollectionMixin:OnLoad()
  179. self.pools = {};
  180. end
  181. function FramePoolCollectionMixin:GetNumActive()
  182. local numTotalActive = 0;
  183. for _, pool in pairs(self.pools) do
  184. numTotalActive = numTotalActive + pool:GetNumActive();
  185. end
  186. return numTotalActive;
  187. end
  188. function FramePoolCollectionMixin:GetOrCreatePool(frameType, parent, template, resetterFunc, forbidden)
  189. local pool = self:GetPool(template);
  190. if not pool then
  191. pool = self:CreatePool(frameType, parent, template, resetterFunc, forbidden);
  192. end
  193. return pool;
  194. end
  195. function FramePoolCollectionMixin:CreatePool(frameType, parent, template, resetterFunc, forbidden)
  196. assert(self:GetPool(template) == nil);
  197. local pool = CreateFramePool(frameType, parent, template, resetterFunc, forbidden);
  198. self.pools[template] = pool;
  199. return pool;
  200. end
  201. function FramePoolCollectionMixin:GetPool(template)
  202. return self.pools[template];
  203. end
  204. function FramePoolCollectionMixin:Acquire(template)
  205. local pool = self:GetPool(template);
  206. assert(pool);
  207. return pool:Acquire();
  208. end
  209. function FramePoolCollectionMixin:Release(object)
  210. for _, pool in pairs(self.pools) do
  211. if pool:Release(object) then
  212. -- Found it! Just return
  213. return;
  214. end
  215. end
  216. -- Huh, we didn't find that object
  217. assert(false);
  218. end
  219. function FramePoolCollectionMixin:ReleaseAllByTemplate(template)
  220. local pool = self:GetPool(template);
  221. if pool then
  222. pool:ReleaseAll();
  223. end
  224. end
  225. function FramePoolCollectionMixin:ReleaseAll()
  226. for key, pool in pairs(self.pools) do
  227. pool:ReleaseAll();
  228. end
  229. end
  230. function FramePoolCollectionMixin:EnumerateActiveByTemplate(template)
  231. local pool = self:GetPool(template);
  232. if pool then
  233. return pool:EnumerateActive();
  234. end
  235. return nop;
  236. end
  237. function FramePoolCollectionMixin:EnumerateActive()
  238. local currentPoolKey, currentPool = next(self.pools, nil);
  239. local currentObject = nil;
  240. return function()
  241. if currentPool then
  242. currentObject = currentPool:GetNextActive(currentObject);
  243. while not currentObject do
  244. currentPoolKey, currentPool = next(self.pools, currentPoolKey);
  245. if currentPool then
  246. currentObject = currentPool:GetNextActive();
  247. else
  248. break;
  249. end
  250. end
  251. end
  252. return currentObject;
  253. end, nil;
  254. end
  255. function FramePoolCollectionMixin:EnumerateInactiveByTemplate(template)
  256. local pool = self:GetPool(template);
  257. if pool then
  258. return pool:EnumerateInactive();
  259. end
  260. return nop;
  261. end
  262. function FramePoolCollectionMixin:EnumerateInactive()
  263. local currentPoolKey, currentPool = next(self.pools, nil);
  264. local currentObject = nil;
  265. return function()
  266. if currentPool then
  267. currentObject = currentPool:GetNextInactive(currentObject);
  268. while not currentObject do
  269. currentPoolKey, currentPool = next(self.pools, currentPoolKey);
  270. if currentPool then
  271. currentObject = currentPool:GetNextInactive();
  272. else
  273. break;
  274. end
  275. end
  276. end
  277. return currentObject;
  278. end, nil;
  279. end
  280. FixedSizeFramePoolCollectionMixin = CreateFromMixins(FramePoolCollectionMixin);
  281. function CreateFixedSizeFramePoolCollection()
  282. local poolCollection = CreateFromMixins(FixedSizeFramePoolCollectionMixin);
  283. poolCollection:OnLoad();
  284. return poolCollection;
  285. end
  286. function FixedSizeFramePoolCollectionMixin:OnLoad()
  287. FramePoolCollectionMixin.OnLoad(self);
  288. self.sizes = {};
  289. end
  290. function FixedSizeFramePoolCollectionMixin:CreatePool(frameType, parent, template, resetterFunc, forbidden, maxPoolSize, preallocate)
  291. local pool = FramePoolCollectionMixin.CreatePool(self, frameType, parent, template, resetterFunc, forbidden);
  292. if preallocate then
  293. for i = 1, maxPoolSize do
  294. pool:Acquire();
  295. end
  296. pool:ReleaseAll();
  297. end
  298. self.sizes[template] = maxPoolSize;
  299. return pool;
  300. end
  301. function FixedSizeFramePoolCollectionMixin:Acquire(template)
  302. local pool = self:GetPool(template);
  303. assert(pool);
  304. if pool:GetNumActive() < self.sizes[template] then
  305. return pool:Acquire();
  306. end
  307. return nil;
  308. end