It's not documented in the wiki but it looks like what you need is the ZO_ControlPool.
Use \zgoo and take a look at that table to see how it works. You can pass a virtual template to it as well.
An example of it in use is in both my Gatherer addon as well as Shinni's HarvestMap addon and the CustomCompassPins library addon.
Take a browse through those and see if you can see how it will work in your situation.
As a taster, this is a portion of the control pool class in action in my addon. Half of the functionality is dealt with behind the scenes by ESO's ControlPool class but there are a few classes based off of it like ZO_MapPin if I remember rightly, although I couldn't use that sub class myself so stuck with the control pool for functionality. In the New() function the XRGACompassPin is my template control to use for this class and ZO_CompassContainer the parent. The "Pin" I suspect is a suffix to the internally generated control name which then has a number added to it. This last info is based on the one error I received that implied the generated pin control ended with Pin01.
Lua Code:
local CompassPinManager = ZO_ControlPool:Subclass()
-- Create the compass manager pin using the template in the xml file
function CompassPinManager:New( ... )
local CompassManager = ZO_ControlPool.New(self, "XRGACompassPin", ZO_CompassContainer, "Pin")
CompassManager:Initialize( ... )
return CompassManager
end
-- Initialise the new compass manager and link it to the map pin manager
function CompassPinManager:Initialize(MapPinManager)
self.Data = {}
self.Layouts = {}
self.Filters = {}
self.MapPinManager = MapPinManager
end
-- Create the requested pinType and set the layout
function CompassPinManager:CreatePinType( pinType, pinLayout )
if not self.Data and not self.Layouts and not self.MapPinManager then return end
pinLayout.size = 20
self.Layouts[ pinType ] = pinLayout
self.Data[ pinType ] = {}
end
-- Create the specific pin at the specified location
function CompassPinManager:CreatePin( pinType, pinX, pinY, pinZ, pinRadius )
if not self.Data and not self.Layouts and not self.MapPinManager then return end
local pin, pinKey = self:AcquireObject()
table.insert( self.Data[ pinType ], pinKey )
pin.x = pinX
pin.y = pinY
pin.z = pinZ
pin.radius = pinRadius
pin.type = pinType
local layout = self.Layouts[ pinType ]
local texture = pin:GetNamedChild( "Background" )
texture:SetTexture( layout.texture )
end
-- Remove the selected pin type
function CompassPinManager:RemovePins( pinType )
if not self.Data then return end
if not pinType then
self:ReleaseAllObjects()
for pinType, pinData in pairs( self.Data ) do
self.Data[ pinType ] = {}
end
else
for pinID, pinKey in pairs( self.Data[ pinType ] ) do
self:ReleaseObject( pinKey )
end
self.Data[ pinType ] = {}
end
end
Once something similar to the above is set up a simple call to the following will allow you to use it:
local compassPinManager = CompassPinManager:New()
Then all you will need to use is the compassPinManager to work on a manager instance that will handle all objects of that 'type'. As you can see there are calls to AcquireObject and ReleaseObject. These will work behind the scenes to release and locate the next available object to use. There are probably more functions that can be customised as needed but I didn't need to use them all so I didn't use them.
If you are used to release and recreate you may be able to figure this functionality out pretty quickly based on the function names. Hopefully this will help you start your research off.