190 lines
5.6 KiB
Lua
190 lines
5.6 KiB
Lua
--[[
|
|
TransparencyController - Manages transparency of player character at close camera-to-subject distances
|
|
2018 Camera Update - AllYourBlox
|
|
--]]
|
|
|
|
local MAX_TWEEN_RATE = 2.8 -- per second
|
|
|
|
local Util = require(script.Parent:WaitForChild("CameraUtils"))
|
|
|
|
--[[ 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 object.Parent:IsA('Tool') or self:HasToolAncestor(object.Parent)
|
|
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
|
|
elseif object:IsA('Tool') then
|
|
if self.toolDescendantAddedConns[object] then self.toolDescendantAddedConns[object]:Disconnect() end
|
|
self.toolDescendantAddedConns[object] = object.DescendantAdded:Connect(function(toolChild)
|
|
self.cachedParts[toolChild] = nil
|
|
if toolChild:IsA('BasePart') or toolChild:IsA('Decal') then
|
|
-- Reset the transparency
|
|
toolChild.LocalTransparencyModifier = 0
|
|
end
|
|
end)
|
|
if self.toolDescendantRemovingConns[object] then self.toolDescendantRemovingConns[object]:disconnect() end
|
|
self.toolDescendantRemovingConns[object] = object.DescendantRemoving:Connect(function(formerToolChild)
|
|
wait() -- wait for new parent
|
|
if character and formerToolChild and formerToolChild:IsDescendantOf(character) then
|
|
if self:IsValidPartToModify(formerToolChild) then
|
|
self.cachedParts[formerToolChild] = true
|
|
self.transparencyDirty = true
|
|
end
|
|
end
|
|
end)
|
|
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 = Util.Clamp(-maxDelta, maxDelta, deltaTransparency)
|
|
end
|
|
transparency = self.lastTransparency + deltaTransparency
|
|
else
|
|
self.transparencyDirty = true
|
|
end
|
|
|
|
transparency = Util.Clamp(0, 1, Util.Round(transparency, 2))
|
|
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
|