This commit is contained in:
Cooldude2606
2019-09-28 16:34:52 +01:00
parent 2e06023332
commit 654550bcb1
45 changed files with 4139 additions and 4115 deletions

View File

@@ -0,0 +1,128 @@
--[[-- Core Module - Gui
@module Gui
@alias Prototype
]]
--- Buttons.
-- Gui class define for buttons and sprite buttons
-- @section Buttons
--[[
>>>> Functions
Button.new_button(name) --- Creates a new button element define
Button._prototype:on_click(player,element) --- Registers a handler for when the button is clicked
Button._prototype:on_left_click(player,element) --- Registers a handler for when the button is clicked with the left mouse button
Button._prototype:on_right_click(player,element) --- Registers a handler for when the button is clicked with the right mouse button
Button._prototype:set_sprites(sprite,hovered_sprite,clicked_sprite) --- Adds sprites to a button making it a sprite button
Button._prototype:set_click_filter(filter,...) --- Adds a click / mouse button filter to the button
Button._prototype:set_key_filter(filter,...) --- Adds a control key filter to the button
Other functions present from expcore.gui.core
]]
local mod_gui = require 'mod-gui' --- @dep mod-gui
local Gui = require 'expcore.gui.core' --- @dep expcore.gui.core
local Prototype = require 'expcore.gui.prototype' --- @dep expcore.gui.prototype
local Button = {
_prototype=Prototype.extend{
on_raw_click = Prototype.event,
on_click = Prototype.event,
on_left_click = Prototype.event,
on_right_click = Prototype.event,
}
}
--- Creates a new button element define
-- @tparam[opt] string name the optional debug name that can be added
-- @treturn table the new button element define
function Button.new_button(name)
local self = Gui.new_define(Button._prototype,name)
self.draw_data.type = 'button'
self.draw_data.style = mod_gui.button_style
Gui.on_click(self.name,function(event)
local mouse_button = event.button
local keys = {alt=event.alt,control=event.control,shift=event.shift}
local player,element = event.player,event.element
event.keys = keys
self:raise_event('on_raw_click',event)
if self.post_authenticator then
if not self.post_authenticator(event.player,self.name) then return end
end
if mouse_button == defines.mouse_button_type.left then
self:raise_event('on_left_click',player,element)
elseif mouse_button == defines.mouse_button_type.right and self.events.on_right_click then
self:raise_event('on_right_click',player,element)
end
if self.mouse_button_filter and not self.mouse_button_filter[mouse_button] then return end
if self.key_button_filter then
for key,state in pairs(self.key_button_filter) do
if state and not keys[key] then return end
end
end
self:raise_event('on_click',player,element)
end)
return self
end
--- Adds sprites to a button making it a sprite button
-- @tparam SpritePath sprite the sprite path for the default sprite for the button
-- @tparam[opt] SpritePath hovered_sprite the sprite path for the sprite when the player hovers over the button
-- @tparam[opt] SpritePath clicked_sprite the sprite path for the sprite when the player clicks the button
-- @treturn self returns the button define to allow chaining
function Button._prototype:set_sprites(sprite,hovered_sprite,clicked_sprite)
self.draw_data.type = 'sprite-button'
self.draw_data.sprite = sprite
self.draw_data.hovered_sprite = hovered_sprite
self.draw_data.clicked_sprite = clicked_sprite
return self
end
--- Adds a click / mouse button filter to the button
-- @tparam table filter ?string|table either a of mouse buttons or the first mouse button to filter, with a table true means allowed
-- @tparam[opt] table ... when filter is not a you can add the mouse buttons one after each other
-- @treturn self returns the button define to allow chaining
function Button._prototype:set_click_filter(filter,...)
if type(filter) == 'string' then
filter = {[filter]=true}
for _,v in pairs({...}) do
filter[v] = true
end
end
for k,v in pairs(filter) do
if type(v) == 'string' then
filter[k] = defines.mouse_button_type[v]
end
end
self.mouse_button_filter = filter
return self
end
--- Adds a control key filter to the button
-- @tparam table filter ?string|table either a of control keys or the first control keys to filter, with a table true means allowed
-- @tparam[opt] table ... when filter is not a you can add the control keys one after each other
-- @treturn self returns the button define to allow chaining
function Button._prototype:set_key_filter(filter,...)
if type(filter) == 'string' then
filter = {[filter]=true}
for _,v in pairs({...}) do
filter[v] = true
end
end
self.key_button_filter = filter
return self
end
return Button

View File

