333 lines
14 KiB
Lua
333 lines
14 KiB
Lua
-- ** LOCAL UTIL **
|
|
local function add_preference_box(content_frame, type)
|
|
local bordered_frame = content_frame.add{type="frame", direction="vertical", style="fp_frame_bordered_stretch"}
|
|
|
|
local caption = {"fp.info_label", {"fp.preference_".. type .. "_title"}}
|
|
local tooltip = {"fp.preference_".. type .. "_title_tt"}
|
|
bordered_frame.add{type="label", caption=caption, tooltip=tooltip, style="caption_label"}
|
|
|
|
return bordered_frame
|
|
end
|
|
|
|
local function refresh_defaults_table(player, modal_elements, type, category_id)
|
|
local table_prototypes, prototypes
|
|
|
|
if not category_id then
|
|
table_prototypes = modal_elements[type]
|
|
prototypes = global.prototypes[type]
|
|
else
|
|
table_prototypes = modal_elements[type][category_id]
|
|
prototypes = global.prototypes[type][category_id].members
|
|
end
|
|
|
|
table_prototypes.clear()
|
|
local default_proto = prototyper.defaults.get(player, type, category_id)
|
|
|
|
for prototype_id, prototype in ipairs(prototypes) do
|
|
local selected = (default_proto.id == prototype_id)
|
|
local style = (selected) and "flib_slot_button_green_small" or "flib_slot_button_default_small"
|
|
local first_line = (selected) and {"fp.tt_title_with_note", prototype.localised_name, {"fp.selected"}}
|
|
or {"fp.tt_title", prototype.localised_name}
|
|
local tooltip = {"", first_line, "\n", prototyper.util.get_attributes(prototype)}
|
|
|
|
table_prototypes.add{type="sprite-button", sprite=prototype.sprite, tooltip=tooltip, style=style,
|
|
tags={mod="fp", on_gui_click="select_preference_default", type=type, prototype_id=prototype_id,
|
|
category_id=category_id}, mouse_button_filter={"left"}}
|
|
end
|
|
end
|
|
|
|
|
|
local preference_structures = {}
|
|
|
|
function preference_structures.checkboxes(preferences, content_frame, type, preference_names)
|
|
local preference_box = add_preference_box(content_frame, type)
|
|
local flow_checkboxes = preference_box.add{type="flow", direction="vertical"}
|
|
|
|
for _, pref_name in ipairs(preference_names) do
|
|
local identifier = type .. "_" .. pref_name
|
|
local caption = {"fp.info_label", {"fp.preference_" .. identifier}}
|
|
local tooltip ={"fp.preference_" .. identifier .. "_tt"}
|
|
flow_checkboxes.add{type="checkbox", state=preferences[pref_name], caption=caption, tooltip=tooltip,
|
|
tags={mod="fp", on_gui_checked_state_changed="toggle_preference", type=type, name=pref_name}}
|
|
end
|
|
end
|
|
|
|
function preference_structures.mb_defaults(preferences, content_frame)
|
|
local mb_defaults = preferences.mb_defaults
|
|
local preference_box = add_preference_box(content_frame, "mb_defaults")
|
|
|
|
local function add_mb_default_button(parent_flow, type)
|
|
local flow = parent_flow.add{type="flow", direction="horizontal"}
|
|
flow.style.vertical_align = "center"
|
|
flow.style.horizontal_spacing = 8
|
|
|
|
flow.add{type="label", caption={"fp.info_label", {"fp.preference_mb_default_" .. type}},
|
|
tooltip={"fp.preference_mb_default_" .. type .. "_tt"}}
|
|
local item = (mb_defaults[type] ~= nil) and mb_defaults[type].name or nil
|
|
flow.add{type="choose-elem-button", elem_type="item", item=item, style="fp_sprite-button_inset_tiny",
|
|
elem_filters={{filter="type", type="module"}, {filter="flag", flag="hidden", mode="and", invert=true}},
|
|
tags={mod="fp", on_gui_elem_changed="change_mb_default", type=type}}
|
|
end
|
|
|
|
local table_mb_defaults = preference_box.add{type="table", column_count=3}
|
|
table_mb_defaults.style.horizontal_spacing = 18
|
|
-- Table alignment is so stupid
|
|
table_mb_defaults.style.column_alignments[1] = "left"
|
|
table_mb_defaults.style.column_alignments[2] = "right"
|
|
table_mb_defaults.style.column_alignments[3] = "right"
|
|
|
|
table_mb_defaults.add{type="label", caption={"", {"fp.pu_machine", 1}, ":"}}
|
|
add_mb_default_button(table_mb_defaults, "machine")
|
|
add_mb_default_button(table_mb_defaults, "machine_secondary")
|
|
|
|
table_mb_defaults.add{type="label", caption={"", {"fp.pu_beacon", 1}, ":"}}
|
|
add_mb_default_button(table_mb_defaults, "beacon")
|
|
|
|
local beacon_amount_flow = table_mb_defaults.add{type="flow", direction="horizontal"}
|
|
beacon_amount_flow.style.vertical_align = "center"
|
|
beacon_amount_flow.style.horizontal_spacing = 8
|
|
|
|
beacon_amount_flow.add{type="label", caption={"fp.info_label", {"fp.preference_mb_default_beacon_amount"}},
|
|
tooltip={"fp.preference_mb_default_beacon_amount_tt"}}
|
|
|
|
local beacon_amount = (BEACON_OVERLOAD_ACTIVE) and "1" or tostring(mb_defaults.beacon_count or "")
|
|
local textfield_amount = beacon_amount_flow.add{type="textfield", text=beacon_amount,
|
|
enabled=(not BEACON_OVERLOAD_ACTIVE), tags={mod="fp", on_gui_text_changed="mb_default_beacon_amount"}}
|
|
util.gui.setup_numeric_textfield(textfield_amount, true, false)
|
|
textfield_amount.style.width = 42
|
|
end
|
|
|
|
function preference_structures.prototypes(player, content_frame, modal_elements, type)
|
|
local preference_box = add_preference_box(content_frame, ("default_" .. type))
|
|
local table_prototypes = preference_box.add{type="table", column_count=3}
|
|
table_prototypes.style.horizontal_spacing = 20
|
|
table_prototypes.style.vertical_spacing = 8
|
|
table_prototypes.style.top_margin = 4
|
|
|
|
local function add_defaults_table(column_count, category_id)
|
|
local frame = table_prototypes.add{type="frame", direction="horizontal", style="fp_frame_deep_slots_small"}
|
|
local table = frame.add{type="table", column_count=column_count, style="filter_slot_table"}
|
|
|
|
if category_id then
|
|
modal_elements[type] = modal_elements[type] or {}
|
|
modal_elements[type][category_id] = table
|
|
else
|
|
modal_elements[type] = table
|
|
end
|
|
end
|
|
|
|
if not prototyper.data_types[type] then
|
|
local prototypes = global.prototypes[type]
|
|
if #prototypes < 2 then preference_box.visible = false; return end
|
|
|
|
table_prototypes.add{type="empty-widget", style="flib_horizontal_pusher"}
|
|
add_defaults_table(8, nil)
|
|
refresh_defaults_table(player, modal_elements, type, nil)
|
|
|
|
else
|
|
local categories = global.prototypes[type]
|
|
if not next(categories) then preference_box.visible = false; return end
|
|
|
|
local any_category_visible = false
|
|
for category_id, category in ipairs(categories) do
|
|
local prototypes = category.members
|
|
|
|
if #prototypes > 1 then
|
|
any_category_visible = true
|
|
|
|
table_prototypes.add{type="label", caption=("'" .. category.name .. "'")}
|
|
table_prototypes.add{type="empty-widget", style="flib_horizontal_pusher"}
|
|
|
|
add_defaults_table(8, category_id)
|
|
refresh_defaults_table(player, modal_elements, type, category_id)
|
|
end
|
|
end
|
|
if not any_category_visible then preference_box.visible = false end
|
|
end
|
|
end
|
|
|
|
|
|
local function handle_checkbox_preference_change(player, tags, event)
|
|
local preference_name = tags.name
|
|
util.globals.preferences(player)[preference_name] = event.element.state
|
|
|
|
local refresh = util.globals.modal_data(player).refresh
|
|
|
|
if tags.type == "production" or preference_name == "round_button_numbers"
|
|
or preference_name == "show_floor_items" or preference_name == "fold_out_subfloors" then
|
|
refresh.production = true
|
|
end
|
|
|
|
if preference_name == "ingredient_satisfaction" then
|
|
-- Only recalculate if the satisfaction data will actually be shown now
|
|
refresh.update_ingredient_satisfaction = (event.element.state)
|
|
refresh.production = true -- always refresh production
|
|
|
|
elseif preference_name == "attach_subfactory_products" then
|
|
refresh.subfactory_list = true
|
|
end
|
|
end
|
|
|
|
local function handle_mb_default_change(player, tags, event)
|
|
local mb_defaults = util.globals.preferences(player).mb_defaults
|
|
local module_name = event.element.elem_value
|
|
|
|
mb_defaults[tags.type] = (module_name ~= nil) and MODULE_NAME_MAP[module_name] or nil
|
|
end
|
|
|
|
local function handle_default_prototype_change(player, tags, event)
|
|
local type = tags.type
|
|
local category_id = tags.category_id
|
|
|
|
local modal_data = util.globals.modal_data(player)
|
|
if type == "belts" then modal_data.refresh.view_state = true end
|
|
if type == "wagons" then modal_data.refresh.production = true end
|
|
|
|
prototyper.defaults.set(player, type, tags.prototype_id, category_id)
|
|
refresh_defaults_table(player, modal_data.modal_elements, type, category_id)
|
|
|
|
-- If this was an shift-click, set this prototype on every category that also has it
|
|
if event.shift and type == "machines" then
|
|
local new_default_prototype = prototyper.defaults.get(player, type, category_id)
|
|
|
|
for _, secondary_category in pairs(PROTOTYPE_MAPS[type]) do
|
|
if table_size(secondary_category.members) > 1 then -- don't attempt to change categories with only one machine
|
|
local secondary_prototype = secondary_category.members[new_default_prototype.name]
|
|
|
|
if secondary_prototype ~= nil then
|
|
prototyper.defaults.set(player, type, secondary_prototype.id, secondary_category.id)
|
|
refresh_defaults_table(player, modal_data.modal_elements, type, secondary_category.id)
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
|
|
local function open_preferences_dialog(player, modal_data)
|
|
local preferences = util.globals.preferences(player)
|
|
local modal_elements = modal_data.modal_elements
|
|
modal_data.refresh = {}
|
|
|
|
local flow_content = modal_elements.dialog_flow.add{type="flow", direction="horizontal"}
|
|
flow_content.style.horizontal_spacing = 12
|
|
|
|
local function add_content_frame()
|
|
local content_frame = flow_content.add{type="frame", direction="vertical", style="inside_shallow_frame"}
|
|
content_frame.style.vertically_stretchable = true
|
|
|
|
return content_frame.add{type="scroll-pane", style="flib_naked_scroll_pane"}
|
|
end
|
|
|
|
local left_content_frame = add_content_frame()
|
|
|
|
local info_frame = left_content_frame.add{type="frame", direction="vertical", style="fp_frame_bordered_stretch"}
|
|
local label_preferences_info = info_frame.add{type="label", caption={"fp.preferences_info"}}
|
|
label_preferences_info.style.single_line = false
|
|
label_preferences_info.style.width = 335
|
|
|
|
local support_frame = left_content_frame.add{type="frame", direction="vertical", style="fp_frame_bordered_stretch"}
|
|
support_frame.add{type="label", caption={"fp.preferences_support"}}
|
|
|
|
local general_preference_names = {"attach_subfactory_products", "show_floor_items", "fold_out_subfloors",
|
|
"ingredient_satisfaction", "round_button_numbers", "ignore_barreling_recipes", "ignore_recycling_recipes"}
|
|
preference_structures.checkboxes(preferences, left_content_frame, "general", general_preference_names)
|
|
|
|
local production_preference_names = {"done_column", "pollution_column", "line_comment_column"}
|
|
preference_structures.checkboxes(preferences, left_content_frame, "production", production_preference_names)
|
|
|
|
preference_structures.mb_defaults(preferences, left_content_frame)
|
|
|
|
local right_content_frame = add_content_frame()
|
|
|
|
preference_structures.prototypes(player, right_content_frame, modal_elements, "belts")
|
|
preference_structures.prototypes(player, right_content_frame, modal_elements, "beacons")
|
|
preference_structures.prototypes(player, right_content_frame, modal_elements, "wagons")
|
|
preference_structures.prototypes(player, right_content_frame, modal_elements, "fuels")
|
|
preference_structures.prototypes(player, right_content_frame, modal_elements, "machines")
|
|
end
|
|
|
|
local function close_preferences_dialog(player, _)
|
|
-- We refresh all these things only when closing to avoid duplicate refreshes
|
|
local refresh = util.globals.modal_data(player).refresh
|
|
|
|
if refresh.update_ingredient_satisfaction then
|
|
local player_table = util.globals.player_table(player)
|
|
Factory.update_ingredient_satisfactions(player_table.factory)
|
|
Factory.update_ingredient_satisfactions(player_table.archive)
|
|
end
|
|
|
|
if refresh.subfactory_list then
|
|
util.raise.refresh(player, "subfactory_list", nil)
|
|
end
|
|
|
|
local context_to_refresh = nil -- don't refresh by default
|
|
|
|
-- The order of these matters, they go from smallest context to biggest
|
|
if refresh.production then
|
|
context_to_refresh = "production"
|
|
end
|
|
|
|
if refresh.view_state then
|
|
-- Rebuilding state requires every button that shows item amounts to refresh
|
|
view_state.rebuild_state(player)
|
|
context_to_refresh = "production"
|
|
end
|
|
|
|
if refresh.calculations then
|
|
local context = util.globals.context(player)
|
|
solver.update(player, context.subfactory)
|
|
context_to_refresh = "subfactory"
|
|
end
|
|
|
|
if context_to_refresh then
|
|
util.raise.refresh(player, context_to_refresh, nil)
|
|
end
|
|
end
|
|
|
|
|
|
-- ** EVENTS **
|
|
local listeners = {}
|
|
|
|
listeners.gui = {
|
|
on_gui_click = {
|
|
{
|
|
name = "select_preference_default",
|
|
handler = handle_default_prototype_change
|
|
}
|
|
},
|
|
on_gui_text_changed = {
|
|
{
|
|
name = "mb_default_beacon_amount",
|
|
handler = (function(player, _, event)
|
|
local mb_defaults = util.globals.preferences(player).mb_defaults
|
|
mb_defaults.beacon_count = tonumber(event.element.text)
|
|
end)
|
|
}
|
|
},
|
|
on_gui_checked_state_changed = {
|
|
{
|
|
name = "toggle_preference",
|
|
handler = handle_checkbox_preference_change
|
|
}
|
|
},
|
|
on_gui_elem_changed = {
|
|
{
|
|
name = "change_mb_default",
|
|
handler = handle_mb_default_change
|
|
}
|
|
}
|
|
}
|
|
|
|
listeners.dialog = {
|
|
dialog = "preferences",
|
|
metadata = (function(_) return {
|
|
caption = {"fp.preferences"},
|
|
create_content_frame = false
|
|
} end),
|
|
open = open_preferences_dialog,
|
|
close = close_preferences_dialog
|
|
}
|
|
|
|
return { listeners }
|