Clients/Client2018/content/scripts/PlayerScripts/StarterPlayerScripts_NewStr.../RobloxPlayerScript/CameraScript/TransparencyController.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