@@ -0,0 +1,252 @@
--[[-- Core Module - Gui
@module Gui
@alias Prototype
]]
--- Checkboxs.
-- Gui class define for checkbox and radiobuttons
-- @section checkboxs
--[[
>>>> Using an option set
An option set is a set of radio buttons where only one of them can be active at a time, this means that when one
is clicked all the other ones are set to false, an option set must be defined before hand and will always store
its state but is not limited by how it can categorize the store.
First you must register the store with a name and a update callback, and an optional function for categorize:
local example_option_set =
Gui.new_option_set('example-option-set',function(value,category)
game.print('Example options set '..category..' is now: '..tostring(value))
end,Gui.categorize_by_player)
Then you must register some radiobutton defines and include them in the option set:
local example_option_one =
Gui.new_radiobutton()
:set_caption('Option One')
:add_as_option(example_option_set,'One')
local example_option_two =
Gui.new_radiobutton()
:set_caption('Option Two')
:add_as_option(example_option_set,'Two')
Note that these radiobuttons can still have on_element_update events but this may result in a double trigger of events as
the option set update is always triggered; also add_store cant be used as the option set acts as the store however get
and set store will still work but will effect the option set rather than the individual radiobuttons.
>>>> Functions
Checkbox.new_checkbox(name) --- Creates a new checkbox element define
Checkbox._prototype_checkbox:on_element_update(callback) --- Registers a handler for when an element instance updates
Checkbox._prototype_checkbox:on_store_update(callback) --- Registers a handler for when the stored value updates
Checkbox.new_radiobutton(name) --- Creates a new radiobutton element define
Checkbox._prototype_radiobutton:on_element_update(callback) --- Registers a handler for when an element instance updates
Checkbox._prototype_radiobutton:on_store_update(callback) --- Registers a handler for when the stored value updates
Checkbox._prototype_radiobutton:add_as_option(option_set,option_name) --- Adds this radiobutton to be an option in the given option set (only one can be true at a time)
Checkbox.new_option_set(name,callback,categorize) --- Registers a new option set that can be linked to radiobutton (only one can be true at a time)
Checkbox.draw_option_set(name,element) --- Draws all radiobuttons that are part of an option set at once (Gui.draw will not work)
Checkbox.reset_radiobutton(element,exclude,recursive) --- Sets all radiobutton in a element to false (unless excluded) and can act recursively
Other functions present from expcore.gui.core
]]
local Gui = require 'expcore.gui.core' --- @dep expcore.gui.core
local Prototype = require 'expcore.gui.prototype' --- @dep expcore.gui.prototype
local Store = require 'expcore.store' --- @dep expcore.store
local Game = require 'utils.game' --- @dep utils.game
--- Store call for store update
-- @tparam table define the define that this is acting on
-- @tparam LuaGuiElement element the element that triggered the event
-- @tparam boolean value the new state of the checkbox
local function store_update(define,element,value)
element.state = value
local player = Game.get_player_by_index(element.player_index)
define:raise_event('on_element_update',player,element,value)
end
local Checkbox = {
option_sets={},
option_categorize={},
_prototype_checkbox=Prototype.extend{
on_element_update = Prototype.event,
on_store_update = Prototype.event,
add_store = Prototype.store(false,store_update),
add_sync_store = Prototype.store(true,store_update)
},
_prototype_radiobutton=Prototype.extend{
on_element_update = Prototype.event,
on_store_update = Prototype.event,
add_store = Prototype.store(false,store_update),
add_sync_store = Prototype.store(true,store_update)
}
}
--- Creates a new checkbox element define
-- @tparam[opt] string name the optional debug name that can be added
-- @treturn table the new checkbox element define
function Checkbox.new_checkbox(name)
local self = Gui.new_define(Checkbox._prototype_checkbox,name)
self.draw_data.type = 'checkbox'
self.draw_data.state = false
self:on_draw(function(player,element)
if self.store then
local category = self.categorize and self.categorize(element) or nil
local state = self:get_store(category,true)
if state then element.state = true end
end
end)
Gui.on_checked_state_changed(self.name,function(event)
local element = event.element
if self.option_set then
local value = Checkbox.option_sets[self.option_set][element.name]
local category = self.categorize and self.categorize(element)
self:set_store(category,value)
elseif self.store then
local value = element.state
local category = self.categorize and self.categorize(element)
self:set_store(category,value)
else
self:raise_event('on_element_update',event.player,element,element.state)
end
end)
return self
end
--- Creates a new radiobutton element define, has all functions checkbox has
-- @tparam[opt] string name the optional debug name that can be added
-- @treturn table the new button element define
function Checkbox.new_radiobutton(name)
local self = Checkbox.new_checkbox(name)
self.draw_data.type = 'radiobutton'
local mt = getmetatable(self)
mt.__index = Checkbox._prototype_radiobutton
return self
end
--- Adds this radiobutton to be an option in the given option set (only one can be true at a time)
-- @tparam string option_set the name of the option set to add this element to
-- @tparam string option_name the name of this option that will be used to identify it
-- @treturn self the define to allow chaining
function Checkbox._prototype_radiobutton:add_as_option(option_set,option_name)
self.option_set = option_set
self.option_name = option_name or self.name
Checkbox.option_sets[option_set][self.option_name] = self.name
Checkbox.option_sets[option_set][self.name] = self.option_name
self:add_store(Checkbox.option_categorize[option_set])
return self
end
--- Gets the stored value of the radiobutton or the option set if present
-- @tparam string category[opt] the category to get such as player name or force name
-- @tparam boolean internal used to prevent stackover flow
-- @treturn any the value that is stored for this define
function Checkbox._prototype_radiobutton:get_store(category,internal)
if not self.store then return end
local location = not internal and self.option_set or self.store
return Store.get(location,category)
end
--- Sets the stored value of the radiobutton or the option set if present
-- @tparam string category[opt] the category to get such as player name or force name
-- @tparam boolean value the value to set for this define, must be valid for its type ie for checkbox etc
-- @tparam boolean internal used to prevent stackover flow
-- @treturn boolean true if the value was set
function Checkbox._prototype_radiobutton:set_store(category,value,internal)
if not self.store then return end
local location = not internal and self.option_set or self.store
return Store.set(location,category,value)
end
--- Registers a new option set that can be linked to radiobuttons (only one can be true at a time)
-- @tparam string name the name of the option set, must be unique
-- @tparam function callback the update callback when the value of the option set changes
-- callback param - value string - the new selected option for this option set
-- callback param - category string - the category that updated if categorize was used
-- @tparam function categorize the function used to convert an element into a string
-- @treturn string the name of this option set to be passed to add_as_option
function Checkbox.new_option_set(name,callback,categorize)
Store.register(name,function(value,category)
local options = Checkbox.option_sets[name]
for opt_name,define_name in pairs(options) do
if Gui.defines[define_name] then
local define = Gui.get_define(define_name)
local state = opt_name == value
define:set_store(category,state,true)
end
end
callback(value,category)
end)
Checkbox.option_categorize[name] = categorize
Checkbox.option_sets[name] = {}
return name
end
--- Draws all radiobuttons that are part of an option set at once (Gui.draw will not work)
-- @tparam string name the name of the option set to draw the radiobuttons of
-- @tparam LuaGuiElement element the parent element that the radiobuttons will be drawn to
function Checkbox.draw_option_set(name,element)
if not Checkbox.option_sets[name] then return end
local options = Checkbox.option_sets[name]
for _,option in pairs(options) do
if Gui.defines[option] then
Gui.defines[option]:draw_to(element)
end
end
end
--- Sets all radiobutton in a element to false (unless excluded) and can act recursively
-- @tparam LuaGuiElement element the root gui element to start setting radio buttons from
-- @tparam[opt] table exclude ?string|table the name of the radiobutton to exclude or a of radiobuttons where true will set the state true
-- @tparam[opt=false] ?number|boolean recursive if true will recur as much as possible, if a will recur that number of times
-- @treturn boolean true if successful
function Checkbox.reset_radiobuttons(element,exclude,recursive)
if not element or not element.valid then return end
exclude = type(exclude) == 'table' and exclude or exclude ~= nil and {[exclude]=true} or {}
recursive = type(recursive) == 'number' and recursive-1 or recursive
for _,child in pairs(element.children) do
if child and child.valid and child.type == 'radiobutton' then
local state = exclude[child.name] or false
local define = Gui.defines[child.name]
if define then
local category = define.categorize and define.categorize(child) or state
define:set_store(category,state)
else
child.state = state
end
elseif child.children and (type(recursive) == 'number' and recursive >= 0 or recursive == true) then
Checkbox.reset_radiobutton(child,exclude,recursive)
end
end
return true
end
return Checkbox

