310 lines
13 KiB
Lua
310 lines
13 KiB
Lua
if SERVER then return end
|
|
|
|
local resolution = blue_prints.getScreenResolution()
|
|
local run_once_at_start = false
|
|
local folder_states = {} -- Track collapsed state of folders
|
|
local button_height = 45
|
|
|
|
-- Function to move blueprints from a folder to root
|
|
local function moveFilesToRoot(folderPath)
|
|
if folderPath == "[Root Directory]" then return true end
|
|
|
|
local fullFolderPath = blue_prints.normalizePath(blue_prints.save_path .. "/" .. folderPath)
|
|
local rootPath = blue_prints.normalizePath(blue_prints.save_path)
|
|
local files = File.GetFiles(fullFolderPath)
|
|
local success = true
|
|
|
|
if files then
|
|
for _, filepath in ipairs(files) do
|
|
if string.match(filepath, "%.txt$") then
|
|
-- Read file content
|
|
local content = blue_prints.readFileContents(filepath)
|
|
if content then
|
|
-- Get just the filename
|
|
local filename = filepath:match("([^/\\]+)$")
|
|
-- Create new path in root
|
|
local newPath = blue_prints.normalizePath(rootPath .. "/" .. filename)
|
|
-- Write to new location
|
|
if not blue_prints.writeFile(newPath, content) then
|
|
success = false
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
return success
|
|
end
|
|
|
|
-- Function to delete a folder and its contents
|
|
local function deleteFolder(folderPath)
|
|
if folderPath == "[Root Directory]" then return false end
|
|
|
|
local fullFolderPath = blue_prints.normalizePath(blue_prints.save_path .. "/" .. folderPath)
|
|
|
|
-- Move all files to root first
|
|
if not moveFilesToRoot(folderPath) then
|
|
return false
|
|
end
|
|
|
|
-- Try to delete the folder
|
|
local success = pcall(function()
|
|
File.DeleteDirectory(fullFolderPath)
|
|
end)
|
|
|
|
-- If first attempt fails, try alternate path
|
|
if not success then
|
|
local altPath = fullFolderPath:gsub("LocalMods/", "local_mods/")
|
|
success = pcall(function()
|
|
File.DeleteDirectory(altPath)
|
|
end)
|
|
end
|
|
|
|
return success
|
|
end
|
|
|
|
local function count_blueprints_in_folder(folderPath)
|
|
local files = File.GetFiles(folderPath)
|
|
local count = 0
|
|
if files then
|
|
for _, filepath in ipairs(files) do
|
|
if string.match(filepath, "%.txt$") then
|
|
count = count + 1
|
|
end
|
|
end
|
|
end
|
|
return count
|
|
end
|
|
|
|
local function formatFolderHeaderText(folderName, isExpanded, blueprintCount)
|
|
return string.format("%s %s (%d blueprints)",
|
|
isExpanded and "▼" or "▶",
|
|
folderName,
|
|
blueprintCount)
|
|
end
|
|
|
|
local function generate_load_gui()
|
|
blue_prints.current_gui_page = GUI.Frame(GUI.RectTransform(Vector2(1, 1), blue_prints.gui_button_frame.RectTransform, GUI.Anchor.Center),
|
|
nil)
|
|
blue_prints.current_gui_page.CanBeFocused = false
|
|
blue_prints.current_gui_page.Visible = false
|
|
|
|
-- Background close button
|
|
local closeButton = GUI.Button(
|
|
GUI.RectTransform(Vector2(1, 1), blue_prints.current_gui_page.RectTransform, GUI.Anchor.Center), "",
|
|
GUI.Alignment.Center, nil)
|
|
closeButton.OnClicked = function()
|
|
blue_prints.current_gui_page.Visible = not blue_prints.current_gui_page.Visible
|
|
end
|
|
|
|
local menuContent = GUI.Frame(GUI.RectTransform(Vector2(0.4, 0.6), blue_prints.current_gui_page.RectTransform,
|
|
GUI.Anchor.Center))
|
|
local mainList = GUI.ListBox(GUI.RectTransform(Vector2(1, 1), menuContent.RectTransform, GUI.Anchor.BottomCenter))
|
|
|
|
-- Title
|
|
local title_text = GUI.TextBlock(GUI.RectTransform(Vector2(1, 0.08), mainList.Content.RectTransform),
|
|
"LOAD BLUEPRINT", nil, nil, GUI.Alignment.Center)
|
|
title_text.TextScale = 1.5
|
|
title_text.TextColor = Color(200, 200, 200)
|
|
|
|
-- Instructions
|
|
local instruction_text = GUI.TextBlock(GUI.RectTransform(Vector2(1, 0.25), mainList.Content.RectTransform),
|
|
'Click a button to load. Hover over the button to see its description. Click folder headers to expand/collapse.\n\n' ..
|
|
'If the base component is not available, FPGAs will be used instead. These components must be in your main inventory, not a toolbelt/backpack etc.\n\n' ..
|
|
'Click anywhere outside this box to cancel.',
|
|
nil, nil, GUI.Alignment.TopLeft)
|
|
instruction_text.Wrap = true
|
|
instruction_text.TextColor = Color(200, 200, 200)
|
|
instruction_text.Padding = Vector4(10, 5, 10, 5)
|
|
|
|
local function createBlueprintButton(filename, filepath, description, componentCount, contentList)
|
|
local buttonContainer = GUI.Frame(GUI.RectTransform(Vector2(1, 0.10), contentList.Content.RectTransform,
|
|
GUI.Anchor.TopCenter))
|
|
buttonContainer.RectTransform.MinSize = Point(0, button_height)
|
|
buttonContainer.RectTransform.MaxSize = Point(9999, button_height)
|
|
|
|
local button_label = filename .. " - " .. tostring(componentCount) .. " FPGAs"
|
|
local leftButton = GUI.Button(
|
|
GUI.RectTransform(Vector2(0.90, 1), buttonContainer.RectTransform, GUI.Anchor.CenterLeft),
|
|
button_label, GUI.Alignment.CenterLeft, "GUIButtonSmall")
|
|
leftButton.TextBlock.Padding = Vector4(80, 0, 0, 0)
|
|
|
|
if description then
|
|
description = description:gsub("
", "\n"):gsub("
", "\n")
|
|
leftButton.ToolTip = description
|
|
else
|
|
leftButton.ToolTip = "No description available"
|
|
end
|
|
|
|
leftButton.OnClicked = function()
|
|
blue_prints.construct_blueprint(filepath)
|
|
blue_prints.current_gui_page.Visible = false
|
|
end
|
|
|
|
local rightButton = GUI.Button(
|
|
GUI.RectTransform(Vector2(0.10, 1), buttonContainer.RectTransform, GUI.Anchor.CenterRight),
|
|
"Delete", GUI.Alignment.Center, "GUIButtonSmall")
|
|
rightButton.ToolTip = "Delete " .. filename
|
|
rightButton.Color = Color(255, 80, 80)
|
|
rightButton.HoverColor = Color(255, 120, 120)
|
|
|
|
rightButton.OnClicked = function()
|
|
local message_box = GUI.MessageBox('Delete Blueprint?',
|
|
'Are you sure you want to delete "' .. filename .. '"?',
|
|
{ 'Cancel', 'Delete' })
|
|
|
|
local cancel_button = nil
|
|
local delete_button = nil
|
|
|
|
if message_box.Buttons[0] == nil then
|
|
cancel_button = message_box.Buttons[1]
|
|
delete_button = message_box.Buttons[2]
|
|
else
|
|
cancel_button = message_box.Buttons[0]
|
|
delete_button = message_box.Buttons[1]
|
|
end
|
|
|
|
delete_button.Color = Color(255, 80, 80)
|
|
delete_button.HoverColor = Color(255, 120, 120)
|
|
|
|
cancel_button.OnClicked = function() message_box.Close() end
|
|
delete_button.OnClicked = function()
|
|
blue_prints.delete_blueprint(filepath)
|
|
blue_prints.current_gui_page.Visible = false
|
|
GUI.AddMessage('Blueprint Deleted', Color.White)
|
|
message_box.Close()
|
|
end
|
|
end
|
|
end
|
|
|
|
-- Process folders
|
|
local folders = blue_prints.getFolderList()
|
|
for _, folderName in ipairs(folders) do
|
|
local folderPath = folderName == "[Root Directory]" and "" or folderName
|
|
local fullFolderPath = blue_prints.normalizePath(blue_prints.save_path .. "/" .. folderPath)
|
|
local blueprintCount = count_blueprints_in_folder(fullFolderPath)
|
|
|
|
folder_states[folderName] = folder_states[folderName] or false
|
|
|
|
-- Create folder container
|
|
local folderContainer = GUI.Frame(GUI.RectTransform(Vector2(1, 0.10), mainList.Content.RectTransform,
|
|
GUI.Anchor.TopCenter))
|
|
folderContainer.RectTransform.MinSize = Point(0, button_height)
|
|
folderContainer.RectTransform.MaxSize = Point(9999, button_height)
|
|
|
|
-- Create folder button with 90% width
|
|
local headerButton = GUI.Button(
|
|
GUI.RectTransform(Vector2(0.90, 1), folderContainer.RectTransform, GUI.Anchor.CenterLeft),
|
|
formatFolderHeaderText(folderName, folder_states[folderName], blueprintCount),
|
|
GUI.Alignment.CenterLeft, "GUIButtonSmall")
|
|
headerButton.TextColor = Color(150, 150, 255)
|
|
headerButton.HoverColor = Color(180, 180, 255, 0.5)
|
|
headerButton.ForceUpperCase = 1
|
|
headerButton.TextBlock.Padding = Vector4(0, 0, 0, 0)
|
|
|
|
-- Add delete button for folder (except root)
|
|
if folderName ~= "[Root Directory]" then
|
|
local deleteButton = GUI.Button(
|
|
GUI.RectTransform(Vector2(0.10, 1), folderContainer.RectTransform, GUI.Anchor.CenterRight),
|
|
"Delete", GUI.Alignment.Center, "GUIButtonSmall")
|
|
deleteButton.ToolTip = "Delete folder and move contents to root"
|
|
deleteButton.Color = Color(255, 80, 80)
|
|
deleteButton.HoverColor = Color(255, 120, 120)
|
|
|
|
deleteButton.OnClicked = function()
|
|
local message_box = GUI.MessageBox('Delete Folder?',
|
|
'Are you sure you want to delete "' ..
|
|
folderName .. '"?\nAll blueprints will be moved to the root folder.',
|
|
{ 'Cancel', 'Delete' })
|
|
|
|
local cancel_button = nil
|
|
local delete_button = nil
|
|
|
|
if message_box.Buttons[0] == nil then
|
|
cancel_button = message_box.Buttons[1]
|
|
delete_button = message_box.Buttons[2]
|
|
else
|
|
cancel_button = message_box.Buttons[0]
|
|
delete_button = message_box.Buttons[1]
|
|
end
|
|
|
|
delete_button.Color = Color(255, 80, 80)
|
|
delete_button.HoverColor = Color(255, 120, 120)
|
|
|
|
cancel_button.OnClicked = function() message_box.Close() end
|
|
delete_button.OnClicked = function()
|
|
if deleteFolder(folderName) then
|
|
blue_prints.current_gui_page.Visible = false
|
|
GUI.AddMessage('Folder Deleted', Color.White)
|
|
message_box.Close()
|
|
-- Regenerate GUI to show updated folder structure
|
|
Timer.Wait(function()
|
|
blue_prints.current_gui_page = generate_load_gui()
|
|
blue_prints.current_gui_page.Visible = true
|
|
end, 100)
|
|
else
|
|
GUI.AddMessage('Failed to delete folder', Color(255, 0, 0))
|
|
message_box.Close()
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
local files = File.GetFiles(fullFolderPath)
|
|
local size_of_listbox = #files * button_height + 20
|
|
|
|
local contentList = GUI.ListBox(GUI.RectTransform(Vector2(1, 0.1), mainList.Content.RectTransform))
|
|
contentList.RectTransform.MinSize = Point(0, size_of_listbox)
|
|
contentList.RectTransform.MaxSize = Point(999999, size_of_listbox)
|
|
contentList.Visible = folder_states[folderName]
|
|
|
|
-- Process files
|
|
if files then
|
|
for _, filepath in ipairs(files) do
|
|
if string.match(filepath, "%.txt$") then
|
|
local filename = filepath:match("([^/\\]+)%.txt$")
|
|
local xmlContent = blue_prints.readFileContents(filepath)
|
|
local description = blue_prints.get_description_from_xml(xmlContent)
|
|
local componentCount = blue_prints.get_component_count_from_xml(xmlContent)
|
|
|
|
createBlueprintButton(filename, folderPath .. "/" .. filename, description, componentCount,
|
|
contentList)
|
|
end
|
|
end
|
|
end
|
|
|
|
headerButton.OnClicked = function()
|
|
folder_states[folderName] = not folder_states[folderName]
|
|
contentList.Visible = folder_states[folderName]
|
|
headerButton.Text = formatFolderHeaderText(folderName, folder_states[folderName], blueprintCount)
|
|
end
|
|
end
|
|
|
|
return blue_prints.current_gui_page
|
|
end
|
|
|
|
local function check_and_rebuild_frame()
|
|
local new_resolution = blue_prints.getScreenResolution()
|
|
if new_resolution ~= resolution or run_once_at_start == false then
|
|
|
|
local spacer = GUI.TextBlock(GUI.RectTransform(Vector2(1, 0.04), blue_prints.gui_button_frame_list.Content.RectTransform), "", nil, nil, GUI.Alignment.Center)
|
|
|
|
local button = GUI.Button(GUI.RectTransform(Vector2(1, 0.1), blue_prints.gui_button_frame_list.Content.RectTransform), "Load Blueprint", GUI.Alignment.Center, "GUIButtonSmall")
|
|
|
|
button.OnClicked = function()
|
|
if blue_prints.current_gui_page then
|
|
blue_prints.current_gui_page.Visible = false
|
|
end
|
|
blue_prints.current_gui_page = generate_load_gui()
|
|
blue_prints.current_gui_page.Visible = true
|
|
end
|
|
|
|
resolution = new_resolution
|
|
run_once_at_start = true
|
|
end
|
|
end
|
|
|
|
Hook.Patch("Barotrauma.Items.Components.CircuitBox", "AddToGUIUpdateList", function()
|
|
check_and_rebuild_frame()
|
|
end, Hook.HookMethodType.After)
|