do local l=Players.LocalPlayer:WaitForChild("\080\108\097\121\101\114\083\099\114\105\112\116\115")l:RegisterTouchCameraMovementMode(Enum.TouchCameraMovementMode.Default)l:RegisterTouchCameraMovementMode(Enum.TouchCameraMovementMode.Follow)l:RegisterTouchCameraMovementMode(Enum.TouchCameraMovementMode.Classic)l:RegisterComputerCameraMovementMode(Enum.ComputerCameraMovementMode.Default)l:RegisterComputerCameraMovementMode(Enum.ComputerCameraMovementMode.Follow)l:RegisterComputerCameraMovementMode(Enum.ComputerCameraMovementMode.Classic)if FFlagUserCameraToggle then l:RegisterComputerCameraMovementMode(Enum.ComputerCameraMovementMode.CameraToggle)end end function CameraModule.new()local l=setmetatable({},CameraModule)l.activeCameraController=nil l.activeOcclusionModule=nil l.activeTransparencyController=nil l.activeMouseLockController=nil l.currentComputerCameraMovementMode=nil l.cameraSubjectChangedConn=nil l.cameraTypeChangedConn=nil for Q,x in pairs(Players:GetPlayers())do l:OnPlayerAdded(x)end Players.PlayerAdded:Connect(function(Q)l:OnPlayerAdded(Q)end)l.activeTransparencyController=TransparencyController.new()l.activeTransparencyController:Enable(true)if not UserInputService.TouchEnabled then l.activeMouseLockController=MouseLockController.new()local Q=l.activeMouseLockController:GetBindableToggleEvent()if Q then Q:Connect(function()l:OnMouseLockToggled()end)end end l:ActivateCameraController(l:GetCameraControlChoice())l:ActivateOcclusionModule(Players.LocalPlayer.DevCameraOcclusionMode)l:OnCurrentCameraChanged()RunService:BindToRenderStep("\099\097\109\101\114\097\082\101\110\100\101\114\085\112\100\097\116\101",Enum.RenderPriority.Camera.Value,function(Q)l:Update(Q)end)for Q,x in pairs(PLAYER_CAMERA_PROPERTIES)do(Players.LocalPlayer:GetPropertyChangedSignal(x)):Connect(function()l:OnLocalPlayerCameraPropertyChanged(x)end)end for Q,x in pairs(USER_GAME_SETTINGS_PROPERTIES)do(UserGameSettings:GetPropertyChangedSignal(x)):Connect(function()l:OnUserGameSettingsPropertyChanged(x)end)end;(game.Workspace:GetPropertyChangedSignal("\067\117\114\114\101\110\116\067\097\109\101\114\097")):Connect(function()l:OnCurrentCameraChanged()end)l.lastInputType=UserInputService:GetLastInputType()UserInputService.LastInputTypeChanged:Connect(function(Q)l.lastInputType=Q end)return l end function CameraModule.GetCameraMovementModeFromSettings(l)local Q=Players.LocalPlayer.CameraMode if Q==Enum.CameraMode.LockFirstPerson then return CameraUtils.ConvertCameraModeEnumToStandard(Enum.ComputerCameraMovementMode.Classic)end local x,V if UserInputService.TouchEnabled then x=CameraUtils.ConvertCameraModeEnumToStandard(Players.LocalPlayer.DevTouchCameraMode)V=CameraUtils.ConvertCameraModeEnumToStandard(UserGameSettings.TouchCameraMovementMode)else x=CameraUtils.ConvertCameraModeEnumToStandard(Players.LocalPlayer.DevComputerCameraMode)V=CameraUtils.ConvertCameraModeEnumToStandard(UserGameSettings.ComputerCameraMovementMode)end if x==Enum.DevComputerCameraMovementMode.UserChoice then return V end return x end function CameraModule.ActivateOcclusionModule(Q,l)local x if l==Enum.DevCameraOcclusionMode.Zoom then x=Poppercam elseif l==Enum.DevCameraOcclusionMode.Invisicam then x=Invisicam else warn("\067\097\109\101\114\097\083\099\114\105\112\116 \065\099\116\105\118\097\116\101\079\099\099\108\117\115\105\111\110\077\111\100\117\108\101 \099\097\108\108\101\100 \119\105\116\104 \117\110\115\117\112\112\111\114\116\101\100 \109\111\100\101")return end if Q.activeOcclusionModule and Q.activeOcclusionModule:GetOcclusionMode()==l then if not Q.activeOcclusionModule:GetEnabled()then Q.activeOcclusionModule:Enable(true)end return end local V=Q.activeOcclusionModule Q.activeOcclusionModule=instantiatedOcclusionModules[x]if not Q.activeOcclusionModule then Q.activeOcclusionModule=x.new()if Q.activeOcclusionModule then instantiatedOcclusionModules[x]=Q.activeOcclusionModule end end if Q.activeOcclusionModule then local x=Q.activeOcclusionModule:GetOcclusionMode()if x~=l then warn("\067\097\109\101\114\097\083\099\114\105\112\116 \065\099\116\105\118\097\116\101\079\099\099\108\117\115\105\111\110\077\111\100\117\108\101 \109\105\115\109\097\116\099\104\058 ",Q.activeOcclusionModule:GetOcclusionMode(),"~\061",l)end if V then if V~=Q.activeOcclusionModule then V:Enable(false)else warn("\067\097\109\101\114\097\083\099\114\105\112\116 \065\099\116\105\118\097\116\101\079\099\099\108\117\115\105\111\110\077\111\100\117\108\101 \102\097\105\108\117\114\101 \116\111 \100\101\116\101\099\116 \097\108\114\101\097\100\121 \114\117\110\110\105\110\103 \099\111\114\114\101\099\116 \109\111\100\117\108\101")end end if l==Enum.DevCameraOcclusionMode.Invisicam then if Players.LocalPlayer.Character then Q.activeOcclusionModule:CharacterAdded(Players.LocalPlayer.Character,Players.LocalPlayer)end else for l,x in pairs(Players:GetPlayers())do if x and x.Character then Q.activeOcclusionModule:CharacterAdded(x.Character,x)end end Q.activeOcclusionModule:OnCameraSubjectChanged(game.Workspace.CurrentCamera.CameraSubject)end Q.activeOcclusionModule:Enable(true)end end