View File

@@ -0,0 +1,187 @@
--[[-- Core Module - Gui
@module Gui
@alias Prototype
]]
--- Dropdowns.
-- Gui class define for dropdowns and list box
-- @section dropdowns
--[[
>>>> Functions
Dropdown.new_dropdown(name) --- Creates a new dropdown element define
Dropdown.new_list_box(name) --- Creates a new list box element define
Dropdown._prototype:on_element_update(callback) --- Registers a handler for when an element instance updates
Dropdown._prototype:on_store_update(callback) --- Registers a handler for when the stored value updates
Dropdown._prototype:new_static_options(options,...) --- Adds new static options to the dropdown which will trigger the general callback
Dropdown._prototype:new_dynamic_options(callback) --- Adds a callback which should return a table of values to be added as options for the dropdown (appended after static options)
Dropdown._prototype:add_option_callback(option,callback) --- Adds a case specific callback which will only run when that option is selected (general case still triggered)
Dropdown.select_value(element,value) --- Selects the option from a dropdown or list box given the value rather than key
Dropdown.get_selected_value(element) --- Returns the currently selected value rather than index
Other functions present from expcore.gui.core
]]
local Gui = require 'expcore.gui.core' --- @dep expcore.gui.core
local Prototype = require 'expcore.gui.prototype' --- @dep expcore.gui.prototype
local Game = require 'utils.game' --- @dep utils.game
local select_value
--- Store call for store update
-- @tparam table define the define that this is acting on
-- @tparam LuaGuiElement element the element that triggered the event
-- @tparam string value the new option for the dropdown
local function store_update(define,element,value)
select_value(element,value)
local player = Game.get_player_by_index(element.player_index)
define:raise_event('on_element_update',player,element,value)
if define.option_callbacks and define.option_callbacks[value] then
define.option_callbacks[value](player,element,value)
end
end
local Dropdown = {
_prototype=Prototype.extend{
on_element_update = Prototype.event,
on_store_update = Prototype.event,
add_store = Prototype.store(false,store_update),
add_sync_store = Prototype.store(true,store_update)
}
}
--- Creates a new dropdown element define
-- @tparam[opt] string name the optional debug name that can be added
-- @treturn table the new dropdown element define
function Dropdown.new_dropdown(name)
local self = Gui.new_define(Dropdown._prototype,name)
self.draw_data.type = 'drop-down'
self:on_draw(function(player,element)
if self.dynamic_options then
local dynamic_options = self.dynamic_options(player,element)
local items = element.items
for _,v in pairs(dynamic_options) do
table.insert(items,v)
end
element.items = items
end
if self.store then
local category = self.categorize and self.categorize(element) or nil
local value = self:get_store(category)
if value then Dropdown.select_value(element,value) end
end
end)
Gui.on_selection_state_changed(self.name,function(event)
local element = event.element
local value = Dropdown.get_selected_value(element)
if self.store then
local category = self.categorize and self.categorize(element) or value
self:set_store(category,value)
else
local player = event.player
local option_callbacks = self.option_callbacks
self:raise_event('on_element_update',player,element,value)
if option_callbacks and option_callbacks[value] then
option_callbacks[value](player,element,value)
end
end
end)
return self
end
--- Creates a new list box element define
-- @tparam[opt] string name the optional debug name that can be added
-- @treturn table the new list box element define
function Dropdown.new_list_box(name)
local self = Dropdown.new_dropdown(name)
self.draw_data.type = 'list-box'
return self
end
--- Adds new static options to the dropdown which will trigger the general callback
-- @tparam table options ?string|table either a of option strings or the first option string, with a table values are the options
-- @tparam[opt] table ... when options is not a you can add the options one after each other
-- @tparam self the define to allow chaining
function Dropdown._prototype:new_static_options(options,...)
if type(options) == 'string' then
options = {options}
for _,v in pairs({...}) do
table.insert(options,v)
end
end
self.options = options
self.draw_data.items = options
return self
end
Dropdown._prototype.add_options = Dropdown._prototype.new_static_options
--- Adds a callback which should return a table of values to be added as options for the dropdown (appended after static options)
-- @tparam function callback the function that will run to get the options for the dropdown
-- callback param - player LuaPlayer - the player that the element is being drawn to
-- callback param - element LuaGuiElement - the element that is being drawn
-- callback return - table - the values of this table will be appended to the static options of the dropdown
-- @treturn self the define to allow chaining
function Dropdown._prototype:new_dynamic_options(callback)
if type(callback) ~= 'function' then
return error('Dynamic options callback must be a function',2)
end
self.dynamic_options = callback
return self
end
Dropdown._prototype.add_dynamic = Dropdown._prototype.new_dynamic_options
--- Adds a case specific callback which will only run when that option is selected (general case still triggered)
-- @tparam string option the name of the option to trigger the callback on; if not already added then will be added as an option
-- @tparam function callback the function that will be called when that option is selected
-- callback param - player LuaPlayer - the player who owns the gui element
-- callback param - element LuaGuiElement - the element which is being effected
-- callback param - value string - the new option that has been selected
-- @treturn self the define to allow chaining
function Dropdown._prototype:add_option_callback(option,callback)
if not self.option_callbacks then self.option_callbacks = {} end
if not self.options then self.options = {} end
self.option_callbacks[option] = callback
if not table.contains(self.options,option) then
table.insert(self.options,option)
end
return self
end
--- Selects the option from a dropdown or list box given the value rather than key
-- @tparam LuaGuiElement element the element that contains the option
-- @tparam string value the option to select from the dropdown
-- @treturn number the key where the value was
function Dropdown.select_value(element,value)
for k,item in pairs(element.items) do
if item == value then
element.selected_index = k
return k
end
end
end
select_value = Dropdown.select_value
--- Returns the currently selected value rather than index
-- @tparam LuaGuiElement element the gui element that you want to get the value of
-- @treturn string the value that is currently selected
function Dropdown.get_selected_value(element)
local index = element.selected_index
return element.items[index]
end
return Dropdown

