Aleksei-bird 7c9c708c92 Первый фикс
Пачки некоторых позиций увеличены
2024-03-01 20:54:33 +03:00

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 }