local _, ParticleSystem = ...; local ParticleMixin = ParticleSystem.ParticleMixin; local Deformer = ParticleSystem.Deformer; local Collider = ParticleSystem.Collider; local Attractor = ParticleSystem.Attractor; local random = math.random; local tinsert = table.insert; local tremove = table.remove; local function Mixin(object, mixin) for k, v in pairs(mixin) do object[k] = v; end return object; end local function GetRandom() return (random(100, 200)/100); end local MAX_PARTICLES = 400; local NUM_PARTICLE_PER_PULSE = 8; local Emitter = CreateFrame("Frame"); local Pool = {}; Pool.all = {}; Pool.dead = {}; Pool.live = {}; Pool.numAll = 0; Pool.numDead = 0; Pool.numLive = 0; function ParticleMixin:Kill() self:Hide(); self.isLive = nil; self:ClearAllPoints(); --Add to the "deadpool" Pool:Collect(self); end local testContainer = CreateFrame("Frame"); testContainer:SetSize(256, 256); testContainer:SetPoint("CENTER", UIParent, "CENTER", 0, 0); local colliderTexture = testContainer:CreateTexture(nil, "OVERLAY"); colliderTexture:SetTexture("Interface\\AddOns\\Narcissus\\Art\\Particles\\Collider.tga"); colliderTexture:SetSize(64, 64); colliderTexture:SetPoint("CENTER", testContainer, "TOPLEFT", 128, -48); local labels = {"Total: ", "Live: ", "Dead: "}; local indicators = {}; for i = 1, 3 do indicators[i] = testContainer:CreateFontString(nil, "OVERLAY", "NarciTooltipDescriptionFontSmall"); indicators[i]:SetPoint("TOPLEFT", testContainer, "TOPLEFT", -80, -12 * i); local label = testContainer:CreateFontString(nil, "OVERLAY", "NarciTooltipDescriptionFontSmall"); label:SetPoint("TOPLEFT", testContainer, "TOPLEFT", -110, -12 * i); label:SetText(labels[i]); end function Pool:Accquire() local numDead = self.numDead; local p = self.dead[numDead]; if p then self.dead[numDead] = nil; self.numDead = numDead - 1; else local numAll = self.numAll; if numAll < MAX_PARTICLES then p = testContainer:CreateTexture(nil, "OVERLAY", "NarciDynamicTextParticleTemplate"); Mixin(p, ParticleMixin); numAll = numAll + 1; --self.all[numAll] = p; tinsert(self.all, p); self.numAll = numAll; p:ClearAllPoints(); p:SetParticleTexture("Interface\\AddOns\\Narcissus\\Art\\Particles\\Sphere.tga"); p:SetRadius(4); end end if p then self.numLive = self.numLive + 1; self.live[self.numLive] = p; return p end end function Pool:Collect(particle) for i = 1, self.numLive do if particle == self.live[i] then tremove(self.live, i); self.numLive = self.numLive - 1; break end end local numDead = self.numDead + 1; self.numDead = numDead; self.dead[numDead] = particle; end Deformer:SetParticleGroup(Pool.live); function Emitter:SetPosition(point, relativeTo, relativePoint, x, y) self:SetPoint(point, relativeTo, relativePoint, x, y); self.point = point; self.relativeTo = relativeTo; self.relativePoint = relativePoint; self.x0 = x; self.y0 = y; end function Emitter:SetVelocity(vX, vY) self.vX = vX or 0; self.vY = vY or 0; end function Emitter:SetBirthrate(birthrate) end function Emitter:SetInterval(interval) self.interval = interval or 0; end function Emitter:Start() self.t = 0; self:SetScript("OnUpdate", function(f, elapsed) self.t = self.t + elapsed; if self.t >= self.interval then self.t = 0; self:Emit(); --Counter indicators[1]:SetText(Pool.numAll); indicators[2]:SetText(Pool.numLive); indicators[3]:SetText(Pool.numDead); end end); end function Emitter:Stop() self:SetScript("OnUpdate", nil); end function Emitter:Emit() local p; for i = 1, NUM_PARTICLE_PER_PULSE do p = Pool:Accquire(); if p then p:Init(self.vX, self.vY); p:SetWeight( 1 ); --GetRandom() p:SetPosition(testContainer, "TOPLEFT", 0, -32 -4 * i); p:Show(); end end end Emitter:SetVelocity(0, 0); Emitter:SetInterval(0.2); --Public --/run TestEmitter() function TestEmitter() Emitter:SetVelocity(200, 0); Emitter:SetInterval(0.1); Emitter:Start(); Deformer:Start(); end local GetCursorPosition = GetCursorPosition; local UpdateFrame = CreateFrame("Frame"); UpdateFrame.t = 0 UpdateFrame:SetScript("OnUpdate", function(self, elapsed) self.x, self.y = GetCursorPosition(); colliderTexture:SetPoint("CENTER", UIParent, "BOTTOMLEFT", self.x, self.y); self.t = self.t + elapsed; if self.t > 0.0 then self.t = 0; if not self.x0 then self.x0 = testContainer:GetLeft(); self.y0 = testContainer:GetTop(); end --Collider:SetOffset(self.x - self.x0, self.y - self.y0); Attractor:SetOffset(self.x - self.x0, self.y - self.y0); end end);