-- Stop snapping whenever mouse is released

Support.AddUserInputListener('Ended', 'MouseButton1', true, function (Input)

	-- Ensure snapping is ongoing
	if not SnappingStage then
		return;
	end;

	-- Finish snapping
	FinishSnapping();

end);


function FinishSnapping()
	-- Cleans up and finalizes the snapping operation

	-- Ensure snapping is ongoing
	if not SnappingStage then
		return;
	end;

	-- Restore the selection's original state if stage was reached
	if SnappingStartSelectionState then
		for Part, State in pairs(SnappingStartSelectionState) do
			Part:MakeJoints();
			Part.CanCollide = State.CanCollide;
			Part.Anchored = State.Anchored;
		end;
	end;

	-- Disable any snapping stage
	SnappingStage = nil;

	-- Stop snap point tracking
	SnapTracking.StopTracking();

	-- Clear any UI
	if DirectionLine then
		DirectionLine:Destroy();
		DirectionLine = nil;
	end;
	if AlignmentLine then
		AlignmentLine:Destroy();
		AlignmentLine = nil;
	end;

	-- Register any change
	if HistoryRecord then
		RegisterChange();
	end;

	-- Disconnect snapping listeners
	ClearConnection 'SnapDragStart';
	ClearConnection 'SnapDrag';
	ClearConnection 'Snap';
	ClearConnection 'SnapDragEnd';

end;


function GetFaceOffsetsFromCorner(Part, Point)
	-- Returns offsets of the given corner point in the direction of its intersecting faces

	local Offsets = {};

	-- Go through each face the corner intersects
	local Faces = GetFacesFromCorner(Part, Point);
	for _, Face in pairs(Faces) do

		-- Calculate the offset from the corner in the direction of the face
		local FaceOffset = (Vector3.FromNormalId(Face) * Part.Size) / 2;
		local Offset = CFrame.new(Point) * CFrame.Angles(Part.CFrame:toEulerAnglesXYZ()) * FaceOffset;
		table.insert(Offsets, { Face = Face, Offset = Offset });

	end;

	-- Return the list of offsets
	return Offsets;
end;

function GetFacesFromCorner(Part, Point)
	-- Returns the 3 faces that the given corner point intersects

	local Faces = {};

	-- Get all the face centers of the part
	for _, FaceEnum in pairs(Enum.NormalId:GetEnumItems()) do
		local Face = Part.CFrame * (Part.Size / 2 * Vector3.FromNormalId(FaceEnum));

		-- Get the face's proximity to the point
		local Proximity = (Point - Face).magnitude;

		-- Keep track of the proximity to the point
		table.insert(Faces, { Proximity = Proximity, Face = FaceEnum });
	end;

	-- Find the closest faces to the point
	table.sort(Faces, function (A, B)
		return A.Proximity < B.Proximity;
	end);

	-- Return the 3 closest faces
	return { Faces[1].Face, Faces[2].Face, Faces[3].Face };
end;
