From 9bf81bb6f20d7c34146850802d251038876da003 Mon Sep 17 00:00:00 2001 From: GigsD4X Date: Wed, 8 Nov 2023 20:11:02 -0800 Subject: [PATCH] fix: Add temp. accuracy workaround to Move & Rotate This adds a temporary workaround to the floating point error accumulation problem by rounding delta CFrame components to an identity CFrame when they are fuzzily equal. --- Libraries/SupportLibrary.lua | 25 +++++++++++++++++++++++++ Tools/Move/Util.lua | 14 +++++++++----- Tools/Move/init.lua | 4 ++-- Tools/Rotate.lua | 4 ++-- 4 files changed, 38 insertions(+), 9 deletions(-) diff --git a/Libraries/SupportLibrary.lua b/Libraries/SupportLibrary.lua index 6c1c5e3..f966b3e 100644 --- a/Libraries/SupportLibrary.lua +++ b/Libraries/SupportLibrary.lua @@ -826,4 +826,29 @@ function SupportLibrary.CreateConsecutiveCallDeferrer(MaxInterval) end +--[=[ + Returns objectCFrame:ToObjectSpace(cframe), with each component + rounded to an identity CFrame if it's fuzzily equal. + + TODO: Figure out a more elegant solution to this. +]=] +function SupportLibrary.ToObjectSpace(objectCFrame: CFrame, cframe: CFrame): CFrame + local identity = CFrame.identity + local offset = objectCFrame:ToObjectSpace(cframe) + return CFrame.fromMatrix( + if offset.Position:FuzzyEq(identity.Position) + then identity.Position + else offset.Position, + if offset.XVector:FuzzyEq(identity.XVector) + then identity.XVector + else offset.XVector, + if offset.YVector:FuzzyEq(identity.YVector) + then identity.YVector + else offset.YVector, + if offset.ZVector:FuzzyEq(identity.ZVector) + then identity.ZVector + else offset.ZVector + ) +end + return SupportLibrary; \ No newline at end of file diff --git a/Tools/Move/Util.lua b/Tools/Move/Util.lua index c6443e4..5454650 100644 --- a/Tools/Move/Util.lua +++ b/Tools/Move/Util.lua @@ -1,14 +1,18 @@ +local Tool = script.Parent.Parent.Parent + +-- Libraries +local Libraries = Tool:WaitForChild("Libraries") +local Support = require(Libraries:WaitForChild("SupportLibrary")) + local function TranslatePartsRelativeToPart(BasePart, InitialPartStates, InitialModelStates) -- Moves the given parts in `InitialStates` to BasePart's current position, with their original offset from it -- Get focused part's position for offsetting - local RelativeTo = InitialPartStates[BasePart].CFrame:inverse() + local PivotCFrame = InitialPartStates[BasePart].CFrame -- Calculate offset and move each part for Part, InitialState in pairs(InitialPartStates) do - - -- Calculate how far apart we should be from the focused part - local Offset = RelativeTo * InitialState.CFrame + local Offset = Support.ToObjectSpace(PivotCFrame, InitialState.CFrame) -- Move relative to the focused part by this part's offset from it Part.CFrame = BasePart.CFrame * Offset @@ -17,7 +21,7 @@ local function TranslatePartsRelativeToPart(BasePart, InitialPartStates, Initial -- Calculate offset and move each model for Model, InitialState in pairs(InitialModelStates) do - local Offset = RelativeTo * InitialState.Pivot + local Offset = Support.ToObjectSpace(PivotCFrame, InitialState.Pivot) Model.WorldPivot = BasePart.CFrame * Offset end end diff --git a/Tools/Move/init.lua b/Tools/Move/init.lua index 67d84a8..21737e9 100644 --- a/Tools/Move/init.lua +++ b/Tools/Move/init.lua @@ -172,11 +172,11 @@ function MoveTool:MovePartsAlongAxesByFace(Face, Distance, InitialPartStates, In -- Move parts based on initial offset from focus for Part, InitialState in pairs(InitialPartStates) do - local FocusOffset = InitialFocusCFrame:toObjectSpace(InitialState.CFrame) + local FocusOffset = Support.ToObjectSpace(InitialFocusCFrame, InitialState.CFrame) Part.CFrame = FocusCFrame * FocusOffset end for Model, InitialState in pairs(InitialModelStates) do - local FocusOffset = InitialFocusCFrame:ToObjectSpace(InitialState.Pivot) + local FocusOffset = Support.ToObjectSpace(InitialFocusCFrame, InitialState.Pivot) Model.WorldPivot = FocusCFrame * FocusOffset end diff --git a/Tools/Rotate.lua b/Tools/Rotate.lua index 328c73b..f3dd21e 100644 --- a/Tools/Rotate.lua +++ b/Tools/Rotate.lua @@ -463,7 +463,7 @@ function RotateSelectionAroundPivot(PivotMode, PivotPoint, Axis, Rotation, Initi local RelativeTo = PivotPoint * RotationCFrame; -- Calculate this part's offset from the focused part's rotation - local Offset = PivotPoint:toObjectSpace(InitialState.CFrame); + local Offset = Support.ToObjectSpace(PivotPoint, InitialState.CFrame) -- Rotate relative to the focused part by this part's offset from it Part.CFrame = RelativeTo * Offset; @@ -486,7 +486,7 @@ function RotateSelectionAroundPivot(PivotMode, PivotPoint, Axis, Rotation, Initi local RelativeTo = PivotPoint * RotationCFrame -- Calculate this part's offset from the focused part's rotation - local Offset = PivotPoint:ToObjectSpace(InitialState.Pivot) + local Offset = Support.ToObjectSpace(PivotPoint, InitialState.Pivot) -- Rotate relative to the focused part by this model's offset from it Model.WorldPivot = RelativeTo * Offset