**|If possible please write easy answers for me to understand when it comes to CFrame math! I'm still figuring out how it works. Thanks in advance.|**
My goal here is to make a building system where I could snap objects to surfaces of other objects while still following a grid (like the Stamper Tool or something else similar.)
Currently I've only managed to make grid snapping (I deleted that part of the code.) Surface snap only works when I remove the grid snapping functionality and all the workarounds I could think of don't work correctly (or I'm probably just tired when I work with them).
What else can I do to make this happen?:
local PlayerCont = game:GetService("Players")
local Mouse = PlayerCont.LocalPlayer:GetMouse()
local PlacementCursor = Instance.new("Part", workspace) -- Since FilteringEnabled is true, we can
-- make the player's cursor invisible to others.
local SnapByStuds = 4
local States = { -- Non functional
OFF = 0,
BUILD = 1,
EDIT = 2,
COLOR = 3,
WIRE = 4,
CLIPBOARD = 5,
REMOVE = 6
}
local RotationStates -- does nothing for now
-- Initialization
PlacementCursor.Transparency = 0.8 -- 0.8 for now
PlacementCursor.Anchored = true
PlacementCursor.CanCollide = false
PlacementCursor.CastShadow = false
PlacementCursor.Size = Vector3.new(4, 4, 4)
PlacementCursor.Material = "Neon"
Mouse.TargetFilter = PlacementCursor
local cmath = {}
function cmath.even(x, returnNum, custCheck)
local custN = custCheck or 1
if returnNum then
return (x % custN)
end
return (x % custN) == 0
end
function cmath.nearest(x, roundnum)
local rounding = roundnum or 1
if typeof(x) == "Vector3" then
local X, Y, Z = x.X, x.Y, x.Z
local rX, rY, rZ = cmath.even(X, true, rounding) / rounding, cmath.even(Y, true, rounding) / rounding, cmath.even(Z, true, rounding) / rounding
if rX > 0.5 then
X = math.ceil(X / rounding) * rounding + (SnapByStuds/2)
else
X = math.floor(X / rounding) * rounding + (SnapByStuds/2)
end
if rY > 0.5 then
Y = math.ceil(Y / rounding) * rounding + (SnapByStuds/2)
else
Y = math.floor(Y / rounding) * rounding + (SnapByStuds/2)
end
if rZ > 0.5 then
Z = math.ceil(Z / rounding) * rounding + (SnapByStuds/2)
else
Z = math.floor(Z / rounding) * rounding + (SnapByStuds/2)
end
return Vector3.new(X, Y, Z)
else
-- numbers only not used for now
end
end
-- ===========================================================
-- =========================================================== ACTUAL FUNCTIONS
-- ===========================================================
function DisplayNewPosition() -- Something to improve on.
local Normal = Vector3.FromNormalId(Mouse.TargetSurface)
local Position = Mouse.Hit.p
local CursorCFrame = Mouse.Hit
local Anchor = Mouse.Target
if CursorCFrame ~= nil and Anchor ~= nil then
local ObjectHit = Anchor.CFrame -- Anchor to center of object + rotation
local ObjectSpace = Anchor.CFrame:ToObjectSpace(CFrame.new(Position)) * CFrame.Angles(0, 0, 0)
local ObjectRotation = Anchor.CFrame - Anchor.CFrame.Position
local RotatedNormal = (ObjectRotation * Normal) * (PlacementCursor.Size / 2)
--print(RotatedNormal * PlacementCursor.Size)
local FinalFormulation = (ObjectHit * ObjectSpace) + RotatedNormal
PlacementCursor.CFrame = FinalFormulation
end
end
function RequestAddition()
-- nothing yet
end
Mouse.Move:Connect(DisplayNewPosition)
Thanks (again) in advance!
