I have got a custom system made of several HandleAdornments which allows me to make my custom archandle look similar to Studio’s own orientator tool. However there is an issue with rotating the object based on the movement of the mouse whilst the handle is dragged.
Context
Here’s the main component of the draggable handle part below
local function LinkOrientHandle(handle: SphereHandleAdornment, dragMethod: (number)->(), axis: Enum.Axis)
local pairedAxes =
{
Enum.Axis:FromValue((axis.Value + 1) % 3),
Enum.Axis:FromValue((axis.Value - 1) % 3)
}
local axisFilter = (Vector3.FromAxis(pairedAxes[1]) + Vector3.FromAxis(pairedAxes[2]))
handle.MouseButton1Down:Connect(function()
local onMove : RBXScriptConnection
local mouseOrigin = mouse.Origin
local lastAngle = 0
onMove = mouse.Move:Connect(function()
local adornCF = handle.Adornee:GetPivot()
local mousePlane : Vector3 = cfe.axisIntersect(adornCF:ToObjectSpace(mouse.Origin), axis)
local currentAngle
if pairedAxes[1].Value > pairedAxes[2].Value then
currentAngle = math.atan2(mousePlane[pairedAxes[1].Name], mousePlane[pairedAxes[2].Name])
else
currentAngle = math.atan2(mousePlane[pairedAxes[2].Name], mousePlane[pairedAxes[1].Name])
end
local angularChange = (currentAngle - lastAngle + math.pi) % (2 * math.pi) - math.pi
lastAngle += angularChange
dragMethod(angularChange)
end)
mouse.Button1Up:Once(function()
onMove:Disconnect()
end)
end)
end
For context, cfe reffers to a module script (CFrame Extentions)
, the method mentioned above .axisIntersect
is of such:
cfExtentions.axisIntersect = function(line: CFrame, axis: Enum.Axis)
local t = - line.Position[axis.Name] / line.LookVector[axis.Name]
return line.Position + t * line.LookVector
end
For this context, it is used to figure out where the mouse would intersect with the plane perpendicular to the rotation axis, it is used to find the angle between the object and mouse.
The usage of the LinkOrientHandle()
procedure is as such:
LinkOrientHandle(uniqueHandle, function(change)
local startPivot = uniqueHandle.Adornee:GetPivot()
local orientalChange = {0, 0, 0}
orientalChange[inx] = -change / math.pi
uniqueHandle.Adornee:PivotTo(startPivot * CFrame.fromEulerAnglesXYZ(table.unpack(orientalChange)))
end, axis)
inx:
The index of the current axis (x axis: 1, y axis: 2, z axis: 3)
change:
The change in radian angle in the last frame.
uniqueHandle.Adornee:
The basepart or model that is being orientated.
Problem
There seem to be two major problems with this, which are the following:
Over-rotation
When the mouse moves, it seems that the change in angle on the plane is overstated, causing for the model to rotate far more than intended. This effect seems to act stronger with the distance between mouse-plane intersect and object center.
Rotation Opposition
One or Two of the Three axes (depending on sign multiplier) rotate opposite of their intended direction of rotation.
As a conclusion, it’s safe to assume that this problem is coming from the usage of arctan2
, yet changes to the order don’t seem to fix things. If you need extra source code or context then do ask!