local b={}b.__index=b b.Easing=require(script:WaitForChild("\069\097\115\105\110\103"))function b.new(W,H)do assert(typeof(H)=="\102\117\110\099\116\105\111\110","\067\097\108\108\098\097\099\107 \097\114\103\117\109\101\110\116 \109\117\115\116 \098\101 \097 \102\117\110\099\116\105\111\110")local b=typeof(W)assert(b=="\084\119\101\101\110\073\110\102\111"or b=="\116\097\098\108\101","\084\119\101\101\110\073\110\102\111 \109\117\115\116 \098\101 \111\102 \116\121\112\101 \084\119\101\101\110\073\110\102\111 \111\114 \116\097\098\108\101")if b=="\116\097\098\108\101"then if W.Time==nil then W.Time=1 end if W.EasingStyle==nil then W.EasingStyle=Enum.EasingStyle.Quad end if W.EasingDirection==nil then W.EasingDirection=Enum.EasingDirection.Out end if W.RepeatCount==nil then W.RepeatCount=0 end if W.Reverses==nil then W.Reverses=false end if W.DelayTime==nil then W.DelayTime=0 end end end local O=Instance.new("\066\105\110\100\097\098\108\101\069\118\101\110\116")local z=Instance.new("\066\105\110\100\097\098\108\101\069\118\101\110\116")local M=setmetatable({TweenInfo=W;Callback=H;PlaybackState=Enum.PlaybackState.Begin;Completed=O.Event;PlaybackStateChanged=z.Event,_id="\116\119\101\101\110\095"..(game:GetService("\072\116\116\112\083\101\114\118\105\099\101")):GenerateGUID(false);_playing=false;_paused=false,_completed=O;_playbackStateChanged=z,_elapsedTime=0;_repeated=0;_reversing=false;_elapsedDelayTime=0},b)return M end function b.ResetState(b)b._playing=false b._paused=false b._elapsedTime=0 b._repeated=0 b._reversing=false b._elapsedDelayTime=0 end function b.SetPlaybackState(W,b)local H=W.PlaybackState W.PlaybackState=b if b~=H then W._playbackStateChanged:Fire(b)end end function b.Play(W)if W._playing and not W._paused then return end W._playing=true W._paused=false local H if typeof(W.TweenInfo)=="\084\119\101\101\110\073\110\102\111"then H=b.Easing[W.TweenInfo.EasingDirection.Name][W.TweenInfo.EasingStyle.Name]else local O,z O=typeof(W.TweenInfo.EasingDirection)=="\069\110\117\109\073\116\101\109"and W.TweenInfo.EasingDirection.Name or W.TweenInfo.EasingDirection z=typeof(W.TweenInfo.EasingStyle)=="\069\110\117\109\073\116\101\109"and W.TweenInfo.EasingStyle.Name or W.TweenInfo.EasingStyle H=b.Easing[O][z]if not W.TweenInfo.RepeatCount then W.TweenInfo.RepeatCount=0 end end local O=tick local z=W._elapsedTime local M=W.TweenInfo.Time local S=O()local C=W.Callback local k=W.TweenInfo.Reverses local U=W._elapsedDelayTime local n=W.TweenInfo.DelayTime local K=W._reversing local function r()C(H(M,0,1,M));(game:GetService("\082\117\110\083\101\114\118\105\099\101")):UnbindFromRenderStep(W._id)W.PlaybackState=Enum.PlaybackState.Completed W._completed:Fire(W.PlaybackState)W:ResetState()end local function P(b)if U>=n then return false end U=U+b W._elapsedDelayTime=U if U<n then W:SetPlaybackState(Enum.PlaybackState.Delayed)else W:SetPlaybackState(Enum.PlaybackState.Playing)end return U<n end;(game:GetService("\082\117\110\083\101\114\118\105\099\101")):BindToRenderStep(W._id,Enum.RenderPriority.Camera.Value-1,function()local b=O()local n=b-S S=b if P(n)then return end z=z+n W._elapsedTime=z local e=z<M if e then if K then C(H(z,1,-1,M))else C(H(z,0,1,M))end else if W._repeated<W.TweenInfo.RepeatCount or K then if k then K=not K W._reversing=K end if not k or K then W._repeated=W._repeated+1 end if not K then W._elapsedDelayTime=0 U=0 end W._elapsedTime=0 z=0 else r()end end end)end function b.Pause(b)if not b._playing or b._paused then return end b._paused=true b:SetPlaybackState(Enum.PlaybackState.Paused);(game:GetService("\082\117\110\083\101\114\118\105\099\101")):UnbindFromRenderStep(b._id)end function b.Cancel(b)if not b._playing then return end;(game:GetService("\082\117\110\083\101\114\118\105\099\101")):UnbindFromRenderStep(b._id)b:ResetState()b:SetPlaybackState(Enum.PlaybackState.Cancelled)b._completed:Fire(b.PlaybackState)end function b.fromService(...)return(game:GetService("\084\119\101\101\110\083\101\114\118\105\099\101")):Create(...)end b.FromService=b.fromService b.New=b.new return b




local Tween = {}
Tween.__index = Tween


Tween.Easing = require(script:WaitForChild("Easing"))


