212 lines
6.4 KiB
Lua
212 lines
6.4 KiB
Lua
--[[
|
|
MouseLockController - Replacement for ShiftLockController, manages use of mouse-locked mode
|
|
2018 Camera Update - AllYourBlox
|
|
--]]
|
|
|
|
--[[ Constants ]]--
|
|
local DEFAULT_MOUSE_LOCK_CURSOR = "rbxasset://textures/MouseLockedCursor.png"
|
|
|
|
local Util = require(script.Parent:WaitForChild("CameraUtils"))
|
|
|
|
--[[ Services ]]--
|
|
local PlayersService = game:GetService("Players")
|
|
local UserInputService = game:GetService("UserInputService")
|
|
local Settings = UserSettings() -- ignore warning
|
|
local GameSettings = Settings.GameSettings
|
|
local Mouse = PlayersService.LocalPlayer:GetMouse()
|
|
|
|
--[[ The Module ]]--
|
|
local MouseLockController = {}
|
|
MouseLockController.__index = MouseLockController
|
|
|
|
function MouseLockController.new()
|
|
local self = setmetatable({}, MouseLockController)
|
|
|
|
self.inputBeganConn = nil
|
|
self.isMouseLocked = false
|
|
self.savedMouseCursor = nil
|
|
self.boundKeys = {Enum.KeyCode.LeftShift, Enum.KeyCode.RightShift} -- defaults
|
|
|
|
self.mouseLockToggledEvent = Instance.new("BindableEvent")
|
|
|
|
local boundKeysObj = script:FindFirstChild("BoundKeys")
|
|
if (not boundKeysObj) or (not boundKeysObj:IsA("StringValue")) then
|
|
-- If object with correct name was found, but it's not a StringValue, destroy and replace
|
|
if boundKeysObj then
|
|
boundKeysObj:Destroy()
|
|
end
|
|
|
|
boundKeysObj = Instance.new("StringValue")
|
|
boundKeysObj.Name = "BoundKeys"
|
|
boundKeysObj.Value = "LeftShift,RightShift"
|
|
boundKeysObj.Parent = script
|
|
end
|
|
|
|
if boundKeysObj then
|
|
boundKeysObj.Changed:Connect(function(value)
|
|
self:OnBoundKeysObjectChanged(value)
|
|
end)
|
|
self:OnBoundKeysObjectChanged(boundKeysObj.Value) -- Initial setup call
|
|
end
|
|
|
|
-- Watch for changes to user's ControlMode and ComputerMovementMode settings and update the feature availabilty accordingly
|
|
GameSettings.Changed:Connect(function(property)
|
|
if property == "ControlMode" or property == "ComputerMovementMode" then
|
|
self:UpdateMouseLockAvailability()
|
|
end
|
|
end)
|
|
|
|
-- Watch for changes to DevEnableMouseLock and update the feature availabilty accordingly
|
|
PlayersService.LocalPlayer:GetPropertyChangedSignal("DevEnableMouseLock"):Connect(function()
|
|
self:UpdateMouseLockAvailability()
|
|
end)
|
|
|
|
-- Watch for changes to DevEnableMouseLock and update the feature availabilty accordingly
|
|
PlayersService.LocalPlayer:GetPropertyChangedSignal("DevComputerMovementMode"):Connect(function()
|
|
self:UpdateMouseLockAvailability()
|
|
end)
|
|
|
|
self:UpdateMouseLockAvailability()
|
|
|
|
return self
|
|
end
|
|
|
|
function MouseLockController:GetIsMouseLocked()
|
|
return self.isMouseLocked
|
|
end
|
|
|
|
function MouseLockController:GetBindableToggleEvent()
|
|
return self.mouseLockToggledEvent.Event
|
|
end
|
|
|
|
function MouseLockController:GetMouseLockOffset()
|
|
local offsetValueObj = script:FindFirstChild("CameraOffset")
|
|
if offsetValueObj and offsetValueObj:IsA("Vector3Value") then
|
|
return offsetValueObj.Value
|
|
else
|
|
-- If CameraOffset object was found but not correct type, destroy
|
|
if offsetValueObj then
|
|
offsetValueObj:Destroy()
|
|
end
|
|
offsetValueObj = Instance.new("Vector3Value")
|
|
offsetValueObj.Name = "CameraOffset"
|
|
offsetValueObj.Value = Vector3.new(1.75,0,0) -- Legacy Default Value
|
|
offsetValueObj.Parent = script
|
|
end
|
|
|
|
if offsetValueObj and offsetValueObj.Value then
|
|
return offsetValueObj.Value
|
|
end
|
|
|
|
return Vector3.new(1.75,0,0)
|
|
end
|
|
|
|
function MouseLockController:UpdateMouseLockAvailability()
|
|
local devAllowsMouseLock = PlayersService.LocalPlayer.DevEnableMouseLock
|
|
local devMovementModeIsScriptable = PlayersService.LocalPlayer.DevComputerMovementMode == Enum.DevComputerMovementMode.Scriptable
|
|
local userHasMouseLockModeEnabled = GameSettings.ControlMode == Enum.ControlMode.MouseLockSwitch
|
|
local userHasClickToMoveEnabled = GameSettings.ComputerMovementMode == Enum.ComputerMovementMode.ClickToMove
|
|
local MouseLockAvailable = devAllowsMouseLock and userHasMouseLockModeEnabled and not userHasClickToMoveEnabled and not devMovementModeIsScriptable
|
|
|
|
if MouseLockAvailable~=self.enabled then
|
|
self:EnableMouseLock(MouseLockAvailable)
|
|
end
|
|
end
|
|
|
|
function MouseLockController:OnBoundKeysObjectChanged(newValue)
|
|
self.boundKeys = {} -- Overriding defaults, note: possibly with nothing at all if boundKeysObj.Value is "" or contains invalid values
|
|
for token in string.gmatch(newValue,"[^%s,]+") do
|
|
for keyCode, keyEnum in pairs(Enum.KeyCode:GetEnumItems()) do
|
|
if token == keyEnum.Name then
|
|
self.boundKeys[#self.boundKeys+1] = keyEnum
|
|
break
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
--[[ Local Functions ]]--
|
|
function MouseLockController:OnMouseLockToggled()
|
|
self.isMouseLocked = not self.isMouseLocked
|
|
|
|
if self.isMouseLocked then
|
|
local cursorImageValueObj = script:FindFirstChild("CursorImage")
|
|
if cursorImageValueObj and cursorImageValueObj:IsA("StringValue") and cursorImageValueObj.Value then
|
|
self.savedMouseCursor = Mouse.Icon
|
|
Mouse.Icon = cursorImageValueObj.Value
|
|
else
|
|
if cursorImageValueObj then
|
|
cursorImageValueObj:Destroy()
|
|
end
|
|
cursorImageValueObj = Instance.new("StringValue")
|
|
cursorImageValueObj.Name = "CursorImage"
|
|
cursorImageValueObj.Value = DEFAULT_MOUSE_LOCK_CURSOR
|
|
cursorImageValueObj.Parent = script
|
|
self.savedMouseCursor = Mouse.Icon
|
|
Mouse.Icon = DEFAULT_MOUSE_LOCK_CURSOR
|
|
end
|
|
else
|
|
if self.savedMouseCursor then
|
|
Mouse.Icon = self.savedMouseCursor
|
|
self.savedMouseCursor = nil
|
|
end
|
|
end
|
|
|
|
self.mouseLockToggledEvent:Fire()
|
|
end
|
|
|
|
function MouseLockController:OnInputBegan(input, processed)
|
|
if processed then return end
|
|
|
|
if input.UserInputType == Enum.UserInputType.Keyboard then
|
|
for _, keyCode in pairs(self.boundKeys) do
|
|
if keyCode == input.KeyCode then
|
|
self:OnMouseLockToggled()
|
|
return
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
--[[ Public API ]]--
|
|
function MouseLockController:IsMouseLocked()
|
|
return self.enabled and self.isMouseLocked
|
|
end
|
|
|
|
function MouseLockController:EnableMouseLock(enable)
|
|
if enable~=self.enabled then
|
|
|
|
self.enabled = enable
|
|
|
|
if self.enabled then
|
|
-- Enabling the mode
|
|
if self.inputBeganConn then
|
|
self.inputBeganConn:Disconnect()
|
|
end
|
|
self.inputBeganConn = UserInputService.InputBegan:Connect(function(input, processed)
|
|
self:OnInputBegan(input, processed)
|
|
end)
|
|
else
|
|
-- Disabling
|
|
-- Restore mouse cursor
|
|
if Mouse.Icon~="" then
|
|
Mouse.Icon = ""
|
|
end
|
|
if self.inputBeganConn then
|
|
self.inputBeganConn:Disconnect()
|
|
end
|
|
self.inputBeganConn = nil
|
|
|
|
-- If the mode is disabled while being used, fire the event to toggle it off
|
|
if self.isMouseLocked then
|
|
self.mouseLockToggledEvent:Fire()
|
|
end
|
|
|
|
self.isMouseLocked = false
|
|
end
|
|
|
|
end
|
|
end
|
|
|
|
return MouseLockController
|