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\099\107")local F=N("\070\097\100\101\066\101\116\119\101\101\110\067\097\109\101\114\097")local h=N("\077\097\105\100")local d={}d.ClassName="\067\097\109\101\114\097\083\116\097\116\101\084\119\101\101\110\101\114"d.__index=d function d.new(N,K)local a=setmetatable({},d)a._maid=h.new()local I,b=C:GetNewStateBelow()a._cameraBelow=I a._fadeBetween=F.new(I,N)b(a._fadeBetween)C:Add(a._fadeBetween)a._fadeBetween.Speed=K or 20 a._fadeBetween.Target=0 a._fadeBetween.Value=0 a._maid:GiveTask(function()C:Remove(a._fadeBetween)end)return a end function d.Show(C,N)C:SetTarget(1,N)end function d.Hide(C,N)C:SetTarget(0,N)end function d.Finish(F,N,C)F:Hide(N)if F._fadeBetween.HasReachedTarget then C()else spawn(function()while not F._fadeBetween.HasReachedTarget do wait(.05)end C()end)end end function d.GetCameraBelow(N)return N._cameraBelow end function d.SetTarget(F,N,C)F._fadeBetween.Target=N or error("\078\111 \116\097\114\103\101\116")if C then F._fadeBetween.Value=F._fadeBetween.Target F._fadeBetween.Velocity=0 end return F end function d.SetSpeed(C,N)C._fadeBetween.Speed=N return C end function d.SetVisible(F,N,C)if N then F:Show(C)else F:Hide(C)end end function d.GetFader(N)return N._fadeBetween end function d.Destroy(N)N._maid:DoCleaning()setmetatable(N,nil)end return d
--- Makes transitions between states easier. Uses the `CameraStack` to tween in and
-- out a new camera state Call `:Show()` and `:Hide()` to do so, and make sure to
-- call `:Destroy()` after usage
-- @classmod CameraStateTweener

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

local CameraStack = require("CameraStack")
local FadeBetweenCamera = require("FadeBetweenCamera")
local Maid = require("Maid")

local CameraStateTweener = {}
CameraStateTweener.ClassName = "CameraStateTweener"
CameraStateTweener.__index = CameraStateTweener

--- Constructs a new camera state tweener
-- @tparam ICameraEffect cameraEffect A camera effect
-- @tparam[opt=20] number speed that the camera tweener tweens at
function CameraStateTweener.new(cameraEffect, speed)
	local self = setmetatable({}, CameraStateTweener)

	self._maid = Maid.new()
	local cameraBelow, assign = CameraStack:GetNewStateBelow()
	self._cameraBelow = cameraBelow
	self._fadeBetween = FadeBetweenCamera.new(cameraBelow, cameraEffect)
	assign(self._fadeBetween)

	CameraStack:Add(self._fadeBetween)

	self._fadeBetween.Speed = speed or 20
	self._fadeBetween.Target = 0
	self._fadeBetween.Value = 0

	self._maid:GiveTask(function()
		CameraStack:Remove(self._fadeBetween)
	end)

	return self
end

function CameraStateTweener:Show(doNotAnimate)
	self:SetTarget(1, doNotAnimate)
end


function CameraStateTweener:Hide(doNotAnimate)
	self:SetTarget(0, doNotAnimate)
end

function CameraStateTweener:Finish(doNotAnimate, callback)
	self:Hide(doNotAnimate)

	if self._fadeBetween.HasReachedTarget then
		callback()
	else
		spawn(function()
			while not self._fadeBetween.HasReachedTarget do
				wait(0.05)
			end
			callback()
		end)
	end
end

function CameraStateTweener:GetCameraBelow()
	return self._cameraBelow
end

function CameraStateTweener:SetTarget(target, doNotAnimate)
	self._fadeBetween.Target = target or error("No target")
	if doNotAnimate then
		self._fadeBetween.Value = self._fadeBetween.Target
		self._fadeBetween.Velocity = 0
	end
	return self
end

function CameraStateTweener:SetSpeed(speed)
	self._fadeBetween.Speed = speed

	return self
end

function CameraStateTweener:SetVisible(isVisible, doNotAnimate)
	if isVisible then
		self:Show(doNotAnimate)
	else
		self:Hide(doNotAnimate)
	end
end

function CameraStateTweener:GetFader()
	return self._fadeBetween
end

function CameraStateTweener:Destroy()
	self._maid:DoCleaning()
	setmetatable(self, nil)
end

return CameraStateTweener