local G={}function CollisionTool.Equip()ShowUI()BindShortcutKeys()end function CollisionTool.Unequip()HideUI()ClearConnections()end function ClearConnections()for R,d in pairs(G)do d:Disconnect()G[R]=nil end end function ShowUI()if UI then UI.Visible=true UIUpdater=Support.ScheduleRecurringTask(UpdateUI,.1)return end UI=Core.Tool.Interfaces.BTCollisionToolGUI:Clone()UI.Parent=Core.UI UI.Visible=true local G=UI.Status.On.Button local R=UI.Status.Off.Button G.MouseButton1Click:Connect(function()SetProperty("\067\097\110\067\111\108\108\105\100\101",true)end)R.MouseButton1Click:Connect(function()SetProperty("\067\097\110\067\111\108\108\105\100\101",false)end)local d=(UI:WaitForChild("\084\105\116\108\101")):WaitForChild("\083\105\103\110\097\116\117\114\101")ListenForManualWindowTrigger(CollisionTool.ManualText,CollisionTool.Color.Color,d)UIUpdater=Support.ScheduleRecurringTask(UpdateUI,.1)end function UpdateUI()if not UI then return end local G=Support.IdentifyCommonProperty(Selection.Parts,"\067\097\110\067\111\108\108\105\100\101")if G==true then Core.ToggleSwitch("\079\110",UI.Status)elseif G==false then Core.ToggleSwitch("\079\102\102",UI.Status)elseif G==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(G,R)if R==nil then return end TrackChange()for d,q in pairs(Selection.Parts)do table.insert(HistoryRecord.Before,{Part=q;[G]=q[G]})table.insert(HistoryRecord.After,{Part=q,[G]=R})end RegisterChange()end function BindShortcutKeys()table.insert(G,UserInputService.InputBegan:Connect(function(G,R)if R then return end if G.UserInputType~=Enum.UserInputType.Keyboard then return end if UserInputService:GetFocusedTextBox()then return end if G.KeyCode==Enum.KeyCode.Return or G.KeyCode==Enum.KeyCode.KeypadEnter then ToggleCollision()end end))end function ToggleCollision()SetProperty("\067\097\110\067\111\108\108\105\100\101",not Support.IdentifyCommonProperty(Selection.Parts,"\067\097\110\067\111\108\108\105\100\101"))end function TrackChange()HistoryRecord={Before={},After={},Selection=Selection.Items;Unapply=function(G)Selection.Replace(G.Selection)Core.SyncAPI:Invoke("\083\121\110\099\067\111\108\108\105\115\105\111\110",G.Before)end;Apply=function(G)Selection.Replace(G.Selection)Core.SyncAPI:Invoke("\083\121\110\099\067\111\108\108\105\115\105\111\110",G.After)end}end function RegisterChange()if not HistoryRecord then return end Core.SyncAPI:Invoke("\083\121\110\099\067\111\108\108\105\115\105\111\110",HistoryRecord.After)Core.History.Add(HistoryRecord)HistoryRecord=nil end
-- Container for temporary connections (disconnected automatically)
local Connections = {}

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

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

function CollisionTool.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.BTCollisionToolGUI:Clone()
	UI.Parent = Core.UI
	UI.Visible = true

	-- References to UI elements
	local OnButton = UI.Status.On.Button
	local OffButton = UI.Status.Off.Button

	-- Enable the collision status switch
	OnButton.MouseButton1Click:Connect(function()
		SetProperty("CanCollide", true)
	end)
	OffButton.MouseButton1Click:Connect(function()
		SetProperty("CanCollide", false)
	end)

	-- Hook up manual triggering
	local SignatureButton = UI:WaitForChild("Title"):WaitForChild("Signature")
	ListenForManualWindowTrigger(CollisionTool.ManualText, CollisionTool.Color.Color, SignatureButton)

	-- 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 collision status of selection
	local Collision = Support.IdentifyCommonProperty(Selection.Parts, "CanCollide")

	-- Update the collision option switch
	if Collision == true then
		Core.ToggleSwitch("On", UI.Status)

	-- If the selection has collision disabled
	elseif Collision == false then
		Core.ToggleSwitch("Off", UI.Status)

	-- If the collision status varies, don't select a current switch
	elseif Collision == 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 collision status
				ToggleCollision()
			end
		end)
	)
end

function ToggleCollision()
	-- Toggles the collision status of the selection

	-- Change the collision status to the opposite of the common collision status
	SetProperty("CanCollide", not Support.IdentifyCommonProperty(Selection.Parts, "CanCollide"))
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("SyncCollision", Record.Before)
		end,

		Apply = function(Record)
			-- Applies this change

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

			-- Send the change request
			Core.SyncAPI:Invoke("SyncCollision", 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("SyncCollision", HistoryRecord.After)

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