local X={}X.__index=X function X.new()local G=setmetatable({},X)G.lastUpdate=tick()G.transparencyDirty=false G.enabled=false G.lastTransparency=nil G.descendantAddedConn,G.descendantRemovingConn=nil,nil G.toolDescendantAddedConns={}G.toolDescendantRemovingConns={}G.cachedParts={}return G end function X.HasToolAncestor(G,X)if X.Parent==nil then return false end return false end function X.IsValidPartToModify(G,X)if X:IsA("\066\097\115\101\080\097\114\116")or X:IsA("\068\101\099\097\108")then return not G:HasToolAncestor(X)end return false end function X.CachePartsRecursive(G,X)if X then if G:IsValidPartToModify(X)then G.cachedParts[X]=true G.transparencyDirty=true end for X,F in pairs(X:GetChildren())do G:CachePartsRecursive(F)end end end function X.TeardownTransparency(X)for X,G in pairs(X.cachedParts)do X.LocalTransparencyModifier=0 end X.cachedParts={}X.transparencyDirty=true X.lastTransparency=nil if X.descendantAddedConn then X.descendantAddedConn:disconnect()X.descendantAddedConn=nil end if X.descendantRemovingConn then X.descendantRemovingConn:disconnect()X.descendantRemovingConn=nil end for G,F in pairs(X.toolDescendantAddedConns)do F:Disconnect()X.toolDescendantAddedConns[G]=nil end for G,F in pairs(X.toolDescendantRemovingConns)do F:Disconnect()X.toolDescendantRemovingConns[G]=nil end end function X.SetupTransparency(G,X)G:TeardownTransparency()if G.descendantAddedConn then G.descendantAddedConn:disconnect()end G.descendantAddedConn=X.DescendantAdded:Connect(function(X)if G:IsValidPartToModify(X)then G.cachedParts[X]=true G.transparencyDirty=true end end)if G.descendantRemovingConn then G.descendantRemovingConn:disconnect()end G.descendantRemovingConn=X.DescendantRemoving:connect(function(X)if G.cachedParts[X]then G.cachedParts[X]=nil X.LocalTransparencyModifier=0 end end)G:CachePartsRecursive(X)end function X.Enable(G,X)if G.enabled~=X then G.enabled=X G:Update()end end function X.SetSubject(G,X)local F=nil if X and X:IsA("\072\117\109\097\110\111\105\100")then F=X.Parent end if X and(X:IsA("\086\101\104\105\099\108\101\083\101\097\116")and X.Occupant)then F=X.Occupant.Parent end if F then G:SetupTransparency(F)else G:TeardownTransparency()end end function X.Update(X)local G=false local F=tick()local c=workspace.CurrentCamera if c then local T=0 if not X.enabled then G=true else local a=(c.Focus.p-c.CoordinateFrame.p).magnitude T=a<2 and 1.0-(a-.5)/1.5 or 0 if T<.5 then T=0 end if X.lastTransparency then local c=T-X.lastTransparency if not G and(T<1 and X.lastTransparency<.95)then local G=MAX_TWEEN_RATE*(F-X.lastUpdate)c=math.clamp(c,-G,G)end T=X.lastTransparency+c else X.transparencyDirty=true end T=math.clamp(Util.Round(T,2),0,1)end if X.transparencyDirty or X.lastTransparency~=T then for X,G in pairs(X.cachedParts)do X.LocalTransparencyModifier=T end X.transparencyDirty=false X.lastTransparency=T end end X.lastUpdate=F end return X
--[[ The Module ]]
--
local TransparencyController = {}
TransparencyController.__index = TransparencyController

function TransparencyController.new()
	local self = setmetatable({}, TransparencyController)

	self.lastUpdate = tick()
	self.transparencyDirty = false
	self.enabled = false
	self.lastTransparency = nil

	self.descendantAddedConn, self.descendantRemovingConn = nil, nil
	self.toolDescendantAddedConns = {}
	self.toolDescendantRemovingConns = {}
	self.cachedParts = {}

	return self
end

function TransparencyController:HasToolAncestor(object)
	if object.Parent == nil then
		return false
	end
	return false