View File

@@ -0,0 +1,99 @@
--[[-- Core Module - Gui
@module Gui
@alias Prototype
]]
--- Elem Buttons.
-- Gui class defines for elem buttons
-- @section elem-buttons
--[[
>>>> Functions
ElemButton.new_elem_button(name) --- Creates a new elem button element define
ElemButton._prototype:on_element_update(callback) --- Registers a handler for when an element instance updates
ElemButton._prototype:on_store_update(callback) --- Registers a handler for when the stored value updates
ElemButton._prototype:set_type(type) --- Sets the type of the elem button, the type is required so this must be called at least once
ElemButton._prototype:set_default(value) --- Sets the default value for the elem button, this may be a function or a string
Other functions present from expcore.gui.core
]]
local Gui = require 'expcore.gui.core' --- @dep expcore.gui.core
local Prototype = require 'expcore.gui.prototype' --- @dep expcore.gui.prototype
local Game = require 'utils.game' --- @dep utils.game
--- Store call for store update
-- @tparam table define the define that this is acting on
-- @tparam LuaGuiElement element the element that triggered the event
-- @tparam string value the new value for the elem button
local function store_update(define,element,value)
element.elem_value = value
local player = Game.get_player_by_index(element.player_index)
define:raise_event('on_element_update',player,element,value)
end
local ElemButton = {
_prototype=Prototype.extend{
on_element_update = Prototype.event,
on_store_update = Prototype.event,
add_store = Prototype.store(false,store_update),
add_sync_store = Prototype.store(true,store_update)
}
}
--- Creates a new elem button element define
-- @tparam[opt] string name the optional debug name that can be added
-- @treturn table the new elem button element define
function ElemButton.new_elem_button(name)
local self = Gui.new_define(ElemButton._prototype,name)
self.draw_data.type = 'choose-elem-button'
self:on_draw(function(player,element)
if type(self.default) == 'function' then
element.elem_value = self.default(player,element)
end
if self.store then
local category = self.categorize and self.categorize(element) or nil
local value = self:get_store(category)
if value then element.elem_value = value end
end
end)
Gui.on_elem_changed(self.name,function(event)
local element = event.element
local value = element.elem_value
if self.store then
local category = self.categorize and self.categorize(element) or value
self:set_store(category,value)
else
self:raise_event('on_element_update',event.player,element,value)
end
end)
return self
end
--- Sets the type of the elem button, the type is required so this must be called at least once
-- @tparam string type the type that this elem button is see factorio api
-- @treturn the element define to allow for chaining
ElemButton._prototype.set_type = Prototype.setter('string','draw_data','elem_type')
--- Sets the default value for the elem button, this may be a function or a string
-- @tparam ?string|function value string a will be a static default and a function will be called when drawn to get the default
-- @treturn the element define to allow for chaining
function ElemButton._prototype:set_default(value)
self.default = value
if type(value) ~= 'function' then
self.draw_data[self.draw_data.elem_type] = value
end
return self
end
return ElemButton

