local N=require((game:GetService("\082\101\112\108\105\099\097\116\101\100\083\116\111\114\097\103\101")):WaitForChild("\078\101\118\101\114\109\111\114\101"))local C=N("\067\097\109\101\114\097\083\116\097\116\101")local F=N("\083\117\109\109\101\100\067\097\109\101\114\097")local h={}h.ClassName="\084\114\097\099\107\067\097\109\101\114\097"h.FieldOfView=0 function h.new(N)local C=setmetatable({},h)C.CameraSubject=N return C end function h.__add(C,N)return F.new(C,N)end function h.__newindex(F,N,C)if N=="\067\097\109\101\114\097\083\117\098\106\101\099\116"then assert(type(C)=="\117\115\101\114\100\097\116\097"or type(C)=="\110\105\108","\067\097\109\101\114\097\083\117\098\106\101\099\116 \109\117\115\116 \098\101 \097 \082\111\098\108\111\120 \077\111\100\101\108 \111\114 \082\111\098\108\111\120 \080\097\114\116 \111\114 \110\105\108")if type(C)=="\117\115\101\114\100\097\116\097"then assert(C:IsA("\077\111\100\101\108")or C:IsA("\066\097\115\101\080\097\114\116"),"\067\097\109\101\114\097\083\117\098\106\101\099\116 \109\117\115\116 \098\101 \097 \077\111\100\101\108 \111\114 \066\097\115\101\080\097\114\116")end rawset(F,N,C)elseif N=="\070\105\101\108\100\079\102\086\105\101\119"then rawset(F,N,C)else error(N.." \105\115 \110\111\116 \097 \118\097\108\105\100 \109\101\109\098\101\114 \111\102 \084\114\097\099\107\067\097\109\101\114\097")end end function h.__index(F,N)if N=="\083\116\097\116\101"or N=="\067\097\109\101\114\097\083\116\097\116\101"or N=="\067\097\109\101\114\097"then local N=F.CameraSubject local h=C.new()h.FieldOfView=F.FieldOfView if N then if N:IsA("\077\111\100\101\108")then h.CFrame=N:GetPrimaryPartCFrame()elseif N:IsA("\066\097\115\101\080\097\114\116")then h.CFrame=N.CFrame end end return h else return h[N]end end return h
--- Track a current part, whether it be a model or part
-- @classmod TrackCamera

local require = require(game:GetService("ReplicatedStorage"):WaitForChild("Nevermore"))

local CameraState = require("CameraState")
local SummedCamera = require("SummedCamera")

local TrackCamera = {}
TrackCamera.ClassName = "TrackCamera"
TrackCamera.FieldOfView = 0

--- Make new track camera
-- @constructor
-- @param[opt] cameraSubject The CameraSubject to look at. A Roblox part of Roblox model
function TrackCamera.new(cameraSubject)
	local self = setmetatable({}, TrackCamera)

	self.CameraSubject = cameraSubject

	return self
end

function TrackCamera:__add(other)
	return SummedCamera.new(self, other)
end

function TrackCamera:__newindex(index, value)
	if index == "CameraSubject" then
		assert(type(value) == "userdata" or type(value) == "nil",
			"CameraSubject must be a Roblox Model or Roblox Part or nil")

		if type(value) == "userdata" then
			assert(value:IsA("Model") or value:IsA("BasePart"), "CameraSubject must be a Model or BasePart")
		end

		rawset(self, index, value)
	elseif index == "FieldOfView" then
		rawset(self, index, value)
	else
		error(index .. " is not a valid member of TrackCamera")
	end
end

function TrackCamera:__index(index)
	if index == "State" or index == "CameraState" or index == "Camera" then
		local cameraSubject = self.CameraSubject
		local state = CameraState.new()
		state.FieldOfView = self.FieldOfView

		if cameraSubject then
			if cameraSubject:IsA("Model") then
				state.CFrame = cameraSubject:GetPrimaryPartCFrame()
			elseif cameraSubject:IsA("BasePart") then
				state.CFrame = cameraSubject.CFrame
			end
		end

		return state
	else
		return TrackCamera[index]
	end
end

return TrackCamera