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

		function Input.StopCapture()
			navSpeed = 1
			Zero(gamepad)
			Zero(keyboard)
			Zero(mouse)
			ContextActionService:UnbindAction("FreecamKeyboard")
			ContextActionService:UnbindAction("FreecamMousePan")
			ContextActionService:UnbindAction("FreecamMouseWheel")
			ContextActionService:UnbindAction("FreecamGamepadButton")
			ContextActionService:UnbindAction("FreecamGamepadTrigger")
			ContextActionService:UnbindAction("FreecamGamepadThumbstick")
		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