View File

@@ -0,0 +1,390 @@
--[[-- Core Module - Gui
@module Gui
@alias Prototype
]]
--- Progress Bars.
-- Gui element define for progress bars
-- @section progress-bars
--[[
>>>> Functions
ProgressBar.set_maximum(element,amount,count_down) --- Sets the maximum value that represents the end value of the progress bar
ProgressBar.increment(element,amount) --- Increases the value of the progressbar, if a define is given all of its instances have incremented
ProgressBar.decrement(element,amount) --- Decreases the value of the progressbar, if a define is given all of its instances have decremented
ProgressBar.new_progressbar(name) --- Creates a new progressbar element define
ProgressBar._prototype:set_maximum(amount,count_down) --- Sets the maximum value that represents the end value of the progress bar
ProgressBar._prototype:use_count_down(state) --- Will set the progress bar to start at 1 and trigger when it hits 0
ProgressBar._prototype:increment(amount,category) --- Increases the value of the progressbar
ProgressBar._prototype:increment_filtered(amount,filter) --- Increases the value of the progressbar, if the filter condition is met, does not work with store
ProgressBar._prototype:decrement(amount,category) --- Decreases the value of the progressbar
ProgressBar._prototype:decrement_filtered(amount,filter) --- Decreases the value of the progressbar, if the filter condition is met, does not work with store
ProgressBar._prototype:add_element(element,maximum) --- Adds an element into the list of instances that will are waiting to complete, does not work with store
ProgressBar._prototype:reset_element(element) --- Resets an element, or its store, to be back at the start, either 1 or 0
ProgressBar._prototype:on_complete(callback) --- Triggers when a progress bar element completes (hits 0 or 1)
ProgressBar._prototype:on_complete(callback) --- Triggers when a store value completes (hits 0 or 1)
ProgressBar._prototype:event_counter(filter) --- Event handler factory that counts up by 1 every time the event triggers, can filter which elements have incremented
ProgressBar._prototype:event_countdown(filter) --- Event handler factory that counts down by 1 every time the event triggers, can filter which elements have decremented
]]
local Gui = require 'expcore.gui.core' --- @dep expcore.gui.core
local Prototype = require 'expcore.gui.prototype' --- @dep expcore.gui.prototype
local Global = require 'utils.global' --- @dep utils.global
local Game = require 'utils.game' --- @dep utils.game
--- Event call for when the value is outside the range 0-1
-- @tparam table define the define that this is acting on
-- @tparam LuaGuiElement element the element that triggered the event
local function event_call(define,element)
local player = Game.get_player_by_index(element.player_index)
define:raise_event('on_complete',player,element,function()
define:add_element(element)
define:reset_element(element)
end)
end
--- Store call for store update
-- @tparam table define the define that this is acting on
-- @tparam LuaGuiElement element the element that triggered the event
-- @tparam number value the new value for the progress bar
local function store_update(define,element,value)
if value then
element.value = value
if define.count_down and value <= 0
or not define.count_down and value >= 1 then
event_call(define,element)
end
end
end
local ProgressBar = {
unregistered={}, -- elements with no callbacks
independent={}, -- elements with a link to a define
_prototype=Prototype.extend{
on_complete = Prototype.event,
on_store_complete = Prototype.event,
add_store = Prototype.store(false,store_update),
add_sync_store = Prototype.store(true,store_update)
}
}
Global.register({
unregistered = ProgressBar.unregistered,
independent = ProgressBar.independent
},function(tbl)
ProgressBar.unregistered = tbl.unregistered
ProgressBar.independent = tbl.independent
end)
--- Gets the define data, cant use Gui.get_define as it would error
-- @tparam ?table|string define the define to get
-- @treturn table the define or nil
local function get_define(define)
if type(define) == 'table' then
if define.name and Gui.defines[define.name] then
return Gui.defines[define.name]
end
end
return Gui.defines[define]
end
--- Gets the element data, used when there is no define
-- @tparam LuaGuiElement element the element to get the data of
-- @treturn table the element data similar to define
local function get_element(element)
if not element.valid then return end
local name = element.player_index..':'..element.index
if ProgressBar.unregistered[name] then
return ProgressBar.unregistered[name]
end
end
--- Sets the maximum value that represents the end value of the progress bar
-- @tparam ?LuaGuiElement|string element either a gui element or a registered define
-- @tparam number amount the amount to have set as the maximum
function ProgressBar.set_maximum(element,amount)
amount = amount > 0 and amount or error('amount must be greater than 0')
local define = get_define(element)
if define then
define:set_default_maximum(amount)
else
local element_data = get_element(element)
if element_data then
element_data.maximum = amount
else
local name = element.player_index..':'..element.index
ProgressBar.unregistered[name] = {
element=element,
maximum=amount or 1
}
end
end
end
--- Increases the value of the progressbar, if a define is given all of its instances have incremented
-- @tparam ?LuaGuiElement|string element either a gui element or a registered define
-- @tparam[opt=1] number amount the amount to increase the progressbar by
function ProgressBar.increment(element,amount)
amount = type(amount) == 'number' and amount or 1
local define = get_define(element)
if define then
define:increment(amount)
else
local element_data = get_element(element)
if element_data then
local real_amount = amount/element_data.maximum
element.value = element.value + real_amount
if element.value >= 1 then
local name = element.player_index..':'..element.index
ProgressBar.unregistered[name] = nil
return true
end
end
end
end
--- Decreases the value of the progressbar, if a define is given all of its instances have decremented
-- @tparam ?LuaGuiElement|string element either a gui element or a registered define
-- @tparam[opt=1] number amount the amount to decrease the progressbar by
function ProgressBar.decrement(element,amount)
amount = type(amount) == 'number' and amount or 1
local define = get_define(element)
if define then
define:decrement(amount)
else
local element_data = get_element(element)
if element_data then
local real_amount = amount/element_data.maximum
element.value = element.value - real_amount
if element.value <= 0 then
local name = element.player_index..':'..element.index
ProgressBar.unregistered[name] = nil
return true
end
end
end
end
--- Creates a new progressbar element define
-- @tparam[opt] string name the optional debug name that can be added
-- @treturn table the new progressbar element define
function ProgressBar.new_progressbar(name)
local self = Gui.new_define(ProgressBar._prototype,name)
self.draw_data.type = 'progressbar'
self:on_draw(function(player,element,maximum)
if self.store then
local category = self.categorize and self.categorize(element) or nil
local value = self:get_store(category)
if not value then
value = self.count_down and 1 or 0
self:set_store(category,value)
end
element.value = value
else
if self.count_down then
element.value = 1
end
if not ProgressBar.independent[self.name] then
ProgressBar.independent[self.name] = {}
end
table.insert(ProgressBar.independent[self.name],{
element = element,
maximum = maximum
})
end
end)
return self
end
--- Sets the maximum value that represents the end value of the progress bar
-- @tparam number amount the amount to have set as the maximum
-- @treturn table the define to allow chaining
function ProgressBar._prototype:set_default_maximum(amount)
amount = amount > 0 and amount or error('amount must be greater than 0')
self.default_maximum = amount
return self
end
--- Will set the progress bar to start at 1 and trigger when it hits 0
-- @tparam[opt=true] boolean state when true the bar will start filled, to be used with decrease
-- @treturn table the define to allow chaining
function ProgressBar._prototype:use_count_down(state)
if state == false then
self.count_down = false
else
self.count_down = true
end
return self
end
--- Main logic for changing the value of a progress bar, this only applies when its a registered define
-- @tparam table self the define that is being changed
-- @tparam number amount the amount which it is being changed by, may be negative
-- @tparam[opt] string category the category to use with store
-- @tparam[opt] function filter when given the filter must return true for the value of the element to be changed
local function change_value_prototype(self,amount,category,filter)
local function reset_store()
local value = self.count_down and 1 or 0
self:set_store(category,value)
end
if self.store then
local value = self:get_store(category) or self.count_down and 1 or 0
local maximum = self.default_maximum or 1
local new_value = value + (amount/maximum)
self:set_store(category,new_value)
if self.count_down and new_value <= 0
or not self.count_down and new_value >= 1 then
self:clear_store(category)
self:raise_event('on_store_complete',category,reset_store)
return
end
return
end
if ProgressBar.independent[self.name] then
for key,element_data in pairs(ProgressBar.independent[self.name]) do
local element = element_data.element
if not element or not element.valid then
ProgressBar.independent[self.name][key] = nil
else
if not filter or filter(element) then
local maximum = element_data.maximum or self.default_maximum or 1
element.value = element.value + (amount/maximum)
if self.count_down and element.value <= 0
or not self.count_down and element.value >= 1 then
ProgressBar.independent[self.name][key] = nil
event_call(self,element)
end
end
end
end
end
end
--- Increases the value of the progressbar
-- @tparam[opt=1] number amount the amount to increase the progressbar by
-- @tparam[opt] string category the category that is used with a store
function ProgressBar._prototype:increment(amount,category)
amount = type(amount) == 'number' and amount or 1
change_value_prototype(self,amount,category)
end
--- Increases the value of the progressbar, if the filter condition is met, does not work with store
-- @tparam[opt=1] number amount the amount to increase the progressbar by
-- @tparam function filter the filter to be used
function ProgressBar._prototype:increment_filtered(amount,filter)
amount = type(amount) == 'number' and amount or 1
change_value_prototype(self,amount,nil,filter)
end
--- Decreases the value of the progressbar
-- @tparam[opt=1] number amount the amount to decrease the progressbar by
-- @tparam[opt] string category the category that is used with a store
function ProgressBar._prototype:decrement(amount,category)
amount = type(amount) == 'number' and amount or 1
change_value_prototype(self,-amount,category)
end
--- Decreases the value of the progressbar, if the filter condition is met, does not work with store
-- @tparam[opt=1] number amount the amount to decrease the progressbar by
-- @tparam function filter the filter to be used
function ProgressBar._prototype:decrement_filtered(amount,filter)
amount = type(amount) == 'number' and amount or 1
change_value_prototype(self,-amount,nil,filter)
end
--- Adds an element into the list of instances that will are waiting to complete, does not work with store
-- note use store if you want persistent data, this only stores the elements not the values which they have
-- @tparam LuaGuiElement element the element that you want to add into the waiting to complete list
-- @tparam[opt] number maximum the maximum for this element if not given the default for this define is used
function ProgressBar._prototype:add_element(element,maximum)
if self.store then return end
if not ProgressBar.independent[self.name] then
ProgressBar.independent[self.name] = {}
end
table.insert(ProgressBar.independent[self.name],{
element = element,
maximum = maximum
})
end
--- Resets an element, or its store, to be back at the start, either 1 or 0
-- @tparam LuaGuiElement element the element that you want to reset the progress of
function ProgressBar._prototype:reset_element(element)
if not element or not element.valid then return end
local value = self.count_down and 1 or 0
if self.store then
local category = self.categorize and self.categorize(element) or value
self:set_store(category,value)
else
element.value = value
end
end
--- Event handler factory that counts up by 1 every time the event triggers, can filter which elements have incremented
-- @tparam[opt] function filter when given will use filtered increment
-- @treturn function the event handler
function ProgressBar._prototype:event_counter(filter)
if type(filter) == 'function' then
return function()
self:increment_filtered(1,filter)
end
else
return function()
self:increment()
end
end
end
--- Event handler factory that counts down by 1 every time the event triggers, can filter which elements have decremented
-- @tparam[opt] function filter when given will use filtered decrement
-- @treturn function the event handler
function ProgressBar._prototype:event_countdown(filter)
if type(filter) == 'function' then
return function()
self:decrement_filtered(1,filter)
end
else
return function()
self:decrement()
end
end
end
return ProgressBar

