Help with block placement

Use this module, please search on the devforums before posting.

function CalcCanvas(CanvasPart)
	local canvasSize = CanvasPart.Size

	-- want to create CFrame such that cf.lookVector == self.CanvasPart.CFrame.upVector
	-- do this by using object space and build the CFrame
	local back = Vector3.new(0, -1, 0)
	local top = Vector3.new(0, 0, -1)
	local right = Vector3.new(-1, 0, 0)

	-- convert to world space
	local cf = CanvasPart.CFrame * CFrame.fromMatrix(-back*canvasSize/2, right, top, back)
	-- use object space vectors to find the width and height
	local size = Vector2.new((canvasSize * right).magnitude, (canvasSize * top).magnitude)

	return cf, size
end

function CalcPlacementCFrame(model, position, rotation, CanvasPart)
	-- use other method to get info about the surface
	local cf, size = CalcCanvas(CanvasPart)

	-- rotate the size so that we can properly constrain to the surface
	local modelSize 
	if model:IsA("Model") then
		modelSize = CFrame.fromEulerAnglesYXZ(0, rotation, 0) *  model:GetExtentsSize() --model.PrimaryPart.Size
	else
		modelSize = model.Size
	end
	modelSize = Vector3.new(math.abs(modelSize.x), math.abs(modelSize.y), math.abs(modelSize.z))

	-- get the position relative to the surface's CFrame
	local lpos = cf:pointToObjectSpace(position);
	-- the max bounds the model can be from the surface's center
	local size2 = (size - Vector2.new(modelSize.x, modelSize.z))/2

	-- constrain the position using size2
	local x = math.clamp(lpos.x, -size2.x, size2.x);
	local y = math.clamp(lpos.y, -size2.y, size2.y);

	local g = 1
	if (g > 0) then
		x = math.sign(x)*((math.abs(x) - math.abs(x) % g) + (size2.x % g))
		y = math.sign(y)*((math.abs(y) - math.abs(y) % g) + (size2.y % g))
	end


	-- create and return the CFrame
	return cf * CFrame.new(x, y, -modelSize.y/2) * CFrame.Angles(-math.pi/2 + tilt, -math.pi/2+rotation, 0)
end
1 Like