local G=.35 local t=.8 local function q(q)q=CameraUtils.Clamp(-1,1,q)if q>=0 then return(G*q)/((G-q)+1)end return-((t*-q)/((t+q)+1))end local U=.1 local function O(G)return(1+U)*(2*math.abs(G)-1)-U end local function j(G)return G/2+.5 end function CameraUtils.GamepadLinearToCurve(G)local function t(G)local t=1 if G<0 then t=-1 end local U=j(q(O(math.abs(G))))U=U*t return CameraUtils.Clamp(-1,1,U)end return Vector2.new(t(G.x),t(G.y))end
-- K is a tunable parameter that changes the shape of the S-curve
-- the larger K is the more straight/linear the curve gets
local k = 0.35
local lowerK = 0.8
local function SCurveTranform(t)
	t = CameraUtils.Clamp(-1, 1, t)
	if t >= 0 then
		return (k * t) / (k - t + 1)
	end
	return -((lowerK * -t) / (lowerK + t + 1))
end

local DEADZONE = 0.1
local function toSCurveSpace(t)
	return (1 + DEADZONE) * (2 * math.abs(t) - 1) - DEADZONE
end

local function fromSCurveSpace(t)
	return t / 2 + 0.5
end

function CameraUtils.GamepadLinearToCurve(thumbstickPosition)
	local function onAxis(axisValue)
		local sign = 1
		if axisValue < 0 then
			sign = -1
		end
		local point = fromSCurveSpace(SCurveTranform(toSCurveSpace(math.abs(axisValue))))
		point = point * sign
		return CameraUtils.Clamp(-1, 1, point)
	end
	return Vector2.new(onAxis(thumbstickPosition.x), onAxis(thumbstickPosition.y))
end