function Tween.new(tweenInfo, callback)
	
	do
		-- Verify callback is function:
		assert(typeof(callback) == "function", "Callback argument must be a function")
		
		-- Verify tweenInfo:
		local typeOfTweenInfo = typeof(tweenInfo)
		assert(typeOfTweenInfo == "TweenInfo" or typeOfTweenInfo == "table", "TweenInfo must be of type TweenInfo or table")
		
		-- Defaults:
		if (typeOfTweenInfo == "table") then
			if (tweenInfo.Time == nil) then tweenInfo.Time = 1 end
			if (tweenInfo.EasingStyle == nil) then tweenInfo.EasingStyle = Enum.EasingStyle.Quad end
			if (tweenInfo.EasingDirection == nil) then tweenInfo.EasingDirection = Enum.EasingDirection.Out end
			if (tweenInfo.RepeatCount == nil) then tweenInfo.RepeatCount = 0 end
			if (tweenInfo.Reverses == nil) then tweenInfo.Reverses = false end
			if (tweenInfo.DelayTime == nil) then tweenInfo.DelayTime = 0 end
		end
		
	end
	
	local completed = Instance.new("BindableEvent")
	local playbackStateChanged = Instance.new("BindableEvent")
	
	local self = setmetatable({
		
		TweenInfo = tweenInfo;
		Callback = callback;
		PlaybackState = Enum.PlaybackState.Begin;
		Completed = completed.Event;
		PlaybackStateChanged = playbackStateChanged.Event;
		
		_id = "tween_" .. game:GetService("HttpService"):GenerateGUID(false);
		_playing = false;
		_paused = false;
		_completed = completed;
		_playbackStateChanged = playbackStateChanged;
		_elapsedTime = 0;
		_repeated = 0;
		_reversing = false;
		_elapsedDelayTime = 0;
		
	}, Tween)
	
	return self
	
end


function Tween:ResetState()
	self._playing = false
	self._paused = false
	self._elapsedTime = 0
	self._repeated = 0
	self._reversing = false
	self._elapsedDelayTime = 0
end


function Tween:SetPlaybackState(state)
	local lastState = self.PlaybackState
	self.PlaybackState = state
	if (state ~= lastState) then
		self._playbackStateChanged:Fire(state)
	end
end


function Tween:Play()
	
	if (self._playing and not self._paused) then return end
	self._playing = true
	self._paused = false
	
	-- Resolve easing function:
	local easingFunc
	if (typeof(self.TweenInfo) == "TweenInfo") then
		easingFunc = Tween.Easing[self.TweenInfo.EasingDirection.Name][self.TweenInfo.EasingStyle.Name]
	else
		local dir, style
		dir = typeof(self.TweenInfo.EasingDirection) == "EnumItem" and self.TweenInfo.EasingDirection.Name or self.TweenInfo.EasingDirection
		style = typeof(self.TweenInfo.EasingStyle) == "EnumItem" and self.TweenInfo.EasingStyle.Name or self.TweenInfo.EasingStyle
		easingFunc = Tween.Easing[dir][style]
		if (not self.TweenInfo.RepeatCount) then
			self.TweenInfo.RepeatCount = 0
		end
	end
	
	local tick = tick
	
	local elapsed = self._elapsedTime
	local duration = self.TweenInfo.Time
	local last = tick()
	local callback = self.Callback
	local reverses = self.TweenInfo.Reverses
	
	local elapsedDelay = self._elapsedDelayTime
	local durationDelay = self.TweenInfo.DelayTime
	
	local reversing = self._reversing
	
	local function OnCompleted()
		callback(easingFunc(duration, 0, 1, duration))
		game:GetService("RunService"):UnbindFromRenderStep(self._id)
		self.PlaybackState = Enum.PlaybackState.Completed
		self._completed:Fire(self.PlaybackState)
		self:ResetState()
	end
	
	local function IsDelayed(dt)
		if (elapsedDelay >= durationDelay) then return false end
		elapsedDelay = (elapsedDelay + dt)
		self._elapsedDelayTime = elapsedDelay
		if (elapsedDelay < durationDelay) then
			self:SetPlaybackState(Enum.PlaybackState.Delayed)
		else
			self:SetPlaybackState(Enum.PlaybackState.Playing)
		end
		return (elapsedDelay < durationDelay)
	end
	
	-- Tween:
	game:GetService("RunService"):BindToRenderStep(self._id, Enum.RenderPriority.Camera.Value - 1, function()
		local now = tick()
		local dt = (now - last)
		last = now
		if (IsDelayed(dt)) then return end
		elapsed = (elapsed + dt)
		self._elapsedTime = elapsed
		local notDone = (elapsed < duration)
		if (notDone) then
			if (reversing) then
				callback(easingFunc(elapsed, 1, -1, duration))
			else
				callback(easingFunc(elapsed, 0, 1, duration))
			end
		else
			if ((self._repeated < self.TweenInfo.RepeatCount) or reversing) then
				if (reverses) then
					reversing = (not reversing)
					self._reversing = reversing
				end
				if ((not reverses) or (reversing)) then
					self._repeated = (self._repeated + 1)
				end
				if (not reversing) then
					self._elapsedDelayTime = 0
					elapsedDelay = 0
				end
				self._elapsedTime = 0
				elapsed = 0
			else
				OnCompleted()
			end
		end
	end)
	
end


function Tween:Pause()
	if ((not self._playing) or (self._paused)) then return end
	self._paused = true
	self:SetPlaybackState(Enum.PlaybackState.Paused)
	game:GetService("RunService"):UnbindFromRenderStep(self._id)
end


function Tween:Cancel()
	if (not self._playing) then return end
	game:GetService("RunService"):UnbindFromRenderStep(self._id)
	self:ResetState()
	self:SetPlaybackState(Enum.PlaybackState.Cancelled)
	self._completed:Fire(self.PlaybackState)
end


function Tween.fromService(...)
	return game:GetService("TweenService"):Create(...)
end


Tween.FromService = Tween.fromService
Tween.New = Tween.new


return Tween
