mirror of
https://github.com/PHIDIAS0303/ExpCluster.git
synced 2025-12-27 03:25:23 +09:00
8
exp_gui/index.ts
Normal file
8
exp_gui/index.ts
Normal file
@@ -0,0 +1,8 @@
|
||||
import * as lib from "@clusterio/lib";
|
||||
|
||||
export const plugin: lib.PluginDeclaration = {
|
||||
name: "exp_gui",
|
||||
title: "exp_gui",
|
||||
description: "Example Description. Plugin. Change me in index.ts",
|
||||
instanceEntrypoint: "./dist/node/instance",
|
||||
};
|
||||
7
exp_gui/instance.ts
Normal file
7
exp_gui/instance.ts
Normal file
@@ -0,0 +1,7 @@
|
||||
import * as lib from "@clusterio/lib";
|
||||
import { BaseInstancePlugin } from "@clusterio/host";
|
||||
|
||||
export class InstancePlugin extends BaseInstancePlugin {
|
||||
// This class is empty because an instance plugin must be defined for a module to be injected
|
||||
// This requirement may change in the future to allow for standalone modules
|
||||
}
|
||||
213
exp_gui/module/control.lua
Normal file
213
exp_gui/module/control.lua
Normal file
@@ -0,0 +1,213 @@
|
||||
|
||||
local Storage = require("modules/exp_util/storage")
|
||||
|
||||
local ExpElement = require("modules/exp_gui/prototype")
|
||||
|
||||
--- @alias ExpGui.VisibleCallback fun(player: LuaPlayer, element: LuaGuiElement): boolean
|
||||
|
||||
--- @class ExpGui.player_elements
|
||||
--- @field top table<string, LuaGuiElement?>
|
||||
--- @field left table<string, LuaGuiElement?>
|
||||
--- @field relative table<string, LuaGuiElement?>
|
||||
|
||||
--- @type table<uint, ExpGui.player_elements>
|
||||
local player_elements = {}
|
||||
Storage.register(player_elements, function(tbl)
|
||||
player_elements = tbl
|
||||
end)
|
||||
|
||||
--- @class ExpGui
|
||||
local ExpGui = {
|
||||
element = ExpElement.create,
|
||||
property_from_arg = ExpElement.property_from_arg,
|
||||
property_from_name = ExpElement.property_from_name,
|
||||
top_elements = {}, --- @type table<ExpElement, ExpGui.VisibleCallback | boolean>
|
||||
left_elements = {}, --- @type table<ExpElement, ExpGui.VisibleCallback | boolean>
|
||||
relative_elements = {}, --- @type table<ExpElement, ExpGui.VisibleCallback | boolean>
|
||||
}
|
||||
|
||||
local mod_gui = require("mod-gui")
|
||||
ExpGui.get_top_flow = mod_gui.get_button_flow
|
||||
ExpGui.get_left_flow = mod_gui.get_frame_flow
|
||||
|
||||
--- Get a player from an element or gui event
|
||||
--- @param input LuaGuiElement | { player_index: uint } | { element: LuaGuiElement }
|
||||
--- @return LuaPlayer
|
||||
function ExpGui.get_player(input)
|
||||
if type(input) == "table" and not input.player_index then
|
||||
return assert(game.get_player(input.element.player_index))
|
||||
end
|
||||
return assert(game.get_player(input.player_index))
|
||||
end
|
||||
|
||||
--- Toggle the enable state of an element
|
||||
--- @param element LuaGuiElement
|
||||
--- @param state boolean?
|
||||
--- @return boolean
|
||||
function ExpGui.toggle_enabled_state(element, state)
|
||||
if not element or not element.valid then return false end
|
||||
if state == nil then
|
||||
state = not element.enabled
|
||||
end
|
||||
element.enabled = state
|
||||
return state
|
||||
end
|
||||
|
||||
--- Toggle the visibility of an element
|
||||
--- @param element LuaGuiElement
|
||||
--- @param state boolean?
|
||||
--- @return boolean
|
||||
function ExpGui.toggle_visible_state(element, state)
|
||||
if not element or not element.valid then return false end
|
||||
if state == nil then
|
||||
state = not element.visible
|
||||
end
|
||||
element.visible = state
|
||||
return state
|
||||
end
|
||||
|
||||
--- Destroy an element if it exists and is valid
|
||||
--- @param element LuaGuiElement?
|
||||
function ExpGui.destroy_if_valid(element)
|
||||
if not element or not element.valid then return end
|
||||
element.destroy()
|
||||
end
|
||||
|
||||
--- Register a element define to be drawn to the top flow on join
|
||||
--- @param define ExpElement
|
||||
--- @param visible ExpGui.VisibleCallback | boolean | nil
|
||||
function ExpGui.add_top_element(define, visible)
|
||||
assert(ExpGui.top_elements[define.name] == nil, "Element is already added to the top flow")
|
||||
ExpGui.top_elements[define] = visible or false
|
||||
end
|
||||
|
||||
--- Register a element define to be drawn to the left flow on join
|
||||
--- @param define ExpElement
|
||||
--- @param visible ExpGui.VisibleCallback | boolean | nil
|
||||
function ExpGui.add_left_element(define, visible)
|
||||
assert(ExpGui.left_elements[define.name] == nil, "Element is already added to the left flow")
|
||||
ExpGui.left_elements[define] = visible or false
|
||||
|
||||
end
|
||||
|
||||
--- Register a element define to be drawn to the relative flow on join
|
||||
--- @param define ExpElement
|
||||
--- @param visible ExpGui.VisibleCallback | boolean | nil
|
||||
function ExpGui.add_relative_element(define, visible)
|
||||
assert(ExpGui.relative_elements[define.name] == nil, "Element is already added to the relative flow")
|
||||
ExpGui.relative_elements[define] = visible or false
|
||||
end
|
||||
|
||||
--- Register a element define to be drawn to the top flow on join
|
||||
--- @param define ExpElement
|
||||
--- @param player LuaPlayer
|
||||
--- @return LuaGuiElement
|
||||
function ExpGui.get_top_element(define, player)
|
||||
return assert(player_elements[player.index].top[define.name], "Element is not on the top flow")
|
||||
end
|
||||
|
||||
--- Register a element define to be drawn to the left flow on join
|
||||
--- @param define ExpElement
|
||||
--- @param player LuaPlayer
|
||||
--- @return LuaGuiElement
|
||||
function ExpGui.get_left_element(define, player)
|
||||
return assert(player_elements[player.index].left[define.name], "Element is not on the left flow")
|
||||
end
|
||||
|
||||
--- Register a element define to be drawn to the relative flow on join
|
||||
--- @param define ExpElement
|
||||
--- @param player LuaPlayer
|
||||
--- @return LuaGuiElement
|
||||
function ExpGui.get_relative_element(define, player)
|
||||
return assert(player_elements[player.index].relative[define.name], "Element is not on the relative flow")
|
||||
end
|
||||
|
||||
--- Ensure all the correct elements are visible and exist
|
||||
--- @param player LuaPlayer
|
||||
--- @param element_defines table<ExpElement, ExpGui.VisibleCallback | boolean>
|
||||
--- @param elements table<string, LuaGuiElement?>
|
||||
--- @param parent LuaGuiElement
|
||||
local function ensure_elements(player, element_defines, elements, parent)
|
||||
local done = {}
|
||||
for define, visible in pairs(element_defines) do
|
||||
done[define.name] = true
|
||||
local element = elements[define.name]
|
||||
if not element or not element.valid then
|
||||
element = assert(define(parent), "Element define did not return an element: " .. define.name)
|
||||
elements[define.name] = element
|
||||
|
||||
if type(visible) == "function" then
|
||||
visible = visible(player, element)
|
||||
end
|
||||
element.visible = visible
|
||||
end
|
||||
end
|
||||
|
||||
for name, element in pairs(elements) do
|
||||
if not done[name] then
|
||||
element.destroy()
|
||||
elements[name] = nil
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
--- Ensure all elements have been created
|
||||
--- @param event EventData.on_player_created | EventData.on_player_joined_game
|
||||
function ExpGui._ensure_consistency(event)
|
||||
local player = assert(game.get_player(event.player_index))
|
||||
local elements = player_elements[event.player_index]
|
||||
if not elements then
|
||||
elements = {
|
||||
top = {},
|
||||
left = {},
|
||||
relative = {},
|
||||
}
|
||||
player_elements[event.player_index] = elements
|
||||
end
|
||||
|
||||
ensure_elements(player, ExpGui.top_elements, elements.top, ExpGui.get_top_flow(player))
|
||||
ensure_elements(player, ExpGui.left_elements, elements.left, ExpGui.get_left_flow(player))
|
||||
ensure_elements(player, ExpGui.relative_elements, elements.relative, player.gui.relative)
|
||||
|
||||
-- This check isn't needed, but allows the toolbar file to be deleted without modifying any lib code
|
||||
if ExpGui.toolbar then
|
||||
--- @diagnostic disable-next-line invisible
|
||||
ExpGui.toolbar._create_elements(player)
|
||||
--- @diagnostic disable-next-line invisible
|
||||
ExpGui.toolbar._ensure_consistency(player)
|
||||
end
|
||||
end
|
||||
|
||||
--- Rerun the visible check for relative elements
|
||||
--- @param event EventData.on_gui_opened
|
||||
local function on_gui_opened(event)
|
||||
local player = ExpGui.get_player(event)
|
||||
local original_element = event.element
|
||||
|
||||
for define, visible in pairs(ExpGui.relative_elements) do
|
||||
local element = ExpGui.get_relative_element(define, player)
|
||||
|
||||
if type(visible) == "function" then
|
||||
visible = visible(player, element)
|
||||
end
|
||||
element.visible = visible
|
||||
|
||||
if visible then
|
||||
event.element = element
|
||||
--- @diagnostic disable-next-line invisible
|
||||
define:raise_event(event)
|
||||
end
|
||||
end
|
||||
|
||||
event.element = original_element
|
||||
end
|
||||
|
||||
local e = defines.events
|
||||
local events = {
|
||||
[e.on_player_created] = ExpGui._ensure_consistency,
|
||||
[e.on_player_joined_game] = ExpGui._ensure_consistency,
|
||||
[e.on_gui_opened] = on_gui_opened,
|
||||
}
|
||||
|
||||
ExpGui.events = events
|
||||
return ExpGui
|
||||
208
exp_gui/module/data.lua
Normal file
208
exp_gui/module/data.lua
Normal file
@@ -0,0 +1,208 @@
|
||||
--[[-- 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 Storage = require("modules/exp_util/storage")
|
||||
|
||||
--- @type table<string, ExpGui.GuiData_Raw>
|
||||
local scope_data = {}
|
||||
|
||||
--- @type table<string, ExpGui.GuiData_Internal>
|
||||
local registered_scopes = {}
|
||||
|
||||
--- @type table<uint, uint> Reg -> Player Index
|
||||
local registration_numbers = {}
|
||||
local reg_obj = script.register_on_object_destroyed
|
||||
|
||||
--- @alias DataKey LuaGuiElement | LuaPlayer | LuaForce
|
||||
--- @alias DataKeys "element_data" | "player_data" | "force_data" | "global_data"
|
||||
local DataKeys = ExpUtil.enum{ "element_data", "player_data", "force_data", "global_data" }
|
||||
local DataKeysConcat = table.concat(DataKeys, ", ")
|
||||
|
||||
Storage.register({
|
||||
scope_data = scope_data,
|
||||
registration_numbers = registration_numbers,
|
||||
}, function(tbl)
|
||||
registration_numbers = tbl.registration_numbers
|
||||
for scope, data in pairs(tbl.scope_data) do
|
||||
local proxy = registered_scopes[scope]
|
||||
if proxy then
|
||||
rawset(proxy, "_raw", data)
|
||||
for k, v in pairs(data) do
|
||||
rawset(proxy, k, v)
|
||||
end
|
||||
end
|
||||
end
|
||||
end)
|
||||
|
||||
--- @class ExpGui_GuiData
|
||||
local GuiData = {
|
||||
_scopes = registered_scopes,
|
||||
}
|
||||
|
||||
--- @class ExpGui.GuiData_Raw
|
||||
--- @field element_data table<uint, table<uint, any>?>?
|
||||
--- @field player_data table<uint, any>?
|
||||
--- @field force_data table<uint, any>?
|
||||
--- @field global_data table?
|
||||
-- This class has no prototype methods
|
||||
-- Keep this in sync with DataKeys to block arbitrary strings
|
||||
|
||||
--- @class ExpGui.GuiData_Internal
|
||||
--- @field _scope string
|
||||
--- @field _raw ExpGui.GuiData_Raw
|
||||
-- This class has no prototype methods
|
||||
-- Do add keys to _raw without also referencing scope_data
|
||||
|
||||
--- @class ExpGui.GuiData: ExpGui.GuiData_Internal
|
||||
--- @field element_data table<uint, table<uint, any>>
|
||||
--- @field player_data table<uint, any>
|
||||
--- @field force_data table<uint, any>
|
||||
--- @field global_data table
|
||||
-- This class has no prototype methods
|
||||
-- Same as raw but __index ensures the values exist
|
||||
|
||||
GuiData._metatable = {
|
||||
__class = "GuiData",
|
||||
}
|
||||
|
||||
--- Return the index for a given key
|
||||
--- @param self ExpGui.GuiData_Internal
|
||||
--- @param key DataKeys | DataKey
|
||||
--- @return any
|
||||
function GuiData._metatable.__index(self, key)
|
||||
if type(key) == "string" then
|
||||
-- This is only called when the key does not exist, ie it is not in storage
|
||||
-- Once created, these tables are never removed as they are likely to be used again
|
||||
assert(DataKeys[key], "Valid keys are: " .. DataKeysConcat)
|
||||
local value = {}
|
||||
self._raw[key] = value
|
||||
rawset(self, key, value)
|
||||
scope_data[self._scope] = self._raw
|
||||
return value
|
||||
end
|
||||
|
||||
-- Check a given child table based on the object type
|
||||
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
|
||||
if object_name == "LuaGuiElement" then
|
||||
local data = self._raw.element_data
|
||||
local player_elements = data and data[key.player_index]
|
||||
return player_elements and player_elements[key.index]
|
||||
elseif object_name == "LuaPlayer" then
|
||||
local data = self._raw.player_data
|
||||
return data and data[key.index]
|
||||
elseif object_name == "LuaForce" then
|
||||
local data = self._raw.force_data
|
||||
return data and data[key.index]
|
||||
else
|
||||
error("Unsupported object class '" .. object_name .. "' given as index to GuiData.")
|
||||
end
|
||||
end
|
||||
|
||||
--- Set the value index of a given key
|
||||
-- Internal type is not used here to allow for creation of storage
|
||||
--- @param self ExpGui.GuiData
|
||||
--- @param key DataKey
|
||||
--- @param value unknown
|
||||
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.")
|
||||
local object_name = key.object_name
|
||||
if object_name == "LuaGuiElement" then
|
||||
local data = self.element_data
|
||||
local player_elements = data[key.player_index]
|
||||
if not player_elements then
|
||||
player_elements = {}
|
||||
data[key.player_index] = player_elements
|
||||
end
|
||||
player_elements[key.index] = value
|
||||
registration_numbers[reg_obj(key)] = key.player_index
|
||||
elseif object_name == "LuaPlayer" then
|
||||
self.player_data[key.index] = value
|
||||
elseif object_name == "LuaForce" then
|
||||
self.force_data[key.index] = value
|
||||
else
|
||||
error("Unsupported object class '" .. object_name .. "' given as index to GuiData.")
|
||||
end
|
||||
end
|
||||
|
||||
--- Create the data object for a given scope
|
||||
--- @param scope string
|
||||
--- @return ExpGui.GuiData
|
||||
function GuiData.create(scope)
|
||||
ExpUtil.assert_not_runtime()
|
||||
assert(GuiData._scopes[scope] == nil, "Scope already exists with name: " .. scope)
|
||||
|
||||
local instance = {
|
||||
_scope = scope,
|
||||
_raw = {},
|
||||
}
|
||||
|
||||
GuiData._scopes[scope] = instance
|
||||
--- @cast instance ExpGui.GuiData
|
||||
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] --[[ @as ExpGui.GuiData ]]
|
||||
end
|
||||
|
||||
--- Used to clean up data from destroyed elements
|
||||
--- @param event EventData.on_object_destroyed
|
||||
local function on_object_destroyed(event)
|
||||
local player_index = registration_numbers[event.registration_number]
|
||||
if not player_index then return end
|
||||
|
||||
local element_index = event.useful_id
|
||||
registration_numbers[event.registration_number] = nil
|
||||
|
||||
for _, scope in pairs(registered_scopes) do
|
||||
local data = scope._raw.element_data
|
||||
local player_elements = data and data[player_index]
|
||||
if player_elements then
|
||||
player_elements[element_index] = nil
|
||||
if not next(player_elements) then
|
||||
data[player_index] = nil
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
--- Used to clean up data from destroyed players
|
||||
--- @param event EventData.on_player_removed
|
||||
local function on_player_removed(event)
|
||||
local player_index = event.player_index
|
||||
for _, scope in pairs(registered_scopes) do
|
||||
local data = scope._raw.player_data
|
||||
if data then
|
||||
data[player_index] = nil
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
--- Used to clean up data from destroyed forces
|
||||
--- @param event EventData.on_forces_merged
|
||||
local function on_forces_merged(event)
|
||||
local force_index = event.source_index
|
||||
for _, scope in pairs(registered_scopes) do
|
||||
local data = scope._raw.force_data
|
||||
if data then
|
||||
data[force_index] = nil
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local e = defines.events
|
||||
local events = {
|
||||
[e.on_object_destroyed] = on_object_destroyed,
|
||||
[e.on_player_removed] = on_player_removed,
|
||||
[e.on_forces_merged] = on_forces_merged,
|
||||
}
|
||||
|
||||
GuiData.events = events
|
||||
return GuiData
|
||||
193
exp_gui/module/elements.lua
Normal file
193
exp_gui/module/elements.lua
Normal file
@@ -0,0 +1,193 @@
|
||||
--- @class ExpGui
|
||||
local ExpGui = require("modules/exp_gui")
|
||||
|
||||
--- @class ExpGui.elements
|
||||
local elements = {}
|
||||
ExpGui.elements = elements
|
||||
|
||||
--- A flow which aligns its content as specified
|
||||
elements.aligned_flow = ExpGui.element("aligned_flow")
|
||||
:draw{
|
||||
type = "flow",
|
||||
name = ExpGui.property_from_arg("name"),
|
||||
}
|
||||
:style(function(def, element, parent, opts)
|
||||
opts = opts or {}
|
||||
local vertical_align = opts.vertical_align or "center"
|
||||
local horizontal_align = opts.horizontal_align or "right"
|
||||
return {
|
||||
padding = { 1, 2 },
|
||||
vertical_align = vertical_align,
|
||||
horizontal_align = horizontal_align,
|
||||
vertically_stretchable = vertical_align ~= "center",
|
||||
horizontally_stretchable = horizontal_align ~= "center",
|
||||
}
|
||||
end)
|
||||
|
||||
--- A solid horizontal white bar element
|
||||
elements.bar = ExpGui.element("bar")
|
||||
:draw{
|
||||
type = "progressbar",
|
||||
value = 1,
|
||||
}
|
||||
:style(function(def, element, parent, width)
|
||||
local style = element.style
|
||||
style.color = { r = 255, g = 255, b = 255 }
|
||||
style.height = 4
|
||||
if width then
|
||||
style.width = width
|
||||
else
|
||||
style.horizontally_stretchable = true
|
||||
end
|
||||
end)
|
||||
|
||||
--- A label which is centered
|
||||
elements.centered_label = ExpGui.element("centered_label")
|
||||
:draw{
|
||||
type = "label",
|
||||
caption = ExpGui.property_from_arg(2),
|
||||
tooltip = ExpGui.property_from_arg(3),
|
||||
}
|
||||
:style{
|
||||
horizontal_align = "center",
|
||||
single_line = false,
|
||||
width = ExpGui.property_from_arg(1),
|
||||
}
|
||||
|
||||
--- A label which has two white bars on either side of it
|
||||
elements.title_label = ExpGui.element("title_label")
|
||||
:draw(function(def, parent, width, caption, tooltip)
|
||||
local flow =
|
||||
parent.add{
|
||||
type = "flow"
|
||||
}
|
||||
|
||||
flow.style.vertical_align = "center"
|
||||
elements.bar(flow, width)
|
||||
|
||||
local label =
|
||||
flow.add{
|
||||
type = "label",
|
||||
style = "frame_title",
|
||||
caption = caption,
|
||||
tooltip = tooltip,
|
||||
}
|
||||
|
||||
elements.bar(flow)
|
||||
|
||||
return label
|
||||
end)
|
||||
|
||||
--- A fixed size vertical scroll pane
|
||||
elements.scroll_pane = ExpGui.element("scroll_pane")
|
||||
:draw{
|
||||
type = "scroll-pane",
|
||||
name = ExpGui.property_from_arg(2),
|
||||
direction = "vertical",
|
||||
horizontal_scroll_policy = "never",
|
||||
vertical_scroll_policy = "auto",
|
||||
style = "scroll_pane_under_subheader",
|
||||
}
|
||||
:style{
|
||||
padding = { 1, 3 },
|
||||
maximal_height = ExpGui.property_from_arg(1),
|
||||
horizontally_stretchable = true,
|
||||
}
|
||||
|
||||
--- A fixed size vertical scroll pane containing a table
|
||||
elements.scroll_table = ExpGui.element("scroll_table")
|
||||
:draw(function(def, parent, height, column_count, scroll_name)
|
||||
local scroll_pane = elements.scroll_pane(parent, height, scroll_name)
|
||||
|
||||
return scroll_pane.add{
|
||||
type = "table",
|
||||
name = "table",
|
||||
column_count = column_count,
|
||||
}
|
||||
end)
|
||||
:style{
|
||||
padding = 0,
|
||||
cell_padding = 0,
|
||||
vertical_align = "center",
|
||||
horizontally_stretchable = true,
|
||||
}
|
||||
|
||||
--- A container frame
|
||||
elements.container = ExpGui.element("container")
|
||||
:draw(function(def, parent, width, container_name)
|
||||
local container =
|
||||
parent.add{
|
||||
type = "frame",
|
||||
name = container_name,
|
||||
}
|
||||
|
||||
local style = container.style
|
||||
style.horizontally_stretchable = false
|
||||
style.minimal_width = width
|
||||
style.padding = 2
|
||||
|
||||
return container.add{
|
||||
type = "frame",
|
||||
name = "frame",
|
||||
direction = "vertical",
|
||||
style = "inside_shallow_frame_packed",
|
||||
}
|
||||
end)
|
||||
:style{
|
||||
vertically_stretchable = false,
|
||||
}
|
||||
|
||||
--- A frame within a container
|
||||
elements.subframe_base = ExpGui.element("container_subframe")
|
||||
:draw{
|
||||
type = "frame",
|
||||
name = ExpGui.property_from_arg(2),
|
||||
style = ExpGui.property_from_arg(1),
|
||||
}
|
||||
:style{
|
||||
height = 0,
|
||||
minimal_height = 36,
|
||||
padding = { 3, 4 },
|
||||
use_header_filler = false,
|
||||
horizontally_stretchable = true,
|
||||
}
|
||||
|
||||
--- A header frame within a container
|
||||
elements.header = ExpGui.element("container_header")
|
||||
:draw(function(def, parent, opts)
|
||||
opts = opts or {}
|
||||
local subframe = elements.subframe_base(parent, "subheader_frame", opts.name)
|
||||
|
||||
if opts.caption then
|
||||
subframe.add{
|
||||
type = "label",
|
||||
name = opts.label_name,
|
||||
caption = opts.caption,
|
||||
tooltip = opts.tooltip,
|
||||
style = "frame_title",
|
||||
}
|
||||
end
|
||||
|
||||
return opts.no_flow and subframe or elements.aligned_flow(subframe, { name = "flow" })
|
||||
end)
|
||||
|
||||
--- A footer frame within a container
|
||||
elements.footer = ExpGui.element("container_footer")
|
||||
:draw(function(def, parent, opts)
|
||||
opts = opts or {}
|
||||
local subframe = elements.subframe_base(parent, "subfooter_frame", opts.name)
|
||||
|
||||
if opts.caption then
|
||||
subframe.add{
|
||||
type = "label",
|
||||
name = opts.label_name,
|
||||
caption = opts.caption,
|
||||
tooltip = opts.tooltip,
|
||||
style = "frame_title",
|
||||
}
|
||||
end
|
||||
|
||||
return opts.no_flow and subframe or elements.aligned_flow(subframe, { name = "flow" })
|
||||
end)
|
||||
|
||||
return elements
|
||||
274
exp_gui/module/iter.lua
Normal file
274
exp_gui/module/iter.lua
Normal file
@@ -0,0 +1,274 @@
|
||||
--[[-- 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 Storage = require("modules/exp_util/storage")
|
||||
|
||||
--- @alias ExpGui_GuiIter.FilterType LuaPlayer | LuaForce | LuaPlayer[] | nil
|
||||
--- @alias ExpGui_GuiIter.ReturnType fun(): LuaPlayer?, LuaGuiElement?
|
||||
|
||||
--- @type table<string, table<uint, table<uint, LuaGuiElement>>>
|
||||
local registered_scopes = {}
|
||||
|
||||
--- @type table<uint, uint> Reg -> Player Index
|
||||
local registration_numbers = {}
|
||||
local reg_obj = script.register_on_object_destroyed
|
||||
|
||||
Storage.register({
|
||||
registered_scopes = registered_scopes,
|
||||
registration_numbers = registration_numbers,
|
||||
}, function(tbl)
|
||||
registered_scopes = tbl.registered_scopes
|
||||
registration_numbers = tbl.registration_numbers
|
||||
end)
|
||||
|
||||
--- @class ExpGui_GuiIter
|
||||
local GuiIter = {
|
||||
_scopes = registered_scopes,
|
||||
}
|
||||
|
||||
local function nop() return nil, nil end
|
||||
|
||||
--- Get the next valid element
|
||||
--- @param elements table<uint, LuaGuiElement>
|
||||
--- @param prev_index uint?
|
||||
--- @return uint?, LuaGuiElement?
|
||||
local function next_valid_element(elements, prev_index)
|
||||
local element_index, element = next(elements, prev_index)
|
||||
while element and not element.valid do
|
||||
elements[element_index] = nil
|
||||
element_index, element = next(elements, element_index)
|
||||
end
|
||||
return element_index, element
|
||||
end
|
||||
|
||||
--- Get the next valid player with elements
|
||||
--- @param scope_elements table<uint, table<uint, LuaGuiElement>>
|
||||
--- @param players LuaPlayer[]
|
||||
--- @param prev_index uint?
|
||||
--- @param online boolean?
|
||||
--- @return uint?, LuaPlayer?, table<uint, LuaGuiElement>?
|
||||
local function next_valid_player(scope_elements, players, prev_index, online)
|
||||
local index, player = nil, nil
|
||||
while true do
|
||||
index, player = next(players, prev_index)
|
||||
while player and not player.valid do
|
||||
scope_elements[player.index] = nil
|
||||
index, player = next(players, index)
|
||||
end
|
||||
|
||||
if index == nil then
|
||||
return nil, nil, nil
|
||||
end
|
||||
|
||||
if online == nil or player.connected == online then
|
||||
local player_elements = scope_elements[player.index]
|
||||
if player_elements and #player_elements > 0 then
|
||||
return index, player, player_elements
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
--- Iterate over all valid elements for a player
|
||||
--- @param scope string
|
||||
--- @param player LuaPlayer
|
||||
--- @return ExpGui_GuiIter.ReturnType
|
||||
function GuiIter.player_elements(scope, player)
|
||||
if not player.valid then return nop end
|
||||
|
||||
local scope_elements = registered_scopes[scope]
|
||||
if not scope_elements then return nop end
|
||||
|
||||
local player_elements = scope_elements[player.index]
|
||||
if not player_elements then return nop end
|
||||
|
||||
local element_index, element = nil, nil
|
||||
return function()
|
||||
element_index, element = next_valid_element(player_elements, element_index)
|
||||
if element_index == nil then return nil, nil end
|
||||
return player, element
|
||||
end
|
||||
end
|
||||
|
||||
--- Iterate over all valid elements for a player
|
||||
--- @param scope string
|
||||
--- @param players LuaPlayer[]
|
||||
--- @param online boolean?
|
||||
--- @return ExpGui_GuiIter.ReturnType
|
||||
function GuiIter.filtered_elements(scope, players, online)
|
||||
local scope_elements = registered_scopes[scope]
|
||||
if not scope_elements then return nop end
|
||||
|
||||
local index, player, player_elements = nil, nil, nil
|
||||
local element_index, element = nil, nil
|
||||
return function()
|
||||
while true do
|
||||
-- Get the next valid player elements if needed
|
||||
if element_index == nil then
|
||||
index, player, player_elements = next_valid_player(scope_elements, players, index, online)
|
||||
if index == nil then return nil, nil end
|
||||
--- @cast player_elements -nil
|
||||
end
|
||||
|
||||
-- Get the next element
|
||||
element_index, element = next_valid_element(player_elements, element_index)
|
||||
if element_index then
|
||||
return player, element
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
--- Iterate over all valid elements
|
||||
--- @param scope string
|
||||
--- @return ExpGui_GuiIter.ReturnType
|
||||
function GuiIter.all_elements(scope)
|
||||
local scope_elements = registered_scopes[scope]
|
||||
if not scope_elements then return nop end
|
||||
|
||||
local player_index, player_elements, player = nil, nil, nil
|
||||
local element_index, element = nil, nil
|
||||
return function()
|
||||
while true do
|
||||
if element_index == nil then
|
||||
-- Get the next player
|
||||
player_index, player_elements = next(scope_elements, player_index)
|
||||
if player_index == nil then return nil, nil end
|
||||
player = game.get_player(player_index)
|
||||
|
||||
-- Ensure next player is valid
|
||||
while player and not player.valid do
|
||||
scope_elements[player_index] = nil
|
||||
player_index, player_elements = next(scope_elements, player_index)
|
||||
if player_index == nil then return nil, nil end
|
||||
player = game.get_player(player_index)
|
||||
end
|
||||
--- @cast player_elements -nil
|
||||
end
|
||||
|
||||
-- Get the next element
|
||||
element_index, element = next_valid_element(player_elements, element_index)
|
||||
if element_index then
|
||||
return player, element
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
--- Iterate over all valid gui elements for all players
|
||||
--- @param scope string
|
||||
--- @param filter ExpGui_GuiIter.FilterType
|
||||
--- @return ExpGui_GuiIter.ReturnType
|
||||
function GuiIter.get_tracked_elements(scope, filter)
|
||||
local class_name = ExpUtil.get_class_name(filter)
|
||||
if class_name == "nil" then
|
||||
--- @cast filter nil
|
||||
return GuiIter.all_elements(scope)
|
||||
elseif class_name == "LuaPlayer" then
|
||||
--- @cast filter LuaPlayer
|
||||
return GuiIter.player_elements(scope, filter)
|
||||
elseif class_name == "LuaForce" then
|
||||
--- @cast filter LuaForce
|
||||
return GuiIter.filtered_elements(scope, filter.players)
|
||||
elseif type(filter) == "table" and ExpUtil.get_class_name(filter[1]) == "LuaPlayer" then
|
||||
--- @cast filter LuaPlayer[]
|
||||
return GuiIter.filtered_elements(scope, filter)
|
||||
else
|
||||
error("Unknown filter type: " .. class_name)
|
||||
end
|
||||
end
|
||||
|
||||
--- Iterate over all valid gui elements for all online players
|
||||
--- @param scope string
|
||||
--- @param filter ExpGui_GuiIter.FilterType
|
||||
--- @return ExpGui_GuiIter.ReturnType
|
||||
function GuiIter.get_online_elements(scope, filter)
|
||||
local class_name = ExpUtil.get_class_name(filter)
|
||||
if class_name == "nil" then
|
||||
--- @cast filter nil
|
||||
return GuiIter.filtered_elements(scope, game.connected_players)
|
||||
elseif class_name == "LuaPlayer" then
|
||||
--- @cast filter LuaPlayer
|
||||
if not filter.connected then return nop end
|
||||
return GuiIter.player_elements(scope, filter)
|
||||
elseif class_name == "LuaForce" then
|
||||
--- @cast filter LuaForce
|
||||
return GuiIter.filtered_elements(scope, filter.connected_players)
|
||||
elseif type(filter) == "table" and ExpUtil.get_class_name(filter[1]) == "LuaPlayer" then
|
||||
--- @cast filter LuaPlayer[]
|
||||
return GuiIter.filtered_elements(scope, filter, true)
|
||||
else
|
||||
error("Unknown filter type: " .. class_name)
|
||||
end
|
||||
end
|
||||
|
||||
--- Add a new element to the global iter
|
||||
--- @param scope string
|
||||
--- @param element LuaGuiElement
|
||||
function GuiIter.add_element(scope, element)
|
||||
if not element.valid then return end
|
||||
|
||||
local scope_elements = registered_scopes[scope]
|
||||
if not scope_elements then
|
||||
scope_elements = {}
|
||||
registered_scopes[scope] = scope_elements
|
||||
end
|
||||
|
||||
local player_elements = scope_elements[element.player_index]
|
||||
if not player_elements then
|
||||
player_elements = {}
|
||||
scope_elements[element.player_index] = player_elements
|
||||
end
|
||||
|
||||
player_elements[element.index] = element
|
||||
registration_numbers[reg_obj(element)] = element.player_index
|
||||
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 = registered_scopes[scope]
|
||||
if not scope_elements then return end
|
||||
local player_elements = registered_scopes[player_index]
|
||||
if not player_elements then return end
|
||||
player_elements[element_index] = nil
|
||||
end
|
||||
|
||||
--- Used to clean up data from destroyed elements
|
||||
--- @param event EventData.on_object_destroyed
|
||||
local function on_object_destroyed(event)
|
||||
local player_index = registration_numbers[event.registration_number]
|
||||
if not player_index then return end
|
||||
|
||||
local element_index = event.useful_id
|
||||
registration_numbers[event.registration_number] = nil
|
||||
|
||||
for _, scope in pairs(registered_scopes) do
|
||||
local player_elements = scope[player_index]
|
||||
if player_elements then
|
||||
player_elements[element_index] = nil
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
--- Used to clean up data from destroyed players
|
||||
--- @param event EventData.on_player_removed
|
||||
local function on_player_removed(event)
|
||||
local player_index = event.player_index
|
||||
for _, scope in pairs(registered_scopes) do
|
||||
scope[player_index] = nil
|
||||
end
|
||||
end
|
||||
|
||||
local e = defines.events
|
||||
local events = {
|
||||
[e.on_object_destroyed] = on_object_destroyed,
|
||||
[e.on_player_removed] = on_player_removed,
|
||||
}
|
||||
|
||||
GuiIter.events = events
|
||||
return GuiIter
|
||||
13
exp_gui/module/locale/en.cfg
Normal file
13
exp_gui/module/locale/en.cfg
Normal file
@@ -0,0 +1,13 @@
|
||||
|
||||
[exp-gui]
|
||||
clear-left-flow=Hide all open windows.
|
||||
close-toolbar=__CONTROL_LEFT_CLICK__: Toggle Settings\n__CONTROL_RIGHT_CLICK__: Close Toolbar
|
||||
open-toolbar=__CONTROL_LEFT_CLICK__: Toggle Settings\n__CONTROL_RIGHT_CLICK__: Open Toolbar
|
||||
|
||||
[exp-gui_toolbar-settings]
|
||||
main-caption=Toolbox
|
||||
main-tooltip=Toolbox Settings\nUse the checkboxes to select favourites
|
||||
reset=Reset All
|
||||
toggle=Toggle Favourites
|
||||
move-up=Move Up
|
||||
move-down=Move Down
|
||||
18
exp_gui/module/module.json
Normal file
18
exp_gui/module/module.json
Normal file
@@ -0,0 +1,18 @@
|
||||
{
|
||||
"name": "exp_gui",
|
||||
"load": [
|
||||
"data.lua",
|
||||
"iter.lua",
|
||||
"prototype.lua",
|
||||
"control.lua"
|
||||
],
|
||||
"require": [
|
||||
"elements.lua",
|
||||
"styles.lua",
|
||||
"toolbar.lua"
|
||||
],
|
||||
"dependencies": {
|
||||
"clusterio": "*",
|
||||
"exp_util": "*"
|
||||
}
|
||||
}
|
||||
1
exp_gui/module/module_exports.lua
Normal file
1
exp_gui/module/module_exports.lua
Normal file
@@ -0,0 +1 @@
|
||||
return require("modules/exp_gui/control")
|
||||
491
exp_gui/module/prototype.lua
Normal file
491
exp_gui/module/prototype.lua
Normal file
@@ -0,0 +1,491 @@
|
||||
|
||||
local ExpUtil = require("modules/exp_util")
|
||||
|
||||
local GuiData = require("modules/exp_gui/data")
|
||||
local GuiIter = require("modules/exp_gui/iter")
|
||||
|
||||
--- @class ExpGui_ExpElement
|
||||
local ExpElement = {
|
||||
_elements = {}, --- @type table<string, ExpElement>
|
||||
}
|
||||
|
||||
ExpElement.events = {}
|
||||
|
||||
--- @alias ExpElement.DrawCallback fun(def: ExpElement, parent: LuaGuiElement, ...): LuaGuiElement?, function?
|
||||
--- @alias ExpElement.PostDrawCallback fun(def: ExpElement, element: LuaGuiElement?, parent: LuaGuiElement, ...): table?
|
||||
--- @alias ExpElement.PostDrawCallbackAdder fun(self: ExpElement, definition: table | ExpElement.PostDrawCallback): ExpElement
|
||||
--- @alias ExpElement.EventHandler<E> fun(def: ExpElement, player: LuaPlayer, element: LuaGuiElement, event: E)
|
||||
--- @alias ExpElement.OnEventAdder<E> fun(self: ExpElement, handler: fun(def: ExpElement, player: LuaPlayer, element: LuaGuiElement, event: E)): ExpElement
|
||||
|
||||
--- @class ExpElement._debug
|
||||
--- @field defined_at string
|
||||
--- @field draw_definition table?
|
||||
--- @field draw_from_args table?
|
||||
--- @field style_definition table?
|
||||
--- @field style_from_args table?
|
||||
--- @field element_data_definition table?
|
||||
--- @field element_data_from_args table?
|
||||
--- @field player_data_definition table?
|
||||
--- @field player_data_from_args table?
|
||||
--- @field force_data_definition table?
|
||||
--- @field force_data_from_args table?
|
||||
--- @field global_data_definition table?
|
||||
--- @field global_data_from_args table?
|
||||
|
||||
--- @class ExpElement
|
||||
--- @field name string
|
||||
--- @field data ExpGui.GuiData
|
||||
--- @field _debug ExpElement._debug
|
||||
--- @field _draw ExpElement.DrawCallback?
|
||||
--- @field _style ExpElement.PostDrawCallback?
|
||||
--- @field _element_data ExpElement.PostDrawCallback?
|
||||
--- @field _player_data ExpElement.PostDrawCallback?
|
||||
--- @field _force_data ExpElement.PostDrawCallback?
|
||||
--- @field _global_data ExpElement.PostDrawCallback?
|
||||
--- @field _events table<defines.events, ExpElement.EventHandler<EventData>[]>
|
||||
--- @overload fun(parent: LuaGuiElement, ...: any): LuaGuiElement
|
||||
ExpElement._prototype = {
|
||||
_track_elements = false,
|
||||
_has_handlers = false,
|
||||
}
|
||||
|
||||
ExpElement._metatable = {
|
||||
__call = nil, -- ExpElement._prototype.create
|
||||
__index = ExpElement._prototype,
|
||||
__class = "ExpElement",
|
||||
}
|
||||
|
||||
--- Used to signal that the property should be the same as the define name
|
||||
--- @return function
|
||||
function ExpElement.property_from_name()
|
||||
return ExpElement.property_from_name
|
||||
end
|
||||
|
||||
--- Used to signal that a property should be taken from the arguments, a string means key of last arg
|
||||
--- @param arg number|string|nil
|
||||
--- @return [function, number|string|nil]
|
||||
function ExpElement.property_from_arg(arg)
|
||||
return { ExpElement.property_from_arg, arg }
|
||||
end
|
||||
|
||||
--- Extract the from args properties from a definition
|
||||
--- @param definition table
|
||||
--- @return table<string|number, string>
|
||||
function ExpElement._prototype:_extract_signals(definition)
|
||||
local from_args = {}
|
||||
for k, v in pairs(definition) do
|
||||
if v == ExpElement.property_from_arg then
|
||||
from_args[#from_args + 1] = k
|
||||
elseif v == ExpElement.property_from_name then
|
||||
definition[k] = self.name
|
||||
elseif type(v) == "table" and rawget(v, 1) == ExpElement.property_from_arg then
|
||||
from_args[v[2] or (#from_args + 1)] = k
|
||||
end
|
||||
end
|
||||
return from_args
|
||||
end
|
||||
|
||||
--- Register a new instance of a prototype
|
||||
--- @param name string
|
||||
--- @return ExpElement
|
||||
function ExpElement.create(name)
|
||||
ExpUtil.assert_not_runtime()
|
||||
local module_name = ExpUtil.get_module_name(2)
|
||||
local element_name = module_name .. "/" .. name
|
||||
assert(ExpElement._elements[element_name] == nil, "ExpElement already defined with name: " .. name)
|
||||
|
||||
local instance = {
|
||||
name = element_name,
|
||||
data = GuiData.create(element_name),
|
||||
_events = {},
|
||||
_debug = {
|
||||
defined_at = ExpUtil.get_current_line(2),
|
||||
},
|
||||
}
|
||||
|
||||
ExpElement._elements[element_name] = instance
|
||||
return setmetatable(instance, ExpElement._metatable)
|
||||
end
|
||||
|
||||
--- Get an element by its name
|
||||
--- @param name string
|
||||
--- @return ExpElement
|
||||
function ExpElement.get(name)
|
||||
return assert(ExpElement._elements[name], "ExpElement is not defined: " .. tostring(name))
|
||||
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 self._global_data then
|
||||
local data = self:_global_data(element, parent, ...)
|
||||
if data then
|
||||
local global_data = self.data.global_data
|
||||
for k, v in pairs(data) do
|
||||
global_data[k] = v
|
||||
end
|
||||
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._has_handlers and status ~= ExpElement._prototype.link_element and status ~= ExpElement._prototype.unlink_element then
|
||||
self:link_element(element)
|
||||
end
|
||||
|
||||
return element
|
||||
end
|
||||
|
||||
--- Enable tracking of all created elements
|
||||
--- @return ExpElement
|
||||
function ExpElement._prototype:track_all_elements()
|
||||
ExpUtil.assert_not_runtime()
|
||||
self._track_elements = true
|
||||
return self
|
||||
end
|
||||
|
||||
--- Add a temp draw definition, useful for when working top down
|
||||
--- @return ExpElement
|
||||
function ExpElement._prototype:dev()
|
||||
log("Dev draw used for " .. self.name)
|
||||
return self:draw{
|
||||
type = "flow"
|
||||
}
|
||||
end
|
||||
|
||||
--- @alias ExpElement.add_param LuaGuiElement.add_param | table<string, [function, number|string|nil] | function>
|
||||
|
||||
--- Set the draw definition
|
||||
--- @param definition ExpElement.add_param | ExpElement.DrawCallback
|
||||
--- @return ExpElement
|
||||
function ExpElement._prototype:draw(definition)
|
||||
ExpUtil.assert_not_runtime()
|
||||
if type(definition) == "function" then
|
||||
self._draw = definition
|
||||
return self
|
||||
end
|
||||
|
||||
assert(type(definition) == "table", "Definition is not a table or function")
|
||||
local from_args = self:_extract_signals(definition)
|
||||
self._debug.draw_definition = definition
|
||||
|
||||
if not next(from_args) then
|
||||
self._draw = function(_, parent)
|
||||
return parent.add(definition)
|
||||
end
|
||||
return self
|
||||
end
|
||||
|
||||
self._debug.draw_from_args = from_args
|
||||
self._draw = function(_, parent, ...)
|
||||
local args = { ... }
|
||||
local last = args[#args] or args
|
||||
-- 'or args' used instead of empty table
|
||||
for i, k in pairs(from_args) do
|
||||
if type(i) == "string" then
|
||||
definition[k] = last[i]
|
||||
else
|
||||
definition[k] = args[i]
|
||||
end
|
||||
end
|
||||
return parent.add(definition)
|
||||
end
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
--- Create a definition adder for anything other than draaw
|
||||
--- @param prop_name string
|
||||
--- @param debug_def string
|
||||
--- @param debug_args string
|
||||
--- @return ExpElement.PostDrawCallbackAdder
|
||||
local function definition_factory(prop_name, debug_def, debug_args)
|
||||
return function(self, definition)
|
||||
ExpUtil.assert_not_runtime()
|
||||
if type(definition) == "function" then
|
||||
self[prop_name] = definition
|
||||
return self
|
||||
end
|
||||
|
||||
assert(type(definition) == "table", "Definition is not a table or function")
|
||||
local from_args = self:_extract_signals(definition)
|
||||
self._debug[debug_def] = definition
|
||||
|
||||
if #from_args == 0 then
|
||||
self[prop_name] = function(_, _, _)
|
||||
return definition
|
||||
end
|
||||
return self
|
||||
end
|
||||
|
||||
self._debug[debug_args] = from_args
|
||||
self[prop_name] = function(_, _, _, ...)
|
||||
local args = { ... }
|
||||
for i, k in pairs(from_args) do
|
||||
definition[k] = args[i]
|
||||
end
|
||||
return definition
|
||||
end
|
||||
|
||||
return self
|
||||
end
|
||||
end
|
||||
|
||||
--- Set the style definition
|
||||
--- @type ExpElement.PostDrawCallbackAdder
|
||||
ExpElement._prototype.style = definition_factory("_style", "style_definition", "style_from_args")
|
||||
|
||||
--- Set the default element data
|
||||
--- @type ExpElement.PostDrawCallbackAdder
|
||||
ExpElement._prototype.element_data = definition_factory("_element_data", "element_data_definition", "element_data_from_args")
|
||||
|
||||
--- Set the default player data
|
||||
--- @type ExpElement.PostDrawCallbackAdder
|
||||
ExpElement._prototype.player_data = definition_factory("_player_data", "player_data_definition", "player_data_from_args")
|
||||
|
||||
--- Set the default force data
|
||||
--- @type ExpElement.PostDrawCallbackAdder
|
||||
ExpElement._prototype.force_data = definition_factory("_force_data", "force_data_definition", "force_data_from_args")
|
||||
|
||||
--- Set the default global data
|
||||
--- @type ExpElement.PostDrawCallbackAdder
|
||||
ExpElement._prototype.global_data = definition_factory("_global_data", "global_data_definition", "global_data_from_args")
|
||||
|
||||
--- 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.name, 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.name, 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.name, 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.name, element.player_index, element.index)
|
||||
return element, ExpElement._prototype.untrack_element
|
||||
end
|
||||
|
||||
--- Link an arbitrary element, linked elements call event handlers
|
||||
--- @param element LuaGuiElement
|
||||
--- @return LuaGuiElement
|
||||
--- @return function
|
||||
function ExpElement._prototype:link_element(element)
|
||||
assert(self._has_handlers, "Element has no event handlers")
|
||||
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.array_contains(event_tags, self.name) then
|
||||
event_tags[#event_tags + 1] = self.name
|
||||
end
|
||||
|
||||
element.tags = element_tags
|
||||
return element, ExpElement._prototype.link_element
|
||||
end
|
||||
|
||||
--- Unlink an arbitrary element, unlinked elements do not call event handlers
|
||||
--- @param element LuaGuiElement
|
||||
--- @return LuaGuiElement
|
||||
--- @return function
|
||||
function ExpElement._prototype:unlink_element(element)
|
||||
assert(self._has_handlers, "Element has no event handlers")
|
||||
local element_tags = element.tags
|
||||
if not element_tags then
|
||||
return element, ExpElement._prototype.unlink_element
|
||||
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.name)
|
||||
element.tags = element_tags
|
||||
return element, ExpElement._prototype.unlink_element
|
||||
end
|
||||
|
||||
--- Handle any gui events
|
||||
--- @param event EventData.on_gui_click
|
||||
local function event_handler(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
|
||||
|
||||
--- Raise all handlers for an event on this definition
|
||||
--- @param event EventData | { element: LuaGuiElement, player_index: number? }
|
||||
function ExpElement._prototype:raise_event(event)
|
||||
local handlers = self._events[event.name]
|
||||
if not handlers then return end
|
||||
local player = event.player_index and game.get_player(event.player_index)
|
||||
if event.element then player = game.get_player(event.element.player_index) end
|
||||
for _, handler in ipairs(handlers) do
|
||||
-- All gui elements will contain player and element, other events might have these as nil
|
||||
-- Therefore only the signature of on_event has these values as optional
|
||||
handler(self, player --[[ @as LuaPlayer ]], event.element, event --[[ @as EventData ]])
|
||||
end
|
||||
end
|
||||
|
||||
--- Add an event handler
|
||||
--- @param event defines.events
|
||||
--- @param handler fun(def: ExpElement, player: LuaPlayer?, element: LuaGuiElement?, event: EventData)
|
||||
--- @return ExpElement
|
||||
function ExpElement._prototype:on_event(event, handler)
|
||||
ExpElement.events[event] = event_handler
|
||||
self._has_handlers = true
|
||||
|
||||
local handlers = self._events[event] or {}
|
||||
handlers[#handlers + 1] = handler
|
||||
self._events[event] = handlers
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
--- Create a function to add event handlers to an element definition
|
||||
--- @param event defines.events
|
||||
--- @return ExpElement.OnEventAdder<EventData>
|
||||
local function event_factory(event)
|
||||
return function(self, handler)
|
||||
return self:on_event(event, handler)
|
||||
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(defines.events.on_gui_checked_state_changed)
|
||||
|
||||
--- Called when LuaGuiElement is clicked.
|
||||
--- @type ExpElement.OnEventAdder<EventData.on_gui_click>
|
||||
ExpElement._prototype.on_click = event_factory(defines.events.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(defines.events.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(defines.events.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(defines.events.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(defines.events.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(defines.events.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(defines.events.on_gui_location_changed)
|
||||
|
||||
--- Called when the player opens a GUI.
|
||||
--- @type ExpElement.OnEventAdder<EventData.on_gui_opened>
|
||||
ExpElement._prototype.on_opened = event_factory(defines.events.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(defines.events.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(defines.events.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(defines.events.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(defines.events.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(defines.events.on_gui_value_changed)
|
||||
|
||||
ExpElement._metatable.__call = ExpElement._prototype.create
|
||||
return ExpElement
|
||||
16
exp_gui/module/styles.lua
Normal file
16
exp_gui/module/styles.lua
Normal file
@@ -0,0 +1,16 @@
|
||||
--- @class ExpGui
|
||||
local ExpGui = require("modules/exp_gui")
|
||||
|
||||
--- @class ExpGui.styles
|
||||
local styles = {}
|
||||
ExpGui.styles = styles
|
||||
|
||||
function styles.sprite(style)
|
||||
style = style or {}
|
||||
if not style.padding then
|
||||
style.padding = -2
|
||||
end
|
||||
return style
|
||||
end
|
||||
|
||||
return styles
|
||||
739
exp_gui/module/toolbar.lua
Normal file
739
exp_gui/module/toolbar.lua
Normal file
@@ -0,0 +1,739 @@
|
||||
|
||||
--- @class ExpGui
|
||||
local ExpGui = require("modules/exp_gui")
|
||||
local ExpElement = require("modules/exp_gui/prototype")
|
||||
local mod_gui = require("mod-gui")
|
||||
|
||||
local toolbar_button_default_style = mod_gui.button_style
|
||||
local toolbar_button_active_style = "menu_button_continue"
|
||||
local toolbar_button_size = 36
|
||||
local toolbar_button_small = 20
|
||||
|
||||
--- @class ExpGui.toolbar
|
||||
local Toolbar = {}
|
||||
ExpGui.toolbar = Toolbar
|
||||
|
||||
local elements = {}
|
||||
Toolbar.elements = elements
|
||||
|
||||
local toolbar_buttons = {} --- @type ExpElement[]
|
||||
local left_elements_with_button = {} --- @type table<ExpElement, ExpElement>
|
||||
local buttons_with_left_element = {} --- @type table<string, ExpElement>
|
||||
|
||||
--- Set the visible state of the toolbar
|
||||
--- @param player LuaPlayer
|
||||
--- @param state boolean? toggles if nil
|
||||
--- @return boolean
|
||||
function Toolbar.set_visible_state(player, state)
|
||||
-- Update the top flow
|
||||
local top_flow = assert(ExpGui.get_top_flow(player).parent)
|
||||
if state == nil then state = not top_flow.visible end
|
||||
top_flow.visible = state
|
||||
|
||||
-- Update the open toolbar button
|
||||
for _, open_toolbar in elements.open_toolbar:tracked_elements(player) do
|
||||
open_toolbar.visible = not state
|
||||
end
|
||||
|
||||
-- Update the toggle toolbar button
|
||||
for _, toggle_toolbar in elements.toggle_toolbar:tracked_elements(player) do
|
||||
toggle_toolbar.toggled = state
|
||||
end
|
||||
|
||||
return state
|
||||
end
|
||||
|
||||
--- Get the visible state of the toolbar
|
||||
--- @param player LuaPlayer
|
||||
--- @return boolean
|
||||
function Toolbar.get_visible_state(player)
|
||||
local top_flow = assert(ExpGui.get_top_flow(player).parent)
|
||||
return top_flow.visible
|
||||
end
|
||||
|
||||
--- Set the toggle state of a toolbar button, does not check for a linked left element
|
||||
--- @param define ExpElement
|
||||
--- @param player LuaPlayer
|
||||
--- @param state boolean? toggles if nil
|
||||
--- @return boolean
|
||||
function Toolbar.set_button_toggled_state(define, player, state)
|
||||
local top_element = assert(ExpGui.get_top_element(define, player), "Element is not on the top flow")
|
||||
if state == nil then state = top_element.style.name == toolbar_button_default_style end
|
||||
|
||||
for _, element in define:tracked_elements(player) do
|
||||
local original_width, original_height = element.style.minimal_width, element.style.maximal_height
|
||||
element.style = state and toolbar_button_active_style or toolbar_button_default_style
|
||||
|
||||
-- Make the extra required adjustments
|
||||
local style = element.style
|
||||
style.minimal_width = original_width
|
||||
style.maximal_height = original_height
|
||||
if element.type == "sprite-button" then
|
||||
style.padding = -2
|
||||
else
|
||||
style.font = "default-semibold"
|
||||
style.padding = 0
|
||||
end
|
||||
end
|
||||
|
||||
return state
|
||||
end
|
||||
|
||||
--- Get the toggle state of a toolbar button
|
||||
--- @param define ExpElement
|
||||
--- @param player LuaPlayer
|
||||
--- @return boolean
|
||||
function Toolbar.get_button_toggled_state(define, player)
|
||||
local element = assert(ExpGui.get_top_element(define, player), "Element is not on the top flow")
|
||||
return element.style.name == toolbar_button_active_style
|
||||
end
|
||||
|
||||
--- Set the visible state of a left element
|
||||
--- @param define ExpElement
|
||||
--- @param player LuaPlayer
|
||||
--- @param state boolean? toggles if nil
|
||||
--- @param _skip_consistency boolean?
|
||||
--- @return boolean
|
||||
function Toolbar.set_left_element_visible_state(define, player, state, _skip_consistency)
|
||||
local element = assert(ExpGui.get_left_element(define, player), "Element is not on the left flow")
|
||||
if state == nil then state = not element.visible end
|
||||
element.visible = state
|
||||
|
||||
-- Check if there is a linked toolbar button and update it
|
||||
local button = left_elements_with_button[define]
|
||||
if button then
|
||||
Toolbar.set_button_toggled_state(button, player, state)
|
||||
end
|
||||
|
||||
-- This check is O(n^2) when setting all left elements to hidden, so internals can it
|
||||
if _skip_consistency then return state end
|
||||
|
||||
-- Update the clear left flow button, visible when at least one element is visible
|
||||
local has_visible = Toolbar.has_visible_left_elements(player)
|
||||
for _, clear_left_flow in elements.clear_left_flow:tracked_elements(player) do
|
||||
clear_left_flow.visible = state or has_visible
|
||||
end
|
||||
|
||||
return state
|
||||
end
|
||||
|
||||
--- Get the toggle state of a left element
|
||||
--- @param define ExpElement
|
||||
--- @param player LuaPlayer
|
||||
--- @return boolean
|
||||
function Toolbar.get_left_element_visible_state(define, player)
|
||||
local element = assert(ExpGui.get_left_element(define, player), "Element is not on the left flow")
|
||||
return element.visible
|
||||
end
|
||||
|
||||
--- Check if there are any visible toolbar buttons
|
||||
--- @param player any
|
||||
--- @return boolean
|
||||
function Toolbar.has_visible_buttons(player)
|
||||
local top_flow = ExpGui.get_top_flow(player)
|
||||
local settings_button = ExpGui.get_top_element(elements.close_toolbar, player)
|
||||
|
||||
for _, element in pairs(top_flow.children) do
|
||||
if element.visible and element ~= settings_button then
|
||||
return true
|
||||
end
|
||||
end
|
||||
|
||||
return false
|
||||
end
|
||||
|
||||
--- Check if there are any visible left elements
|
||||
--- @param player any
|
||||
--- @return boolean
|
||||
function Toolbar.has_visible_left_elements(player)
|
||||
local left_flow = ExpGui.get_left_flow(player)
|
||||
local core_button_flow = ExpGui.get_left_element(elements.core_button_flow, player)
|
||||
|
||||
for _, element in pairs(left_flow.children) do
|
||||
if element.visible and element ~= core_button_flow then
|
||||
return true
|
||||
end
|
||||
end
|
||||
|
||||
return false
|
||||
end
|
||||
|
||||
--- @class ExpGui.toolbar.create_button__param: LuaGuiElement.add_param.sprite_button, LuaGuiElement.add_param.button
|
||||
--- @field name string
|
||||
--- @field type nil
|
||||
--- @field left_element ExpElement| nil
|
||||
--- @field visible ExpGui.VisibleCallback | boolean | nil
|
||||
|
||||
--- Create a toolbar button
|
||||
--- @param options ExpGui.toolbar.create_button__param
|
||||
--- @return ExpElement
|
||||
function Toolbar.create_button(options)
|
||||
-- Extract the custom options from the element.add options
|
||||
local name = assert(options.name, "Name is required for the element")
|
||||
options.type = options.sprite ~= nil and "sprite-button" or "button"
|
||||
|
||||
local visible = options.visible
|
||||
if visible == nil then visible = true end
|
||||
options.visible = nil
|
||||
|
||||
local auto_toggle = options.auto_toggle
|
||||
options.auto_toggle = nil
|
||||
|
||||
local left_element = options.left_element
|
||||
options.left_element = nil
|
||||
|
||||
if options.style == nil then
|
||||
options.style = toolbar_button_default_style
|
||||
end
|
||||
|
||||
-- Create the new element define
|
||||
local toolbar_button = ExpGui.element(name)
|
||||
:track_all_elements()
|
||||
:draw(options)
|
||||
:style{
|
||||
minimal_width = toolbar_button_size,
|
||||
height = toolbar_button_size,
|
||||
padding = options.sprite ~= nil and -2 or nil,
|
||||
}
|
||||
|
||||
-- If a left element was given then link the define
|
||||
if left_element then
|
||||
left_elements_with_button[left_element] = toolbar_button
|
||||
buttons_with_left_element[toolbar_button.name] = left_element
|
||||
end
|
||||
|
||||
-- Setup auto toggle, required if there is a left element
|
||||
if auto_toggle or left_element then
|
||||
toolbar_button:on_click(function(def, player)
|
||||
if left_element then
|
||||
Toolbar.set_left_element_visible_state(left_element, player)
|
||||
else
|
||||
Toolbar.set_button_toggled_state(toolbar_button, player)
|
||||
end
|
||||
end)
|
||||
end
|
||||
|
||||
-- Add the define to the top flow and return
|
||||
toolbar_buttons[#toolbar_buttons + 1] = toolbar_button
|
||||
ExpGui.add_top_element(toolbar_button, visible)
|
||||
return toolbar_button
|
||||
end
|
||||
|
||||
--- Toggles the toolbar settings, RMB will instead hide the toolbar
|
||||
elements.close_toolbar = ExpGui.element("close_toolbar")
|
||||
:draw{
|
||||
type = "sprite-button",
|
||||
sprite = "utility/preset",
|
||||
style = "tool_button",
|
||||
tooltip = { "exp-gui.close-toolbar" },
|
||||
}
|
||||
:style{
|
||||
padding = -2,
|
||||
width = 18,
|
||||
height = 36,
|
||||
}
|
||||
:on_click(function(def, player, element, event)
|
||||
if event.button == defines.mouse_button_type.left then
|
||||
Toolbar.set_left_element_visible_state(elements.toolbar_settings, player)
|
||||
else
|
||||
Toolbar.set_visible_state(player, false)
|
||||
end
|
||||
end)
|
||||
|
||||
--- Shows the toolbar, if no buttons are visible then it shows the settings instead
|
||||
elements.open_toolbar = ExpGui.element("open_toolbar")
|
||||
:track_all_elements()
|
||||
:draw{
|
||||
type = "sprite-button",
|
||||
sprite = "utility/preset",
|
||||
style = "tool_button",
|
||||
tooltip = { "exp-gui.open-toolbar" },
|
||||
}
|
||||
:style{
|
||||
padding = -2,
|
||||
width = 18,
|
||||
height = 20,
|
||||
}
|
||||
:on_click(function(def, player, element, event)
|
||||
if event.button == defines.mouse_button_type.left then
|
||||
Toolbar.set_left_element_visible_state(elements.toolbar_settings, player)
|
||||
else
|
||||
Toolbar.set_visible_state(player, true)
|
||||
end
|
||||
end)
|
||||
|
||||
--- Hides all left elements when clicked
|
||||
elements.clear_left_flow = ExpGui.element("clear_left_flow")
|
||||
:track_all_elements()
|
||||
:draw{
|
||||
type = "sprite-button",
|
||||
sprite = "utility/close_black",
|
||||
style = "tool_button",
|
||||
tooltip = { "exp-gui.clear-left-flow" },
|
||||
}
|
||||
:style{
|
||||
padding = -3,
|
||||
width = 18,
|
||||
height = 20,
|
||||
}
|
||||
:on_click(function(def, player, element)
|
||||
element.visible = false
|
||||
for define in pairs(ExpGui.left_elements) do
|
||||
if define ~= elements.core_button_flow then
|
||||
Toolbar.set_left_element_visible_state(define, player, false, true)
|
||||
end
|
||||
end
|
||||
end)
|
||||
|
||||
--- Contains the two buttons on the left flow
|
||||
elements.core_button_flow = ExpGui.element("core_button_flow")
|
||||
:draw(function(def, parent)
|
||||
local flow = parent.add{
|
||||
type = "flow",
|
||||
direction = "vertical",
|
||||
}
|
||||
|
||||
elements.open_toolbar(flow)
|
||||
elements.clear_left_flow(flow)
|
||||
|
||||
return flow
|
||||
end)
|
||||
|
||||
--[[
|
||||
Below here is the toolbar settings GUI and its associated functions
|
||||
]]
|
||||
|
||||
--- Set the style of the fake toolbar element
|
||||
--- @param src LuaGuiElement
|
||||
--- @param dst LuaGuiElement
|
||||
local function copy_style(src, dst)
|
||||
dst.style = src.style.name
|
||||
dst.style.height = toolbar_button_small
|
||||
dst.style.width = toolbar_button_small
|
||||
dst.style.padding = -2
|
||||
end
|
||||
|
||||
--- Reorder the buttons relative to each other, this will update the datastore
|
||||
--- @param player LuaPlayer
|
||||
--- @param item LuaGuiElement
|
||||
--- @param offset number
|
||||
local function move_toolbar_button(player, item, offset)
|
||||
local old_index = item.get_index_in_parent()
|
||||
local new_index = old_index + offset
|
||||
|
||||
-- Swap the position in the list
|
||||
local list = assert(item.parent)
|
||||
local other_item = list.children[new_index]
|
||||
list.swap_children(old_index, new_index)
|
||||
|
||||
-- Swap the position in the top flow, offset by 1 because of settings button
|
||||
local top_flow = ExpGui.get_top_flow(player)
|
||||
top_flow.swap_children(old_index + 1, new_index + 1)
|
||||
|
||||
-- Check if the element has a left element to move
|
||||
local left_element = buttons_with_left_element[item.name]
|
||||
local other_left_element = buttons_with_left_element[other_item.name]
|
||||
if left_element and other_left_element then
|
||||
local element = ExpGui.get_left_element(left_element, player)
|
||||
local other_element = ExpGui.get_left_element(other_left_element, player)
|
||||
local left_index = element.get_index_in_parent()
|
||||
local other_index = other_element.get_index_in_parent()
|
||||
element.parent.swap_children(left_index, other_index)
|
||||
end
|
||||
|
||||
-- If we are moving in/out of first/last place we need to update the move buttons
|
||||
local last_index = #list.children
|
||||
local item_data = elements.toolbar_list_item.data[item]
|
||||
local other_item_data = elements.toolbar_list_item.data[other_item]
|
||||
if old_index == 1 then -- Moving out of index 1
|
||||
item_data.move_item_up.enabled = true
|
||||
other_item_data.move_item_up.enabled = false
|
||||
elseif new_index == 1 then -- Moving into index 1
|
||||
item_data.move_item_up.enabled = false
|
||||
other_item_data.move_item_up.enabled = true
|
||||
elseif old_index == last_index then -- Moving out of the last index
|
||||
item_data.move_item_down.enabled = true
|
||||
other_item_data.move_item_down.enabled = false
|
||||
elseif new_index == last_index then -- Moving into the last index
|
||||
item_data.move_item_down.enabled = false
|
||||
other_item_data.move_item_down.enabled = true
|
||||
end
|
||||
end
|
||||
|
||||
--- @alias ExpGui.ToolbarOrder { name: string, favourite: boolean }[]
|
||||
|
||||
--- Reorder the toolbar buttons
|
||||
--- @param player LuaPlayer
|
||||
--- @param order ExpGui.ToolbarOrder
|
||||
function Toolbar.set_order(player, order)
|
||||
local list = elements.toolbar_settings.data[player] --[[ @as LuaGuiElement ]]
|
||||
local left_flow = ExpGui.get_left_flow(player)
|
||||
local top_flow = ExpGui.get_top_flow(player)
|
||||
|
||||
-- Reorder the buttons
|
||||
local left_index = 1
|
||||
local last_index = #order
|
||||
for index, item_state in ipairs(order) do
|
||||
-- Switch item order
|
||||
local item = assert(list[item_state.name], "Missing toolbox item for " .. tostring(item_state.name))
|
||||
list.swap_children(index, item.get_index_in_parent())
|
||||
|
||||
-- Switch the toolbar button order
|
||||
local element_define = ExpElement.get(item_state.name)
|
||||
local toolbar_button = ExpGui.get_top_element(element_define, player)
|
||||
top_flow.swap_children(index + 1, toolbar_button.get_index_in_parent())
|
||||
|
||||
-- Update the children buttons
|
||||
local data = elements.toolbar_list_item.data[item]
|
||||
data.set_favourite.state = item_state.favourite
|
||||
data.move_item_up.enabled = index ~= 1
|
||||
data.move_item_down.enabled = index ~= last_index
|
||||
|
||||
-- Switch the left element order
|
||||
local left_define = buttons_with_left_element[item_state.name]
|
||||
if left_define then
|
||||
local left_element = ExpGui.get_left_element(left_define, player)
|
||||
left_flow.swap_children(left_index, left_element.get_index_in_parent())
|
||||
left_index = left_index + 1
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
--- @class (exact) ExpGui.ToolbarState
|
||||
--- @field order ExpGui.ToolbarOrder
|
||||
--- @field open string[]
|
||||
--- @field visible boolean
|
||||
|
||||
--- Reorder the toolbar buttons and set the open state of the left flows
|
||||
--- @param player LuaPlayer
|
||||
--- @param state ExpGui.ToolbarState
|
||||
function Toolbar.set_state(player, state)
|
||||
Toolbar.set_order(player, state.order)
|
||||
Toolbar.set_visible_state(player, state.visible)
|
||||
|
||||
local done = {}
|
||||
-- Make all open elements visible
|
||||
for _, name in pairs(state.open) do
|
||||
local left_element = ExpElement.get(name)
|
||||
Toolbar.set_left_element_visible_state(left_element, player, true, true)
|
||||
done[left_element] = true
|
||||
end
|
||||
|
||||
-- Make all other elements hidden
|
||||
for left_element in pairs(ExpGui.left_elements) do
|
||||
if not done[left_element] then
|
||||
Toolbar.set_left_element_visible_state(left_element, player, false, true)
|
||||
end
|
||||
end
|
||||
|
||||
-- Update clear_left_flow (because we skip above)
|
||||
local has_visible = Toolbar.has_visible_left_elements(player)
|
||||
for _, clear_left_flow in elements.clear_left_flow:tracked_elements(player) do
|
||||
clear_left_flow.visible = has_visible
|
||||
end
|
||||
end
|
||||
|
||||
--- Get the full toolbar state for a player
|
||||
--- @param player LuaPlayer
|
||||
--- @return ExpGui.ToolbarState
|
||||
function Toolbar.get_state(player)
|
||||
-- Get the order of toolbar buttons
|
||||
local order = {}
|
||||
local list = elements.toolbar_settings.data[player] --[[ @as LuaGuiElement ]]
|
||||
for index, item in pairs(list.children) do
|
||||
order[index] = { name = item.name, favourite = elements.toolbar_list_item.data[item].set_favourite.state }
|
||||
end
|
||||
|
||||
-- Get the names of all open left elements
|
||||
local open, open_index = {}, 1
|
||||
for left_element in pairs(ExpGui.left_elements) do
|
||||
if Toolbar.get_left_element_visible_state(left_element, player) then
|
||||
open[open_index] = left_element.name
|
||||
open_index = open_index + 1
|
||||
end
|
||||
end
|
||||
|
||||
return { order = order, open = open, visible = Toolbar.get_visible_state(player) }
|
||||
end
|
||||
|
||||
--- Ensure the toolbar settings gui has all its elements
|
||||
--- @param player LuaPlayer
|
||||
function Toolbar._create_elements(player)
|
||||
-- Add any missing items to the gui
|
||||
local toolbar_list = elements.toolbar_settings.data[player] --[[ @as LuaGuiElement ]]
|
||||
local previous_last_index = #toolbar_list.children_names
|
||||
for define in pairs(ExpGui.top_elements) do
|
||||
if define ~= elements.close_toolbar and toolbar_list[define.name] == nil then
|
||||
local element = elements.toolbar_list_item(toolbar_list, define)
|
||||
element.visible = ExpGui.get_top_element(define, player).visible
|
||||
end
|
||||
end
|
||||
|
||||
-- Reset the state of the previous last child
|
||||
local children = toolbar_list.children
|
||||
if previous_last_index > 0 then
|
||||
elements.toolbar_list_item.data[children[previous_last_index]].move_item_down.enabled = true
|
||||
end
|
||||
|
||||
-- Set the state of the move buttons for the first and last element
|
||||
if #children > 0 then
|
||||
elements.toolbar_list_item.data[children[1]].move_item_up.enabled = false
|
||||
elements.toolbar_list_item.data[children[#children]].move_item_down.enabled = false
|
||||
end
|
||||
end
|
||||
|
||||
--- Ensure all the toolbar buttons are in a consistent state
|
||||
--- @param player LuaPlayer
|
||||
function Toolbar._ensure_consistency(player)
|
||||
-- Update the toolbar buttons
|
||||
local list = elements.toolbar_settings.data[player] --[[ @as LuaGuiElement ]]
|
||||
for _, button in ipairs(toolbar_buttons) do
|
||||
-- Update the visible state based on if the player is allowed the button
|
||||
local element = ExpGui.get_top_element(button, player)
|
||||
local allowed = ExpGui.top_elements[button]
|
||||
if type(allowed) == "function" then
|
||||
allowed = allowed(player, element)
|
||||
end
|
||||
element.visible = allowed and element.visible or false
|
||||
list[button.name].visible = element.visible
|
||||
|
||||
-- Update the toggle state and hide the linked left element if the button is not allowed
|
||||
local left_define = buttons_with_left_element[button.name]
|
||||
if left_define then
|
||||
local left_element = ExpGui.get_left_element(left_define, player)
|
||||
Toolbar.set_button_toggled_state(button, player, left_element.visible)
|
||||
if not allowed then
|
||||
Toolbar.set_left_element_visible_state(left_define, player, false)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- Update clear_left_flow
|
||||
local has_visible = Toolbar.has_visible_left_elements(player)
|
||||
for _, clear_left_flow in elements.clear_left_flow:tracked_elements(player) do
|
||||
clear_left_flow.visible = has_visible
|
||||
end
|
||||
|
||||
-- Update open_toolbar
|
||||
local top_flow = assert(ExpGui.get_top_flow(player).parent)
|
||||
for _, open_toolbar in elements.open_toolbar:tracked_elements(player) do
|
||||
open_toolbar.visible = not top_flow.visible
|
||||
end
|
||||
|
||||
-- Update toggle_toolbar
|
||||
local has_buttons = Toolbar.has_visible_buttons(player)
|
||||
for _, toggle_toolbar in elements.toggle_toolbar:tracked_elements(player) do
|
||||
toggle_toolbar.enabled = has_buttons
|
||||
end
|
||||
end
|
||||
|
||||
do
|
||||
local default_order --- @type ExpGui.ToolbarOrder
|
||||
--- Gets the default order for the toolbar
|
||||
--- @return ExpGui.ToolbarOrder
|
||||
function Toolbar.get_default_order()
|
||||
if default_order then return default_order end
|
||||
|
||||
local index = 1
|
||||
default_order = {}
|
||||
for define in pairs(ExpGui.top_elements) do
|
||||
if define ~= elements.close_toolbar then
|
||||
default_order[index] = { name = define.name, favourite = true }
|
||||
index = index + 1
|
||||
end
|
||||
end
|
||||
|
||||
return default_order
|
||||
end
|
||||
end
|
||||
|
||||
--- Toggle the visibility of the toolbar, does not care if buttons are visible
|
||||
elements.toggle_toolbar = ExpGui.element("toggle_toolbar")
|
||||
:track_all_elements()
|
||||
:draw{
|
||||
type = "sprite-button",
|
||||
sprite = "utility/bookmark",
|
||||
tooltip = { "exp-gui_toolbar-settings.toggle" },
|
||||
style = "tool_button",
|
||||
auto_toggle = true,
|
||||
}
|
||||
:style(ExpGui.styles.sprite{
|
||||
size = 22,
|
||||
})
|
||||
:on_click(function(def, player, element)
|
||||
Toolbar.set_visible_state(player, element.toggled)
|
||||
end)
|
||||
|
||||
--- Reset the toolbar to its default state
|
||||
elements.reset_toolbar = ExpGui.element("reset_toolbar")
|
||||
:draw{
|
||||
type = "sprite-button",
|
||||
sprite = "utility/reset",
|
||||
style = "shortcut_bar_button_red",
|
||||
tooltip = { "exp-gui_toolbar-settings.reset" },
|
||||
}
|
||||
:style(ExpGui.styles.sprite{
|
||||
size = 22,
|
||||
padding = -1,
|
||||
})
|
||||
:on_click(function(def, player, element)
|
||||
Toolbar.set_order(player, Toolbar.get_default_order())
|
||||
end)
|
||||
|
||||
--- Move an item up/left on the toolbar
|
||||
elements.move_item_up = ExpGui.element("move_item_up")
|
||||
:draw{
|
||||
type = "sprite-button",
|
||||
sprite = "utility/speed_up",
|
||||
tooltip = { "exp-gui_toolbar-settings.move-up" },
|
||||
}
|
||||
:style(ExpGui.styles.sprite{
|
||||
size = toolbar_button_small,
|
||||
})
|
||||
:on_click(function(def, player, element)
|
||||
local item = assert(element.parent.parent)
|
||||
move_toolbar_button(player, item, -1)
|
||||
end)
|
||||
|
||||
--- Move an item down/right on the toolbar
|
||||
elements.move_item_down = ExpGui.element("move_item_down")
|
||||
:draw{
|
||||
type = "sprite-button",
|
||||
sprite = "utility/speed_down",
|
||||
tooltip = { "exp-gui_toolbar-settings.move-down" },
|
||||
}
|
||||
:style(ExpGui.styles.sprite{
|
||||
size = toolbar_button_small,
|
||||
})
|
||||
:on_click(function(def, player, element)
|
||||
local item = assert(element.parent.parent)
|
||||
move_toolbar_button(player, item, 1)
|
||||
end)
|
||||
|
||||
--- Set an item as a favourite, making it appear on the toolbar
|
||||
elements.set_favourite = ExpGui.element("set_favourite")
|
||||
:draw(function(def, parent, item_define)
|
||||
--- @cast item_define ExpElement
|
||||
local player = ExpGui.get_player(parent)
|
||||
local top_element = ExpGui.get_top_element(item_define, player)
|
||||
|
||||
return parent.add{
|
||||
type = "checkbox",
|
||||
caption = top_element.tooltip or top_element.caption or nil,
|
||||
state = top_element.visible or false,
|
||||
tags = {
|
||||
element_name = item_define.name,
|
||||
},
|
||||
}
|
||||
end)
|
||||
:style{
|
||||
width = 180,
|
||||
}
|
||||
:on_checked_state_changed(function(def, player, element)
|
||||
local define = ExpElement.get(element.tags.element_name --[[ @as string ]])
|
||||
local top_element = ExpGui.get_top_element(define, player)
|
||||
local had_visible = Toolbar.has_visible_buttons(player)
|
||||
top_element.visible = element.state
|
||||
|
||||
-- Check if we are on the edge case between 0 and 1 visible elements
|
||||
if element.state and not had_visible then
|
||||
Toolbar.set_visible_state(player, true)
|
||||
for _, toggle_toolbar in elements.toggle_toolbar:tracked_elements(player) do
|
||||
toggle_toolbar.enabled = true
|
||||
end
|
||||
elseif not element.state and not Toolbar.has_visible_buttons(player) then
|
||||
Toolbar.set_visible_state(player, false)
|
||||
for _, toggle_toolbar in elements.toggle_toolbar:tracked_elements(player) do
|
||||
toggle_toolbar.enabled = false
|
||||
end
|
||||
end
|
||||
end)
|
||||
|
||||
elements.toolbar_list_item = ExpGui.element("toolbar_list_item")
|
||||
:draw(function(def, parent, item_define)
|
||||
--- @cast item_define ExpElement
|
||||
local data = {}
|
||||
|
||||
-- Add the flow for the item
|
||||
local flow = parent.add{
|
||||
name = item_define.name,
|
||||
type = "frame",
|
||||
style = "shortcut_selection_row",
|
||||
}
|
||||
flow.style.horizontally_stretchable = true
|
||||
flow.style.vertical_align = "center"
|
||||
|
||||
-- Add the button and the icon edit button
|
||||
local element = item_define(flow)
|
||||
local player = ExpGui.get_player(parent)
|
||||
local top_element = ExpGui.get_top_element(item_define, player)
|
||||
copy_style(top_element, element)
|
||||
|
||||
-- Add the favourite checkbox and label
|
||||
data.set_favourite = elements.set_favourite(flow, item_define)
|
||||
|
||||
-- Add the buttons used to move the flow up and down
|
||||
local move_flow = flow.add{ type = "flow", name = "move" }
|
||||
move_flow.style.horizontal_spacing = 0
|
||||
data.move_item_up = elements.move_item_up(move_flow)
|
||||
data.move_item_down = elements.move_item_down(move_flow)
|
||||
|
||||
def.data[flow] = data
|
||||
return flow
|
||||
end)
|
||||
|
||||
--- Main list for all toolbar items
|
||||
elements.toolbar_list = ExpGui.element("toolbar_list")
|
||||
:draw(function(def, parent)
|
||||
local scroll = parent.add{
|
||||
type = "scroll-pane",
|
||||
direction = "vertical",
|
||||
horizontal_scroll_policy = "never",
|
||||
vertical_scroll_policy = "auto",
|
||||
style = "scroll_pane_under_subheader",
|
||||
}
|
||||
scroll.style.horizontally_stretchable = true
|
||||
scroll.style.maximal_height = 224
|
||||
scroll.style.padding = 0
|
||||
|
||||
-- This is required because vertical_spacing can't be set on a scroll pane
|
||||
return scroll.add{
|
||||
type = "flow",
|
||||
direction = "vertical",
|
||||
}
|
||||
end)
|
||||
:style{
|
||||
horizontally_stretchable = true,
|
||||
vertical_spacing = 0,
|
||||
}
|
||||
|
||||
-- The main container for the toolbar settings
|
||||
elements.toolbar_settings = ExpGui.element("toolbar_settings")
|
||||
:draw(function(def, parent)
|
||||
-- Draw the container
|
||||
local frame = ExpGui.elements.container(parent, 268)
|
||||
frame.style.maximal_width = 268
|
||||
frame.style.minimal_width = 268
|
||||
|
||||
-- Draw the header
|
||||
local player = ExpGui.get_player(parent)
|
||||
local header = ExpGui.elements.header(frame, {
|
||||
caption = { "exp-gui_toolbar-settings.main-caption" },
|
||||
tooltip = { "exp-gui_toolbar-settings.main-tooltip" },
|
||||
})
|
||||
|
||||
-- Draw the toolbar control buttons
|
||||
local toggle_element = elements.toggle_toolbar(header)
|
||||
toggle_element.toggled = Toolbar.get_visible_state(player)
|
||||
elements.reset_toolbar(header)
|
||||
|
||||
def.data[player] = elements.toolbar_list(frame)
|
||||
Toolbar._create_elements(player)
|
||||
return frame.parent
|
||||
end)
|
||||
|
||||
ExpGui.add_left_element(elements.core_button_flow, true)
|
||||
ExpGui.add_left_element(elements.toolbar_settings, false)
|
||||
ExpGui.add_top_element(elements.close_toolbar, true)
|
||||
|
||||
return Toolbar
|
||||
35
exp_gui/package.json
Normal file
35
exp_gui/package.json
Normal file
@@ -0,0 +1,35 @@
|
||||
{
|
||||
"name": "@expcluster/lib_gui",
|
||||
"version": "0.1.0",
|
||||
"description": "Clusterio plugin providing a Lua GUI definition library.",
|
||||
"author": "Cooldude2606 <https://github.com/Cooldude2606>",
|
||||
"license": "MIT",
|
||||
"repository": "explosivegaming/ExpCluster",
|
||||
"main": "dist/node/index.js",
|
||||
"scripts": {
|
||||
"prepare": "tsc --build"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@clusterio/lib": "^2.0.0-alpha.19"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@clusterio/lib": "2.0.0-alpha.19",
|
||||
"@types/node": "^20.14.9",
|
||||
"typescript": "^5.5.3"
|
||||
},
|
||||
"dependencies": {
|
||||
"@expcluster/lib_util": "workspace:*",
|
||||
"@sinclair/typebox": "^0.30.4"
|
||||
},
|
||||
"publishConfig": {
|
||||
"access": "public"
|
||||
},
|
||||
"keywords": [
|
||||
"clusterio",
|
||||
"clusterio-plugin",
|
||||
"factorio"
|
||||
]
|
||||
}
|
||||
6
exp_gui/tsconfig.json
Normal file
6
exp_gui/tsconfig.json
Normal file
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"files": [],
|
||||
"references": [
|
||||
{ "path": "./tsconfig.node.json" }
|
||||
]
|
||||
}
|
||||
5
exp_gui/tsconfig.node.json
Normal file
5
exp_gui/tsconfig.node.json
Normal file
@@ -0,0 +1,5 @@
|
||||
{
|
||||
"extends": "../tsconfig.node.json",
|
||||
"include": ["./**/*.ts"],
|
||||
"exclude": ["test/*", "./dist/*"],
|
||||
}
|
||||
@@ -41,14 +41,15 @@ return {
|
||||
-- 'modules.data.bonus',
|
||||
"modules.data.personal-logistic",
|
||||
"modules.data.language",
|
||||
--"modules.data.toolbar",
|
||||
|
||||
--- GUI
|
||||
"modules.gui.readme",
|
||||
-- "modules.gui.rocket-info",
|
||||
-- "modules.gui.science-info",
|
||||
"modules.gui.autofill",
|
||||
"modules.gui.warp-list",
|
||||
"modules.gui.task-list",
|
||||
"modules.gui.warp-list",
|
||||
"modules.gui.player-list",
|
||||
"modules.gui.server-ups",
|
||||
"modules.gui.bonus",
|
||||
@@ -60,9 +61,9 @@ return {
|
||||
"modules.gui.production",
|
||||
"modules.gui.playerdata",
|
||||
"modules.gui.surveillance",
|
||||
"modules.graftorio.require", -- graftorio
|
||||
"modules.gui.toolbar", -- must be loaded last to register toolbar handlers
|
||||
"modules.gui._role_updates",
|
||||
|
||||
"modules.graftorio.require", -- graftorio
|
||||
--- Config Files
|
||||
"config.expcore.permission_groups", -- loads some predefined permission groups
|
||||
"config.expcore.roles", -- loads some predefined roles
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
-- @config Player-List
|
||||
|
||||
local ExpUtil = require("modules/exp_util")
|
||||
local Gui = require("modules.exp_legacy.expcore.gui") --- @dep expcore.gui
|
||||
local Gui = require("modules/exp_gui")
|
||||
local Roles = require("modules.exp_legacy.expcore.roles") --- @dep expcore.roles
|
||||
local Reports = require("modules.exp_legacy.modules.control.reports") --- @dep modules.control.reports
|
||||
local Warnings = require("modules.exp_legacy.modules.control.warnings") --- @dep modules.control.warnings
|
||||
@@ -47,22 +47,24 @@ local function teleport(from_player, to_player)
|
||||
end
|
||||
|
||||
local function new_button(sprite, tooltip)
|
||||
return Gui.element{
|
||||
type = "sprite-button",
|
||||
style = "tool_button",
|
||||
sprite = sprite,
|
||||
tooltip = tooltip,
|
||||
}:style{
|
||||
padding = -1,
|
||||
height = 28,
|
||||
width = 28,
|
||||
}
|
||||
return Gui.element(tooltip[1])
|
||||
:draw{
|
||||
type = "sprite-button",
|
||||
style = "tool_button",
|
||||
sprite = sprite,
|
||||
tooltip = tooltip,
|
||||
}
|
||||
:style{
|
||||
padding = -1,
|
||||
height = 28,
|
||||
width = 28,
|
||||
}
|
||||
end
|
||||
|
||||
--- Teleports the user to the action player
|
||||
-- @element goto_player
|
||||
local goto_player = new_button("utility/export", { "player-list.goto-player" })
|
||||
:on_click(function(player)
|
||||
:on_click(function(def, player, element)
|
||||
local selected_player_name = get_action_player_name(player)
|
||||
local selected_player = game.players[selected_player_name]
|
||||
if not player.character or not selected_player.character then
|
||||
@@ -75,7 +77,7 @@ local goto_player = new_button("utility/export", { "player-list.goto-player" })
|
||||
--- Teleports the action player to the user
|
||||
-- @element bring_player
|
||||
local bring_player = new_button("utility/import", { "player-list.bring-player" })
|
||||
:on_click(function(player)
|
||||
:on_click(function(def, player, element)
|
||||
local selected_player_name = get_action_player_name(player)
|
||||
local selected_player = game.players[selected_player_name]
|
||||
if not player.character or not selected_player.character then
|
||||
@@ -88,7 +90,7 @@ local bring_player = new_button("utility/import", { "player-list.bring-player" }
|
||||
--- Reports the action player, requires a reason to be given
|
||||
-- @element report_player
|
||||
local report_player = new_button("utility/spawn_flag", { "player-list.report-player" })
|
||||
:on_click(function(player)
|
||||
:on_click(function(def, player, element)
|
||||
local selected_player_name = get_action_player_name(player)
|
||||
if Reports.is_reported(selected_player_name, player.name) then
|
||||
player.print({ "exp-commands_report.already-reported" }, Colors.orange_red)
|
||||
@@ -108,7 +110,7 @@ end
|
||||
--- Gives the action player a warning, requires a reason
|
||||
-- @element warn_player
|
||||
local warn_player = new_button("utility/spawn_flag", { "player-list.warn-player" })
|
||||
:on_click(function(player)
|
||||
:on_click(function(def, player, element)
|
||||
SelectedAction:set(player, "command/give-warning")
|
||||
end)
|
||||
|
||||
@@ -122,7 +124,7 @@ end
|
||||
--- Jails the action player, requires a reason
|
||||
-- @element jail_player
|
||||
local jail_player = new_button("utility/multiplayer_waiting_icon", { "player-list.jail-player" })
|
||||
:on_click(function(player)
|
||||
:on_click(function(def, player, element)
|
||||
local selected_player_name, selected_player_color = get_action_player_name(player)
|
||||
if Jail.is_jailed(selected_player_name) then
|
||||
player.print({ "exp-commands_jail.already-jailed", selected_player_color }, Colors.orange_red)
|
||||
@@ -141,7 +143,7 @@ end
|
||||
--- Kicks the action player, requires a reason
|
||||
-- @element kick_player
|
||||
local kick_player = new_button("utility/warning_icon", { "player-list.kick-player" })
|
||||
:on_click(function(player)
|
||||
:on_click(function(def, player, element)
|
||||
SelectedAction:set(player, "command/kick")
|
||||
end)
|
||||
|
||||
@@ -153,7 +155,7 @@ end
|
||||
--- Bans the action player, requires a reason
|
||||
-- @element ban_player
|
||||
local ban_player = new_button("utility/danger_icon", { "player-list.ban-player" })
|
||||
:on_click(function(player)
|
||||
:on_click(function(def, player, element)
|
||||
SelectedAction:set(player, "command/ban")
|
||||
end)
|
||||
|
||||
|
||||
@@ -13,4 +13,9 @@ return {
|
||||
"production-science-pack",
|
||||
"utility-science-pack",
|
||||
"space-science-pack",
|
||||
"metallurgic-science-pack",
|
||||
"agricultural-science-pack",
|
||||
"electromagnetic-science-pack",
|
||||
"cryogenic-science-pack",
|
||||
"promethium-science-pack",
|
||||
}
|
||||
|
||||
@@ -164,6 +164,10 @@ Storage.register(Data, function(tbl)
|
||||
for name, datastore in pairs(Datastores) do
|
||||
datastore.data = Data[name]
|
||||
end
|
||||
end, function(tbl)
|
||||
for name in pairs(Datastores) do
|
||||
tbl[name] = tbl[name] or {}
|
||||
end
|
||||
end)
|
||||
|
||||
----- Datastore Manager
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
return require("modules.exp_legacy.expcore.gui._require")
|
||||
@@ -1,144 +0,0 @@
|
||||
--[[-- Core Module - Gui
|
||||
- Used to simplify gui creation using factory functions called element defines
|
||||
@core Gui
|
||||
@alias Gui
|
||||
|
||||
@usage-- To draw your element you only need to call the factory function
|
||||
-- You are able to pass any other arguments that are used in your custom functions but the first is always the parent element
|
||||
local example_button_element = example_button(parent_element)
|
||||
|
||||
@usage-- Making a factory function for a button with the caption "Example Button"
|
||||
-- This method has all the same features as LuaGuiElement.add
|
||||
local example_button =
|
||||
Gui.element{
|
||||
type = 'button',
|
||||
caption = 'Example Button'
|
||||
}
|
||||
|
||||
@usage-- Making a factory function for a button which is contained within a flow
|
||||
-- This method is for when you still want to register event handlers but cant use the table method
|
||||
local example_flow_with_button =
|
||||
Gui.element(function(definition, parent, ...)
|
||||
-- ... shows that all other arguments from the factory call are passed to this function
|
||||
-- Here we are adding a flow which we will then later add a button to
|
||||
local flow =
|
||||
parent.add{ -- paraent is the element which is passed to the factory function
|
||||
name = 'example_flow',
|
||||
type = 'flow'
|
||||
}
|
||||
|
||||
-- Now we add the button to the flow that we created earlier
|
||||
local element = definition:triggers_event(
|
||||
flow.add{
|
||||
type = 'button',
|
||||
caption = 'Example Button'
|
||||
}
|
||||
)
|
||||
|
||||
-- You must return a new element, this is so styles can be applied and returned to the caller
|
||||
-- You may return any of your elements that you added, consider the context in which it will be used for which should be returned
|
||||
return element
|
||||
end)
|
||||
|
||||
@usage-- Styles can be added to any element define, simplest way mimics LuaGuiElement.style[key] = value
|
||||
local example_button =
|
||||
Gui.element{
|
||||
type = 'button',
|
||||
caption = 'Example Button',
|
||||
style = 'forward_button' -- factorio styles can be applied here
|
||||
}
|
||||
:style{
|
||||
height = 25, -- same as element.style.height = 25
|
||||
width = 100 -- same as element.style.width = 25
|
||||
}
|
||||
|
||||
@usage-- Styles can also have a custom function when the style is dynamic and depends on other factors
|
||||
-- Use this method if your style is dynamic and depends on other factors
|
||||
local example_button =
|
||||
Gui.element{
|
||||
type = 'button',
|
||||
caption = 'Example Button',
|
||||
style = 'forward_button' -- factorio styles can be applied here
|
||||
}
|
||||
:style(function(style, element, ...)
|
||||
-- style is the current style object for the elemenent
|
||||
-- element is the element that is being changed
|
||||
-- ... shows that all other arguments from the factory call are passed to this function
|
||||
local player = game.players[element.player_index]
|
||||
style.height = 25
|
||||
style.width = 100
|
||||
style.font_color = player.color
|
||||
end)
|
||||
|
||||
@usage-- You are able to register event handlers to your elements, these can be factorio events or custom ones
|
||||
-- All events are checked to be valid before raising any handlers, this means element.valid = true and player.valid = true
|
||||
Gui.element{
|
||||
type = 'button',
|
||||
caption = 'Example Button'
|
||||
}
|
||||
:on_click(function(player, element, event)
|
||||
-- player is the player who interacted with the element to cause the event
|
||||
-- element is a refrence to the element which caused the event
|
||||
-- event is a raw refrence to the event data if player and element are not enough
|
||||
player.print('Clicked: '..element.name)
|
||||
end)
|
||||
|
||||
@usage-- Example from core_defines, Gui.core_defines.hide_left_flow, called like: hide_left_flow(parent_element)
|
||||
--- Button which hides the elements in the left flow, shows inside the left flow when frames are visible
|
||||
-- @element hide_left_flow
|
||||
local hide_left_flow =
|
||||
Gui.element{
|
||||
type = 'sprite-button',
|
||||
sprite = 'utility/close_black',
|
||||
style = 'tool_button',
|
||||
tooltip = {'expcore-gui.left-button-tooltip'}
|
||||
}
|
||||
:style{
|
||||
padding = -3,
|
||||
width = 18,
|
||||
height = 20
|
||||
}
|
||||
:on_click(function(player, _,_)
|
||||
Gui.hide_left_flow(player)
|
||||
end)
|
||||
|
||||
@usage-- Eample from defines, Gui.alignment, called like: Gui.alignment(parent, name, horizontal_align, vertical_align)
|
||||
-- Notice how _ are used to blank arguments that are not needed in that context and how they line up with above
|
||||
Gui.alignment =
|
||||
Gui.element(function(_, parent, name, _,_)
|
||||
return parent.add{
|
||||
name = name or 'alignment',
|
||||
type = 'flow',
|
||||
}
|
||||
end)
|
||||
:style(function(style, _,_, horizontal_align, vertical_align)
|
||||
style.padding = {1, 2}
|
||||
style.vertical_align = vertical_align or 'center'
|
||||
style.horizontal_align = horizontal_align or 'right'
|
||||
style.vertically_stretchable = style.vertical_align ~= 'center'
|
||||
style.horizontally_stretchable = style.horizontal_align ~= 'center'
|
||||
end)
|
||||
|
||||
]]
|
||||
|
||||
local ExpUtil = require("modules/exp_util")
|
||||
local Gui = require("modules.exp_legacy.expcore.gui.prototype")
|
||||
require("modules.exp_legacy.expcore.gui.helper_functions")
|
||||
require("modules.exp_legacy.expcore.gui.core_defines")
|
||||
require("modules.exp_legacy.expcore.gui.top_flow")
|
||||
require("modules.exp_legacy.expcore.gui.left_flow")
|
||||
require("modules.exp_legacy.expcore.gui.defines")
|
||||
|
||||
local Roles = ExpUtil.optional_require("modules.exp_legacy.expcore.roles")
|
||||
local Event = ExpUtil.optional_require("modules/exp_legacy/utils/event")
|
||||
|
||||
if Roles and Event then
|
||||
Event.add(Roles.events.on_role_assigned, function(e)
|
||||
Gui.update_top_flow(game.players[e.player_index])
|
||||
end)
|
||||
Event.add(Roles.events.on_role_unassigned, function(e)
|
||||
Gui.update_top_flow(game.players[e.player_index])
|
||||
end)
|
||||
end
|
||||
|
||||
return Gui
|
||||
@@ -1,89 +0,0 @@
|
||||
--[[-- Core Module - Gui
|
||||
- Gui defines that are used internally by the gui system
|
||||
@module Gui
|
||||
]]
|
||||
|
||||
local Gui = require("modules.exp_legacy.expcore.gui.prototype")
|
||||
local Event = require("modules/exp_legacy/utils/event")
|
||||
|
||||
--- Core Defines.
|
||||
-- @section coreDefines
|
||||
|
||||
--- Button which toggles the top flow elements, version which shows inside the top flow when top flow is visible
|
||||
-- @element hide_top_flow
|
||||
local hide_top_flow =
|
||||
Gui.element{
|
||||
type = "sprite-button",
|
||||
sprite = "utility/preset",
|
||||
style = "tool_button",
|
||||
tooltip = { "gui_util.button_tooltip" },
|
||||
name = Gui.unique_static_name,
|
||||
}
|
||||
:style{
|
||||
padding = -2,
|
||||
width = 18,
|
||||
height = 36,
|
||||
}
|
||||
:on_click(function(player, _, _)
|
||||
Gui.toggle_top_flow(player, false)
|
||||
end)
|
||||
Gui.core_defines.hide_top_flow = hide_top_flow
|
||||
|
||||
--- Button which toggles the top flow elements, version which shows inside the left flow when top flow is hidden
|
||||
-- @element show_top_flow
|
||||
local show_top_flow =
|
||||
Gui.element{
|
||||
type = "sprite-button",
|
||||
sprite = "utility/preset",
|
||||
style = "tool_button",
|
||||
tooltip = { "gui_util.button_tooltip" },
|
||||
name = Gui.unique_static_name,
|
||||
}
|
||||
:style{
|
||||
padding = -2,
|
||||
width = 18,
|
||||
height = 20,
|
||||
}
|
||||
:on_click(function(player, _, _)
|
||||
Gui.toggle_top_flow(player, true)
|
||||
end)
|
||||
Gui.core_defines.show_top_flow = show_top_flow
|
||||
|
||||
--- Button which hides the elements in the left flow, shows inside the left flow when frames are visible
|
||||
-- @element hide_left_flow
|
||||
local hide_left_flow =
|
||||
Gui.element{
|
||||
type = "sprite-button",
|
||||
sprite = "utility/close_black",
|
||||
style = "tool_button",
|
||||
tooltip = { "expcore-gui.left-button-tooltip" },
|
||||
name = Gui.unique_static_name,
|
||||
}
|
||||
:style{
|
||||
padding = -3,
|
||||
width = 18,
|
||||
height = 20,
|
||||
}
|
||||
:on_click(function(player, _, _)
|
||||
Gui.hide_left_flow(player)
|
||||
end)
|
||||
Gui.core_defines.hide_left_flow = hide_left_flow
|
||||
|
||||
--- Draw the core elements when a player joins the game
|
||||
Event.add(defines.events.on_player_created, function(event)
|
||||
local player = game.players[event.player_index]
|
||||
|
||||
-- Draw the top flow
|
||||
local top_flow = Gui.get_top_flow(player)
|
||||
hide_top_flow(top_flow)
|
||||
Gui.update_top_flow(player)
|
||||
|
||||
-- Draw the left flow
|
||||
local left_flow = Gui.get_left_flow(player)
|
||||
local button_flow = left_flow.add{ type = "flow", name = "gui_core_buttons", direction = "vertical" }
|
||||
local show_top = show_top_flow(button_flow)
|
||||
local hide_left = hide_left_flow(button_flow)
|
||||
show_top.visible = false
|
||||
hide_left.visible = false
|
||||
Gui.draw_left_flow(player)
|
||||
end)
|
||||
@@ -1,301 +0,0 @@
|
||||
--[[-- Core Module - Gui
|
||||
- Common defines that are used by other modules, non of these are used internally
|
||||
@module Gui
|
||||
]]
|
||||
|
||||
local Gui = require("modules.exp_legacy.expcore.gui.prototype")
|
||||
|
||||
--- Defines.
|
||||
-- @section defines
|
||||
|
||||
--[[-- Draw a flow used to align its child elements, default is right align
|
||||
@element Gui.alignment
|
||||
@tparam LuaGuiElement parent the parent element to which the alignment will be added
|
||||
@tparam[opt='alignment'] string name the name of the alignment flow which is added
|
||||
@tparam[opt='right'] string horizontal_align the horizontal alignment of the elements in the flow
|
||||
@tparam[opt='center'] string vertical_align the vertical alignment of the elements in the flow
|
||||
@treturn LuaGuiElement the alignment flow that was created
|
||||
|
||||
@usage-- Adding a right align flow
|
||||
local alignment = Gui.alignment(element, 'example_right_alignment')
|
||||
|
||||
@usage-- Adding a horizontal center and top align flow
|
||||
local alignment = Gui.alignment(element, 'example_center_top_alignment', 'center', 'top')
|
||||
|
||||
]]
|
||||
Gui.alignment =
|
||||
Gui.element(function(_, parent, name, _, _)
|
||||
return parent.add{
|
||||
name = name or "alignment",
|
||||
type = "flow",
|
||||
}
|
||||
end)
|
||||
:style(function(style, _, _, horizontal_align, vertical_align)
|
||||
style.padding = { 1, 2 }
|
||||
style.vertical_align = vertical_align or "center"
|
||||
style.horizontal_align = horizontal_align or "right"
|
||||
style.vertically_stretchable = style.vertical_align ~= "center"
|
||||
style.horizontally_stretchable = style.horizontal_align ~= "center"
|
||||
end)
|
||||
|
||||
--[[-- Draw a scroll pane that has a table inside of it
|
||||
@element Gui.scroll_table
|
||||
@tparam LuaGuiElement parent the parent element to which the scroll table will be added
|
||||
@tparam number height the maximum height for the scroll pane
|
||||
@tparam number column_count the number of columns that the table will have
|
||||
@tparam[opt='scroll'] string name the name of the scroll pane that is added, the table is always called "table"
|
||||
@treturn LuaGuiElement the table that was created
|
||||
|
||||
@usage-- Adding a scroll table with max height of 200 and column count of 3
|
||||
local scroll_table = Gui.scroll_table(element, 200, 3)
|
||||
|
||||
]]
|
||||
Gui.scroll_table =
|
||||
Gui.element(function(_, parent, height, column_count, name)
|
||||
-- Draw the scroll
|
||||
local scroll_pane =
|
||||
parent.add{
|
||||
name = name or "scroll",
|
||||
type = "scroll-pane",
|
||||
direction = "vertical",
|
||||
horizontal_scroll_policy = "never",
|
||||
vertical_scroll_policy = "auto",
|
||||
style = "scroll_pane_under_subheader",
|
||||
}
|
||||
|
||||
-- Set the style of the scroll pane
|
||||
local scroll_style = scroll_pane.style
|
||||
scroll_style.padding = { 1, 3 }
|
||||
scroll_style.maximal_height = height
|
||||
scroll_style.horizontally_stretchable = true
|
||||
|
||||
-- Draw the table
|
||||
local scroll_table =
|
||||
scroll_pane.add{
|
||||
type = "table",
|
||||
name = "table",
|
||||
column_count = column_count,
|
||||
}
|
||||
|
||||
-- Return the scroll table
|
||||
return scroll_table
|
||||
end)
|
||||
:style{
|
||||
padding = 0,
|
||||
cell_padding = 0,
|
||||
vertical_align = "center",
|
||||
horizontally_stretchable = true,
|
||||
}
|
||||
|
||||
--[[-- Used to add a frame with the header style, has the option for a right alignment flow for buttons
|
||||
@element Gui.header
|
||||
@tparam LuaGuiElement parent the parent element to which the header will be added
|
||||
@tparam ?string|Concepts.LocalizedString caption the caption that will be shown on the header
|
||||
@tparam[opt] ?string|Concepts.LocalizedString tooltip the tooltip that will be shown on the header
|
||||
@tparam[opt=false] boolean add_alignment when true an alignment flow will be added to the header
|
||||
@tparam[opt='header'] string name the name of the header that is being added, the alignment is always called "alignment"
|
||||
@treturn LuaGuiElement either the header or the header alignment if add_alignment is true
|
||||
|
||||
@usage-- Adding a custom header with a label
|
||||
local header = Gui.header(
|
||||
element,
|
||||
'Example Caption',
|
||||
'Example Tooltip'
|
||||
)
|
||||
|
||||
]]
|
||||
Gui.header =
|
||||
Gui.element(function(_, parent, caption, tooltip, add_alignment, name, label_name)
|
||||
-- Draw the header
|
||||
local header =
|
||||
parent.add{
|
||||
name = name or "header",
|
||||
type = "frame",
|
||||
style = "subheader_frame",
|
||||
}
|
||||
|
||||
-- Change the style of the header
|
||||
local style = header.style
|
||||
style.padding = { 2, 4 }
|
||||
style.use_header_filler = false
|
||||
style.horizontally_stretchable = true
|
||||
|
||||
-- Draw the caption label
|
||||
if caption then
|
||||
header.add{
|
||||
name = label_name or "header_label",
|
||||
type = "label",
|
||||
style = "frame_title",
|
||||
caption = caption,
|
||||
tooltip = tooltip,
|
||||
}
|
||||
end
|
||||
|
||||
-- Return either the header or the added alignment
|
||||
return add_alignment and Gui.alignment(header) or header
|
||||
end)
|
||||
|
||||
--[[-- Used to add a frame with the footer style, has the option for a right alignment flow for buttons
|
||||
@element Gui.footer
|
||||
@tparam LuaGuiElement parent the parent element to which the footer will be added
|
||||
@tparam ?string|Concepts.LocalizedString caption the caption that will be shown on the footer
|
||||
@tparam[opt] ?string|Concepts.LocalizedString tooltip the tooltip that will be shown on the footer
|
||||
@tparam[opt=false] boolean add_alignment when true an alignment flow will be added to the footer
|
||||
@tparam[opt='footer'] string name the name of the footer that is being added, the alignment is always called "alignment"
|
||||
@treturn LuaGuiElement either the footer or the footer alignment if add_alignment is true
|
||||
|
||||
@usage-- Adding a custom footer with a label
|
||||
local footer = Gui.footer(
|
||||
element,
|
||||
'Example Caption',
|
||||
'Example Tooltip'
|
||||
)
|
||||
|
||||
]]
|
||||
Gui.footer =
|
||||
Gui.element(function(_, parent, caption, tooltip, add_alignment, name)
|
||||
-- Draw the header
|
||||
local footer =
|
||||
parent.add{
|
||||
name = name or "footer",
|
||||
type = "frame",
|
||||
style = "subfooter_frame",
|
||||
}
|
||||
|
||||
-- Change the style of the footer
|
||||
local style = footer.style
|
||||
style.padding = { 2, 4 }
|
||||
style.use_header_filler = false
|
||||
style.horizontally_stretchable = true
|
||||
|
||||
-- Draw the caption label
|
||||
if caption then
|
||||
footer.add{
|
||||
name = "footer_label",
|
||||
type = "label",
|
||||
style = "frame_title",
|
||||
caption = caption,
|
||||
tooltip = tooltip,
|
||||
}
|
||||
end
|
||||
|
||||
-- Return either the footer or the added alignment
|
||||
return add_alignment and Gui.alignment(footer) or footer
|
||||
end)
|
||||
|
||||
--[[-- Used for left frames to give them a nice boarder
|
||||
@element Gui.container
|
||||
@tparam LuaGuiElement parent the parent element to which the container will be added
|
||||
@tparam string name the name that you want to give to the outer frame, often just event_trigger
|
||||
@tparam number width the minimal width that the frame will have
|
||||
|
||||
@usage-- Adding a container as a base
|
||||
local container = Gui.container(parent, 'my_container', 200)
|
||||
|
||||
]]
|
||||
Gui.container =
|
||||
Gui.element(function(_, parent, name, _)
|
||||
-- Draw the external container
|
||||
local frame =
|
||||
parent.add{
|
||||
name = name,
|
||||
type = "frame",
|
||||
}
|
||||
frame.style.horizontally_stretchable = false
|
||||
|
||||
-- Return the container
|
||||
return frame.add{
|
||||
name = "container",
|
||||
type = "frame",
|
||||
direction = "vertical",
|
||||
style = "inside_shallow_frame_packed",
|
||||
}
|
||||
end)
|
||||
:style(function(style, element, _, width)
|
||||
style.vertically_stretchable = false
|
||||
local frame_style = element.parent.style
|
||||
frame_style.padding = 2
|
||||
frame_style.minimal_width = width
|
||||
end)
|
||||
|
||||
--[[-- Used to make a solid white bar in a gui
|
||||
@element Gui.bar
|
||||
@tparam LuaGuiElement parent the parent element to which the bar will be added
|
||||
@tparam number width the width of the bar that will be made, if not given bar will strech to fill the parent
|
||||
|
||||
@usage-- Adding a bar to a gui
|
||||
local bar = Gui.bar(parent, 100)
|
||||
|
||||
]]
|
||||
Gui.bar =
|
||||
Gui.element(function(_, parent)
|
||||
return parent.add{
|
||||
type = "progressbar",
|
||||
size = 1,
|
||||
value = 1,
|
||||
}
|
||||
end)
|
||||
:style(function(style, _, width)
|
||||
style.height = 3
|
||||
style.color = { r = 255, g = 255, b = 255 }
|
||||
if width then
|
||||
style.width = width
|
||||
else
|
||||
style.horizontally_stretchable = true
|
||||
end
|
||||
end)
|
||||
|
||||
--[[-- Used to make a label which is centered and of a certian size
|
||||
@element Gui.centered_label
|
||||
@tparam LuaGuiElement parent the parent element to which the label will be added
|
||||
@tparam number width the width of the label, must be given in order to center the caption
|
||||
@tparam ?string|Concepts.LocalizedString caption the caption that will be shown on the label
|
||||
@tparam[opt] ?string|Concepts.LocalizedString tooltip the tooltip that will be shown on the label
|
||||
|
||||
@usage-- Adding a centered label
|
||||
local label = Gui.centered_label(parent, 100, 'This is centered')
|
||||
|
||||
]]
|
||||
Gui.centered_label =
|
||||
Gui.element(function(_, parent, width, caption, tooltip)
|
||||
local label = parent.add{
|
||||
type = "label",
|
||||
caption = caption,
|
||||
tooltip = tooltip,
|
||||
}
|
||||
|
||||
local style = label.style
|
||||
style.horizontal_align = "center"
|
||||
style.single_line = false
|
||||
style.width = width
|
||||
|
||||
return label
|
||||
end)
|
||||
|
||||
--[[-- Used to make a title which has two bars on either side
|
||||
@element Gui.title_label
|
||||
@tparam LuaGuiElement parent the parent element to which the label will be added
|
||||
@tparam number width the width of the first bar, this can be used to position the label
|
||||
@tparam ?string|Concepts.LocalizedString caption the caption that will be shown on the label
|
||||
@tparam[opt] ?string|Concepts.LocalizedString tooltip the tooltip that will be shown on the label
|
||||
|
||||
@usage-- Adding a centered label
|
||||
local label = Gui.centered_label(parent, 100, 'This is centered')
|
||||
|
||||
]]
|
||||
Gui.title_label =
|
||||
Gui.element(function(_, parent, width, caption, tooltip)
|
||||
local title_flow = parent.add{ type = "flow" }
|
||||
title_flow.style.vertical_align = "center"
|
||||
|
||||
Gui.bar(title_flow, width)
|
||||
local title_label = title_flow.add{
|
||||
type = "label",
|
||||
caption = caption,
|
||||
tooltip = tooltip,
|
||||
style = "frame_title",
|
||||
}
|
||||
Gui.bar(title_flow)
|
||||
|
||||
return title_label
|
||||
end)
|
||||
@@ -1,91 +0,0 @@
|
||||
--[[-- Core Module - Gui
|
||||
- Functions used to help with the use of guis
|
||||
@module Gui
|
||||
]]
|
||||
|
||||
local Gui = require("modules.exp_legacy.expcore.gui.prototype")
|
||||
|
||||
--- Helper Functions.
|
||||
-- @section helperFunctions
|
||||
|
||||
--[[-- Get the player that owns a gui element
|
||||
@tparam LuaGuiElement element the element to get the owner of
|
||||
@treturn LuaPlayer the player that owns this element
|
||||
|
||||
@usage-- Geting the owner of an element
|
||||
local player = Gui.get_player_from_element(element)
|
||||
|
||||
]]
|
||||
function Gui.get_player_from_element(element)
|
||||
if not element or not element.valid then return end
|
||||
return game.players[element.player_index]
|
||||
end
|
||||
|
||||
--[[-- Will toggle the enabled state of an element or set it to the one given
|
||||
@tparam LuaGuiElement element the element to toggle/set the enabled state of
|
||||
@tparam[opt] boolean state with given will set the state, else state will be toggled
|
||||
@treturn boolean the new enabled state that the element has
|
||||
|
||||
@usage-- Toggling the the enabled state
|
||||
local new_enabled_state = Gui.toggle_enabled_state(element)
|
||||
|
||||
]]
|
||||
function Gui.toggle_enabled_state(element, state)
|
||||
if not element or not element.valid then return end
|
||||
if state == nil then state = not element.enabled end
|
||||
element.enabled = state
|
||||
return state
|
||||
end
|
||||
|
||||
--[[-- Will toggle the visible state of an element or set it to the one given
|
||||
@tparam LuaGuiElement element the element to toggle/set the visible state of
|
||||
@tparam[opt] boolean state with given will set the state, else state will be toggled
|
||||
@treturn boolean the new visible state that the element has
|
||||
|
||||
@usage-- Toggling the the visible state
|
||||
local new_visible_state = Gui.toggle_visible_state(element)
|
||||
|
||||
]]
|
||||
function Gui.toggle_visible_state(element, state)
|
||||
if not element or not element.valid then return end
|
||||
if state == nil then state = not element.visible end
|
||||
element.visible = state
|
||||
return state
|
||||
end
|
||||
|
||||
--[[-- Destory a gui element without causing any errors, often because the element was already removed
|
||||
@tparam LuaGuiElement element the element that you want to remove
|
||||
@treturn boolean true if the element was valid and has been removed
|
||||
|
||||
@usage-- Remove a child element if it exists
|
||||
Gui.destroy_if_valid(element[child_name])
|
||||
|
||||
]]
|
||||
function Gui.destroy_if_valid(element)
|
||||
if not element or not element.valid then return false end
|
||||
element.destroy()
|
||||
return true
|
||||
end
|
||||
|
||||
--[[-- Returns a table to be used as the style for a sprite buttons, produces a sqaure button
|
||||
@tparam number size the size that you want the button to be
|
||||
@tparam[opt=-2] number padding the padding that you want on the sprite
|
||||
@tparam[opt] table style any extra style settings that you want to have
|
||||
@treturn table the style table to be used with element_define:style()
|
||||
|
||||
@usage-- Adding a sprite button with size 20
|
||||
local button =
|
||||
Gui.element{
|
||||
type = 'sprite-button',
|
||||
sprite = 'entity/inserter'
|
||||
}
|
||||
:style(Gui.sprite_style(20))
|
||||
|
||||
]]
|
||||
function Gui.sprite_style(size, padding, style)
|
||||
style = style or {}
|
||||
style.padding = padding or -2
|
||||
style.height = size
|
||||
style.width = size
|
||||
return style
|
||||
end
|
||||
@@ -1,277 +0,0 @@
|
||||
--[[-- Core Module - Gui
|
||||
- Used to define new gui elements and gui event handlers
|
||||
@module Gui
|
||||
]]
|
||||
|
||||
local ExpUtil = require("modules/exp_util")
|
||||
local Gui = require("modules.exp_legacy.expcore.gui.prototype")
|
||||
local mod_gui = require "mod-gui"
|
||||
|
||||
local hide_left_flow = Gui.core_defines.hide_left_flow.name
|
||||
|
||||
--- Left Flow.
|
||||
-- @section leftFlow
|
||||
|
||||
-- Triggered when a user changed the visibility of a left flow element by clicking a button
|
||||
Gui.events.on_visibility_changed_by_click = "on_visibility_changed_by_click"
|
||||
|
||||
--- Contains the uids of the elements that will shown on the left flow and their join functions
|
||||
-- @table left_elements
|
||||
Gui.left_elements = {}
|
||||
|
||||
--[[-- Gets the flow refered to as the left flow, each player has one left flow
|
||||
@function Gui.get_left_flow(player)
|
||||
@tparam LuaPlayer player the player that you want to get the left flow for
|
||||
@treturn LuaGuiElement the left element flow
|
||||
|
||||
@usage-- Geting your left flow
|
||||
local left_flow = Gui.get_left_flow(game.player)
|
||||
|
||||
]]
|
||||
Gui.get_left_flow = mod_gui.get_frame_flow
|
||||
|
||||
--[[-- Sets an element define to be drawn to the left flow when a player joins, includes optional check
|
||||
@tparam[opt] ?boolean|function open_on_join called during first darw to decide if the element should be visible
|
||||
@treturn table the new element define that is used to register events to this element
|
||||
|
||||
@usage-- Adding the example button
|
||||
example_flow_with_button:add_to_left_flow(true)
|
||||
|
||||
]]
|
||||
function Gui._prototype_element:add_to_left_flow(open_on_join)
|
||||
ExpUtil.assert_not_runtime()
|
||||
if not self.name then error("Elements for the top flow must have a static name") end
|
||||
self.open_on_join = open_on_join or false
|
||||
table.insert(Gui.left_elements, self)
|
||||
return self
|
||||
end
|
||||
|
||||
--[[-- Creates a button on the top flow which will toggle the given element define, the define must exist in the left flow
|
||||
@tparam string sprite the sprite that you want to use on the button
|
||||
@tparam ?string|Concepts.LocalizedString tooltip the tooltip that you want the button to have
|
||||
@tparam table element_define the element define that you want to have toggled by this button, define must exist on the left flow
|
||||
@tparam[opt] function authenticator used to decide if the button should be visible to a player
|
||||
|
||||
@usage-- Add a button to toggle a left element
|
||||
local toolbar_button =
|
||||
Gui.left_toolbar_button('entity/inserter', 'Nothing to see here', example_flow_with_button, function(player)
|
||||
return player.admin
|
||||
end)
|
||||
|
||||
]]
|
||||
function Gui.left_toolbar_button(sprite, tooltip, element_define, authenticator)
|
||||
local button = Gui.toolbar_button(sprite, tooltip, authenticator)
|
||||
|
||||
-- Add on_click handler to handle click events comming from the player
|
||||
button:on_click(function(player, _, _)
|
||||
-- Raise custom event that tells listening elements if the element has changed visibility by a player clicking
|
||||
-- Used in warp gui to handle the keep open logic
|
||||
button:raise_event{
|
||||
name = Gui.events.on_visibility_changed_by_click,
|
||||
element = Gui.get_top_element(player, button),
|
||||
state = Gui.toggle_left_element(player, element_define),
|
||||
}
|
||||
end)
|
||||
|
||||
-- Add property to the left flow element with the name of the button
|
||||
-- This is for the ability to reverse lookup the button from the left flow element
|
||||
element_define.toolbar_button = button
|
||||
button.left_flow_element = element_define
|
||||
return button
|
||||
end
|
||||
|
||||
Gui._left_flow_order_src = "<default>"
|
||||
--- Get the order of elements in the left flow, first argument is player but is unused in the default method
|
||||
function Gui.get_left_flow_order(_)
|
||||
return Gui.left_elements
|
||||
end
|
||||
|
||||
--- Inject a custom left flow order provider, this should accept a player and return a list of elements definitions to draw
|
||||
function Gui.inject_left_flow_order(provider)
|
||||
Gui.get_left_flow_order = provider
|
||||
local debug_info = debug.getinfo(2, "Sn")
|
||||
local file_name = debug_info.short_src:sub(10, -5)
|
||||
local func_name = debug_info.name or ("<anonymous:" .. debug_info.linedefined .. ">")
|
||||
Gui._left_flow_order_src = file_name .. ":" .. func_name
|
||||
end
|
||||
|
||||
--[[-- Draw all the left elements onto the left flow, internal use only with on join
|
||||
@tparam LuaPlayer player the player that you want to draw the elements for
|
||||
|
||||
@usage-- Draw all the left elements
|
||||
Gui.draw_left_flow(player)
|
||||
|
||||
]]
|
||||
function Gui.draw_left_flow(player)
|
||||
local left_flow = Gui.get_left_flow(player)
|
||||
local hide_button = left_flow.gui_core_buttons[hide_left_flow]
|
||||
local show_hide_button = false
|
||||
|
||||
-- Get the order to draw the elements in
|
||||
local flow_order = Gui.get_left_flow_order(player)
|
||||
if #flow_order ~= #Gui.left_elements then
|
||||
error(string.format("Left flow order provider (%s) did not return the correct element count, expect %d got %d",
|
||||
Gui._left_flow_order_src, #Gui.left_elements, #flow_order
|
||||
))
|
||||
end
|
||||
|
||||
for _, element_define in ipairs(flow_order) do
|
||||
-- Draw the element to the left flow
|
||||
local draw_success, left_element = xpcall(function()
|
||||
return element_define(left_flow)
|
||||
end, debug.traceback)
|
||||
|
||||
if not draw_success then
|
||||
log("There as been an error with an element draw function: " .. element_define.defined_at .. "\n\t" .. left_element)
|
||||
goto continue
|
||||
end
|
||||
|
||||
-- Check if it should be open by default
|
||||
local open_on_join = element_define.open_on_join
|
||||
local visible = type(open_on_join) == "boolean" and open_on_join or false
|
||||
if type(open_on_join) == "function" then
|
||||
local success, err = xpcall(open_on_join, debug.traceback, player)
|
||||
if not success then
|
||||
log("There as been an error with an open on join hander for a gui element:\n\t" .. err)
|
||||
goto continue
|
||||
end
|
||||
visible = err
|
||||
end
|
||||
|
||||
-- Set the visible state of the element
|
||||
left_element.visible = visible
|
||||
show_hide_button = show_hide_button or visible
|
||||
|
||||
-- Check if the the element has a button attached
|
||||
if element_define.toolbar_button then
|
||||
Gui.toggle_toolbar_button(player, element_define.toolbar_button, visible)
|
||||
end
|
||||
::continue::
|
||||
end
|
||||
|
||||
hide_button.visible = show_hide_button
|
||||
end
|
||||
|
||||
--- Reorder the left flow elements to match that returned by the provider, uses a method equivalent to insert sort
|
||||
function Gui.reorder_left_flow(player)
|
||||
local left_flow = Gui.get_left_flow(player)
|
||||
|
||||
-- Get the order to draw the elements in
|
||||
local flow_order = Gui.get_left_flow_order(player)
|
||||
if #flow_order ~= #Gui.left_elements then
|
||||
error(string.format("Left flow order provider (%s) did not return the correct element count, expect %d got %d",
|
||||
Gui._left_flow_order_src, #Gui.left_elements, #flow_order
|
||||
))
|
||||
end
|
||||
|
||||
-- Reorder the elements, index 1 is the core ui buttons so +1 is required
|
||||
for index, element_define in ipairs(flow_order) do
|
||||
local element = left_flow[element_define.name]
|
||||
left_flow.swap_children(index + 1, element.get_index_in_parent())
|
||||
end
|
||||
end
|
||||
|
||||
--[[-- Update the visible state of the hide button, can be used to check if any frames are visible
|
||||
@tparam LuaPlayer player the player to update the left flow for
|
||||
@treturn boolean true if any left element is visible
|
||||
|
||||
@usage-- Check if any left elements are visible
|
||||
local visible = Gui.update_left_flow(player)
|
||||
|
||||
]]
|
||||
function Gui.update_left_flow(player)
|
||||
local left_flow = Gui.get_left_flow(player)
|
||||
local hide_button = left_flow.gui_core_buttons[hide_left_flow]
|
||||
for _, element_define in ipairs(Gui.left_elements) do
|
||||
local left_element = left_flow[element_define.name]
|
||||
if left_element.visible then
|
||||
hide_button.visible = true
|
||||
return true
|
||||
end
|
||||
end
|
||||
|
||||
hide_button.visible = false
|
||||
return false
|
||||
end
|
||||
|
||||
--[[-- Hides all left elements for a player
|
||||
@tparam LuaPlayer player the player to hide the elements for
|
||||
|
||||
@usage-- Hide your left elements
|
||||
Gui.hide_left_flow(game.player)
|
||||
|
||||
]]
|
||||
function Gui.hide_left_flow(player)
|
||||
local top_flow = Gui.get_top_flow(player)
|
||||
local left_flow = Gui.get_left_flow(player)
|
||||
local hide_button = left_flow.gui_core_buttons[hide_left_flow]
|
||||
|
||||
-- Set the visible state of all elements in the flow
|
||||
hide_button.visible = false
|
||||
for _, element_define in ipairs(Gui.left_elements) do
|
||||
left_flow[element_define.name].visible = false
|
||||
|
||||
-- Check if the the element has a toobar button attached
|
||||
if element_define.toolbar_button then
|
||||
-- Check if the topflow contains the button
|
||||
local button = top_flow[element_define.toolbar_button.name]
|
||||
if button then
|
||||
-- Style the button
|
||||
Gui.toggle_toolbar_button(player, element_define.toolbar_button, false)
|
||||
-- Raise the custom event if all of the top checks have passed
|
||||
element_define.toolbar_button:raise_event{
|
||||
name = Gui.events.on_visibility_changed_by_click,
|
||||
element = button,
|
||||
state = false,
|
||||
}
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
--- Checks if an element is loaded, used internally when the normal left gui assumptions may not hold
|
||||
function Gui.left_flow_loaded(player, element_define)
|
||||
local left_flow = Gui.get_left_flow(player)
|
||||
return left_flow[element_define.name] ~= nil
|
||||
end
|
||||
|
||||
--[[-- Get the element define that is in the left flow, use in events without an element refrence
|
||||
@tparam LuaPlayer player the player that you want to get the element for
|
||||
@tparam table element_define the element that you want to get
|
||||
@treturn LuaGuiElement the gui element linked to this define for this player
|
||||
|
||||
@usage-- Get your left element
|
||||
local frame = Gui.get_left_element(game.player, example_flow_with_button)
|
||||
|
||||
]]
|
||||
function Gui.get_left_element(player, element_define)
|
||||
local left_flow = Gui.get_left_flow(player)
|
||||
return assert(left_flow[element_define.name], "Left element failed to load")
|
||||
end
|
||||
|
||||
--[[-- Toggles the visible state of a left element for a given player, can be used to set the visible state
|
||||
@tparam LuaPlayer player the player that you want to toggle the element for
|
||||
@tparam table element_define the element that you want to toggle
|
||||
@tparam[opt] boolean state with given will set the state, else state will be toggled
|
||||
@treturn boolean the new visible state of the element
|
||||
|
||||
@usage-- Toggle your example button
|
||||
Gui.toggle_top_flow(game.player, example_flow_with_button)
|
||||
|
||||
@usage-- Show your example button
|
||||
Gui.toggle_top_flow(game.player, example_flow_with_button, true)
|
||||
|
||||
]]
|
||||
function Gui.toggle_left_element(player, element_define, state)
|
||||
-- Set the visible state
|
||||
local element = Gui.get_left_element(player, element_define)
|
||||
if state == nil then state = not element.visible end
|
||||
element.visible = state
|
||||
Gui.update_left_flow(player)
|
||||
|
||||
-- Check if the the element has a button attached
|
||||
if element_define.toolbar_button then
|
||||
Gui.toggle_toolbar_button(player, element_define.toolbar_button, state)
|
||||
end
|
||||
return state
|
||||
end
|
||||
@@ -1,415 +0,0 @@
|
||||
--[[-- Core Module - Gui
|
||||
- Used to simplify gui creation using factory functions called element defines
|
||||
@module Gui
|
||||
]]
|
||||
|
||||
local ExpUtil = require("modules/exp_util")
|
||||
local Event = require("modules/exp_legacy/utils/event") --- @dep utils.event
|
||||
|
||||
local Gui = {
|
||||
--- The current highest uid that is being used by a define, will not increase during runtime
|
||||
uid = 0,
|
||||
--- Used to automatically assign a unique static name to an element
|
||||
unique_static_name = {},
|
||||
--- String indexed table used to avoid conflict with custom event names, similar to how defines.events works
|
||||
events = {},
|
||||
--- Uid indexed array that stores all the factory functions that were defined, no new values will be added during runtime
|
||||
defines = {},
|
||||
--- An string indexed table of all the defines which are used by the core of the gui system, used for internal reference
|
||||
core_defines = {},
|
||||
--- Used to store the file names where elements were defined, this can be useful to find the uid of an element, mostly for debugging
|
||||
file_paths = {},
|
||||
--- Used to store extra information about elements as they get defined such as the params used and event handlers registered to them
|
||||
debug_info = {},
|
||||
--- The prototype used to store the functions of an element define
|
||||
_prototype_element = {},
|
||||
--- The prototype metatable applied to new element defines
|
||||
_mt_element = {},
|
||||
}
|
||||
|
||||
--- Allow access to the element prototype methods
|
||||
Gui._mt_element.__index = Gui._prototype_element
|
||||
|
||||
--- Allows the define to be called to draw the element
|
||||
function Gui._mt_element.__call(self, parent, ...)
|
||||
local element, no_events = self._draw(self, parent, ...)
|
||||
if self._style then self._style(element.style, element, ...) end
|
||||
|
||||
-- Asserts to catch common errors
|
||||
if element then
|
||||
if self.name and self.name ~= element.name then
|
||||
error("Static name \"" .. self.name .. "\" expected but got: " .. tostring(element.name))
|
||||
end
|
||||
local event_triggers = element.tags and element.tags.ExpGui_event_triggers
|
||||
if event_triggers and table.array_contains(event_triggers, self.uid) then
|
||||
error("Element::triggers_events should not be called on the value you return from the definition")
|
||||
end
|
||||
elseif self.name then
|
||||
error("Static name \"" .. self.name .. "\" expected but no element was returned from the definition")
|
||||
end
|
||||
|
||||
-- Register events by default, but allow skipping them
|
||||
if no_events == self.no_events then
|
||||
return element
|
||||
else
|
||||
return element and self:triggers_events(element)
|
||||
end
|
||||
end
|
||||
|
||||
--- Get where a function was defined as a string
|
||||
local function get_defined_at(level)
|
||||
local debug_info = debug.getinfo(level, "Sn")
|
||||
local file_name = debug_info.short_src:sub(10, -5)
|
||||
local func_name = debug_info.name or ("<anonymous:" .. debug_info.linedefined .. ">")
|
||||
return file_name .. ":" .. func_name
|
||||
end
|
||||
|
||||
--- Element Define.
|
||||
-- @section elementDefine
|
||||
|
||||
--[[-- Used to define new elements for your gui, can be used like LuaGuiElement.add or a custom function
|
||||
@tparam ?table|function element_define the define information for the gui element, same data as LuaGuiElement.add, or a custom function may be used
|
||||
@treturn table the new element define, this can be considered a factory for the element which can be called to draw the element to any other element
|
||||
|
||||
@usage-- Using element defines like LuaGuiElement.add
|
||||
-- This returns a factory function to draw a button with the caption "Example Button"
|
||||
local example_button =
|
||||
Gui.element{
|
||||
type = 'button',
|
||||
caption = 'Example Button'
|
||||
}
|
||||
|
||||
@usage-- Using element defines with a custom factory function
|
||||
-- This method can be used if you still want to be able register event handlers but it is too complex to be compatible with LuaGuiElement.add
|
||||
local example_flow_with_button =
|
||||
Gui.element(function(event_trigger, parent, ...)
|
||||
-- ... shows that all other arguments from the factory call are passed to this function
|
||||
-- parent is the element which was passed to the factory function where you should add your new element
|
||||
-- here we are adding a flow which we will then later add a button to
|
||||
local flow =
|
||||
parent.add{
|
||||
name = 'example_flow',
|
||||
type = 'flow'
|
||||
}
|
||||
|
||||
-- event_trigger should be the name of any elements you want to trigger your event handlers, such as on_click or on_state_changed
|
||||
-- now we add the button to the flow that we created earlier
|
||||
local element =
|
||||
flow.add{
|
||||
name = event_trigger,
|
||||
type = 'button',
|
||||
caption = 'Example Button'
|
||||
}
|
||||
|
||||
-- you must return your new element, this is so styles can be applied and returned to the caller
|
||||
-- you may return any of your elements that you add, consider the context in which it will be used for what should be returned
|
||||
return element
|
||||
end)
|
||||
|
||||
]]
|
||||
function Gui.element(element_define)
|
||||
ExpUtil.assert_not_runtime()
|
||||
-- Set the metatable to allow access to register events
|
||||
local element = setmetatable({}, Gui._mt_element)
|
||||
|
||||
-- Increment the uid counter
|
||||
local uid = Gui.uid + 1
|
||||
Gui.uid = uid
|
||||
element.uid = uid
|
||||
Gui.debug_info[uid] = { draw = "None", style = "None", events = {} }
|
||||
|
||||
-- Add the definition function
|
||||
if type(element_define) == "table" then
|
||||
Gui.debug_info[uid].draw = element_define
|
||||
if element_define.name == Gui.unique_static_name then
|
||||
element_define.name = "ExpGui_" .. tostring(uid)
|
||||
end
|
||||
for k, v in pairs(element_define) do
|
||||
if element[k] == nil then
|
||||
element[k] = v
|
||||
end
|
||||
end
|
||||
|
||||
element._draw = function(_, parent)
|
||||
return parent.add(element_define)
|
||||
end
|
||||
else
|
||||
Gui.debug_info[uid].draw = get_defined_at(element_define)
|
||||
element._draw = element_define
|
||||
end
|
||||
|
||||
-- Add the define to the base module
|
||||
element.defined_at = get_defined_at(3)
|
||||
Gui.file_paths[uid] = element.defined_at
|
||||
Gui.defines[uid] = element
|
||||
|
||||
-- Return the element so event handers can be accessed
|
||||
return element
|
||||
end
|
||||
|
||||
--[[-- Used to extent your element define with a style factory, this style will be applied to your element when created, can also be a custom function
|
||||
@tparam ?table|function style_define style table where each key and value pair is treated like LuaGuiElement.style[key] = value, a custom function can be used
|
||||
@treturn table the element define is returned to allow for event handlers to be registered
|
||||
|
||||
@usage-- Using the table method of setting the style
|
||||
local example_button =
|
||||
Gui.element{
|
||||
type = 'button',
|
||||
caption = 'Example Button',
|
||||
style = 'forward_button' -- factorio styles can be applied here
|
||||
}
|
||||
:style{
|
||||
height = 25, -- same as element.style.height = 25
|
||||
width = 100 -- same as element.style.width = 25
|
||||
}
|
||||
|
||||
@usage-- Using the function method to set the style
|
||||
-- Use this method if your style is dynamic and depends on other factors
|
||||
local example_button =
|
||||
Gui.element{
|
||||
type = 'button',
|
||||
caption = 'Example Button',
|
||||
style = 'forward_button' -- factorio styles can be applied here
|
||||
}
|
||||
:style(function(style, element, ...)
|
||||
-- style is the current style object for the elemenent
|
||||
-- element is the element that is being changed
|
||||
-- ... shows that all other arguments from the factory call are passed to this function
|
||||
local player = game.players[element.player_index]
|
||||
style.height = 25
|
||||
style.width = 100
|
||||
style.font_color = player.color
|
||||
end)
|
||||
|
||||
]]
|
||||
function Gui._prototype_element:style(style_define)
|
||||
ExpUtil.assert_not_runtime()
|
||||
-- Add the definition function
|
||||
if type(style_define) == "table" then
|
||||
Gui.debug_info[self.uid].style = style_define
|
||||
self._style = function(style)
|
||||
for key, value in pairs(style_define) do
|
||||
style[key] = value
|
||||
end
|
||||
end
|
||||
else
|
||||
Gui.debug_info[self.uid].style = get_defined_at(style_define)
|
||||
self._style = style_define
|
||||
end
|
||||
|
||||
-- Return the element so event handers can be accessed
|
||||
return self
|
||||
end
|
||||
|
||||
--[[-- Enforce the fact the element has a static name, this is required for the cases when a function define is used
|
||||
@tparam[opt] string element The element that will trigger calls to the event handlers
|
||||
@treturn table the element define is returned to allow for event handlers to be registered
|
||||
]]
|
||||
function Gui._prototype_element:static_name(name)
|
||||
ExpUtil.assert_not_runtime()
|
||||
if name == Gui.unique_static_name then
|
||||
self.name = "ExpGui_" .. tostring(self.uid)
|
||||
else
|
||||
self.name = name
|
||||
end
|
||||
return self
|
||||
end
|
||||
|
||||
--[[-- Used to link an element to an element define such that any event on the element will call the handlers on the element define
|
||||
-- You should not call this on the element you return from your constructor because this is done automatically
|
||||
@tparam LuaGuiElement element The element that will trigger calls to the event handlers
|
||||
@treturn LuaGuiElement The element passed as the argument to allow for cleaner returns
|
||||
]]
|
||||
function Gui._prototype_element:triggers_events(element)
|
||||
if not self._has_events then return element end
|
||||
local tags = element.tags
|
||||
if not tags then
|
||||
element.tags = { ExpGui_event_triggers = { self.uid } }
|
||||
return element
|
||||
elseif not tags.ExpGui_event_triggers then
|
||||
--- @diagnostic disable-next-line: name-style-check
|
||||
tags.ExpGui_event_triggers = { self.uid }
|
||||
elseif table.array_contains(tags.ExpGui_event_triggers, self.uid) then
|
||||
error("Element::triggers_events called multiple times on the same element with the same definition")
|
||||
else
|
||||
table.insert(tags.ExpGui_event_triggers, self.uid)
|
||||
end
|
||||
-- To modify a set of tags, the whole table needs to be written back to the respective property.
|
||||
element.tags = tags
|
||||
return element
|
||||
end
|
||||
|
||||
--- Explicitly skip events on the element returned by your definition function
|
||||
function Gui._prototype_element:no_events(element)
|
||||
return element, self.no_events
|
||||
end
|
||||
|
||||
--[[-- Set the handler which will be called for a custom event, only one handler can be used per event per element
|
||||
@tparam string event_name the name of the event you want to handler to be called on, often from Gui.events
|
||||
@tparam function handler the handler that you want to be called when the event is raised
|
||||
@treturn table the element define so more handleres can be registered
|
||||
|
||||
@usage-- Register a handler to "my_custom_event" for this element
|
||||
element_deinfe:on_event('my_custom_event', function(event)
|
||||
event.player.print(player.name)
|
||||
end)
|
||||
|
||||
]]
|
||||
function Gui._prototype_element:on_event(event_name, handler)
|
||||
ExpUtil.assert_not_runtime()
|
||||
table.insert(Gui.debug_info[self.uid].events, event_name)
|
||||
Gui.events[event_name] = event_name
|
||||
self[event_name] = handler
|
||||
self._has_events = true
|
||||
return self
|
||||
end
|
||||
|
||||
--[[-- Raise the handler which is attached to an event; external use should be limited to custom events
|
||||
@tparam table event the event table passed to the handler, must contain fields: name, element
|
||||
@treturn table the element define so more events can be raised
|
||||
|
||||
@usage Raising a custom event
|
||||
element_define:raise_event{
|
||||
name = 'my_custom_event',
|
||||
element = element
|
||||
}
|
||||
|
||||
]]
|
||||
function Gui._prototype_element:raise_event(event)
|
||||
-- Check the element is valid
|
||||
local element = event.element
|
||||
if not element or not element.valid then
|
||||
return self
|
||||
end
|
||||
|
||||
-- Get the event handler for this element
|
||||
local handler = self[event.name]
|
||||
if not handler then
|
||||
return self
|
||||
end
|
||||
|
||||
-- Get the player for this event
|
||||
local player_index = event.player_index or element.player_index
|
||||
local player = game.players[player_index]
|
||||
if not player or not player.valid then
|
||||
return self
|
||||
end
|
||||
event.player = player
|
||||
|
||||
local success, err = xpcall(handler, debug.traceback, player, element, event)
|
||||
if not success then
|
||||
error("There as been an error with an event handler for a gui element:\n\t" .. err)
|
||||
end
|
||||
return self
|
||||
end
|
||||
|
||||
-- This function is used to link element define events and the events from the factorio api
|
||||
local function event_handler_factory(event_name)
|
||||
Event.add(event_name, function(event)
|
||||
local element = event.element
|
||||
if not element or not element.valid then return end
|
||||
local event_triggers = element.tags.ExpGui_event_triggers
|
||||
if not event_triggers then return end
|
||||
for _, uid in pairs(event_triggers) do
|
||||
local element_define = Gui.defines[uid]
|
||||
if element_define then
|
||||
element_define:raise_event(event)
|
||||
end
|
||||
end
|
||||
end)
|
||||
|
||||
Gui.events[event_name] = event_name
|
||||
return function(self, handler)
|
||||
return self:on_event(event_name, handler)
|
||||
end
|
||||
end
|
||||
|
||||
--- Element Events.
|
||||
-- @section elementEvents
|
||||
|
||||
--- Called when the player opens a GUI.
|
||||
-- @tparam function handler the event handler which will be called
|
||||
-- @usage element_define:on_open(function(event)
|
||||
-- event.player.print(table.inspect(event))
|
||||
-- end)
|
||||
Gui._prototype_element.on_open = event_handler_factory(defines.events.on_gui_opened)
|
||||
|
||||
--- Called when the player closes the GUI they have open.
|
||||
-- @tparam function handler the event handler which will be called
|
||||
-- @usage element_define:on_close(function(event)
|
||||
-- event.player.print(table.inspect(event))
|
||||
-- end)
|
||||
Gui._prototype_element.on_close = event_handler_factory(defines.events.on_gui_closed)
|
||||
|
||||
--- Called when LuaGuiElement is clicked.
|
||||
-- @tparam function handler the event handler which will be called
|
||||
-- @usage element_define:on_click(function(event)
|
||||
-- event.player.print(table.inspect(event))
|
||||
-- end)
|
||||
Gui._prototype_element.on_click = event_handler_factory(defines.events.on_gui_click)
|
||||
|
||||
--- Called when a LuaGuiElement is confirmed, for example by pressing Enter in a textfield.
|
||||
-- @tparam function handler the event handler which will be called
|
||||
-- @usage element_define:on_confirmed(function(event)
|
||||
-- event.player.print(table.inspect(event))
|
||||
-- end)
|
||||
Gui._prototype_element.on_confirmed = event_handler_factory(defines.events.on_gui_confirmed)
|
||||
|
||||
--- Called when LuaGuiElement checked state is changed (related to checkboxes and radio buttons).
|
||||
-- @tparam function handler the event handler which will be called
|
||||
-- @usage element_define:on_checked_changed(function(event)
|
||||
-- event.player.print(table.inspect(event))
|
||||
-- end)
|
||||
Gui._prototype_element.on_checked_changed = event_handler_factory(defines.events.on_gui_checked_state_changed)
|
||||
|
||||
--- Called when LuaGuiElement element value is changed (related to choose element buttons).
|
||||
-- @tparam function handler the event handler which will be called
|
||||
-- @usage element_define:on_elem_changed(function(event)
|
||||
-- event.player.print(table.inspect(event))
|
||||
-- end)
|
||||
Gui._prototype_element.on_elem_changed = event_handler_factory(defines.events.on_gui_elem_changed)
|
||||
|
||||
--- Called when LuaGuiElement element location is changed (related to frames in player.gui.screen).
|
||||
-- @tparam function handler the event handler which will be called
|
||||
-- @usage element_define:on_location_changed(function(event)
|
||||
-- event.player.print(table.inspect(event))
|
||||
-- end)
|
||||
Gui._prototype_element.on_location_changed = event_handler_factory(defines.events.on_gui_location_changed)
|
||||
|
||||
--- Called when LuaGuiElement selected tab is changed (related to tabbed-panes).
|
||||
-- @tparam function handler the event handler which will be called
|
||||
-- @usage element_define:on_tab_changed(function(event)
|
||||
-- event.player.print(table.inspect(event))
|
||||
-- end)
|
||||
Gui._prototype_element.on_tab_changed = event_handler_factory(defines.events.on_gui_selected_tab_changed)
|
||||
|
||||
--- Called when LuaGuiElement selection state is changed (related to drop-downs and listboxes).
|
||||
-- @tparam function handler the event handler which will be called
|
||||
-- @usage element_define:on_selection_changed(function(event)
|
||||
-- event.player.print(table.inspect(event))
|
||||
-- end)
|
||||
Gui._prototype_element.on_selection_changed = event_handler_factory(defines.events.on_gui_selection_state_changed)
|
||||
|
||||
--- Called when LuaGuiElement switch state is changed (related to switches).
|
||||
-- @tparam function handler the event handler which will be called
|
||||
-- @usage element_define:on_switch_changed(function(event)
|
||||
-- event.player.print(table.inspect(event))
|
||||
-- end)
|
||||
Gui._prototype_element.on_switch_changed = event_handler_factory(defines.events.on_gui_switch_state_changed)
|
||||
|
||||
--- Called when LuaGuiElement text is changed by the player.
|
||||
-- @tparam function handler the event handler which will be called
|
||||
-- @usage element_define:on_text_changed(function(event)
|
||||
-- event.player.print(table.inspect(event))
|
||||
-- end)
|
||||
Gui._prototype_element.on_text_changed = event_handler_factory(defines.events.on_gui_text_changed)
|
||||
|
||||
--- Called when LuaGuiElement slider value is changed (related to the slider element).
|
||||
-- @tparam function handler the event handler which will be called
|
||||
-- @usage element_define:on_value_changed(function(event)
|
||||
-- event.player.print(table.inspect(event))
|
||||
-- end)
|
||||
Gui._prototype_element.on_value_changed = event_handler_factory(defines.events.on_gui_value_changed)
|
||||
|
||||
-- Module return
|
||||
return Gui
|
||||
@@ -1,316 +0,0 @@
|
||||
--[[-- Core Module - Gui
|
||||
- Controls the elements on the top flow
|
||||
@module Gui
|
||||
]]
|
||||
|
||||
local ExpUtil = require("modules/exp_util")
|
||||
local Gui = require("modules.exp_legacy.expcore.gui.prototype")
|
||||
local mod_gui = require "mod-gui" --- @dep mod-gui
|
||||
|
||||
local toolbar_button_size = 36
|
||||
local hide_top_flow = Gui.core_defines.hide_top_flow.name
|
||||
local show_top_flow = Gui.core_defines.show_top_flow.name
|
||||
|
||||
--- Top Flow.
|
||||
-- @section topFlow
|
||||
|
||||
-- Triggered when a user changed the visibility of a left flow element by clicking a button
|
||||
Gui.events.on_toolbar_button_toggled = "on_toolbar_button_toggled"
|
||||
|
||||
--- Contains the uids of the elements that will shown on the top flow and their auth functions
|
||||
-- @table top_elements
|
||||
Gui.top_elements = {}
|
||||
|
||||
--- The style that should be used for buttons on the top flow
|
||||
-- @field Gui.top_flow_button_style
|
||||
Gui.top_flow_button_style = mod_gui.button_style
|
||||
|
||||
--- The style that should be used for buttons on the top flow when their flow is visible
|
||||
-- @field Gui.top_flow_button_toggled_style
|
||||
Gui.top_flow_button_toggled_style = "menu_button_continue"
|
||||
|
||||
--[[-- Styles a top flow button depending on the state given
|
||||
@tparam LuaGuiElement button the button element to style
|
||||
@tparam boolean state The state the button is in
|
||||
|
||||
@usage-- Sets the button to the visible style
|
||||
Gui.toolbar_button_style(button, true)
|
||||
|
||||
@usage-- Sets the button to the hidden style
|
||||
Gui.toolbar_button_style(button, false)
|
||||
|
||||
]]
|
||||
function Gui.toolbar_button_style(button, state, size)
|
||||
--- @cast button LuaGuiElement
|
||||
if state then
|
||||
button.style = Gui.top_flow_button_toggled_style
|
||||
else
|
||||
button.style = Gui.top_flow_button_style
|
||||
end
|
||||
button.style.minimal_width = size or toolbar_button_size
|
||||
button.style.height = size or toolbar_button_size
|
||||
button.style.padding = -2
|
||||
end
|
||||
|
||||
--[[-- Gets the flow refered to as the top flow, each player has one top flow
|
||||
@function Gui.get_top_flow(player)
|
||||
@tparam LuaPlayer player the player that you want to get the flow for
|
||||
@treturn LuaGuiElement the top element flow
|
||||
|
||||
@usage-- Geting your top flow
|
||||
local top_flow = Gui.get_top_flow(game.player)
|
||||
|
||||
]]
|
||||
Gui.get_top_flow = mod_gui.get_button_flow
|
||||
|
||||
--[[-- Sets an element define to be drawn to the top flow when a player joins, includes optional authenticator
|
||||
@tparam[opt] function authenticator called during toggle or update to decide weather the element should be visible
|
||||
@treturn table the new element define to allow event handlers to be registered
|
||||
|
||||
@usage-- Adding an element to the top flow on join
|
||||
example_button:add_to_top_flow(function(player)
|
||||
-- example button will only be shown if the player is an admin
|
||||
-- note button will not update its state when player.admin is changed Gui.update_top_flow must be called for this
|
||||
return player.admin
|
||||
end)
|
||||
|
||||
]]
|
||||
function Gui._prototype_element:add_to_top_flow(authenticator)
|
||||
ExpUtil.assert_not_runtime()
|
||||
if not self.name then error("Elements for the top flow must have a static name") end
|
||||
self.authenticator = authenticator or true
|
||||
table.insert(Gui.top_elements, self)
|
||||
return self
|
||||
end
|
||||
|
||||
--- Returns true if the top flow has visible elements
|
||||
function Gui.top_flow_has_visible_elements(player)
|
||||
local top_flow = Gui.get_top_flow(player)
|
||||
|
||||
for _, child in pairs(top_flow.children) do
|
||||
if child.name ~= hide_top_flow then
|
||||
if child.visible then
|
||||
return true
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
return false
|
||||
end
|
||||
|
||||
Gui._top_flow_order_src = "<default>"
|
||||
--- Get the order of elements in the top flow, first argument is player but is unused in the default method
|
||||
function Gui.get_top_flow_order(_)
|
||||
return Gui.top_elements
|
||||
end
|
||||
|
||||
--- Inject a custom top flow order provider, this should accept a player and return a list of elements definitions to draw
|
||||
function Gui.inject_top_flow_order(provider)
|
||||
Gui.get_top_flow_order = provider
|
||||
local debug_info = debug.getinfo(2, "Sn")
|
||||
local file_name = debug_info.short_src:sub(10, -5)
|
||||
local func_name = debug_info.name or ("<anonymous:" .. debug_info.linedefined .. ">")
|
||||
Gui._top_flow_order_src = file_name .. ":" .. func_name
|
||||
end
|
||||
|
||||
--[[-- Updates the visible state of all the elements on the players top flow, uses authenticator
|
||||
@tparam LuaPlayer player the player that you want to update the top flow for
|
||||
|
||||
@usage-- Update your top flow
|
||||
Gui.update_top_flow(game.player)
|
||||
|
||||
]]
|
||||
function Gui.update_top_flow(player)
|
||||
local top_flow = Gui.get_top_flow(player)
|
||||
|
||||
-- Get the order to draw the elements in
|
||||
local flow_order = Gui.get_top_flow_order(player)
|
||||
if #flow_order ~= #Gui.top_elements then
|
||||
error(string.format("Top flow order provider (%s) did not return the correct element count, expect %d got %d",
|
||||
Gui._top_flow_order_src, #Gui.top_elements, #flow_order
|
||||
))
|
||||
end
|
||||
|
||||
-- Set the visible state of all elements in the flow
|
||||
for index, element_define in ipairs(flow_order) do
|
||||
-- Ensure the element exists
|
||||
local element = top_flow[element_define.name]
|
||||
if not element then
|
||||
element = element_define(top_flow)
|
||||
else
|
||||
top_flow.swap_children(index + 1, element.get_index_in_parent())
|
||||
end
|
||||
|
||||
-- Set the visible state
|
||||
local allowed = element_define.authenticator
|
||||
if type(allowed) == "function" then allowed = allowed(player) end
|
||||
element.visible = allowed or false
|
||||
|
||||
-- If its not visible and there is a left element, then hide it
|
||||
if element_define.left_flow_element and not element.visible and Gui.left_flow_loaded(player, element_define.left_flow_element) then
|
||||
Gui.toggle_left_element(player, element_define.left_flow_element, false)
|
||||
end
|
||||
end
|
||||
|
||||
-- Check if there are any visible elements in the top flow
|
||||
if not Gui.top_flow_has_visible_elements(player) then
|
||||
-- None are visible so hide the top_flow and its show button
|
||||
Gui.toggle_top_flow(player, false)
|
||||
local left_flow = Gui.get_left_flow(player)
|
||||
local show_button = left_flow.gui_core_buttons[show_top_flow]
|
||||
show_button.visible = false
|
||||
end
|
||||
end
|
||||
|
||||
--- Reorder the top flow elements to match that returned by the provider, uses a method equivalent to insert sort
|
||||
function Gui.reorder_top_flow(player)
|
||||
local top_flow = Gui.get_top_flow(player)
|
||||
|
||||
-- Get the order to draw the elements in
|
||||
local flow_order = Gui.get_top_flow_order(player)
|
||||
if #flow_order ~= #Gui.top_elements then
|
||||
error(string.format("Top flow order provider (%s) did not return the correct element count, expect %d got %d",
|
||||
Gui._top_flow_order_src, #Gui.top_elements, #flow_order
|
||||
))
|
||||
end
|
||||
|
||||
-- Reorder the elements, index 1 is the core ui buttons so +1 is required
|
||||
for index, element_define in ipairs(flow_order) do
|
||||
local element = top_flow[element_define.name]
|
||||
top_flow.swap_children(index + 1, element.get_index_in_parent())
|
||||
end
|
||||
end
|
||||
|
||||
--[[-- Toggles the visible state of all the elements on a players top flow, effects all elements
|
||||
@tparam LuaPlayer player the player that you want to toggle the top flow for
|
||||
@tparam[opt] boolean state if given then the state will be set to this
|
||||
@treturn boolean the new visible state of the top flow
|
||||
|
||||
@usage-- Toggle your flow
|
||||
Gui.toggle_top_flow(game.player)
|
||||
|
||||
@usage-- Open your top flow
|
||||
Gui.toggle_top_flow(game.player, true)
|
||||
|
||||
]]
|
||||
function Gui.toggle_top_flow(player, state)
|
||||
-- Get the top flow, we need the parent as we want to toggle the outer frame
|
||||
local top_flow = Gui.get_top_flow(player).parent --- @cast top_flow -nil
|
||||
if state == nil then state = not top_flow.visible end
|
||||
|
||||
-- Get the show button for the top flow
|
||||
local left_flow = Gui.get_left_flow(player)
|
||||
local show_button = left_flow.gui_core_buttons[show_top_flow]
|
||||
|
||||
-- Change the visibility of the top flow and show top flow button
|
||||
show_button.visible = not state
|
||||
top_flow.visible = state
|
||||
|
||||
return state
|
||||
end
|
||||
|
||||
--[[-- Get the element define that is in the top flow, use in events without an element refrence
|
||||
@tparam LuaPlayer player the player that you want to get the element for
|
||||
@tparam table element_define the element that you want to get
|
||||
@treturn LuaGuiElement the gui element linked to this define for this player
|
||||
|
||||
@usage-- Get your top element
|
||||
local button = Gui.get_top_element(game.player, example_button)
|
||||
|
||||
]]
|
||||
function Gui.get_top_element(player, element_define)
|
||||
local top_flow = Gui.get_top_flow(player)
|
||||
return assert(top_flow[element_define.name], "Top element failed to load")
|
||||
end
|
||||
|
||||
--[[-- Toggles the state of a toolbar button for a given player, can be used to set the visual state
|
||||
@tparam LuaPlayer player the player that you want to toggle the element for
|
||||
@tparam table element_define the element that you want to toggle
|
||||
@tparam[opt] boolean state with given will set the state, else state will be toggled
|
||||
@treturn boolean the new visible state of the element
|
||||
|
||||
@usage-- Toggle your example button
|
||||
Gui.toggle_toolbar_button(game.player, toolbar_button)
|
||||
|
||||
@usage-- Show your example button
|
||||
Gui.toggle_toolbar_button(game.player, toolbar_button, true)
|
||||
|
||||
]]
|
||||
function Gui.toggle_toolbar_button(player, element_define, state)
|
||||
local toolbar_button = Gui.get_top_element(player, element_define)
|
||||
if state == nil then state = toolbar_button.style.name ~= Gui.top_flow_button_toggled_style end
|
||||
Gui.toolbar_button_style(toolbar_button, state, toolbar_button.style.minimal_width)
|
||||
element_define:raise_event{
|
||||
name = Gui.events.on_toolbar_button_toggled,
|
||||
element = toolbar_button,
|
||||
player = player,
|
||||
state = state,
|
||||
}
|
||||
return state
|
||||
end
|
||||
|
||||
--[[-- Creates a button on the top flow with consistent styling
|
||||
@tparam string sprite the sprite that you want to use on the button
|
||||
@tparam ?string|Concepts.LocalizedString tooltip the tooltip that you want the button to have
|
||||
@tparam[opt] function authenticator used to decide if the button should be visible to a player
|
||||
|
||||
@usage-- Add a button to the toolbar
|
||||
local toolbar_button =
|
||||
Gui.left_toolbar_button('entity/inserter', 'Nothing to see here', function(player)
|
||||
return player.admin
|
||||
end)
|
||||
|
||||
]]
|
||||
function Gui.toolbar_button(sprite, tooltip, authenticator)
|
||||
return Gui.element{
|
||||
type = "sprite-button",
|
||||
sprite = sprite,
|
||||
tooltip = tooltip,
|
||||
style = Gui.top_flow_button_style,
|
||||
name = Gui.unique_static_name,
|
||||
}
|
||||
:style{
|
||||
minimal_width = toolbar_button_size,
|
||||
height = toolbar_button_size,
|
||||
padding = -2,
|
||||
}
|
||||
:add_to_top_flow(authenticator)
|
||||
end
|
||||
|
||||
--[[-- Creates a toggle button on the top flow with consistent styling
|
||||
@tparam string sprite the sprite that you want to use on the button
|
||||
@tparam ?string|Concepts.LocalizedString tooltip the tooltip that you want the button to have
|
||||
@tparam[opt] function authenticator used to decide if the button should be visible to a player
|
||||
|
||||
@usage-- Add a button to the toolbar
|
||||
local toolbar_button =
|
||||
Gui.toolbar_toggle_button('entity/inserter', 'Nothing to see here', function(player)
|
||||
return player.admin
|
||||
end)
|
||||
:on_event(Gui.events.on_toolbar_button_toggled, function(player, element, event)
|
||||
game.print(table.inspect(event))
|
||||
end)
|
||||
|
||||
]]
|
||||
function Gui.toolbar_toggle_button(sprite, tooltip, authenticator)
|
||||
local button =
|
||||
Gui.element{
|
||||
type = "sprite-button",
|
||||
sprite = sprite,
|
||||
tooltip = tooltip,
|
||||
style = Gui.top_flow_button_style,
|
||||
name = Gui.unique_static_name,
|
||||
}
|
||||
:style{
|
||||
minimal_width = toolbar_button_size,
|
||||
height = toolbar_button_size,
|
||||
padding = -2,
|
||||
}
|
||||
:add_to_top_flow(authenticator)
|
||||
|
||||
button:on_click(function(player, _, _)
|
||||
Gui.toggle_toolbar_button(player, button)
|
||||
end)
|
||||
|
||||
return button
|
||||
end
|
||||
@@ -6,12 +6,6 @@ game-message-unassign=__1__ has been unassigned from __2__ by __3__
|
||||
reject-role=Invalid Role Name.
|
||||
reject-player-role=Player has a higher role.
|
||||
|
||||
[gui_util]
|
||||
button_tooltip=Shows/hides the toolbar.
|
||||
|
||||
[expcore-gui]
|
||||
left-button-tooltip=Hide all open windows.
|
||||
|
||||
[expcore-data]
|
||||
description-preference=Allows you to set/get your data saving preference.
|
||||
description-data=Writes all your player data to a file on your computer.
|
||||
|
||||
@@ -316,14 +316,6 @@ type-player=Player
|
||||
type-static=Static
|
||||
type-player-loop=Player loop
|
||||
|
||||
[toolbar]
|
||||
main-caption=Toolbox
|
||||
main-tooltip=Toolbox Settings\nUse the checkboxs to select facourites
|
||||
reset=Reset All
|
||||
toggle=Toggle Favourites
|
||||
move-up=Move Up
|
||||
move-down=Move Down
|
||||
|
||||
[research]
|
||||
msg=[color=255, 255, 255] Research completed at __1__ - [technology=__2__][/color]
|
||||
inf=[color=255, 255, 255] Research completed at __1__ - [technology=__2__] - __3__[/color]
|
||||
|
||||
@@ -6,12 +6,6 @@ game-message-unassign=__1__ 已被 __3__ 取消指派到身分組 __2__
|
||||
reject-role=無效的身分組。
|
||||
reject-player-role=用戶已有更高的身分組。
|
||||
|
||||
[gui_util]
|
||||
button_tooltip=是否顯示工具欄。
|
||||
|
||||
[expcore-gui]
|
||||
left-button-tooltip=關閉所有打開的視窗。
|
||||
|
||||
[expcore-data]
|
||||
description-preference=允許寫入資料。
|
||||
description-data=把用戶資料寫入電腦
|
||||
|
||||
@@ -6,12 +6,6 @@ game-message-unassign=__1__ 已被 __3__ 取消指派到身分組 __2__
|
||||
reject-role=無效的身分組。
|
||||
reject-player-role=用戶已有更高的身分組。
|
||||
|
||||
[gui_util]
|
||||
button_tooltip=是否顯示工具欄。
|
||||
|
||||
[expcore-gui]
|
||||
left-button-tooltip=關閉所有打開的視窗。
|
||||
|
||||
[expcore-data]
|
||||
description-preference=允許寫入資料。
|
||||
description-data=把用戶資料寫入電腦
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
],
|
||||
"dependencies": {
|
||||
"clusterio": "*",
|
||||
"exp_util": "*"
|
||||
"exp_util": "*",
|
||||
"exp_gui": "*"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
--- Makes trees which are marked for decon "decay" quickly to allow faster building
|
||||
-- @addon Tree-Decon
|
||||
|
||||
local Event = require("modules/exp_legacy/utils/event") --- @dep utils.event
|
||||
local Storage = require("modules/exp_util/storage")
|
||||
local Gui = require("modules/exp_gui")
|
||||
|
||||
local Event = require("modules/exp_legacy/utils/event") --- @dep utils.event
|
||||
local Roles = require("modules.exp_legacy.expcore.roles") --- @dep expcore.roles
|
||||
local Gui = require("modules.exp_legacy.expcore.gui") --- @dep expcore.gui
|
||||
local PlayerData = require("modules.exp_legacy.expcore.player_data") --- @dep expcore.player_data
|
||||
|
||||
-- Storage queue used to store trees that need to be removed, also cache for player roles
|
||||
@@ -34,13 +35,20 @@ end
|
||||
local HasEnabledDecon = PlayerData.Settings:combine("HasEnabledDecon")
|
||||
HasEnabledDecon:set_default(false)
|
||||
|
||||
Gui.toolbar_toggle_button("entity/tree-01", { "tree-decon.main-tooltip" }, function(player)
|
||||
return Roles.player_allowed(player, "fast-tree-decon")
|
||||
Gui.toolbar.create_button{
|
||||
name = "toggle-tree-decon",
|
||||
sprite = "entity/tree-01",
|
||||
tooltip = { "tree-decon.main-tooltip" },
|
||||
auto_toggle = true,
|
||||
visible = function(player, _)
|
||||
return Roles.player_allowed(player, "fast-tree-decon")
|
||||
end
|
||||
}:on_click(function(def, event, element)
|
||||
local player = Gui.get_player(event)
|
||||
local state = Gui.toolbar.get_button_toggled_state(def, player)
|
||||
HasEnabledDecon:set(player, state)
|
||||
player.print{ "tree-decon.toggle-msg", state and { "tree-decon.enabled" } or { "tree-decon.disabled" } }
|
||||
end)
|
||||
:on_event(Gui.events.on_toolbar_button_toggled, function(player, _, event)
|
||||
HasEnabledDecon:set(player, event.state)
|
||||
player.print{ "tree-decon.toggle-msg", event.state and { "tree-decon.enabled" } or { "tree-decon.disabled" } }
|
||||
end)
|
||||
|
||||
-- Add trees to queue when marked, only allows simple entities and for players with role permission
|
||||
Event.add(defines.events.on_marked_for_deconstruction, function(event)
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
local Event = require("modules/exp_legacy/utils/event") --- @dep utils.event
|
||||
local Storage = require("modules/exp_util/storage")
|
||||
local Gui = require("modules.exp_legacy.expcore.gui") --- @dep expcore.gui
|
||||
local Gui = require("modules/exp_gui")
|
||||
|
||||
local Event = require("modules/exp_legacy/utils/event") --- @dep utils.event
|
||||
|
||||
----- Locals -----
|
||||
local follow_label -- Gui constructor
|
||||
@@ -88,7 +89,7 @@ function Public.stop_follow(player)
|
||||
Public.stop_spectate(player)
|
||||
end
|
||||
|
||||
Gui.destroy_if_valid(player.gui.screen[follow_label.name])
|
||||
Gui.destroy_if_valid(player.gui.screen.follow_label)
|
||||
following[player.index] = nil
|
||||
end
|
||||
|
||||
@@ -102,19 +103,18 @@ end
|
||||
----- Gui -----
|
||||
|
||||
--- Label used to show that the player is following, also used to allow esc to stop following
|
||||
-- @element follow_label
|
||||
follow_label =
|
||||
Gui.element(function(definition, parent, target)
|
||||
Gui.destroy_if_valid(parent[definition.name])
|
||||
follow_label = Gui.element("follow-label")
|
||||
:draw(function(def, parent, target)
|
||||
Gui.destroy_if_valid(parent.follow_label)
|
||||
|
||||
local label = parent.add{
|
||||
type = "label",
|
||||
name = "follow_label",
|
||||
style = "frame_title",
|
||||
caption = "Following " .. target.name .. ".\nClick here or press esc to stop following.",
|
||||
name = definition.name,
|
||||
}
|
||||
|
||||
local player = Gui.get_player_from_element(parent)
|
||||
local player = Gui.get_player(parent)
|
||||
local res = player.display_resolution
|
||||
label.location = { 0, res.height - 150 }
|
||||
label.style.width = res.width
|
||||
@@ -123,9 +123,10 @@ follow_label =
|
||||
|
||||
return label
|
||||
end)
|
||||
:static_name(Gui.unique_static_name)
|
||||
:on_click(Public.stop_follow)
|
||||
:on_close(function(player)
|
||||
:on_click(function(def, player, element)
|
||||
Public.stop_follow(player)
|
||||
end)
|
||||
:on_closed(function(def, player, element)
|
||||
-- Don't call set_controller during on_close as it invalidates the controller
|
||||
-- Setting an invalid position (as to not equal their current) will call stop_follow on the next tick
|
||||
following[player.index][3] = {}
|
||||
|
||||
31
exp_legacy/module/modules/data/toolbar.lua
Normal file
31
exp_legacy/module/modules/data/toolbar.lua
Normal file
@@ -0,0 +1,31 @@
|
||||
local Gui = require("modules/exp_gui")
|
||||
local PlayerData = require("modules.exp_legacy.expcore.player_data")
|
||||
|
||||
-- Used to store the state of the toolbar when a player leaves
|
||||
local ToolbarState = PlayerData.Settings:combine("ToolbarState")
|
||||
ToolbarState:set_metadata{
|
||||
stringify = function()
|
||||
return "Toolbar is saved on exit"
|
||||
end,
|
||||
}
|
||||
|
||||
--- Uncompress the data to be more useable
|
||||
ToolbarState:on_load(function(player_name, value)
|
||||
-- If there is no value, do nothing
|
||||
if value == nil then return end
|
||||
-- Old format, we discard it [ string[], string[], string[], boolean ]
|
||||
if type(value) ~= "string" then return end
|
||||
|
||||
local decompressed = helpers.json_to_table(assert(helpers.decode_string(value), "Failed String Decode"))
|
||||
local player = assert(game.get_player(player_name))
|
||||
Gui.toolbar.set_state(player, decompressed --[[ @as ExpGui.ToolbarState ]])
|
||||
|
||||
return nil -- We don't save the state, use Gui.toolbar.get_state
|
||||
end)
|
||||
|
||||
--- Save the current state of the players toolbar menu
|
||||
ToolbarState:on_save(function(player_name, _)
|
||||
local player = assert(game.get_player(player_name))
|
||||
local value = Gui.toolbar.get_state(player)
|
||||
return helpers.encode_string(helpers.table_to_json(value))
|
||||
end)
|
||||
7
exp_legacy/module/modules/gui/_role_updates.lua
Normal file
7
exp_legacy/module/modules/gui/_role_updates.lua
Normal file
@@ -0,0 +1,7 @@
|
||||
local Gui = require("modules/exp_gui")
|
||||
local Roles = require("modules.exp_legacy.expcore.roles")
|
||||
local Event = require("modules/exp_legacy/utils/event")
|
||||
|
||||
--- @diagnostic disable invisible
|
||||
Event.add(Roles.events.on_role_assigned, Gui._ensure_consistency)
|
||||
Event.add(Roles.events.on_role_unassigned, Gui._ensure_consistency)
|
||||
@@ -4,10 +4,10 @@
|
||||
@alias autofill
|
||||
]]
|
||||
|
||||
local Storage = require("modules/exp_util/storage")
|
||||
local FlyingText = require("modules/exp_util/flying_text")
|
||||
local Gui = require("modules.exp_legacy.expcore.gui") -- @dep expcore.gui
|
||||
local Roles = require("modules.exp_legacy.expcore.roles") -- @dep expcore.gui
|
||||
local Storage = require("modules/exp_util/storage") -- @dep utils.global
|
||||
local Gui = require("modules/exp_gui")
|
||||
local Roles = require("modules.exp_legacy.expcore.roles")
|
||||
local config = require("modules.exp_legacy.config.gui.autofill") -- @dep config.gui.autofill
|
||||
local Event = require("modules/exp_legacy/utils/event") -- @dep utils.event
|
||||
|
||||
@@ -25,17 +25,19 @@ end
|
||||
|
||||
--- Toggle entity section visibility
|
||||
-- @element toggle_item_button
|
||||
local toggle_section =
|
||||
Gui.element{
|
||||
local toggle_section = Gui.element("autofill_toggle_section")
|
||||
:draw{
|
||||
type = "sprite-button",
|
||||
sprite = "utility/expand",
|
||||
tooltip = { "autofill.toggle-section-tooltip" },
|
||||
style = "frame_action_button",
|
||||
name = Gui.unique_static_name,
|
||||
name = Gui.property_from_name,
|
||||
}
|
||||
:style(Gui.sprite_style(20))
|
||||
:on_click(function(_, element, _)
|
||||
local header_flow = element.parent
|
||||
:style(Gui.styles.sprite{
|
||||
size = 20
|
||||
})
|
||||
:on_click(function(def, player, element)
|
||||
local header_flow = assert(element.parent)
|
||||
local flow_name = header_flow.caption
|
||||
local flow = header_flow.parent.parent[flow_name]
|
||||
if Gui.toggle_visible_state(flow) then
|
||||
@@ -50,8 +52,8 @@ local toggle_section =
|
||||
--- Toggle enitity button, used for toggling autofill for the specific entity
|
||||
-- All entity autofill settings will be ignored if its disabled
|
||||
-- @element entity_toggle
|
||||
local entity_toggle =
|
||||
Gui.element(function(_, parent, entity_name)
|
||||
local entity_toggle = Gui.element("entity_toggle")
|
||||
:draw(function(_, parent, entity_name)
|
||||
return parent.add{
|
||||
type = "sprite-button",
|
||||
sprite = "utility/confirm_slot",
|
||||
@@ -59,8 +61,10 @@ local entity_toggle =
|
||||
style = "shortcut_bar_button_green",
|
||||
}
|
||||
end)
|
||||
:style(Gui.sprite_style(22))
|
||||
:on_click(function(player, element, _)
|
||||
:style(Gui.styles.sprite{
|
||||
size = 22
|
||||
})
|
||||
:on_click(function(def, player, element)
|
||||
local entity_name = string.match(element.parent.parent.name, "(.*)%-header")
|
||||
if not autofill_player_settings[player.name] then return end
|
||||
local setting = autofill_player_settings[player.name][entity_name]
|
||||
@@ -75,7 +79,7 @@ local entity_toggle =
|
||||
element.style = "shortcut_bar_button_green"
|
||||
end
|
||||
-- Correct the button size
|
||||
local style = element.style --[[@as LuaStyle]]
|
||||
local style = element.style
|
||||
style.padding = -2
|
||||
style.height = 22
|
||||
style.width = 22
|
||||
@@ -83,18 +87,17 @@ local entity_toggle =
|
||||
|
||||
--- Draw a section header and main scroll
|
||||
-- @element autofill_section_container
|
||||
local section =
|
||||
Gui.element(function(definition, parent, section_name, table_size)
|
||||
local section = Gui.element("autofill_section")
|
||||
:draw(function(def, parent, section_name, table_size)
|
||||
-- Draw the header for the section
|
||||
local header = Gui.header(
|
||||
parent,
|
||||
{ "autofill.toggle-section-caption", rich_img("item", section_name), { "entity-name." .. section_name } },
|
||||
{ "autofill.toggle-section-tooltip" },
|
||||
true,
|
||||
section_name .. "-header"
|
||||
)
|
||||
local header = Gui.elements.header(parent, {
|
||||
name = section_name .. "-header",
|
||||
caption = { "autofill.toggle-section-caption", rich_img("item", section_name), { "entity-name." .. section_name } },
|
||||
tooltip = { "autofill.toggle-section-tooltip" },
|
||||
label_name = "label",
|
||||
})
|
||||
|
||||
definition:triggers_events(header.parent.header_label)
|
||||
def:link_element(header.parent.label)
|
||||
|
||||
-- Right aligned button to toggle the section
|
||||
header.caption = section_name
|
||||
@@ -109,17 +112,17 @@ local section =
|
||||
|
||||
section_table.visible = false
|
||||
|
||||
return definition:no_events(section_table)
|
||||
return def:unlink_element(section_table)
|
||||
end)
|
||||
:on_click(function(_, element, event)
|
||||
:on_click(function(def, player, element, event)
|
||||
event.element = element.parent.alignment[toggle_section.name]
|
||||
toggle_section:raise_event(event)
|
||||
end)
|
||||
|
||||
--- Toggle item button, used for toggling autofill for the specific item
|
||||
-- @element toggle_item_button
|
||||
local toggle_item_button =
|
||||
Gui.element(function(_, parent, item)
|
||||
local toggle_item_button = Gui.element("toggle_item_button")
|
||||
:draw(function(_, parent, item)
|
||||
return parent.add{
|
||||
type = "sprite-button",
|
||||
sprite = "item/" .. item.name,
|
||||
@@ -127,8 +130,11 @@ local toggle_item_button =
|
||||
style = "shortcut_bar_button_red",
|
||||
}
|
||||
end)
|
||||
:style(Gui.sprite_style(32, nil, { right_margin = -3 }))
|
||||
:on_click(function(player, element)
|
||||
:style(Gui.styles.sprite{
|
||||
size = 32,
|
||||
right_margin = -3,
|
||||
})
|
||||
:on_click(function(def, player, element)
|
||||
local item_name = element.parent.tooltip
|
||||
local entity_name = element.parent.parent.parent.name
|
||||
if not autofill_player_settings[player.name] then return end
|
||||
@@ -144,7 +150,7 @@ local toggle_item_button =
|
||||
element.style = "shortcut_bar_button_green"
|
||||
end
|
||||
-- Correct the button size
|
||||
local style = element.style --[[@as LuaStyle]]
|
||||
local style = element.style
|
||||
style.right_margin = -3
|
||||
style.padding = -2
|
||||
style.height = 32
|
||||
@@ -153,8 +159,8 @@ local toggle_item_button =
|
||||
|
||||
--- Amount text field for a autofill item
|
||||
-- @element amount_textfield
|
||||
local amount_textfield =
|
||||
Gui.element(function(_, parent, item)
|
||||
local amount_textfield = Gui.element("amount_textfield")
|
||||
:draw(function(_, parent, item)
|
||||
return parent.add{
|
||||
type = "textfield",
|
||||
text = item.amount,
|
||||
@@ -170,7 +176,7 @@ local amount_textfield =
|
||||
height = 31,
|
||||
padding = -2,
|
||||
}
|
||||
:on_text_changed(function(player, element, _)
|
||||
:on_text_changed(function(def, player, element)
|
||||
local value = tonumber(element.text)
|
||||
if not value then value = 0 end
|
||||
local clamped = math.clamp(value, 0, 1000)
|
||||
@@ -183,7 +189,7 @@ local amount_textfield =
|
||||
if not item then return end
|
||||
item.amount = clamped
|
||||
if clamped ~= value then
|
||||
element.text = clamped
|
||||
element.text = tostring(clamped)
|
||||
player.print{ "autofill.invalid", item.amount, rich_img("item", item.name), rich_img("entity", entity_name) }
|
||||
return
|
||||
end
|
||||
@@ -191,8 +197,8 @@ local amount_textfield =
|
||||
|
||||
--- Autofill setting, contains a button and a textbox
|
||||
-- @element add_autofill_setting
|
||||
local add_autofill_setting =
|
||||
Gui.element(function(_, parent, item)
|
||||
local add_autofill_setting = Gui.element("add_autofill_setting")
|
||||
:draw(function(_, parent, item)
|
||||
local toggle_flow = parent.add{ type = "flow", name = "toggle-setting-" .. item.name, tooltip = item.name }
|
||||
local amount_flow = parent.add{ type = "flow", name = "amount-setting-" .. item.name, tooltip = item.name }
|
||||
toggle_flow.style.padding = 0
|
||||
@@ -203,8 +209,8 @@ local add_autofill_setting =
|
||||
|
||||
--- Autofill setting empty, contains filler button and textfield gui elements
|
||||
-- @element add_empty_autofill_setting
|
||||
local add_empty_autofill_setting =
|
||||
Gui.element(function(_, parent)
|
||||
local add_empty_autofill_setting = Gui.element("add_empty_autofill_setting")
|
||||
:draw(function(_, parent)
|
||||
local toggle_element = parent.add{
|
||||
type = "sprite-button",
|
||||
}
|
||||
@@ -223,19 +229,19 @@ local add_empty_autofill_setting =
|
||||
|
||||
--- Main gui container for the left flow
|
||||
-- @element autofill_container
|
||||
autofill_container =
|
||||
Gui.element(function(definition, parent)
|
||||
autofill_container = Gui.element("autofill_container")
|
||||
:draw(function(def, parent)
|
||||
-- Draw the internal container
|
||||
local container = Gui.container(parent, definition.name)
|
||||
local container = Gui.elements.container(parent)
|
||||
-- Draw the scroll container
|
||||
local scroll_table = Gui.scroll_table(container, 400, 1, "autofill-scroll-table")
|
||||
local scroll_table = Gui.elements.scroll_table(container, 400, 1, "autofill-scroll-table")
|
||||
-- Set the scroll panel to always show the scrollbar (not doing this will result in a changing gui size)
|
||||
scroll_table.parent.vertical_scroll_policy = "always"
|
||||
-- Scroll panel has by default padding
|
||||
scroll_table.parent.style.padding = 0
|
||||
-- Remove the default gap that is added in a table between elements
|
||||
scroll_table.style.vertical_spacing = 0
|
||||
-- Center the first collumn in the table
|
||||
-- Center the first column in the table
|
||||
scroll_table.style.column_alignments[1] = "center"
|
||||
-- Loop over each default entity config
|
||||
for _, setting in pairs(config.default_entities) do
|
||||
@@ -245,7 +251,7 @@ autofill_container =
|
||||
local entity_table = section(scroll_table, setting.entity, 3)
|
||||
-- Add some padding around the table
|
||||
entity_table.style.padding = 3
|
||||
-- Make sure each collumn is alignment top center
|
||||
-- Make sure each column is alignment top center
|
||||
entity_table.style.column_alignments[1] = "top-center"
|
||||
entity_table.style.column_alignments[2] = "top-center"
|
||||
entity_table.style.column_alignments[3] = "top-center"
|
||||
@@ -284,14 +290,18 @@ autofill_container =
|
||||
-- Return the external container
|
||||
return container.parent
|
||||
end)
|
||||
:static_name(Gui.unique_static_name)
|
||||
:add_to_left_flow()
|
||||
|
||||
--- Button on the top flow used to toggle autofill container
|
||||
-- @element autofill_toggle
|
||||
Gui.left_toolbar_button(config.icon, { "autofill.main-tooltip" }, autofill_container, function(player)
|
||||
return Roles.player_allowed(player, "gui/autofill")
|
||||
end)
|
||||
--- Add the element to the left flow with a toolbar button
|
||||
Gui.add_left_element(autofill_container, false)
|
||||
Gui.toolbar.create_button{
|
||||
name = "autofill_toggle",
|
||||
left_element = autofill_container,
|
||||
sprite = config.icon,
|
||||
tooltip = { "autofill.main-tooltip" },
|
||||
visible = function(player, element)
|
||||
return Roles.player_allowed(player, "gui/autofill")
|
||||
end
|
||||
}
|
||||
|
||||
--- When a player is created make sure they have the default autofill settings
|
||||
Event.add(defines.events.on_player_created, function(event)
|
||||
@@ -321,6 +331,7 @@ local function entity_build(event)
|
||||
-- Get the inventory of the player
|
||||
local player_inventory = player.get_main_inventory() --- @cast player_inventory -nil
|
||||
|
||||
local offset = { x = 0, y = 0 }
|
||||
-- Loop over all possible items to insert into the entity
|
||||
for _, item in pairs(entity_settings.items) do
|
||||
-- Check if the item is enabled or goto next item
|
||||
@@ -330,28 +341,30 @@ local function entity_build(event)
|
||||
local entity_inventory = entity.get_inventory(item.inv)
|
||||
if not entity_inventory then goto end_item end
|
||||
|
||||
local preferd_amount = item.amount
|
||||
local preferred_amount = item.amount
|
||||
local item_amount = player_inventory.get_item_count(item.name)
|
||||
if item_amount ~= 0 then
|
||||
local inserted
|
||||
local color = { r = 0, g = 255, b = 0, a = 1 }
|
||||
if item_amount >= preferd_amount then
|
||||
local color = { r = 0, g = 255, b = 0, a = 255 }
|
||||
if item_amount >= preferred_amount then
|
||||
-- Can item be inserted? no, goto next item!
|
||||
if not entity_inventory.can_insert{ name = item.name, count = preferd_amount } then
|
||||
if not entity_inventory.can_insert{ name = item.name, count = preferred_amount } then
|
||||
goto end_item
|
||||
end
|
||||
inserted = entity_inventory.insert{ name = item.name, count = preferd_amount }
|
||||
inserted = entity_inventory.insert{ name = item.name, count = preferred_amount }
|
||||
else
|
||||
inserted = entity_inventory.insert{ name = item.name, count = item_amount }
|
||||
color = { r = 255, g = 165, b = 0, a = 1 }
|
||||
color = { r = 255, g = 165, b = 0, a = 255 }
|
||||
end
|
||||
player_inventory.remove{ name = item.name, count = inserted }
|
||||
FlyingText.create_above_entity{
|
||||
target_entity = entity,
|
||||
text = { "autofill.inserted", inserted, rich_img("item", item.name), rich_img("entity", entity.name) },
|
||||
offset = offset,
|
||||
player = player,
|
||||
color = color,
|
||||
}
|
||||
offset.y = offset.y - 0.33
|
||||
end
|
||||
::end_item::
|
||||
end
|
||||
|
||||
@@ -3,9 +3,9 @@
|
||||
@alias bonus_container
|
||||
]]
|
||||
|
||||
local Gui = require("modules.exp_legacy.expcore.gui") --- @dep expcore.gui
|
||||
local Roles = require("modules.exp_legacy.expcore.roles") --- @dep expcore.roles
|
||||
local Gui = require("modules/exp_gui")
|
||||
local Event = require("modules/exp_legacy/utils/event") --- @dep utils.event
|
||||
local Roles = require("modules.exp_legacy.expcore.roles") --- @dep expcore.roles
|
||||
local config = require("modules.exp_legacy.config.bonus") --- @dep config.bonus
|
||||
local vlayer = require("modules.exp_legacy.modules.control.vlayer")
|
||||
local format_number = require("util").format_number --- @dep util
|
||||
@@ -13,9 +13,12 @@ local format_number = require("util").format_number --- @dep util
|
||||
local bonus_container
|
||||
local bonus_gui_control_pts_a_count
|
||||
|
||||
local function bonus_gui_pts_needed(player)
|
||||
local frame = Gui.get_left_element(player, bonus_container)
|
||||
local disp = frame.container["bonus_st_2"].disp.table
|
||||
--- @param player LuaPlayer
|
||||
--- @param container LuaGuiElement?
|
||||
--- @return number
|
||||
local function bonus_gui_pts_needed(player, container)
|
||||
container = container or Gui.get_left_element(bonus_container, player)
|
||||
local disp = container.frame["bonus_st_2"].disp.table
|
||||
local total = 0
|
||||
|
||||
for k, v in pairs(config.conversion) do
|
||||
@@ -31,6 +34,7 @@ local function bonus_gui_pts_needed(player)
|
||||
return total
|
||||
end
|
||||
|
||||
--- @param player LuaPlayer
|
||||
local function apply_bonus(player)
|
||||
if not Roles.player_allowed(player, "gui/bonus") then
|
||||
for k, v in pairs(config.player_bonus) do
|
||||
@@ -50,8 +54,8 @@ local function apply_bonus(player)
|
||||
return
|
||||
end
|
||||
|
||||
local frame = Gui.get_left_element(player, bonus_container)
|
||||
local disp = frame.container["bonus_st_2"].disp.table
|
||||
local container = Gui.get_left_element(bonus_container, player)
|
||||
local disp = container.frame["bonus_st_2"].disp.table
|
||||
|
||||
for k, v in pairs(config.conversion) do
|
||||
player[v] = disp["bonus_display_" .. k .. "_slider"].slider_value
|
||||
@@ -81,8 +85,8 @@ local function apply_periodic_bonus(player)
|
||||
return
|
||||
end
|
||||
|
||||
local frame = Gui.get_left_element(player, bonus_container)
|
||||
local disp = frame.container["bonus_st_2"].disp.table
|
||||
local container = Gui.get_left_element(bonus_container, player)
|
||||
local disp = container.frame["bonus_st_2"].disp.table
|
||||
|
||||
if vlayer.get_statistics()["energy_sustained"] > 0 then
|
||||
local armor = player.get_inventory(defines.inventory.character_armor)
|
||||
@@ -109,20 +113,20 @@ end
|
||||
|
||||
--- Control label for the bonus points available
|
||||
-- @element bonus_gui_control_pts_a
|
||||
local bonus_gui_control_pts_a =
|
||||
Gui.element{
|
||||
local bonus_gui_control_pts_a = Gui.element("bonus_gui_control_pts_a")
|
||||
:draw{
|
||||
type = "label",
|
||||
name = "bonus_control_pts_a",
|
||||
name = Gui.property_from_name,
|
||||
caption = { "bonus.control-pts-a" },
|
||||
style = "heading_2_label",
|
||||
}:style{
|
||||
width = config.gui_display_width["half"],
|
||||
}
|
||||
|
||||
bonus_gui_control_pts_a_count =
|
||||
Gui.element{
|
||||
local bonus_gui_control_pts_a_count = Gui.element("bonus_gui_control_pts_a_count")
|
||||
:draw{
|
||||
type = "label",
|
||||
name = "bonus_control_pts_a_count",
|
||||
name = Gui.property_from_name,
|
||||
caption = config.pts.base,
|
||||
style = "heading_2_label",
|
||||
}:style{
|
||||
@@ -131,20 +135,20 @@ bonus_gui_control_pts_a_count =
|
||||
|
||||
--- Control label for the bonus points needed
|
||||
-- @element bonus_gui_control_pts_n
|
||||
local bonus_gui_control_pts_n =
|
||||
Gui.element{
|
||||
local bonus_gui_control_pts_n = Gui.element("bonus_gui_control_pts_n")
|
||||
:draw{
|
||||
type = "label",
|
||||
name = "bonus_control_pts_n",
|
||||
name = Gui.property_from_name,
|
||||
caption = { "bonus.control-pts-n" },
|
||||
style = "heading_2_label",
|
||||
}:style{
|
||||
width = config.gui_display_width["half"],
|
||||
}
|
||||
|
||||
local bonus_gui_control_pts_n_count =
|
||||
Gui.element{
|
||||
local bonus_gui_control_pts_n_count = Gui.element("bonus_gui_control_pts_n_count")
|
||||
:draw{
|
||||
type = "label",
|
||||
name = "bonus_control_pts_n_count",
|
||||
name = Gui.property_from_name,
|
||||
caption = "0",
|
||||
style = "heading_2_label",
|
||||
}:style{
|
||||
@@ -153,20 +157,20 @@ local bonus_gui_control_pts_n_count =
|
||||
|
||||
--- Control label for the bonus points remaining
|
||||
-- @element bonus_gui_control_pts_r
|
||||
local bonus_gui_control_pts_r =
|
||||
Gui.element{
|
||||
local bonus_gui_control_pts_r = Gui.element("bonus_gui_control_pts_r")
|
||||
:draw{
|
||||
type = "label",
|
||||
name = "bonus_control_pts_r",
|
||||
name = Gui.property_from_name,
|
||||
caption = { "bonus.control-pts-r" },
|
||||
style = "heading_2_label",
|
||||
}:style{
|
||||
width = config.gui_display_width["half"],
|
||||
}
|
||||
|
||||
local bonus_gui_control_pts_r_count =
|
||||
Gui.element{
|
||||
local bonus_gui_control_pts_r_count = Gui.element("bonus_gui_control_pts_r_count")
|
||||
:draw{
|
||||
type = "label",
|
||||
name = "bonus_control_pts_r_count",
|
||||
name = Gui.property_from_name,
|
||||
caption = "0",
|
||||
style = "heading_2_label",
|
||||
}:style{
|
||||
@@ -175,16 +179,16 @@ local bonus_gui_control_pts_r_count =
|
||||
|
||||
--- A button used for pts calculations
|
||||
-- @element bonus_gui_control_refresh
|
||||
local bonus_gui_control_reset =
|
||||
Gui.element{
|
||||
local bonus_gui_control_reset = Gui.element("bonus_gui_control_reset")
|
||||
:draw{
|
||||
type = "button",
|
||||
name = Gui.unique_static_name,
|
||||
name = Gui.property_from_name,
|
||||
caption = { "bonus.control-reset" },
|
||||
}:style{
|
||||
width = config.gui_display_width["half"],
|
||||
}:on_click(function(player, element, _)
|
||||
local frame = Gui.get_left_element(player, bonus_container)
|
||||
local disp = frame.container["bonus_st_2"].disp.table
|
||||
}:on_click(function(def, player, element)
|
||||
local container = Gui.get_left_element(bonus_container, player)
|
||||
local disp = container.frame["bonus_st_2"].disp.table
|
||||
|
||||
for k, v in pairs(config.conversion) do
|
||||
local s = "bonus_display_" .. k .. "_slider"
|
||||
@@ -208,14 +212,14 @@ local bonus_gui_control_reset =
|
||||
|
||||
--- A button used for pts apply
|
||||
-- @element bonus_gui_control_apply
|
||||
local bonus_gui_control_apply =
|
||||
Gui.element{
|
||||
local bonus_gui_control_apply = Gui.element("bonus_gui_control_apply")
|
||||
:draw{
|
||||
type = "button",
|
||||
name = Gui.unique_static_name,
|
||||
name = Gui.property_from_name,
|
||||
caption = { "bonus.control-apply" },
|
||||
}:style{
|
||||
width = config.gui_display_width["half"],
|
||||
}:on_click(function(player, element, _)
|
||||
}:on_click(function(def, player, element)
|
||||
local n = bonus_gui_pts_needed(player)
|
||||
element.parent[bonus_gui_control_pts_n_count.name].caption = n
|
||||
local r = tonumber(element.parent[bonus_gui_control_pts_a_count.name].caption) - n
|
||||
@@ -228,10 +232,10 @@ local bonus_gui_control_apply =
|
||||
|
||||
--- A vertical flow containing all the bonus control
|
||||
-- @element bonus_control_set
|
||||
local bonus_control_set =
|
||||
Gui.element(function(_, parent, name)
|
||||
local bonus_control_set = Gui.element("bonus_control_set")
|
||||
:draw(function(_, parent, name)
|
||||
local bonus_set = parent.add{ type = "flow", direction = "vertical", name = name }
|
||||
local disp = Gui.scroll_table(bonus_set, config.gui_display_width["half"] * 2, 2, "disp")
|
||||
local disp = Gui.elements.scroll_table(bonus_set, config.gui_display_width["half"] * 2, 2, "disp")
|
||||
|
||||
bonus_gui_control_pts_a(disp)
|
||||
bonus_gui_control_pts_a_count(disp)
|
||||
@@ -250,8 +254,8 @@ local bonus_control_set =
|
||||
|
||||
--- Display group
|
||||
-- @element bonus_gui_slider
|
||||
local bonus_gui_slider =
|
||||
Gui.element(function(_definition, parent, name, caption, tooltip, bonus)
|
||||
local bonus_gui_slider = Gui.element("bonus_gui_slider")
|
||||
:draw(function(def, parent, name, caption, tooltip, bonus)
|
||||
local label = parent.add{
|
||||
type = "label",
|
||||
caption = caption,
|
||||
@@ -294,7 +298,7 @@ local bonus_gui_slider =
|
||||
|
||||
return slider
|
||||
end)
|
||||
:on_value_changed(function(player, element, _event)
|
||||
:on_value_changed(function(def, player, element)
|
||||
if element.tags.is_percentage then
|
||||
element.parent[element.tags.counter].caption = format_number(element.slider_value * 100, false) .. " %"
|
||||
else
|
||||
@@ -302,18 +306,18 @@ local bonus_gui_slider =
|
||||
end
|
||||
|
||||
local r = bonus_gui_pts_needed(player)
|
||||
local frame = Gui.get_left_element(player, bonus_container)
|
||||
local disp = frame.container["bonus_st_1"].disp.table
|
||||
local container = Gui.get_left_element(bonus_container, player)
|
||||
local disp = container.frame["bonus_st_1"].disp.table
|
||||
disp[bonus_gui_control_pts_n_count.name].caption = r
|
||||
disp[bonus_gui_control_pts_r_count.name].caption = tonumber(disp[bonus_gui_control_pts_a_count.name].caption) - r
|
||||
end)
|
||||
|
||||
--- A vertical flow containing all the bonus data
|
||||
-- @element bonus_data_set
|
||||
local bonus_data_set =
|
||||
Gui.element(function(_, parent, name)
|
||||
local bonus_data_set = Gui.element("bonus_data_set")
|
||||
:draw(function(_, parent, name)
|
||||
local bonus_set = parent.add{ type = "flow", direction = "vertical", name = name }
|
||||
local disp = Gui.scroll_table(bonus_set, config.gui_display_width["half"] * 2, 3, "disp")
|
||||
local disp = Gui.elements.scroll_table(bonus_set, config.gui_display_width["half"] * 2, 3, "disp")
|
||||
|
||||
for k, v in pairs(config.conversion) do
|
||||
bonus_gui_slider(disp, "bonus_display_" .. k, { "bonus.display-" .. k }, { "bonus.display-" .. k .. "-tooltip" }, config.player_bonus[v])
|
||||
@@ -327,32 +331,34 @@ local bonus_data_set =
|
||||
|
||||
--- The main container for the bonus gui
|
||||
-- @element bonus_container
|
||||
bonus_container =
|
||||
Gui.element(function(definition, parent)
|
||||
local player = Gui.get_player_from_element(parent)
|
||||
local container = Gui.container(parent, definition.name, config.gui_display_width["half"] * 2)
|
||||
bonus_container = Gui.element("bonus_container")
|
||||
:draw(function(def, parent)
|
||||
local player = Gui.get_player(parent)
|
||||
local container = Gui.elements.container(parent, config.gui_display_width["half"] * 2)
|
||||
|
||||
bonus_control_set(container, "bonus_st_1")
|
||||
bonus_data_set(container, "bonus_st_2")
|
||||
|
||||
local frame = Gui.get_left_element(player, bonus_container)
|
||||
local disp = frame.container["bonus_st_1"].disp.table
|
||||
local n = bonus_gui_pts_needed(player)
|
||||
local disp = container["bonus_st_1"].disp.table
|
||||
local n = bonus_gui_pts_needed(player, container.parent)
|
||||
disp[bonus_gui_control_pts_n_count.name].caption = n
|
||||
local r = tonumber(disp[bonus_gui_control_pts_a_count.name].caption) - n
|
||||
disp[bonus_gui_control_pts_r_count.name].caption = r
|
||||
|
||||
apply_bonus(player)
|
||||
return container.parent
|
||||
end)
|
||||
:static_name(Gui.unique_static_name)
|
||||
:add_to_left_flow()
|
||||
|
||||
--- Button on the top flow used to toggle the bonus container
|
||||
-- @element toggle_left_element
|
||||
Gui.left_toolbar_button("item/exoskeleton-equipment", { "bonus.main-tooltip" }, bonus_container, function(player)
|
||||
return Roles.player_allowed(player, "gui/bonus")
|
||||
end)
|
||||
--- Add the element to the left flow with a toolbar button
|
||||
Gui.add_left_element(bonus_container, false)
|
||||
Gui.toolbar.create_button{
|
||||
name = "bonus_toggle",
|
||||
left_element = bonus_container,
|
||||
sprite = "item/exoskeleton-equipment",
|
||||
tooltip = { "bonus.main-tooltip" },
|
||||
visible = function(player, element)
|
||||
return Roles.player_allowed(player, "gui/bonus")
|
||||
end
|
||||
}
|
||||
|
||||
Event.add(defines.events.on_player_created, function(event)
|
||||
if event.player_index ~= 1 then
|
||||
@@ -379,8 +385,8 @@ end)
|
||||
--- When a player respawns re-apply bonus
|
||||
Event.add(defines.events.on_player_respawned, function(event)
|
||||
local player = game.players[event.player_index]
|
||||
local frame = Gui.get_left_element(player, bonus_container)
|
||||
local disp = frame.container["bonus_st_1"].disp.table
|
||||
local container = Gui.get_left_element(bonus_container, player)
|
||||
local disp = container.frame["bonus_st_1"].disp.table
|
||||
local n = bonus_gui_pts_needed(player)
|
||||
disp[bonus_gui_control_pts_n_count.name].caption = n
|
||||
local r = tonumber(disp[bonus_gui_control_pts_a_count.name].caption) - n
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
local Event = require("modules/exp_legacy/utils/event")
|
||||
local Storage = require("modules/exp_util/storage")
|
||||
local Gui = require("modules.exp_legacy.utils.gui")
|
||||
local Model = require("modules.exp_legacy.modules.gui.debug.model")
|
||||
|
||||
@@ -21,6 +22,11 @@ local checkbox_name = Gui.uid_name()
|
||||
local filter_name = Gui.uid_name()
|
||||
local clear_filter_name = Gui.uid_name()
|
||||
|
||||
local storage = {}
|
||||
Storage.register(storage, function(tbl)
|
||||
storage = tbl
|
||||
end)
|
||||
|
||||
-- storage tables
|
||||
local enabled = {}
|
||||
local last_events = {}
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
local Gui = require("modules.exp_legacy.utils.gui") --- @dep utils.gui
|
||||
local ExpGui = require("modules.exp_legacy.expcore.gui")
|
||||
local ExpElement = require("modules/exp_gui/prototype")
|
||||
local ExpData = require("modules/exp_gui/data")
|
||||
local ExpIter = require("modules/exp_gui/iter")
|
||||
local Color = require("modules/exp_util/include/color")
|
||||
|
||||
local Gui = require("modules.exp_legacy.utils.gui") --- @dep utils.gui
|
||||
local Model = require("modules.exp_legacy.modules.gui.debug.model") --- @dep modules.gui.debug.model
|
||||
|
||||
local dump = Model.dump
|
||||
@@ -24,9 +27,10 @@ function Public.show(container)
|
||||
local left_panel_style = left_panel.style
|
||||
left_panel_style.width = 300
|
||||
|
||||
for element_id, file_path in pairs(ExpGui.file_paths) do
|
||||
local header = left_panel.add{ type = "flow" }.add{ type = "label", name = header_name, caption = element_id .. " - " .. file_path }
|
||||
Gui.set_data(header, element_id)
|
||||
--- @diagnostic disable-next-line invisible
|
||||
for element_name in pairs(ExpElement._elements) do
|
||||
local header = left_panel.add{ type = "flow" }.add{ type = "label", name = header_name, caption = element_name }
|
||||
Gui.set_data(header, element_name)
|
||||
end
|
||||
|
||||
local right_flow = main_flow.add{ type = "flow", direction = "vertical" }
|
||||
@@ -70,7 +74,7 @@ Gui.on_click(
|
||||
header_name,
|
||||
function(event)
|
||||
local element = event.element
|
||||
local element_id = Gui.get_data(element)
|
||||
local element_name = Gui.get_data(element)
|
||||
|
||||
local left_panel = element.parent.parent
|
||||
local data = Gui.get_data(left_panel)
|
||||
@@ -85,10 +89,23 @@ Gui.on_click(
|
||||
element.style.font_color = Color.orange
|
||||
data.selected_header = element
|
||||
|
||||
input_text_box.text = concat{ "Gui.defines[", element_id, "]" }
|
||||
input_text_box.text = concat{ "ExpElement._elements[\"", element_name, "\"]" }
|
||||
input_text_box.style.font_color = Color.black
|
||||
|
||||
local content = dump(ExpGui.debug_info[element_id]) or "nil"
|
||||
--- @diagnostic disable-next-line invisible
|
||||
local define = ExpElement._elements[element_name]
|
||||
local content = dump({
|
||||
--- @diagnostic disable-next-line invisible
|
||||
debug = define._debug,
|
||||
--- @diagnostic disable-next-line invisible
|
||||
has_handlers = define._has_handlers,
|
||||
--- @diagnostic disable-next-line invisible
|
||||
track_elements = define._track_elements,
|
||||
--- @diagnostic disable-next-line invisible
|
||||
elements = ExpIter._scopes[element_name],
|
||||
--- @diagnostic disable-next-line invisible
|
||||
data = ExpData._scopes[element_name]._raw,
|
||||
}) or "nil"
|
||||
right_panel.text = content
|
||||
end
|
||||
)
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
local Gui = require("modules.exp_legacy.utils.gui") --- @dep utils.gui
|
||||
local ExpUtil = require("modules/exp_util")
|
||||
|
||||
local gui_names = Gui.names
|
||||
local type = type
|
||||
local concat = table.concat
|
||||
local inspect = table.inspect
|
||||
local pcall = pcall
|
||||
@@ -10,76 +9,7 @@ local rawset = rawset
|
||||
|
||||
local Public = {}
|
||||
|
||||
local LuaObject = { "{", nil, ", name = '", nil, "'}" }
|
||||
local LuaPlayer = { "{LuaPlayer, name = '", nil, "', index = ", nil, "}" }
|
||||
local LuaEntity = { "{LuaEntity, name = '", nil, "', unit_number = ", nil, "}" }
|
||||
local LuaGuiElement = { "{LuaGuiElement, name = '", nil, "'}" }
|
||||
|
||||
local function get(obj, prop)
|
||||
return obj[prop]
|
||||
end
|
||||
|
||||
local function get_name_safe(obj)
|
||||
local s, r = pcall(get, obj, "name")
|
||||
if not s then
|
||||
return "nil"
|
||||
else
|
||||
return r or "nil"
|
||||
end
|
||||
end
|
||||
|
||||
local function get_lua_object_type_safe(obj)
|
||||
local s, r = pcall(get, obj, "help")
|
||||
|
||||
if not s then
|
||||
return
|
||||
end
|
||||
|
||||
return r():match("Lua%a+")
|
||||
end
|
||||
|
||||
local function inspect_process(item)
|
||||
if type(item) ~= "table" or type(item.__self) ~= "userdata" then
|
||||
return item
|
||||
end
|
||||
|
||||
local suc, valid = pcall(get, item, "valid")
|
||||
if not suc then
|
||||
-- no 'valid' property
|
||||
return get_lua_object_type_safe(item) or "{NoHelp LuaObject}"
|
||||
end
|
||||
|
||||
if not valid then
|
||||
return "{Invalid LuaObject}"
|
||||
end
|
||||
|
||||
local obj_type = get_lua_object_type_safe(item)
|
||||
if not obj_type then
|
||||
return "{NoHelp LuaObject}"
|
||||
end
|
||||
|
||||
if obj_type == "LuaPlayer" then
|
||||
LuaPlayer[2] = item.name or "nil"
|
||||
LuaPlayer[4] = item.index or "nil"
|
||||
|
||||
return concat(LuaPlayer)
|
||||
elseif obj_type == "LuaEntity" then
|
||||
LuaEntity[2] = item.name or "nil"
|
||||
LuaEntity[4] = item.unit_number or "nil"
|
||||
|
||||
return concat(LuaEntity)
|
||||
elseif obj_type == "LuaGuiElement" then
|
||||
local name = item.name
|
||||
LuaGuiElement[2] = gui_names and gui_names[name] or name or "nil"
|
||||
|
||||
return concat(LuaGuiElement)
|
||||
else
|
||||
LuaObject[2] = obj_type
|
||||
LuaObject[4] = get_name_safe(item)
|
||||
|
||||
return concat(LuaObject)
|
||||
end
|
||||
end
|
||||
local inspect_process = ExpUtil.safe_value
|
||||
|
||||
local inspect_options = { process = inspect_process }
|
||||
function Public.dump(data)
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
@alias landfill_container
|
||||
]]
|
||||
|
||||
local Gui = require("modules.exp_legacy.expcore.gui") --- @dep expcore.gui
|
||||
local Gui = require("modules/exp_gui")
|
||||
local Event = require("modules/exp_legacy/utils/event") --- @dep utils.event
|
||||
local Roles = require("modules.exp_legacy.expcore.roles") --- @dep expcore.roles
|
||||
|
||||
@@ -93,8 +93,10 @@ for i, map in ipairs(curves) do
|
||||
end
|
||||
end
|
||||
|
||||
--- @param blueprint LuaItemStack
|
||||
--- @return table
|
||||
local function landfill_gui_add_landfill(blueprint)
|
||||
local entities = blueprint.get_blueprint_entities()
|
||||
local entities = assert(blueprint.get_blueprint_entities())
|
||||
local tile_index = 0
|
||||
local new_tiles = {}
|
||||
|
||||
@@ -164,22 +166,26 @@ local function landfill_gui_add_landfill(blueprint)
|
||||
return { tiles = new_tiles }
|
||||
end
|
||||
|
||||
-- @element toolbar_button
|
||||
Gui.toolbar_button("item/landfill", { "landfill.main-tooltip" }, function(player)
|
||||
return Roles.player_allowed(player, "gui/landfill")
|
||||
end)
|
||||
:on_click(function(player, _, _)
|
||||
if player.cursor_stack and player.cursor_stack.valid_for_read then
|
||||
if player.cursor_stack.type == "blueprint" and player.cursor_stack.is_blueprint_setup() then
|
||||
local modified = landfill_gui_add_landfill(player.cursor_stack)
|
||||
--- Add the toolbar button
|
||||
Gui.toolbar.create_button{
|
||||
name = "landfill",
|
||||
sprite = "item/landfill",
|
||||
tooltip = { "landfill.main-tooltip" },
|
||||
visible = function(player, element)
|
||||
return Roles.player_allowed(player, "gui/landfill")
|
||||
end
|
||||
}:on_click(function(def, player, element)
|
||||
if player.cursor_stack and player.cursor_stack.valid_for_read then
|
||||
if player.cursor_stack.type == "blueprint" and player.cursor_stack.is_blueprint_setup() then
|
||||
local modified = landfill_gui_add_landfill(player.cursor_stack)
|
||||
|
||||
if modified and next(modified.tiles) then
|
||||
player.cursor_stack.set_blueprint_tiles(modified.tiles)
|
||||
end
|
||||
if modified and next(modified.tiles) then
|
||||
player.cursor_stack.set_blueprint_tiles(modified.tiles)
|
||||
end
|
||||
else
|
||||
player.print{ "landfill.cursor-none" }
|
||||
end
|
||||
end)
|
||||
else
|
||||
player.print{ "landfill.cursor-none" }
|
||||
end
|
||||
end)
|
||||
|
||||
Event.add(defines.events.on_player_joined_game, landfill_init)
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
---- module inserter
|
||||
-- @gui Module
|
||||
|
||||
local Gui = require("modules/exp_gui")
|
||||
local AABB = require("modules/exp_util/aabb")
|
||||
local Gui = require("modules.exp_legacy.expcore.gui") --- @dep expcore.gui
|
||||
local Event = require("modules/exp_legacy/utils/event") --- @dep utils.event
|
||||
local Roles = require("modules.exp_legacy.expcore.roles") --- @dep expcore.roles
|
||||
local config = require("modules.exp_legacy.config.module") --- @dep config.module
|
||||
@@ -93,8 +93,8 @@ end
|
||||
Selection.on_selection(SelectionModuleArea, function(event)
|
||||
local area = AABB.expand(event.area)
|
||||
local player = game.players[event.player_index]
|
||||
local frame = Gui.get_left_element(player, module_container) --- @type LuaGuiElement
|
||||
local scroll_table = frame.container.scroll.table
|
||||
local container = Gui.get_left_element(module_container, player)
|
||||
local scroll_table = container.frame.scroll.table
|
||||
|
||||
-- Create an inventory with three upgrade planners
|
||||
local inventory = game.create_inventory(3)
|
||||
@@ -205,8 +205,8 @@ end)
|
||||
--- @param player LuaPlayer
|
||||
--- @param element_name string
|
||||
local function row_set(player, element_name)
|
||||
local frame = Gui.get_left_element(player, module_container) --[[ @as LuaGuiElement ]]
|
||||
local scroll_table = frame.container.scroll.table
|
||||
local container = Gui.get_left_element(module_container, player)
|
||||
local scroll_table = container.frame.scroll.table
|
||||
local machine_name = scroll_table[element_name .. "0"].elem_value --[[ @as string ]]
|
||||
|
||||
if machine_name then
|
||||
@@ -247,12 +247,12 @@ local function row_set(player, element_name)
|
||||
end
|
||||
end
|
||||
|
||||
local button_apply =
|
||||
Gui.element{
|
||||
local button_apply = Gui.element("button_apply")
|
||||
:draw{
|
||||
type = "button",
|
||||
caption = { "module.apply" },
|
||||
style = "button",
|
||||
}:on_click(function(player)
|
||||
}:on_click(function(def, player, element)
|
||||
if Selection.is_selecting(player, SelectionModuleArea) then
|
||||
Selection.stop(player)
|
||||
else
|
||||
@@ -260,13 +260,15 @@ local button_apply =
|
||||
end
|
||||
end)
|
||||
|
||||
module_container =
|
||||
Gui.element(function(definition, parent)
|
||||
local container = Gui.container(parent, definition.name, (config.module_slots_per_row + 2) * 36)
|
||||
Gui.header(container, "Module Inserter", "", true)
|
||||
module_container = Gui.element("module_container")
|
||||
:draw(function(definition, parent)
|
||||
local container = Gui.elements.container(parent, (config.module_slots_per_row + 2) * 36)
|
||||
Gui.elements.header(container, {
|
||||
caption = "Module Inserter",
|
||||
})
|
||||
|
||||
local slots_per_row = config.module_slots_per_row + 1
|
||||
local scroll_table = Gui.scroll_table(container, (config.module_slots_per_row + 2) * 36, slots_per_row)
|
||||
local scroll_table = Gui.elements.scroll_table(container, (config.module_slots_per_row + 2) * 36, slots_per_row, "scroll")
|
||||
|
||||
for i = 1, config.default_module_row_count do
|
||||
scroll_table.add{
|
||||
@@ -301,12 +303,18 @@ module_container =
|
||||
|
||||
return container.parent
|
||||
end)
|
||||
:static_name(Gui.unique_static_name)
|
||||
:add_to_left_flow()
|
||||
|
||||
Gui.left_toolbar_button("item/productivity-module-3", { "module.main-tooltip" }, module_container, function(player)
|
||||
return Roles.player_allowed(player, "gui/module")
|
||||
end)
|
||||
--- Add the element to the left flow with a toolbar button
|
||||
Gui.add_left_element(module_container, false)
|
||||
Gui.toolbar.create_button{
|
||||
name = "module_toggle",
|
||||
left_element = module_container,
|
||||
sprite = "item/productivity-module-3",
|
||||
tooltip = { "module.main-tooltip" },
|
||||
visible = function(player, element)
|
||||
return Roles.player_allowed(player, "gui/module")
|
||||
end
|
||||
}
|
||||
|
||||
--- @param event EventData.on_gui_elem_changed
|
||||
Event.add(defines.events.on_gui_elem_changed, function(event)
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
|
||||
-- luacheck:ignore 211/Colors
|
||||
local ExpUtil = require("modules/exp_util")
|
||||
local Gui = require("modules.exp_legacy.expcore.gui") --- @dep expcore.gui
|
||||
local Gui = require("modules/exp_gui")
|
||||
local Roles = require("modules.exp_legacy.expcore.roles") --- @dep expcore.roles
|
||||
local Datastore = require("modules.exp_legacy.expcore.datastore") --- @dep expcore.datastore
|
||||
local Event = require("modules/exp_legacy/utils/event") --- @dep utils.event
|
||||
@@ -23,20 +23,20 @@ config.set_datastores(SelectedPlayer, SelectedAction)
|
||||
|
||||
--- Button used to open the action bar
|
||||
-- @element open_action_bar
|
||||
local open_action_bar =
|
||||
Gui.element{
|
||||
local open_action_bar = Gui.element("open_action_bar")
|
||||
:draw{
|
||||
type = "sprite-button",
|
||||
sprite = "utility/expand_dots",
|
||||
tooltip = { "player-list.open-action-bar" },
|
||||
style = "frame_button",
|
||||
name = Gui.unique_static_name,
|
||||
name = Gui.property_from_name,
|
||||
}
|
||||
:style{
|
||||
padding = -2,
|
||||
width = 8,
|
||||
height = 14,
|
||||
}
|
||||
:on_click(function(player, element, _)
|
||||
:on_click(function(def, player, element)
|
||||
local selected_player_name = element.parent.name
|
||||
local old_selected_player_name = SelectedPlayer:get(player)
|
||||
if selected_player_name == old_selected_player_name then
|
||||
@@ -48,30 +48,40 @@ local open_action_bar =
|
||||
|
||||
--- Button used to close the action bar
|
||||
-- @element close_action_bar
|
||||
local close_action_bar =
|
||||
Gui.element{
|
||||
local close_action_bar = Gui.element("close_action_bar")
|
||||
:draw{
|
||||
type = "sprite-button",
|
||||
sprite = "utility/close_black",
|
||||
tooltip = { "player-list.close-action-bar" },
|
||||
style = "slot_sized_button_red",
|
||||
}
|
||||
:style(Gui.sprite_style(30, -1, { top_margin = -1, right_margin = -1 }))
|
||||
:on_click(function(player, _)
|
||||
:style(Gui.styles.sprite{
|
||||
size = 20,
|
||||
padding = -1,
|
||||
top_margin = -1,
|
||||
right_margin = -1,
|
||||
})
|
||||
:on_click(function(def, player, element)
|
||||
SelectedPlayer:remove(player)
|
||||
SelectedAction:remove(player)
|
||||
end)
|
||||
|
||||
--- Button used to confirm a reason
|
||||
-- @element reason_confirm
|
||||
local reason_confirm =
|
||||
Gui.element{
|
||||
local reason_confirm = Gui.element("reason_confirm")
|
||||
:draw{
|
||||
type = "sprite-button",
|
||||
sprite = "utility/confirm_slot",
|
||||
tooltip = { "player-list.reason-confirm" },
|
||||
style = "slot_sized_button_green",
|
||||
}
|
||||
:style(Gui.sprite_style(30, -1, { left_margin = -2, right_margin = -1 }))
|
||||
:on_click(function(player, element)
|
||||
:style(Gui.styles.sprite{
|
||||
size = 30,
|
||||
padding = -1,
|
||||
left_margin = -2,
|
||||
right_margin = -1,
|
||||
})
|
||||
:on_click(function(def, player, element)
|
||||
local reason = element.parent.entry.text
|
||||
local action_name = SelectedAction:get(player)
|
||||
local reason_callback = config.buttons[action_name].reason_callback
|
||||
@@ -84,8 +94,8 @@ local reason_confirm =
|
||||
|
||||
--- Set of elements that are used to make up a row of the player table
|
||||
-- @element add_player_base
|
||||
local add_player_base =
|
||||
Gui.element(function(_, parent, player_data)
|
||||
local add_player_base = Gui.element("add_player_base")
|
||||
:draw(function(_, parent, player_data)
|
||||
-- Add the button to open the action bar
|
||||
local toggle_action_bar_flow = parent.add{ type = "flow", name = player_data.name }
|
||||
open_action_bar(toggle_action_bar_flow)
|
||||
@@ -101,7 +111,7 @@ local add_player_base =
|
||||
player_name.style.font_color = player_data.chat_color
|
||||
|
||||
-- Add the time played label
|
||||
local alignment = Gui.alignment(parent, "player-time-" .. player_data.index)
|
||||
local alignment = Gui.elements.aligned_flow(parent, { name = "player-time-" .. player_data.index })
|
||||
local time_label = alignment.add{
|
||||
name = "label",
|
||||
type = "label",
|
||||
@@ -112,12 +122,16 @@ local add_player_base =
|
||||
|
||||
return player_name
|
||||
end)
|
||||
:on_click(function(player, element, event)
|
||||
:on_click(function(def, player, element, event)
|
||||
local selected_player_name = element.caption
|
||||
local selected_player = game.players[selected_player_name]
|
||||
if event.button == defines.mouse_button_type.left then
|
||||
-- LMB will open the map to the selected player
|
||||
event.player.set_controller{ type = defines.controllers.remote, position = selected_player.physical_position, surface = selected_player.physical_surface }
|
||||
player.set_controller{
|
||||
type = defines.controllers.remote,
|
||||
position = selected_player.physical_position,
|
||||
surface = selected_player.physical_surface
|
||||
}
|
||||
else
|
||||
-- RMB will toggle the settings
|
||||
local old_selected_player_name = SelectedPlayer:get(player)
|
||||
@@ -148,8 +162,8 @@ end
|
||||
|
||||
--- Adds all the buttons and flows that make up the action bar
|
||||
-- @element add_action_bar
|
||||
local add_action_bar_buttons =
|
||||
Gui.element(function(_, parent)
|
||||
local add_action_bar_buttons = Gui.element("add_action_bar_buttons")
|
||||
:draw(function(_, parent)
|
||||
close_action_bar(parent)
|
||||
-- Loop over all the buttons in the config
|
||||
for action_name, button_data in pairs(config.buttons) do
|
||||
@@ -167,7 +181,7 @@ local add_action_bar_buttons =
|
||||
|
||||
--- Updates the visible state of the action bar buttons
|
||||
local function update_action_bar(element)
|
||||
local player = Gui.get_player_from_element(element)
|
||||
local player = Gui.get_player(element)
|
||||
local selected_player_name = SelectedPlayer:get(player)
|
||||
|
||||
if not selected_player_name then
|
||||
@@ -196,20 +210,20 @@ end
|
||||
|
||||
--- Main player list container for the left flow
|
||||
-- @element player_list_container
|
||||
local player_list_container =
|
||||
Gui.element(function(definition, parent)
|
||||
local player_list_container = Gui.element("player_list_container")
|
||||
:draw(function(definition, parent)
|
||||
-- Draw the internal container
|
||||
local container = Gui.container(parent, definition.name, 200)
|
||||
local container = Gui.elements.container(parent, 200)
|
||||
|
||||
-- Draw the scroll table for the players
|
||||
local scroll_table = Gui.scroll_table(container, 184, 3)
|
||||
local scroll_table = Gui.elements.scroll_table(container, 184, 3, "scroll")
|
||||
|
||||
-- Change the style of the scroll table
|
||||
local scroll_table_style = scroll_table.style
|
||||
scroll_table_style.padding = { 1, 0, 1, 2 }
|
||||
|
||||
-- Add the action bar
|
||||
local action_bar = Gui.footer(container, nil, nil, false, "action_bar")
|
||||
local action_bar = Gui.elements.footer(container, { name = "action_bar", no_flow = true })
|
||||
|
||||
-- Change the style of the action bar
|
||||
local action_bar_style = action_bar.style
|
||||
@@ -221,7 +235,7 @@ local player_list_container =
|
||||
add_action_bar_buttons(action_bar)
|
||||
|
||||
-- Add the reason bar
|
||||
local reason_bar = Gui.footer(container, nil, nil, false, "reason_bar")
|
||||
local reason_bar = Gui.elements.footer(container, { name = "reason_bar", no_flow = true })
|
||||
|
||||
-- Change the style of the reason bar
|
||||
local reason_bar_style = reason_bar.style
|
||||
@@ -250,14 +264,18 @@ local player_list_container =
|
||||
-- Return the exteral container
|
||||
return container.parent
|
||||
end)
|
||||
:static_name(Gui.unique_static_name)
|
||||
:add_to_left_flow(true)
|
||||
|
||||
--- Button on the top flow used to toggle the player list container
|
||||
-- @element toggle_player_list
|
||||
Gui.left_toolbar_button("entity/character", { "player-list.main-tooltip" }, player_list_container, function(player)
|
||||
return Roles.player_allowed(player, "gui/player-list")
|
||||
end)
|
||||
--- Add the element to the left flow with a toolbar button
|
||||
Gui.add_left_element(player_list_container, true)
|
||||
Gui.toolbar.create_button{
|
||||
name = "player_list_toggle",
|
||||
left_element = player_list_container,
|
||||
sprite = "entity/character",
|
||||
tooltip = { "player-list.main-tooltip" },
|
||||
visible = function(player, element)
|
||||
return Roles.player_allowed(player, "gui/player-list")
|
||||
end
|
||||
}
|
||||
|
||||
local online_time_format = ExpUtil.format_time_factory_locale{ format = "short", hours = true, minutes = true }
|
||||
local afk_time_format = ExpUtil.format_time_factory_locale{ format = "long", minutes = true }
|
||||
@@ -347,8 +365,8 @@ end
|
||||
Event.on_nth_tick(1800, function()
|
||||
local player_times = get_player_times()
|
||||
for _, player in pairs(game.connected_players) do
|
||||
local frame = Gui.get_left_element(player, player_list_container)
|
||||
local scroll_table = frame.container.scroll.table
|
||||
local container = Gui.get_left_element(player_list_container, player)
|
||||
local scroll_table = container.frame.scroll.table
|
||||
for _, player_time in pairs(player_times) do
|
||||
update_player_base(scroll_table, player_time)
|
||||
end
|
||||
@@ -359,8 +377,8 @@ end)
|
||||
Event.add(defines.events.on_player_left_game, function(event)
|
||||
local remove_player = game.players[event.player_index]
|
||||
for _, player in pairs(game.connected_players) do
|
||||
local frame = Gui.get_left_element(player, player_list_container)
|
||||
local scroll_table = frame.container.scroll.table
|
||||
local container = Gui.get_left_element(player_list_container, player)
|
||||
local scroll_table = container.frame.scroll.table
|
||||
remove_player_base(scroll_table, remove_player)
|
||||
|
||||
local selected_player_name = SelectedPlayer:get(player)
|
||||
@@ -375,8 +393,8 @@ end)
|
||||
local function redraw_player_list()
|
||||
local player_list_order = get_player_list_order()
|
||||
for _, player in pairs(game.connected_players) do
|
||||
local frame = Gui.get_left_element(player, player_list_container)
|
||||
local scroll_table = frame.container.scroll.table
|
||||
local container = Gui.get_left_element(player_list_container, player)
|
||||
local scroll_table = container.frame.scroll.table
|
||||
scroll_table.clear()
|
||||
for _, next_player_data in ipairs(player_list_order) do
|
||||
add_player_base(scroll_table, next_player_data)
|
||||
@@ -391,9 +409,9 @@ Event.add(Roles.events.on_role_unassigned, redraw_player_list)
|
||||
--- When the action player is changed the action bar will update
|
||||
SelectedPlayer:on_update(function(player_name, selected_player)
|
||||
local player = game.players[player_name]
|
||||
local frame = Gui.get_left_element(player, player_list_container)
|
||||
local scroll_table = frame.container.scroll.table
|
||||
update_action_bar(frame.container.action_bar)
|
||||
local container = Gui.get_left_element(player_list_container, player)
|
||||
local scroll_table = container.frame.scroll.table
|
||||
update_action_bar(container.frame.action_bar)
|
||||
for _, next_player in pairs(game.connected_players) do
|
||||
local element = scroll_table[next_player.name][open_action_bar.name]
|
||||
local style = "frame_button"
|
||||
@@ -411,8 +429,8 @@ end)
|
||||
--- When the action name is changed the reason input will update
|
||||
SelectedAction:on_update(function(player_name, selected_action)
|
||||
local player = game.players[player_name]
|
||||
local frame = Gui.get_left_element(player, player_list_container)
|
||||
local element = frame.container.reason_bar
|
||||
local container = Gui.get_left_element(player_list_container, player)
|
||||
local element = container.frame.reason_bar
|
||||
if selected_action then
|
||||
-- if there is a new value then check the player is still online
|
||||
local selected_player_name = SelectedPlayer:get(player_name)
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
-- @gui PlayerData
|
||||
|
||||
local ExpUtil = require("modules/exp_util")
|
||||
local Gui = require("modules.exp_legacy.expcore.gui") --- @dep expcore.gui
|
||||
local Gui = require("modules/exp_gui")
|
||||
local Roles = require("modules.exp_legacy.expcore.roles") --- @dep expcore.roles
|
||||
local Event = require("modules/exp_legacy/utils/event") --- @dep utils.event
|
||||
local PlayerData = require("modules.exp_legacy.expcore.player_data") --- @dep expcore.player_data
|
||||
@@ -74,8 +74,8 @@ local computed_stats = {
|
||||
},
|
||||
}
|
||||
|
||||
local label =
|
||||
Gui.element(function(_, parent, width, caption, tooltip, name)
|
||||
local label = Gui.element("label")
|
||||
:draw(function(_, parent, width, caption, tooltip, name)
|
||||
local new_label = parent.add{
|
||||
type = "label",
|
||||
caption = caption,
|
||||
@@ -88,10 +88,10 @@ local label =
|
||||
return new_label
|
||||
end)
|
||||
|
||||
local pd_data_set =
|
||||
Gui.element(function(_, parent, name)
|
||||
local pd_data_set = Gui.element("pd_data_set")
|
||||
:draw(function(_, parent, name)
|
||||
local pd_data_set = parent.add{ type = "flow", direction = "vertical", name = name }
|
||||
local disp = Gui.scroll_table(pd_data_set, label_width["total"], 4, "disp")
|
||||
local disp = Gui.elements.scroll_table(pd_data_set, label_width["total"], 4, "disp")
|
||||
|
||||
for _, stat_name in pairs(PlayerData.Statistics.metadata.display_order) do
|
||||
local child = PlayerData.Statistics[stat_name]
|
||||
@@ -129,32 +129,31 @@ local function pd_update(table, player_name)
|
||||
end
|
||||
end
|
||||
|
||||
local pd_username_player =
|
||||
Gui.element(function(definition, parent, player_list)
|
||||
local pd_username_player = Gui.element("pd_username_player")
|
||||
:draw(function(def, parent, player_list)
|
||||
return parent.add{
|
||||
name = definition.name,
|
||||
name = def.name,
|
||||
type = "drop-down",
|
||||
items = player_list,
|
||||
selected_index = #player_list > 0 and 1,
|
||||
selected_index = #player_list > 0 and 1 or nil,
|
||||
}
|
||||
end)
|
||||
:style{
|
||||
horizontally_stretchable = true,
|
||||
}:on_selection_changed(function(_, element, _)
|
||||
}:on_selection_state_changed(function(def, player, element)
|
||||
local player_name = game.connected_players[element.selected_index]
|
||||
local table = element.parent.parent.parent.parent["pd_st_2"].disp.table
|
||||
pd_update(table, player_name)
|
||||
end)
|
||||
:static_name(Gui.unique_static_name)
|
||||
|
||||
local pd_username_update =
|
||||
Gui.element{
|
||||
local pd_username_update = Gui.element("pd_username_update")
|
||||
:draw{
|
||||
type = "button",
|
||||
name = Gui.unique_static_name,
|
||||
name = Gui.property_from_name,
|
||||
caption = "update",
|
||||
}:style{
|
||||
width = 128,
|
||||
}:on_click(function(_, element, _)
|
||||
}:on_click(function(def, player, element)
|
||||
local player_index = element.parent[pd_username_player.name].selected_index
|
||||
|
||||
if player_index > 0 then
|
||||
@@ -164,10 +163,10 @@ local pd_username_update =
|
||||
end
|
||||
end)
|
||||
|
||||
local pd_username_set =
|
||||
Gui.element(function(_, parent, name, player_list)
|
||||
local pd_username_set = Gui.element("pd_username_set")
|
||||
:draw(function(_, parent, name, player_list)
|
||||
local pd_username_set = parent.add{ type = "flow", direction = "vertical", name = name }
|
||||
local disp = Gui.scroll_table(pd_username_set, label_width["total"], 2, "disp")
|
||||
local disp = Gui.elements.scroll_table(pd_username_set, label_width["total"], 2, "disp")
|
||||
|
||||
pd_username_player(disp, player_list)
|
||||
pd_username_update(disp)
|
||||
@@ -175,9 +174,9 @@ local pd_username_set =
|
||||
return pd_username_set
|
||||
end)
|
||||
|
||||
pd_container =
|
||||
Gui.element(function(definition, parent)
|
||||
local container = Gui.container(parent, definition.name, label_width["total"])
|
||||
pd_container = Gui.element("pd_container")
|
||||
:draw(function(def, parent)
|
||||
local container = Gui.elements.container(parent, label_width["total"])
|
||||
local player_list = {}
|
||||
|
||||
for _, player in pairs(game.connected_players) do
|
||||
@@ -189,12 +188,18 @@ pd_container =
|
||||
|
||||
return container.parent
|
||||
end)
|
||||
:static_name(Gui.unique_static_name)
|
||||
:add_to_left_flow()
|
||||
|
||||
Gui.left_toolbar_button("item/power-armor-mk2", "Player Data GUI", pd_container, function(player)
|
||||
return Roles.player_allowed(player, "gui/playerdata")
|
||||
end)
|
||||
--- Add the element to the left flow with a toolbar button
|
||||
Gui.add_left_element(pd_container, false)
|
||||
Gui.toolbar.create_button{
|
||||
name = "player_data_toggle",
|
||||
left_element = pd_container,
|
||||
sprite = "item/power-armor-mk2",
|
||||
tooltip = "Player Data GUI",
|
||||
visible = function(player, element)
|
||||
return Roles.player_allowed(player, "gui/playerdata")
|
||||
end
|
||||
}
|
||||
|
||||
local function gui_player_list_update()
|
||||
local player_list = {}
|
||||
@@ -204,8 +209,8 @@ local function gui_player_list_update()
|
||||
end
|
||||
|
||||
for _, player in pairs(game.connected_players) do
|
||||
local frame = Gui.get_left_element(player, pd_container)
|
||||
frame.container["pd_st_1"].disp.table[pd_username_player.name].items = player_list
|
||||
local container = Gui.get_left_element(pd_container, player)
|
||||
container.frame["pd_st_1"].disp.table[pd_username_player.name].items = player_list
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
---- Production Data
|
||||
-- @gui Production
|
||||
|
||||
local Gui = require("modules.exp_legacy.expcore.gui") --- @dep expcore.gui
|
||||
local Gui = require("modules/exp_gui")
|
||||
local Event = require("modules/exp_legacy/utils/event") --- @dep utils.event
|
||||
local Roles = require("modules.exp_legacy.expcore.roles") --- @dep expcore.roles
|
||||
|
||||
@@ -35,8 +35,8 @@ end
|
||||
|
||||
--- Display group
|
||||
-- @element production_data_group
|
||||
local production_data_group =
|
||||
Gui.element(function(_definition, parent, i)
|
||||
local production_data_group = Gui.element("production_data_group")
|
||||
:draw(function(_def, parent, i)
|
||||
local item
|
||||
|
||||
if i == 0 then
|
||||
@@ -93,10 +93,10 @@ local production_data_group =
|
||||
|
||||
--- A vertical flow containing all the production data
|
||||
-- @element production_data_set
|
||||
local production_data_set =
|
||||
Gui.element(function(_, parent, name)
|
||||
local production_data_set = Gui.element("production_data_set")
|
||||
:draw(function(_, parent, name)
|
||||
local production_set = parent.add{ type = "flow", direction = "vertical", name = name }
|
||||
local disp = Gui.scroll_table(production_set, 350, 4, "disp")
|
||||
local disp = Gui.elements.scroll_table(production_set, 350, 4, "disp")
|
||||
|
||||
production_data_group(disp, 0)
|
||||
|
||||
@@ -111,31 +111,37 @@ local production_data_set =
|
||||
return production_set
|
||||
end)
|
||||
|
||||
production_container =
|
||||
Gui.element(function(definition, parent)
|
||||
local container = Gui.container(parent, definition.name, 350)
|
||||
production_container = Gui.element("production_container")
|
||||
:draw(function(def, parent)
|
||||
local container = Gui.elements.container(parent, 350)
|
||||
|
||||
production_data_set(container, "production_st")
|
||||
|
||||
return container.parent
|
||||
end)
|
||||
:static_name(Gui.unique_static_name)
|
||||
:add_to_left_flow()
|
||||
|
||||
Gui.left_toolbar_button("entity/assembling-machine-3", { "production.main-tooltip" }, production_container, function(player)
|
||||
return Roles.player_allowed(player, "gui/production")
|
||||
end)
|
||||
--- Add the element to the left flow with a toolbar button
|
||||
Gui.add_left_element(production_container, false)
|
||||
Gui.toolbar.create_button{
|
||||
name = "production_toggle",
|
||||
left_element = production_container,
|
||||
sprite = "entity/assembling-machine-3",
|
||||
tooltip = { "production.main-tooltip" },
|
||||
visible = function(player, element)
|
||||
return Roles.player_allowed(player, "gui/production")
|
||||
end
|
||||
}
|
||||
|
||||
Event.on_nth_tick(60, function()
|
||||
for _, player in pairs(game.connected_players) do
|
||||
local frame = Gui.get_left_element(player, production_container)
|
||||
local container = Gui.get_left_element(production_container, player)
|
||||
local stat = player.force.get_item_production_statistics(player.surface) -- Allow remote view
|
||||
local precision_value = precision[frame.container["production_st"].disp.table["production_0_e"].selected_index]
|
||||
local table = frame.container["production_st"].disp.table
|
||||
local precision_value = precision[container.frame["production_st"].disp.table["production_0_e"].selected_index]
|
||||
local table = container.frame["production_st"].disp.table
|
||||
|
||||
for i = 1, 8 do
|
||||
local production_prefix = "production_" .. i
|
||||
local item = table[production_prefix .. "_e"].elem_value
|
||||
local item = table[production_prefix .. "_e"].elem_value --[[ @as string ]]
|
||||
|
||||
if item then
|
||||
local add = math.floor(stat.get_flow_count{ name = item, category = "input", precision_index = precision_value, count = false } / 6) / 10
|
||||
|
||||
@@ -5,8 +5,8 @@
|
||||
]]
|
||||
|
||||
local ExpUtil = require("modules/exp_util")
|
||||
local Gui = require("modules/exp_gui")
|
||||
local Event = require("modules/exp_legacy/utils/event") --- @dep utils.event
|
||||
local Gui = require("modules.exp_legacy.expcore.gui") --- @dep expcore.gui
|
||||
local Roles = require("modules.exp_legacy.expcore.roles") --- @dep expcore.roles
|
||||
local Commands = require("modules/exp_commands") --- @dep expcore.commands
|
||||
local PlayerData = require("modules.exp_legacy.expcore.player_data") --- @dep expcore.player_data
|
||||
@@ -23,9 +23,8 @@ local title_width = 270 -- controls the centering of the titles
|
||||
local scroll_height = 275 -- controls the height of the scrolls
|
||||
|
||||
--- Sub content area used within the content areas
|
||||
-- @element sub_content
|
||||
local sub_content =
|
||||
Gui.element{
|
||||
local sub_content = Gui.element("readme_sub_content")
|
||||
:draw{
|
||||
type = "frame",
|
||||
direction = "vertical",
|
||||
style = "inside_deep_frame",
|
||||
@@ -38,10 +37,9 @@ local sub_content =
|
||||
}
|
||||
|
||||
--- Table which has a title above it above it
|
||||
-- @element title_table
|
||||
local title_table =
|
||||
Gui.element(function(_, parent, bar_size, caption, column_count)
|
||||
Gui.title_label(parent, bar_size, caption)
|
||||
local title_table = Gui.element("readme_title_table")
|
||||
:draw(function(_, parent, bar_size, caption, column_count)
|
||||
Gui.elements.title_label(parent, bar_size, caption)
|
||||
|
||||
return parent.add{
|
||||
type = "table",
|
||||
@@ -56,10 +54,9 @@ local title_table =
|
||||
horizontally_stretchable = true,
|
||||
}
|
||||
|
||||
--- Scroll to be used with Gui.title_label tables
|
||||
-- @element title_table_scroll
|
||||
local title_table_scroll =
|
||||
Gui.element{
|
||||
--- Scroll to be used with Gui.elements.title_label tables
|
||||
local title_table_scroll = Gui.element("readme_title_table_scroll")
|
||||
:draw{
|
||||
type = "scroll-pane",
|
||||
direction = "vertical",
|
||||
horizontal_scroll_policy = "never",
|
||||
@@ -73,9 +70,8 @@ local title_table_scroll =
|
||||
}
|
||||
|
||||
--- Used to connect to servers in server list
|
||||
-- @element join_server
|
||||
local join_server =
|
||||
Gui.element(function(_, parent, server_id, wrong_version)
|
||||
local join_server = Gui.element("readme_join_server")
|
||||
:draw(function(_, parent, server_id, wrong_version)
|
||||
local status = External.get_server_status(server_id) or "Offline"
|
||||
if wrong_version then status = "Version" end
|
||||
local flow = parent.add{ name = server_id, type = "flow" }
|
||||
@@ -103,8 +99,11 @@ local join_server =
|
||||
|
||||
return button
|
||||
end)
|
||||
:style(Gui.sprite_style(20, -1))
|
||||
:on_click(function(player, element, _)
|
||||
:style{
|
||||
size = 20,
|
||||
padding = -1,
|
||||
}
|
||||
:on_click(function(def, player, element)
|
||||
local server_id = element.parent.name
|
||||
External.request_connection(player, server_id, true)
|
||||
end)
|
||||
@@ -112,13 +111,12 @@ local join_server =
|
||||
local welcome_time_format = ExpUtil.format_time_factory_locale{ format = "long", days = true, hours = true, minutes = true }
|
||||
|
||||
--- Content area for the welcome tab
|
||||
-- @element welcome_content
|
||||
define_tab({ "readme.welcome-tab" }, { "readme.welcome-tooltip" },
|
||||
Gui.element(function(_, parent)
|
||||
define_tab({ "readme.welcome-tab" }, { "readme.welcome-tooltip" }, Gui.element("readme_welcome")
|
||||
:draw(function(_, parent)
|
||||
local server_details = { name = "APERX S0 - Local", welcome = "Failed to load description: disconnected from external api.", reset_time = "Non Set", branch = "Unknown" }
|
||||
if External.valid() then server_details = External.get_current_server() end
|
||||
local container = parent.add{ type = "flow", direction = "vertical" }
|
||||
local player = Gui.get_player_from_element(parent)
|
||||
local player = Gui.get_player(parent)
|
||||
|
||||
-- Set up the top flow with logos
|
||||
local top_flow = container.add{ type = "flow" }
|
||||
@@ -128,9 +126,9 @@ define_tab({ "readme.welcome-tab" }, { "readme.welcome-tooltip" },
|
||||
top_vertical_flow.style.horizontal_align = "center"
|
||||
|
||||
-- Add the title and description to the top flow
|
||||
Gui.title_label(top_vertical_flow, 62, "Welcome to " .. server_details.name)
|
||||
Gui.centered_label(top_vertical_flow, 380, server_details.welcome)
|
||||
Gui.bar(container)
|
||||
Gui.elements.title_label(top_vertical_flow, 62, "Welcome to " .. server_details.name)
|
||||
Gui.elements.centered_label(top_vertical_flow, 380, server_details.welcome)
|
||||
Gui.elements.bar(container)
|
||||
|
||||
-- Get the names of the roles the player has
|
||||
local player_roles = Roles.get_player_roles(player)
|
||||
@@ -142,75 +140,72 @@ define_tab({ "readme.welcome-tab" }, { "readme.welcome-tooltip" },
|
||||
-- Add the other information to the gui
|
||||
container.add{ type = "flow" }.style.height = 4
|
||||
local online_time = welcome_time_format(game.tick)
|
||||
Gui.centered_label(sub_content(container), frame_width, { "readme.welcome-general", server_details.reset_time, online_time })
|
||||
Gui.centered_label(sub_content(container), frame_width, { "readme.welcome-roles", table.concat(role_names, ", ") })
|
||||
Gui.centered_label(sub_content(container), frame_width, { "readme.welcome-chat" })
|
||||
Gui.elements.centered_label(sub_content(container), frame_width, { "readme.welcome-general", server_details.reset_time, online_time })
|
||||
Gui.elements.centered_label(sub_content(container), frame_width, { "readme.welcome-roles", table.concat(role_names, ", ") })
|
||||
Gui.elements.centered_label(sub_content(container), frame_width, { "readme.welcome-chat" })
|
||||
|
||||
return container
|
||||
end))
|
||||
|
||||
--- Content area for the rules tab
|
||||
-- @element rules_content
|
||||
define_tab({ "readme.rules-tab" }, { "readme.rules-tooltip" },
|
||||
Gui.element(function(_, parent)
|
||||
define_tab({ "readme.rules-tab" }, { "readme.rules-tooltip" }, Gui.element("readme_rules")
|
||||
:draw(function(_, parent)
|
||||
local container = parent.add{ type = "flow", direction = "vertical" }
|
||||
|
||||
-- Add the title and description to the content
|
||||
Gui.title_label(container, title_width - 3, { "readme.rules-tab" })
|
||||
Gui.centered_label(container, frame_width, { "readme.rules-general" })
|
||||
Gui.bar(container)
|
||||
Gui.elements.title_label(container, title_width - 3, { "readme.rules-tab" })
|
||||
Gui.elements.centered_label(container, frame_width, { "readme.rules-general" })
|
||||
Gui.elements.bar(container)
|
||||
container.add{ type = "flow" }
|
||||
|
||||
-- Add a table for the rules
|
||||
local rules = Gui.scroll_table(container, scroll_height, 1) --[[@as LuaGuiElement]]
|
||||
local rules = Gui.elements.scroll_table(container, scroll_height, 1) --[[@as LuaGuiElement]]
|
||||
rules.style = "bordered_table"
|
||||
rules.style.cell_padding = 4
|
||||
|
||||
-- Add the rules to the table
|
||||
for i = 1, 15 do
|
||||
Gui.centered_label(rules, 565, { "readme.rules-" .. i })
|
||||
Gui.elements.centered_label(rules, 565, { "readme.rules-" .. i })
|
||||
end
|
||||
|
||||
return container
|
||||
end))
|
||||
|
||||
--- Content area for the commands tab
|
||||
-- @element commands_content
|
||||
define_tab({ "readme.commands-tab" }, { "readme.commands-tooltip" },
|
||||
Gui.element(function(_, parent)
|
||||
define_tab({ "readme.commands-tab" }, { "readme.commands-tooltip" }, Gui.element("readme_commands")
|
||||
:draw(function(_, parent)
|
||||
local container = parent.add{ type = "flow", direction = "vertical" }
|
||||
local player = Gui.get_player_from_element(parent)
|
||||
local player = Gui.get_player(parent)
|
||||
|
||||
-- Add the title and description to the content
|
||||
Gui.title_label(container, title_width - 20, { "readme.commands-tab" })
|
||||
Gui.centered_label(container, frame_width, { "readme.commands-general" })
|
||||
Gui.bar(container)
|
||||
Gui.elements.title_label(container, title_width - 20, { "readme.commands-tab" })
|
||||
Gui.elements.centered_label(container, frame_width, { "readme.commands-general" })
|
||||
Gui.elements.bar(container)
|
||||
container.add{ type = "flow" }
|
||||
|
||||
-- Add a table for the commands
|
||||
local commands = Gui.scroll_table(container, scroll_height, 2) --[[@as LuaGuiElement]]
|
||||
local commands = Gui.elements.scroll_table(container, scroll_height, 2) --[[@as LuaGuiElement]]
|
||||
commands.style = "bordered_table"
|
||||
commands.style.cell_padding = 0
|
||||
|
||||
-- Add the rules to the table
|
||||
for name, command in pairs(Commands.list_for_player(player)) do
|
||||
Gui.centered_label(commands, 120, name)
|
||||
Gui.centered_label(commands, 450, command.description)
|
||||
Gui.elements.centered_label(commands, 120, name)
|
||||
Gui.elements.centered_label(commands, 450, command.description)
|
||||
end
|
||||
|
||||
return container
|
||||
end))
|
||||
|
||||
--- Content area for the servers tab
|
||||
-- @element servers_content
|
||||
define_tab({ "readme.servers-tab" }, { "readme.servers-tooltip" },
|
||||
Gui.element(function(_, parent)
|
||||
define_tab({ "readme.servers-tab" }, { "readme.servers-tooltip" }, Gui.element("readme_servers")
|
||||
:draw(function(_, parent)
|
||||
local container = parent.add{ type = "flow", direction = "vertical" }
|
||||
|
||||
-- Add the title and description to the content
|
||||
Gui.title_label(container, title_width - 10, { "readme.servers-tab" })
|
||||
Gui.centered_label(container, frame_width, { "readme.servers-general" })
|
||||
Gui.bar(container)
|
||||
Gui.elements.title_label(container, title_width - 10, { "readme.servers-tab" })
|
||||
Gui.elements.centered_label(container, frame_width, { "readme.servers-general" })
|
||||
Gui.elements.bar(container)
|
||||
container.add{ type = "flow" }
|
||||
|
||||
-- Draw the scroll
|
||||
@@ -222,15 +217,15 @@ define_tab({ "readme.servers-tab" }, { "readme.servers-tooltip" },
|
||||
local factorio_servers = title_table(scroll_pane, 225, { "readme.servers-factorio" }, 3)
|
||||
local current_version = External.get_current_server().version
|
||||
for server_id, server in pairs(External.get_servers()) do
|
||||
Gui.centered_label(factorio_servers, 110, server.short_name)
|
||||
Gui.centered_label(factorio_servers, 436, server.description)
|
||||
Gui.elements.centered_label(factorio_servers, 110, server.short_name)
|
||||
Gui.elements.centered_label(factorio_servers, 436, server.description)
|
||||
join_server(factorio_servers, server_id, current_version ~= server.version and server.version)
|
||||
end
|
||||
else
|
||||
local factorio_servers = title_table(scroll_pane, 225, { "readme.servers-factorio" }, 2)
|
||||
for _, i in pairs{ 1, 2, 3, 5, 6, 8 } do
|
||||
Gui.centered_label(factorio_servers, 110, { "readme.servers-" .. i })
|
||||
Gui.centered_label(factorio_servers, 460, { "readme.servers-d" .. i })
|
||||
Gui.elements.centered_label(factorio_servers, 110, { "readme.servers-" .. i })
|
||||
Gui.elements.centered_label(factorio_servers, 460, { "readme.servers-d" .. i })
|
||||
end
|
||||
end
|
||||
|
||||
@@ -238,23 +233,22 @@ define_tab({ "readme.servers-tab" }, { "readme.servers-tooltip" },
|
||||
local external_links = title_table(scroll_pane, 235, { "readme.servers-external" }, 2)
|
||||
for _, key in ipairs{ "website", "github" } do
|
||||
local upper_key = key:gsub("^%l", string.upper)
|
||||
Gui.centered_label(external_links, 110, upper_key)
|
||||
Gui.centered_label(external_links, 460, { "links." .. key }, { "readme.servers-open-in-browser" })
|
||||
Gui.elements.centered_label(external_links, 110, upper_key)
|
||||
Gui.elements.centered_label(external_links, 460, { "links." .. key }, { "readme.servers-open-in-browser" })
|
||||
end
|
||||
|
||||
return container
|
||||
end))
|
||||
|
||||
--- Content area for the servers tab
|
||||
-- @element backers_content
|
||||
define_tab({ "readme.backers-tab" }, { "readme.backers-tooltip" },
|
||||
Gui.element(function(_, parent)
|
||||
define_tab({ "readme.backers-tab" }, { "readme.backers-tooltip" }, Gui.element("readme_backers")
|
||||
:draw(function(_, parent)
|
||||
local container = parent.add{ type = "flow", direction = "vertical" }
|
||||
|
||||
-- Add the title and description to the content
|
||||
Gui.title_label(container, title_width - 10, { "readme.backers-tab" })
|
||||
Gui.centered_label(container, frame_width, { "readme.backers-general" })
|
||||
Gui.bar(container)
|
||||
Gui.elements.title_label(container, title_width - 10, { "readme.backers-tab" })
|
||||
Gui.elements.centered_label(container, frame_width, { "readme.backers-general" })
|
||||
Gui.elements.bar(container)
|
||||
container.add{ type = "flow" }
|
||||
|
||||
-- Find which players will go where
|
||||
@@ -296,12 +290,12 @@ define_tab({ "readme.backers-tab" }, { "readme.backers-tooltip" },
|
||||
for _, players in ipairs(groups) do
|
||||
local table = title_table(scroll_pane, players._width, players._title, 4)
|
||||
for _, player_name in ipairs(players) do
|
||||
Gui.centered_label(table, 140, player_name)
|
||||
Gui.elements.centered_label(table, 140, player_name)
|
||||
end
|
||||
|
||||
if #players < 4 then
|
||||
for i = 1, 4 - #players do
|
||||
Gui.centered_label(table, 140)
|
||||
Gui.elements.centered_label(table, 140)
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -310,11 +304,10 @@ define_tab({ "readme.backers-tab" }, { "readme.backers-tooltip" },
|
||||
end))
|
||||
|
||||
--- Content area for the player data tab
|
||||
-- @element commands_content
|
||||
define_tab({ "readme.data-tab" }, { "readme.data-tooltip" },
|
||||
Gui.element(function(_, parent)
|
||||
define_tab({ "readme.data-tab" }, { "readme.data-tooltip" }, Gui.element("readme_data")
|
||||
:draw(function(_, parent)
|
||||
local container = parent.add{ type = "flow", direction = "vertical" }
|
||||
local player = Gui.get_player_from_element(parent)
|
||||
local player = Gui.get_player(parent)
|
||||
local player_name = player.name
|
||||
|
||||
local enum = PlayerData.PreferenceEnum
|
||||
@@ -323,24 +316,24 @@ define_tab({ "readme.data-tab" }, { "readme.data-tooltip" },
|
||||
preference = enum[preference]
|
||||
|
||||
-- Add the title and description to the content
|
||||
Gui.title_label(container, title_width, { "readme.data-tab" })
|
||||
Gui.centered_label(container, frame_width, { "readme.data-general" })
|
||||
Gui.bar(container)
|
||||
Gui.elements.title_label(container, title_width, { "readme.data-tab" })
|
||||
Gui.elements.centered_label(container, frame_width, { "readme.data-general" })
|
||||
Gui.elements.bar(container)
|
||||
container.add{ type = "flow" }
|
||||
local scroll_pane = title_table_scroll(container)
|
||||
|
||||
-- Add the required area
|
||||
local required = title_table(scroll_pane, 250, { "readme.data-required" }, 2)
|
||||
Gui.centered_label(required, 150, preference_meta.name, preference_meta.tooltip)
|
||||
Gui.centered_label(required, 420, { "expcore-data.preference-" .. enum[preference] }, preference_meta.value_tooltip)
|
||||
Gui.elements.centered_label(required, 150, preference_meta.name, preference_meta.tooltip)
|
||||
Gui.elements.centered_label(required, 420, { "expcore-data.preference-" .. enum[preference] }, preference_meta.value_tooltip)
|
||||
|
||||
for name, child in pairs(PlayerData.Required.children) do
|
||||
local metadata = child.metadata
|
||||
local value = child:get(player_name)
|
||||
if value ~= nil or metadata.show_always then
|
||||
if metadata.stringify then value = metadata.stringify(value) end
|
||||
Gui.centered_label(required, 150, metadata.name or { "exp-required." .. name }, metadata.tooltip or { "exp-required." .. name .. "-tooltip" })
|
||||
Gui.centered_label(required, 420, tostring(value), metadata.value_tooltip or { "exp-required." .. name .. "-value-tooltip" })
|
||||
Gui.elements.centered_label(required, 150, metadata.name or { "exp-required." .. name }, metadata.tooltip or { "exp-required." .. name .. "-tooltip" })
|
||||
Gui.elements.centered_label(required, 420, tostring(value), metadata.value_tooltip or { "exp-required." .. name .. "-value-tooltip" })
|
||||
end
|
||||
end
|
||||
|
||||
@@ -353,8 +346,8 @@ define_tab({ "readme.data-tab" }, { "readme.data-tooltip" },
|
||||
if not metadata.permission or Roles.player_allowed(player, metadata.permission) then
|
||||
if metadata.stringify then value = metadata.stringify(value) end
|
||||
if value == nil then value = "None set" end
|
||||
Gui.centered_label(settings, 150, metadata.name or { "exp-settings." .. name }, metadata.tooltip or { "exp-settings." .. name .. "-tooltip" })
|
||||
Gui.centered_label(settings, 420, tostring(value), metadata.value_tooltip or { "exp-settings." .. name .. "-value-tooltip" })
|
||||
Gui.elements.centered_label(settings, 150, metadata.name or { "exp-settings." .. name }, metadata.tooltip or { "exp-settings." .. name .. "-tooltip" })
|
||||
Gui.elements.centered_label(settings, 420, tostring(value), metadata.value_tooltip or { "exp-settings." .. name .. "-value-tooltip" })
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -374,12 +367,12 @@ define_tab({ "readme.data-tab" }, { "readme.data-tooltip" },
|
||||
else
|
||||
value = format_number(value or 0, false)
|
||||
end
|
||||
Gui.centered_label(statistics, 150, metadata.name or { "exp-statistics." .. name }, metadata.tooltip or { "exp-statistics." .. name .. "-tooltip" })
|
||||
Gui.centered_label(statistics, 130, { "readme.data-format", value, metadata.unit or "" }, metadata.value_tooltip or { "exp-statistics." .. name .. "-tooltip" })
|
||||
Gui.elements.centered_label(statistics, 150, metadata.name or { "exp-statistics." .. name }, metadata.tooltip or { "exp-statistics." .. name .. "-tooltip" })
|
||||
Gui.elements.centered_label(statistics, 130, { "readme.data-format", value, metadata.unit or "" }, metadata.value_tooltip or { "exp-statistics." .. name .. "-tooltip" })
|
||||
end
|
||||
end
|
||||
|
||||
if count > 0 then for i = 1, count do Gui.centered_label(statistics, 140) end end
|
||||
if count > 0 then for i = 1, count do Gui.elements.centered_label(statistics, 140) end end
|
||||
end
|
||||
|
||||
-- Add the misc area
|
||||
@@ -394,8 +387,8 @@ define_tab({ "readme.data-tab" }, { "readme.data-tooltip" },
|
||||
local value = child:get(player_name)
|
||||
if value ~= nil or metadata.show_always then
|
||||
if metadata.stringify then value = metadata.stringify(value) end
|
||||
Gui.centered_label(misc, 150, metadata.name or name, metadata.tooltip)
|
||||
Gui.centered_label(misc, 420, tostring(value), metadata.value_tooltip)
|
||||
Gui.elements.centered_label(misc, 150, metadata.name or name, metadata.tooltip)
|
||||
Gui.elements.centered_label(misc, 420, tostring(value), metadata.value_tooltip)
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -405,18 +398,17 @@ define_tab({ "readme.data-tab" }, { "readme.data-tooltip" },
|
||||
end))
|
||||
|
||||
--- Main readme container for the center flow
|
||||
-- @element readme
|
||||
local readme_toggle
|
||||
local readme =
|
||||
Gui.element(function(definition, parent)
|
||||
local readme = Gui.element("readme")
|
||||
:draw(function(def, parent)
|
||||
local container = parent.add{
|
||||
name = definition.name,
|
||||
name = def.name,
|
||||
type = "frame",
|
||||
style = "invisible_frame",
|
||||
}
|
||||
|
||||
-- Add the left hand side of the frame back, removed because of frame_tabbed_pane style
|
||||
local left_alignment = Gui.alignment(container, nil, nil, "bottom")
|
||||
local left_alignment = Gui.elements.aligned_flow(container, { vertical_align = "bottom" })
|
||||
left_alignment.style.padding = { 32, 0, 0, 0 }
|
||||
|
||||
local left_side =
|
||||
@@ -443,22 +435,26 @@ local readme =
|
||||
|
||||
return container
|
||||
end)
|
||||
:static_name(Gui.unique_static_name)
|
||||
:on_open(function(player)
|
||||
Gui.toggle_toolbar_button(player, readme_toggle, true)
|
||||
:on_opened(function(def, player, element)
|
||||
Gui.toolbar.set_button_toggled_state(readme_toggle, player, true)
|
||||
end)
|
||||
:on_close(function(player, element)
|
||||
Gui.toggle_toolbar_button(player, readme_toggle, false)
|
||||
:on_closed(function(def, player, element)
|
||||
Gui.toolbar.set_button_toggled_state(readme_toggle, player, false)
|
||||
Gui.destroy_if_valid(element)
|
||||
end)
|
||||
|
||||
--- Toggle button for the readme gui
|
||||
-- @element readme_toggle
|
||||
readme_toggle =
|
||||
Gui.toolbar_button("virtual-signal/signal-info", { "readme.main-tooltip" }, function(player)
|
||||
return Roles.player_allowed(player, "gui/readme")
|
||||
end)
|
||||
:on_click(function(player, _)
|
||||
Gui.toolbar.create_button{
|
||||
name = "readme_toggle",
|
||||
auto_toggle = true,
|
||||
sprite = "virtual-signal/signal-info",
|
||||
tooltip = { "readme.main-tooltip" },
|
||||
visible = function(player, element)
|
||||
return Roles.player_allowed(player, "gui/readme")
|
||||
end
|
||||
}
|
||||
:on_click(function(def, player, element)
|
||||
local center = player.gui.center
|
||||
if center[readme.name] then
|
||||
player.opened = nil
|
||||
@@ -475,18 +471,13 @@ Event.add(defines.events.on_player_created, function(event)
|
||||
player.opened = element
|
||||
end)
|
||||
|
||||
--- When a player joins clear center unless the player has something open
|
||||
Event.add(defines.events.on_player_joined_game, function(event)
|
||||
local function clear_readme(event)
|
||||
local player = game.players[event.player_index]
|
||||
if not player.opened then
|
||||
player.gui.center.clear()
|
||||
Gui.destroy_if_valid(player.gui.center[readme.name])
|
||||
end
|
||||
end)
|
||||
end
|
||||
|
||||
--- When a player respawns clear center unless the player has something open
|
||||
Event.add(defines.events.on_player_respawned, function(event)
|
||||
local player = game.players[event.player_index]
|
||||
if not player.opened then
|
||||
player.gui.center.clear()
|
||||
end
|
||||
end)
|
||||
--- When a player joins or respawns, clear center unless the player has something open
|
||||
Event.add(defines.events.on_player_joined_game, clear_readme)
|
||||
Event.add(defines.events.on_player_respawned, clear_readme)
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
-- @gui Research
|
||||
|
||||
local ExpUtil = require("modules/exp_util")
|
||||
local Gui = require("modules.exp_legacy.expcore.gui") --- @dep expcore.gui
|
||||
local Gui = require("modules/exp_gui")
|
||||
local Storage = require("modules/exp_util/storage")
|
||||
local Event = require("modules/exp_legacy/utils/event") --- @dep utils.event
|
||||
local Roles = require("modules.exp_legacy.expcore.roles") --- @dep expcore.roles
|
||||
@@ -174,20 +174,20 @@ end
|
||||
|
||||
--- Display label for the clock display
|
||||
-- @element research_gui_clock_display
|
||||
local research_gui_clock =
|
||||
Gui.element{
|
||||
local research_gui_clock = Gui.element("research_gui_clock")
|
||||
:draw{
|
||||
type = "label",
|
||||
name = Gui.unique_static_name,
|
||||
name = Gui.property_from_name,
|
||||
caption = empty_time,
|
||||
style = "heading_2_label",
|
||||
}
|
||||
|
||||
--- A vertical flow containing the clock
|
||||
-- @element research_clock_set
|
||||
local research_clock_set =
|
||||
Gui.element(function(_, parent, name)
|
||||
local research_clock_set = Gui.element("research_clock_set")
|
||||
:draw(function(_, parent, name)
|
||||
local research_set = parent.add{ type = "flow", direction = "vertical", name = name }
|
||||
local disp = Gui.scroll_table(research_set, 390, 1, "disp")
|
||||
local disp = Gui.elements.scroll_table(research_set, 390, 1, "disp")
|
||||
|
||||
research_gui_clock(disp)
|
||||
|
||||
@@ -196,8 +196,8 @@ local research_clock_set =
|
||||
|
||||
--- Display group
|
||||
-- @element research_data_group
|
||||
local research_data_group =
|
||||
Gui.element(function(_definition, parent, i)
|
||||
local research_data_group = Gui.element("research_data_group")
|
||||
:draw(function(_def, parent, i)
|
||||
local name = parent.add{
|
||||
type = "label",
|
||||
name = "research_" .. i .. "_name",
|
||||
@@ -238,10 +238,10 @@ local research_data_group =
|
||||
|
||||
--- A vertical flow containing the data
|
||||
-- @element research_data_set
|
||||
local research_data_set =
|
||||
Gui.element(function(_, parent, name)
|
||||
local research_data_set = Gui.element("research_data_set")
|
||||
:draw(function(_, parent, name)
|
||||
local research_set = parent.add{ type = "flow", direction = "vertical", name = name }
|
||||
local disp = Gui.scroll_table(research_set, 390, 4, "disp")
|
||||
local disp = Gui.elements.scroll_table(research_set, 390, 4, "disp")
|
||||
local res_disp = research_gui_update()
|
||||
|
||||
research_data_group(disp, 0)
|
||||
@@ -265,21 +265,27 @@ local research_data_set =
|
||||
return research_set
|
||||
end)
|
||||
|
||||
local research_container =
|
||||
Gui.element(function(definition, parent)
|
||||
local container = Gui.container(parent, definition.name, 390)
|
||||
local research_container = Gui.element("research_container")
|
||||
:draw(function(def, parent)
|
||||
local container = Gui.elements.container(parent, 390)
|
||||
|
||||
research_clock_set(container, "research_st_1")
|
||||
research_data_set(container, "research_st_2")
|
||||
|
||||
return container.parent
|
||||
end)
|
||||
:static_name(Gui.unique_static_name)
|
||||
:add_to_left_flow()
|
||||
|
||||
Gui.left_toolbar_button("item/space-science-pack", { "research.main-tooltip" }, research_container, function(player)
|
||||
return Roles.player_allowed(player, "gui/research")
|
||||
end)
|
||||
--- Add the element to the left flow with a toolbar button
|
||||
Gui.add_left_element(research_container, false)
|
||||
Gui.toolbar.create_button{
|
||||
name = "research_toggle",
|
||||
left_element = research_container,
|
||||
sprite = "item/space-science-pack",
|
||||
tooltip = { "research.main-tooltip" },
|
||||
visible = function(player, element)
|
||||
return Roles.player_allowed(player, "gui/research")
|
||||
end
|
||||
}
|
||||
|
||||
Event.add(defines.events.on_research_finished, function(event)
|
||||
research_notification(event)
|
||||
@@ -294,8 +300,8 @@ Event.add(defines.events.on_research_finished, function(event)
|
||||
local res_disp = research_gui_update()
|
||||
|
||||
for _, player in pairs(game.connected_players) do
|
||||
local frame = Gui.get_left_element(player, research_container)
|
||||
local disp = frame.container["research_st_2"].disp.table
|
||||
local container = Gui.get_left_element(research_container, player)
|
||||
local disp = container.frame["research_st_2"].disp.table
|
||||
|
||||
for i = 1, 8, 1 do
|
||||
local research_name_i = "research_" .. i
|
||||
@@ -326,8 +332,8 @@ Event.on_nth_tick(60, function()
|
||||
local current_time = research_time_format(game.tick)
|
||||
|
||||
for _, player in pairs(game.connected_players) do
|
||||
local frame = Gui.get_left_element(player, research_container)
|
||||
local disp = frame.container["research_st_1"].disp.table
|
||||
local container = Gui.get_left_element(research_container, player)
|
||||
local disp = container.frame["research_st_1"].disp.table
|
||||
disp[research_gui_clock.name].caption = current_time
|
||||
end
|
||||
end)
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
]]
|
||||
|
||||
local ExpUtil = require("modules/exp_util")
|
||||
local Gui = require("modules.exp_legacy.expcore.gui") --- @dep expcore.gui
|
||||
local Gui = require("modules/exp_gui")
|
||||
local Roles = require("modules.exp_legacy.expcore.roles") --- @dep expcore.roles
|
||||
local Event = require("modules/exp_legacy/utils/event") --- @dep utils.event
|
||||
local config = require("modules.exp_legacy.config.gui.rockets") --- @dep config.gui.rockets
|
||||
@@ -39,15 +39,17 @@ end
|
||||
|
||||
--- Button to toggle the auto launch on a rocket silo
|
||||
-- @element toggle_launch
|
||||
local toggle_launch =
|
||||
Gui.element{
|
||||
local toggle_launch = Gui.element("toggle_launch")
|
||||
:draw{
|
||||
type = "sprite-button",
|
||||
sprite = "utility/play",
|
||||
tooltip = { "rocket-info.toggle-rocket-tooltip" },
|
||||
name = Gui.unique_static_name,
|
||||
name = Gui.property_from_name,
|
||||
}
|
||||
:style(Gui.sprite_style(16))
|
||||
:on_click(function(_, element, _)
|
||||
:style(Gui.styles.sprite{
|
||||
size = 16,
|
||||
})
|
||||
:on_click(function(def, player, element)
|
||||
local rocket_silo_name = element.parent.name:sub(8)
|
||||
local rocket_silo = Rockets.get_silo_entity(rocket_silo_name)
|
||||
if rocket_silo.auto_launch then
|
||||
@@ -61,30 +63,10 @@ local toggle_launch =
|
||||
end
|
||||
end)
|
||||
|
||||
--- Button to remotely launch a rocket from a silo
|
||||
-- @element launch_rocket
|
||||
local launch_rocket =
|
||||
Gui.element{
|
||||
type = "sprite-button",
|
||||
sprite = "utility/center",
|
||||
tooltip = { "rocket-info.launch-tooltip" },
|
||||
name = Gui.unique_static_name,
|
||||
}
|
||||
:style(Gui.sprite_style(16, -1))
|
||||
:on_click(function(player, element, _)
|
||||
local rocket_silo_name = element.parent.name:sub(8)
|
||||
local silo_data = Rockets.get_silo_data_by_name(rocket_silo_name)
|
||||
if silo_data.entity.launch_rocket() then
|
||||
element.enabled = false
|
||||
else
|
||||
player.print({ "rocket-info.launch-failed" }, Colors.orange_red)
|
||||
end
|
||||
end)
|
||||
|
||||
--- XY cords that allow zoom to map when pressed
|
||||
-- @element silo_cords
|
||||
local silo_cords =
|
||||
Gui.element(function(definition, parent, silo_data)
|
||||
local silo_cords = Gui.element("silo_cords")
|
||||
:draw(function(definition, parent, silo_data)
|
||||
local silo_name = silo_data.silo_name
|
||||
local pos = silo_data.position
|
||||
local tooltip = config.progress.allow_zoom_to_map and { "rocket-info.progress-label-tooltip" } or nil
|
||||
@@ -120,11 +102,11 @@ local silo_cords =
|
||||
}
|
||||
|
||||
if config.progress.allow_zoom_to_map then
|
||||
definition:triggers_events(label_x)
|
||||
definition:triggers_events(label_y)
|
||||
definition:link_element(label_x)
|
||||
definition:link_element(label_y)
|
||||
end
|
||||
end)
|
||||
:on_click(function(player, element, _)
|
||||
:on_click(function(def, player, element)
|
||||
local rocket_silo_name = element.parent.caption
|
||||
local rocket_silo = Rockets.get_silo_entity(rocket_silo_name)
|
||||
player.set_controller{ type = defines.controllers.remote, position = rocket_silo.position, surface = rocket_silo.surface }
|
||||
@@ -132,10 +114,10 @@ local silo_cords =
|
||||
|
||||
--- Base element for each rocket in the progress list
|
||||
-- @element rocket_entry
|
||||
local rocket_entry =
|
||||
Gui.element(function(_, parent, silo_data)
|
||||
local rocket_entry = Gui.element("rocket_entry")
|
||||
:draw(function(_, parent, silo_data)
|
||||
local silo_name = silo_data.silo_name
|
||||
local player = Gui.get_player_from_element(parent)
|
||||
local player = Gui.get_player(parent)
|
||||
|
||||
-- Add the toggle auto launch if the player is allowed it
|
||||
-- Auto launch was removed from the api and no 2.0 equivalent was added
|
||||
@@ -148,18 +130,11 @@ local rocket_entry =
|
||||
button.sprite = silo_data.toggle_sprite]]
|
||||
end
|
||||
|
||||
-- Add the remote launch if the player is allowed it
|
||||
if check_player_permissions(player, "remote_launch") then
|
||||
local flow = parent.add{ type = "flow", name = "launch-" .. silo_name }
|
||||
local button = launch_rocket(flow)
|
||||
button.enabled = silo_data.allow_launch
|
||||
end
|
||||
|
||||
-- Draw the silo cords element
|
||||
silo_cords(parent, silo_data)
|
||||
|
||||
-- Add a progress label
|
||||
local alignment = Gui.alignment(parent, silo_name)
|
||||
local alignment = Gui.elements.aligned_flow(parent, { name = silo_name })
|
||||
local element =
|
||||
alignment.add{
|
||||
type = "label",
|
||||
@@ -174,8 +149,8 @@ local rocket_entry =
|
||||
|
||||
--- Data label which contains a name and a value label pair
|
||||
-- @element data_label
|
||||
local data_label =
|
||||
Gui.element(function(_, parent, label_data)
|
||||
local data_label = Gui.element("data_label")
|
||||
:draw(function(_, parent, label_data)
|
||||
local data_name = label_data.name
|
||||
local data_subname = label_data.subname
|
||||
local data_fullname = data_subname and data_name .. data_subname or data_name
|
||||
@@ -190,7 +165,7 @@ local data_label =
|
||||
name_label.style.padding = { 0, 2 }
|
||||
|
||||
--- Right aligned label to store the data
|
||||
local alignment = Gui.alignment(parent, data_fullname)
|
||||
local alignment = Gui.elements.aligned_flow(parent, { name = data_fullname })
|
||||
local element =
|
||||
alignment.add{
|
||||
type = "label",
|
||||
@@ -305,13 +280,6 @@ local function update_build_progress(parent, progress_data)
|
||||
toggle_button.tooltip = silo_data.toggle_tooltip
|
||||
toggle_button.sprite = silo_data.toggle_sprite
|
||||
end
|
||||
|
||||
-- Update the launch button
|
||||
local launch_button = parent["launch-" .. silo_name]
|
||||
if launch_button then
|
||||
launch_button = launch_button[launch_rocket.name]
|
||||
launch_button.enabled = silo_data.allow_launch
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -424,18 +392,20 @@ end
|
||||
|
||||
-- Button to toggle a section dropdown
|
||||
-- @element toggle_section
|
||||
local toggle_section =
|
||||
Gui.element{
|
||||
local toggle_section = Gui.element("rocket_info_toggle_section")
|
||||
:draw{
|
||||
type = "sprite-button",
|
||||
sprite = "utility/expand",
|
||||
hovered_sprite = "utility/expand",
|
||||
tooltip = { "rocket-info.toggle-section-tooltip" },
|
||||
style = "frame_action_button",
|
||||
name = Gui.unique_static_name,
|
||||
name = Gui.property_from_name,
|
||||
}
|
||||
:style(Gui.sprite_style(20))
|
||||
:on_click(function(_, element, _)
|
||||
local header_flow = element.parent
|
||||
:style(Gui.styles.sprite{
|
||||
size = 20,
|
||||
})
|
||||
:on_click(function(def, player, element)
|
||||
local header_flow = assert(element.parent)
|
||||
local flow_name = header_flow.caption
|
||||
local flow = header_flow.parent.parent[flow_name]
|
||||
if Gui.toggle_visible_state(flow) then
|
||||
@@ -449,46 +419,46 @@ local toggle_section =
|
||||
|
||||
-- Draw a section header and main scroll
|
||||
-- @element rocket_list_container
|
||||
local section =
|
||||
Gui.element(function(definition, parent, section_name, table_size)
|
||||
local section = Gui.element("rocket_info_section")
|
||||
:draw(function(definition, parent, section_name, table_size)
|
||||
-- Draw the header for the section
|
||||
local header = Gui.header(
|
||||
parent,
|
||||
{ "rocket-info.section-caption-" .. section_name },
|
||||
{ "rocket-info.section-tooltip-" .. section_name },
|
||||
true,
|
||||
section_name .. "-header"
|
||||
)
|
||||
definition:triggers_events(header.parent.header_label)
|
||||
local header = Gui.elements.header(parent, {
|
||||
name = section_name .. "-header",
|
||||
caption = { "rocket-info.section-caption-" .. section_name },
|
||||
tooltip = { "rocket-info.section-tooltip-" .. section_name },
|
||||
label_name = "label",
|
||||
})
|
||||
|
||||
definition:link_element(header.parent.label)
|
||||
|
||||
-- Right aligned button to toggle the section
|
||||
header.caption = section_name
|
||||
toggle_section(header)
|
||||
|
||||
-- Table used to store the data
|
||||
local scroll_table = Gui.scroll_table(parent, 215, table_size, section_name)
|
||||
local scroll_table = Gui.elements.scroll_table(parent, 215, table_size, section_name)
|
||||
scroll_table.parent.visible = false
|
||||
|
||||
-- Return the flow table
|
||||
return definition:no_events(scroll_table)
|
||||
return definition:unlink_element(scroll_table)
|
||||
end)
|
||||
:on_click(function(_, element, event)
|
||||
:on_click(function(def, player, element, event)
|
||||
event.element = element.parent.alignment[toggle_section.name]
|
||||
toggle_section:raise_event(event)
|
||||
end)
|
||||
|
||||
--- Main gui container for the left flow
|
||||
-- @element rocket_list_container
|
||||
local rocket_list_container =
|
||||
Gui.element(function(definition, parent)
|
||||
local rocket_list_container = Gui.element("rocket_list_container")
|
||||
:draw(function(definition, parent)
|
||||
-- Draw the internal container
|
||||
local container = Gui.container(parent, definition.name, 200)
|
||||
local container = Gui.elements.container(parent, 200)
|
||||
|
||||
-- Set the container style
|
||||
local style = container.style
|
||||
style.padding = 0
|
||||
|
||||
local player = Gui.get_player_from_element(parent)
|
||||
local player = Gui.get_player(parent)
|
||||
local force_name = player.force.name
|
||||
-- Draw stats section
|
||||
if config.stats.show_stats then
|
||||
@@ -503,7 +473,6 @@ local rocket_list_container =
|
||||
-- Draw build progress list
|
||||
if config.progress.show_progress then
|
||||
local col_count = 3
|
||||
if check_player_permissions(player, "remote_launch") then col_count = col_count + 1 end
|
||||
if check_player_permissions(player, "toggle_active") then col_count = col_count + 1 end
|
||||
local progress = section(container, "progress", col_count)
|
||||
-- Label used when there are no active silos
|
||||
@@ -516,19 +485,23 @@ local rocket_list_container =
|
||||
update_build_progress(progress, get_progress_data(force_name))
|
||||
end
|
||||
|
||||
-- Return the exteral container
|
||||
-- Return the external container
|
||||
return container.parent
|
||||
end)
|
||||
:static_name(Gui.unique_static_name)
|
||||
:add_to_left_flow(function(player)
|
||||
return player.force.rockets_launched > 0 and Roles.player_allowed(player, "gui/rocket-info")
|
||||
end)
|
||||
|
||||
--- Button on the top flow used to toggle the container
|
||||
-- @element toggle_rocket_info
|
||||
Gui.left_toolbar_button("item/rocket-silo", { "rocket-info.main-tooltip" }, rocket_list_container, function(player)
|
||||
return Roles.player_allowed(player, "gui/rocket-info")
|
||||
--- Add the element to the left flow with a toolbar button
|
||||
Gui.add_left_element(rocket_list_container, function(player, element)
|
||||
return player.force.rockets_launched > 0 and Roles.player_allowed(player, "gui/rocket-info")
|
||||
end)
|
||||
Gui.toolbar.create_button{
|
||||
name = "rocket_list_toggle",
|
||||
left_element = rocket_list_container,
|
||||
sprite = "item/rocket-silo",
|
||||
tooltip = { "rocket-info.main-tooltip" },
|
||||
visible = function(player, element)
|
||||
return Roles.player_allowed(player, "gui/rocket-info")
|
||||
end
|
||||
}
|
||||
|
||||
--- Update the gui for all players on a force
|
||||
local function update_rocket_gui_all(force_name)
|
||||
@@ -536,11 +509,11 @@ local function update_rocket_gui_all(force_name)
|
||||
local milestones = get_milestone_data(force_name)
|
||||
local progress = get_progress_data(force_name)
|
||||
for _, player in pairs(game.forces[force_name].players) do
|
||||
local frame = Gui.get_left_element(player, rocket_list_container)
|
||||
local container = frame.container
|
||||
update_data_labels(container.stats.table, stats)
|
||||
update_data_labels(container.milestones.table, milestones)
|
||||
update_build_progress(container.progress.table, progress)
|
||||
local container = Gui.get_left_element(rocket_list_container, player)
|
||||
local frame = container.frame
|
||||
update_data_labels(frame.stats.table, stats)
|
||||
update_data_labels(frame.milestones.table, milestones)
|
||||
update_build_progress(frame.progress.table, progress)
|
||||
end
|
||||
end
|
||||
|
||||
@@ -553,10 +526,10 @@ end)
|
||||
--- Update only the progress gui for a force
|
||||
local function update_rocket_gui_progress(force_name)
|
||||
local progress = get_progress_data(force_name)
|
||||
for _, player in pairs(game.forces[force_name].players) do
|
||||
local frame = Gui.get_left_element(player, rocket_list_container)
|
||||
local container = frame.container
|
||||
update_build_progress(container.progress.table, progress)
|
||||
for _, player in pairs(game.forces[force_name].connected_players) do
|
||||
local container = Gui.get_left_element(rocket_list_container, player)
|
||||
local frame = container.frame
|
||||
update_build_progress(frame.progress.table, progress)
|
||||
end
|
||||
end
|
||||
|
||||
@@ -590,12 +563,11 @@ Event.add(defines.events.on_robot_built_entity, on_built)
|
||||
local function role_update_event(event)
|
||||
if not config.progress.show_progress then return end
|
||||
local player = game.players[event.player_index]
|
||||
local container = Gui.get_left_element(player, rocket_list_container).container
|
||||
local progress_scroll = container.progress
|
||||
local container = Gui.get_left_element(rocket_list_container, player)
|
||||
local progress_scroll = container.frame.progress
|
||||
Gui.destroy_if_valid(progress_scroll.table)
|
||||
|
||||
local col_count = 3
|
||||
if check_player_permissions(player, "remote_launch") then col_count = col_count + 1 end
|
||||
if check_player_permissions(player, "toggle_active") then col_count = col_count + 1 end
|
||||
local progress = progress_scroll.add{
|
||||
type = "table",
|
||||
|
||||
@@ -5,8 +5,8 @@
|
||||
]]
|
||||
|
||||
local ExpUtil = require("modules/exp_util")
|
||||
local Gui = require("modules.exp_legacy.expcore.gui") --- @dep expcore.gui
|
||||
local Roles = require("modules.exp_legacy.expcore.roles") --- @dep expcore.gui
|
||||
local Gui = require("modules/exp_gui")
|
||||
local Roles = require("modules.exp_legacy.expcore.roles")
|
||||
local Event = require("modules/exp_legacy/utils/event") --- @dep utils.event
|
||||
local config = require("modules.exp_legacy.config.gui.science") --- @dep config.gui.science
|
||||
local Production = require("modules.exp_legacy.modules.control.production") --- @dep modules.control.production
|
||||
@@ -17,16 +17,23 @@ local long_time_format = ExpUtil.format_time_factory_locale{ format = "long", ho
|
||||
local null_time_clock = { "science-info.eta-time", clock_time_format(nil) }
|
||||
local null_time_long = long_time_format(nil)
|
||||
|
||||
--- Data label that contains the value and the surfix
|
||||
--- Remove invalid science packs, this can result from a certain mod not being loaded
|
||||
for i = #config, 1, -1 do
|
||||
if not prototypes.item[config[i]] then
|
||||
table.remove(config, i)
|
||||
end
|
||||
end
|
||||
|
||||
--- Data label that contains the value and the suffix
|
||||
-- @element production_label
|
||||
local production_label =
|
||||
Gui.element(function(_, parent, production_label_data)
|
||||
local production_label = Gui.element("science_info_production_label")
|
||||
:draw(function(_, parent, production_label_data)
|
||||
local name = production_label_data.name
|
||||
local tooltip = production_label_data.tooltip
|
||||
local color = production_label_data.color
|
||||
|
||||
-- Add an alignment for the number
|
||||
local alignment = Gui.alignment(parent, name)
|
||||
local alignment = Gui.elements.aligned_flow(parent, { name = name })
|
||||
|
||||
-- Add the main value label
|
||||
local element =
|
||||
@@ -40,19 +47,19 @@ local production_label =
|
||||
-- Change the style
|
||||
element.style.font_color = color
|
||||
|
||||
-- Add the surfix label
|
||||
local surfix_element =
|
||||
-- Add the suffix label
|
||||
local suffix_element =
|
||||
parent.add{
|
||||
name = "surfix-" .. name,
|
||||
name = "suffix-" .. name,
|
||||
type = "label",
|
||||
caption = { "science-info.unit", production_label_data.surfix },
|
||||
caption = { "science-info.unit", production_label_data.suffix },
|
||||
tooltip = tooltip,
|
||||
}
|
||||
|
||||
-- Change the style
|
||||
local surfix_element_style = surfix_element.style
|
||||
surfix_element_style.font_color = color
|
||||
surfix_element_style.right_margin = 1
|
||||
local suffix_element_style = suffix_element.style
|
||||
suffix_element_style.font_color = color
|
||||
suffix_element_style.right_margin = 1
|
||||
|
||||
-- Return the value label
|
||||
return element
|
||||
@@ -61,12 +68,12 @@ local production_label =
|
||||
-- Get the data that is used with the production label
|
||||
local function get_production_label_data(name, tooltip, value, cutout, secondary)
|
||||
local data_colour = Production.get_color(config.color_cutoff * cutout, value, secondary)
|
||||
local surfix, caption = Production.format_number(value)
|
||||
local suffix, caption = Production.format_number(value)
|
||||
|
||||
return {
|
||||
name = name,
|
||||
caption = caption,
|
||||
surfix = surfix,
|
||||
suffix = suffix,
|
||||
tooltip = tooltip,
|
||||
color = data_colour,
|
||||
}
|
||||
@@ -84,17 +91,17 @@ local function update_production_label(parent, production_label_data)
|
||||
production_label_element.tooltip = production_label_data.tooltip
|
||||
production_label_element.style.font_color = color
|
||||
|
||||
-- Update the surfix label
|
||||
local surfix_element = parent["surfix-" .. name]
|
||||
surfix_element.caption = { "science-info.unit", production_label_data.surfix }
|
||||
surfix_element.tooltip = tooltip
|
||||
surfix_element.style.font_color = color
|
||||
-- Update the suffix label
|
||||
local suffix_element = parent["suffix-" .. name]
|
||||
suffix_element.caption = { "science-info.unit", production_label_data.suffix }
|
||||
suffix_element.tooltip = tooltip
|
||||
suffix_element.style.font_color = color
|
||||
end
|
||||
|
||||
--- Adds 4 elements that show the data for a science pack
|
||||
-- @element science_pack_base
|
||||
local science_pack_base =
|
||||
Gui.element(function(_, parent, science_pack_data)
|
||||
local science_pack_base = Gui.element("science_info_science_pack_base")
|
||||
:draw(function(_, parent, science_pack_data)
|
||||
local science_pack = science_pack_data.science_pack
|
||||
|
||||
-- Draw the icon for the science pack
|
||||
@@ -262,18 +269,21 @@ end
|
||||
|
||||
--- Main task list container for the left flow
|
||||
-- @element task_list_container
|
||||
local science_info_container =
|
||||
Gui.element(function(definition, parent)
|
||||
local player = Gui.get_player_from_element(parent)
|
||||
local science_info = Gui.element("science_info")
|
||||
:draw(function(def, parent)
|
||||
local player = Gui.get_player(parent)
|
||||
|
||||
-- Draw the internal container
|
||||
local container = Gui.container(parent, definition.name, 200)
|
||||
local container = Gui.elements.container(parent, 200)
|
||||
|
||||
-- Draw the header
|
||||
Gui.header(container, { "science-info.main-caption" }, { "science-info.main-tooltip" })
|
||||
Gui.elements.header(container, {
|
||||
caption = { "science-info.main-caption" },
|
||||
tooltip = { "science-info.main-tooltip" },
|
||||
})
|
||||
|
||||
-- Draw the scroll table for the tasks
|
||||
local scroll_table = Gui.scroll_table(container, 178, 4)
|
||||
local scroll_table = Gui.elements.scroll_table(container, 178, 4, "scroll")
|
||||
|
||||
-- Draw the no packs label
|
||||
local no_packs_label =
|
||||
@@ -292,7 +302,11 @@ local science_info_container =
|
||||
-- Add the footer and eta
|
||||
if config.show_eta then
|
||||
-- Draw the footer
|
||||
local footer = Gui.footer(container, { "science-info.eta-caption" }, { "science-info.eta-tooltip" }, true)
|
||||
local footer = Gui.elements.footer(container, {
|
||||
name = "footer",
|
||||
caption = { "science-info.eta-caption" },
|
||||
tooltip = { "science-info.eta-tooltip" },
|
||||
})
|
||||
|
||||
-- Draw the eta label
|
||||
local eta_label =
|
||||
@@ -313,17 +327,21 @@ local science_info_container =
|
||||
update_science_pack(scroll_table, get_science_pack_data(player, science_pack))
|
||||
end
|
||||
|
||||
-- Return the exteral container
|
||||
-- Return the external container
|
||||
return container.parent
|
||||
end)
|
||||
:static_name(Gui.unique_static_name)
|
||||
:add_to_left_flow()
|
||||
|
||||
--- Button on the top flow used to toggle the task list container
|
||||
-- @element toggle_science_info
|
||||
Gui.left_toolbar_button("entity/lab", { "science-info.main-tooltip" }, science_info_container, function(player)
|
||||
return Roles.player_allowed(player, "gui/science-info")
|
||||
end)
|
||||
--- Add the element to the left flow with a toolbar button
|
||||
Gui.add_left_element(science_info, false)
|
||||
Gui.toolbar.create_button{
|
||||
name = "science_info_toggle",
|
||||
left_element = science_info,
|
||||
sprite = "entity/lab",
|
||||
tooltip = { "science-info.main-tooltip" },
|
||||
visible = function(player, element)
|
||||
return Roles.player_allowed(player, "gui/science-info")
|
||||
end
|
||||
}
|
||||
|
||||
--- Updates the gui every 1 second
|
||||
Event.on_nth_tick(60, function()
|
||||
@@ -331,11 +349,11 @@ Event.on_nth_tick(60, function()
|
||||
local force_eta_data = {}
|
||||
for _, player in pairs(game.connected_players) do
|
||||
local force_name = player.force.name
|
||||
local frame = Gui.get_left_element(player, science_info_container)
|
||||
local container = frame.container
|
||||
local container = Gui.get_left_element(science_info, player)
|
||||
local frame = container.frame
|
||||
|
||||
-- Update the science packs
|
||||
local scroll_table = container.scroll.table
|
||||
local scroll_table = frame.scroll.table
|
||||
local pack_data = force_pack_data[force_name]
|
||||
if not pack_data then
|
||||
-- No data in cache so it needs to be generated
|
||||
@@ -355,7 +373,7 @@ Event.on_nth_tick(60, function()
|
||||
|
||||
-- Update the eta times
|
||||
if not config.show_eta then return end
|
||||
local eta_label = container.footer.alignment.label
|
||||
local eta_label = frame.footer.flow.label
|
||||
local eta_data = force_eta_data[force_name]
|
||||
if not eta_data then
|
||||
-- No data in chache so it needs to be generated
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
@alias server_ups
|
||||
]]
|
||||
|
||||
local Gui = require("modules.exp_legacy.expcore.gui") --- @dep expcore.gui
|
||||
local Gui = require("modules/exp_gui")
|
||||
local Event = require("modules/exp_legacy/utils/event") --- @dep utils.event
|
||||
local External = require("modules.exp_legacy.expcore.external") --- @dep expcore.external
|
||||
local Commands = require("modules/exp_commands")
|
||||
@@ -20,11 +20,11 @@ UsesServerUps:set_metadata{
|
||||
|
||||
--- Label to show the server ups
|
||||
-- @element server_ups
|
||||
local server_ups =
|
||||
Gui.element{
|
||||
local server_ups = Gui.element("server_ups")
|
||||
:draw{
|
||||
type = "label",
|
||||
caption = "SUPS = 60.0",
|
||||
name = Gui.unique_static_name,
|
||||
name = Gui.property_from_name,
|
||||
}
|
||||
:style{
|
||||
font = "default-game",
|
||||
@@ -71,6 +71,7 @@ end
|
||||
|
||||
-- Draw the label when the player joins
|
||||
Event.add(defines.events.on_player_created, set_location)
|
||||
Event.add(defines.events.on_player_joined_game, set_location)
|
||||
|
||||
-- Update the caption for all online players
|
||||
-- percentage of game speed
|
||||
|
||||
@@ -1,32 +1,31 @@
|
||||
---- module surveillance
|
||||
-- @gui surveillance
|
||||
|
||||
local Gui = require("modules.exp_legacy.expcore.gui") --- @dep expcore.gui
|
||||
local Gui = require("modules/exp_gui")
|
||||
local Roles = require("modules.exp_legacy.expcore.roles") --- @dep expcore.roles
|
||||
local Event = require("modules/exp_legacy/utils/event") --- @dep utils.event
|
||||
|
||||
local cctv_player =
|
||||
Gui.element(function(definition, parent, player_list)
|
||||
local cctv_player = Gui.element("cctv_player")
|
||||
:draw(function(def, parent, player_list)
|
||||
return parent.add{
|
||||
name = definition.name,
|
||||
name = def.name,
|
||||
type = "drop-down",
|
||||
items = player_list,
|
||||
selected_index = #player_list > 0 and 1,
|
||||
selected_index = #player_list > 0 and 1 or nil,
|
||||
}
|
||||
end)
|
||||
:style{
|
||||
horizontally_stretchable = true,
|
||||
}
|
||||
:static_name(Gui.unique_static_name)
|
||||
|
||||
local cctv_status =
|
||||
Gui.element{
|
||||
local cctv_status = Gui.element("cctv_status")
|
||||
:draw{
|
||||
type = "drop-down",
|
||||
items = { { "surveillance.status-enable" }, { "surveillance.status-disable" } },
|
||||
selected_index = 2,
|
||||
}:style{
|
||||
width = 96,
|
||||
}:on_selection_changed(function(_, element, _)
|
||||
}:on_selection_state_changed(function(def, player, element)
|
||||
if element.selected_index == 1 then
|
||||
element.parent.parent.parent.cctv_display.visible = true
|
||||
else
|
||||
@@ -34,59 +33,59 @@ local cctv_status =
|
||||
end
|
||||
end)
|
||||
|
||||
local cctv_type =
|
||||
Gui.element{
|
||||
local cctv_type = Gui.element("cctv_type")
|
||||
:draw{
|
||||
type = "drop-down",
|
||||
name = Gui.unique_static_name,
|
||||
name = Gui.property_from_name,
|
||||
items = { { "surveillance.type-player" }, { "surveillance.type-static" }, { "surveillance.type-player-loop" } },
|
||||
selected_index = 1,
|
||||
}:style{
|
||||
width = 96,
|
||||
}
|
||||
|
||||
local cctv_location =
|
||||
Gui.element{
|
||||
local cctv_location = Gui.element("cctv_location")
|
||||
:draw{
|
||||
type = "button",
|
||||
name = Gui.unique_static_name,
|
||||
name = Gui.property_from_name,
|
||||
caption = { "surveillance.func-set" },
|
||||
}:style{
|
||||
width = 48,
|
||||
}:on_click(function(player, element, _)
|
||||
}:on_click(function(def, player, element)
|
||||
element.parent.parent.parent.cctv_display.position = player.physical_position
|
||||
end)
|
||||
|
||||
local zoom_in =
|
||||
Gui.element{
|
||||
local zoom_in = Gui.element("zoom_in")
|
||||
:draw{
|
||||
type = "button",
|
||||
name = Gui.unique_static_name,
|
||||
name = Gui.property_from_name,
|
||||
caption = "+",
|
||||
}:style{
|
||||
width = 32,
|
||||
}:on_click(function(_, element, _)
|
||||
}:on_click(function(def, player, element)
|
||||
local display = element.parent.parent.parent.cctv_display
|
||||
if display.zoom < 2.0 then
|
||||
display.zoom = display.zoom + 0.05
|
||||
end
|
||||
end)
|
||||
|
||||
local zoom_out =
|
||||
Gui.element{
|
||||
local zoom_out = Gui.element("zoom_out")
|
||||
:draw{
|
||||
type = "button",
|
||||
name = Gui.unique_static_name,
|
||||
name = Gui.property_from_name,
|
||||
caption = "-",
|
||||
}:style{
|
||||
width = 32,
|
||||
}:on_click(function(_, element, _)
|
||||
}:on_click(function(def, player, element)
|
||||
local display = element.parent.parent.parent.cctv_display
|
||||
if display.zoom > 0.2 then
|
||||
display.zoom = display.zoom - 0.05
|
||||
end
|
||||
end)
|
||||
|
||||
local camera_set =
|
||||
Gui.element(function(_, parent, name, player_list)
|
||||
local camera_set = Gui.element("camera_set")
|
||||
:draw(function(_, parent, name, player_list)
|
||||
local camera_set = parent.add{ type = "flow", direction = "vertical", name = name }
|
||||
local buttons = Gui.scroll_table(camera_set, 480, 6, "buttons")
|
||||
local buttons = Gui.elements.scroll_table(camera_set, 480, 6, "buttons")
|
||||
|
||||
cctv_player(buttons, player_list)
|
||||
cctv_status(buttons)
|
||||
@@ -109,9 +108,9 @@ local camera_set =
|
||||
return camera_set
|
||||
end)
|
||||
|
||||
local cctv_container =
|
||||
Gui.element(function(definition, parent)
|
||||
local container = Gui.container(parent, definition.name, 480)
|
||||
local cctv_container = Gui.element("cctv_container")
|
||||
:draw(function(def, parent)
|
||||
local container = Gui.elements.container(parent, 480)
|
||||
local scroll = container.add{ name = "scroll", type = "scroll-pane", direction = "vertical" }
|
||||
scroll.style.maximal_height = 704
|
||||
local player_list = {}
|
||||
@@ -125,12 +124,18 @@ local cctv_container =
|
||||
|
||||
return container.parent
|
||||
end)
|
||||
:static_name(Gui.unique_static_name)
|
||||
:add_to_left_flow()
|
||||
|
||||
Gui.left_toolbar_button("entity/radar", { "surveillance.main-tooltip" }, cctv_container, function(player)
|
||||
return Roles.player_allowed(player, "gui/surveillance")
|
||||
end)
|
||||
--- Add the element to the left flow with a toolbar button
|
||||
Gui.add_left_element(cctv_container, false)
|
||||
Gui.toolbar.create_button{
|
||||
name = "cctv_toggle",
|
||||
left_element = cctv_container,
|
||||
sprite = "entity/radar",
|
||||
tooltip = { "surveillance.main-tooltip" },
|
||||
visible = function(player, element)
|
||||
return Roles.player_allowed(player, "gui/surveillance")
|
||||
end
|
||||
}
|
||||
|
||||
local function gui_update()
|
||||
local player_list = {}
|
||||
@@ -140,9 +145,9 @@ local function gui_update()
|
||||
end
|
||||
|
||||
for _, player in pairs(game.connected_players) do
|
||||
local frame = Gui.get_left_element(player, cctv_container)
|
||||
frame.container.scroll["cctv_st_1"].buttons.table[cctv_player.name].items = player_list
|
||||
frame.container.scroll["cctv_st_2"].buttons.table[cctv_player.name].items = player_list
|
||||
local container = Gui.get_left_element(cctv_container, player)
|
||||
container.frame.scroll["cctv_st_1"].buttons.table[cctv_player.name].items = player_list
|
||||
container.frame.scroll["cctv_st_2"].buttons.table[cctv_player.name].items = player_list
|
||||
end
|
||||
end
|
||||
|
||||
@@ -151,18 +156,18 @@ Event.add(defines.events.on_player_left_game, gui_update)
|
||||
|
||||
Event.add(defines.events.on_tick, function(_)
|
||||
for _, player in pairs(game.connected_players) do
|
||||
local frame = Gui.get_left_element(player, cctv_container)
|
||||
local container = Gui.get_left_element(cctv_container, player)
|
||||
|
||||
for i = 1, 2 do
|
||||
local scroll_table_name = "cctv_st_" .. i
|
||||
local current_camera_set = frame.container.scroll[scroll_table_name]
|
||||
local current_camera_set = container.frame.scroll[scroll_table_name]
|
||||
local switch_index = current_camera_set.buttons.table[cctv_type.name].selected_index
|
||||
|
||||
if (switch_index == 1) or (switch_index == 3) then
|
||||
local selected_index = current_camera_set.buttons.table[cctv_player.name].selected_index
|
||||
|
||||
if selected_index ~= 0 then
|
||||
selected_index = current_camera_set.buttons.table[cctv_player.name].items[selected_index]
|
||||
selected_index = current_camera_set.buttons.table[cctv_player.name].items[selected_index] --[[ @as number ]]
|
||||
current_camera_set["cctv_display"].position = game.players[selected_index].physical_position
|
||||
current_camera_set["cctv_display"].surface_index = game.players[selected_index].surface_index
|
||||
else
|
||||
@@ -176,10 +181,10 @@ end)
|
||||
|
||||
Event.on_nth_tick(600, function(_)
|
||||
for _, player in pairs(game.connected_players) do
|
||||
local frame = Gui.get_left_element(player, cctv_container)
|
||||
local container = Gui.get_left_element(cctv_container, player)
|
||||
|
||||
for i = 1, 2 do
|
||||
local current_camera_set = frame.container.scroll["cctv_st_" .. i]
|
||||
local current_camera_set = container.frame.scroll["cctv_st_" .. i]
|
||||
|
||||
if current_camera_set.buttons.table[cctv_type.name].selected_index == 3 then
|
||||
local item_n = #current_camera_set.buttons.table[cctv_player.name].items
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
]]
|
||||
|
||||
local ExpUtil = require("modules/exp_util")
|
||||
local Gui = require("modules.exp_legacy.expcore.gui") --- @dep expcore.gui
|
||||
local Gui = require("modules/exp_gui")
|
||||
local Event = require("modules/exp_legacy/utils/event") --- @dep utils.event
|
||||
local Roles = require("modules.exp_legacy.expcore.roles") --- @dep expcore.roles
|
||||
local Datastore = require("modules.exp_legacy.expcore.datastore") --- @dep expcore.datastore
|
||||
@@ -83,15 +83,17 @@ end
|
||||
|
||||
--- Button displayed in the header bar, used to add a new task
|
||||
-- @element add_new_task
|
||||
local add_new_task =
|
||||
Gui.element{
|
||||
local add_new_task = Gui.element("add_new_task")
|
||||
:draw{
|
||||
type = "sprite-button",
|
||||
sprite = "utility/add",
|
||||
tooltip = { "task-list.add-tooltip" },
|
||||
style = "tool_button",
|
||||
name = Gui.unique_static_name,
|
||||
}:style(Styles.sprite22):on_click(
|
||||
function(player, _, _)
|
||||
name = Gui.property_from_name,
|
||||
}
|
||||
:style(Styles.sprite22)
|
||||
:on_click(
|
||||
function(def, player, element)
|
||||
-- Disable editing
|
||||
PlayerIsEditing:set(player, false)
|
||||
-- Clear selected
|
||||
@@ -103,8 +105,8 @@ local add_new_task =
|
||||
|
||||
--- Header displayed when no tasks are in the task list
|
||||
-- @element no_tasks_found
|
||||
local no_tasks_found =
|
||||
Gui.element(
|
||||
local no_tasks_found = Gui.element("no_tasks_found")
|
||||
:draw(
|
||||
function(_, parent)
|
||||
local header =
|
||||
parent.add{
|
||||
@@ -113,6 +115,7 @@ local no_tasks_found =
|
||||
style = "negative_subheader_frame",
|
||||
}
|
||||
header.style.horizontally_stretchable = true
|
||||
header.style.bottom_margin = 0
|
||||
-- Flow used for centering the content in the subheader
|
||||
local center =
|
||||
header.add{
|
||||
@@ -134,50 +137,43 @@ local no_tasks_found =
|
||||
|
||||
--- Frame element with the right styling
|
||||
-- @element subfooter_frame
|
||||
local subfooter_frame =
|
||||
Gui.element(
|
||||
function(_, parent, name)
|
||||
return parent.add{
|
||||
type = "frame",
|
||||
name = name,
|
||||
direction = "vertical",
|
||||
style = "subfooter_frame",
|
||||
}
|
||||
end
|
||||
):style{
|
||||
local subfooter_frame = Gui.element("task_list_subfooter_frame")
|
||||
:draw{
|
||||
type = "frame",
|
||||
name = Gui.property_from_arg(1),
|
||||
direction = "vertical",
|
||||
style = "subfooter_frame",
|
||||
}
|
||||
:style{
|
||||
height = 0,
|
||||
padding = 5,
|
||||
use_header_filler = false,
|
||||
horizontally_stretchable = true,
|
||||
}
|
||||
|
||||
|
||||
--- Label element preset
|
||||
-- @element subfooter_label
|
||||
local subfooter_label =
|
||||
Gui.element(
|
||||
function(_, parent, caption)
|
||||
return parent.add{
|
||||
name = "footer_label",
|
||||
type = "label",
|
||||
style = "frame_title",
|
||||
caption = caption,
|
||||
}
|
||||
end
|
||||
)
|
||||
local subfooter_label = Gui.element("task_list_subfooter_label")
|
||||
:draw{
|
||||
name = "footer_label",
|
||||
type = "label",
|
||||
style = "frame_title",
|
||||
caption = Gui.property_from_arg(1),
|
||||
}
|
||||
|
||||
--- Action flow that contains action buttons
|
||||
-- @element subfooter_actions
|
||||
local subfooter_actions =
|
||||
Gui.element{
|
||||
local subfooter_actions = Gui.element("task_list_subfooter_actions")
|
||||
:draw{
|
||||
type = "flow",
|
||||
name = "actions",
|
||||
}
|
||||
|
||||
--- Button element with a flow around it to fix duplicate name inside of the scroll flow
|
||||
-- @element task_list_item
|
||||
local task_list_item =
|
||||
Gui.element(
|
||||
function(definition, parent, task)
|
||||
local task_list_item = Gui.element("task_list_item")
|
||||
:draw(
|
||||
function(def, parent, task)
|
||||
local flow = parent.add{
|
||||
type = "flow",
|
||||
name = "task-" .. task.task_id,
|
||||
@@ -187,7 +183,7 @@ local task_list_item =
|
||||
flow.style.horizontally_stretchable = true
|
||||
|
||||
local button = flow.add{
|
||||
name = definition.name,
|
||||
name = def.name,
|
||||
type = "button",
|
||||
style = "list_box_item",
|
||||
caption = task.title,
|
||||
@@ -199,17 +195,18 @@ local task_list_item =
|
||||
|
||||
return button
|
||||
end
|
||||
):on_click(
|
||||
function(player, element, _)
|
||||
)
|
||||
:on_click(
|
||||
function(def, player, element)
|
||||
local task_id = element.parent.caption
|
||||
PlayerSelected:set(player, task_id)
|
||||
end
|
||||
):static_name(Gui.unique_static_name)
|
||||
)
|
||||
|
||||
--- Scrollable list of all tasks
|
||||
-- @element task_list
|
||||
local task_list =
|
||||
Gui.element(
|
||||
local task_list = Gui.element("task_list")
|
||||
:draw(
|
||||
function(_, parent)
|
||||
local scroll_pane =
|
||||
parent.add{
|
||||
@@ -239,15 +236,16 @@ local task_list =
|
||||
|
||||
--- Button element inside the task view footer to start editing a task
|
||||
-- @element task_view_edit_button
|
||||
local task_view_edit_button =
|
||||
Gui.element{
|
||||
local task_view_edit_button = Gui.element("task_view_edit_button")
|
||||
:draw{
|
||||
type = "button",
|
||||
name = Gui.unique_static_name,
|
||||
name = Gui.property_from_name,
|
||||
caption = { "", "[img=utility/rename_icon] ", { "task-list.edit" } },
|
||||
tooltip = { "task-list.edit-tooltip" },
|
||||
style = "shortcut_bar_button",
|
||||
}:style(Styles.footer_button):on_click(
|
||||
function(player, _, _)
|
||||
function(def, event, element)
|
||||
local player = Gui.get_player(event)
|
||||
local selected = PlayerSelected:get(player)
|
||||
PlayerIsEditing:set(player, true)
|
||||
|
||||
@@ -257,30 +255,33 @@ local task_view_edit_button =
|
||||
|
||||
--- Button to close the task view footer
|
||||
-- @element task_view_close_button
|
||||
local task_view_close_button =
|
||||
Gui.element{
|
||||
local task_view_close_button = Gui.element("task_view_close_button")
|
||||
:draw{
|
||||
type = "sprite-button",
|
||||
sprite = "utility/collapse",
|
||||
style = "frame_action_button",
|
||||
tooltip = { "task-list.close-tooltip" },
|
||||
}
|
||||
:style(Styles.sprite22):on_click(
|
||||
function(player, _, _)
|
||||
:style(Styles.sprite22)
|
||||
:on_click(
|
||||
function(def, player, element)
|
||||
PlayerSelected:set(player, nil)
|
||||
end
|
||||
)
|
||||
|
||||
--- Button to delete the task inside the task view footer
|
||||
-- @element task_view_delete_button
|
||||
local task_view_delete_button =
|
||||
Gui.element{
|
||||
local task_view_delete_button = Gui.element("task_view_delete_button")
|
||||
:draw{
|
||||
type = "button",
|
||||
name = Gui.unique_static_name,
|
||||
name = Gui.property_from_name,
|
||||
caption = { "", "[img=utility/trash] ", { "task-list.delete" } },
|
||||
tooltip = { "task-list.delete-tooltip" },
|
||||
style = "shortcut_bar_button_red",
|
||||
}:style(Styles.footer_button):on_click(
|
||||
function(player, _, _)
|
||||
}
|
||||
:style(Styles.footer_button)
|
||||
:on_click(
|
||||
function(def, player, element)
|
||||
local selected = PlayerSelected:get(player)
|
||||
PlayerSelected:set(player, nil)
|
||||
Tasks.remove_task(selected)
|
||||
@@ -289,13 +290,13 @@ local task_view_delete_button =
|
||||
|
||||
--- Subfooter inside the tasklist container that holds all the elements for viewing a task
|
||||
-- @element task_view_footer
|
||||
local task_view_footer =
|
||||
Gui.element(
|
||||
local task_view_footer = Gui.element("task_view_footer")
|
||||
:draw(
|
||||
function(_, parent)
|
||||
local footer = subfooter_frame(parent, "view")
|
||||
local flow = footer.add{ type = "flow" }
|
||||
subfooter_label(flow, { "task-list.view-footer-header" })
|
||||
local alignment = Gui.alignment(flow)
|
||||
local alignment = Gui.elements.aligned_flow(flow)
|
||||
task_view_close_button(alignment)
|
||||
local title_label =
|
||||
footer.add{
|
||||
@@ -345,9 +346,9 @@ local task_create_confirm_button
|
||||
|
||||
--- Textfield element used in both the task create and edit footers
|
||||
-- @element task_message_textfield
|
||||
local task_message_textfield =
|
||||
Gui.element{
|
||||
name = Gui.unique_static_name,
|
||||
local task_message_textfield = Gui.element("task_message_textfield")
|
||||
:draw{
|
||||
name = Gui.property_from_name,
|
||||
type = "text-box",
|
||||
text = "",
|
||||
}:style{
|
||||
@@ -356,7 +357,7 @@ local task_message_textfield =
|
||||
horizontally_stretchable = true,
|
||||
}
|
||||
:on_text_changed(
|
||||
function(player, element, _)
|
||||
function(def, player, element)
|
||||
local is_editing = PlayerIsEditing:get(player)
|
||||
local is_creating = PlayerIsCreating:get(player)
|
||||
|
||||
@@ -372,15 +373,17 @@ local task_message_textfield =
|
||||
|
||||
--- Button to confirm the changes inside the task edit footer
|
||||
-- @element task_edit_confirm_button
|
||||
task_edit_confirm_button =
|
||||
Gui.element{
|
||||
task_edit_confirm_button = Gui.element("task_edit_confirm_button")
|
||||
:draw{
|
||||
type = "button",
|
||||
name = Gui.unique_static_name,
|
||||
name = Gui.property_from_name,
|
||||
caption = { "", "[img=utility/check_mark] ", { "task-list.confirm" } },
|
||||
tooltip = { "task-list.confirm-tooltip" },
|
||||
style = "shortcut_bar_button_green",
|
||||
}:style(Styles.footer_button):on_click(
|
||||
function(player, element, _)
|
||||
}
|
||||
:style(Styles.footer_button)
|
||||
:on_click(
|
||||
function(def, player, element)
|
||||
local selected = PlayerSelected:get(player)
|
||||
PlayerIsEditing:set(player, false)
|
||||
local new_message = element.parent.parent[task_message_textfield.name].text
|
||||
@@ -392,14 +395,16 @@ task_edit_confirm_button =
|
||||
|
||||
--- Button to discard the changes inside the task edit footer
|
||||
-- @element edit_task_discard_button
|
||||
local edit_task_discard_button =
|
||||
Gui.element{
|
||||
local edit_task_discard_button = Gui.element("edit_task_discard_button")
|
||||
:draw{
|
||||
type = "button",
|
||||
caption = { "", "[img=utility/close_black] ", { "task-list.discard" } },
|
||||
tooltip = { "task-list.discard-tooltip" },
|
||||
style = "shortcut_bar_button_red",
|
||||
}:style(Styles.footer_button):on_click(
|
||||
function(player, _, _)
|
||||
}
|
||||
:style(Styles.footer_button)
|
||||
:on_click(
|
||||
function(def, player, element)
|
||||
local selected = PlayerSelected:get(player)
|
||||
Tasks.set_editing(selected, player.name, nil)
|
||||
PlayerIsEditing:set(player, false)
|
||||
@@ -408,8 +413,8 @@ local edit_task_discard_button =
|
||||
|
||||
--- Subfooter inside the tasklist container that holds all the elements for editing a task
|
||||
-- @element task_edit_footer
|
||||
local task_edit_footer =
|
||||
Gui.element(
|
||||
local task_edit_footer = Gui.element("task_edit_footer")
|
||||
:draw(
|
||||
function(_, parent)
|
||||
local footer = subfooter_frame(parent, "edit")
|
||||
subfooter_label(footer, { "task-list.edit-footer-header" })
|
||||
@@ -427,16 +432,18 @@ local task_edit_footer =
|
||||
|
||||
--- Button to confirm the changes inside the task create footer
|
||||
-- @element task_create_confirm_button
|
||||
task_create_confirm_button =
|
||||
Gui.element{
|
||||
task_create_confirm_button = Gui.element("task_create_confirm_button")
|
||||
:draw{
|
||||
type = "button",
|
||||
name = Gui.unique_static_name,
|
||||
name = Gui.property_from_name,
|
||||
caption = { "", "[img=utility/check_mark] ", { "task-list.confirm" } },
|
||||
tooltip = { "task-list.confirm-tooltip" },
|
||||
style = "shortcut_bar_button_green",
|
||||
enabled = false,
|
||||
}:style(Styles.footer_button):on_click(
|
||||
function(player, element, _)
|
||||
}
|
||||
:style(Styles.footer_button)
|
||||
:on_click(
|
||||
function(def, player, element)
|
||||
local message = element.parent.parent[task_message_textfield.name].text
|
||||
PlayerIsCreating:set(player, false)
|
||||
local parsed = parse_message(message)
|
||||
@@ -447,22 +454,24 @@ task_create_confirm_button =
|
||||
|
||||
--- Button to discard the changes inside the task create footer
|
||||
-- @element task_create_discard_button
|
||||
local task_create_discard_button =
|
||||
Gui.element{
|
||||
local task_create_discard_button = Gui.element("task_create_discard_button")
|
||||
:draw{
|
||||
type = "button",
|
||||
caption = { "", "[img=utility/close_black] ", { "task-list.discard" } },
|
||||
tooltip = { "task-list.discard-tooltip" },
|
||||
style = "shortcut_bar_button_red",
|
||||
}:style(Styles.footer_button):on_click(
|
||||
function(player, _, _)
|
||||
}
|
||||
:style(Styles.footer_button)
|
||||
:on_click(
|
||||
function(def, player, element)
|
||||
PlayerIsCreating:set(player, false)
|
||||
end
|
||||
)
|
||||
|
||||
--- Subfooter inside the tasklist container that holds all the elements to create a new task
|
||||
-- @element task_create_footer
|
||||
local task_create_footer =
|
||||
Gui.element(
|
||||
local task_create_footer = Gui.element("task_create_footer")
|
||||
:draw(
|
||||
function(_, parent)
|
||||
local footer = subfooter_frame(parent, "create")
|
||||
subfooter_label(footer, { "task-list.create-footer-header" })
|
||||
@@ -480,7 +489,7 @@ local task_create_footer =
|
||||
|
||||
--- Clear and repopulate the task list with all current tasks
|
||||
local repopulate_task_list = function(task_list_element)
|
||||
local force = Gui.get_player_from_element(task_list_element).force
|
||||
local force = Gui.get_player(task_list_element).force
|
||||
local task_ids = Tasks.get_force_task_ids(force.name)
|
||||
task_list_element.clear()
|
||||
|
||||
@@ -497,19 +506,22 @@ end
|
||||
|
||||
--- Main task list container for the left flow
|
||||
-- @element task_list_container
|
||||
local task_list_container =
|
||||
Gui.element(
|
||||
function(definition, parent)
|
||||
local task_list_container = Gui.element("task_list_container")
|
||||
:draw(
|
||||
function(def, parent)
|
||||
-- Draw the internal container
|
||||
local container = Gui.container(parent, definition.name, 268)
|
||||
local container = Gui.elements.container(parent, 268)
|
||||
container.style.maximal_width = 268
|
||||
container.style.minimal_width = 268
|
||||
|
||||
-- Draw the header
|
||||
local header = Gui.header(container, { "task-list.main-caption" }, { "task-list.sub-tooltip" }, true)
|
||||
local header = Gui.elements.header(container, {
|
||||
name = "header",
|
||||
caption = { "task-list.main-caption" },
|
||||
tooltip = { "task-list.sub-tooltip" },
|
||||
})
|
||||
|
||||
-- Draw the new task button
|
||||
local player = Gui.get_player_from_element(parent)
|
||||
local player = Gui.get_player(parent)
|
||||
local add_new_task_element = add_new_task(header)
|
||||
add_new_task_element.visible = check_player_permissions(player)
|
||||
|
||||
@@ -529,23 +541,22 @@ local task_list_container =
|
||||
-- Return the external container
|
||||
return container.parent
|
||||
end
|
||||
):static_name(Gui.unique_static_name):add_to_left_flow(
|
||||
function(player)
|
||||
local task_ids = Tasks.get_force_task_ids(player.force.name)
|
||||
return #task_ids > 0
|
||||
end
|
||||
)
|
||||
|
||||
--- Button on the top flow used to toggle the task list container
|
||||
-- @element toggle_left_element
|
||||
Gui.left_toolbar_button(
|
||||
"utility/not_enough_repair_packs_icon",
|
||||
{ "task-list.main-tooltip" },
|
||||
task_list_container,
|
||||
function(player)
|
||||
--- Add the element to the left flow with a toolbar button
|
||||
Gui.add_left_element(task_list_container, function(player)
|
||||
local task_ids = Tasks.get_force_task_ids(player.force.name)
|
||||
return #task_ids > 0
|
||||
end)
|
||||
Gui.toolbar.create_button{
|
||||
name = "task_list_toggle",
|
||||
left_element = task_list_container,
|
||||
sprite = "utility/not_enough_repair_packs_icon",
|
||||
tooltip = { "task-list.main-tooltip" },
|
||||
visible = function(player, element)
|
||||
return Roles.player_allowed(player, "gui/task-list")
|
||||
end
|
||||
)
|
||||
}
|
||||
|
||||
-- Function to update a single task and some of the elements inside the container
|
||||
local update_task = function(player, task_list_element, task_id)
|
||||
@@ -575,8 +586,8 @@ end
|
||||
-- Update the footer task edit view
|
||||
local update_task_edit_footer = function(player, task_id)
|
||||
local task = Tasks.get_task(task_id)
|
||||
local frame = Gui.get_left_element(player, task_list_container)
|
||||
local edit_flow = frame.container.edit
|
||||
local container = Gui.get_left_element(task_list_container, player)
|
||||
local edit_flow = container.frame.edit
|
||||
|
||||
local message_element = edit_flow[task_message_textfield.name]
|
||||
|
||||
@@ -587,8 +598,8 @@ end
|
||||
-- Update the footer task view
|
||||
local update_task_view_footer = function(player, task_id)
|
||||
local task = Tasks.get_task(task_id)
|
||||
local frame = Gui.get_left_element(player, task_list_container)
|
||||
local view_flow = frame.container.view
|
||||
local container = Gui.get_left_element(task_list_container, player)
|
||||
local view_flow = container.frame.view
|
||||
local has_permission = check_player_permissions(player, task)
|
||||
|
||||
local title_element = view_flow.title
|
||||
@@ -633,8 +644,8 @@ Tasks.on_update(
|
||||
end
|
||||
end
|
||||
|
||||
local frame = Gui.get_left_element(player, task_list_container)
|
||||
local task_list_element = frame.container.scroll.task_list
|
||||
local container = Gui.get_left_element(task_list_container, player)
|
||||
local task_list_element = container.frame.scroll.task_list
|
||||
|
||||
-- Update the task that was changed
|
||||
update_task(player, task_list_element, task_id)
|
||||
@@ -647,12 +658,12 @@ PlayerIsCreating:on_update(
|
||||
function(player_name, curr_state, _)
|
||||
local player = game.players[player_name]
|
||||
|
||||
local frame = Gui.get_left_element(player, task_list_container)
|
||||
local create = frame.container.create
|
||||
local container = Gui.get_left_element(task_list_container, player)
|
||||
local create = container.frame.create
|
||||
|
||||
-- Clear the textfield
|
||||
local message_element = frame.container.create[task_message_textfield.name]
|
||||
local confirm_button_element = frame.container.create.actions[task_create_confirm_button.name]
|
||||
local message_element = container.frame.create[task_message_textfield.name]
|
||||
local confirm_button_element = container.frame.create.actions[task_create_confirm_button.name]
|
||||
message_element.focus()
|
||||
message_element.text = ""
|
||||
confirm_button_element.enabled = false
|
||||
@@ -670,10 +681,10 @@ PlayerSelected:on_update(
|
||||
function(player_name, curr_state, prev_state)
|
||||
local player = game.players[player_name]
|
||||
|
||||
local frame = Gui.get_left_element(player, task_list_container)
|
||||
local task_list_element = frame.container.scroll.task_list
|
||||
local view_flow = frame.container.view
|
||||
local edit_flow = frame.container.edit
|
||||
local container = Gui.get_left_element(task_list_container, player)
|
||||
local task_list_element = container.frame.scroll.task_list
|
||||
local view_flow = container.frame.view
|
||||
local edit_flow = container.frame.edit
|
||||
local is_editing = PlayerIsEditing:get(player)
|
||||
local is_creating = PlayerIsCreating:get(player)
|
||||
|
||||
@@ -721,9 +732,9 @@ PlayerIsEditing:on_update(
|
||||
function(player_name, curr_state, _)
|
||||
local player = game.players[player_name]
|
||||
|
||||
local frame = Gui.get_left_element(player, task_list_container)
|
||||
local view_flow = frame.container.view
|
||||
local edit_flow = frame.container.edit
|
||||
local container = Gui.get_left_element(task_list_container, player)
|
||||
local view_flow = container.frame.view
|
||||
local edit_flow = container.frame.edit
|
||||
|
||||
local selected = PlayerSelected:get(player)
|
||||
if curr_state then
|
||||
@@ -740,7 +751,7 @@ PlayerIsEditing:on_update(
|
||||
--- Makes sure the right buttons are present when roles change
|
||||
local function role_update_event(event)
|
||||
local player = game.players[event.player_index]
|
||||
local container = Gui.get_left_element(player, task_list_container).container
|
||||
local frame = Gui.get_left_element(task_list_container, player).frame
|
||||
-- Update the view task
|
||||
local selected = PlayerSelected:get(player)
|
||||
if selected then
|
||||
@@ -752,7 +763,7 @@ local function role_update_event(event)
|
||||
|
||||
-- Update the new task button and create footer in case the user can now add them
|
||||
local has_permission = check_player_permissions(player)
|
||||
local add_new_task_element = container.header.alignment[add_new_task.name]
|
||||
local add_new_task_element = frame.header.flow[add_new_task.name]
|
||||
add_new_task_element.visible = has_permission
|
||||
local is_creating = PlayerIsCreating:get(player)
|
||||
if is_creating and not has_permission then
|
||||
@@ -767,8 +778,8 @@ Event.add(Roles.events.on_role_unassigned, role_update_event)
|
||||
local function reset_task_list(event)
|
||||
-- Repopulate the task list
|
||||
local player = game.players[event.player_index]
|
||||
local frame = Gui.get_left_element(player, task_list_container)
|
||||
local task_list_element = frame.container.scroll.task_list
|
||||
local container = Gui.get_left_element(task_list_container, player)
|
||||
local task_list_element = container.frame.scroll.task_list
|
||||
repopulate_task_list(task_list_element)
|
||||
|
||||
-- Check if the selected task is still valid
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
]]
|
||||
|
||||
local ExpUtil = require("modules/exp_util")
|
||||
local Gui = require("modules/exp_legacy/expcore/gui") --- @dep expcore.gui
|
||||
local Gui = require("modules/exp_gui")
|
||||
local Roles = require("modules.exp_legacy.expcore.roles") --- @dep expcore.roles
|
||||
local Event = require("modules/exp_legacy/utils/event") --- @dep utils.event
|
||||
local Selection = require("modules/exp_legacy/modules/control/selection") --- @dep modules.control.selection
|
||||
@@ -27,10 +27,10 @@ local style = {
|
||||
|
||||
--- Arty label
|
||||
-- @element tool_gui_arty_l
|
||||
local tool_gui_arty_l =
|
||||
Gui.element{
|
||||
local tool_gui_arty_l = Gui.element("tool_gui_arty_l")
|
||||
:draw{
|
||||
type = "label",
|
||||
name = "tool_arty_l",
|
||||
name = Gui.property_from_name,
|
||||
caption = { "tool.artillery" },
|
||||
tooltip = { "tool.artillery-tooltip" },
|
||||
style = "heading_2_label"
|
||||
@@ -40,14 +40,14 @@ local tool_gui_arty_l =
|
||||
|
||||
--- Arty button
|
||||
-- @element tool_gui_arty_b
|
||||
local tool_gui_arty_b =
|
||||
Gui.element{
|
||||
local tool_gui_arty_b = Gui.element("tool_gui_arty_b")
|
||||
:draw{
|
||||
type = "button",
|
||||
name = "tool_arty_b",
|
||||
name = Gui.property_from_name,
|
||||
caption = { "tool.apply" }
|
||||
}:style(
|
||||
style.button
|
||||
):on_click(function(player, _, _)
|
||||
):on_click(function(def, player, element)
|
||||
if Selection.is_selecting(player, SelectionArtyArea) then
|
||||
Selection.stop(player)
|
||||
|
||||
@@ -59,10 +59,10 @@ local tool_gui_arty_b =
|
||||
|
||||
--- Waterfill label
|
||||
-- @element tool_gui_waterfill_l
|
||||
local tool_gui_waterfill_l =
|
||||
Gui.element{
|
||||
local tool_gui_waterfill_l = Gui.element("tool_gui_waterfill_l")
|
||||
:draw{
|
||||
type = "label",
|
||||
name = "tool_waterfill_l",
|
||||
name = Gui.property_from_name,
|
||||
caption = { "tool.waterfill" },
|
||||
tooltip = { "tool.waterfill-tooltip" },
|
||||
style = "heading_2_label"
|
||||
@@ -72,14 +72,14 @@ local tool_gui_waterfill_l =
|
||||
|
||||
--- Waterfill button
|
||||
-- @element tool_gui_waterfill_b
|
||||
local tool_gui_waterfill_b =
|
||||
Gui.element{
|
||||
local tool_gui_waterfill_b = Gui.element("tool_gui_waterfill_b")
|
||||
:draw{
|
||||
type = "button",
|
||||
name = "tool_waterfill_b",
|
||||
name = Gui.property_from_name,
|
||||
caption = { "tool.apply" }
|
||||
}:style(
|
||||
style.button
|
||||
):on_click(function(player, _, _)
|
||||
):on_click(function(def, player, element)
|
||||
if Selection.is_selecting(player, SelectionWaterfillArea) then
|
||||
Selection.stop(player)
|
||||
return player.print{ "exp-commands_waterfill.exit" }
|
||||
@@ -98,10 +98,10 @@ local tool_gui_waterfill_b =
|
||||
|
||||
--- Train label
|
||||
-- @element tool_gui_train_l
|
||||
local tool_gui_train_l =
|
||||
Gui.element{
|
||||
local tool_gui_train_l = Gui.element("tool_gui_train_l")
|
||||
:draw{
|
||||
type = "label",
|
||||
name = "tool_train_l",
|
||||
name = Gui.property_from_name,
|
||||
caption = { "tool.train" },
|
||||
tooltip = { "tool.train-tooltip" },
|
||||
style = "heading_2_label"
|
||||
@@ -111,23 +111,23 @@ local tool_gui_train_l =
|
||||
|
||||
--- Train button
|
||||
-- @element tool_gui_train_b
|
||||
local tool_gui_train_b =
|
||||
Gui.element{
|
||||
local tool_gui_train_b = Gui.element("tool_gui_train_b")
|
||||
:draw{
|
||||
type = "button",
|
||||
name = "tool_train_b",
|
||||
name = Gui.property_from_name,
|
||||
caption = { "tool.apply" }
|
||||
}:style(
|
||||
style.button
|
||||
):on_click(function(player, _, _)
|
||||
):on_click(function(def, player, element)
|
||||
addon_train.manual(player)
|
||||
end)
|
||||
|
||||
--- Research label
|
||||
-- @element tool_gui_research_l
|
||||
local tool_gui_research_l =
|
||||
Gui.element{
|
||||
local tool_gui_research_l = Gui.element("tool_gui_research_l")
|
||||
:draw{
|
||||
type = "label",
|
||||
name = "tool_research_l",
|
||||
name = Gui.property_from_name,
|
||||
caption = { "tool.research" },
|
||||
tooltip = { "tool.research-tooltip" },
|
||||
style = "heading_2_label"
|
||||
@@ -137,18 +137,18 @@ local tool_gui_research_l =
|
||||
|
||||
--- Research button
|
||||
-- @element tool_gui_research_b
|
||||
local tool_gui_research_b =
|
||||
Gui.element{
|
||||
local tool_gui_research_b = Gui.element("tool_gui_research_b")
|
||||
:draw{
|
||||
type = "button",
|
||||
name = "tool_research_b",
|
||||
name = Gui.property_from_name,
|
||||
caption = { "tool.apply" }
|
||||
}:style(
|
||||
style.button
|
||||
):on_click(function(player, _, _)
|
||||
):on_click(function(def, player, element)
|
||||
local enabled = addon_research.set_auto_research()
|
||||
|
||||
if enabled then
|
||||
addon_research.res_queue(player.force, true)
|
||||
addon_research.res_queue(player.force --[[ @as LuaForce ]], true)
|
||||
end
|
||||
|
||||
local player_name = ExpUtil.format_player_name_locale(player)
|
||||
@@ -157,10 +157,10 @@ local tool_gui_research_b =
|
||||
|
||||
--- Spawn label
|
||||
-- @element tool_gui_spawn_l
|
||||
local tool_gui_spawn_l =
|
||||
Gui.element{
|
||||
local tool_gui_spawn_l = Gui.element("tool_gui_spawn_l")
|
||||
:draw{
|
||||
type = "label",
|
||||
name = "tool_spawn_l",
|
||||
name = Gui.property_from_name,
|
||||
caption = { "tool.spawn" },
|
||||
tooltip = { "tool.spawn-tooltip" },
|
||||
style = "heading_2_label"
|
||||
@@ -170,14 +170,14 @@ local tool_gui_spawn_l =
|
||||
|
||||
--- Spawn button
|
||||
-- @element tool_gui_spawn_b
|
||||
local tool_gui_spawn_b =
|
||||
Gui.element{
|
||||
local tool_gui_spawn_b = Gui.element("tool_gui_spawn_b")
|
||||
:draw{
|
||||
type = "button",
|
||||
name = "tool_spawn_b",
|
||||
name = Gui.property_from_name,
|
||||
caption = { "tool.apply" }
|
||||
}:style(
|
||||
style.button
|
||||
):on_click(function(player, _, _)
|
||||
):on_click(function(def, player, element)
|
||||
if not player.character
|
||||
or player.character.health <= 0
|
||||
or not ExpUtil.teleport_player(player, game.surfaces.nauvis, { 0, 0 }, "dismount") then
|
||||
@@ -185,9 +185,9 @@ local tool_gui_spawn_b =
|
||||
end
|
||||
end)
|
||||
|
||||
local function tool_perm(player)
|
||||
local frame = Gui.get_left_element(player, tool_container)
|
||||
local disp = frame.container["tool_st"].disp.table
|
||||
local function tool_perm(player, container)
|
||||
container = container or Gui.get_left_element(tool_container, player)
|
||||
local disp = container.frame.tool_st.disp.table
|
||||
local allowed
|
||||
|
||||
allowed = Roles.player_allowed(player, "command/artillery")
|
||||
@@ -213,10 +213,10 @@ end
|
||||
|
||||
--- A vertical flow containing all the tool
|
||||
-- @element tool_set
|
||||
local tool_set =
|
||||
Gui.element(function(_, parent, name)
|
||||
local tool_set = Gui.element("tool_set")
|
||||
:draw(function(_, parent, name)
|
||||
local tool_set = parent.add{ type = "flow", direction = "vertical", name = name }
|
||||
local disp = Gui.scroll_table(tool_set, 240, 2, "disp")
|
||||
local disp = Gui.elements.scroll_table(tool_set, 240, 2, "disp")
|
||||
|
||||
tool_gui_arty_l(disp)
|
||||
tool_gui_arty_b(disp)
|
||||
@@ -238,25 +238,29 @@ local tool_set =
|
||||
|
||||
--- The main container for the tool gui
|
||||
-- @element tool_container
|
||||
tool_container =
|
||||
Gui.element(function(definition, parent)
|
||||
local player = Gui.get_player_from_element(parent)
|
||||
local container = Gui.container(parent, definition.name, 240)
|
||||
tool_container = Gui.element("tool_container")
|
||||
:draw(function(def, parent)
|
||||
local player = Gui.get_player(parent)
|
||||
local container = Gui.elements.container(parent, 240)
|
||||
|
||||
tool_set(container, "tool_st")
|
||||
|
||||
tool_perm(player)
|
||||
tool_perm(player, container.parent)
|
||||
|
||||
return container.parent
|
||||
end)
|
||||
:static_name(Gui.unique_static_name)
|
||||
:add_to_left_flow()
|
||||
|
||||
--- Button on the top flow used to toggle the tool container
|
||||
-- @element toggle_left_element
|
||||
Gui.left_toolbar_button("item/repair-pack", { "tool.main-tooltip" }, tool_container, function(player)
|
||||
return Roles.player_allowed(player, "gui/tool")
|
||||
end)
|
||||
--- Add the element to the left flow with a toolbar button
|
||||
Gui.add_left_element(tool_container, false)
|
||||
Gui.toolbar.create_button{
|
||||
name = "tool_toggle",
|
||||
left_element = tool_container,
|
||||
sprite = "item/repair-pack",
|
||||
tooltip = { "tool.main-tooltip" },
|
||||
visible = function(player, element)
|
||||
return Roles.player_allowed(player, "gui/tool")
|
||||
end
|
||||
}
|
||||
|
||||
Event.add(Roles.events.on_role_assigned, function(event)
|
||||
tool_perm(game.players[event.player_index])
|
||||
|
||||
@@ -1,528 +0,0 @@
|
||||
local Gui = require("modules.exp_legacy.expcore.gui") --- @dep expcore.gui
|
||||
local PlayerData = require("modules.exp_legacy.expcore.player_data") --- @dep expcore.player_data
|
||||
|
||||
-- Used to store the state of the toolbar when a player leaves
|
||||
local ToolbarState = PlayerData.Settings:combine("ToolbarState")
|
||||
ToolbarState:set_metadata{
|
||||
stringify = function(value)
|
||||
local buttons, favourites = 0, 0
|
||||
for _, state in ipairs(value) do
|
||||
buttons = buttons + 1
|
||||
if state.favourite then
|
||||
favourites = favourites + 1
|
||||
end
|
||||
end
|
||||
|
||||
return string.format("Buttons: %d, Favourites: %d", buttons, favourites)
|
||||
end,
|
||||
}
|
||||
|
||||
-- Styles used for sprite buttons
|
||||
local button_size = 20
|
||||
local Styles = {
|
||||
header = Gui.sprite_style(22),
|
||||
item = Gui.sprite_style(button_size),
|
||||
}
|
||||
|
||||
--- Set the style of the fake toolbar element
|
||||
local function copy_style(src, dst)
|
||||
dst.style = src.style.name
|
||||
dst.style.height = button_size
|
||||
dst.style.width = button_size
|
||||
dst.style.padding = -2
|
||||
end
|
||||
|
||||
local toolbar_container, move_up, move_down, toggle_toolbar
|
||||
|
||||
--- Reorder the buttons relative to each other, this will update the datastore
|
||||
local function move_toolbar_button(player, item, offset)
|
||||
local old_index = item.get_index_in_parent()
|
||||
local new_index = old_index + offset
|
||||
|
||||
-- Ideally the following would all happen in on_update but this had too much latency
|
||||
-- Swap the position in the list
|
||||
local list = item.parent
|
||||
local other_item = list.children[new_index]
|
||||
list.swap_children(old_index, new_index)
|
||||
|
||||
-- Swap the position in the top flow, offset by 1 because of settings button
|
||||
local top_flow = Gui.get_top_flow(player)
|
||||
top_flow.swap_children(old_index + 1, new_index + 1)
|
||||
|
||||
-- Check if the element has a left element to move
|
||||
local element_define = Gui.defines[item.tags.top_element_uid]
|
||||
local other_define = Gui.defines[other_item.tags.top_element_uid]
|
||||
if element_define.left_flow_element and other_define.left_flow_element then
|
||||
local left_element = Gui.get_left_element(player, element_define.left_flow_element)
|
||||
local other_left_element = Gui.get_left_element(player, other_define.left_flow_element)
|
||||
local left_index = left_element.get_index_in_parent()
|
||||
local other_index = other_left_element.get_index_in_parent()
|
||||
left_element.parent.swap_children(left_index, other_index)
|
||||
end
|
||||
|
||||
-- If we are moving in/out of first/last place we need to update the move buttons
|
||||
local last_index = #list.children
|
||||
if old_index == 1 then -- Moving out of index 1
|
||||
other_item.move[move_up.name].enabled = false
|
||||
item.move[move_up.name].enabled = true
|
||||
elseif new_index == 1 then -- Moving into index 1
|
||||
other_item.move[move_up.name].enabled = true
|
||||
item.move[move_up.name].enabled = false
|
||||
elseif old_index == last_index then -- Moving out of the last index
|
||||
other_item.move[move_down.name].enabled = false
|
||||
item.move[move_down.name].enabled = true
|
||||
elseif new_index == last_index then -- Moving into the last index
|
||||
other_item.move[move_down.name].enabled = true
|
||||
item.move[move_down.name].enabled = false
|
||||
end
|
||||
|
||||
-- Update the datastore state
|
||||
ToolbarState:update(player, function(_, order)
|
||||
local tmp = order[old_index]
|
||||
order[old_index] = order[new_index]
|
||||
order[new_index] = tmp
|
||||
end)
|
||||
end
|
||||
|
||||
--- Reorder the toolbar buttons
|
||||
local function reorder_toolbar_menu(player)
|
||||
local frame = Gui.get_left_element(player, toolbar_container)
|
||||
local list = frame.container.scroll.list
|
||||
local order = ToolbarState:get(player)
|
||||
local last_index = #order
|
||||
|
||||
-- Reorder the buttons
|
||||
for index, state in ipairs(order) do
|
||||
local element_define = Gui.defines[state.element_uid]
|
||||
|
||||
-- Switch item order
|
||||
local item = list[element_define.name]
|
||||
list.swap_children(index, item.get_index_in_parent())
|
||||
|
||||
-- Check if the player is allowed to see the button
|
||||
local allowed = element_define.authenticator
|
||||
if type(allowed) == "function" then allowed = allowed(player) end
|
||||
|
||||
-- Update the checkbox state and item visibility
|
||||
local toolbar_button = Gui.get_top_element(player, element_define)
|
||||
toolbar_button.visible = allowed and state.favourite or false
|
||||
item.checkbox.state = state.favourite
|
||||
|
||||
-- Update the state if the move buttons
|
||||
item.move[move_up.name].enabled = index ~= 1
|
||||
item.move[move_down.name].enabled = index ~= last_index
|
||||
end
|
||||
|
||||
-- Update the state of the toggle button
|
||||
local button = frame.container.header.alignment[toggle_toolbar.name]
|
||||
button.enabled = Gui.top_flow_has_visible_elements(player)
|
||||
button.toggled = Gui.get_top_flow(player).parent.visible
|
||||
end
|
||||
|
||||
--- Resets the toolbar to its default state when pressed
|
||||
-- @element reset_toolbar
|
||||
local reset_toolbar =
|
||||
Gui.element{
|
||||
type = "sprite-button",
|
||||
sprite = "utility/reset",
|
||||
style = "shortcut_bar_button_red",
|
||||
tooltip = { "toolbar.reset" },
|
||||
name = Gui.unique_static_name,
|
||||
}
|
||||
:style(Gui.sprite_style(Styles.header.width, -1))
|
||||
:on_click(function(player)
|
||||
ToolbarState:set(player, nil)
|
||||
Gui.toggle_top_flow(player, true)
|
||||
reorder_toolbar_menu(player)
|
||||
end)
|
||||
|
||||
--- Replaces the default method for opening and closing the toolbar
|
||||
-- @element toggle_toolbar
|
||||
toggle_toolbar =
|
||||
Gui.element{
|
||||
type = "sprite-button",
|
||||
sprite = "utility/bookmark",
|
||||
tooltip = { "toolbar.toggle" },
|
||||
style = "tool_button",
|
||||
auto_toggle = true,
|
||||
name = Gui.unique_static_name,
|
||||
}
|
||||
:style(Styles.header)
|
||||
:on_click(function(player, element)
|
||||
Gui.toggle_top_flow(player, element.toggled)
|
||||
end)
|
||||
|
||||
--- Move an element up the list
|
||||
-- @element move_up
|
||||
move_up =
|
||||
Gui.element{
|
||||
type = "sprite-button",
|
||||
sprite = "utility/speed_up",
|
||||
tooltip = { "toolbar.move-up" },
|
||||
name = Gui.unique_static_name,
|
||||
}
|
||||
:style(Styles.item)
|
||||
:on_click(function(player, element)
|
||||
local item = element.parent.parent
|
||||
move_toolbar_button(player, item, -1)
|
||||
end)
|
||||
|
||||
--- Move an element down the list
|
||||
-- @element move_down
|
||||
move_down =
|
||||
Gui.element{
|
||||
type = "sprite-button",
|
||||
sprite = "utility/speed_down",
|
||||
tooltip = { "toolbar.move-down" },
|
||||
name = Gui.unique_static_name,
|
||||
}
|
||||
:style(Styles.item)
|
||||
:on_click(function(player, element)
|
||||
local item = element.parent.parent
|
||||
move_toolbar_button(player, item, 1)
|
||||
end)
|
||||
|
||||
--- A flow which represents one item in the toolbar list
|
||||
-- @element toolbar_list_item
|
||||
local toolbar_list_item =
|
||||
Gui.element(function(definition, parent, element_define)
|
||||
local flow = parent.add{
|
||||
type = "frame",
|
||||
style = "shortcut_selection_row",
|
||||
name = element_define.name,
|
||||
tags = {
|
||||
top_element_uid = element_define.uid,
|
||||
},
|
||||
}
|
||||
flow.style.horizontally_stretchable = true
|
||||
flow.style.vertical_align = "center"
|
||||
|
||||
-- Add the button and the icon edit button
|
||||
local element = element_define(flow)
|
||||
local player = Gui.get_player_from_element(parent)
|
||||
local top_element = Gui.get_top_element(player, element_define)
|
||||
copy_style(top_element, element)
|
||||
|
||||
-- Add the checkbox that can toggle the visibility
|
||||
local checkbox = flow.add{
|
||||
type = "checkbox",
|
||||
name = "checkbox",
|
||||
caption = element_define.tooltip or element_define.caption or "None",
|
||||
state = top_element.visible or false,
|
||||
tags = {
|
||||
top_element_name = element_define.name,
|
||||
},
|
||||
}
|
||||
definition:triggers_events(checkbox)
|
||||
checkbox.style.width = 180
|
||||
|
||||
-- Add the buttons used to move the flow up and down
|
||||
local move_flow = flow.add{ type = "flow", name = "move" }
|
||||
move_flow.style.horizontal_spacing = 0
|
||||
move_up(move_flow)
|
||||
move_down(move_flow)
|
||||
|
||||
return definition:no_events(flow)
|
||||
end)
|
||||
:on_checked_changed(function(player, element)
|
||||
local top_flow = Gui.get_top_flow(player)
|
||||
local top_element = top_flow[element.tags.top_element_name]
|
||||
local had_visible = Gui.top_flow_has_visible_elements(player)
|
||||
top_element.visible = element.state
|
||||
|
||||
-- Check if we are on the edge case between 0 and 1 visible elements
|
||||
if element.state and not had_visible then
|
||||
Gui.toggle_top_flow(player, true)
|
||||
local container = element.parent.parent.parent.parent
|
||||
local button = container.header.alignment[toggle_toolbar.name]
|
||||
button.toggled = true
|
||||
button.enabled = true
|
||||
elseif not element.state and not Gui.top_flow_has_visible_elements(player) then
|
||||
Gui.toggle_top_flow(player, false)
|
||||
local container = element.parent.parent.parent.parent
|
||||
local button = container.header.alignment[toggle_toolbar.name]
|
||||
button.toggled = false
|
||||
button.enabled = false
|
||||
end
|
||||
|
||||
-- Update the datastore state
|
||||
ToolbarState:update(player, function(_, order)
|
||||
local index = element.parent.get_index_in_parent()
|
||||
order[index].favourite = element.state
|
||||
end)
|
||||
end)
|
||||
|
||||
--- Scrollable list of all toolbar buttons
|
||||
-- @element toolbar_list
|
||||
local toolbar_list =
|
||||
Gui.element(function(_, parent)
|
||||
-- This is a scroll pane for the list
|
||||
local scroll_pane = parent.add{
|
||||
name = "scroll",
|
||||
type = "scroll-pane",
|
||||
direction = "vertical",
|
||||
horizontal_scroll_policy = "never",
|
||||
vertical_scroll_policy = "auto",
|
||||
style = "scroll_pane_under_subheader",
|
||||
}
|
||||
scroll_pane.style.horizontally_stretchable = true
|
||||
scroll_pane.style.padding = 0
|
||||
scroll_pane.style.maximal_height = 224
|
||||
|
||||
-- This flow is the list, we need a linear list because of get_index_in_parent
|
||||
local flow = scroll_pane.add{
|
||||
name = "list",
|
||||
type = "flow",
|
||||
direction = "vertical",
|
||||
}
|
||||
flow.style.vertical_spacing = 0
|
||||
flow.style.horizontally_stretchable = true
|
||||
|
||||
return flow
|
||||
end)
|
||||
|
||||
--- Main toolbar container for the left flow
|
||||
-- @element toolbar_container
|
||||
toolbar_container =
|
||||
Gui.element(function(definition, parent)
|
||||
-- Draw the internal container
|
||||
local container = Gui.container(parent, definition.name, 268)
|
||||
container.style.maximal_width = 268
|
||||
container.style.minimal_width = 268
|
||||
|
||||
-- Draw the header
|
||||
local player = Gui.get_player_from_element(parent)
|
||||
local header = Gui.header(container, { "toolbar.main-caption" }, { "toolbar.main-tooltip" }, true)
|
||||
|
||||
-- Draw the toolbar control buttons
|
||||
local toggle_element = toggle_toolbar(header)
|
||||
toggle_element.toggled = Gui.get_top_flow(player).visible
|
||||
reset_toolbar(header)
|
||||
|
||||
-- Draw toolbar list element
|
||||
local list_element = toolbar_list(container)
|
||||
local flow_order = Gui.get_top_flow_order(player)
|
||||
|
||||
for _, element_define in ipairs(flow_order) do
|
||||
-- Ensure the element exists
|
||||
local element = list_element[element_define.name]
|
||||
if not element then
|
||||
element = toolbar_list_item(list_element, element_define)
|
||||
end
|
||||
|
||||
-- Set the visible state
|
||||
local allowed = element_define.authenticator
|
||||
if type(allowed) == "function" then allowed = allowed(player) end
|
||||
element.visible = allowed or false
|
||||
end
|
||||
|
||||
-- Set the state of the move buttons for the first and last element
|
||||
local children = list_element.children
|
||||
children[1].move[move_up.name].enabled = false
|
||||
children[#children].move[move_down.name].enabled = false
|
||||
|
||||
-- Return the external container
|
||||
return container.parent
|
||||
end)
|
||||
:static_name(Gui.unique_static_name)
|
||||
:add_to_left_flow(false)
|
||||
|
||||
--- Set the default value for the datastore
|
||||
local datastore_id_map = {}
|
||||
local toolbar_default_state = {}
|
||||
ToolbarState:set_default(toolbar_default_state)
|
||||
|
||||
--- Get the datastore id for this element define, to best of ability it should be unique between versions
|
||||
local function to_datastore_id(element_define)
|
||||
-- First try to use the tooltip locale string
|
||||
local tooltip = element_define.tooltip
|
||||
if type(tooltip) == "table" then
|
||||
return tooltip[1]:gsub("%.(.+)", "")
|
||||
end
|
||||
|
||||
-- Then try to use the caption or sprite
|
||||
return element_define.caption or element_define.sprite
|
||||
end
|
||||
|
||||
--- For all top element, register an on click which will copy their style
|
||||
for index, element_define in ipairs(Gui.top_elements) do
|
||||
-- This is a bit hacky, the gui system cant have multiple handlers registered
|
||||
local prev_handler = element_define[Gui.events.on_toolbar_button_toggled]
|
||||
|
||||
-- Add the handler for when the button is toggled
|
||||
element_define:on_event(Gui.events.on_toolbar_button_toggled, function(player, element, event)
|
||||
if prev_handler then prev_handler(player, element, event) end -- Kind of hacky but works
|
||||
local frame = Gui.get_left_element(player, toolbar_container)
|
||||
if not frame then return end -- Gui might not be loaded yet
|
||||
if not frame.container then
|
||||
log(frame.name)
|
||||
log(frame.parent.name)
|
||||
end
|
||||
local button = frame.container.scroll.list[element_define.name][element_define.name]
|
||||
local toolbar_button = Gui.get_top_element(player, element_define)
|
||||
copy_style(toolbar_button, button)
|
||||
end)
|
||||
|
||||
-- Insert the element into the id map
|
||||
local id = to_datastore_id(element_define)
|
||||
if datastore_id_map[id] then
|
||||
error(string.format("All toolbar elements need a unique id to be saved correctly, %d (%s) and %d (%s) share the id %s",
|
||||
datastore_id_map[id].uid, datastore_id_map[id].defined_at, element_define.uid, element_define.defined_at, id
|
||||
))
|
||||
end
|
||||
datastore_id_map[id] = element_define
|
||||
|
||||
-- Add the element to the default state
|
||||
table.insert(toolbar_default_state, {
|
||||
element_uid = element_define.uid,
|
||||
favourite = true,
|
||||
})
|
||||
end
|
||||
|
||||
--- Get the top order based on the players settings
|
||||
Gui.inject_top_flow_order(function(player)
|
||||
local order = ToolbarState:get(player)
|
||||
|
||||
local elements = {}
|
||||
for index, state in ipairs(order) do
|
||||
elements[index] = Gui.defines[state.element_uid]
|
||||
end
|
||||
|
||||
return elements
|
||||
end)
|
||||
|
||||
--- Get the left order based on the player settings, with toolbar menu first, and all remaining after
|
||||
Gui.inject_left_flow_order(function(player)
|
||||
local order = Gui.get_top_flow_order(player)
|
||||
local elements, element_map = { toolbar_container }, { [toolbar_container] = true }
|
||||
|
||||
-- Add the flows that have a top element
|
||||
for _, element_define in ipairs(order) do
|
||||
if element_define.left_flow_element then
|
||||
table.insert(elements, element_define.left_flow_element)
|
||||
element_map[element_define.left_flow_element] = true
|
||||
end
|
||||
end
|
||||
|
||||
-- Add the flows that dont have a top element
|
||||
for _, element_define in ipairs(Gui.left_elements) do
|
||||
if not element_map[element_define] then
|
||||
table.insert(elements, element_define)
|
||||
end
|
||||
end
|
||||
|
||||
return elements
|
||||
end)
|
||||
|
||||
--- Overwrite the default toggle behaviour and instead toggle this menu
|
||||
Gui.core_defines.hide_top_flow:on_click(function(player, _, _)
|
||||
Gui.toggle_left_element(player, toolbar_container)
|
||||
end)
|
||||
|
||||
--- Overwrite the default toggle behaviour and instead toggle this menu
|
||||
Gui.core_defines.show_top_flow:on_click(function(player, _, _)
|
||||
Gui.toggle_left_element(player, toolbar_container)
|
||||
end)
|
||||
|
||||
--- Overwrite the default update top flow
|
||||
local _update_top_flow = Gui.update_top_flow
|
||||
function Gui.update_top_flow(player)
|
||||
_update_top_flow(player) -- Call the original
|
||||
|
||||
local order = ToolbarState:get(player)
|
||||
for index, state in ipairs(order) do
|
||||
local element_define = Gui.defines[state.element_uid]
|
||||
local top_element = Gui.get_top_element(player, element_define)
|
||||
top_element.visible = top_element.visible and state.favourite or false
|
||||
end
|
||||
end
|
||||
|
||||
--- Uncompress the data to be more useable
|
||||
ToolbarState:on_load(function(player_name, value)
|
||||
-- If there is no value, do nothing
|
||||
if value == nil then return end
|
||||
|
||||
-- Create a hash map of the favourites
|
||||
local favourites = {}
|
||||
for _, id in ipairs(value[2]) do
|
||||
favourites[id] = true
|
||||
end
|
||||
|
||||
-- Read the order from the value
|
||||
local elements = {}
|
||||
local element_hash = {}
|
||||
for index, id in ipairs(value[1]) do
|
||||
local element = datastore_id_map[id]
|
||||
if element and not element_hash[element.uid] then
|
||||
element_hash[element.uid] = true
|
||||
elements[index] = {
|
||||
element_uid = element.uid,
|
||||
favourite = favourites[id] or false,
|
||||
}
|
||||
end
|
||||
end
|
||||
|
||||
-- Add any in the default state that are missing
|
||||
for _, state in ipairs(toolbar_default_state) do
|
||||
if not element_hash[state.element_uid] then
|
||||
table.insert(elements, table.deep_copy(state))
|
||||
end
|
||||
end
|
||||
|
||||
-- Create a hash map of the open left flows
|
||||
local left_flows = {}
|
||||
for _, id in ipairs(value[3]) do
|
||||
local element = datastore_id_map[id]
|
||||
if element.left_flow_element then
|
||||
left_flows[element.left_flow_element] = true
|
||||
end
|
||||
end
|
||||
|
||||
-- Set the visible state of all left flows
|
||||
local player = game.get_player(player_name)
|
||||
for _, left_element in ipairs(Gui.left_elements) do
|
||||
Gui.toggle_left_element(player, left_element, left_flows[left_element] or false)
|
||||
end
|
||||
|
||||
-- Set the toolbar visible state
|
||||
Gui.toggle_top_flow(player, value[4])
|
||||
|
||||
-- Set the data now and update now, ideally this would be on_update but that had too large of a latency
|
||||
ToolbarState:raw_set(player_name, elements)
|
||||
Gui.reorder_top_flow(player)
|
||||
Gui.reorder_left_flow(player)
|
||||
reorder_toolbar_menu(player)
|
||||
|
||||
return elements
|
||||
end)
|
||||
|
||||
--- Save the current state of the players toolbar menu
|
||||
ToolbarState:on_save(function(player_name, value)
|
||||
if value == nil then return nil end -- Don't save default
|
||||
local order, favourites, left_flows = {}, {}, {}
|
||||
|
||||
local player = game.get_player(player_name)
|
||||
local top_flow_open = Gui.get_top_flow(player).parent.visible
|
||||
|
||||
for index, state in ipairs(value) do
|
||||
-- Add the element to the order array
|
||||
local element_define = Gui.defines[state.element_uid]
|
||||
local id = to_datastore_id(element_define)
|
||||
order[index] = id
|
||||
|
||||
-- If its a favourite then insert it
|
||||
if state.favourite then
|
||||
table.insert(favourites, id)
|
||||
end
|
||||
|
||||
-- If it has a left flow and its open then insert it
|
||||
if element_define.left_flow_element then
|
||||
local left_element = Gui.get_left_element(player, element_define.left_flow_element)
|
||||
if left_element.visible then
|
||||
table.insert(left_flows, id)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
return { order, favourites, left_flows, top_flow_open }
|
||||
end)
|
||||
@@ -4,7 +4,7 @@
|
||||
@alias vlayer_container
|
||||
]]
|
||||
|
||||
local Gui = require("modules.exp_legacy.expcore.gui") --- @dep expcore.gui
|
||||
local Gui = require("modules/exp_gui")
|
||||
local Roles = require("modules.exp_legacy.expcore.roles") --- @dep expcore.roles
|
||||
local Event = require("modules/exp_legacy/utils/event") --- @dep utils.event
|
||||
local format_number = require("util").format_number --- @dep util
|
||||
@@ -81,8 +81,8 @@ Selection.on_selection(SelectionConvertArea, function(event)
|
||||
return nil
|
||||
end
|
||||
|
||||
local frame = Gui.get_left_element(player, vlayer_container)
|
||||
local disp = frame.container["vlayer_st_2"].disp.table
|
||||
local container = Gui.get_left_element(vlayer_container, player)
|
||||
local disp = container.frame["vlayer_st_2"].disp.table
|
||||
local target = vlayer_control_type_list[disp[vlayer_gui_control_type.name].selected_index]
|
||||
local entities
|
||||
|
||||
@@ -143,20 +143,20 @@ end)
|
||||
|
||||
--- Display label for the number of solar panels
|
||||
-- @element vlayer_gui_display_item_solar_name
|
||||
local vlayer_gui_display_item_solar_name =
|
||||
Gui.element{
|
||||
local vlayer_gui_display_item_solar_name = Gui.element("vlayer_gui_display_item_solar_name")
|
||||
:draw{
|
||||
type = "label",
|
||||
name = "vlayer_display_item_solar_name",
|
||||
name = Gui.property_from_name,
|
||||
caption = { "vlayer.display-item-solar" },
|
||||
style = "heading_2_label",
|
||||
}:style{
|
||||
width = 200,
|
||||
}
|
||||
|
||||
local vlayer_gui_display_item_solar_count =
|
||||
Gui.element{
|
||||
local vlayer_gui_display_item_solar_count = Gui.element("vlayer_gui_display_item_solar_count")
|
||||
:draw{
|
||||
type = "progressbar",
|
||||
name = "vlayer_display_item_solar_count",
|
||||
name = Gui.property_from_name,
|
||||
caption = "",
|
||||
value = 0,
|
||||
style = "electric_satisfaction_statistics_progressbar",
|
||||
@@ -167,20 +167,20 @@ local vlayer_gui_display_item_solar_count =
|
||||
|
||||
--- Display label for the number of accumulators
|
||||
-- @element vlayer_gui_display_item_accumulator_name
|
||||
local vlayer_gui_display_item_accumulator_name =
|
||||
Gui.element{
|
||||
local vlayer_gui_display_item_accumulator_name = Gui.element("vlayer_gui_display_item_accumulator_name")
|
||||
:draw{
|
||||
type = "label",
|
||||
name = "vlayer_display_item_accumulator_name",
|
||||
name = Gui.property_from_name,
|
||||
caption = { "vlayer.display-item-accumulator" },
|
||||
style = "heading_2_label",
|
||||
}:style{
|
||||
width = 200,
|
||||
}
|
||||
|
||||
local vlayer_gui_display_item_accumulator_count =
|
||||
Gui.element{
|
||||
local vlayer_gui_display_item_accumulator_count = Gui.element("vlayer_gui_display_item_accumulator_count")
|
||||
:draw{
|
||||
type = "progressbar",
|
||||
name = "vlayer_display_item_accumulator_count",
|
||||
name = Gui.property_from_name,
|
||||
caption = "",
|
||||
value = 0,
|
||||
style = "electric_satisfaction_statistics_progressbar",
|
||||
@@ -191,10 +191,10 @@ local vlayer_gui_display_item_accumulator_count =
|
||||
|
||||
--- Display label for the surface area
|
||||
-- @element vlayer_gui_display_signal_surface_area_name
|
||||
local vlayer_gui_display_signal_surface_area_name =
|
||||
Gui.element{
|
||||
local vlayer_gui_display_signal_surface_area_name = Gui.element("vlayer_gui_display_signal_surface_area_name")
|
||||
:draw{
|
||||
type = "label",
|
||||
name = "vlayer_display_signal_remaining_surface_area_name",
|
||||
name = Gui.property_from_name,
|
||||
caption = { "vlayer.display-remaining-surface-area" },
|
||||
tooltip = { "vlayer.display-remaining-surface-area-tooltip" },
|
||||
style = "heading_2_label",
|
||||
@@ -202,10 +202,10 @@ local vlayer_gui_display_signal_surface_area_name =
|
||||
width = 200,
|
||||
}
|
||||
|
||||
local vlayer_gui_display_signal_surface_area_count =
|
||||
Gui.element{
|
||||
local vlayer_gui_display_signal_surface_area_count = Gui.element("vlayer_gui_display_signal_surface_area_count")
|
||||
:draw{
|
||||
type = "progressbar",
|
||||
name = "vlayer_display_signal_surface_area_count",
|
||||
name = Gui.property_from_name,
|
||||
caption = "",
|
||||
value = 0,
|
||||
style = "electric_satisfaction_statistics_progressbar",
|
||||
@@ -216,10 +216,10 @@ local vlayer_gui_display_signal_surface_area_count =
|
||||
|
||||
--- Display label for the sustained energy production
|
||||
-- @element vlayer_gui_display_signal_sustained_name
|
||||
local vlayer_gui_display_signal_sustained_name =
|
||||
Gui.element{
|
||||
local vlayer_gui_display_signal_sustained_name = Gui.element("vlayer_gui_display_signal_sustained_name")
|
||||
:draw{
|
||||
type = "label",
|
||||
name = "vlayer_display_signal_sustained_name",
|
||||
name = Gui.property_from_name,
|
||||
caption = { "vlayer.display-sustained-production" },
|
||||
tooltip = { "vlayer.display-sustained-production-tooltip" },
|
||||
style = "heading_2_label",
|
||||
@@ -227,10 +227,10 @@ local vlayer_gui_display_signal_sustained_name =
|
||||
width = 200,
|
||||
}
|
||||
|
||||
local vlayer_gui_display_signal_sustained_count =
|
||||
Gui.element{
|
||||
local vlayer_gui_display_signal_sustained_count = Gui.element("vlayer_gui_display_signal_sustained_count")
|
||||
:draw{
|
||||
type = "progressbar",
|
||||
name = "vlayer_display_signal_sustained_count",
|
||||
name = Gui.property_from_name,
|
||||
caption = "",
|
||||
value = 0,
|
||||
style = "electric_satisfaction_statistics_progressbar",
|
||||
@@ -241,10 +241,10 @@ local vlayer_gui_display_signal_sustained_count =
|
||||
|
||||
--- Display label for the current energy production
|
||||
-- @element vlayer_gui_display_signal_production_name
|
||||
local vlayer_gui_display_signal_production_name =
|
||||
Gui.element{
|
||||
local vlayer_gui_display_signal_production_name = Gui.element("vlayer_gui_display_signal_production_name")
|
||||
:draw{
|
||||
type = "label",
|
||||
name = "vlayer_display_signal_production_name",
|
||||
name = Gui.property_from_name,
|
||||
caption = { "vlayer.display-current-production" },
|
||||
tooltip = { "vlayer.display-current-production-tooltip" },
|
||||
style = "heading_2_label",
|
||||
@@ -252,10 +252,10 @@ local vlayer_gui_display_signal_production_name =
|
||||
width = 200,
|
||||
}
|
||||
|
||||
local vlayer_gui_display_signal_production_count =
|
||||
Gui.element{
|
||||
local vlayer_gui_display_signal_production_count = Gui.element("vlayer_gui_display_signal_production_count")
|
||||
:draw{
|
||||
type = "progressbar",
|
||||
name = "vlayer_display_signal_production_count",
|
||||
name = Gui.property_from_name,
|
||||
caption = "",
|
||||
value = 0,
|
||||
style = "electric_satisfaction_statistics_progressbar",
|
||||
@@ -266,10 +266,10 @@ local vlayer_gui_display_signal_production_count =
|
||||
|
||||
--- Display label for the sustained energy capacity
|
||||
-- @element vlayer_gui_display_signal_capacity_name
|
||||
local vlayer_gui_display_signal_capacity_name =
|
||||
Gui.element{
|
||||
local vlayer_gui_display_signal_capacity_name = Gui.element("vlayer_gui_display_signal_capacity_name")
|
||||
:draw{
|
||||
type = "label",
|
||||
name = "vlayer_display_signal_capacity_name",
|
||||
name = Gui.property_from_name,
|
||||
caption = { "vlayer.display-current-capacity" },
|
||||
tooltip = { "vlayer.display-current-capacity-tooltip" },
|
||||
style = "heading_2_label",
|
||||
@@ -277,10 +277,10 @@ local vlayer_gui_display_signal_capacity_name =
|
||||
width = 200,
|
||||
}
|
||||
|
||||
local vlayer_gui_display_signal_capacity_count =
|
||||
Gui.element{
|
||||
local vlayer_gui_display_signal_capacity_count = Gui.element("vlayer_gui_display_signal_capacity_count")
|
||||
:draw{
|
||||
type = "progressbar",
|
||||
name = "vlayer_display_signal_capacity_count",
|
||||
name = Gui.property_from_name,
|
||||
caption = "",
|
||||
value = 0,
|
||||
style = "electric_satisfaction_statistics_progressbar",
|
||||
@@ -291,10 +291,10 @@ local vlayer_gui_display_signal_capacity_count =
|
||||
|
||||
--- A vertical flow containing all the displays labels and their counts
|
||||
-- @element vlayer_display_set
|
||||
local vlayer_display_set =
|
||||
Gui.element(function(_, parent, name)
|
||||
local vlayer_display_set = Gui.element("vlayer_display_set")
|
||||
:draw(function(_, parent, name)
|
||||
local vlayer_set = parent.add{ type = "flow", direction = "vertical", name = name }
|
||||
local disp = Gui.scroll_table(vlayer_set, 400, 2, "disp")
|
||||
local disp = Gui.elements.scroll_table(vlayer_set, 400, 2, "disp")
|
||||
|
||||
vlayer_gui_display_item_solar_name(disp)
|
||||
vlayer_gui_display_item_solar_count(disp)
|
||||
@@ -313,8 +313,8 @@ local vlayer_display_set =
|
||||
end)
|
||||
|
||||
local function vlayer_gui_list_refresh(player)
|
||||
local frame = Gui.get_left_element(player, vlayer_container)
|
||||
local disp = frame.container["vlayer_st_2"].disp.table
|
||||
local container = Gui.get_left_element(vlayer_container, player)
|
||||
local disp = container.frame["vlayer_st_2"].disp.table
|
||||
local target = disp[vlayer_gui_control_type.name].selected_index
|
||||
local full_list = {}
|
||||
|
||||
@@ -331,58 +331,59 @@ end
|
||||
|
||||
--- A drop down list filter by this type
|
||||
-- @element vlayer_gui_control_type
|
||||
vlayer_gui_control_type =
|
||||
Gui.element{
|
||||
vlayer_gui_control_type = Gui.element("vlayer_gui_control_type")
|
||||
:draw{
|
||||
type = "drop-down",
|
||||
name = Gui.unique_static_name,
|
||||
name = Gui.property_from_name,
|
||||
items = { { "vlayer.control-type-energy" }, { "vlayer.control-type-circuit" }, { "vlayer.control-type-storage-input" }, { "vlayer.control-type-storage-output" } },
|
||||
selected_index = 1,
|
||||
}:style{
|
||||
width = 200,
|
||||
}:on_selection_changed(function(player, _, _)
|
||||
}:on_selection_state_changed(function(def, player, element)
|
||||
vlayer_gui_list_refresh(player)
|
||||
end)
|
||||
|
||||
--- A drop down list to see the exact item to remove
|
||||
-- @element vlayer_gui_control_list
|
||||
vlayer_gui_control_list =
|
||||
Gui.element{
|
||||
vlayer_gui_control_list = Gui.element("vlayer_gui_control_list")
|
||||
:draw{
|
||||
type = "drop-down",
|
||||
name = Gui.unique_static_name,
|
||||
name = Gui.property_from_name,
|
||||
}:style{
|
||||
width = 200,
|
||||
}
|
||||
|
||||
--- A button to refresh the remove list
|
||||
-- @element vlayer_gui_control_refresh
|
||||
local vlayer_gui_control_refresh =
|
||||
Gui.element{
|
||||
local vlayer_gui_control_refresh = Gui.element("vlayer_gui_control_refresh")
|
||||
:draw{
|
||||
type = "button",
|
||||
name = Gui.unique_static_name,
|
||||
name = Gui.property_from_name,
|
||||
caption = { "vlayer.control-refresh" },
|
||||
}:style{
|
||||
width = 200,
|
||||
}:on_click(function(player, _, _)
|
||||
}:on_click(function(def, player, element)
|
||||
vlayer_gui_list_refresh(player)
|
||||
end)
|
||||
|
||||
--- A button to check if the item is the one wanted to remove
|
||||
-- @element vlayer_gui_control_see
|
||||
local vlayer_gui_control_see =
|
||||
Gui.element{
|
||||
local vlayer_gui_control_see = Gui.element("vlayer_gui_control_see")
|
||||
:draw{
|
||||
type = "button",
|
||||
name = Gui.unique_static_name,
|
||||
name = Gui.property_from_name,
|
||||
caption = { "vlayer.control-see" },
|
||||
}:style{
|
||||
width = 200,
|
||||
}:on_click(function(player, element, _)
|
||||
}:on_click(function(def, player, element, event)
|
||||
local target = element.parent[vlayer_gui_control_type.name].selected_index
|
||||
local n = element.parent[vlayer_gui_control_list.name].selected_index
|
||||
|
||||
|
||||
if target and vlayer_control_type_list[target] and n > 0 then
|
||||
local i = vlayer.get_interfaces()
|
||||
local entity = i[vlayer_control_type_list[target]][n]
|
||||
if entity and entity.valid then
|
||||
local player = Gui.get_player(event)
|
||||
player.set_controller{ type = defines.controllers.remote, position = entity.position, surface = entity.surface }
|
||||
player.print{ "vlayer.result-interface-location", { "vlayer.control-type-" .. vlayer_control_type_list[target]:gsub("_", "-") }, pos_to_gps_string(entity.position, entity.surface.name) }
|
||||
end
|
||||
@@ -391,14 +392,14 @@ local vlayer_gui_control_see =
|
||||
|
||||
--- A button used to build the vlayer interface
|
||||
-- @element vlayer_gui_control_build
|
||||
local vlayer_gui_control_build =
|
||||
Gui.element{
|
||||
local vlayer_gui_control_build = Gui.element("vlayer_gui_control_build")
|
||||
:draw{
|
||||
type = "button",
|
||||
name = Gui.unique_static_name,
|
||||
name = Gui.property_from_name,
|
||||
caption = { "vlayer.control-build" },
|
||||
}:style{
|
||||
width = 200,
|
||||
}:on_click(function(player, _, _)
|
||||
}:on_click(function(def, player, element)
|
||||
if Selection.is_selecting(player, SelectionConvertArea) then
|
||||
Selection.stop(player)
|
||||
player.print{ "vlayer.exit" }
|
||||
@@ -412,14 +413,14 @@ local vlayer_gui_control_build =
|
||||
|
||||
--- A button used to remove the vlayer interface
|
||||
-- @element vlayer_gui_control_remove
|
||||
local vlayer_gui_control_remove =
|
||||
Gui.element{
|
||||
local vlayer_gui_control_remove = Gui.element("vlayer_gui_control_remove")
|
||||
:draw{
|
||||
type = "button",
|
||||
name = Gui.unique_static_name,
|
||||
name = Gui.property_from_name,
|
||||
caption = { "vlayer.control-remove" },
|
||||
}:style{
|
||||
width = 200,
|
||||
}:on_click(function(player, element, _)
|
||||
}:on_click(function(def, player, element)
|
||||
local target = element.parent[vlayer_gui_control_type.name].selected_index
|
||||
local n = element.parent[vlayer_gui_control_list.name].selected_index
|
||||
|
||||
@@ -440,10 +441,10 @@ local vlayer_gui_control_remove =
|
||||
|
||||
--- A vertical flow containing all the control buttons
|
||||
-- @element vlayer_control_set
|
||||
local vlayer_control_set =
|
||||
Gui.element(function(_, parent, name)
|
||||
local vlayer_control_set = Gui.element("vlayer_control_set")
|
||||
:draw(function(_, parent, name)
|
||||
local vlayer_set = parent.add{ type = "flow", direction = "vertical", name = name }
|
||||
local disp = Gui.scroll_table(vlayer_set, 400, 2, "disp")
|
||||
local disp = Gui.elements.scroll_table(vlayer_set, 400, 2, "disp")
|
||||
|
||||
vlayer_gui_control_type(disp)
|
||||
vlayer_gui_control_list(disp)
|
||||
@@ -457,10 +458,10 @@ local vlayer_control_set =
|
||||
|
||||
--- The main container for the vlayer gui
|
||||
-- @element vlayer_container
|
||||
vlayer_container =
|
||||
Gui.element(function(definition, parent)
|
||||
local player = Gui.get_player_from_element(parent)
|
||||
local container = Gui.container(parent, definition.name, 400)
|
||||
vlayer_container = Gui.element("vlayer_container")
|
||||
:draw(function(definition, parent)
|
||||
local player = Gui.get_player(parent)
|
||||
local container = Gui.elements.container(parent, 400)
|
||||
|
||||
vlayer_display_set(container, "vlayer_st_1")
|
||||
local control_set = vlayer_control_set(container, "vlayer_st_2")
|
||||
@@ -468,21 +469,25 @@ vlayer_container =
|
||||
|
||||
return container.parent
|
||||
end)
|
||||
:static_name(Gui.unique_static_name)
|
||||
:add_to_left_flow()
|
||||
|
||||
--- Button on the top flow used to toggle the task list container
|
||||
-- @element toggle_left_element
|
||||
Gui.left_toolbar_button("entity/solar-panel", { "vlayer.main-tooltip" }, vlayer_container, function(player)
|
||||
return Roles.player_allowed(player, "gui/vlayer")
|
||||
end)
|
||||
--- Add the element to the left flow with a toolbar button
|
||||
Gui.add_left_element(vlayer_container, false)
|
||||
Gui.toolbar.create_button{
|
||||
name = "vlayer_toggle",
|
||||
left_element = vlayer_container,
|
||||
sprite = "entity/solar-panel",
|
||||
tooltip = { "vlayer.main-tooltip" },
|
||||
visible = function(player, element)
|
||||
return Roles.player_allowed(player, "gui/vlayer")
|
||||
end
|
||||
}
|
||||
|
||||
--- Update the visibly of the buttons based on a players roles
|
||||
local function role_update_event(event)
|
||||
local player = game.players[event.player_index]
|
||||
local visible = Roles.player_allowed(player, "gui/vlayer-edit")
|
||||
local frame = Gui.get_left_element(player, vlayer_container)
|
||||
frame.container["vlayer_st_2"].visible = visible
|
||||
local container = Gui.get_left_element(vlayer_container, player)
|
||||
container.frame["vlayer_st_2"].visible = visible
|
||||
end
|
||||
|
||||
Event.add(Roles.events.on_role_assigned, role_update_event)
|
||||
@@ -521,8 +526,8 @@ Event.on_nth_tick(config.update_tick_gui, function(_)
|
||||
}
|
||||
|
||||
for _, player in pairs(game.connected_players) do
|
||||
local frame = Gui.get_left_element(player, vlayer_container)
|
||||
local disp = frame.container["vlayer_st_1"].disp.table
|
||||
local container = Gui.get_left_element(vlayer_container, player)
|
||||
local disp = container.frame["vlayer_st_1"].disp.table
|
||||
|
||||
for k, v in pairs(vlayer_display) do
|
||||
disp[k].caption = v.cap
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
]]
|
||||
|
||||
local ExpUtil = require("modules/exp_util")
|
||||
local Gui = require("modules.exp_legacy.expcore.gui") --- @dep expcore.gui
|
||||
local Gui = require("modules/exp_gui")
|
||||
local Datastore = require("modules.exp_legacy.expcore.datastore") --- @dep expcore.datastore
|
||||
local Storage = require("modules/exp_util/storage")
|
||||
local Event = require("modules/exp_legacy/utils/event") --- @dep utils.event
|
||||
@@ -78,18 +78,18 @@ end
|
||||
|
||||
--- Will add a new warp to the list, checks if the player is too close to an existing one
|
||||
-- @element add_new_warp
|
||||
local add_new_warp =
|
||||
Gui.element{
|
||||
local add_new_warp = Gui.element("add_new_warp")
|
||||
:draw{
|
||||
type = "sprite-button",
|
||||
sprite = "utility/add",
|
||||
tooltip = { "warp-list.add-tooltip" },
|
||||
style = "shortcut_bar_button",
|
||||
name = Gui.unique_static_name,
|
||||
name = Gui.property_from_name,
|
||||
}
|
||||
:style(Styles.sprite22)
|
||||
:on_click(function(player, _)
|
||||
-- Add the new warp
|
||||
:on_click(function(def, player, element)
|
||||
if player.controller_type ~= defines.controllers.character then return end
|
||||
-- Add the new warp
|
||||
local force_name = player.force.name
|
||||
local surface = player.physical_surface
|
||||
local position = player.physical_position
|
||||
@@ -158,8 +158,8 @@ local add_new_warp =
|
||||
|
||||
--- Warp icon button, this will trigger a warp when the player is able to
|
||||
-- @element warp_icon_button
|
||||
local warp_icon_button =
|
||||
Gui.element(function(definition, parent, warp)
|
||||
local warp_icon_button = Gui.element("warp_icon_button")
|
||||
:draw(function(def, parent, warp)
|
||||
local warp_position = warp.position
|
||||
|
||||
-- The SpritePath type is not the same as the SignalID type
|
||||
@@ -172,14 +172,13 @@ local warp_icon_button =
|
||||
return parent.add{
|
||||
type = "sprite-button",
|
||||
sprite = sprite,
|
||||
name = definition.name,
|
||||
name = def.name,
|
||||
tooltip = { "warp-list.goto-tooltip", warp_position.x, warp_position.y },
|
||||
style = "slot_button",
|
||||
}
|
||||
end)
|
||||
:style(Styles.sprite32)
|
||||
:static_name(Gui.unique_static_name)
|
||||
:on_click(function(player, element, _)
|
||||
:on_click(function(def, player, element)
|
||||
if element.type == "choose-elem-button" then return end
|
||||
local warp_id = element.parent.caption
|
||||
Warps.teleport_player(warp_id, player)
|
||||
@@ -194,23 +193,22 @@ local warp_icon_button =
|
||||
|
||||
--- The button that is visible when the warp is in edit state
|
||||
-- @element warp_icon_editing
|
||||
local warp_icon_editing =
|
||||
Gui.element(function(definition, parent, warp)
|
||||
local warp_icon_editing = Gui.element("warp_icon_editing")
|
||||
:draw(function(def, parent, warp)
|
||||
return parent.add{
|
||||
name = definition.name,
|
||||
name = def.name,
|
||||
type = "choose-elem-button",
|
||||
elem_type = "signal",
|
||||
signal = { type = warp.icon.type, name = warp.icon.name },
|
||||
tooltip = { "warp-list.goto-edit" },
|
||||
}
|
||||
end)
|
||||
:static_name(Gui.unique_static_name)
|
||||
:style(Styles.sprite32)
|
||||
|
||||
--- Warp label, visible if the player is not in edit state
|
||||
-- @element warp_label
|
||||
local warp_label =
|
||||
Gui.element(function(definition, parent, warp)
|
||||
local warp_label = Gui.element("warp_label")
|
||||
:draw(function(def, parent, warp)
|
||||
local last_edit_name = warp.last_edit_name
|
||||
local last_edit_time = warp.last_edit_time
|
||||
-- Draw the element
|
||||
@@ -218,7 +216,7 @@ local warp_label =
|
||||
type = "label",
|
||||
caption = warp.name,
|
||||
tooltip = { "warp-list.last-edit", last_edit_name, format_time(last_edit_time) },
|
||||
name = definition.name,
|
||||
name = def.name,
|
||||
}
|
||||
end)
|
||||
:style{
|
||||
@@ -227,21 +225,20 @@ local warp_label =
|
||||
right_padding = 2,
|
||||
horizontally_stretchable = true,
|
||||
}
|
||||
:on_click(function(player, element, _)
|
||||
:on_click(function(def, player, element)
|
||||
local warp_id = element.parent.caption
|
||||
local warp = Warps.get_warp(warp_id)
|
||||
player.set_controller{ type = defines.controllers.remote, position = warp.position, surface = warp.surface }
|
||||
end)
|
||||
:static_name(Gui.unique_static_name)
|
||||
|
||||
--- Warp status, visible if the player is not in edit state
|
||||
--- This will show if the warp is connected or not
|
||||
-- @element warp_status
|
||||
local warp_status =
|
||||
Gui.element{
|
||||
local warp_status = Gui.element("warp_status")
|
||||
:draw{
|
||||
type = "label",
|
||||
caption = "[img=utility/electricity_icon_unplugged]", -- Temporary icon
|
||||
name = Gui.unique_static_name,
|
||||
name = Gui.property_from_name,
|
||||
}
|
||||
:style{
|
||||
-- When editing mode because textbox is larger the icon would move up.
|
||||
@@ -251,14 +248,14 @@ local warp_status =
|
||||
|
||||
--- Warp textfield, visible if the player is in edit state
|
||||
-- @element warp_textfield
|
||||
local warp_textfield =
|
||||
Gui.element(function(definition, parent, warp)
|
||||
local warp_textfield = Gui.element("warp_textfield")
|
||||
:draw(function(def, parent, warp)
|
||||
-- Draw the element
|
||||
return parent.add{
|
||||
type = "textfield",
|
||||
text = warp.name,
|
||||
clear_and_focus_on_right_click = true,
|
||||
name = definition.name,
|
||||
name = def.name,
|
||||
}
|
||||
end)
|
||||
:style{
|
||||
@@ -273,46 +270,47 @@ local warp_textfield =
|
||||
left_margin = 2,
|
||||
right_margin = 2,
|
||||
}
|
||||
:on_confirmed(function(player, element, _)
|
||||
:on_confirmed(function(def, player, element)
|
||||
local warp_id = element.parent.caption
|
||||
local warp_name = element.text
|
||||
local warp_icon = element.parent.parent["icon-" .. warp_id][warp_icon_editing.name].elem_value
|
||||
local warp_icon = element.parent.parent["icon-" .. warp_id][warp_icon_editing.name].elem_value --[[ @as SignalID ]]
|
||||
if warp_icon.type == nil then warp_icon.type = "item" end
|
||||
Warps.set_editing(warp_id, player.name)
|
||||
Warps.update_warp(warp_id, warp_name, warp_icon, player.name)
|
||||
end)
|
||||
:static_name(Gui.unique_static_name)
|
||||
|
||||
--- Confirms the edit to name or icon of the warp
|
||||
-- @element confirm_edit_button
|
||||
local confirm_edit_button =
|
||||
Gui.element{
|
||||
local confirm_edit_button = Gui.element("confirm_edit_button")
|
||||
:draw{
|
||||
type = "sprite-button",
|
||||
sprite = "utility/confirm_slot",
|
||||
tooltip = { "warp-list.confirm-tooltip" },
|
||||
style = "shortcut_bar_button_green",
|
||||
name = Gui.unique_static_name,
|
||||
name = Gui.property_from_name,
|
||||
}
|
||||
:style(Styles.sprite22)
|
||||
:on_click(function(player, element)
|
||||
:on_click(function(def, player, element)
|
||||
local warp_id = element.parent.caption
|
||||
local warp_name = element.parent.parent["name-" .. warp_id][warp_textfield.name].text
|
||||
local warp_icon = element.parent.parent["icon-" .. warp_id][warp_icon_editing.name].elem_value
|
||||
local warp_icon = element.parent.parent["icon-" .. warp_id][warp_icon_editing.name].elem_value --[[ @as SignalID ]]
|
||||
if warp_icon.type == nil then warp_icon.type = "item" end
|
||||
Warps.set_editing(warp_id, player.name)
|
||||
Warps.update_warp(warp_id, warp_name, warp_icon, player.name)
|
||||
end)
|
||||
|
||||
--- Cancels the editing changes of the selected warp name or icon
|
||||
-- @element cancel_edit_button
|
||||
local cancel_edit_button =
|
||||
Gui.element{
|
||||
local cancel_edit_button = Gui.element("cancel_edit_button")
|
||||
:draw{
|
||||
type = "sprite-button",
|
||||
sprite = "utility/close_black",
|
||||
tooltip = { "warp-list.cancel-tooltip" },
|
||||
style = "shortcut_bar_button_red",
|
||||
name = Gui.unique_static_name,
|
||||
name = Gui.property_from_name,
|
||||
}
|
||||
:style(Styles.sprite22)
|
||||
:on_click(function(player, element)
|
||||
:on_click(function(def, player, element)
|
||||
local warp_id = element.parent.caption
|
||||
-- Check if this is the first edit, if so remove the warp.
|
||||
local warp = Warps.get_warp(warp_id)
|
||||
@@ -325,32 +323,32 @@ local cancel_edit_button =
|
||||
|
||||
--- Removes a warp from the list, including the physical area and map tag
|
||||
-- @element remove_warp_button
|
||||
local remove_warp_button =
|
||||
Gui.element{
|
||||
local remove_warp_button = Gui.element("remove_warp_button")
|
||||
:draw{
|
||||
type = "sprite-button",
|
||||
sprite = "utility/trash",
|
||||
tooltip = { "warp-list.remove-tooltip" },
|
||||
style = "shortcut_bar_button_red",
|
||||
name = Gui.unique_static_name,
|
||||
name = Gui.property_from_name,
|
||||
}
|
||||
:style(Styles.sprite22)
|
||||
:on_click(function(_, element)
|
||||
:on_click(function(def, player, element)
|
||||
local warp_id = element.parent.caption
|
||||
Warps.remove_warp(warp_id)
|
||||
end)
|
||||
|
||||
--- Opens edit mode for the warp
|
||||
-- @element edit_warp_button
|
||||
local edit_warp_button =
|
||||
Gui.element{
|
||||
local edit_warp_button = Gui.element("edit_warp_button")
|
||||
:draw{
|
||||
type = "sprite-button",
|
||||
sprite = "utility/rename_icon",
|
||||
tooltip = { "warp-list.edit-tooltip-none" },
|
||||
style = "shortcut_bar_button",
|
||||
name = Gui.unique_static_name,
|
||||
name = Gui.property_from_name,
|
||||
}
|
||||
:style(Styles.sprite22)
|
||||
:on_click(function(player, element)
|
||||
:on_click(function(def, player, element)
|
||||
local warp_id = element.parent.caption
|
||||
Warps.set_editing(warp_id, player.name, true)
|
||||
end)
|
||||
@@ -358,8 +356,8 @@ local edit_warp_button =
|
||||
local update_all_warp_elements
|
||||
--- Set of three elements which make up each row of the warp table
|
||||
-- @element add_warp_elements
|
||||
local add_warp_elements =
|
||||
Gui.element(function(_, parent, warp)
|
||||
local add_warp_elements = Gui.element("add_warp_elements")
|
||||
:draw(function(_, parent, warp)
|
||||
-- Add icon flow, this will contain the warp button and warp icon edit button
|
||||
local icon_flow = parent.add{
|
||||
name = "icon-" .. warp.warp_id,
|
||||
@@ -398,9 +396,6 @@ local add_warp_elements =
|
||||
cancel_edit_button(button_flow)
|
||||
edit_warp_button(button_flow)
|
||||
remove_warp_button(button_flow)
|
||||
|
||||
-- Return the warp flow elements
|
||||
return { icon_flow, name_flow, button_flow }
|
||||
end)
|
||||
|
||||
-- Removes the three elements that are added as part of the warp base
|
||||
@@ -412,10 +407,10 @@ end
|
||||
|
||||
--- This timer controls when a player is able to warp, eg every 60 seconds
|
||||
-- @element warp_timer
|
||||
local warp_timer =
|
||||
Gui.element{
|
||||
local warp_timer = Gui.element("warp_timer")
|
||||
:draw{
|
||||
type = "progressbar",
|
||||
name = Gui.unique_static_name,
|
||||
name = Gui.property_from_name,
|
||||
tooltip = { "warp-list.timer-tooltip-zero", config.cooldown_duration },
|
||||
minimum_value = 0,
|
||||
maximum_value = config.cooldown_duration * config.update_smoothing,
|
||||
@@ -499,10 +494,10 @@ end
|
||||
--- Update the warp buttons for a player
|
||||
function update_all_warp_elements(player, timer, warp_id)
|
||||
-- Get the warp table
|
||||
local frame = Gui.get_left_element(player, warp_list_container)
|
||||
local scroll_table = frame.container.scroll.table
|
||||
local container = Gui.get_left_element(warp_list_container, player)
|
||||
local scroll_table = container.frame.scroll.table
|
||||
|
||||
-- Check if the player is currenty on cooldown
|
||||
-- Check if the player is currently on cooldown
|
||||
timer = timer or PlayerCooldown:get(player)
|
||||
local on_cooldown = timer > 0
|
||||
-- Get the warp the player is on
|
||||
@@ -627,8 +622,8 @@ end
|
||||
local function update_all_warp_force(force)
|
||||
local warp_ids = Warps.get_force_warp_ids(force.name)
|
||||
for _, player in pairs(force.connected_players) do
|
||||
local frame = Gui.get_left_element(player, warp_list_container)
|
||||
local warp_table = frame.container.scroll.table
|
||||
local container = Gui.get_left_element(warp_list_container, player)
|
||||
local warp_table = container.frame.scroll.table
|
||||
|
||||
warp_table.clear() -- Needed to re-sort the warps
|
||||
for _, warp_id in ipairs(warp_ids) do
|
||||
@@ -639,20 +634,20 @@ end
|
||||
|
||||
--- Main warp list container for the left flow
|
||||
-- @element warp_list_container
|
||||
warp_list_container =
|
||||
Gui.element(function(definition, parent)
|
||||
local player = Gui.get_player_from_element(parent)
|
||||
warp_list_container = Gui.element("warp_list_container")
|
||||
:draw(function(def, parent)
|
||||
local player = Gui.get_player(parent)
|
||||
-- Check if user has permission to add warps
|
||||
local allow_add_warp = check_player_permissions(player, "allow_add_warp")
|
||||
|
||||
-- Draw the internal container
|
||||
local container = Gui.container(parent, definition.name, allow_add_warp and 268 or 220)
|
||||
local container = Gui.elements.container(parent, allow_add_warp and 268 or 220)
|
||||
|
||||
-- Draw the header
|
||||
local header = Gui.header(
|
||||
container,
|
||||
{ "warp-list.main-caption" },
|
||||
{
|
||||
local header = Gui.elements.header(container, {
|
||||
name = "header",
|
||||
caption = { "warp-list.main-caption" },
|
||||
tooltip = {
|
||||
"warp-list.sub-tooltip",
|
||||
config.cooldown_duration,
|
||||
config.standard_proximity_radius,
|
||||
@@ -663,15 +658,14 @@ warp_list_container =
|
||||
{ "warp-list.sub-tooltip-not_available", warp_status_icons.not_available },
|
||||
{ "warp-list.sub-tooltip-bypass", warp_status_icons.bypass },
|
||||
},
|
||||
true
|
||||
)
|
||||
})
|
||||
|
||||
-- Draw the new warp button
|
||||
local add_new_warp_element = add_new_warp(header)
|
||||
add_new_warp_element.visible = allow_add_warp
|
||||
|
||||
-- Draw the scroll table for the warps
|
||||
local scroll_table = Gui.scroll_table(container, 250, 3)
|
||||
local scroll_table = Gui.elements.scroll_table(container, 250, 3, "scroll")
|
||||
-- Set the scroll panel to always show the scrollbar (not doing this will result in a changing gui size)
|
||||
scroll_table.parent.vertical_scroll_policy = "always"
|
||||
|
||||
@@ -699,18 +693,21 @@ warp_list_container =
|
||||
-- Return the external container
|
||||
return container.parent
|
||||
end)
|
||||
:static_name(Gui.unique_static_name)
|
||||
:add_to_left_flow()
|
||||
|
||||
--- Button on the top flow used to toggle the warp list container
|
||||
-- @element toggle_warp_list
|
||||
Gui.left_toolbar_button(config.default_icon.type .. "/" .. config.default_icon.name, { "warp-list.main-tooltip" }, warp_list_container, function(player)
|
||||
return Roles.player_allowed(player, "gui/warp-list")
|
||||
--- Add the element to the left flow with a toolbar button
|
||||
Gui.add_left_element(warp_list_container, false)
|
||||
Gui.toolbar.create_button{
|
||||
name = "warp_list_toggle",
|
||||
left_element = warp_list_container,
|
||||
sprite = config.default_icon.type .. "/" .. config.default_icon.name,
|
||||
tooltip = { "warp-list.main-tooltip" },
|
||||
visible = function(player, element)
|
||||
return Roles.player_allowed(player, "gui/warp-list")
|
||||
end
|
||||
}:on_click(function(def, player, element)
|
||||
-- Set gui keep open state for player that clicked the button: true if visible, false if invisible
|
||||
keep_gui_open[player.name] = Gui.toolbar.get_button_toggled_state(def, player)
|
||||
end)
|
||||
:on_event(Gui.events.on_visibility_changed_by_click, function(player, _, event)
|
||||
-- Set gui keep open state for player that clicked the button: true if visible, false if invisible
|
||||
keep_gui_open[player.name] = event.state
|
||||
end)
|
||||
|
||||
--- When the name of a warp is updated this is triggered
|
||||
Warps.on_update(function(_, warp, old_warp)
|
||||
@@ -728,7 +725,7 @@ PlayerInRange:on_update(function(player_name, warp_id)
|
||||
|
||||
-- Change if the frame is visible based on if the player is in range
|
||||
if not keep_gui_open[player.name] then
|
||||
Gui.toggle_left_element(player, warp_list_container, warp_id ~= nil)
|
||||
Gui.toolbar.set_left_element_visible_state(warp_list_container, player, warp_id ~= nil)
|
||||
end
|
||||
|
||||
update_all_warp_elements(player, nil, warp_id)
|
||||
@@ -738,8 +735,8 @@ end)
|
||||
PlayerCooldown:on_update(function(player_name, player_cooldown)
|
||||
-- Get the progress bar element
|
||||
local player = game.players[player_name]
|
||||
local frame = Gui.get_left_element(player, warp_list_container)
|
||||
local warp_timer_element = frame.container[warp_timer.name]
|
||||
local container = Gui.get_left_element(warp_list_container, player)
|
||||
local warp_timer_element = container.frame[warp_timer.name]
|
||||
|
||||
-- Set the progress
|
||||
if player_cooldown and player_cooldown > 0 then
|
||||
@@ -818,8 +815,8 @@ Event.on_nth_tick(math.floor(60 / config.update_smoothing), function()
|
||||
end
|
||||
|
||||
-- Change the enabled state of the add warp button
|
||||
local frame = Gui.get_left_element(player, warp_list_container)
|
||||
local add_warp_element = frame.container.header.alignment[add_new_warp.name]
|
||||
local container = Gui.get_left_element(warp_list_container, player)
|
||||
local add_warp_element = container.frame.header.flow[add_new_warp.name]
|
||||
local old_closest_warp_name = add_warp_element.tooltip[2] or closest_warp and closest_warp.name
|
||||
local was_able_to_make_warp = add_warp_element.enabled
|
||||
local can_make_warp = closest_distance == nil or closest_distance > mr2
|
||||
@@ -858,27 +855,27 @@ end)
|
||||
--- Update the warps when the player joins
|
||||
Event.add(defines.events.on_player_joined_game, function(event)
|
||||
local player = game.players[event.player_index]
|
||||
local frame = Gui.get_left_element(player, warp_list_container)
|
||||
local scroll_table = frame.container.scroll.table
|
||||
local container = Gui.get_left_element(warp_list_container, player)
|
||||
local scroll_table = container.frame.scroll.table
|
||||
update_all_warps(player, scroll_table)
|
||||
end)
|
||||
|
||||
--- Makes sure the right buttons are present when roles change
|
||||
local function role_update_event(event)
|
||||
local player = game.players[event.player_index]
|
||||
local container = Gui.get_left_element(player, warp_list_container).container
|
||||
local frame = Gui.get_left_element(warp_list_container, player).frame
|
||||
|
||||
-- Check if user has permission to add warps
|
||||
local allow_add_warp = check_player_permissions(player, "allow_add_warp")
|
||||
-- Update container size depending on whether the player is allowed to add warps
|
||||
container.parent.style.width = allow_add_warp and 268 or 220
|
||||
frame.parent.style.width = allow_add_warp and 268 or 220
|
||||
|
||||
-- Update the warps, incase the user can now edit them
|
||||
local scroll_table = container.scroll.table
|
||||
-- Update the warps, in case the user can now edit them
|
||||
local scroll_table = frame.scroll.table
|
||||
update_all_warps(player, scroll_table)
|
||||
|
||||
-- Update the new warp button incase the user can now add them
|
||||
local add_new_warp_element = container.header.alignment[add_new_warp.name]
|
||||
-- Update the new warp button in case the user can now add them
|
||||
local add_new_warp_element = frame.header.flow[add_new_warp.name]
|
||||
add_new_warp_element.visible = allow_add_warp
|
||||
end
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
local Storage = require("modules/exp_util/storage")
|
||||
local Event = require("modules/exp_legacy/utils/event") --- @dep expcore.gui
|
||||
local mod_gui = require "mod-gui" --- @dep mod-gui
|
||||
local Event = require("modules/exp_legacy/utils/event")
|
||||
local mod_gui = require "mod-gui"
|
||||
|
||||
local Gui = {}
|
||||
local data = {}
|
||||
|
||||
@@ -5,8 +5,9 @@ Adds rcon interfaces for the legacy exp core
|
||||
local Commands = require("modules/exp_commands")
|
||||
local add_static, add_dynamic = Commands.add_rcon_static, Commands.add_rcon_dynamic
|
||||
|
||||
add_static("Gui", require("modules/exp_gui"))
|
||||
|
||||
add_static("Group", require("modules.exp_legacy.expcore.permission_groups"))
|
||||
add_static("Roles", require("modules.exp_legacy.expcore.roles"))
|
||||
add_static("Gui", require("modules.exp_legacy.expcore.gui"))
|
||||
add_static("Datastore", require("modules.exp_legacy.expcore.datastore"))
|
||||
add_static("External", require("modules.exp_legacy.expcore.external"))
|
||||
|
||||
@@ -36,16 +36,18 @@ end
|
||||
|
||||
--- @class FlyingText.create_above_entity_param:FlyingText.create_param
|
||||
--- @field target_entity? LuaEntity The entity to create the text above
|
||||
--- @field offset? { x: number, y: number } Offset to move the text by
|
||||
|
||||
--- Create flying above an entity, overrides the position option of FlyingText.create
|
||||
--- @param options FlyingText.create_above_entity_param
|
||||
function FlyingText.create_above_entity(options)
|
||||
local entity = assert(options.target_entity, "A target entity is required")
|
||||
local size_y = entity.bounding_box.left_top.y - entity.bounding_box.right_bottom.y
|
||||
local offset = options.offset or { x = 0, y = 0 }
|
||||
|
||||
options.position = {
|
||||
x = entity.position.x,
|
||||
y = entity.position.y - size_y * 0.25,
|
||||
x = offset.x + entity.position.x,
|
||||
y = offset.y + entity.position.y + size_y * 0.25,
|
||||
}
|
||||
|
||||
FlyingText.create(options)
|
||||
@@ -53,6 +55,7 @@ end
|
||||
|
||||
--- @class FlyingText.create_above_player_param:FlyingText.create_param
|
||||
--- @field target_player? LuaPlayer The player to create the text above
|
||||
--- @field offset? { x: number, y: number } Offset to move the text by
|
||||
|
||||
--- Create flying above a player, overrides the position option of FlyingText.create
|
||||
--- @param options FlyingText.create_above_player_param
|
||||
@@ -60,10 +63,11 @@ function FlyingText.create_above_player(options)
|
||||
local player = assert(options.target_player, "A target player is required")
|
||||
local entity = player.character; if not entity then return end
|
||||
local size_y = entity.bounding_box.left_top.y - entity.bounding_box.right_bottom.y
|
||||
local offset = options.offset or { x = 0, y = 0 }
|
||||
|
||||
options.position = {
|
||||
x = entity.position.x,
|
||||
y = entity.position.y - size_y * 0.25,
|
||||
x = offset.x + entity.position.x,
|
||||
y = offset.y + entity.position.y + size_y * 0.25,
|
||||
}
|
||||
|
||||
FlyingText.create(options)
|
||||
@@ -71,6 +75,7 @@ end
|
||||
|
||||
--- @class FlyingText.create_as_player_param:FlyingText.create_param
|
||||
--- @field target_player? LuaPlayer The player to create the text above
|
||||
--- @field offset? { x: number, y: number } Offset to move the text by
|
||||
|
||||
--- Create flying above a player, overrides the position and color option of FlyingText.create
|
||||
--- @param options FlyingText.create_as_player_param
|
||||
@@ -78,11 +83,12 @@ function FlyingText.create_as_player(options)
|
||||
local player = assert(options.target_player, "A target player is required")
|
||||
local entity = player.character; if not entity then return end
|
||||
local size_y = entity.bounding_box.left_top.y - entity.bounding_box.right_bottom.y
|
||||
local offset = options.offset or { x = 0, y = 0 }
|
||||
|
||||
options.color = player.chat_color
|
||||
options.position = {
|
||||
x = entity.position.x,
|
||||
y = entity.position.y - size_y * 0.25,
|
||||
x = offset.x + entity.position.x,
|
||||
y = offset.y + entity.position.y + size_y * 0.25,
|
||||
}
|
||||
|
||||
FlyingText.create(options)
|
||||
|
||||
@@ -167,6 +167,18 @@ function ExpUtil.get_function_name(func, raw)
|
||||
return "<" .. file_name .. ":" .. func_name .. ">"
|
||||
end
|
||||
|
||||
--- Returns a desync sale filepath and current line for a given stack frame, default is the current file
|
||||
--- @param level number? The level of the stack to get the file of, a value of 1 is the caller of this function
|
||||
--- @param raw boolean? When true there will not be any < > around the name
|
||||
--- @return string # The relative filepath of the given stack frame
|
||||
function ExpUtil.get_current_line(level, raw)
|
||||
local debug_info = getinfo((level or 1) + 1, "Snl")
|
||||
local safe_source = debug_info.source:find("@__level__")
|
||||
local file_path = safe_source == 1 and debug_info.short_src:sub(10, -5) or debug_info.source
|
||||
if raw then return file_path .. ":" .. debug_info.currentline end
|
||||
return "<" .. file_path .. ":" .. debug_info.currentline .. ">"
|
||||
end
|
||||
|
||||
--- Attempt a simple autocomplete search from a set of options
|
||||
--- @param options table The table representing the possible options which can be selected
|
||||
--- @param input string The user input string which should be matched to an option
|
||||
|
||||
@@ -49,15 +49,16 @@ local ExpUtil = require("modules/exp_util")
|
||||
|
||||
--- @class ExpUtil_Storage
|
||||
local Storage = {
|
||||
_registered = {}, --- @type table<string, { init: table, callback: fun(tbl: table) }> Map of all registered values and their initial values
|
||||
_registered = {}, --- @type table<string, { init: table, callback: fun(tbl: table), on_init: fun(tbl: table)? }>
|
||||
}
|
||||
|
||||
--- Register a new table to be stored in storage, can only be called once per file, can not be called during runtime
|
||||
--- @generic T:table
|
||||
--- @param tbl T The initial value for the table you are registering, this should be a local variable
|
||||
--- @param callback fun(tbl: T) The callback used to replace local references and metatables
|
||||
--- @param on_init fun(tbl: T)? The callback used to setup/validate storage if a static value is not enough
|
||||
-- This function does not return the table because the callback can't access the local it would be assigned to
|
||||
function Storage.register(tbl, callback)
|
||||
function Storage.register(tbl, callback, on_init)
|
||||
ExpUtil.assert_not_runtime()
|
||||
ExpUtil.assert_argument_type(tbl, "table", 1, "tbl")
|
||||
ExpUtil.assert_argument_type(callback, "function", 2, "callback")
|
||||
@@ -70,6 +71,7 @@ function Storage.register(tbl, callback)
|
||||
Storage._registered[name] = {
|
||||
init = tbl,
|
||||
callback = callback,
|
||||
on_init = on_init,
|
||||
}
|
||||
end
|
||||
|
||||
@@ -110,6 +112,9 @@ function Storage.on_init()
|
||||
if exp_storage[name] == nil then
|
||||
exp_storage[name] = info.init
|
||||
end
|
||||
if info.on_init then
|
||||
info.on_init(exp_storage[name])
|
||||
end
|
||||
info.callback(exp_storage[name])
|
||||
end
|
||||
end
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
"references": [
|
||||
{ "path": "./exp_commands/" },
|
||||
{ "path": "./exp_groups/" },
|
||||
{ "path": "./exp_gui/" },
|
||||
{ "path": "./exp_legacy/" },
|
||||
{ "path": "./exp_scenario/" },
|
||||
{ "path": "./exp_util/" },
|
||||
|
||||
Reference in New Issue
Block a user