Hey there, I have a building game in Roblox which is called “Wubby” and it has a resize tool inside of it. The resize tool supports multiple selection, however, if a non-parallel rotated block with the first block (like 0, 0, 0 vs 0, 90, 0) is inside the multiple selection, it’ll just resize that block towards its own axis instead of following the first part’s axis.
What I’ve been searching for is something like this:
btw, the “ResizeObject” mode you can see in this gif is nearly the same thing that is happening to me, I want to make it work like “ResizeWorld”
Since my resize tool system works with normals, what I’ve been looking for is something like this:
(I’m not really good explaining, haha) I was looking for someway (WITHOUT RAYCASTING, I know how to use raycasting but I don’t want to use raycasting for this case because of performance issues) to adapt a normal to another part’s orientation or CFrame. In the first segment of that image you can see a part pointing to one direction, and in the next one you can see a rotated part which also keeps the same direction, however it’s using a different normal to be in the same direction as the first part.
Any help is welcome, I’ve been 3 days straight searching a solution for this and I haven’t found anything that suits my needs!
Hey I’ve looked at the link you sent and I don’t quite understand that answer. I need to calculate 2 things when resizing: the CFrame and the size, that answer only gives me the size, and also has an example that makes no sense whatsoever (why are you getting the part’s size to then apply the method you’re trying to showcase?)
Still, thank you for answering because I completely forgot WorldSpaces and ObjectSpacess were a thing!
update 2025: fixed the script a little bit so it’s more readable cuz this is very useful ngl
original post:
Hey, I forgot to respond to this long time ago. Someone gave me this script through DMs that completely fixes my problem:
local PartsInformation = {}
local _INCREMENT = 1 -- your grid size ig
local Blocks = {} -- the blocks you're gonna resize
local function Snap(x, inc) -- if someone can simplify this function pls lmk idk what it does
if inc == 0 then return end
local rem = x%inc
if 2*rem ~= inc then
return (2*rem < inc and x or x + inc) - rem
end
return ((x - rem)%(2*inc) == 0 and x or x + inc) - rem
end
local FACE_MULTIPLIER = {
[Enum.NormalId.Top] = 1;
[Enum.NormalId.Bottom] = -1;
[Enum.NormalId.Front] = -1;
[Enum.NormalId.Back] = 1;
[Enum.NormalId.Left] = -1;
[Enum.NormalId.Right] = 1;
};
local facecomponent = {
[Enum.NormalId.Top] = "Y",
[Enum.NormalId.Bottom] = "Y",
[Enum.NormalId.Front] = "Z",
[Enum.NormalId.Back] = "Z",
[Enum.NormalId.Left] = "X",
[Enum.NormalId.Right] = "X",
}
local faceList = {
Enum.NormalId.Back;
Enum.NormalId.Bottom;
Enum.NormalId.Front;
Enum.NormalId.Left;
Enum.NormalId.Right;
Enum.NormalId.Top;
}
local faceVectors = {}
for index, face in faceList do
faceVectors[index] = Vector3.FromNormalId(face)
end
local first, inc, FirstNormal
local LastDistance = 0
-- OverlayHandles is supposed to be ur handles
OverlayHandles.MouseButton1Down:Connect(function(face)
LastDistance = 0
first = Blocks[1]
table.clear(PartsInformation)
FirstNormal = first.CFrame:VectorToWorldSpace(Vector3.fromNormalId(face))
for _,part in Blocks do
local partCFrame = part.CFrame
local rIndex, rDot = 1, -inf
for i, test in faceVectors do
local td = part.CFrame:VectorToWorldSpace(test):Dot(FirstNormal)
if td > rDot then
rDot = td
rIndex = i
end
end
local faceObj = faceList[rIndex]
local isTruss = part:IsA('TrussPart')
PartsInformation[part] = {
partCFrame;
part.Size;
isTruss;
isTruss and 2 or MIN_SIZE;
FACE_MULTIPLIER[faceObj];
FACE_COMPONENT[faceObj];
faceVectors[rIndex];
}
end
inc = Snap(_INCREMENT, 1)
if inc == 0 then
inc = 1
end
end)
OverlayHandles.MouseDrag:Connect(function(face, distance)
local ddis = Snap(distance, _INCREMENT)
if ddis == LastDistance then return end
LastDistance = ddis
for part, info in PartsInformation do
local sz, isTruss, ffm, face_mult, face_size, face_vec = info[2], info[3], info[4], info[5], info[6], info[7]
local dis = distance*face_mult
local mult = Snap(dis, isTruss and inc*ffm or cinc)
local mod = sz[face_size] + mult*face_mult < ffm and face_vec*((ffm - sz[face_size])*face_mult) or face_vec*mult
part.Size = sz + mod
part.CFrame = info[1]*cf(mod*face_mult/2)
end
end)