local N={}do local R do local N=2.0 local s=.15 local function v(R)return(exp(N*R)-1)/(exp(N)-1)end local function g(N)return v((N-s)/(1-s))end function R(N)return sign(N)*clamp(g(abs(N)),0,1)end end local s={ButtonX=0,ButtonY=0,DPadDown=0,DPadUp=0;ButtonL2=0;ButtonR2=0;Thumbstick1=Vector2.new(),Thumbstick2=Vector2.new()}local v={W=0;A=0,S=0,D=0,E=0;Q=0,U=0;H=0;J=0;K=0,I=0;Y=0,Up=0,Down=0,LeftShift=0;RightShift=0}local g={Delta=Vector2.new();MouseWheel=0}local b=Vector3.new(1,1,1)local K=Vector3.new(1,1,1)local c=Vector2.new(1,1)*(pi/64)local P=Vector2.new(1,1)*(pi/8)local x=1.0 local p=.25 local z=.75 local r=.25 local t=1 function N.Vel(N)t=clamp(t+(N*(v.Up-v.Down))*z,.01,4)local g=Vector3.new(R(s.Thumbstick1.x),R(s.ButtonR2)-R(s.ButtonL2),R(-s.Thumbstick1.y))*b local c=Vector3.new(((v.D-v.A)+v.K)-v.H,((v.E-v.Q)+v.I)-v.Y,((v.S-v.W)+v.J)-v.U)*K local P=UserInputService:IsKeyDown(Enum.KeyCode.LeftShift)or UserInputService:IsKeyDown(Enum.KeyCode.RightShift)return(g+c)*(t*(P and r or 1))end function N.Pan(N)local v=Vector2.new(R(s.Thumbstick2.y),R(-s.Thumbstick2.x))*P local b=g.Delta*c g.Delta=Vector2.new()return v+b end function N.Fov(N)local R=(s.ButtonX-s.ButtonY)*p local v=g.MouseWheel*x g.MouseWheel=0 return R+v end do local function R(N,R,s)v[s.KeyCode.Name]=R==Enum.UserInputState.Begin and 1 or 0 return Enum.ContextActionResult.Sink end local function b(N,R,v)s[v.KeyCode.Name]=R==Enum.UserInputState.Begin and 1 or 0 return Enum.ContextActionResult.Sink end local function K(N,R,s)local v=s.Delta g.Delta=Vector2.new(-v.y,-v.x)return Enum.ContextActionResult.Sink end local function c(N,R,v)s[v.KeyCode.Name]=v.Position return Enum.ContextActionResult.Sink end local function P(N,R,v)s[v.KeyCode.Name]=v.Position.z return Enum.ContextActionResult.Sink end local function x(N,R,s)g[s.UserInputType.Name]=-s.Position.z return Enum.ContextActionResult.Sink end local function p(N)for R,s in pairs(N)do N[R]=s*0 end end function N.StartCapture()ContextActionService:BindActionAtPriority("\070\114\101\101\099\097\109\075\101\121\098\111\097\114\100\050",R,false,INPUT_PRIORITY,Enum.KeyCode.W,Enum.KeyCode.U,Enum.KeyCode.A,Enum.KeyCode.H,Enum.KeyCode.S,Enum.KeyCode.J,Enum.KeyCode.D,Enum.KeyCode.K,Enum.KeyCode.E,Enum.KeyCode.I,Enum.KeyCode.Q,Enum.KeyCode.Y,Enum.KeyCode.Up,Enum.KeyCode.Down)ContextActionService:BindActionAtPriority("\070\114\101\101\099\097\109\077\111\117\115\101\080\097\110\050",K,false,INPUT_PRIORITY,Enum.UserInputType.MouseMovement)ContextActionService:BindActionAtPriority("\070\114\101\101\099\097\109\077\111\117\115\101\087\104\101\101\108\050",x,false,INPUT_PRIORITY,Enum.UserInputType.MouseWheel)ContextActionService:BindActionAtPriority("\070\114\101\101\099\097\109\071\097\109\101\112\097\100\066\117\116\116\111\110\050",b,false,INPUT_PRIORITY,Enum.KeyCode.ButtonX,Enum.KeyCode.ButtonY)ContextActionService:BindActionAtPriority("\070\114\101\101\099\097\109\071\097\109\101\112\097\100\084\114\105\103\103\101\114\050",P,false,INPUT_PRIORITY,Enum.KeyCode.ButtonR2,Enum.KeyCode.ButtonL2)ContextActionService:BindActionAtPriority("\070\114\101\101\099\097\109\071\097\109\101\112\097\100\084\104\117\109\098\115\116\105\099\107\050",c,false,INPUT_PRIORITY,Enum.KeyCode.Thumbstick1,Enum.KeyCode.Thumbstick2)end function N.StopCapture()t=1 p(s)p(v)p(g)ContextActionService:UnbindAction("\070\114\101\101\099\097\109\075\101\121\098\111\097\114\100\050")ContextActionService:UnbindAction("\070\114\101\101\099\097\109\077\111\117\115\101\080\097\110\050")ContextActionService:UnbindAction("\070\114\101\101\099\097\109\077\111\117\115\101\087\104\101\101\108\050")ContextActionService:UnbindAction("\070\114\101\101\099\097\109\071\097\109\101\112\097\100\066\117\116\116\111\110\050")ContextActionService:UnbindAction("\070\114\101\101\099\097\109\071\097\109\101\112\097\100\084\114\105\103\103\101\114\050")ContextActionService:UnbindAction("\070\114\101\101\099\097\109\071\097\109\101\112\097\100\084\104\117\109\098\115\116\105\099\107\050")end end end local function R(N)local R=.1 local s=Camera.ViewportSize local v=2*tan(cameraFov/2)local g=(s.x/s.y)*v local b=N.rightVector local K=N.upVector local c=N.lookVector local P=Vector3.new()local x=512 for s=0,1,.5 do for p=0,1,.5 do local z=(s-.5)*g local r=(p-.5)*v local t=(b*z-K*r)+c local D=N.p+t*R local E,O=Workspace:FindPartOnRay(Ray.new(D,t.unit*x))local A=(O-D).magnitude if x>A then x=A P=t.unit end end end return c:Dot(P)*x end
------------------------------------------------------------------------