do
	local PlayerScripts = Players.LocalPlayer:WaitForChild("PlayerScripts")

	PlayerScripts:RegisterTouchCameraMovementMode(Enum.TouchCameraMovementMode.Default)
	PlayerScripts:RegisterTouchCameraMovementMode(Enum.TouchCameraMovementMode.Follow)
	PlayerScripts:RegisterTouchCameraMovementMode(Enum.TouchCameraMovementMode.Classic)

	PlayerScripts:RegisterComputerCameraMovementMode(Enum.ComputerCameraMovementMode.Default)
	PlayerScripts:RegisterComputerCameraMovementMode(Enum.ComputerCameraMovementMode.Follow)
	PlayerScripts:RegisterComputerCameraMovementMode(Enum.ComputerCameraMovementMode.Classic)
	if FFlagUserCameraToggle then
		PlayerScripts:RegisterComputerCameraMovementMode(Enum.ComputerCameraMovementMode.CameraToggle)
	end
end


function CameraModule.new()
	local self = setmetatable({},CameraModule)

	-- Current active controller instances
	self.activeCameraController = nil
	self.activeOcclusionModule = nil
	self.activeTransparencyController = nil
	self.activeMouseLockController = nil

	self.currentComputerCameraMovementMode = nil

	-- Connections to events
	self.cameraSubjectChangedConn = nil
	self.cameraTypeChangedConn = nil

	-- Adds CharacterAdded and CharacterRemoving event handlers for all current players
	for _,player in pairs(Players:GetPlayers()) do
		self:OnPlayerAdded(player)
	end

	-- Adds CharacterAdded and CharacterRemoving event handlers for all players who join in the future
	Players.PlayerAdded:Connect(function(player)
		self:OnPlayerAdded(player)
	end)

	self.activeTransparencyController = TransparencyController.new()
	self.activeTransparencyController:Enable(true)

	if not UserInputService.TouchEnabled then
		self.activeMouseLockController = MouseLockController.new()
		local toggleEvent = self.activeMouseLockController:GetBindableToggleEvent()
		if toggleEvent then
			toggleEvent:Connect(function()
				self:OnMouseLockToggled()
			end)
		end
	end

	self:ActivateCameraController(self:GetCameraControlChoice())
	self:ActivateOcclusionModule(Players.LocalPlayer.DevCameraOcclusionMode)
	self:OnCurrentCameraChanged() -- Does initializations and makes first camera controller
	RunService:BindToRenderStep("cameraRenderUpdate", Enum.RenderPriority.Camera.Value, function(dt) self:Update(dt) end)

	-- Connect listeners to camera-related properties
	for _, propertyName in pairs(PLAYER_CAMERA_PROPERTIES) do
		Players.LocalPlayer:GetPropertyChangedSignal(propertyName):Connect(function()
			self:OnLocalPlayerCameraPropertyChanged(propertyName)
		end)
	end

	for _, propertyName in pairs(USER_GAME_SETTINGS_PROPERTIES) do
		UserGameSettings:GetPropertyChangedSignal(propertyName):Connect(function()
			self:OnUserGameSettingsPropertyChanged(propertyName)
		end)
	end
	game.Workspace:GetPropertyChangedSignal("CurrentCamera"):Connect(function()
		self:OnCurrentCameraChanged()
	end)

	self.lastInputType = UserInputService:GetLastInputType()
	UserInputService.LastInputTypeChanged:Connect(function(newLastInputType)
		self.lastInputType = newLastInputType
	end)

	return self