View File

@@ -0,0 +1,177 @@
--[[-- Core Module - Gui
@module Gui
@alias Prototype
]]
--- Sliders.
-- Gui class define for sliders
-- @section sliders
--[[
>>>> Functions
Slider.new_slider(name) --- Creates a new slider element define
Slider._prototype:on_element_update(callback) --- Registers a handler for when an element instance updates
Slider._prototype:on_store_update(callback) --- Registers a handler for when the stored value updates
Slider._prototype:set_range(min,max) --- Sets the range of a slider, if not used will use default values for a slider
Slider._prototype:draw_label(element) --- Draws a new label and links its value to the value of this slider, if no store then it will only show one value per player
Slider._prototype:enable_auto_draw_label(state) --- Enables auto draw of the label, the label will share the same parent element as the slider
Other functions present from expcore.gui.core
]]
local Gui = require 'expcore.gui.core' --- @dep expcore.gui.core
local Prototype = require 'expcore.gui.prototype' --- @dep expcore.gui.prototype
local Instances = require 'expcore.gui.instances' --- @dep expcore.gui.instances
local Game = require 'utils.game' --- @dep utils.game
--- Event call for on_value_changed and store update
-- @tparam table define the define that this is acting on
-- @tparam LuaGuiElement element the element that triggered the event
-- @tparam number value the new value for the slider
local function event_call(define,element,value)
local player = Game.get_player_by_index(element.player_index)
local min,max = element.get_slider_minimum(),element.get_slider_maximum()
local delta = max-min
local percent = delta == 0 and 0 or (value-min)/delta
define:raise_event('on_element_update',player,element,value,percent)
local category = player.name
if define.categorize then
category = define.categorize(element)
end
Instances.unregistered_get_elements(define.name..'-label',category,function(label)
label.caption = tostring(math.round(value,2))
end)
end
--- Store call for store update
-- @tparam table define the define that this is acting on
-- @tparam LuaGuiElement element the element that triggered the event
-- @tparam number value the new value for the slider
local function store_update(define,element,value)
element.slider_value = value
event_call(define,element,value)
end
local Slider = {
_prototype=Prototype.extend{
on_element_update = Prototype.event,
on_store_update = Prototype.event,
add_store = Prototype.store(false,store_update),
add_sync_store = Prototype.store(true,store_update)
}
}
--- Creates a new slider element define
-- @tparam[opt] string name the optional debug name that can be added
-- @treturn table the new slider element define
function Slider.new_slider(name)
local self = Gui.new_define(Slider._prototype,name)
self.draw_data.type = 'slider'
self:on_draw(function(player,element)
local min,max = element.get_slider_minimum(),element.get_slider_maximum()
if type(self.min) == 'function' then
min = self.min(player,element)
end
if type(self.max) == 'function' then
max = self.max(player,element)
end
element.set_slider_minimum_maximum(min,max)
if self.store then
local category = self.categorize and self.categorize(element) or nil
local value = self:get_store(category)
if value then element.slider_value = value end
end
if self.auto_label then
self:draw_label(element.parent)
end
end)
Gui.on_value_changed(self.name,function(event)
local element = event.element
local value = element.slider_value
if self.store then
local category = self.categorize and self.categorize(element) or value
self:set_store(category,value)
else
event_call(self,element,value)
end
end)
return self
end
--- Sets the range of a slider, if not used will use default values for a slider
-- @tparam[opt] number min the minimum value that the slider can take
-- @tparam[opt] number max the maximum value that the slider can take
-- @treturn self the define to allow chaining
function Slider._prototype:set_range(min,max)
self.min = min
self.max = max
if type(min) == 'number' then
self.draw_data.minimum_value = min
end
if type(max) == 'number' then
self.draw_data.maximum_value = max
end
return self
end
--- Draws a new label and links its value to the value of this slider, if no store then it will only show one value per player
-- @tparam LuaGuiElement element the parent element that the label will be drawn to
-- @treturn LuaGuiElement the new label element so that styles can be applied
function Slider._prototype:draw_label(element)
local name = self.name..'-label'
if element[name] then return end
local value = 0
if self.store then
local category = self.categorize and self.categorize(element) or value
value = self:get_store(category) or 0
end
local new_element = element.add{
name=name,
type='label',
caption=tostring(math.round(value,2))
}
local categorise = self.categorise or Gui.categorize_by_player
local category = categorise(new_element)
Instances.unregistered_add_element(name,category,new_element)
return new_element
end
--- Enables auto draw of the label, the label will share the same parent element as the slider
-- @tparam[opt=true] boolean state when false will disable the auto draw of the label
-- @treturn self the define to allow chaining
function Slider._prototype:enable_auto_draw_label(state)
if state == false then
self.auto_label = false
else
self.auto_label = true
end
return self
end
return Slider

