Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update F3X to use PivotTo where possible #148

Open
wants to merge 1 commit into
base: development
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
39 changes: 39 additions & 0 deletions Core/Selection.lua
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,45 @@ local function CollectPartsAndModels(Item, PartTable, ModelTable)
end
end

local function CollectTransformablesRecursive(PotentialRoot: Instance, Seen: {PVInstance: boolean}, Roots: {PVInstance})
if PotentialRoot:IsA("PVInstance") then
-- Once we hit a PVInstance, if it's already been seen, this heirarchy
-- has already been traversed down, bail out.
if Seen[PotentialRoot] then
return
end

-- Mark this as seen and insert it into the set of roots
Seen[PotentialRoot] = true
table.insert(Roots, PotentialRoot)

-- At this point, we know we haven't seen the descendants, go and mark
-- all the descendants as seen.
for _, Descendant in PotentialRoot:GetDescendants() do
if Descendant:IsA("PVInstance") then
Seen[Descendant] = true
end
end
else
-- Traverse down hierarchy looking for roots
for _, Child in PotentialRoot:GetChildren() do
CollectTransformablesRecursive(Child, Seen, Roots)
end
end
end

-- Get all the PVInstances in the selection which are NOT inside of another
-- PVInstance in the selection. Those are the PVInstances which need to be
-- transformed via PivotTo.
function Selection.GetRootPVInstances(Items: {Instance}): {PVInstance}
local Seen = {} :: {PVInstance: boolean}
local Results = {} :: {PVInstance}
for _, Instance in Items do
CollectTransformablesRecursive(Instance, Seen, Results)
end
return Results
end

function Selection.Add(Items, RegisterHistory)
-- Adds the given items to the selection

