local p=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 N=p("\081\117\097\116\101\114\110\105\111\110\079\098\106\101\099\116")local q={}q.ClassName="\067\097\109\101\114\097\083\116\097\116\101"q.FieldOfView=0 q.Quaterion=N.new()q.Position=Vector3.new()function q.__index(k,p)if p=="\067\070\114\097\109\101"then return N.toCFrame(k.Quaterion,k.Position)else return q[p]end end function q.__newindex(k,p,q)if p=="\067\070\114\097\109\101"then rawset(k,"\080\111\115\105\116\105\111\110",q.p)rawset(k,"\081\117\097\116\101\114\105\111\110",N.fromCFrame(q))elseif p=="\070\105\101\108\100\079\102\086\105\101\119"or p=="\080\111\115\105\116\105\111\110"or p=="\081\117\097\116\101\114\105\111\110"then rawset(k,p,q)else error(("\'\037\115\' \105\115 \110\111\116 \097 \118\097\108\105\100 \105\110\100\101\120 \111\102 \067\097\109\101\114\097\083\116\097\116\101"):format(tostring(p)))end end function q.new(p)local N=setmetatable({},q)if p then N.FieldOfView=p.FieldOfView N.CFrame=p.CFrame end return N end function q.__add(N,p)local k=q.new(N)k.FieldOfView=N.FieldOfView+p.FieldOfView k.Position=k.Position+p.Position k.Quaterion=N.Quaterion*p.Quaterion return k end function q.__sub(N,p)local k=q.new(N)k.FieldOfView=N.FieldOfView-p.FieldOfView k.Position=k.Position-p.Position k.Quaterion=N.Quaterion/p.Quaterion return k end function q.__unm(p)local N=q.new(p)N.FieldOfView=-p.FieldOfView N.Position=-p.Position N.Quaterion=-p.Quaterion return N end function q.__mul(N,p)local k=q.new(N)if type(p)=="\110\117\109\098\101\114"then k.FieldOfView=N.FieldOfView*p k.Quaterion=N.Quaterion^p k.Position=N.Position*p else error("\073\110\118\097\108\105\100 \111\116\104\101\114")end return k end function q.Set(N,p)p.FieldOfView=N.FieldOfView p.CFrame=N.CFrame end return q
--- Data container for the state of a camera.
-- @classmod CameraState

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

local QuaternionObject = require("QuaternionObject")

local CameraState = {}
CameraState.ClassName = "CameraState"
CameraState.FieldOfView = 0
CameraState.Quaterion = QuaternionObject.new()
CameraState.Position = Vector3.new()

function CameraState:__index(index)
	if index == "CFrame" then
		return QuaternionObject.toCFrame(self.Quaterion, self.Position)
	else
		return CameraState[index]
	end
end

function CameraState:__newindex(index, Value)
	if index == "CFrame" then
		rawset(self, "Position", Value.p)
		rawset(self, "Quaterion", QuaternionObject.fromCFrame(Value))
	elseif index == "FieldOfView" or index == "Position" or index == "Quaterion" then
		rawset(self, index, Value)
	else
		error(("'%s' is not a valid index of CameraState"):format(tostring(index)))
	end
end

--- Builds a new camera stack
-- @constructor
-- @param[opt=nil] camera
-- @treturn CameraState
function CameraState.new(camera)
	local self = setmetatable({}, CameraState)

	if camera then
		self.FieldOfView = camera.FieldOfView
		self.CFrame = camera.CFrame
	end

	return self
end

--- Current FieldOfView
-- @tfield number FieldOfView

--- Current CFrame
-- @tfield CFrame CFrame

--- Current Position
-- @tfield Vector3 Position

--- Quaternion representation of the rotation of the CameraState
-- @tfield Quaterion Quaternion


--- Adds two camera states together
-- @tparam CameraState other
function CameraState:__add(other)
	local cameraState = CameraState.new(self)
	cameraState.FieldOfView = self.FieldOfView + other.FieldOfView
	cameraState.Position = cameraState.Position + other.Position
	cameraState.Quaterion = self.Quaterion*other.Quaterion

	return cameraState
end

--- Subtract the camera state from another
-- @tparam CameraState other
function CameraState:__sub(other)
	local cameraState = CameraState.new(self)
	cameraState.FieldOfView = self.FieldOfView - other.FieldOfView
	cameraState.Position = cameraState.Position - other.Position
	cameraState.Quaterion = self.Quaterion/other.Quaterion
	return cameraState
end

--- Inverts camera state
function CameraState:__unm()
	local cameraState = CameraState.new(self)
	cameraState.FieldOfView = -self.FieldOfView
	cameraState.Position = -self.Position
	cameraState.Quaterion = -self.Quaterion
	return cameraState
end

--- Multiply camera state by percent effect
-- @tparam number other
function CameraState:__mul(other)
	local cameraState = CameraState.new(self)

	if type(other) == "number" then
		cameraState.FieldOfView = self.FieldOfView * other
		cameraState.Quaterion = self.Quaterion^other
		cameraState.Position = self.Position * other
	else
		error("Invalid other")
	end

	return cameraState
end

--- Set another camera state. Typically used to set Workspace.CurrentCamera's state to match this camera's state
-- @tparam Camera camera A CameraState to set, also accepts a Roblox Camera
-- @treturn nil
function CameraState:Set(camera)
	camera.FieldOfView = self.FieldOfView
	camera.CFrame = self.CFrame
end

return CameraState