end

function TransparencyController:IsValidPartToModify(part)
	if part:IsA("BasePart") or part:IsA("Decal") then
		return not self:HasToolAncestor(part)
	end
	return false
end

function TransparencyController:CachePartsRecursive(object)
	if object then
		if self:IsValidPartToModify(object) then
			self.cachedParts[object] = true
			self.transparencyDirty = true
		end
		for _, child in pairs(object:GetChildren()) do
			self:CachePartsRecursive(child)
		end
	end
end

function TransparencyController:TeardownTransparency()
	for child, _ in pairs(self.cachedParts) do
		child.LocalTransparencyModifier = 0
	end
	self.cachedParts = {}
	self.transparencyDirty = true
	self.lastTransparency = nil

	if self.descendantAddedConn then
		self.descendantAddedConn:disconnect()
		self.descendantAddedConn = nil
	end
	if self.descendantRemovingConn then
		self.descendantRemovingConn:disconnect()
		self.descendantRemovingConn = nil
	end
	for object, conn in pairs(self.toolDescendantAddedConns) do
		conn:Disconnect()
		self.toolDescendantAddedConns[object] = nil
	end
	for object, conn in pairs(self.toolDescendantRemovingConns) do
		conn:Disconnect()
		self.toolDescendantRemovingConns[object] = nil
	end
end

function TransparencyController:SetupTransparency(character)
	self:TeardownTransparency()

	if self.descendantAddedConn then
		self.descendantAddedConn:disconnect()
	end
	self.descendantAddedConn = character.DescendantAdded:Connect(function(object)
		-- This is a part we want to invisify
		if self:IsValidPartToModify(object) then
			self.cachedParts[object] = true
			self.transparencyDirty = true
			-- There is now a tool under the character
		end
	end)
	if self.descendantRemovingConn then
		self.descendantRemovingConn:disconnect()
	end
	self.descendantRemovingConn = character.DescendantRemoving:connect(function(object)
		if self.cachedParts[object] then
			self.cachedParts[object] = nil
			-- Reset the transparency
			object.LocalTransparencyModifier = 0
		end
	end)
	self:CachePartsRecursive(character)
end

function TransparencyController:Enable(enable)
	if self.enabled ~= enable then
		self.enabled = enable
		self:Update()
	end
end

function TransparencyController:SetSubject(subject)
	local character = nil
	if subject and subject:IsA("Humanoid") then
		character = subject.Parent
	end
	if subject and subject:IsA("VehicleSeat") and subject.Occupant then
		character = subject.Occupant.Parent
	end
	if character then
		self:SetupTransparency(character)
	else
		self:TeardownTransparency()
	end
end

function TransparencyController:Update()
	local instant = false
	local now = tick()
	local currentCamera = workspace.CurrentCamera

	if currentCamera then
		local transparency = 0
		if not self.enabled then
			instant = true
		else
			local distance = (currentCamera.Focus.p - currentCamera.CoordinateFrame.p).magnitude
			transparency = (distance < 2) and (1.0 - (distance - 0.5) / 1.5) or 0 --(7 - distance) / 5
			if transparency < 0.5 then
				transparency = 0
			end

			if self.lastTransparency then
				local deltaTransparency = transparency - self.lastTransparency

				-- Don't tween transparency if it is instant or your character was fully invisible last frame
				if not instant and transparency < 1 and self.lastTransparency < 0.95 then
					local maxDelta = MAX_TWEEN_RATE * (now - self.lastUpdate)
					deltaTransparency = math.clamp(deltaTransparency, -maxDelta, maxDelta)
				end
				transparency = self.lastTransparency + deltaTransparency
			else
				self.transparencyDirty = true
			end

			transparency = math.clamp(Util.Round(transparency, 2), 0, 1)
		end

		if self.transparencyDirty or self.lastTransparency ~= transparency then
			for child, _ in pairs(self.cachedParts) do
				child.LocalTransparencyModifier = transparency
			end
			self.transparencyDirty = false
			self.lastTransparency = transparency
		end
	end
	self.lastUpdate = now
end

return TransparencyController
