Добавлены все обновления от сообщества, вплоть до #148
This commit is contained in:
420
ghost-counter/scripts/gui.lua
Normal file
420
ghost-counter/scripts/gui.lua
Normal file
@@ -0,0 +1,420 @@
|
||||
Gui = {}
|
||||
|
||||
---Toggles mod GUI on or off
|
||||
---@param player_index uint Player index
|
||||
---@param state boolean true -> on, false -> off
|
||||
function Gui.toggle(player_index, state)
|
||||
local playerdata = get_make_playerdata(player_index)
|
||||
state = state or not playerdata.is_active
|
||||
|
||||
if state then
|
||||
playerdata.is_active = true
|
||||
|
||||
-- Create mod gui and register event handler
|
||||
Gui.make_gui(player_index)
|
||||
register_inventory_monitoring(true)
|
||||
register_logistics_monitoring(true)
|
||||
else
|
||||
playerdata.is_active = false
|
||||
playerdata.job = {
|
||||
area={},
|
||||
ghosts={},
|
||||
requests={},
|
||||
requests_sorted={}
|
||||
}
|
||||
-- Destroy mod GUI and remove references to it
|
||||
if playerdata.gui.root and playerdata.gui.root.valid then
|
||||
local last_location = playerdata.gui.root.location --[[@as GuiLocation.0]]
|
||||
playerdata.gui.root.destroy()
|
||||
playerdata.gui = {last_location=last_location}
|
||||
end
|
||||
|
||||
-- Unbind event hooks if no no longer needed
|
||||
if not is_inventory_monitoring_needed() then register_inventory_monitoring(false) end
|
||||
if not is_logistics_monitoring_needed() then register_logistics_monitoring(false) end
|
||||
end
|
||||
end
|
||||
|
||||
---Make mod GUI
|
||||
---@param player_index uint Player index
|
||||
function Gui.make_gui(player_index)
|
||||
local playerdata = get_make_playerdata(player_index)
|
||||
local screen = playerdata.luaplayer.gui.screen
|
||||
local window_loc_x, window_loc_y
|
||||
|
||||
-- Restore previous saved location, if any
|
||||
if playerdata.gui.last_location then
|
||||
local location = playerdata.gui.last_location
|
||||
local resolution = playerdata.luaplayer.display_resolution
|
||||
|
||||
window_loc_x = location.x < resolution.width and location.x or nil
|
||||
window_loc_y = location.y < resolution.height and location.y or nil
|
||||
end
|
||||
|
||||
-- Destory existing mod GUI if one exists
|
||||
if screen[NAME.gui.root_frame] then
|
||||
local location = screen[NAME.gui.root_frame].location
|
||||
window_loc_x, window_loc_y = location.x, location.y
|
||||
screen[NAME.gui.root_frame].destroy()
|
||||
end
|
||||
|
||||
playerdata.gui.root = screen.add{
|
||||
type="frame",
|
||||
name=NAME.gui.root_frame,
|
||||
direction="vertical",
|
||||
style=NAME.style.root_frame
|
||||
}
|
||||
|
||||
do
|
||||
local resolution = playerdata.luaplayer.display_resolution
|
||||
local x = window_loc_x or 50
|
||||
local y = window_loc_y or (resolution.height / 2) - 300
|
||||
playerdata.gui.root.location = {x, y}
|
||||
end
|
||||
|
||||
-- Create title bar
|
||||
local titlebar_flow = playerdata.gui.root.add{
|
||||
type="flow",
|
||||
direction="horizontal",
|
||||
style=NAME.style.titlebar_flow
|
||||
}
|
||||
titlebar_flow.drag_target = playerdata.gui.root
|
||||
titlebar_flow.add{
|
||||
type="label",
|
||||
caption="Ghost Counter",
|
||||
ignored_by_interaction=true,
|
||||
style="frame_title"
|
||||
}
|
||||
titlebar_flow.add{
|
||||
type="empty-widget",
|
||||
ignored_by_interaction=true,
|
||||
style=NAME.style.titlebar_space_header
|
||||
}
|
||||
|
||||
local hide_empty = playerdata.options.hide_empty_requests
|
||||
titlebar_flow.add{
|
||||
type="sprite-button",
|
||||
name=NAME.gui.hide_empty_button,
|
||||
tooltip={"ghost-counter-gui.hide-empty-requests-tooltip"},
|
||||
sprite=hide_empty and NAME.sprite.hide_empty_black or NAME.sprite.hide_empty_white,
|
||||
hovered_sprite=NAME.sprite.hide_empty_black,
|
||||
clicked_sprite=hide_empty and NAME.sprite.hide_empty_white or NAME.sprite.hide_empty_black,
|
||||
style=hide_empty and NAME.style.titlebar_button_active or NAME.style.titlebar_button
|
||||
}
|
||||
titlebar_flow.add{
|
||||
type="sprite-button",
|
||||
name=NAME.gui.close_button,
|
||||
sprite="utility/close_white",
|
||||
hovered_sprite="utility/close_black",
|
||||
clicked_sprite="utility/close_black",
|
||||
tooltip={"ghost-counter-gui.close-button-tooltip"},
|
||||
style="close_button"
|
||||
}
|
||||
|
||||
local deep_frame = playerdata.gui.root.add{
|
||||
type="frame",
|
||||
direction="vertical",
|
||||
style=NAME.style.inside_deep_frame
|
||||
}
|
||||
|
||||
local toolbar = deep_frame.add{
|
||||
type="frame",
|
||||
direction="horizontal",
|
||||
style=NAME.style.topbar_frame
|
||||
}
|
||||
toolbar.add{
|
||||
type="sprite-button",
|
||||
name=NAME.gui.get_signals_button,
|
||||
sprite=NAME.sprite.get_signals_white,
|
||||
hovered_sprite=NAME.sprite.get_signals_black,
|
||||
clicked_sprite=NAME.sprite.get_signals_black,
|
||||
tooltip={"ghost-counter-gui.get-signals-tooltip"},
|
||||
style=NAME.style.get_signals_button
|
||||
}
|
||||
toolbar.add{
|
||||
type="empty-widget",
|
||||
style=NAME.style.topbar_space
|
||||
}
|
||||
toolbar.add{
|
||||
type="sprite-button",
|
||||
name=NAME.gui.craft_all_button,
|
||||
sprite=NAME.sprite.craft_all_white,
|
||||
hovered_sprite=NAME.sprite.craft_all_black,
|
||||
clicked_sprite=NAME.sprite.craft_all_black,
|
||||
tooltip={"ghost-counter-gui.craft-all-tooltip"},
|
||||
style=NAME.style.get_signals_button
|
||||
}
|
||||
toolbar.add{
|
||||
type="button",
|
||||
name=NAME.gui.request_all_button,
|
||||
caption={"ghost-counter-gui.request-all-caption"},
|
||||
tooltip={"ghost-counter-gui.request-all-tooltip"},
|
||||
style=NAME.style.ghost_request_all_button
|
||||
}
|
||||
toolbar.add{
|
||||
type="sprite-button",
|
||||
name=NAME.gui.cancel_all_button,
|
||||
sprite=NAME.sprite.cancel_white,
|
||||
hovered_sprite=NAME.sprite.cancel_black,
|
||||
clicked_sprite=NAME.sprite.cancel_black,
|
||||
tooltip={"ghost-counter-gui.cancel-all-tooltip"},
|
||||
style=NAME.style.ghost_cancel_all_button
|
||||
}
|
||||
|
||||
playerdata.gui.requests_container = deep_frame.add{
|
||||
type="scroll-pane",
|
||||
name=NAME.gui.scroll_pane,
|
||||
style=NAME.style.scroll_pane
|
||||
}
|
||||
|
||||
Gui.make_list(player_index)
|
||||
end
|
||||
|
||||
---Creates the list of request frames in the GUI
|
||||
---@param player_index uint Player index
|
||||
function Gui.make_list(player_index)
|
||||
local playerdata = get_make_playerdata(player_index)
|
||||
|
||||
-- Create a new row frame for each request
|
||||
playerdata.gui.requests = {}
|
||||
for _, request in pairs(playerdata.job.requests_sorted) do
|
||||
Gui.make_row(player_index, request)
|
||||
end
|
||||
end
|
||||
|
||||
---Returns request button properties based on request fulfillment and other criteria
|
||||
---@param request table `request` table
|
||||
---@param one_time_request table `playerdata.logistic_requests[request.name]`
|
||||
---@return boolean enabled Whehter button should be enabled
|
||||
---@return string style Style that should be applied to the button
|
||||
---@return LocalisedString tooltip Tooltip shown for button
|
||||
function make_request_button_properties(request, one_time_request)
|
||||
local logistic_request = request.logistic_request or {}
|
||||
|
||||
local enabled = ((logistic_request.min or 0) < request.count) or one_time_request and true or
|
||||
false
|
||||
local style =
|
||||
((logistic_request.min or 0) < request.count) and NAME.style.ghost_request_button or
|
||||
NAME.style.ghost_request_active_button
|
||||
|
||||
local str = "[item=" .. request.name .. "] "
|
||||
|
||||
local tooltip
|
||||
if enabled then
|
||||
tooltip = ((logistic_request.min or 0) < request.count) and
|
||||
{"ghost-counter-gui.set-temporary-request-tooltip", request.count, str} or
|
||||
{"ghost-counter-gui.unset-temporary-request-tooltip"}
|
||||
else
|
||||
tooltip = {"ghost-counter-gui.existing-logistic-request-tooltip"}
|
||||
end
|
||||
|
||||
return enabled, style, tooltip
|
||||
end
|
||||
|
||||
---Updates the list of request frames in the GUI
|
||||
---@param player_index uint Player index
|
||||
function Gui.update_list(player_index)
|
||||
local playerdata = get_make_playerdata(player_index)
|
||||
if not playerdata.is_active or not playerdata.gui.requests then return end
|
||||
|
||||
local indices = {count=1, sprite=2, label=3, inventory=4, request=5}
|
||||
|
||||
-- Update gui elements with new values
|
||||
for name, frame in pairs(playerdata.gui.requests) do
|
||||
local request = playerdata.job.requests[name]
|
||||
|
||||
if request.count > 0 or not playerdata.options.hide_empty_requests then
|
||||
frame.visible = true
|
||||
-- Update ghost count
|
||||
frame.children[indices.count].caption = request.count
|
||||
|
||||
-- Update amont in inventory
|
||||
frame.children[indices.inventory].caption = request.inventory
|
||||
|
||||
-- Calculate amount missing
|
||||
local diff = request.count - request.inventory
|
||||
|
||||
-- If amount needed exceeds amount in inventory, show request button
|
||||
local request_element = frame.children[indices.request]
|
||||
if diff > 0 then
|
||||
local enabled, style, tooltip = make_request_button_properties(request,
|
||||
playerdata.logistic_requests[request.name])
|
||||
|
||||
if request_element.type == "button" then
|
||||
request_element.enabled = enabled
|
||||
request_element.style = style
|
||||
request_element.caption = diff
|
||||
request_element.tooltip = tooltip
|
||||
else
|
||||
frame.children[indices.request].destroy()
|
||||
frame.add{
|
||||
type="button",
|
||||
caption=diff,
|
||||
enabled=enabled,
|
||||
style=style,
|
||||
tooltip=tooltip,
|
||||
tags={ghost_counter_request=request.name}
|
||||
}
|
||||
end
|
||||
-- Otherwise create request-fulfilled checkmark previous element was a request button
|
||||
elseif request_element.type == "button" then
|
||||
request_element.destroy()
|
||||
|
||||
local sprite_container = frame.add{
|
||||
type="flow",
|
||||
direction="horizontal",
|
||||
style=NAME.style.ghost_request_fulfilled_flow
|
||||
}
|
||||
sprite_container.add{
|
||||
type="sprite",
|
||||
sprite="utility/check_mark_white",
|
||||
resize_to_sprite=false,
|
||||
style=NAME.style.ghost_request_fulfilled_sprite
|
||||
}
|
||||
end
|
||||
else
|
||||
frame.visible = false
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
---Generates the row frame for a given request table
|
||||
---@param player_index uint Player index
|
||||
---@param request table `request` table, containing name, count, inventory, etc.
|
||||
function Gui.make_row(player_index, request)
|
||||
local playerdata = get_make_playerdata(player_index)
|
||||
local parent = playerdata.gui.requests_container
|
||||
|
||||
local localized_name = game.item_prototypes[request.name].localised_name
|
||||
|
||||
-- Row frame
|
||||
local frame = parent.add{type="frame", direction="horizontal", style=NAME.style.row_frame}
|
||||
playerdata.gui.requests[request.name] = frame
|
||||
|
||||
-- Ghost (item) count
|
||||
frame.add{type="label", caption=request.count, style=NAME.style.ghost_number_label}
|
||||
|
||||
-- Item sprite
|
||||
frame.add{
|
||||
type="sprite",
|
||||
sprite="item/" .. request.name,
|
||||
resize_to_sprite=false,
|
||||
style=NAME.style.ghost_sprite
|
||||
}
|
||||
|
||||
-- Item or tile localized name
|
||||
frame.add{type="label", caption=localized_name, style=NAME.style.ghost_name_label}
|
||||
|
||||
-- Amount in inventory
|
||||
frame.add{type="label", caption=request.inventory, style=NAME.style.inventory_number_label}
|
||||
|
||||
-- Calculate amount missing
|
||||
local diff = request.count - request.inventory
|
||||
|
||||
-- Show one-time request logistic button
|
||||
if diff > 0 then
|
||||
local enabled, style, tooltip = make_request_button_properties(request,
|
||||
playerdata.logistic_requests[request.name])
|
||||
|
||||
frame.add{
|
||||
type="button",
|
||||
caption=diff,
|
||||
enabled=enabled,
|
||||
style=style,
|
||||
tooltip=tooltip,
|
||||
tags={ghost_counter_request=request.name}
|
||||
}
|
||||
else -- Show request fulfilled sprite
|
||||
local sprite_container = frame.add{
|
||||
type="flow",
|
||||
direction="horizontal",
|
||||
style=NAME.style.ghost_request_fulfilled_flow
|
||||
}
|
||||
sprite_container.add{
|
||||
type="sprite",
|
||||
sprite="utility/check_mark_white",
|
||||
resize_to_sprite=false,
|
||||
style=NAME.style.ghost_request_fulfilled_sprite
|
||||
}
|
||||
end
|
||||
|
||||
-- Hide frame if ghost count is 0 and player toggled hide empty requests
|
||||
frame.visible = request.count > 0 or not playerdata.options.hide_empty_requests and true or
|
||||
false
|
||||
end
|
||||
|
||||
---Event handler for GUI button clicks
|
||||
---@param event EventData.on_gui_click Event table
|
||||
function Gui.on_gui_click(event)
|
||||
local player_index = event.player_index
|
||||
local element = event.element
|
||||
local element_name = element.name
|
||||
|
||||
if element.name == NAME.gui.close_button then
|
||||
-- Close button
|
||||
Gui.toggle(player_index, false)
|
||||
elseif element.tags and element.tags.ghost_counter_request then
|
||||
-- One-time logistic request/craft button
|
||||
local playerdata = get_make_playerdata(player_index)
|
||||
local request_name = element.tags.ghost_counter_request --[[@as string]]
|
||||
if event.shift == true then
|
||||
local request = playerdata.job.requests[request_name]
|
||||
if request then
|
||||
local result, crafted = craft_request(event.player_index, request)
|
||||
local player = game.get_player(player_index) --[[@as LuaPlayer]]
|
||||
if result == "no-crafts-needed" then
|
||||
player.create_local_flying_text{
|
||||
text={"ghost-counter-message.crafts-not-needed"},
|
||||
create_at_cursor=true
|
||||
}
|
||||
elseif result == "attempted" and crafted == 0 then
|
||||
player.create_local_flying_text{
|
||||
text={"ghost-counter-message.crafts-attempted-none"},
|
||||
create_at_cursor=true
|
||||
}
|
||||
end
|
||||
end
|
||||
else
|
||||
if not playerdata.logistic_requests[request_name] then
|
||||
make_one_time_logistic_request(player_index, request_name)
|
||||
Gui.update_list(player_index)
|
||||
else
|
||||
restore_prior_logistic_request(player_index, request_name)
|
||||
Gui.update_list(player_index)
|
||||
end
|
||||
end
|
||||
elseif element_name == NAME.gui.hide_empty_button then
|
||||
local playerdata = get_make_playerdata(player_index)
|
||||
local new_state = not playerdata.options.hide_empty_requests
|
||||
playerdata.options.hide_empty_requests = new_state
|
||||
|
||||
element.style = new_state and NAME.style.titlebar_button_active or
|
||||
NAME.style.titlebar_button
|
||||
element.sprite = new_state and NAME.sprite.hide_empty_black or NAME.sprite.hide_empty_white
|
||||
element.clicked_sprite = new_state and NAME.sprite.hide_empty_white or
|
||||
NAME.sprite.hide_empty_black
|
||||
|
||||
Gui.update_list(player_index)
|
||||
elseif element_name == NAME.gui.get_signals_button then
|
||||
make_combinators_blueprint(event.player_index)
|
||||
elseif element_name == NAME.gui.craft_all_button then
|
||||
local playerdata = get_make_playerdata(player_index)
|
||||
for _, request in pairs(playerdata.job.requests) do
|
||||
craft_request(player_index, request)
|
||||
end
|
||||
elseif element_name == NAME.gui.request_all_button then
|
||||
local playerdata = get_make_playerdata(player_index)
|
||||
for _, request in pairs(playerdata.job.requests) do
|
||||
if request.count > 0 and not playerdata.logistic_requests[request.name] then
|
||||
make_one_time_logistic_request(player_index, request.name)
|
||||
end
|
||||
end
|
||||
|
||||
Gui.update_list(player_index)
|
||||
elseif element_name == NAME.gui.cancel_all_button then
|
||||
cancel_all_one_time_requests(player_index)
|
||||
|
||||
Gui.update_list(player_index)
|
||||
end
|
||||
end
|
||||
script.on_event(defines.events.on_gui_click, Gui.on_gui_click)
|
||||
Reference in New Issue
Block a user