Expand Down
151 changes: 64 additions & 87 deletions SyncAPI.lua
Original file line number Diff line number Diff line change
Expand Up @@ -415,22 +415,19 @@ Actions = {

end;

['SyncMove'] = function (Changes)
-- Updates parts server-side given their new CFrames
['SyncResize'] = function (Changes)
-- Updates parts server-side given their new sizes and CFrames

-- Grab a list of every part we're attempting to modify
local Parts = {};
local Models = {}
for _, Change in pairs(Changes) do
if Change.Part then
table.insert(Parts, Change.Part);
elseif Change.Model then
table.insert(Models, Change.Model)
end
end;
end;

-- Ensure parts are selectable
if not (CanModifyItems(Parts) and CanModifyItems(Models)) then
if not CanModifyItems(Parts) then
return;
end;

Expand All @@ -443,74 +440,59 @@ Actions = {
end;

-- Reorganize the changes
local PartChangeSet = {}
local ModelChangeSet = {}
local ChangeSet = {};
for _, Change in pairs(Changes) do
if Change.Part then
Change.InitialState = {
Anchored = Change.Part.Anchored;
CFrame = Change.Part.CFrame;
}
PartChangeSet[Change.Part] = Change
elseif Change.Model then
ModelChangeSet[Change.Model] = Change.Pivot
end
end;

-- Preserve joints
for Part, Change in pairs(PartChangeSet) do
Change.Joints = PreserveJoints(Part, PartChangeSet)
Change.InitialState = { Anchored = Change.Part.Anchored, Size = Change.Part.Size, CFrame = Change.Part.CFrame };
ChangeSet[Change.Part] = Change;
end;
end;

-- Perform each change
for Part, Change in pairs(PartChangeSet) do
for Part, Change in pairs(ChangeSet) do

-- Stabilize the parts and maintain the original anchor state
Part.Anchored = true;
Part:BreakJoints();
Part.Velocity = Vector3.new();
Part.RotVelocity = Vector3.new();

-- Set the part's CFrame
-- Set the part's size and CFrame
Part.Size = Change.Size;
Part.CFrame = Change.CFrame;

end;
for Model, Pivot in pairs(ModelChangeSet) do
Model.WorldPivot = Pivot
end

-- Make sure the player is authorized to move parts into this area
if Security.ArePartsViolatingAreas(Parts, Player, false, AreaPermissions) then

-- Revert changes if unauthorized destination
for Part, Change in pairs(PartChangeSet) do
for Part, Change in pairs(ChangeSet) do
Part.Size = Change.InitialState.Size;
Part.CFrame = Change.InitialState.CFrame;
end;

end;

-- Restore the parts' original states
for Part, Change in pairs(PartChangeSet) do
for Part, Change in pairs(ChangeSet) do
Part:MakeJoints();
RestoreJoints(Change.Joints);
Part.Anchored = Change.InitialState.Anchored;
end;

end;

['SyncResize'] = function (Changes)
-- Updates parts server-side given their new sizes and CFrames
['SyncPartTransform'] = function (Changes)
-- Updates parts server-side given their new CFrames

-- Grab a list of every part we're attempting to modify
-- Grab a list of every part and model we're attempting to modify
local Parts = {};
for _, Change in pairs(Changes) do
if Change.Part then
table.insert(Parts, Change.Part);
end;
table.insert(Parts, Change.Part);
end;

-- Ensure parts are selectable
if not CanModifyItems(Parts) then
if not (CanModifyItems(Parts)) then
return;
end;

Expand All @@ -523,25 +505,32 @@ Actions = {
end;

-- Reorganize the changes
local ChangeSet = {};
local PartChangeSet = {}
for _, Change in pairs(Changes) do
if Change.Part then
Change.InitialState = { Anchored = Change.Part.Anchored, Size = Change.Part.Size, CFrame = Change.Part.CFrame };
ChangeSet[Change.Part] = Change;
end;
Change.InitialState = {
Anchored = Change.Part.Anchored;
CFrame = Change.Part.CFrame;
}
PartChangeSet[Change.Part] = Change
end
end;

-- Preserve joints
for Part, Change in pairs(PartChangeSet) do
Change.Joints = PreserveJoints(Part, PartChangeSet)
end;

-- Perform each change
for Part, Change in pairs(ChangeSet) do
for Part, Change in pairs(PartChangeSet) do

-- Stabilize the parts and maintain the original anchor state
Part.Anchored = true;
Part:BreakJoints();
Part.Velocity = Vector3.new();
Part.RotVelocity = Vector3.new();

-- Set the part's size and CFrame
Part.Size = Change.Size;
-- Set the part's CFrame
Part.CFrame = Change.CFrame;

end;
Expand All @@ -550,37 +539,43 @@ Actions = {
if Security.ArePartsViolatingAreas(Parts, Player, false, AreaPermissions) then

-- Revert changes if unauthorized destination
for Part, Change in pairs(ChangeSet) do
Part.Size = Change.InitialState.Size;
for Part, Change in pairs(PartChangeSet) do
Part.CFrame = Change.InitialState.CFrame;
end;

end;

-- Restore the parts' original states
for Part, Change in pairs(ChangeSet) do
for Part, Change in pairs(PartChangeSet) do
Part:MakeJoints();
RestoreJoints(Change.Joints);
Part.Anchored = Change.InitialState.Anchored;
end;

end;

['SyncRotate'] = function (Changes)
['SyncRootTransform'] = function (Changes)
-- Updates parts server-side given their new CFrames

-- Grab a list of every part and model we're attempting to modify
-- Grab a list of every root we're attempting to modify
local Parts = {};
local Models = {}
local PartChangeSet = {};
for _, Change in pairs(Changes) do
if Change.Part then
table.insert(Parts, Change.Part);
elseif Change.Model then
table.insert(Models, Change.Model)
local Root = Change.Root
if Root:IsA("BasePart") then
table.insert(Parts, Root)
PartChangeSet[Root] = {}
end
for _, Descendant in Root:GetDescendants() do
if Descendant:IsA("BasePart") then
table.insert(Parts, Descendant)
PartChangeSet[Descendant] = {}
end
end
end;

-- Ensure parts are selectable
if not (CanModifyItems(Parts) and CanModifyItems(Models)) then
if not (CanModifyItems(Parts)) then
return;
end;

Expand All @@ -593,57 +588,39 @@ Actions = {
end;

-- Reorganize the changes
local PartChangeSet = {}
local ModelChangeSet = {}
for _, Change in pairs(Changes) do
if Change.Part then
Change.InitialState = {
Anchored = Change.Part.Anchored;
CFrame = Change.Part.CFrame;
}
PartChangeSet[Change.Part] = Change
elseif Change.Model then
ModelChangeSet[Change.Model] = Change.Pivot
end
local RootChangeSet = {}
local InitialPivot = {}
for _, Change in Changes do
RootChangeSet[Change.Root] = Change.Pivot
InitialPivot[Change.Root] = Change.Root:GetPivot()
end;

-- Preserve joints
for Part, Change in pairs(PartChangeSet) do
for Part, Change in PartChangeSet do
Change.Joints = PreserveJoints(Part, PartChangeSet)
end;

-- Perform each change
for Part, Change in pairs(PartChangeSet) do

-- Stabilize the parts and maintain the original anchor state
Part.Anchored = true;
-- Stabilize parts
for Part, Change in PartChangeSet do
Part:BreakJoints();
Part.Velocity = Vector3.new();
Part.RotVelocity = Vector3.new();

-- Set the part's CFrame
Part.CFrame = Change.CFrame;

end;
for Model, Pivot in pairs(ModelChangeSet) do
Model.WorldPivot = Pivot
for Root, Pivot in RootChangeSet do
Root:PivotTo(Pivot)
end

-- Make sure the player is authorized to move parts into this area
if Security.ArePartsViolatingAreas(Parts, Player, false, AreaPermissions) then

-- Revert changes if unauthorized destination
for Part, Change in pairs(PartChangeSet) do
Part.CFrame = Change.InitialState.CFrame;
end;

for Root, Pivot in RootChangeSet do
Root:PivotTo(InitialPivot[Root])
end
end;

-- Restore the parts' original states
for Part, Change in pairs(PartChangeSet) do
Part:MakeJoints();
RestoreJoints(Change.Joints);
Part.Anchored = Change.InitialState.Anchored;
end;

end;
Expand Down
Loading