I need help optimizing my movement arrows script with BulkMoveTo

I need help optimizing the following:

local CenterPartWithTheArrows = workspace:WaitForChild("origin")
local movetool = CenterPartWithTheArrows.Handles
CenterPartWithTheArrows.Handles.Parent = game:GetService("Players").LocalPlayer.PlayerGui

local parts = {}
local cframes = {}
local boxes = {}

-- simulating my selection system, ignore
boxes[workspace.Part1] = workspace.SelectionBox1
boxes[workspace.Part2] = workspace.SelectionBox2

local origins = {}
local centerOrigin = Vector3.one

local function MoveLeftRight(number)
	for part, selection in pairs(boxes) do

		local cframe = CFrame.new(origins[part] + Vector3.new(number,0,0)) * CFrame.Angles( math.rad(part.Orientation.X), math.rad(part.Orientation.Y), math.rad(part.Orientation.Z))  

		table.insert(parts, part)  
		table.insert(cframes, cframe) 
	end
	table.insert(parts, CenterPartWithTheArrows)
	table.insert(cframes, CFrame.new(centerOrigin + Vector3.new(number,0,0)) * CFrame.Angles( math.rad(CenterPartWithTheArrows.Orientation.X), math.rad(CenterPartWithTheArrows.Orientation.Y), math.rad(CenterPartWithTheArrows.Orientation.Z)) )  

	workspace:BulkMoveTo(parts, cframes, Enum.BulkMoveMode.FireCFrameChanged)
end

local function MoveUpDown(number)
	for part, selection in pairs(boxes) do

		local cframe = CFrame.new(origins[part] + Vector3.new(0,number,0)) * CFrame.Angles( math.rad(part.Orientation.X), math.rad(part.Orientation.Y), math.rad(part.Orientation.Z))  

		table.insert(parts, part)  
		table.insert(cframes, cframe) 
	end
	table.insert(parts, CenterPartWithTheArrows)
	table.insert(cframes, CFrame.new(centerOrigin + Vector3.new(0,number,0)) * CFrame.Angles( math.rad(CenterPartWithTheArrows.Orientation.X), math.rad(CenterPartWithTheArrows.Orientation.Y), math.rad(CenterPartWithTheArrows.Orientation.Z)) )

	workspace:BulkMoveTo(parts, cframes, Enum.BulkMoveMode.FireCFrameChanged)
end

local function MoveForwardBack(number)
	for part, selection in pairs(boxes) do

		local cframe = CFrame.new(origins[part] + Vector3.new(0,0,number)) * CFrame.Angles( math.rad(part.Orientation.X), math.rad(part.Orientation.Y), math.rad(part.Orientation.Z))  

		table.insert(parts, part)  
		table.insert(cframes, cframe) 
	end
	table.insert(parts, CenterPartWithTheArrows)
	table.insert(cframes, CFrame.new(centerOrigin + Vector3.new(0,0,number)) * CFrame.Angles( math.rad(CenterPartWithTheArrows.Orientation.X), math.rad(CenterPartWithTheArrows.Orientation.Y), math.rad(CenterPartWithTheArrows.Orientation.Z)) )

	workspace:BulkMoveTo(parts, cframes, Enum.BulkMoveMode.FireCFrameChanged)
end

local GridSize = game:GetService("ReplicatedStorage"):WaitForChild("GridSize")

movetool.MouseDrag:Connect(function(face, distance)

	local num = math.round(distance/GridSize.Value)*GridSize.Value

	for i, v in boxes do

		if face == Enum.NormalId.Right then -- 0
			MoveLeftRight(num)
		elseif face == Enum.NormalId.Top then -- 1
			MoveUpDown(num)
		elseif face == Enum.NormalId.Back then -- 2
			MoveForwardBack(num)
		elseif face == Enum.NormalId.Left then -- 3
			MoveLeftRight(-num)
		elseif face == Enum.NormalId.Bottom then -- 4
			MoveUpDown(-num)
		elseif face == Enum.NormalId.Front then -- 5
			MoveForwardBack(-num)
		end

	end
	
end)

movetool.MouseButton1Down:Connect(function()
	
	centerOrigin = CenterPartWithTheArrows.Position
	
	for part, selection in pairs(boxes) do
		
		origins[part] = part.Position
		
	end
end)

Everything works (apart for the part rotating for some reason), but I feel like it can be way simpler, and I’d like for it to be a lot more optimized for if I have hundreds of parts selected. Here’s the game to save some time:
HandlesBulkMoveTo.rbxl (52.4 KB)

Also, BulkMoveTo isn’t necessary, I just read somewhere that it’s better for moving large amount of parts.
Thanks!

Or is this better?

movetool.MouseButton1Down:Connect(function()
	origin = PartToMove.Position
	
	for g,b in boxes do
		posTable[g] = g.Position
	end

end)

movetool.MouseDrag:Connect(function(face, distance)

	for i, v in boxes do
		
		if face == Enum.NormalId.Right then -- 0
			i.Position = posTable[i] + Vector3.new( math.round(distance/GridSize.Value)*GridSize.Value ,0,0)
			PartToMove.Position = origin + Vector3.new( math.round(distance/GridSize.Value)*GridSize.Value ,0,0)
		elseif face == Enum.NormalId.Top then -- 1
			i.Position = posTable[i] + Vector3.new(0, math.round(distance/GridSize.Value)*GridSize.Value ,0)
			PartToMove.Position = origin + Vector3.new(0, math.round(distance/GridSize.Value)*GridSize.Value ,0)
		elseif face == Enum.NormalId.Back then -- 2
			i.Position = posTable[i] + Vector3.new(0,0, math.round(distance/GridSize.Value)*GridSize.Value )
			PartToMove.Position = origin + Vector3.new(0,0, math.round(distance/GridSize.Value)*GridSize.Value )
		elseif face == Enum.NormalId.Left then -- 3
			i.Position = posTable[i] + Vector3.new( -math.round(distance/GridSize.Value)*GridSize.Value ,0,0)
			PartToMove.Position = origin + Vector3.new( -math.round(distance/GridSize.Value)*GridSize.Value ,0,0)
		elseif face == Enum.NormalId.Bottom then -- 4
			i.Position = posTable[i] + Vector3.new(0, -math.round(distance/GridSize.Value)*GridSize.Value ,0)
			PartToMove.Position = origin + Vector3.new(0, -math.round(distance/GridSize.Value)*GridSize.Value ,0)
		elseif face == Enum.NormalId.Front then -- 5
			i.Position = posTable[i] + Vector3.new(0,0, -math.round(distance/GridSize.Value)*GridSize.Value )
			PartToMove.Position = origin + Vector3.new(0,0, -math.round(distance/GridSize.Value)*GridSize.Value )
		end
		
	end

end)

movetool.MouseButton1Up:Connect(function()
	origin = PartToMove.Position
	table.clear(posTable)
end)