227 lines
7.0 KiB
Lua
227 lines
7.0 KiB
Lua
local gui = {}
|
|
local util = scripts.util
|
|
local templates = scripts["gui-templates"]
|
|
local mod_gui = require("mod-gui")
|
|
|
|
local helpers = scripts.helpers
|
|
local _ = helpers.on
|
|
|
|
local MAX_DUPLICATES = 1000
|
|
|
|
-- GUI events are saved in global.guiEvents["EVENT NAME"][PLAYER INDEX][GUI ELEMENT INDEX]
|
|
local eventHandlers = {} -- FIXME: support multiple events (curently all events saved under same ID in eventHandlers)
|
|
|
|
local events = {
|
|
on_gui_checked_state_changed = "onCheckedStateChanged",
|
|
on_gui_click = "onClicked",
|
|
on_gui_elem_changed = "onElementChanged",
|
|
on_gui_selection_state_changed = "onSelectionStateChanged",
|
|
on_gui_text_changed = "onTextChanged",
|
|
on_gui_value_changed = "onValueChanged",
|
|
on_gui_confirmed = "onConfirmed",
|
|
on_gui_selected_tab_changed = "onSelectedTabChanged",
|
|
on_gui_switch_state_changed = "onSwitchStateChanged",
|
|
on_gui_location_changed = "onLocationChanged",
|
|
}
|
|
|
|
local onChangedEvents = {
|
|
["checkbox"] = "onCheckedStateChanged",
|
|
["radiobutton"] = "onCheckedStateChanged",
|
|
["choose-elem-button"] = "onElementChanged",
|
|
["button"] = "onClicked",
|
|
["sprite-button"] = "onClicked",
|
|
["drop-down"] = "onSelectionStateChanged",
|
|
["list-box"] = "onSelectionStateChanged",
|
|
["textfield"] = "onTextChanged",
|
|
["text-box"] = "onTextChanged",
|
|
["slider"] = "onValueChanged",
|
|
["tabbed-pane"] = "onSelectedTabChanged",
|
|
["switch"] = "onSwitchStateChanged",
|
|
}
|
|
|
|
local specialParameters = {
|
|
children = true,
|
|
onCreated = true,
|
|
onChanged = true,
|
|
onCheckedStateChanged = true,
|
|
onClicked = true,
|
|
onElementChanged = true,
|
|
onSelectionStateChanged = true,
|
|
onTextChanged = true,
|
|
onValueChanged = true,
|
|
onConfirmed = true,
|
|
onSelectedTabChanged = true,
|
|
onSwitchStateChanged = true,
|
|
onLocationChanged = true,
|
|
ID = true,
|
|
root = true,
|
|
unique = true,
|
|
content = true,
|
|
}
|
|
|
|
local function registerHandlers(template, ID)
|
|
ID = ID or template.ID
|
|
local elemName = template.name
|
|
|
|
for _,event in pairs(events) do -- register event handler functions with generated ID
|
|
if template[event] then
|
|
eventHandlers[ID..";"..elemName] = template[event]
|
|
end
|
|
end
|
|
|
|
if template.onChanged and onChangedEvents[template.type] then -- register unified onChanged event
|
|
eventHandlers[ID..";"..elemName] = template.onChanged
|
|
end
|
|
|
|
if template.children then -- recursively register childs event handlers
|
|
for _,child in ipairs(template.children) do
|
|
registerHandlers(child, ID)
|
|
end
|
|
end
|
|
|
|
if template.type == "tab" and template.content then -- build tab contents
|
|
registerHandlers(template.content, ID)
|
|
end
|
|
end
|
|
|
|
function gui.registerTemplates(obj) -- called when lua script is loaded initially, assigns unqiue ID to every template
|
|
for name,template in pairs(obj.templates) do
|
|
template.ID = obj.class..";"..name -- unique ID, obj.class is assigned by framework.lua
|
|
registerHandlers(template)
|
|
end
|
|
end
|
|
|
|
local function getParameters(template, name)
|
|
local parameters = { name = name }
|
|
for param,value in pairs(template) do
|
|
if param ~= "name" and not specialParameters[param] then
|
|
if param == "style" and _(value):is("table") then
|
|
parameters.style = value.parent
|
|
else
|
|
parameters[param] = value
|
|
end
|
|
end
|
|
end
|
|
return parameters
|
|
end
|
|
|
|
local function getDefaultRoot(template, player)
|
|
if template.type == "button" or template.type == "sprite-button" then
|
|
return mod_gui.get_button_flow(player)
|
|
end
|
|
|
|
return mod_gui.get_frame_flow(player)
|
|
end
|
|
|
|
local function getRoot(template, player)
|
|
if template.root then
|
|
return template.root(player, getDefaultRoot(template, player))
|
|
end
|
|
|
|
return getDefaultRoot(template, player)
|
|
end
|
|
|
|
function gui.create(player, template, data, parent, ID) -- recursively builds a gui from a template
|
|
ID = ID or template.ID
|
|
parent = parent or getRoot(template, player)
|
|
|
|
local elemName = template.name
|
|
local uniqueElemName = elemName
|
|
if template.unique == false then
|
|
|
|
-- duplicates are named NAME[i] where i is the index starting at 1 (-> multiple can exist at once)
|
|
for i = 1, MAX_DUPLICATES do
|
|
if not parent[elemName.."#"..i] then
|
|
uniqueElemName = elemName.."#"..i
|
|
break
|
|
end
|
|
end
|
|
|
|
elseif template.ID then -- destroy any existing instances of this template if it's not unique
|
|
gui.destroy(player, template, parent)
|
|
end
|
|
|
|
local created = parent.add(getParameters(template, uniqueElemName)) -- create gui element
|
|
|
|
-- Apply custom styles
|
|
local style = _(template.style)
|
|
if style:is("table") then
|
|
_(created.style):set(style:unlesskey("parent"))
|
|
end
|
|
|
|
local index = created.player_index
|
|
for event,list in pairs(global.guiEvents) do -- register events
|
|
if template[event] then
|
|
list[index] = list[index] or {}
|
|
list[index][created.index] = ID..";"..elemName
|
|
end
|
|
end
|
|
|
|
if template.onChanged and onChangedEvents[template.type] then -- register unified onChanged event
|
|
local list = global.guiEvents[onChangedEvents[template.type]]
|
|
list[index] = list[index] or {}
|
|
list[index][created.index] = ID..";"..elemName
|
|
end
|
|
|
|
if template.children then -- build children
|
|
for _,child in ipairs(template.children) do
|
|
gui.create(player, child, data, created, ID)
|
|
end
|
|
end
|
|
|
|
if template.type == "tab" and parent.type == "tabbed-pane" and template.content then -- build tab contents
|
|
parent.add_tab(created, gui.create(player, template.content, data, parent, ID))
|
|
end
|
|
|
|
if template.onCreated then template.onCreated(created, data) end -- fire onCreated event
|
|
return created
|
|
end
|
|
|
|
function gui.get(player, template, parent) -- get the gui element matching the given template (unique templates only)
|
|
parent = parent or getRoot(template, player)
|
|
return parent[template.name]
|
|
end
|
|
|
|
function gui.getAll(player, template, parent) -- get table of all gui elements matching the given template (unique and non-unique)
|
|
parent = parent or getRoot(template, player)
|
|
local result = {}
|
|
|
|
if template.unique == false then -- destroy all
|
|
local regex = "^"..util.escape(template.name).."#[0-9]+$"
|
|
|
|
for _,child in pairs(parent.children) do
|
|
if child.name:find(regex) then
|
|
result[#result + 1] = child
|
|
end
|
|
end
|
|
else
|
|
result[1] = gui.get(player, template, parent)
|
|
end
|
|
|
|
return result
|
|
end
|
|
|
|
function gui.destroy(player, template, parent) -- destroy all gui elements matching the given template
|
|
for _,child in ipairs(gui.getAll(player, template, parent)) do
|
|
util.destroyIfValid(child)
|
|
end
|
|
end
|
|
|
|
local function handleGuiEvent(event, name)
|
|
if event.element.get_mod() == script.mod_name then
|
|
local handlers = global.guiEvents[name][event.player_index]
|
|
if handlers then
|
|
local handler = handlers[event.element.index]
|
|
if handler and eventHandlers[handler] then eventHandlers[handler](event.element, event) end
|
|
end
|
|
end
|
|
end
|
|
|
|
-- register game gui events
|
|
for gameEvent,translated in pairs(events) do
|
|
gui[gameEvent] = function(event)
|
|
handleGuiEvent(event, translated)
|
|
end
|
|
end
|
|
|
|
return gui |