What I did truly changed was the button thing, but even in the video, it shows the exact same system.
LocalScript
--[[
For future readers, I owe you an apology for this terrible script.
Reversing script is inside of the button, while the cloth toggling script is in StarterPlayerScripts.
Very inconsistent.
Oh and I should be using double quotes instead lol
If you think this script is bad, wait until you see the cloth module LOLOLOLOLOL
]]--
local runService = game:GetService('RunService')
local player = game:GetService('Players').LocalPlayer
local playerGui = player.PlayerGui
local cloth = require(script.Parent:WaitForChild('Cloth'))
local myCloth = cloth.new(Vector2.new(10, 10), Vector3.new(10, 1, 10), Vector3.new(-86, 12.5, -118),false)
wait(1)
myCloth:attachTo(1, 1, workspace.Thing.A, Vector3.new(0, workspace.Thing.A.Size.Y/2, 0))
myCloth:attachTo(10, 1, workspace.Thing.B, Vector3.new(0, workspace.Thing.A.Size.Y/2, 0))
myCloth:attachTo(10, 10, workspace.Thing.C, Vector3.new(0, workspace.Thing.A.Size.Y/2, 0))
myCloth:attachTo(1, 10, workspace.Thing.D, Vector3.new(0, workspace.Thing.A.Size.Y/2, 0))
local enabled = true
runService.RenderStepped:Connect(function()
if enabled then
myCloth:update()
end
end)
ModuleScript
local physicsService = game:GetService('PhysicsService')
local cloth = {}
cloth.__index = cloth
local wedge = Instance.new("WedgePart");
wedge.Anchored = true;
wedge.CanCollide = false
wedge.TopSurface = Enum.SurfaceType.Smooth;
wedge.Material = Enum.Material.SmoothPlastic
wedge.Color = Color3.fromRGB(117, 0, 0)
wedge.BottomSurface = Enum.SurfaceType.Smooth;
local function draw3dTriangle(a, b, c, parent, w1, w2)
local ab, ac, bc = b - a, c - a, c - b;
local abd, acd, bcd = ab:Dot(ab), ac:Dot(ac), bc:Dot(bc);
if (abd > acd and abd > bcd) then
c, a = a, c;
elseif (acd > bcd and acd > abd) then
a, b = b, a;
end
ab, ac, bc = b - a, c - a, c - b;
local right = ac:Cross(ab).unit;
local up = bc:Cross(right).unit;
local back = bc.unit;
local height = math.abs(ab:Dot(up));
w1 = w1 or wedge:Clone();
w1.Size = Vector3.new(0, height, math.abs(ab:Dot(back)));
w1.CFrame = CFrame.fromMatrix((a + b)/2, right, up, back);
w1.Parent = parent;
w2 = w2 or wedge:Clone();
w2.Size = Vector3.new(0, height, math.abs(ac:Dot(back)));
w2.CFrame = CFrame.fromMatrix((a + c)/2, -right, up, -back);
w2.Parent = parent;
return w1, w2;
end
function cloth.new(res, size, pos, canCollide)
local self = setmetatable({}, cloth)
self.Attachments = {}
self.CanCollide = canCollide or true
self.Position = pos or Vector3.new(0,0,0)
self.Size = size or Vector3.new(10, 1, 10)
self.Resolution = res or Vector2.new(10, 10)
self.Model = Instance.new("Model")
self.Wedges = {}
self:createParts()
self:createSprings()
self.Model.Parent = workspace
return self
end
function cloth:createParts()
for x = 1, self.Resolution.X, 1 do
self.Attachments[x] = {}
for y = 1, self.Resolution.Y, 1 do
local part = Instance.new("Part")
part.Size = Vector3.new(1,1,1)
part.Position = self.Position + Vector3.new(x*(self.Size.X / self.Resolution.X), 5, y*(self.Size.Z / self.Resolution.Y))
part.Transparency = 1
part.Anchored = false --true
part.CanCollide = self.CanCollide or false
local attachment = Instance.new("Attachment")
attachment.Parent = part
self.Attachments[x][y] = attachment
part.Parent = self.Model
end
end
end
function cloth:createSprings()
for x = 1, self.Resolution.X, 1 do
for y = 1, self.Resolution.Y, 1 do
if self.Attachments[x+1] and self.Attachments[x+1][y] then
local spring1 = script.SpringConstraint:Clone()
spring1.Attachment0 = self.Attachments[x][y]
spring1.Attachment1 = self.Attachments[x+1][y]
spring1.Parent = self.Attachments[x][y].Parent
end
if self.Attachments[x][y+1] then
local spring2 = script.SpringConstraint:Clone()
spring2.Attachment0 = self.Attachments[x][y]
spring2.Attachment1 = self.Attachments[x][y+1]
spring2.Parent = self.Attachments[x][y].Parent
end
end
end
end
function cloth:getAttachment(x, y)
if self.Attachments[x] then
return self.Attachments[x][y]
else
return nil
end
end
function cloth:registerTri(a,b,c, w1, w2)
if not self.Wedges[ self.Attachments[ a[1] ][ a[2] ] ] then
self.Wedges[ self.Attachments[ a[1] ][ a[2] ] ] = {}
end
if not self.Wedges[ self.Attachments[ a[1] ][ a[2] ] ][ self.Attachments[ b[1] ][ b[2] ] ] then
self.Wedges[ self.Attachments[ a[1] ][ a[2] ] ][ self.Attachments[ b[1] ][ b[2] ] ] = {}
end
self.Wedges[ self.Attachments[ a[1] ][ a[2] ] ][ self.Attachments[ b[1] ][ b[2] ] ][ self.Attachments[ c[1] ][ c[2] ] ] = {w1, w2}
end
function cloth:getTri(a,b,c)
if not self.Wedges[ self.Attachments[ a[1] ][ a[2] ] ] then
return
end
if not self.Wedges[ self.Attachments[ a[1] ][ a[2] ] ][ self.Attachments[ b[1] ][ b[2] ] ] then
return
end
return self.Wedges[ self.Attachments[ a[1] ][ a[2] ] ][ self.Attachments[ b[1] ][ b[2] ] ][ self.Attachments[ c[1] ][ c[2] ] ]
end
function cloth:update()
for x = 1, self.Resolution.X, 1 do
for y = 1, self.Resolution.Y, 1 do
local a = self:getAttachment(x, y) and self:getAttachment(x, y).WorldPosition
local b = self:getAttachment(x + 1, y) and self:getAttachment(x + 1, y).WorldPosition
local c = self:getAttachment(x, y + 1) and self:getAttachment(x, y + 1).WorldPosition
local d = self:getAttachment(x + 1, y + 1) and self:getAttachment(x + 1, y + 1).WorldPosition
if a and b and c then
local tri = self:getTri({x, y},{x + 1, y},{x, y + 1})
local w1, w2 = draw3dTriangle(a, b, c, workspace.Terrain, tri and tri[1], tri and tri[2])
self:registerTri({x, y},{x + 1, y},{x, y + 1}, w1, w2)
end
if b and d and c then
local tri = self:getTri({x + 1, y},{x + 1, y + 1},{x, y + 1})
local w1, w2 = draw3dTriangle(b, d, c, workspace.Terrain, tri and tri[1], tri and tri[2])
self:registerTri({x + 1, y},{x + 1, y + 1},{x, y + 1}, w1, w2)
end
end
end
end
function cloth:movePoint(x, y, pos)
self.Attachments[x][y].Parent.Position = pos
end
function cloth:attachTo(x, y, part, offset)
self:movePoint(x, y, part.Position + (offset or Vector3.new(0,0,0)))
local point = self.Attachments[x][y].Parent
local weld = Instance.new("WeldConstraint")
weld.Part0 = point
weld.Part1 = part
weld.Parent = point
end
return cloth