local J={}function AnchorTool.Equip()ShowUI()BindShortcutKeys()end function AnchorTool.Unequip()HideUI()ClearConnections()end function ClearConnections()for O,b in pairs(J)do b:Disconnect()J[O]=nil end end function ShowUI()if UI then UI.Visible=true UIUpdater=Support.ScheduleRecurringTask(UpdateUI,.1)return end UI=Core.Tool.Interfaces.BTAnchorToolGUI:Clone()UI.Parent=Core.UI UI.Visible=true local J=UI.Status.Anchored.Button local O=UI.Status.Unanchored.Button J.MouseButton1Click:Connect(function()SetProperty("\065\110\099\104\111\114\101\100",true)end)O.MouseButton1Click:Connect(function()SetProperty("\065\110\099\104\111\114\101\100",false)end)UIUpdater=Support.ScheduleRecurringTask(UpdateUI,.1)end function UpdateUI()if not UI then return end local J=Support.IdentifyCommonProperty(Selection.Parts,"\065\110\099\104\111\114\101\100")if J==true then Core.ToggleSwitch("\065\110\099\104\111\114\101\100",UI.Status)elseif J==false then Core.ToggleSwitch("\085\110\097\110\099\104\111\114\101\100",UI.Status)elseif J==nil then Core.ToggleSwitch(nil,UI.Status)end end function HideUI()if not UI then return end UI.Visible=false UIUpdater:Stop()end function SetProperty(J,O)if O==nil then return end TrackChange()for b,D in pairs(Selection.Parts)do table.insert(HistoryRecord.Before,{Part=D,[J]=D[J]})table.insert(HistoryRecord.After,{Part=D,[J]=O})end RegisterChange()end function BindShortcutKeys()table.insert(J,UserInputService.InputBegan:Connect(function(J,O)if O then return end if J.UserInputType~=Enum.UserInputType.Keyboard then return end if UserInputService:GetFocusedTextBox()then return end if J.KeyCode==Enum.KeyCode.Return or J.KeyCode==Enum.KeyCode.KeypadEnter then ToggleAnchors()end end))end function ToggleAnchors()SetProperty("\065\110\099\104\111\114\101\100",not Support.IdentifyCommonProperty(Selection.Parts,"\065\110\099\104\111\114\101\100"))end function TrackChange()HistoryRecord={Before={};After={};Selection=Selection.Items,Unapply=function(J)Selection.Replace(J.Selection)Core.SyncAPI:Invoke("\083\121\110\099\065\110\099\104\111\114",J.Before)end;Apply=function(J)Selection.Replace(J.Selection)Core.SyncAPI:Invoke("\083\121\110\099\065\110\099\104\111\114",J.After)end}end function RegisterChange()if not HistoryRecord then return end Core.SyncAPI:Invoke("\083\121\110\099\065\110\099\104\111\114",HistoryRecord.After)Core.History.Add(HistoryRecord)HistoryRecord=nil end

local Connections = {};

function AnchorTool.Equip()
	-- Enables the tool's equipped functionality

	-- Start up our interface
	ShowUI();
	BindShortcutKeys();

end;

function AnchorTool.Unequip()
	-- Disables the tool's equipped functionality

	-- Clear unnecessary resources
	HideUI();
	ClearConnections();

end;

function ClearConnections()
	-- Clears out temporary connections

	for ConnectionKey, Connection in pairs(Connections) do
		Connection:Disconnect();
		Connections[ConnectionKey] = nil;
	end;

end;

function ShowUI()
	-- Creates and reveals the UI

	-- Reveal UI if already created
	if UI then

		-- Reveal the UI
		UI.Visible = true;

		-- Update the UI every 0.1 seconds
		UIUpdater = Support.ScheduleRecurringTask(UpdateUI, 0.1);

		-- Skip UI creation
		return;

	end;

	-- Create the UI
	UI = Core.Tool.Interfaces.BTAnchorToolGUI:Clone();
	UI.Parent = Core.UI;
	UI.Visible = true;

	-- References to UI elements
	local AnchorButton = UI.Status.Anchored.Button;
	local UnanchorButton = UI.Status.Unanchored.Button;

	-- Enable the anchor status switch
	AnchorButton.MouseButton1Click:Connect(function ()
		SetProperty('Anchored', true);
	end);
	UnanchorButton.MouseButton1Click:Connect(function ()
		SetProperty('Anchored', false);
	end);

	-- Update the UI every 0.1 seconds
	UIUpdater = Support.ScheduleRecurringTask(UpdateUI, 0.1);

