Making a move tool that replicates Studio's move tool?

Hello everyone

So I am trying to make a move tool that replicates the ROBLOX studio move tool, but in-game. I have made this topic before, however, I realize now I was not too clear before.

I already know I have to put handles in a part and use the MouseDrag event on the handles and then inside that event add code to move the part based on the arguments given by default on the MoustDrag event

My question is what do I put inside that event? What code should I put in there to make it move the part when the handles are dragged.

5 Likes

First things first, you need to know that MouseDrag has 2 parameters, face and distance. The distance is pretty self explanatory, but the face is where it gets slightly complicated.

You’ll have to find out which direction the selected face is pointing at. Now, all the unit vectors will have 1 coordinate equal to 1, while the others are 0 ((1,0,0), (0,1,0) and (0,0,1)), so they basically represent the global axis of movement.

(Sorry for the edit, kinda mixed things up with a half custom system I have.)

In short, take the NormalId given as the face. Convert the Enum to a Vector3 with the Vector3.FromNormalId(enum) function and offset the part along the axis depending on the distance.

local Part = Handles.Adornee
local CF = Part.CFrame
Handles.MouseDrag:Connect(function(face, dist)
    CF = CF+Vector3.FromNormalId(face)*dist
    Part.CFrame = CF
end)
9 Likes

@nooneisback

Thank you. only issue I am having is that its moving too much. Like its not going 1 stud at a time.

1 Like

Add a factor and multiply the distance by it.
CF = CF+Vector3.FromNormalId(face)* dist* 0.5

1 Like

How does this change it?

It basically divides the distance, try different values until you get the right one.

Is there any way I can make it work with increment?

Make 2 CFrame values, 1 for the actual part’s CFrame, the other to compare it to and check if the magnitude between their position values is above your increment limit. If it is, update the first value.

Can I get an example?

1 Like
local Part = Handles.Adornee
local RCF = Part.CFrame
local CF = RCF
local inc = 0.5
Handles.MouseDrag:Connect(function(face, dist)
    CF = CF+Vector3.FromNormalId(face)*dist
    if (RCF.p-CF.p).magnitude>=0.5 then
        RCF = RCF+(CF.p-RCF.p).Unit*0.5
        CF=RCF Part.CFrame=RCF
    end
end)

IDK if this is correct since I wrote this on my phone, but that’s what I first think of when someone tells me how to do this.

1 Like

nooneisback’s solution is slightly buggy because his code doesn’t account for roblox increasing the dist argument as you drag.

  1. The dist will keep adding up until you let go, so to make the dragging not buggy, use this code:
local Part = Handles.Adornee
local CF
Handles.MouseButton1Down:connect(function()
    CF = Part.CFrame
end)
Handles.MouseDrag:Connect(function(face, dist)
    Part.CFrame = CF = CF+Vector3.FromNormalId(face)*dist
end)

  1. To add an increment, you will want to round the distance down to the closest value that fits the increment. This can be done by dividing the distance by the increment, flooring it, and multiplying it back up by the increment.
local Part = Handles.Adornee
local CF
local increment = 3
Handles.MouseButton1Down:connect(function()
    CF = Part.CFrame
end)
Handles.MouseDrag:Connect(function(face, dist)
    Part.CFrame = CF+Vector3.FromNormalId(face)*(math.floor(dist/increment)*increment)
end)
6 Likes

That’s what I thought of RN. I had no idea whether handles take the original CFrame value, or the current one.

Oh! That is why it kept adding distance.

So the first part how exactly does it prevent the constantly adding distance?

It checks the CFrame value on click, not whenever you drag. Which is where my mistake was.

Ah got it! Also, is there a way to make it so when I move the part, it stays within a certain perimiter?

You will want to check what the CFrame of the part will be after you move it, and then check if each corner of the part is within the bounds you wish to confine it to. If it will still be within, then update the CFrame, otherwise don’t.

I’m confused here. Are you asking for guidance, or asking for code? So far, developers have been providing you code but no prior attempts at creating a dragger from you have been seen nor incorporated using the feedback provided.

I feel I must remind you that the Scripting Support categories are not for asking for code snippets. If that is not your intention, I apologise.

It is not, my intention is to understand how it works.

I tried to use the code but it doesn’t work, maybe I need to use previous distance or something with delta? I saw that somewhere.

And how would I know its within a boundary?

1 Like

Is putting it in a bound complex? How’d I go about doing it?

Depends on what kind of boundary you want. If it’s centered at the part’s position, then you could use a delta. If its corners are given as Vector3s, then you’d have to check if the CFrame’s position value is within it; otherwise, return it to the edge.