local Input = {}
do
	local thumbstickCurve
	do
		local K_CURVATURE = 2.0
		local K_DEADZONE = 0.15

		local function fCurve(x)
			return (exp(K_CURVATURE * x) - 1) / (exp(K_CURVATURE) - 1)
		end

		local function fDeadzone(x)
			return fCurve((x - K_DEADZONE) / (1 - K_DEADZONE))
		end

		function thumbstickCurve(x)
			return sign(x) * clamp(fDeadzone(abs(x)), 0, 1)
		end
	end

	local gamepad = {
		ButtonX = 0,
		ButtonY = 0,
		DPadDown = 0,
		DPadUp = 0,
		ButtonL2 = 0,
		ButtonR2 = 0,
		Thumbstick1 = Vector2.new(),
		Thumbstick2 = Vector2.new(),
	}

	local keyboard = {
		W = 0,
		A = 0,
		S = 0,
		D = 0,
		E = 0,
		Q = 0,
		U = 0,
		H = 0,
		J = 0,
		K = 0,
		I = 0,
		Y = 0,
		Up = 0,
		Down = 0,
		LeftShift = 0,
		RightShift = 0,
	}

	local mouse = {
		Delta = Vector2.new(),
		MouseWheel = 0,
	}

	local NAV_GAMEPAD_SPEED = Vector3.new(1, 1, 1)
	local NAV_KEYBOARD_SPEED = Vector3.new(1, 1, 1)
	local PAN_MOUSE_SPEED = Vector2.new(1, 1) * (pi / 64)
	local PAN_GAMEPAD_SPEED = Vector2.new(1, 1) * (pi / 8)
	local FOV_WHEEL_SPEED = 1.0
	local FOV_GAMEPAD_SPEED = 0.25
	local NAV_ADJ_SPEED = 0.75
	local NAV_SHIFT_MUL = 0.25

	local navSpeed = 1

	function Input.Vel(dt)
		navSpeed = clamp(navSpeed + dt * (keyboard.Up - keyboard.Down) * NAV_ADJ_SPEED, 0.01, 4)

		local kGamepad = Vector3.new(
			thumbstickCurve(gamepad.Thumbstick1.x),
			thumbstickCurve(gamepad.ButtonR2) - thumbstickCurve(gamepad.ButtonL2),
			thumbstickCurve(-gamepad.Thumbstick1.y)
		) * NAV_GAMEPAD_SPEED

		local kKeyboard = Vector3.new(
			keyboard.D - keyboard.A + keyboard.K - keyboard.H,
			keyboard.E - keyboard.Q + keyboard.I - keyboard.Y,
			keyboard.S - keyboard.W + keyboard.J - keyboard.U
		) * NAV_KEYBOARD_SPEED

		local shift = UserInputService:IsKeyDown(Enum.KeyCode.LeftShift)
			or UserInputService:IsKeyDown(Enum.KeyCode.RightShift)

		return (kGamepad + kKeyboard) * (navSpeed * (shift and NAV_SHIFT_MUL or 1))
	end

	function Input.Pan(dt)
		local kGamepad = Vector2.new(thumbstickCurve(gamepad.Thumbstick2.y), thumbstickCurve(-gamepad.Thumbstick2.x))
			* PAN_GAMEPAD_SPEED
		local kMouse = mouse.Delta * PAN_MOUSE_SPEED
		mouse.Delta = Vector2.new()
		return kGamepad + kMouse
	end

	function Input.Fov(dt)
		local kGamepad = (gamepad.ButtonX - gamepad.ButtonY) * FOV_GAMEPAD_SPEED
		local kMouse = mouse.MouseWheel * FOV_WHEEL_SPEED
		mouse.MouseWheel = 0
		return kGamepad + kMouse
	end

	do
		local function Keypress(action, state, input)
			keyboard[input.KeyCode.Name] = state == Enum.UserInputState.Begin and 1 or 0
			return Enum.ContextActionResult.Sink
		end

		local function GpButton(action, state, input)
			gamepad[input.KeyCode.Name] = state == Enum.UserInputState.Begin and 1 or 0
			return Enum.ContextActionResult.Sink
		end

		local function MousePan(action, state, input)
			local delta = input.Delta
			mouse.Delta = Vector2.new(-delta.y, -delta.x)
			return Enum.ContextActionResult.Sink
		end

		local function Thumb(action, state, input)
			gamepad[input.KeyCode.Name] = input.Position
			return Enum.ContextActionResult.Sink
		end

		local function Trigger(action, state, input)
			gamepad[input.KeyCode.Name] = input.Position.z
			return Enum.ContextActionResult.Sink
		end

		local function MouseWheel(action, state, input)
			mouse[input.UserInputType.Name] = -input.Position.z
			return Enum.ContextActionResult.Sink
		end

		local function Zero(t)
			for k, v in pairs(t) do
				t[k] = v * 0
			end
		end

		function Input.StartCapture()
			ContextActionService:BindActionAtPriority(
				"FreecamKeyboard2",
				Keypress,
				false,
				INPUT_PRIORITY,
				Enum.KeyCode.W,
				Enum.KeyCode.U,
				Enum.KeyCode.A,
				Enum.KeyCode.H,
				Enum.KeyCode.S,
				Enum.KeyCode.J,
				Enum.KeyCode.D,
				Enum.KeyCode.K,
				Enum.KeyCode.E,
				Enum.KeyCode.I,
				Enum.KeyCode.Q,
				Enum.KeyCode.Y,
				Enum.KeyCode.Up,
				Enum.KeyCode.Down
			)
			ContextActionService:BindActionAtPriority(
				"FreecamMousePan2",
				MousePan,
				false,
				INPUT_PRIORITY,
				Enum.UserInputType.MouseMovement
			)
			ContextActionService:BindActionAtPriority(
				"FreecamMouseWheel2",
				MouseWheel,
				false,
				INPUT_PRIORITY,
				Enum.UserInputType.MouseWheel
			)
			ContextActionService:BindActionAtPriority(
				"FreecamGamepadButton2",
				GpButton,
				false,
				INPUT_PRIORITY,
				Enum.KeyCode.ButtonX,
				Enum.KeyCode.ButtonY
			)
			ContextActionService:BindActionAtPriority(
				"FreecamGamepadTrigger2",
				Trigger,
				false,
				INPUT_PRIORITY,
				Enum.KeyCode.ButtonR2,
				Enum.KeyCode.ButtonL2
			)
			ContextActionService:BindActionAtPriority(
				"FreecamGamepadThumbstick2",
				Thumb,
				false,
				INPUT_PRIORITY,
				Enum.KeyCode.Thumbstick1,
				Enum.KeyCode.Thumbstick2
			)
		end

		function Input.StopCapture()
			navSpeed = 1
			Zero(gamepad)
			Zero(keyboard)
			Zero(mouse)
			ContextActionService:UnbindAction("FreecamKeyboard2")
			ContextActionService:UnbindAction("FreecamMousePan2")
			ContextActionService:UnbindAction("FreecamMouseWheel2")
			ContextActionService:UnbindAction("FreecamGamepadButton2")
			ContextActionService:UnbindAction("FreecamGamepadTrigger2")
			ContextActionService:UnbindAction("FreecamGamepadThumbstick2")
		end
	end
end

local function GetFocusDistance(cameraFrame)
	local znear = 0.1
	local viewport = Camera.ViewportSize
	local projy = 2 * tan(cameraFov / 2)
	local projx = viewport.x / viewport.y * projy
	local fx = cameraFrame.rightVector
	local fy = cameraFrame.upVector
	local fz = cameraFrame.lookVector

	local minVect = Vector3.new()
	local minDist = 512

	for x = 0, 1, 0.5 do
		for y = 0, 1, 0.5 do
			local cx = (x - 0.5) * projx
			local cy = (y - 0.5) * projy
			local offset = fx * cx - fy * cy + fz
			local origin = cameraFrame.p + offset * znear
			local _, hit = Workspace:FindPartOnRay(Ray.new(origin, offset.unit * minDist))
			local dist = (hit - origin).magnitude
			if minDist > dist then
				minDist = dist
				minVect = offset.unit
			end
		end
	end

	return fz:Dot(minVect) * minDist
end