end;

function UpdateUI()
	-- Updates information on the UI

	-- Make sure the UI's on
	if not UI then
		return;
	end;

	-- Check the common anchor status of selection
	local Anchored = Support.IdentifyCommonProperty(Selection.Parts, 'Anchored');

	-- Update the anchor option switch
	if Anchored == true then
		Core.ToggleSwitch('Anchored', UI.Status);

	-- If the selection is unanchored
	elseif Anchored == false then
		Core.ToggleSwitch('Unanchored', UI.Status);

	-- If the anchor status varies, don't select a current switch
	elseif Anchored == nil then
		Core.ToggleSwitch(nil, UI.Status);
	end;

end;

function HideUI()
	-- Hides the tool UI

	-- Make sure there's a UI
	if not UI then
		return;
	end;

	-- Hide the UI
	UI.Visible = false;

	-- Stop updating the UI
	UIUpdater:Stop();

end;

function SetProperty(Property, Value)

	-- Make sure the given value is valid
	if Value == nil then
		return;
	end;

	-- Start a history record
	TrackChange();

	-- Go through each part
	for _, Part in pairs(Selection.Parts) do

		-- Store the state of the part before modification
		table.insert(HistoryRecord.Before, { Part = Part, [Property] = Part[Property] });

		-- Create the change request for this part
		table.insert(HistoryRecord.After, { Part = Part, [Property] = Value });

	end;

	-- Register the changes
	RegisterChange();

end;

function BindShortcutKeys()
	-- Enables useful shortcut keys for this tool

	-- Track user input while this tool is equipped
	table.insert(Connections, UserInputService.InputBegan:Connect(function (InputInfo, GameProcessedEvent)

		-- Make sure this is an intentional event
		if GameProcessedEvent then
			return;
		end;

		-- Make sure this input is a key press
		if InputInfo.UserInputType ~= Enum.UserInputType.Keyboard then
			return;
		end;

		-- Make sure it wasn't pressed while typing
		if UserInputService:GetFocusedTextBox() then
			return;
		end;

		-- Check if the enter key was pressed
		if InputInfo.KeyCode == Enum.KeyCode.Return or InputInfo.KeyCode == Enum.KeyCode.KeypadEnter then

			-- Toggle the selection's anchor status
			ToggleAnchors();

		end;

	end));

end;

function ToggleAnchors()
	-- Toggles the anchor status of the selection

	-- Change the anchor status to the opposite of the common anchor status
	SetProperty('Anchored', not Support.IdentifyCommonProperty(Selection.Parts, 'Anchored'));

end;

function TrackChange()

	-- Start the record
	HistoryRecord = {
		Before = {};
		After = {};
		Selection = Selection.Items;

		Unapply = function (Record)
			-- Reverts this change

			-- Select the changed parts
			Selection.Replace(Record.Selection)

			-- Send the change request
			Core.SyncAPI:Invoke('SyncAnchor', Record.Before);

		end;

		Apply = function (Record)
			-- Applies this change

			-- Select the changed parts
			Selection.Replace(Record.Selection)

			-- Send the change request
			Core.SyncAPI:Invoke('SyncAnchor', Record.After);

		end;

	};

end;

function RegisterChange()
	-- Finishes creating the history record and registers it

	-- Make sure there's an in-progress history record
	if not HistoryRecord then
		return;
	end;

	-- Send the change to the server
	Core.SyncAPI:Invoke('SyncAnchor', HistoryRecord.After);

	-- Register the record and clear the staging
	Core.History.Add(HistoryRecord);
	HistoryRecord = nil;

end;
