local n={}function Selection.IsSelected(n)return Selection.ItemIndex[n]end function Selection.Add(I,X)local r=GetCore()local t={}for n,I in pairs(I)do if r.IsSelectable(I)and not Selection.ItemIndex[I]then table.insert(t,I)end end local u=Selection.Items for I,X in pairs(t)do Selection.ItemIndex[X]=true n[X]=X.AncestryChanged:connect(function(n,I)if I==nil then Selection.Remove({X})end end)end Selection.Items=Support.Keys(Selection.ItemIndex)if X and#t>0 then TrackSelectionChange(u)end CreateSelectionBoxes(t)Selection.ItemsAdded:fire(t)Selection.Changed:fire()end function Selection.Remove(I,X)local r={}for n,I in pairs(I)do if Selection.IsSelected(I)then table.insert(r,I)end end local t=Selection.Items for I,X in pairs(r)do Selection.ItemIndex[X]=nil n[X]:disconnect()n[X]=nil end RemoveSelectionBoxes(r)Selection.Items=Support.Keys(Selection.ItemIndex)if X and#r>0 then TrackSelectionChange(t)end Selection.ItemsRemoved:fire(r)Selection.Changed:fire()end function Selection.Clear(n)Selection.Remove(Selection.Items,n)Selection.Cleared:fire()end function Selection.Replace(n,I)local X=Selection.Items Selection.Clear(false)Selection.Add(n,false)if I then TrackSelectionChange(X)end end function Selection.SetFocus(n)if not Selection.IsSelected(n)and n~=nil then return end Selection.Focus=n Selection.FocusChanged:fire(n)end function FocusOnLastSelectedPart()if#Selection.Items==0 then Selection.SetFocus(nil)else Selection.SetFocus(Selection.Items[#Selection.Items])end end
-- Item existence listeners
local Listeners = {}

function Selection.IsSelected(Item)
	-- Returns whether `Item` is selected or not

	-- Check and return item presence in index
	return Selection.ItemIndex[Item]
end

function Selection.Add(Items, RegisterHistory)
	-- Adds the given items to the selection

	-- Get core API
	local Core = GetCore()

	-- Go through and validate each given item
	local SelectableItems = {}
	for _, Item in pairs(Items) do
		-- Make sure each item is valid and not already selected
		if Core.IsSelectable(Item) and not Selection.ItemIndex[Item] then
			table.insert(SelectableItems, Item)
		end
	end

	local OldSelection = Selection.Items

	-- Go through the valid new selection items
	for _, Item in pairs(SelectableItems) do
		-- Add each valid item to the selection
		Selection.ItemIndex[Item] = true

		-- Deselect items that are destroyed
		Listeners[Item] = Item.AncestryChanged:connect(function(Object, Parent)
			if Parent == nil then
				Selection.Remove({ Item })
			end
		end)
	end

	-- Update selected item list
	Selection.Items = Support.Keys(Selection.ItemIndex)

	-- Create a history record for this selection change, if requested
	if RegisterHistory and #SelectableItems > 0 then
		TrackSelectionChange(OldSelection)
	end

	-- Create selection boxes for the selection
	CreateSelectionBoxes(SelectableItems)

	-- Fire relevant events
	Selection.ItemsAdded:fire(SelectableItems)
	Selection.Changed:fire()
end

function Selection.Remove(Items, RegisterHistory)
	-- Removes the given items from the selection

	-- Go through and validate each given item
	local DeselectableItems = {}
	for _, Item in pairs(Items) do
		-- Make sure each item is actually selected
		if Selection.IsSelected(Item) then
			table.insert(DeselectableItems, Item)
		end
	end

	local OldSelection = Selection.Items

	-- Go through the valid deselectable items
	for _, Item in pairs(DeselectableItems) do
		-- Remove item from selection
		Selection.ItemIndex[Item] = nil

		-- Stop tracking item's parent
		Listeners[Item]:disconnect()
		Listeners[Item] = nil
	end

	-- Remove selection boxes from deselected items
	RemoveSelectionBoxes(DeselectableItems)

	-- Update selected item list
	Selection.Items = Support.Keys(Selection.ItemIndex)

	-- Create a history record for this selection change, if requested
	if RegisterHistory and #DeselectableItems > 0 then
		TrackSelectionChange(OldSelection)
	end

	-- Fire relevant events
	Selection.ItemsRemoved:fire(DeselectableItems)
	Selection.Changed:fire()
end

function Selection.Clear(RegisterHistory)
	-- Clears all items from selection

	-- Remove all selected items
	Selection.Remove(Selection.Items, RegisterHistory)

	-- Fire relevant events
	Selection.Cleared:fire()
end

function Selection.Replace(Items, RegisterHistory)
	-- Replaces the current selection with the given new items

	-- Save old selection reference for history
	local OldSelection = Selection.Items

	-- Clear current selection and select new items
	Selection.Clear(false)
	Selection.Add(Items, false)

	-- Create a history record for this selection change, if requested
	if RegisterHistory then
		TrackSelectionChange(OldSelection)
	end
end

function Selection.SetFocus(Item)
	-- Selects `Item` as the focused selection item

	-- Make sure the item is selected or is `nil`
	if not Selection.IsSelected(Item) and Item ~= nil then
		return
	end

	-- Set the item as the focus
	Selection.Focus = Item

	-- Fire relevant events
	Selection.FocusChanged:fire(Item)
end

function FocusOnLastSelectedPart()
	-- Sets the last part of the selection as the focus

	-- If selection is empty, clear the focus
	if #Selection.Items == 0 then
		Selection.SetFocus(nil)

	-- Otherwise, focus on the last part in the selection
	else
		Selection.SetFocus(Selection.Items[#Selection.Items])
	end
end