View File

@@ -0,0 +1,149 @@
--[[-- Core Module - Gui
@module Gui
@alias Prototype
]]
--- Text.
-- Gui class define for text fields and text boxes
-- @section text
--[[
>>>> Functions
Text.new_text_field(name) --- Creates a new text field element define
Text._prototype_field:on_element_update(callback) --- Registers a handler for when an element instance updates
Text._prototype_field:on_store_update(callback) --- Registers a handler for when the stored value updates
Text.new_text_box(name) --- Creates a new text box element define
Text._prototype_field:on_element_update(callback) --- Registers a handler for when an element instance updates
Text._prototype_field:on_store_update(callback) --- Registers a handler for when the stored value updates
Text._prototype_box:set_selectable(state) --- Sets the text box to be selectable
Text._prototype_box:set_word_wrap(state) --- Sets the text box to have word wrap
Text._prototype_box:set_read_only(state) --- Sets the text box to be read only
Other functions present from expcore.gui.core
]]
local Gui = require 'expcore.gui.core' --- @dep expcore.gui.core
local Prototype = require 'expcore.gui.prototype' --- @dep expcore.gui.prototype
local Game = require 'utils.game' --- @dep utils.game
--- Store call for store update
-- @tparam table define the define that this is acting on
-- @tparam LuaGuiElement element the element that triggered the event
-- @tparam string value the new text for the text field
local function store_update(define,element,value)
element.text = value
local player = Game.get_player_by_index(element.player_index)
define:raise_event('on_element_update',player,element,value)
end
local Text = {
_prototype_field=Prototype.extend{
on_element_update = Prototype.event,
on_store_update = Prototype.event,
add_store = Prototype.store(false,store_update),
add_sync_store = Prototype.store(true,store_update)
},
_prototype_box=Prototype.extend{
on_element_update = Prototype.event,
on_store_update = Prototype.event,
add_store = Prototype.store(false,store_update),
add_sync_store = Prototype.store(true,store_update)
}
}
--- Creates a new text field element define
-- @tparam[opt] string name the optional debug name that can be added
-- @treturn table the new text field element define
function Text.new_text_field(name)
local self = Gui.new_define(Text._prototype_field,name)
self.draw_data.type = 'textfield'
self:on_draw(function(player,element)
if self.selectable then
element.selectable = true
end
if self.word_wrap then
element.word_wrap = true
end
if self.read_only then
element.read_only = true
end
if self.store then
local category = self.categorize and self.categorize(element) or nil
local value = self:get_store(category)
if value then element.text = value end
end
end)
Gui.on_text_changed(self.name,function(event)
local element = event.element
local value = element.text
if self.store then
local category = self.categorize and self.categorize(element) or value
self:set_store(category,value)
else
self:raise_event('on_element_update',event.player,element,value)
end
end)
return self
end
--- Creates a new text box element define
-- @tparam[opt] string name the optional debug name that can be added
-- @treturn table the new text box element define
function Text.new_text_box(name)
local self = Text.new_text_field(name)
self.draw_data.type = 'text-box'
local mt = getmetatable(self)
mt.__index = Text._prototype_box
return self
end
--- Sets the text box to be selectable
-- @tparam[opt=true] boolean state when false will set the state to false
-- @treturn self table the define to allow for chaining
function Text._prototype_box:set_selectable(state)
if state == false then
self.selectable = false
else
self.selectable = true
end
return self
end
--- Sets the text box to have word wrap
-- @tparam[opt=true] boolean state when false will set the state to false
-- @treturn self table the define to allow for chaining
function Text._prototype_box:set_word_wrap(state)
if state == false then
self.word_wrap = false
else
self.word_wrap = true
end
return self
end
--- Sets the text box to be read only
-- @tparam[opt=true] boolean state when false will set the state to false
-- @treturn self table the define to allow for chaining
function Text._prototype_box:set_read_only(state)
if state == false then
self.read_only = false
else
self.read_only = true
end
return self
end
return Text