154 lines
5.4 KiB
Lua
154 lines
5.4 KiB
Lua
--[[
|
|
LegacyCamera - Implements legacy controller types: Attach, Fixed, Watch
|
|
2018 Camera Update - AllYourBlox
|
|
--]]
|
|
|
|
-- Local private variables and constants
|
|
local UNIT_X = Vector3.new(1,0,0)
|
|
local UNIT_Y = Vector3.new(0,1,0)
|
|
local UNIT_Z = Vector3.new(0,0,1)
|
|
local X1_Y0_Z1 = Vector3.new(1,0,1) --Note: not a unit vector, used for projecting onto XZ plane
|
|
local ZERO_VECTOR3 = Vector3.new(0,0,0)
|
|
local ZERO_VECTOR2 = Vector2.new(0,0)
|
|
|
|
local VR_PITCH_FRACTION = 0.25
|
|
local tweenAcceleration = math.rad(220) --Radians/Second^2
|
|
local tweenSpeed = math.rad(0) --Radians/Second
|
|
local tweenMaxSpeed = math.rad(250) --Radians/Second
|
|
local TIME_BEFORE_AUTO_ROTATE = 2.0 --Seconds, used when auto-aligning camera with vehicles
|
|
local PORTRAIT_OFFSET = Vector3.new(0,-3,0)
|
|
|
|
local Util = require(script.Parent:WaitForChild("CameraUtils"))
|
|
|
|
--[[ Services ]]--
|
|
local PlayersService = game:GetService('Players')
|
|
local VRService = game:GetService("VRService")
|
|
|
|
--[[ The Module ]]--
|
|
local BaseCamera = require(script.Parent:WaitForChild("BaseCamera"))
|
|
local LegacyCamera = setmetatable({}, BaseCamera)
|
|
LegacyCamera.__index = LegacyCamera
|
|
|
|
function LegacyCamera.new()
|
|
local self = setmetatable(BaseCamera.new(), LegacyCamera)
|
|
|
|
self.cameraType = Enum.CameraType.Fixed
|
|
self.lastUpdate = tick()
|
|
self.lastDistanceToSubject = nil
|
|
|
|
return self
|
|
end
|
|
|
|
function LegacyCamera:GetModuleName()
|
|
return "LegacyCamera"
|
|
end
|
|
|
|
function LegacyCamera:Test()
|
|
print("LegacyCamera:Test()")
|
|
end
|
|
|
|
--[[ Functions overridden from BaseCamera ]]--
|
|
function LegacyCamera:SetCameraToSubjectDistance(desiredSubjectDistance)
|
|
return BaseCamera.SetCameraToSubjectDistance(self,desiredSubjectDistance)
|
|
end
|
|
|
|
function LegacyCamera:Update(dt)
|
|
|
|
-- Cannot update until cameraType has been set
|
|
if not self.cameraType then return end
|
|
|
|
local now = tick()
|
|
local timeDelta = (now - self.lastUpdate)
|
|
local camera = workspace.CurrentCamera
|
|
local newCameraCFrame = camera.CFrame
|
|
local newCameraFocus = camera.Focus
|
|
local player = PlayersService.LocalPlayer
|
|
local humanoid = self:GetHumanoid()
|
|
local cameraSubject = camera and camera.CameraSubject
|
|
local isInVehicle = cameraSubject and cameraSubject:IsA('VehicleSeat')
|
|
local isOnASkateboard = cameraSubject and cameraSubject:IsA('SkateboardPlatform')
|
|
local isClimbing = humanoid and humanoid:GetState() == Enum.HumanoidStateType.Climbing
|
|
|
|
if self.lastUpdate == nil or timeDelta > 1 then
|
|
self.lastDistanceToSubject = nil
|
|
end
|
|
local subjectPosition = self:GetSubjectPosition()
|
|
|
|
if self.cameraType == Enum.CameraType.Fixed then
|
|
if self.lastUpdate then
|
|
-- Cap out the delta to 0.1 so we don't get some crazy things when we re-resume from
|
|
local delta = math.min(0.1, now - self.lastUpdate)
|
|
local gamepadRotation = self:UpdateGamepad()
|
|
self.rotateInput = self.rotateInput + (gamepadRotation * delta)
|
|
end
|
|
|
|
if subjectPosition and player and camera then
|
|
local distanceToSubject = self:GetCameraToSubjectDistance()
|
|
local newLookVector = self:CalculateNewLookVector()
|
|
self.rotateInput = ZERO_VECTOR2
|
|
|
|
newCameraFocus = camera.Focus -- Fixed camera does not change focus
|
|
newCameraCFrame = CFrame.new(camera.CFrame.p, camera.CFrame.p + (distanceToSubject * newLookVector))
|
|
end
|
|
elseif self.cameraType == Enum.CameraType.Attach then
|
|
if subjectPosition and camera then
|
|
local distanceToSubject = self:GetCameraToSubjectDistance()
|
|
local humanoid = self:GetHumanoid()
|
|
if self.lastUpdate and humanoid and humanoid.RootPart then
|
|
|
|
-- Cap out the delta to 0.1 so we don't get some crazy things when we re-resume from
|
|
local delta = math.min(0.1, now - self.lastUpdate)
|
|
local gamepadRotation = self:UpdateGamepad()
|
|
self.rotateInput = self.rotateInput + (gamepadRotation * delta)
|
|
|
|
local forwardVector = humanoid.RootPart.CFrame.lookVector
|
|
|
|
local y = Util.GetAngleBetweenXZVectors(forwardVector, self:GetCameraLookVector())
|
|
if Util.IsFinite(y) then
|
|
-- Preserve vertical rotation from user input
|
|
self.rotateInput = Vector2.new(y, self.rotateInput.Y)
|
|
end
|
|
end
|
|
|
|
local newLookVector = self:CalculateNewLookVector()
|
|
self.rotateInput = ZERO_VECTOR2
|
|
|
|
newCameraFocus = CFrame.new(subjectPosition)
|
|
newCameraCFrame = CFrame.new(subjectPosition - (distanceToSubject * newLookVector), subjectPosition)
|
|
end
|
|
elseif self.cameraType == Enum.CameraType.Watch then
|
|
if subjectPosition and player and camera then
|
|
local cameraLook = nil
|
|
|
|
local humanoid = self:GetHumanoid()
|
|
if humanoid and humanoid.RootPart then
|
|
local diffVector = subjectPosition - camera.CFrame.p
|
|
cameraLook = diffVector.unit
|
|
|
|
if self.lastDistanceToSubject and self.lastDistanceToSubject == self:GetCameraToSubjectDistance() then
|
|
-- Don't clobber the zoom if they zoomed the camera
|
|
local newDistanceToSubject = diffVector.magnitude
|
|
self:SetCameraToSubjectDistance(newDistanceToSubject)
|
|
end
|
|
end
|
|
|
|
local distanceToSubject = self:GetCameraToSubjectDistance()
|
|
local newLookVector = self:CalculateNewLookVector(cameraLook)
|
|
self.rotateInput = ZERO_VECTOR2
|
|
|
|
newCameraFocus = CFrame.new(subjectPosition)
|
|
newCameraCFrame = CFrame.new(subjectPosition - (distanceToSubject * newLookVector), subjectPosition)
|
|
|
|
self.lastDistanceToSubject = distanceToSubject
|
|
end
|
|
else
|
|
-- Unsupported type, return current values unchanged
|
|
return camera.CFrame, camera.Focus
|
|
end
|
|
|
|
self.lastUpdate = now
|
|
return newCameraCFrame, newCameraFocus
|
|
end
|
|
|
|
return LegacyCamera
|