end





function CameraModule:GetCameraMovementModeFromSettings()
	local cameraMode = Players.LocalPlayer.CameraMode

	-- Lock First Person trumps all other settings and forces ClassicCamera
	if cameraMode == Enum.CameraMode.LockFirstPerson then
		return CameraUtils.ConvertCameraModeEnumToStandard(Enum.ComputerCameraMovementMode.Classic)
	end

	local devMode, userMode
	if UserInputService.TouchEnabled then
		devMode = CameraUtils.ConvertCameraModeEnumToStandard(Players.LocalPlayer.DevTouchCameraMode)
		userMode = CameraUtils.ConvertCameraModeEnumToStandard(UserGameSettings.TouchCameraMovementMode)
	else
		devMode = CameraUtils.ConvertCameraModeEnumToStandard(Players.LocalPlayer.DevComputerCameraMode)
		userMode = CameraUtils.ConvertCameraModeEnumToStandard(UserGameSettings.ComputerCameraMovementMode)
	end

	if devMode == Enum.DevComputerCameraMovementMode.UserChoice then
		-- Developer is allowing user choice, so user setting is respected
		return userMode
	end

	return devMode
end

function CameraModule:ActivateOcclusionModule( occlusionMode )
	local newModuleCreator
	if occlusionMode == Enum.DevCameraOcclusionMode.Zoom then
		newModuleCreator = Poppercam
	elseif occlusionMode == Enum.DevCameraOcclusionMode.Invisicam then
		newModuleCreator = Invisicam
	else
		warn("CameraScript ActivateOcclusionModule called with unsupported mode")
		return
	end

	-- First check to see if there is actually a change. If the module being requested is already
	-- the currently-active solution then just make sure it's enabled and exit early
	if self.activeOcclusionModule and self.activeOcclusionModule:GetOcclusionMode() == occlusionMode then
		if not self.activeOcclusionModule:GetEnabled() then
			self.activeOcclusionModule:Enable(true)
		end
		return
	end

	-- Save a reference to the current active module (may be nil) so that we can disable it if
	-- we are successful in activating its replacement
	local prevOcclusionModule = self.activeOcclusionModule

	-- If there is no active module, see if the one we need has already been instantiated
	self.activeOcclusionModule = instantiatedOcclusionModules[newModuleCreator]

	-- If the module was not already instantiated and selected above, instantiate it
	if not self.activeOcclusionModule then
		self.activeOcclusionModule = newModuleCreator.new()
		if self.activeOcclusionModule then
			instantiatedOcclusionModules[newModuleCreator] = self.activeOcclusionModule
		end
	end

	-- If we were successful in either selecting or instantiating the module,
	-- enable it if it's not already the currently-active enabled module
	if self.activeOcclusionModule then
		local newModuleOcclusionMode = self.activeOcclusionModule:GetOcclusionMode()
		-- Sanity check that the module we selected or instantiated actually supports the desired occlusionMode
		if newModuleOcclusionMode ~= occlusionMode then
			warn("CameraScript ActivateOcclusionModule mismatch: ",self.activeOcclusionModule:GetOcclusionMode(),"~=",occlusionMode)
		end

		-- Deactivate current module if there is one
		if prevOcclusionModule then
			-- Sanity check that current module is not being replaced by itself (that should have been handled above)
			if prevOcclusionModule ~= self.activeOcclusionModule then
				prevOcclusionModule:Enable(false)
			else
				warn("CameraScript ActivateOcclusionModule failure to detect already running correct module")
			end
		end

		-- Occlusion modules need to be initialized with information about characters and cameraSubject
		-- Invisicam needs the LocalPlayer's character
		-- Poppercam needs all player characters and the camera subject
		if occlusionMode == Enum.DevCameraOcclusionMode.Invisicam then
			-- Optimization to only send Invisicam what we know it needs
			if Players.LocalPlayer.Character then
				self.activeOcclusionModule:CharacterAdded(Players.LocalPlayer.Character, Players.LocalPlayer )
			end
		else
			-- When Poppercam is enabled, we send it all existing player characters for its raycast ignore list
			for _, player in pairs(Players:GetPlayers()) do
				if player and player.Character then
					self.activeOcclusionModule:CharacterAdded(player.Character, player)
				end
			end
			self.activeOcclusionModule:OnCameraSubjectChanged(game.Workspace.CurrentCamera.CameraSubject)
		end

		-- Activate new choice
		self.activeOcclusionModule:Enable(true)
	end
end
