Snapping paintings to a wall

Ah, just need to use .Value on the TargetSurface enum. Here you are:

local coords = {'X', 'Y', 'Z'}

local function getCFrame(mouse, thickness)
	local CF = mouse.Target.CFrame
	local touch = CF:Inverse() * mouse.Hit
	
	local pos = {}

	local normalAxis = mouse.TargetSurface.Value % 3 + 1
	local dir = {0, 0, 0}
	for axis, coord in next, coords do
		if axis == normalAxis then
			pos[axis] = touch[coord] + thickness / 2
			dir[axis] = math.sign(touch[coord])
		else
			pos[axis] = math.floor(touch[coord] + 0.5)
		end
	end
	pos = Vector3(unpack(pos))
	dir = Vector3(unpack(dir))
	
	return CF * CFrame.new(pos, pos + normal)
end
local coords = {'X', 'Y', 'Z'}

local function getCFrame(mouse, thickness)
	local CF = mouse.Target.CFrame
	local touch = CF:Inverse() * mouse.Hit
	
	local pos = {}

	local normalAxis = mouse.TargetSurface.Value % 3 + 1
	local dir = {0, 0, 0}
	for axis, coord in next, coords do
		if axis == normalAxis then
			pos[axis] = touch[coord] + thickness / 2
			dir[axis] = math.sign(touch[coord])
		else
			pos[axis] = math.floor(touch[coord] + 0.5)
		end
	end
	pos = Vector3(unpack(pos)) -- ERROR HERE
	dir = Vector3(unpack(dir))
	
	return CF * CFrame.new(pos, pos + normal)
end

Error

[attempt to call global ‘Vector3’ (a table value)]

Use Vector3.new instead of trying to call Vector3. There might be some small things you can clean up on your own, but let me know if you run into any major issues.

return CF * CFrame.new(pos, pos + normal)

[bad argument #2 to ‘?’ (Vector3 expected, got nil)]

I think this is the normal I was talking about earlier not being referenced anywhere. It’s underlined in red, and no where mentioned in the script

Oh, I see. I renamed it to dir above. Just change normal to dir. You should read through the script and try to understand it rather than just plugging it in and seeing if it works. The way it works isn’t set in stone and can be manipulated.

Ahhh ok :+1:

Seems to be working nicely on one side of the wall


However, walls facing this way have the part inside the wall (thus the red color)

How far inside the wall? If may be a floating point error due to the space transformations and is only very, very slightly inside the wall.

Also, is that a gap I see between the green paintings and the wall?

(btw when this works, it can also replace your default placement scripts including placing anything on the floor. You’ll use the object’s height instead of thickness in that case.)

Well when I move it around, it does the clipping thing, so I’m guessing its like this


Ah, I left out an important piece. Change this:

		if axis == normalAxis then
			pos[axis] = touch[coord] + thickness / 2
			dir[axis] = math.sign(touch[coord])
		else
			pos[axis] = math.floor(touch[coord] + 0.5)
		end

to this:

		if axis == normalAxis then
			local sign = math.sign(touch[coord])
			pos[axis] = touch[coord] + sign * thickness / 2
			dir[axis] = sign
		else
			pos[axis] = math.floor(touch[coord] + 0.5)
		end
1 Like

It’s working! Beyond appreciative of your help! :smiley: :smiley:

1 Like

Sorry to bump this back up but I am having new problems :grimacing:

The 2 problems are

The PrimaryPart (origin) is like so


So the idea would be that this part would be the part the mouse follows

Code

local coords = {'X', 'Y', 'Z'}

function getCFrame(mouse, thickness)
	local CF = mouse.Target.CFrame
	local touch = CF:Inverse()*mouse.Hit
	
	local pos = {}

	local normalAxis = mouse.TargetSurface.Value%3 + var.Grid -- Currently set at 1, but doesn't work as 0.5, 0.1, or even 0
	local dir = {0, 0, 0}
	for axis, coord in next, coords do
		if axis == normalAxis then
			local sign = math.sign(touch[coord])
			pos[axis] = touch[coord] + sign*thickness/2
			dir[axis] = sign
		else
			pos[axis] = math.floor(touch[coord] + 0.5)
		end
	end
	pos = Vector3.new(unpack(pos))
	dir = Vector3.new(unpack(dir))
	
	return CF * CFrame.new(pos, pos + dir)
end

itemClone:SetPrimaryPartCFrame((getCFrame(mouse, itemClone.PrimaryPart.Size.Z))*CFrame.Angles(0, 0, var.Rotation))

var.Grid is the grid I want it to lock to. So 1 is the default grid but I want access for players to have no grid (so basically 0, so it doesn’t snap at all)

Simply stop rounding your numbers, or round them to your wanted granularity.
pos[axis] = math.floor(touch[coord] + 0.5)
would become
pos[axis] = touch[coord]

Perhaps you have your PrimaryPart incorrectly rotated.

Wouldn’t
pos[axis] = touch[coord]
Just make it not snap at all?

Correct

Otherwise just change how you’re rounding it, since the code you currently have does round to 1, so not sure where your attempt of snapping to 0.5 or 0.1 is.