Advertisement
Guest User

Untitled

a guest
Sep 15th, 2019
112
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 12.96 KB | None | 0 0
  1. ------------------------------------------------------------------------
  2. -- Freecam
  3. -- Cinematic free camera for spectating and video production.
  4. ------------------------------------------------------------------------
  5.  
  6. local pi = math.pi
  7. local abs = math.abs
  8. local clamp = math.clamp
  9. local exp = math.exp
  10. local rad = math.rad
  11. local sign = math.sign
  12. local sqrt = math.sqrt
  13. local tan = math.tan
  14.  
  15. local ContextActionService = game:GetService("ContextActionService")
  16. local Players = game:GetService("Players")
  17. local RunService = game:GetService("RunService")
  18. local StarterGui = game:GetService("StarterGui")
  19. local UserInputService = game:GetService("UserInputService")
  20. local Workspace = game:GetService("Workspace")
  21.  
  22. local LocalPlayer = Players.LocalPlayer
  23. if not LocalPlayer then
  24. Players:GetPropertyChangedSignal("LocalPlayer"):Wait()
  25. LocalPlayer = Players.LocalPlayer
  26. end
  27.  
  28. local Camera = Workspace.CurrentCamera
  29. Workspace:GetPropertyChangedSignal("CurrentCamera"):Connect(function()
  30. local newCamera = Workspace.CurrentCamera
  31. if newCamera then
  32. Camera = newCamera
  33. end
  34. end)
  35.  
  36. ------------------------------------------------------------------------
  37.  
  38. local TOGGLE_INPUT_PRIORITY = Enum.ContextActionPriority.Low.Value
  39. local INPUT_PRIORITY = Enum.ContextActionPriority.High.Value
  40. local FREECAM_MACRO_KB = {Enum.KeyCode.LeftShift, Enum.KeyCode.P}
  41.  
  42. local NAV_GAIN = Vector3.new(1, 1, 1)*64
  43. local PAN_GAIN = Vector2.new(0.75, 1)*8
  44. local FOV_GAIN = 300
  45.  
  46. local PITCH_LIMIT = rad(90)
  47.  
  48. local VEL_STIFFNESS = 1.5
  49. local PAN_STIFFNESS = 1.0
  50. local FOV_STIFFNESS = 4.0
  51.  
  52. ------------------------------------------------------------------------
  53.  
  54. local Spring = {} do
  55. Spring.__index = Spring
  56.  
  57. function Spring.new(freq, pos)
  58. local self = setmetatable({}, Spring)
  59. self.f = freq
  60. self.p = pos
  61. self.v = pos*0
  62. return self
  63. end
  64.  
  65. function Spring:Update(dt, goal)
  66. local f = self.f*2*pi
  67. local p0 = self.p
  68. local v0 = self.v
  69.  
  70. local offset = goal - p0
  71. local decay = exp(-f*dt)
  72.  
  73. local p1 = goal + (v0*dt - offset*(f*dt + 1))*decay
  74. local v1 = (f*dt*(offset*f - v0) + v0)*decay
  75.  
  76. self.p = p1
  77. self.v = v1
  78.  
  79. return p1
  80. end
  81.  
  82. function Spring:Reset(pos)
  83. self.p = pos
  84. self.v = pos*0
  85. end
  86. end
  87.  
  88. ------------------------------------------------------------------------
  89.  
  90. local cameraPos = Vector3.new()
  91. local cameraRot = Vector2.new()
  92. local cameraFov = 0
  93.  
  94. local velSpring = Spring.new(VEL_STIFFNESS, Vector3.new())
  95. local panSpring = Spring.new(PAN_STIFFNESS, Vector2.new())
  96. local fovSpring = Spring.new(FOV_STIFFNESS, 0)
  97.  
  98. ------------------------------------------------------------------------
  99.  
  100. local Input = {} do
  101. local thumbstickCurve do
  102. local K_CURVATURE = 2.0
  103. local K_DEADZONE = 0.15
  104.  
  105. local function fCurve(x)
  106. return (exp(K_CURVATURE*x) - 1)/(exp(K_CURVATURE) - 1)
  107. end
  108.  
  109. local function fDeadzone(x)
  110. return fCurve((x - K_DEADZONE)/(1 - K_DEADZONE))
  111. end
  112.  
  113. function thumbstickCurve(x)
  114. return sign(x)*clamp(fDeadzone(abs(x)), 0, 1)
  115. end
  116. end
  117.  
  118. local gamepad = {
  119. ButtonX = 0,
  120. ButtonY = 0,
  121. DPadDown = 0,
  122. DPadUp = 0,
  123. ButtonL2 = 0,
  124. ButtonR2 = 0,
  125. Thumbstick1 = Vector2.new(),
  126. Thumbstick2 = Vector2.new(),
  127. }
  128.  
  129. local keyboard = {
  130. W = 0,
  131. A = 0,
  132. S = 0,
  133. D = 0,
  134. E = 0,
  135. Q = 0,
  136. U = 0,
  137. H = 0,
  138. J = 0,
  139. K = 0,
  140. I = 0,
  141. Y = 0,
  142. Up = 0,
  143. Down = 0,
  144. LeftShift = 0,
  145. RightShift = 0,
  146. }
  147.  
  148. local mouse = {
  149. Delta = Vector2.new(),
  150. MouseWheel = 0,
  151. }
  152.  
  153. local NAV_GAMEPAD_SPEED = Vector3.new(1, 1, 1)
  154. local NAV_KEYBOARD_SPEED = Vector3.new(1, 1, 1)
  155. local PAN_MOUSE_SPEED = Vector2.new(1, 1)*(pi/64)
  156. local PAN_GAMEPAD_SPEED = Vector2.new(1, 1)*(pi/8)
  157. local FOV_WHEEL_SPEED = 1.0
  158. local FOV_GAMEPAD_SPEED = 0.25
  159. local NAV_ADJ_SPEED = 0.75
  160. local NAV_SHIFT_MUL = 0.25
  161.  
  162. local navSpeed = 1
  163.  
  164. function Input.Vel(dt)
  165. navSpeed = clamp(navSpeed + dt*(keyboard.Up - keyboard.Down)*NAV_ADJ_SPEED, 0.01, 4)
  166.  
  167. local kGamepad = Vector3.new(
  168. thumbstickCurve(gamepad.Thumbstick1.x),
  169. thumbstickCurve(gamepad.ButtonR2) - thumbstickCurve(gamepad.ButtonL2),
  170. thumbstickCurve(-gamepad.Thumbstick1.y)
  171. )*NAV_GAMEPAD_SPEED
  172.  
  173. local kKeyboard = Vector3.new(
  174. keyboard.D - keyboard.A + keyboard.K - keyboard.H,
  175. keyboard.E - keyboard.Q + keyboard.I - keyboard.Y,
  176. keyboard.S - keyboard.W + keyboard.J - keyboard.U
  177. )*NAV_KEYBOARD_SPEED
  178.  
  179. local shift = UserInputService:IsKeyDown(Enum.KeyCode.LeftShift) or UserInputService:IsKeyDown(Enum.KeyCode.RightShift)
  180.  
  181. return (kGamepad + kKeyboard)*(navSpeed*(shift and NAV_SHIFT_MUL or 1))
  182. end
  183.  
  184. function Input.Pan(dt)
  185. local kGamepad = Vector2.new(
  186. thumbstickCurve(gamepad.Thumbstick2.y),
  187. thumbstickCurve(-gamepad.Thumbstick2.x)
  188. )*PAN_GAMEPAD_SPEED
  189. local kMouse = mouse.Delta*PAN_MOUSE_SPEED
  190. mouse.Delta = Vector2.new()
  191. return kGamepad + kMouse
  192. end
  193.  
  194. function Input.Fov(dt)
  195. local kGamepad = (gamepad.ButtonX - gamepad.ButtonY)*FOV_GAMEPAD_SPEED
  196. local kMouse = mouse.MouseWheel*FOV_WHEEL_SPEED
  197. mouse.MouseWheel = 0
  198. return kGamepad + kMouse
  199. end
  200.  
  201. do
  202. local function Keypress(action, state, input)
  203. keyboard[input.KeyCode.Name] = state == Enum.UserInputState.Begin and 1 or 0
  204. return Enum.ContextActionResult.Sink
  205. end
  206.  
  207. local function GpButton(action, state, input)
  208. gamepad[input.KeyCode.Name] = state == Enum.UserInputState.Begin and 1 or 0
  209. return Enum.ContextActionResult.Sink
  210. end
  211.  
  212. local function MousePan(action, state, input)
  213. local delta = input.Delta
  214. mouse.Delta = Vector2.new(-delta.y, -delta.x)
  215. return Enum.ContextActionResult.Sink
  216. end
  217.  
  218. local function Thumb(action, state, input)
  219. gamepad[input.KeyCode.Name] = input.Position
  220. return Enum.ContextActionResult.Sink
  221. end
  222.  
  223. local function Trigger(action, state, input)
  224. gamepad[input.KeyCode.Name] = input.Position.z
  225. return Enum.ContextActionResult.Sink
  226. end
  227.  
  228. local function MouseWheel(action, state, input)
  229. mouse[input.UserInputType.Name] = -input.Position.z
  230. return Enum.ContextActionResult.Sink
  231. end
  232.  
  233. local function Zero(t)
  234. for k, v in pairs(t) do
  235. t[k] = v*0
  236. end
  237. end
  238.  
  239. function Input.StartCapture()
  240. ContextActionService:BindActionAtPriority("FreecamKeyboard", Keypress, false, INPUT_PRIORITY,
  241. Enum.KeyCode.W, Enum.KeyCode.U,
  242. Enum.KeyCode.A, Enum.KeyCode.H,
  243. Enum.KeyCode.S, Enum.KeyCode.J,
  244. Enum.KeyCode.D, Enum.KeyCode.K,
  245. Enum.KeyCode.E, Enum.KeyCode.I,
  246. Enum.KeyCode.Q, Enum.KeyCode.Y,
  247. Enum.KeyCode.Up, Enum.KeyCode.Down
  248. )
  249. ContextActionService:BindActionAtPriority("FreecamMousePan", MousePan, false, INPUT_PRIORITY, Enum.UserInputType.MouseMovement)
  250. ContextActionService:BindActionAtPriority("FreecamMouseWheel", MouseWheel, false, INPUT_PRIORITY, Enum.UserInputType.MouseWheel)
  251. ContextActionService:BindActionAtPriority("FreecamGamepadButton", GpButton, false, INPUT_PRIORITY, Enum.KeyCode.ButtonX, Enum.KeyCode.ButtonY)
  252. ContextActionService:BindActionAtPriority("FreecamGamepadTrigger", Trigger, false, INPUT_PRIORITY, Enum.KeyCode.ButtonR2, Enum.KeyCode.ButtonL2)
  253. ContextActionService:BindActionAtPriority("FreecamGamepadThumbstick", Thumb, false, INPUT_PRIORITY, Enum.KeyCode.Thumbstick1, Enum.KeyCode.Thumbstick2)
  254. end
  255.  
  256. function Input.StopCapture()
  257. navSpeed = 1
  258. Zero(gamepad)
  259. Zero(keyboard)
  260. Zero(mouse)
  261. ContextActionService:UnbindAction("FreecamKeyboard")
  262. ContextActionService:UnbindAction("FreecamMousePan")
  263. ContextActionService:UnbindAction("FreecamMouseWheel")
  264. ContextActionService:UnbindAction("FreecamGamepadButton")
  265. ContextActionService:UnbindAction("FreecamGamepadTrigger")
  266. ContextActionService:UnbindAction("FreecamGamepadThumbstick")
  267. end
  268. end
  269. end
  270.  
  271. local function GetFocusDistance(cameraFrame)
  272. local znear = 0.1
  273. local viewport = Camera.ViewportSize
  274. local projy = 2*tan(cameraFov/2)
  275. local projx = viewport.x/viewport.y*projy
  276. local fx = cameraFrame.rightVector
  277. local fy = cameraFrame.upVector
  278. local fz = cameraFrame.lookVector
  279.  
  280. local minVect = Vector3.new()
  281. local minDist = 512
  282.  
  283. for x = 0, 1, 0.5 do
  284. for y = 0, 1, 0.5 do
  285. local cx = (x - 0.5)*projx
  286. local cy = (y - 0.5)*projy
  287. local offset = fx*cx - fy*cy + fz
  288. local origin = cameraFrame.p + offset*znear
  289. local _, hit = Workspace:FindPartOnRay(Ray.new(origin, offset.unit*minDist))
  290. local dist = (hit - origin).magnitude
  291. if minDist > dist then
  292. minDist = dist
  293. minVect = offset.unit
  294. end
  295. end
  296. end
  297.  
  298. return fz:Dot(minVect)*minDist
  299. end
  300.  
  301. ------------------------------------------------------------------------
  302.  
  303. local function StepFreecam(dt)
  304. local vel = velSpring:Update(dt, Input.Vel(dt))
  305. local pan = panSpring:Update(dt, Input.Pan(dt))
  306. local fov = fovSpring:Update(dt, Input.Fov(dt))
  307.  
  308. local zoomFactor = sqrt(tan(rad(70/2))/tan(rad(cameraFov/2)))
  309.  
  310. cameraFov = clamp(cameraFov + fov*FOV_GAIN*(dt/zoomFactor), 1, 120)
  311. cameraRot = cameraRot + pan*PAN_GAIN*(dt/zoomFactor)
  312. cameraRot = Vector2.new(clamp(cameraRot.x, -PITCH_LIMIT, PITCH_LIMIT), cameraRot.y%(2*pi))
  313.  
  314. local cameraCFrame = CFrame.new(cameraPos)*CFrame.fromOrientation(cameraRot.x, cameraRot.y, 0)*CFrame.new(vel*NAV_GAIN*dt)
  315. cameraPos = cameraCFrame.p
  316.  
  317. Camera.CFrame = cameraCFrame
  318. Camera.Focus = cameraCFrame*CFrame.new(0, 0, -GetFocusDistance(cameraCFrame))
  319. Camera.FieldOfView = cameraFov
  320. end
  321.  
  322. ------------------------------------------------------------------------
  323.  
  324. local PlayerState = {} do
  325. local mouseBehavior
  326. local mouseIconEnabled
  327. local cameraType
  328. local cameraFocus
  329. local cameraCFrame
  330. local cameraFieldOfView
  331. local screenGuis = {}
  332. local coreGuis = {
  333. Backpack = true,
  334. Chat = true,
  335. Health = true,
  336. PlayerList = true,
  337. }
  338. local setCores = {
  339. BadgesNotificationsActive = true,
  340. PointsNotificationsActive = true,
  341. }
  342.  
  343. -- Save state and set up for freecam
  344. function PlayerState.Push()
  345. for name in pairs(coreGuis) do
  346. coreGuis[name] = StarterGui:GetCoreGuiEnabled(Enum.CoreGuiType[name])
  347. StarterGui:SetCoreGuiEnabled(Enum.CoreGuiType[name], false)
  348. end
  349. for name in pairs(setCores) do
  350. setCores[name] = StarterGui:GetCore(name)
  351. StarterGui:SetCore(name, false)
  352. end
  353. local playergui = LocalPlayer:FindFirstChildOfClass("PlayerGui")
  354. if playergui then
  355. for _, gui in pairs(playergui:GetChildren()) do
  356. if gui:IsA("ScreenGui") and gui.Enabled then
  357. screenGuis[#screenGuis + 1] = gui
  358. gui.Enabled = false
  359. end
  360. end
  361. end
  362.  
  363. cameraFieldOfView = Camera.FieldOfView
  364. Camera.FieldOfView = 70
  365.  
  366. cameraType = Camera.CameraType
  367. Camera.CameraType = Enum.CameraType.Custom
  368.  
  369. cameraCFrame = Camera.CFrame
  370. cameraFocus = Camera.Focus
  371.  
  372. mouseIconEnabled = UserInputService.MouseIconEnabled
  373. UserInputService.MouseIconEnabled = false
  374.  
  375. mouseBehavior = UserInputService.MouseBehavior
  376. UserInputService.MouseBehavior = Enum.MouseBehavior.Default
  377. end
  378.  
  379. -- Restore state
  380. function PlayerState.Pop()
  381. for name, isEnabled in pairs(coreGuis) do
  382. StarterGui:SetCoreGuiEnabled(Enum.CoreGuiType[name], isEnabled)
  383. end
  384. for name, isEnabled in pairs(setCores) do
  385. StarterGui:SetCore(name, isEnabled)
  386. end
  387. for _, gui in pairs(screenGuis) do
  388. if gui.Parent then
  389. gui.Enabled = true
  390. end
  391. end
  392.  
  393. Camera.FieldOfView = cameraFieldOfView
  394. cameraFieldOfView = nil
  395.  
  396. Camera.CameraType = cameraType
  397. cameraType = nil
  398.  
  399. Camera.CFrame = cameraCFrame
  400. cameraCFrame = nil
  401.  
  402. Camera.Focus = cameraFocus
  403. cameraFocus = nil
  404.  
  405. UserInputService.MouseIconEnabled = mouseIconEnabled
  406. mouseIconEnabled = nil
  407.  
  408. UserInputService.MouseBehavior = mouseBehavior
  409. mouseBehavior = nil
  410. end
  411. end
  412.  
  413. local function StartFreecam()
  414. local cameraCFrame = Camera.CFrame
  415. cameraRot = Vector2.new(cameraCFrame:toEulerAnglesYXZ())
  416. cameraPos = cameraCFrame.p
  417. cameraFov = Camera.FieldOfView
  418.  
  419. velSpring:Reset(Vector3.new())
  420. panSpring:Reset(Vector2.new())
  421. fovSpring:Reset(0)
  422.  
  423. PlayerState.Push()
  424. RunService:BindToRenderStep("Freecam", Enum.RenderPriority.Camera.Value, StepFreecam)
  425. Input.StartCapture()
  426. end
  427.  
  428. local function StopFreecam()
  429. Input.StopCapture()
  430. RunService:UnbindFromRenderStep("Freecam")
  431. PlayerState.Pop()
  432. end
  433.  
  434. ------------------------------------------------------------------------
  435.  
  436. do
  437. local enabled = false
  438.  
  439. local function ToggleFreecam()
  440. if enabled then
  441. StopFreecam()
  442. else
  443. StartFreecam()
  444. end
  445. enabled = not enabled
  446. end
  447.  
  448. local function CheckMacro(macro)
  449. for i = 1, #macro - 1 do
  450. if not UserInputService:IsKeyDown(macro[i]) then
  451. return
  452. end
  453. end
  454. ToggleFreecam()
  455. end
  456.  
  457. local function HandleActivationInput(action, state, input)
  458. if state == Enum.UserInputState.Begin then
  459. if input.KeyCode == FREECAM_MACRO_KB[#FREECAM_MACRO_KB] then
  460. CheckMacro(FREECAM_MACRO_KB)
  461. end
  462. end
  463. return Enum.ContextActionResult.Pass
  464. end
  465.  
  466. ContextActionService:BindActionAtPriority("FreecamToggle", HandleActivationInput, false, TOGGLE_INPUT_PRIORITY, FREECAM_MACRO_KB[#FREECAM_MACRO_KB])
  467. end
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement