Support.AddUserInputListener("\069\110\100\101\100","\077\111\117\115\101\066\117\116\116\111\110\049",true,function(I)if not HandleDragging then return end HandleDragging=false ClearConnection("\072\097\110\100\108\101\082\101\108\101\097\115\101")for I,J in pairs(InitialState)do I:MakeJoints()Core.RestoreJoints(J.Joints)I.CanCollide=J.CanCollide I.Anchored=J.Anchored end RegisterChange()BoundingBox.RecalculateStaticExtents()BoundingBox.ResumeMonitoring()end)function HideHandles()if not Handles or not Handles.Visible then return end Handles.Visible=false Handles.Parent=nil ClearConnection("\065\117\116\111\102\111\099\117\115\072\097\110\100\108\101")end function MovePartsAlongAxesByFace(I,J,z,G,R)local L=AxisMultipliers[I]local g=R[G]for I,G in pairs(R)do if z=="\071\108\111\098\097\108"then I.CFrame=G.CFrame+J*L elseif z=="\076\111\099\097\108"then I.CFrame=G.CFrame*CFrame.new(J*L)elseif z=="\076\097\115\116"then local z=g.CFrame*CFrame.new(J*L)local R=g.CFrame:toObjectSpace(G.CFrame)I.CFrame=z*R end end end function BindShortcutKeys()table.insert(Connections,UserInputService.InputBegan:connect(function(I,J)if J then return end if I.UserInputType~=Enum.UserInputType.Keyboard then return end if UserInputService:GetFocusedTextBox()then return end if I.KeyCode==Enum.KeyCode.Return or I.KeyCode==Enum.KeyCode.KeypadEnter then if MoveTool.Axes=="\071\108\111\098\097\108"then SetAxes("\076\111\099\097\108")elseif MoveTool.Axes=="\076\111\099\097\108"then SetAxes("\076\097\115\116")elseif MoveTool.Axes=="\076\097\115\116"then SetAxes("\071\108\111\098\097\108")end elseif I.KeyCode==Enum.KeyCode.Minus or I.KeyCode==Enum.KeyCode.KeypadMinus then if MoveTool.UI then MoveTool.UI.IncrementOption.Increment.TextBox:CaptureFocus()end elseif I.KeyCode==Enum.KeyCode.R and not Selection.Multiselecting then StartSnapping()elseif I.KeyCode==Enum.KeyCode.KeypadEight then NudgeSelectionByFace(Enum.NormalId.Top)elseif I.KeyCode==Enum.KeyCode.KeypadTwo then NudgeSelectionByFace(Enum.NormalId.Bottom)elseif I.KeyCode==Enum.KeyCode.KeypadNine then NudgeSelectionByFace(Enum.NormalId.Front)elseif I.KeyCode==Enum.KeyCode.KeypadOne then NudgeSelectionByFace(Enum.NormalId.Back)elseif I.KeyCode==Enum.KeyCode.KeypadFour then NudgeSelectionByFace(Enum.NormalId.Left)elseif I.KeyCode==Enum.KeyCode.KeypadSix then NudgeSelectionByFace(Enum.NormalId.Right)elseif I.KeyCode==Enum.KeyCode.T then AlignSelectionToTarget()end end))table.insert(Connections,UserInputService.InputEnded:connect(function(I,J)if J then return end if I.UserInputType~=Enum.UserInputType.Keyboard then return end if I.KeyCode==Enum.KeyCode.R then if UserInputService:GetFocusedTextBox()then return end if not Dragging then SetAxes(MoveTool.Axes)end SnapTracking.StopTracking()end end))end

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

	-- Ensure handle dragging is ongoing
	if not HandleDragging then
		return;
	end;

	-- Disable dragging
	HandleDragging = false;

	-- Clear this connection to prevent it from firing again
	ClearConnection 'HandleRelease';

	-- Make joints, restore original anchor and collision states
	for Part, State in pairs(InitialState) do
		Part:MakeJoints();
		Core.RestoreJoints(State.Joints);
		Part.CanCollide = State.CanCollide;
		Part.Anchored = State.Anchored;
	end;

	-- Register the change
	RegisterChange();

	-- Resume normal bounding box updating
	BoundingBox.RecalculateStaticExtents();
	BoundingBox.ResumeMonitoring();

end);

function HideHandles()
	-- Hides the resizing handles

	-- Make sure handles exist and are visible
	if not Handles or not Handles.Visible then
		return;
	end;

	-- Hide the handles
	Handles.Visible = false;
	Handles.Parent = nil;

	-- Disable handle autofocus
	ClearConnection 'AutofocusHandle';

end;

function MovePartsAlongAxesByFace(Face, Distance, Axes, BasePart, InitialStates)
	-- Moves the given parts in `InitialStates`, along the given axis mode, in the given face direction, by the given distance

	-- Get the axis multiplier for this face
	local AxisMultiplier = AxisMultipliers[Face];

	-- Get starting state for `BasePart`
	local InitialBasePartState = InitialStates[BasePart];

	-- Move each part
	for Part, InitialState in pairs(InitialStates) do

		-- Move along standard axes
		if Axes == 'Global' then
			Part.CFrame = InitialState.CFrame + (Distance * AxisMultiplier);

		-- Move along item's axes
		elseif Axes == 'Local' then
			Part.CFrame = InitialState.CFrame * CFrame.new(Distance * AxisMultiplier);

		-- Move along focused part's axes
		elseif Axes == 'Last' then

			-- Calculate the focused part's position
			local RelativeTo = InitialBasePartState.CFrame * CFrame.new(Distance * AxisMultiplier);

			-- Calculate how far apart we should be from the focused part
			local Offset = InitialBasePartState.CFrame:toObjectSpace(InitialState.CFrame);

			-- Move relative to the focused part by this part's offset from it
			Part.CFrame = RelativeTo * Offset;

		end;

	end;

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 current axis mode
			if MoveTool.Axes == 'Global' then
				SetAxes('Local');

			elseif MoveTool.Axes == 'Local' then
				SetAxes('Last');

			elseif MoveTool.Axes == 'Last' then
				SetAxes('Global');
			end;

		-- Check if the - key was pressed
		elseif InputInfo.KeyCode == Enum.KeyCode.Minus or InputInfo.KeyCode == Enum.KeyCode.KeypadMinus then

			-- Focus on the increment input
			if MoveTool.UI then
				MoveTool.UI.IncrementOption.Increment.TextBox:CaptureFocus();
			end;

		-- Check if the R key was pressed down, and it's not the selection clearing hotkey
		elseif InputInfo.KeyCode == Enum.KeyCode.R and not Selection.Multiselecting then

			-- Start tracking snap points nearest to the mouse
			StartSnapping();

		-- Nudge up if the 8 button on the keypad is pressed
		elseif InputInfo.KeyCode == Enum.KeyCode.KeypadEight then
			NudgeSelectionByFace(Enum.NormalId.Top);

		-- Nudge down if the 2 button on the keypad is pressed
		elseif InputInfo.KeyCode == Enum.KeyCode.KeypadTwo then
			NudgeSelectionByFace(Enum.NormalId.Bottom);

		-- Nudge forward if the 9 button on the keypad is pressed
		elseif InputInfo.KeyCode == Enum.KeyCode.KeypadNine then
			NudgeSelectionByFace(Enum.NormalId.Front);

		-- Nudge backward if the 1 button on the keypad is pressed
		elseif InputInfo.KeyCode == Enum.KeyCode.KeypadOne then
			NudgeSelectionByFace(Enum.NormalId.Back);

		-- Nudge left if the 4 button on the keypad is pressed
		elseif InputInfo.KeyCode == Enum.KeyCode.KeypadFour then
			NudgeSelectionByFace(Enum.NormalId.Left);

		-- Nudge right if the 6 button on the keypad is pressed
		elseif InputInfo.KeyCode == Enum.KeyCode.KeypadSix then
			NudgeSelectionByFace(Enum.NormalId.Right);

		-- Align the selection to the current target surface if T is pressed
		elseif InputInfo.KeyCode == Enum.KeyCode.T then
			AlignSelectionToTarget();

		end;

	end));

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

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

		-- Make sure this is input from the keyboard
		if InputInfo.UserInputType ~= Enum.UserInputType.Keyboard then
			return;
		end;

		-- Check if the R key was let go
		if InputInfo.KeyCode == Enum.KeyCode.R then

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

			-- Reset handles if not dragging
			if not Dragging then
				SetAxes(MoveTool.Axes);
			end;

			-- Stop snapping point tracking if it was enabled
			SnapTracking.StopTracking();

		end;

	end));

end;
