I am working on my placement module v3 and want to fix a issue that has been present for a while now. The position calculated in the module is not relative to the plot. This means that users have to position the plot(s) to work with the system (otherwise it will be offset). What I want to do, is make the calculate function account for the plot position it isn’t offset in some cases. I have tried to use math.modf() to add on offsets but it always was a bit off so I removed it.
-- Calculates the position of the object
local function calculateItemLocation()
if currentRot then
x, z = mouse.Hit.X - primary.Size.X*0.5, mouse.Hit.Z - primary.Size.Z*0.5
cx = primary.Size.X*0.5
cz = primary.Size.Z*0.5
else
x, z = mouse.Hit.X - primary.Size.Z*0.5, mouse.Hit.Z - primary.Size.X*0.5
cx = primary.Size.Z*0.5
cz = primary.Size.X*0.5
end
if moveByGrid then
-- Snaps models to grid
if x%GRID_UNIT < GRID_UNIT*0.5 then
posX = round(x - (x%GRID_UNIT))
else
posX = round(x + (GRID_UNIT - (x%GRID_UNIT)))
end
if z%GRID_UNIT < GRID_UNIT*0.5 then
posZ = round(z - (z%GRID_UNIT))
else
posZ = round(z + (GRID_UNIT - (z%GRID_UNIT)))
end
else
posX = x
posZ = z
end
-- Changes posY depending on mouse target
if stackable and mouse.Target then
posY = calculateYPos(mouse.Target.Position.Y, mouse.Target.Size.Y, primary.Size.Y)
end
-- Clamps posY to a max height above the plot position
posY = clamp(posY, initialY, maxHeight + initialY)
bounds()
end
You can use the EgoMoose’s trick that he used in his placement system Furniture Placement System to snap the CFrame to the grid, this trick consists on using ToWorldSpace to fit the canvas position.
Thank you for the help. I just don’t understand enough of the math to correctly implement this. I appreciate it though. I’ll keep working on it and if I get it to work, I’ll mark it as the solution.
That is correct. I understand the purpose of the functions ToObjectSpace/ToWorldSpace but actually implementing it in my code is another story. I always get offsets and what not (not to mention I managed to break my bounds function which stops the model from leaving the plot). Thank you though!
I’ve made a new placement system since then and have made quite a few changes with the new coding practices that I know now. You also mentioned checking if it exceeds the plot bounds which I have a solution for.
Here’s the first thing. It checks if the part exceeds the plot bounds, if it does, it will return the closest vector to the mouse’s hit.
local function checkExceedsPlotBounds(vector)
local vectorRelative = plot.CFrame:PointToObjectSpace(vector) -- mouse.Hit.p but relative to the plot
local x = vectorRelative.X
local maxPlotBoundsX = plot.Size.X / 2 -- since the plot's CFrame is the new 0,0,0, we have to divide each axis by 2 to account for either side
if x > maxPlotBoundsX then -- if it exceeds the max for X then returns the furthest on the X axis
x = maxPlotBoundsX
elseif x < -maxPlotBoundsX then -- same but negative
x = -maxPlotBoundsX
end
local z = vectorRelative.Z
local maxPlotBoundsZ = plot.Size.Z / 2 -- same checks as above
if z > maxPlotBoundsZ then
z = maxPlotBoundsZ
elseif z < -maxPlotBoundsZ then
z = -maxPlotBoundsZ
end
local newVector = Vector3.new(x, vector.Y, z) -- create the new V3
local newVectorRelative = plot.CFrame:PointToWorldSpace(newVector) -- change it to be in the world's space
return newVectorRelative -- return it
end
As for the other thing, instead of checking the part’s position relative to the world, use :ToObjectSpace on it, then round the :ToObjectSpace CFrame, then return the :ToWorldSpace CFrame. You’re basically never going to check or manipulate the part’s CFrame relative to the world. This is also how you’re going to move objects relative to each other (like placing an object ontop of another object).
I’ve attached a place file, all of whose scripts include comments to better explain what’s going on. It’s a bit messy, just a warning.
Thank you! I realize what I was doing wrong now. I was inputting the wrong stuff in ToObjectSpace(). I was doing objectCFrame:ToObjectSpace(plotCFrame) instead of plotCFrame:ToObjectSpace(objectCFrame). Anyway, your code samples helped me work this out so I will accept your answer.