Files
factorio-scenario-ExpCluster/expcore/gui/instances.lua
Cooldude2606 e187059ae0 Ldoc compliant
2019-05-29 22:24:04 +01:00

227 lines
11 KiB
Lua

--- This file is a breakout from core which forcues on instance management of defines
--[[
>>>> Using registered instance groups
The main use of this module is to register a group of elements refered here as "instances of an element define" in which
is meant that you define the name of a group of drawn elements that are really just multiple versions of a single element.
For example this might be that you have one label in multiple places (either for one player or many) and you want to update
the caption of all of them at once; this is where this module comes it.
First you must register the way that the intances are stored and under what name, using Instances.register you will give the
name of the collective group of instances followed by an optional categorise function which allows varients to be stored under one
name (like one for each force or player)
-- categorise works in the same way as store categorise
-- so the function will worl here but no value is stored only gui elements
Instances.register('score',Gui.force_store)
Then when you draw the new element to a gui you will want to add the element to the group:
Instances.add_element('score',new_element)
Then when you want to get the instances you have two options; Instances.get_elements or Instances.apply_to_elements when you want loop
over the elements it is more efficient to use apply_to_elements:
Instances.get_elements('score','player') -- returns all elements that were added with the 'player' category
Instances.apply_to_elements('score','player',function(element) -- runs the function on every valid element
element.caption = 0
end)
Note that if you dont give a categorise function then you dont need to give a category when getting the elements.
>>>> Using unregistered instance groups
When using a registered group and the functions that go with them it is much simpler to use and more importantly includes error checking
for valid instance group names; the down side is that the group must be registered which can only be done during startup and not during runtime.
To counter this there are two functions simlair to those above in order to add and get instances but may lead to errors not being noticed due to
the error interal error checking being skiped to allow it to work.
The main difference between the two groups of functions is that the category must always be present even if is nil; example below shows how a
instance group would work when registered vs unregistered:
-- Registered with category
Instances.register('score',Gui.force_store) -- force_store will return the force name of an element
Instances.add_element('score',new_element) -- the new element is added to the category based on in force
Instances.apply_to_elements('score','player',function(element)
element.caption = '0'
end) -- gets all instances from the player force and sets the caption to 0
-- Unregistered with category
Instances.unregistered_add_element('score','player',new_element) -- adds the new element to the player category
Instances.unregistered_apply_to_elements('score','player',function(element)
element.caption = '0'
end) -- gets all instances from the player force and sets the caption to 0
-- Registered without category; note that category can just be igroned
Instances.register('score') -- all instances will be under one group with no categories
Instances.add_element('score',new_element) -- adds the new element to the instance list
Instances.apply_to_elements('score',function(element)
element.caption = '0'
end) -- gets all instances and sets the element caption to 0
-- Unregistered without category; note that category must be given as nil
Instances.unregistered_add_element('score',nil,new_element) -- adds the new element to a single group with no categories
Instances.unregistered_apply_to_elements('score',nil,function(element)
element.caption = '0'
end) -- gets all instances and sets the element caption to 0
>>>> Functions
Instances.has_categories(name) --- Returns if a instnace group has a categorise function; must be registerd
Instances.is_registered(name) --- Returns if the given name is a registered instance group
Instances.register(name,categorise) --- Registers the name of an instance group to allow for storing element instances
Instances.add_element(name,element) --- Adds an element to the instance group under the correct category; must be registered
Instances.get_elements_raw(name,category) --- Gets all element instances without first removing any invalid ones; used internally and must be registered
Instances.get_valid_elements(name,category,callback) --- Gets all valid element instances and has the option of running a callback on those that are valid
Instances.unregistered_add_element(name,category,element) --- A version of add_element that does not require the group to be registered
Instances.unregistered_get_elements(name,category,callback) --- A version of get_elements that does not require the group to be registered
]]
local Global = require 'utils.global'
local Instances = {
categorise={},
data={}
}
Global.register(Instances.data,function(tbl)
Instances.data = tbl
end)
--- Returns if a instnace group has a categorise function; must be registerd
-- @tparam string name the name of the instance group
-- @treturn boolean true if there is a categorise function
function Instances.has_categories(name)
return type(Instances.categorise[name]) == 'function'
end
--- Returns if the given name is a registered instance group
-- @tparam string name the name of the instance group you are testing
-- @treturn boolean true if the name is registered
function Instances.is_registered(name)
return Instances.categorise[name] ~= nil
end
--- Registers the name of an instance group to allow for storing element instances
-- @tparam string name the name of the instance group; must to unique
-- @tparam[opt] function categorise function used to turn the element into a string
-- categorise param - element LuaGuiElement - the gui element to be turned into a string
-- categorise return - string - the category that the element will be added to like the player's name or force's name
-- @treturn string the name that was added so it can be used as a varible
function Instances.register(name,categorise)
if _LIFECYCLE ~= _STAGE.control then
return error('Can only be called during the control stage', 2)
end
if Instances.categorise[name] then
return error('Instances for '..name..' already exist.',2)
end
categorise = type(categorise) == 'function' and categorise or true
Instances.data[name] = {}
Instances.categorise[name] = categorise
return name
end
--- Adds an element to the instance group under the correct category; must be registered
-- @tparam string name the name of the instance group to add the element to
-- @tparam LuaGuiElement element the element to add the the instance group
function Instances.add_element(name,element)
if not Instances.categorise[name] then
return error('Inavlid name for instance group: '..name,2)
end
if Instances.has_categories(name) then
local category = Instances.categorise[name](element)
if not Instances.data[name][category] then Instances.data[name][category] = {} end
table.insert(Instances.data[name][category],element)
else
table.insert(Instances.data[name],element)
end
end
--- Gets all element instances without first removing any invalid ones; used internally and must be registered
-- @tparam string name the name of the instance group to get the instances of
-- @tparam[opt] string category the category to get the instance from, not needed when no categorise function
-- @treturn table the table of element instances of which some may be invalid
function Instances.get_elements_raw(name,category)
if not Instances.categorise[name] then
return error('Inavlid name for instance group: '..name,2)
end
if Instances.has_categories(name) then
return Instances.data[name][category] or {}
else
return Instances.data[name]
end
end
--- Gets all valid element instances and has the option of running a callback on those that are valid
-- @tparam string name the name of the instance group to get the instances of
-- @tparam[opt] string category the category to get the instances of, not needed when no categorise function
-- @tparan[opt] callback function when given the callback will be ran on all valid elements
-- callback param - element LuaGuiElement - the current valid element
-- @treturn table the table of element instances with all invalid ones removed
function Instances.get_valid_elements(name,category,callback)
if not Instances.categorise[name] then
return error('Inavlid name for instance group: '..name,2)
end
category = category or callback
local elements = Instances.get_elements_raw(name,category)
local categorise = Instances.has_categories(name)
for key,element in pairs(elements) do
if not element or not element.valid then
elements[key] = nil
else
if categorise and callback then callback(element)
elseif category then category(element) end
end
end
return elements
end
Instances.get_elements = Instances.get_valid_elements
Instances.apply_to_elements = Instances.get_valid_elements
--- A version of add_element that does not require the group to be registered
-- @tparam string name the name of the instance group to add the element to
-- @tparam category ?string|nil the category to add the element to, can be nil but must still be given
-- @tparam LuaGuiElement element the element to add to the instance group
function Instances.unregistered_add_element(name,category,element)
if not Instances.data[name] then Instances.data[name] = {} end
if category then
if not Instances.data[name][category] then Instances.data[name][category] = {} end
table.insert(Instances.data[name][category],element)
else
table.insert(Instances.data[name],element)
end
end
--- A version of get_elements that does not require the group to be registered
-- @tparam string name the name of the instance group to get the instances of
-- @tparam category ?string|nil the category to get the instances of, can be nil but must still be given
-- @tparam[opt] function callback when given will be called on all valid instances
-- callback param - element LuaGuiElement - the current valid element
-- @treturn table the table of element instances with all invalid ones removed
function Instances.unregistered_get_elements(name,category,callback)
local elements = Instances.data[name]
if elements and category then
elements = elements[category]
end
if not elements then return {} end
for key,element in pairs(elements) do
if not element or not element.valid then
elements[key] = nil
else
if callback then callback(element) end
end
end
return elements
end
Instances.unregistered_apply_to_elements = Instances.runtime_get_elements
return Instances