function SpringObject.TimeSkip(C,e)assert(type(e)=="\110\117\109\098\101\114","\066\097\100 \100\101\108\116\097")C._currentSpring:TimeSkip(e)C.Changed:Fire()end function SpringObject.__index(C,e)if e=="\086\097\108\117\101"or e=="\080\111\115\105\116\105\111\110"or e=="\112"then return SpringUtils.fromLinearIfNeeded(C._currentSpring.Value)elseif e=="\086\101\108\111\099\105\116\121"or e=="\118"then return SpringUtils.fromLinearIfNeeded(C._currentSpring.Velocity)elseif e=="\084\097\114\103\101\116"or e=="\116"then return SpringUtils.fromLinearIfNeeded(C._currentSpring.Target)elseif e=="\068\097\109\112\101\114"or e=="\100"then return C._currentSpring.Damper elseif e=="\083\112\101\101\100"or e=="\115"then return C._currentSpring.Speed elseif e=="\067\108\111\099\107"then return C._currentSpring.Clock elseif SpringObject[e]then return SpringObject[e]else error(("\037\113 \105\115 \110\111\116 \097 \109\101\109\098\101\114 \111\102 \083\112\114\105\110\103\079\098\106\101\099\116"):format(tostring(e)))end end function SpringObject.__newindex(D,e,C)if e=="\086\097\108\117\101"or e=="\080\111\115\105\116\105\111\110"or e=="\112"then local e=Blend.toPropertyObservable(C)or Rx.of(C)D._maid._valueSub=e:Subscribe(function(e)local C=SpringUtils.toLinearIfNeeded(e);(D:_getSpringForType(C)).Value=C D.Changed:Fire()end)elseif e=="\086\101\108\111\099\105\116\121"or e=="\118"then local e=Blend.toPropertyObservable(C)or Rx.of(C)D._maid._velocitySub=e:Subscribe(function(e)local C=SpringUtils.toLinearIfNeeded(e);(D:_getSpringForType(0*C)).Velocity=C D.Changed:Fire()end)elseif e=="\084\097\114\103\101\116"or e=="\116"then local e=Blend.toPropertyObservable(C)or Rx.of(C)D._maid._targetSub=e:Subscribe(function(e)local C=SpringUtils.toLinearIfNeeded(e);(D:_getSpringForType(C)).Target=C D.Changed:Fire()end)elseif e=="\068\097\109\112\101\114"or e=="\100"then local e=assert(Blend.toNumberObservable(C),"\073\110\118\097\108\105\100 \100\097\109\112\101\114")D._maid._damperSub=e:Subscribe(function(e)assert(type(e)=="\110\117\109\098\101\114","\066\097\100 \100\097\109\112\101\114")D._currentSpring.Damper=e D.Changed:Fire()end)elseif e=="\083\112\101\101\100"or e=="\115"then local e=assert(Blend.toNumberObservable(C),"\073\110\118\097\108\105\100 \115\112\101\101\100")D._maid._speedSub=e:Subscribe(function(e)assert(type(e)=="\110\117\109\098\101\114","\066\097\100 \100\097\109\112\101\114")D._currentSpring.Speed=e D.Changed:Fire()end)elseif e=="\067\108\111\099\107"then assert(type(C)=="\102\117\110\099\116\105\111\110","\066\097\100 \099\108\111\099\107 \118\097\108\117\101")D._currentSpring.Clock=C D.Changed:Fire()else error(("\037\113 \105\115 \110\111\116 \097 \109\101\109\098\101\114 \111\102 \083\112\114\105\110\103\079\098\106\101\099\116"):format(tostring(e)))end end function SpringObject._getSpringForType(C,e)if rawget(C,"\095\099\117\114\114\101\110\116\083\112\114\105\110\103")==nil then rawset(C,"\095\099\117\114\114\101\110\116\083\112\114\105\110\103",Spring.new(e))return C._currentSpring else local D=typeof(SpringUtils.fromLinearIfNeeded(C._currentSpring.Value))if D==typeof(e)then return C._currentSpring else local D=C._currentSpring.d local m=C._currentSpring.s C._currentSpring=Spring.new(e)C._currentSpring.Speed=m C._currentSpring.Damper=D return C._currentSpring end end end
--[=[
	Instantly skips the spring forwards by that amount time
	@param delta number -- Time to skip forwards
	@return ()
]=]
function SpringObject:TimeSkip(delta)
	assert(type(delta) == "number", "Bad delta")

	self._currentSpring:TimeSkip(delta)
	self.Changed:Fire()
