mirror of
https://github.com/PHIDIAS0303/ExpCluster.git
synced 2025-12-27 11:35:22 +09:00
Add ExpElement
This commit is contained in:
@@ -1,37 +1,60 @@
|
|||||||
|
--[[-- ExpGui - GuiData
|
||||||
|
Provides a method of storing data for elements, players, and forces under a given scope.
|
||||||
|
This is not limited to GUI element definitions but this is the most common use case.
|
||||||
|
]]
|
||||||
|
|
||||||
local ExpUtil = require("modules/exp_util")
|
local ExpUtil = require("modules/exp_util")
|
||||||
local Storage = require("modules/exp_util/storage")
|
local Storage = require("modules/exp_util/storage")
|
||||||
|
|
||||||
--- @type table<string, ExpGui.GuiData>
|
--- @type table<string, ExpGui.GuiData>
|
||||||
|
local registered_scopes = {}
|
||||||
|
|
||||||
|
--- @type table<string, [table, table, table]>
|
||||||
local script_data = {}
|
local script_data = {}
|
||||||
Storage.register(script_data, function(tbl)
|
Storage.register(script_data, function(tbl)
|
||||||
script_data = tbl
|
script_data = tbl
|
||||||
|
for scope, data in pairs(tbl) do
|
||||||
|
local proxy = registered_scopes[scope]
|
||||||
|
if proxy then
|
||||||
|
proxy.element_data = data[1]
|
||||||
|
proxy.player_data = data[2]
|
||||||
|
proxy.force_data = data[3]
|
||||||
|
end
|
||||||
|
end
|
||||||
end)
|
end)
|
||||||
|
|
||||||
--- @class ExpGui_GuiData
|
--- @class ExpGui_GuiData
|
||||||
local GuiData = {
|
local GuiData = {
|
||||||
_gui_data = script_data,
|
_data = script_data,
|
||||||
_registered = {}, --- @type table<string, ExpGui.GuiDataInit>
|
_scopes = registered_scopes,
|
||||||
}
|
}
|
||||||
|
|
||||||
--- @alias DataKey LuaGuiElement | LuaPlayer | LuaForce
|
--- @alias DataKey LuaGuiElement | LuaPlayer | LuaForce
|
||||||
|
|
||||||
--- @class ExpGui.GuiData: table<DataKey, any>
|
--- @class ExpGui.GuiData._init
|
||||||
--- @field _init ExpGui.GuiDataInit
|
|
||||||
--- @field element_data table<uint, table<uint, any>>
|
|
||||||
--- @field player_data table<uint, any>
|
|
||||||
--- @field force_data table<uint, any>
|
|
||||||
|
|
||||||
--- @class ExpGui.GuiDataInit
|
|
||||||
--- @field element any
|
--- @field element any
|
||||||
--- @field player any
|
--- @field player any
|
||||||
--- @field force any
|
--- @field force any
|
||||||
|
|
||||||
|
--- @class ExpGui.GuiData: table<DataKey, any>
|
||||||
|
--- @field _scope string
|
||||||
|
--- @field _init ExpGui.GuiData._init
|
||||||
|
--- @field element_data table<uint, table<uint, any>>
|
||||||
|
--- @field player_data table<uint, any>
|
||||||
|
--- @field force_data table<uint, any>
|
||||||
|
-- This class has no prototype methods
|
||||||
|
|
||||||
|
GuiData._metatable = {
|
||||||
|
__class = "GuiData",
|
||||||
|
}
|
||||||
|
|
||||||
|
Storage.register_metatable(GuiData._metatable.__class, GuiData._metatable)
|
||||||
|
|
||||||
--- Return the index for a given key
|
--- Return the index for a given key
|
||||||
--- @param self ExpGui.GuiData
|
--- @param self ExpGui.GuiData
|
||||||
--- @param key DataKey
|
--- @param key DataKey
|
||||||
--- @return any
|
--- @return any
|
||||||
function GuiData.__index(self, key)
|
function GuiData._metatable.__index(self, key)
|
||||||
assert(type(key) == "userdata", "Index type '" .. ExpUtil.get_class_name(key) .. "' given to GuiData. Must be of type userdata.")
|
assert(type(key) == "userdata", "Index type '" .. ExpUtil.get_class_name(key) .. "' given to GuiData. Must be of type userdata.")
|
||||||
local rtn, init
|
local rtn, init
|
||||||
local object_name = key.object_name
|
local object_name = key.object_name
|
||||||
@@ -61,7 +84,7 @@ end
|
|||||||
--- @param self ExpGui.GuiData
|
--- @param self ExpGui.GuiData
|
||||||
--- @param key DataKey
|
--- @param key DataKey
|
||||||
--- @param value unknown
|
--- @param value unknown
|
||||||
function GuiData.__newindex(self, key, value)
|
function GuiData._metatable.__newindex(self, key, value)
|
||||||
assert(type(key) == "userdata", "Index type '" .. ExpUtil.get_class_name(key) .. "' given to GuiData. Must be of type userdata.")
|
assert(type(key) == "userdata", "Index type '" .. ExpUtil.get_class_name(key) .. "' given to GuiData. Must be of type userdata.")
|
||||||
local object_name = key.object_name
|
local object_name = key.object_name
|
||||||
if object_name == "LuaGuiElement" then
|
if object_name == "LuaGuiElement" then
|
||||||
@@ -80,43 +103,44 @@ function GuiData.__newindex(self, key, value)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
GuiData._metatable = {
|
--- Sallow copy the keys from the provided table into itself
|
||||||
__index = GuiData.__index,
|
--- @param self ExpGui.GuiData
|
||||||
__newindex = GuiData.__newindex,
|
--- @param data table
|
||||||
__class = "GuiData",
|
function GuiData._metatable.__call(self, data)
|
||||||
}
|
for k, v in pairs(data) do
|
||||||
|
self[k] = v
|
||||||
Storage.register_metatable(GuiData._metatable.__class, GuiData._metatable)
|
end
|
||||||
|
|
||||||
--- Register the starting values for element data
|
|
||||||
--- @param define_name string
|
|
||||||
--- @param init_element any
|
|
||||||
--- @param init_player any
|
|
||||||
--- @param init_force any
|
|
||||||
function GuiData.register(define_name, init_element, init_player, init_force)
|
|
||||||
assert(GuiData._registered[define_name] == nil, "Define already has data registered")
|
|
||||||
GuiData._registered[define_name] = {
|
|
||||||
element = init_element,
|
|
||||||
player = init_player,
|
|
||||||
force = init_force,
|
|
||||||
}
|
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Create the data for an element definition
|
--- Create the data object for a given scope
|
||||||
--- @param define_name string
|
--- @param scope string
|
||||||
--- @return ExpGui.GuiData
|
--- @return ExpGui.GuiData
|
||||||
function GuiData.create(define_name)
|
function GuiData.create(scope)
|
||||||
local init = assert(GuiData._registered[define_name], "Define does not have any registered data")
|
assert(GuiData._scopes[scope] == nil, "Scope already exists with name: " .. scope)
|
||||||
|
|
||||||
local data = {
|
local instance = {
|
||||||
_init = init,
|
_init = {},
|
||||||
|
_scope = scope,
|
||||||
element_data = {},
|
element_data = {},
|
||||||
player_data = {},
|
player_data = {},
|
||||||
force_data = {},
|
force_data = {},
|
||||||
}
|
}
|
||||||
|
|
||||||
script_data[define_name] = data
|
script_data[scope] = {
|
||||||
return setmetatable(data, GuiData._metatable)
|
instance.element_data,
|
||||||
|
instance.player_data,
|
||||||
|
instance.force_data,
|
||||||
|
}
|
||||||
|
|
||||||
|
GuiData._scopes[scope] = instance
|
||||||
|
return setmetatable(instance, GuiData._metatable)
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Get the link to an existing data scope
|
||||||
|
--- @param scope string
|
||||||
|
--- @return ExpGui.GuiData
|
||||||
|
function GuiData.get(scope)
|
||||||
|
return GuiData._scopes[scope]
|
||||||
end
|
end
|
||||||
|
|
||||||
return GuiData
|
return GuiData
|
||||||
|
|||||||
@@ -1,7 +1,13 @@
|
|||||||
|
--[[-- ExpGui - GuiData
|
||||||
|
Provides a method of storing elements created for a player and provide a global iterator for them.
|
||||||
|
]]
|
||||||
|
|
||||||
local ExpUtil = require("modules/exp_util")
|
local ExpUtil = require("modules/exp_util")
|
||||||
local Storage = require("modules/exp_util/storage")
|
local Storage = require("modules/exp_util/storage")
|
||||||
|
|
||||||
|
--- @alias ExpGui_GuiIter.FilterType LuaPlayer | LuaForce | LuaPlayer[] | nil
|
||||||
|
--- @alias ExpGui_GuiIter.ReturnType ExpGui_GuiIter.ReturnType
|
||||||
|
|
||||||
--- @type table<string, table<uint, table<uint, LuaGuiElement>>>
|
--- @type table<string, table<uint, table<uint, LuaGuiElement>>>
|
||||||
local script_data = {}
|
local script_data = {}
|
||||||
Storage.register(script_data, function(tbl)
|
Storage.register(script_data, function(tbl)
|
||||||
@@ -29,17 +35,17 @@ local function next_valid_element(elements, prev_index)
|
|||||||
end
|
end
|
||||||
|
|
||||||
--- Get the next valid player with elements
|
--- Get the next valid player with elements
|
||||||
--- @param define_elements table<uint, table<uint, LuaGuiElement>>
|
--- @param scope_elements table<uint, table<uint, LuaGuiElement>>
|
||||||
--- @param players LuaPlayer[]
|
--- @param players LuaPlayer[]
|
||||||
--- @param prev_index uint?
|
--- @param prev_index uint?
|
||||||
--- @param online boolean?
|
--- @param online boolean?
|
||||||
--- @return uint?, LuaPlayer?, table<uint, LuaGuiElement>?
|
--- @return uint?, LuaPlayer?, table<uint, LuaGuiElement>?
|
||||||
local function next_valid_player(define_elements, players, prev_index, online)
|
local function next_valid_player(scope_elements, players, prev_index, online)
|
||||||
local index, player = nil, nil
|
local index, player = nil, nil
|
||||||
while true do
|
while true do
|
||||||
index, player = next(players, prev_index)
|
index, player = next(players, prev_index)
|
||||||
while player and not player.valid do
|
while player and not player.valid do
|
||||||
define_elements[player.index] = nil
|
scope_elements[player.index] = nil
|
||||||
index, player = next(players, index)
|
index, player = next(players, index)
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -48,7 +54,7 @@ local function next_valid_player(define_elements, players, prev_index, online)
|
|||||||
end
|
end
|
||||||
|
|
||||||
if online == nil or player.connected == online then
|
if online == nil or player.connected == online then
|
||||||
local player_elements = define_elements[player.index]
|
local player_elements = scope_elements[player.index]
|
||||||
if player_elements and #player_elements > 0 then
|
if player_elements and #player_elements > 0 then
|
||||||
return index, player, player_elements
|
return index, player, player_elements
|
||||||
end
|
end
|
||||||
@@ -57,16 +63,16 @@ local function next_valid_player(define_elements, players, prev_index, online)
|
|||||||
end
|
end
|
||||||
|
|
||||||
--- Iterate over all valid elements for a player
|
--- Iterate over all valid elements for a player
|
||||||
--- @param define_name string
|
--- @param scope string
|
||||||
--- @param player LuaPlayer
|
--- @param player LuaPlayer
|
||||||
--- @return fun(): LuaPlayer?, LuaGuiElement?
|
--- @return ExpGui_GuiIter.ReturnType
|
||||||
function GuiIter.player_elements(define_name, player)
|
function GuiIter.player_elements(scope, player)
|
||||||
if not player.valid then return nop end
|
if not player.valid then return nop end
|
||||||
|
|
||||||
local define_elements = script_data[define_name]
|
local scope_elements = script_data[scope]
|
||||||
if not define_elements then return nop end
|
if not scope_elements then return nop end
|
||||||
|
|
||||||
local player_elements = define_elements[player.index]
|
local player_elements = scope_elements[player.index]
|
||||||
if not player_elements then return nop end
|
if not player_elements then return nop end
|
||||||
|
|
||||||
local element_index, element = nil, nil
|
local element_index, element = nil, nil
|
||||||
@@ -78,13 +84,13 @@ function GuiIter.player_elements(define_name, player)
|
|||||||
end
|
end
|
||||||
|
|
||||||
--- Iterate over all valid elements for a player
|
--- Iterate over all valid elements for a player
|
||||||
--- @param define_name string
|
--- @param scope string
|
||||||
--- @param players LuaPlayer[]
|
--- @param players LuaPlayer[]
|
||||||
--- @param online boolean?
|
--- @param online boolean?
|
||||||
--- @return fun(): LuaPlayer?, LuaGuiElement?
|
--- @return ExpGui_GuiIter.ReturnType
|
||||||
function GuiIter.filtered_elements(define_name, players, online)
|
function GuiIter.filtered_elements(scope, players, online)
|
||||||
local define_elements = script_data[define_name]
|
local scope_elements = script_data[scope]
|
||||||
if not define_elements then return nop end
|
if not scope_elements then return nop end
|
||||||
|
|
||||||
local index, player, player_elements = nil, nil, nil
|
local index, player, player_elements = nil, nil, nil
|
||||||
local element_index, element = nil, nil
|
local element_index, element = nil, nil
|
||||||
@@ -92,7 +98,7 @@ function GuiIter.filtered_elements(define_name, players, online)
|
|||||||
while true do
|
while true do
|
||||||
-- Get the next valid player elements if needed
|
-- Get the next valid player elements if needed
|
||||||
if element_index == nil then
|
if element_index == nil then
|
||||||
index, player, player_elements = next_valid_player(define_elements, players, index, online)
|
index, player, player_elements = next_valid_player(scope_elements, players, index, online)
|
||||||
if index == nil then return nil, nil end
|
if index == nil then return nil, nil end
|
||||||
--- @cast player_elements -nil
|
--- @cast player_elements -nil
|
||||||
end
|
end
|
||||||
@@ -107,11 +113,11 @@ function GuiIter.filtered_elements(define_name, players, online)
|
|||||||
end
|
end
|
||||||
|
|
||||||
--- Iterate over all valid elements
|
--- Iterate over all valid elements
|
||||||
--- @param define_name string
|
--- @param scope string
|
||||||
--- @return fun(): LuaPlayer?, LuaGuiElement?
|
--- @return ExpGui_GuiIter.ReturnType
|
||||||
function GuiIter.all_elements(define_name)
|
function GuiIter.all_elements(scope)
|
||||||
local define_elements = script_data[define_name]
|
local scope_elements = script_data[scope]
|
||||||
if not define_elements then return nop end
|
if not scope_elements then return nop end
|
||||||
|
|
||||||
local player_index, player_elements, player = nil, nil, nil
|
local player_index, player_elements, player = nil, nil, nil
|
||||||
local element_index, element = nil, nil
|
local element_index, element = nil, nil
|
||||||
@@ -119,14 +125,14 @@ function GuiIter.all_elements(define_name)
|
|||||||
while true do
|
while true do
|
||||||
if element_index == nil then
|
if element_index == nil then
|
||||||
-- Get the next player
|
-- Get the next player
|
||||||
player_index, player_elements = next(define_elements, player_index)
|
player_index, player_elements = next(scope_elements, player_index)
|
||||||
if player_index == nil then return nil, nil end
|
if player_index == nil then return nil, nil end
|
||||||
player = game.get_player(player_index)
|
player = game.get_player(player_index)
|
||||||
|
|
||||||
-- Ensure next player is valid
|
-- Ensure next player is valid
|
||||||
while player and not player.valid do
|
while player and not player.valid do
|
||||||
define_elements[player_index] = nil
|
scope_elements[player_index] = nil
|
||||||
player_index, player_elements = next(define_elements, player_index)
|
player_index, player_elements = next(scope_elements, player_index)
|
||||||
if player_index == nil then return nil, nil end
|
if player_index == nil then return nil, nil end
|
||||||
player = game.get_player(player_index)
|
player = game.get_player(player_index)
|
||||||
end
|
end
|
||||||
@@ -142,65 +148,63 @@ function GuiIter.all_elements(define_name)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
--- @alias FilterType LuaPlayer | LuaForce | LuaPlayer[] | nil
|
|
||||||
|
|
||||||
--- Iterate over all valid gui elements for all players
|
--- Iterate over all valid gui elements for all players
|
||||||
--- @param define_name string
|
--- @param scope string
|
||||||
--- @param filter FilterType
|
--- @param filter ExpGui_GuiIter.FilterType
|
||||||
--- @return fun(): LuaPlayer?, LuaGuiElement?
|
--- @return ExpGui_GuiIter.ReturnType
|
||||||
function GuiIter.get_elements(define_name, filter)
|
function GuiIter.get_tracked_elements(scope, filter)
|
||||||
local class_name = ExpUtil.get_class_name(filter)
|
local class_name = ExpUtil.get_class_name(filter)
|
||||||
if class_name == "nil" then
|
if class_name == "nil" then
|
||||||
--- @cast filter nil
|
--- @cast filter nil
|
||||||
return GuiIter.all_elements(define_name)
|
return GuiIter.all_elements(scope)
|
||||||
elseif class_name == "LuaPlayer" then
|
elseif class_name == "LuaPlayer" then
|
||||||
--- @cast filter LuaPlayer
|
--- @cast filter LuaPlayer
|
||||||
return GuiIter.player_elements(define_name, filter)
|
return GuiIter.player_elements(scope, filter)
|
||||||
elseif class_name == "LuaForce" then
|
elseif class_name == "LuaForce" then
|
||||||
--- @cast filter LuaForce
|
--- @cast filter LuaForce
|
||||||
return GuiIter.filtered_elements(define_name, filter.players)
|
return GuiIter.filtered_elements(scope, filter.players)
|
||||||
elseif type(filter) == "table" and ExpUtil.get_class_name(filter[1]) == "LuaPlayer" then
|
elseif type(filter) == "table" and ExpUtil.get_class_name(filter[1]) == "LuaPlayer" then
|
||||||
--- @cast filter LuaPlayer[]
|
--- @cast filter LuaPlayer[]
|
||||||
return GuiIter.filtered_elements(define_name, filter)
|
return GuiIter.filtered_elements(scope, filter)
|
||||||
else
|
else
|
||||||
error("Unknown filter type: " .. class_name)
|
error("Unknown filter type: " .. class_name)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Iterate over all valid gui elements for all online players
|
--- Iterate over all valid gui elements for all online players
|
||||||
--- @param define_name string
|
--- @param scope string
|
||||||
--- @param filter FilterType
|
--- @param filter ExpGui_GuiIter.FilterType
|
||||||
--- @return fun(): LuaPlayer?, LuaGuiElement?
|
--- @return ExpGui_GuiIter.ReturnType
|
||||||
function GuiIter.get_online_elements(define_name, filter)
|
function GuiIter.get_online_elements(scope, filter)
|
||||||
local class_name = ExpUtil.get_class_name(filter)
|
local class_name = ExpUtil.get_class_name(filter)
|
||||||
if class_name == "nil" then
|
if class_name == "nil" then
|
||||||
--- @cast filter nil
|
--- @cast filter nil
|
||||||
return GuiIter.filtered_elements(define_name, game.connected_players)
|
return GuiIter.filtered_elements(scope, game.connected_players)
|
||||||
elseif class_name == "LuaPlayer" then
|
elseif class_name == "LuaPlayer" then
|
||||||
--- @cast filter LuaPlayer
|
--- @cast filter LuaPlayer
|
||||||
if not filter.connected then return nop end
|
if not filter.connected then return nop end
|
||||||
return GuiIter.player_elements(define_name, filter)
|
return GuiIter.player_elements(scope, filter)
|
||||||
elseif class_name == "LuaForce" then
|
elseif class_name == "LuaForce" then
|
||||||
--- @cast filter LuaForce
|
--- @cast filter LuaForce
|
||||||
return GuiIter.filtered_elements(define_name, filter.connected_players)
|
return GuiIter.filtered_elements(scope, filter.connected_players)
|
||||||
elseif type(filter) == "table" and ExpUtil.get_class_name(filter[1]) == "LuaPlayer" then
|
elseif type(filter) == "table" and ExpUtil.get_class_name(filter[1]) == "LuaPlayer" then
|
||||||
--- @cast filter LuaPlayer[]
|
--- @cast filter LuaPlayer[]
|
||||||
return GuiIter.filtered_elements(define_name, filter, true)
|
return GuiIter.filtered_elements(scope, filter, true)
|
||||||
else
|
else
|
||||||
error("Unknown filter type: " .. class_name)
|
error("Unknown filter type: " .. class_name)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Add a new element to the global iter
|
--- Add a new element to the global iter
|
||||||
--- @param define_name string
|
--- @param scope string
|
||||||
--- @param element LuaGuiElement
|
--- @param element LuaGuiElement
|
||||||
function GuiIter.add_element(define_name, element)
|
function GuiIter.add_element(scope, element)
|
||||||
if not element.valid then return end
|
if not element.valid then return end
|
||||||
|
|
||||||
local define_elements = script_data[define_name]
|
local scope_elements = script_data[scope]
|
||||||
if not define_elements then
|
if not scope_elements then
|
||||||
define_elements = {}
|
scope_elements = {}
|
||||||
script_data[define_name] = define_elements
|
script_data[scope] = scope_elements
|
||||||
end
|
end
|
||||||
|
|
||||||
local player_elements = script_data[element.player_index]
|
local player_elements = script_data[element.player_index]
|
||||||
@@ -212,4 +216,16 @@ function GuiIter.add_element(define_name, element)
|
|||||||
player_elements[element.index] = element
|
player_elements[element.index] = element
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- Remove an element from the global iter
|
||||||
|
--- @param scope string
|
||||||
|
--- @param player_index uint
|
||||||
|
--- @param element_index uint
|
||||||
|
function GuiIter.remove_element(scope, player_index, element_index)
|
||||||
|
local scope_elements = script_data[scope]
|
||||||
|
if not scope_elements then return end
|
||||||
|
local player_elements = script_data[player_index]
|
||||||
|
if not player_elements then return end
|
||||||
|
player_elements[element_index] = nil
|
||||||
|
end
|
||||||
|
|
||||||
return GuiIter
|
return GuiIter
|
||||||
|
|||||||
386
exp_gui/module/prototype.lua
Normal file
386
exp_gui/module/prototype.lua
Normal file
@@ -0,0 +1,386 @@
|
|||||||
|
|
||||||
|
local ExpUtil = require("modules/exp_util")
|
||||||
|
|
||||||
|
local GuiData = require("./data")
|
||||||
|
local GuiIter = require("./iter")
|
||||||
|
|
||||||
|
--- @class ExpGui_ExpElement
|
||||||
|
local ExpElement = {
|
||||||
|
_elements = {}
|
||||||
|
}
|
||||||
|
|
||||||
|
--- @alias ExpElement.DrawCallback fun(def: ExpElement, parent: LuaGuiElement, ...): LuaGuiElement?, function?
|
||||||
|
--- @alias ExpElement.StyleCallback fun(def: ExpElement, element: LuaGuiElement?, parent: LuaGuiElement, ...): table?
|
||||||
|
--- @alias ExpElement.DataCallback fun(def: ExpElement, element: LuaGuiElement?, parent: LuaGuiElement, ...): table?
|
||||||
|
--- @alias ExpElement.OnEventAdder<E> fun(self: ExpElement, handler: fun(event: E)): ExpElement
|
||||||
|
|
||||||
|
--- @class ExpElement._debug
|
||||||
|
--- @field defined_at string
|
||||||
|
--- @field draw_src table?
|
||||||
|
--- @field style_src table?
|
||||||
|
|
||||||
|
--- @class ExpElement
|
||||||
|
--- @field name string
|
||||||
|
--- @field scope string
|
||||||
|
--- @field data ExpGui.GuiData
|
||||||
|
--- @field _debug ExpElement._debug
|
||||||
|
--- @field _draw ExpElement.DrawCallback?
|
||||||
|
--- @field _style ExpElement.StyleCallback?
|
||||||
|
--- @field _element_data ExpElement.DataCallback?
|
||||||
|
--- @field _player_data ExpElement.DataCallback?
|
||||||
|
--- @field _force_data ExpElement.DataCallback?
|
||||||
|
--- @field _events table<defines.events, function[]>
|
||||||
|
ExpElement._prototype = {
|
||||||
|
_track_elements = false,
|
||||||
|
_tag_elements = false,
|
||||||
|
}
|
||||||
|
|
||||||
|
ExpElement._metatable = {
|
||||||
|
__call = nil, -- ExpElement._prototype.create
|
||||||
|
__index = ExpElement._prototype,
|
||||||
|
__class = "ExpGui",
|
||||||
|
}
|
||||||
|
|
||||||
|
--- Register a new instance of a prototype
|
||||||
|
--- @param name string
|
||||||
|
--- @return ExpElement
|
||||||
|
function ExpElement.create(name)
|
||||||
|
ExpUtil.assert_not_runtime()
|
||||||
|
assert(ExpElement._elements[name] == nil, "ExpElement already defined with name: " .. name)
|
||||||
|
local scope = ExpUtil.get_module_name(2) .. "::" .. name
|
||||||
|
|
||||||
|
local instance = {
|
||||||
|
name = name,
|
||||||
|
scope = scope,
|
||||||
|
data = GuiData.create(scope),
|
||||||
|
_events = {},
|
||||||
|
_debug = {
|
||||||
|
defined_at = ExpUtil.safe_file_path(2),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
ExpElement._elements[name] = instance
|
||||||
|
return setmetatable(instance, ExpElement._metatable)
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Create a new instance of this element definition
|
||||||
|
--- @param parent LuaGuiElement
|
||||||
|
--- @param ... any
|
||||||
|
--- @return LuaGuiElement?
|
||||||
|
function ExpElement._prototype:create(parent, ...)
|
||||||
|
assert(self._draw, "Element does not have a draw definition")
|
||||||
|
local element, status = self:_draw(parent, ...)
|
||||||
|
local player = assert(game.get_player(parent.player_index))
|
||||||
|
|
||||||
|
if self._style then
|
||||||
|
local style = self:_style(element, parent, ...)
|
||||||
|
if style then
|
||||||
|
assert(element, "Cannot set style when no element was returned by draw definition")
|
||||||
|
local element_style = element.style
|
||||||
|
for k, v in pairs(style) do
|
||||||
|
element_style[k] = v
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
if self._element_data then
|
||||||
|
local data = self:_element_data(element, parent, ...)
|
||||||
|
if data then
|
||||||
|
assert(element, "Cannot set element data when no element was returned by draw definition")
|
||||||
|
self.data[element] = data
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
if self._player_data then
|
||||||
|
local data = self:_player_data(element, parent, ...)
|
||||||
|
if data then
|
||||||
|
self.data[player] = data
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
if self._force_data then
|
||||||
|
local data = self:_force_data(element, parent, ...)
|
||||||
|
if data then
|
||||||
|
self.data[player.force] = data
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
if not element then return end
|
||||||
|
|
||||||
|
if self._track_elements and status ~= ExpElement._prototype.track_element and status ~= ExpElement._prototype.untrack_element then
|
||||||
|
self:track_element(element)
|
||||||
|
end
|
||||||
|
|
||||||
|
if self._tag_elements and status ~= ExpElement._prototype.tag_element and status ~= ExpElement._prototype.untag_element then
|
||||||
|
self:tag_element(element)
|
||||||
|
end
|
||||||
|
|
||||||
|
return element
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Enable tracking of all created elements
|
||||||
|
--- @return ExpElement
|
||||||
|
function ExpElement._prototype:track_all_elements()
|
||||||
|
self._track_elements = true
|
||||||
|
return self
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Set the draw definition
|
||||||
|
--- @param definition table | ExpElement.DrawCallback
|
||||||
|
--- @return ExpElement
|
||||||
|
function ExpElement._prototype:draw(definition)
|
||||||
|
if type(definition) == "table" then
|
||||||
|
self._debug.draw_src = definition
|
||||||
|
self._draw = function(_, parent)
|
||||||
|
return parent.add(definition)
|
||||||
|
end
|
||||||
|
else
|
||||||
|
self._draw = definition
|
||||||
|
end
|
||||||
|
|
||||||
|
return self
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Set the style definition
|
||||||
|
--- @param definition table | ExpElement.StyleCallback
|
||||||
|
--- @return ExpElement
|
||||||
|
function ExpElement._prototype:style(definition)
|
||||||
|
if type(definition) == "table" then
|
||||||
|
self._debug.style_src = definition
|
||||||
|
self._style = function(_, parent)
|
||||||
|
return parent.add(definition)
|
||||||
|
end
|
||||||
|
else
|
||||||
|
self._style = definition
|
||||||
|
end
|
||||||
|
|
||||||
|
return self
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Set the default element data
|
||||||
|
--- @param definition table | ExpElement.DataCallback
|
||||||
|
--- @return ExpElement
|
||||||
|
function ExpElement._prototype:element_data(definition)
|
||||||
|
if type(definition) == "table" then
|
||||||
|
--- @diagnostic disable-next-line invisible
|
||||||
|
self.data._init.element = definition
|
||||||
|
else
|
||||||
|
self._element_data = definition
|
||||||
|
end
|
||||||
|
|
||||||
|
return self
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Set the default player data
|
||||||
|
--- @param definition table | ExpElement.DataCallback
|
||||||
|
--- @return ExpElement
|
||||||
|
function ExpElement._prototype:player_data(definition)
|
||||||
|
if type(definition) == "table" then
|
||||||
|
--- @diagnostic disable-next-line invisible
|
||||||
|
self.data._init.player = definition
|
||||||
|
else
|
||||||
|
self._player_data = definition
|
||||||
|
end
|
||||||
|
|
||||||
|
return self
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Set the default force data
|
||||||
|
--- @param definition table | ExpElement.DataCallback
|
||||||
|
--- @return ExpElement
|
||||||
|
function ExpElement._prototype:force_data(definition)
|
||||||
|
if type(definition) == "table" then
|
||||||
|
--- @diagnostic disable-next-line invisible
|
||||||
|
self.data._init.force = definition
|
||||||
|
else
|
||||||
|
self._force_data = definition
|
||||||
|
end
|
||||||
|
|
||||||
|
return self
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Iterate the tracked elements of all players
|
||||||
|
--- @param filter ExpGui_GuiIter.FilterType
|
||||||
|
--- @return ExpGui_GuiIter.ReturnType
|
||||||
|
function ExpElement._prototype:tracked_elements(filter)
|
||||||
|
return GuiIter.get_tracked_elements(self.scope, filter)
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Iterate the tracked elements of all online players
|
||||||
|
--- @param filter ExpGui_GuiIter.FilterType
|
||||||
|
--- @return ExpGui_GuiIter.ReturnType
|
||||||
|
function ExpElement._prototype:online_elements(filter)
|
||||||
|
return GuiIter.get_online_elements(self.scope, filter)
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Track an arbitrary element, tracked elements can be iterated
|
||||||
|
--- @param element LuaGuiElement
|
||||||
|
--- @return LuaGuiElement
|
||||||
|
--- @return function
|
||||||
|
function ExpElement._prototype:track_element(element)
|
||||||
|
GuiIter.add_element(self.scope, element)
|
||||||
|
return element, ExpElement._prototype.track_element
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Untrack an arbitrary element, untracked elements can't be iterated
|
||||||
|
--- @param element LuaGuiElement
|
||||||
|
--- @return LuaGuiElement
|
||||||
|
--- @return function
|
||||||
|
function ExpElement._prototype:untrack_element(element)
|
||||||
|
GuiIter.remove_element(self.scope, element.player_index, element.index)
|
||||||
|
return element, ExpElement._prototype.untrack_element
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Tag an arbitrary element, tagged elements call event handlers
|
||||||
|
--- @param element LuaGuiElement
|
||||||
|
--- @return LuaGuiElement
|
||||||
|
--- @return function
|
||||||
|
function ExpElement._prototype:tag_element(element)
|
||||||
|
local element_tags = element.tags
|
||||||
|
if not element_tags then
|
||||||
|
element_tags = {}
|
||||||
|
end
|
||||||
|
|
||||||
|
local event_tags = element_tags["ExpGui"]
|
||||||
|
if not event_tags then
|
||||||
|
event_tags = {}
|
||||||
|
element_tags["ExpGui"] = event_tags
|
||||||
|
end
|
||||||
|
--- @cast event_tags string[]
|
||||||
|
|
||||||
|
if not table.contains(event_tags, self.scope) then
|
||||||
|
event_tags[#event_tags + 1] = self.scope
|
||||||
|
end
|
||||||
|
|
||||||
|
element.tags = element_tags
|
||||||
|
return element, ExpElement._prototype.tag_element
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Untag an arbitrary element, untagged elements do not call event handlers
|
||||||
|
--- @param element LuaGuiElement
|
||||||
|
--- @return LuaGuiElement
|
||||||
|
--- @return function
|
||||||
|
function ExpElement._prototype:untag_element(element)
|
||||||
|
local element_tags = element.tags
|
||||||
|
if not element_tags then
|
||||||
|
element_tags = {}
|
||||||
|
end
|
||||||
|
|
||||||
|
local event_tags = element_tags["ExpGui"]
|
||||||
|
if not event_tags then
|
||||||
|
event_tags = {}
|
||||||
|
element_tags["ExpGui"] = event_tags
|
||||||
|
end
|
||||||
|
--- @cast event_tags string[]
|
||||||
|
|
||||||
|
table.remove_element(event_tags, self.scope)
|
||||||
|
element.tags = element_tags
|
||||||
|
return element, ExpElement._prototype.untag_element
|
||||||
|
end
|
||||||
|
|
||||||
|
local e = defines.events
|
||||||
|
local events = {
|
||||||
|
}
|
||||||
|
|
||||||
|
--- Create a function to add event handlers to an element definition
|
||||||
|
--- @param event_name any
|
||||||
|
--- @return ExpElement.OnEventAdder<EventData>
|
||||||
|
local function event_factory(event_name)
|
||||||
|
--- @param event EventData.on_gui_click
|
||||||
|
events[event_name] = function(event)
|
||||||
|
local element = event.element
|
||||||
|
if not element or not element.valid then return end
|
||||||
|
|
||||||
|
local event_tags = element.tags and element.tags["ExpGui"]
|
||||||
|
if not event_tags then return end
|
||||||
|
--- @cast event_tags string[]
|
||||||
|
|
||||||
|
for _, define_name in ipairs(event_tags) do
|
||||||
|
local define = ExpElement._elements[define_name]
|
||||||
|
if define then
|
||||||
|
define:_raise_event(event)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
return function(self, handler)
|
||||||
|
self._tag_elements = true
|
||||||
|
local handlers = self._events[event_name]
|
||||||
|
if not handlers then
|
||||||
|
handlers = {}
|
||||||
|
self._events[event_name] = handlers
|
||||||
|
end
|
||||||
|
handlers[#handlers + 1] = handler
|
||||||
|
return self
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Raise all handlers for an event on this definition
|
||||||
|
--- @param event EventData
|
||||||
|
function ExpElement._prototype:_raise_event(event)
|
||||||
|
local handlers = self._events[event.name]
|
||||||
|
if not handlers then return end
|
||||||
|
for _, handler in ipairs(handlers) do
|
||||||
|
handler(event)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Called when LuaGuiElement checked state is changed (related to checkboxes and radio buttons).
|
||||||
|
--- @type ExpElement.OnEventAdder<EventData.on_gui_checked_state_changed>
|
||||||
|
ExpElement._prototype.on_checked_state_changed = event_factory(e.on_gui_checked_state_changed)
|
||||||
|
|
||||||
|
--- Called when LuaGuiElement is clicked.
|
||||||
|
--- @type ExpElement.OnEventAdder<EventData.on_gui_click>
|
||||||
|
ExpElement._prototype.on_click = event_factory(e.on_gui_click)
|
||||||
|
|
||||||
|
--- Called when the player closes the GUI they have open.
|
||||||
|
--- @type ExpElement.OnEventAdder<EventData.on_gui_closed>
|
||||||
|
ExpElement._prototype.on_closed = event_factory(e.on_gui_closed)
|
||||||
|
|
||||||
|
--- Called when a LuaGuiElement is confirmed, for example by pressing Enter in a textfield.
|
||||||
|
--- @type ExpElement.OnEventAdder<EventData.on_gui_confirmed>
|
||||||
|
ExpElement._prototype.on_confirmed = event_factory(e.on_gui_confirmed)
|
||||||
|
|
||||||
|
--- Called when LuaGuiElement element value is changed (related to choose element buttons).
|
||||||
|
--- @type ExpElement.OnEventAdder<EventData.on_gui_elem_changed>
|
||||||
|
ExpElement._prototype.on_elem_changed = event_factory(e.on_gui_elem_changed)
|
||||||
|
|
||||||
|
--- Called when LuaGuiElement is hovered by the mouse.
|
||||||
|
--- @type ExpElement.OnEventAdder<EventData.on_gui_hover>
|
||||||
|
ExpElement._prototype.on_hover = event_factory(e.on_gui_hover)
|
||||||
|
|
||||||
|
--- Called when the player's cursor leaves a LuaGuiElement that was previously hovered.
|
||||||
|
--- @type ExpElement.OnEventAdder<EventData.on_gui_leave>
|
||||||
|
ExpElement._prototype.on_leave = event_factory(e.on_gui_leave)
|
||||||
|
|
||||||
|
--- Called when LuaGuiElement element location is changed (related to frames in player.gui.screen).
|
||||||
|
--- @type ExpElement.OnEventAdder<EventData.on_gui_location_changed>
|
||||||
|
ExpElement._prototype.on_location_changed = event_factory(e.on_gui_location_changed)
|
||||||
|
|
||||||
|
--- Called when the player opens a GUI.
|
||||||
|
--- @type ExpElement.OnEventAdder<EventData.on_gui_opened>
|
||||||
|
ExpElement._prototype.on_opened = event_factory(e.on_gui_opened)
|
||||||
|
|
||||||
|
--- Called when LuaGuiElement selected tab is changed (related to tabbed-panes).
|
||||||
|
--- @type ExpElement.OnEventAdder<EventData.on_gui_selected_tab_changed>
|
||||||
|
ExpElement._prototype.on_selected_tab_changed = event_factory(e.on_gui_selected_tab_changed)
|
||||||
|
|
||||||
|
--- Called when LuaGuiElement selection state is changed (related to drop-downs and listboxes).
|
||||||
|
--- @type ExpElement.OnEventAdder<EventData.on_gui_selection_state_changed>
|
||||||
|
ExpElement._prototype.on_selection_state_changed = event_factory(e.on_gui_selection_state_changed)
|
||||||
|
|
||||||
|
--- Called when LuaGuiElement switch state is changed (related to switches).
|
||||||
|
--- @type ExpElement.OnEventAdder<EventData.on_gui_switch_state_changed>
|
||||||
|
ExpElement._prototype.on_switch_state_changed = event_factory(e.on_gui_switch_state_changed)
|
||||||
|
|
||||||
|
--- Called when LuaGuiElement text is changed by the player.
|
||||||
|
--- @type ExpElement.OnEventAdder<EventData.on_gui_text_changed>
|
||||||
|
ExpElement._prototype.on_text_changed = event_factory(e.on_gui_text_changed)
|
||||||
|
|
||||||
|
--- Called when LuaGuiElement slider value is changed (related to the slider element).
|
||||||
|
--- @type ExpElement.OnEventAdder<EventData.on_gui_value_changed>
|
||||||
|
ExpElement._prototype.on_value_changed = event_factory(e.on_gui_value_changed)
|
||||||
|
|
||||||
|
ExpElement._metatable.__call = ExpElement._prototype.create
|
||||||
|
ExpElement.events = events --- @package
|
||||||
|
return ExpElement
|
||||||
Reference in New Issue
Block a user