How to make a part resizable via dragging?

I’m making a building game and I’m currently stuck on creating a resizing system. I’m mainly having trouble with getting a part to resize from only one face, so any help with that aspect of the system would be appreciated.

2 Likes

What do you have so far, do you have the handles made?

This here is actually quite complex, ngl.

You can either make it simple(er) by adding a grid system for resizing just like bloxburg, orr…

Use vector math for calculating the increased value in each axes, eg:
image

using this equation, you can take the coordinates of mouse.hit as cor1 and the coordinates (i.e CFrame.position) of the players camera as cor0 and plug in the values to the above equation for the particular axes you want to calculate the distance of…

Important note:

  1. For getting the player’s cam and hit location you’ll have to use a local script, but for resizing you’ll have to use a server script.
  2. Due to the above limitation you’ll have to make a remote event for data transfer between the client and the server
  3. While resizing the object you need to change the position of the object to 1/2 of it’s total length from start as well so that it doesn’t increase in size on both sides

Overall I’d say that you should just try using a grid system, or a “part size entends to mouse” system since it reduces the overall complexity of the code

1 Like

I have the handles and they move with the part.

I currently have a snap-to-grid system in place, but I want an option to disable that for the resizing aspect of my game as well.

My first attempt at this took the origin position of the mouse and subtracted it from its current position, then got the magnitude of that difference and used that to determine the new size of the part. The only issue is that method resized the part from both faces, instead of just the one.

After reading your response, I halved the output of my method and it worked for the positive direction, but did not respond to any attempts to shrink the part (because magnitude is always positive). I’m gonna try a hacky solution to determine whether the mouse’s position is increasing/decreasing in a given direction and make the magnitude negative/positive based on that. If that doesn’t work I’ll try the camera thing.

Thank you for your help so far, and I’ll be sure to update you based on how it goes.

Edit: The part now decreases in size but unfortunately it now appears to extend in both directions.

You could just get the delta from the last frame to the current frame (or whatever method you use, just get the difference) and set the size += to that delta, and then change the position to 1/2 of the delta so it looks like it didnt go on both faces

1 Like

I have almost this exact thing implemented right now, I multiply the output vector by Vector3.new(.5, 0, 0), and it still looks like it’s extending both ways. Why is this happening?

Ah okay, so since Roblox handles mouse movement translated to the 3D world, you can just use that for resizing:

local handles = script.Parent:WaitForChild('Handles')

local part = handles.Adornee
local cframeAtMouseDown, sizeAtMouseDown, lastGoalSize

handles.MouseButton1Down:Connect(function(face)
	cframeAtMouseDown = handles.Adornee.CFrame
	sizeAtMouseDown = handles.Adornee.Size
end)

local function toPositive(vector: Vector3)		-- for sizing, we use this to get the correct sizing. if you don't, the negative axes will scale improperly
	return Vector3.new(
		math.abs(vector.X),
		math.abs(vector.Y),
		math.abs(vector.Z)
	)
end

local function minimumVector(vector: Vector3) 	-- this function checks that the size is at least 0.001 which is the minimum size. 
	return Vector3.new(							-- if you remove this, you will have your part attempting to go into the negative size 
		math.max(vector.X, 0.001),				-- which obviously won't work but it'll result in the part moving backwards
		math.max(vector.Y, 0.001),
		math.max(vector.Z, 0.001)
	)
end

handles.MouseDrag:Connect(function(face, distance) --face is obviously the face that was resized. the distance is the distance since the mouse button was pressed which is why we're saving it as a variable earlier
	local goalSize = minimumVector(sizeAtMouseDown + toPositive(Vector3.fromNormalId(face)) * distance)
	part.Size = goalSize
	if lastGoalSize ~= goalSize then -- removes the part from positioning when the minimum size is reached, also prevents an unnecessary calculation
		part.CFrame = cframeAtMouseDown * CFrame.new(Vector3.fromNormalId(face) * distance / 2) -- positioning is divided by 2 because it's only one face to be resized, not 2. if we don't divide, it will scale at double the rate
	end
	lastGoalSize = goalSize
end)

4 Likes

Maybe try changing the values? Like making it 1 instead of .5?

Thank you so much! I’ll try this when I get to my computer! Also, totally unrelated but is a “:” after an argument a way to specify an expected data type in lua?

1 Like

Im only changing the X for now, sorry if I didn’t specify.

Yeah, only in Luau though. It’s not available in vanilla Lua. It will give you autocomplete with the datatype’s members if you have the new autocomplete:

image

Oh cool, thanks again for your help.

1 Like

How would I do this if I wanted to make it so I could move/rotate a part?