end

function SpringObject:__index(index)
	if index == "Value" or index == "Position" or index == "p" then
		return SpringUtils.fromLinearIfNeeded(self._currentSpring.Value)
	elseif index == "Velocity" or index == "v" then
		return SpringUtils.fromLinearIfNeeded(self._currentSpring.Velocity)
	elseif index == "Target" or index == "t" then
		return SpringUtils.fromLinearIfNeeded(self._currentSpring.Target)
	elseif index == "Damper" or index == "d" then
		return self._currentSpring.Damper
	elseif index == "Speed" or index == "s" then
		return self._currentSpring.Speed
	elseif index == "Clock" then
		return self._currentSpring.Clock
	elseif SpringObject[index] then
		return SpringObject[index]
	else
		error(("%q is not a member of SpringObject"):format(tostring(index)))
	end
end

function SpringObject:__newindex(index, value)
	if index == "Value" or index == "Position" or index == "p" then
		local observable = Blend.toPropertyObservable(value) or Rx.of(value)

		self._maid._valueSub = observable:Subscribe(function(unconverted)
			local converted = SpringUtils.toLinearIfNeeded(unconverted)
			self:_getSpringForType(converted).Value = converted
			self.Changed:Fire()
		end)
	elseif index == "Velocity" or index == "v" then
		local observable = Blend.toPropertyObservable(value) or Rx.of(value)

		self._maid._velocitySub = observable:Subscribe(function(unconverted)
			local converted = SpringUtils.toLinearIfNeeded(unconverted)

			self:_getSpringForType(0 * converted).Velocity = converted
			self.Changed:Fire()
		end)
	elseif index == "Target" or index == "t" then
		local observable = Blend.toPropertyObservable(value) or Rx.of(value)

		self._maid._targetSub = observable:Subscribe(function(unconverted)
			local converted = SpringUtils.toLinearIfNeeded(unconverted)
			self:_getSpringForType(converted).Target = converted

			self.Changed:Fire()
		end)
	elseif index == "Damper" or index == "d" then
		local observable = assert(Blend.toNumberObservable(value), "Invalid damper")

		self._maid._damperSub = observable:Subscribe(function(unconverted)
			assert(type(unconverted) == "number", "Bad damper")

			self._currentSpring.Damper = unconverted
			self.Changed:Fire()
		end)
	elseif index == "Speed" or index == "s" then
		local observable = assert(Blend.toNumberObservable(value), "Invalid speed")

		self._maid._speedSub = observable:Subscribe(function(unconverted)
			assert(type(unconverted) == "number", "Bad damper")

			self._currentSpring.Speed = unconverted
			self.Changed:Fire()
		end)
	elseif index == "Clock" then
		assert(type(value) == "function", "Bad clock value")
		self._currentSpring.Clock = value
		self.Changed:Fire()
	else
		error(("%q is not a member of SpringObject"):format(tostring(index)))
	end
end

function SpringObject:_getSpringForType(converted)
	if rawget(self, "_currentSpring") == nil then
		-- only happens on init
		rawset(self, "_currentSpring", Spring.new(converted))
		return self._currentSpring
	else
		local currentType = typeof(SpringUtils.fromLinearIfNeeded(self._currentSpring.Value))
		if currentType == typeof(converted) then
			return self._currentSpring
		else
			local oldDamper = self._currentSpring.d
			local oldSpeed = self._currentSpring.s

			self._currentSpring = Spring.new(converted)
			self._currentSpring.Speed = oldSpeed
			self._currentSpring.Damper = oldDamper
			return self._currentSpring
		end
	end
end
