Advertisement
Stefanuk12

RbxMouse

Mar 2nd, 2020
186,673
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 12.76 KB | None | 0 0
  1. function aConfiguration()
  2.     return {
  3.     -- Raycast distance for the CFrame and Target properties
  4.     RaycastDistance = 1000;
  5.  
  6.     -- Maximum number of seconds for a mouse button to be down for the click event to be called
  7.     ClickThreshold = 0.5;
  8.  
  9.     -- Whether touch input is mapped to the first (left) mouse button
  10.     DetectTouchAsButton1 = true;
  11.  
  12.     -- Whether the mouse has target functionality (Target and TargetFilter)
  13.     TargetEnabled = true;
  14.  
  15.     -- Update properties with RunService and not mouse movemenet
  16.     -- Less efficient than updating with mouse movement, but will update properties even if mouse hasn't been moved
  17.     ConstantlyUpdatingProperties = true;
  18. }
  19. end
  20.  
  21. function aInput()
  22.     local CONFIG = aConfiguration()
  23. local UIT_TOUCH = Enum.UserInputType.Touch
  24. local UIT_BUTTON1 = Enum.UserInputType.MouseButton1
  25.  
  26. local UserInputService = game:GetService("UserInputService")
  27. local RenderStepped = game:GetService("RunService").RenderStepped
  28.  
  29. local boundActions = {}
  30. local boundBinaryActions = {}
  31. local boundChangeActions = {}
  32. local boundFrames = {}
  33.  
  34. local connectionBegin, connectionEnd, connectionChanged, connectionFrame
  35. local callbackBegan, callbackEnded, callbackChanged, callbackFrame do
  36.     callbackBegan = function(inputObject)
  37.         local input = inputObject.UserInputType
  38.         if (CONFIG.DetectTouchAsButton1 and input == UIT_TOUCH) then
  39.             input = UIT_BUTTON1
  40.         end
  41.  
  42.         local inputCallbacks = boundActions[input]
  43.         if inputCallbacks then
  44.             for index = 1, #inputCallbacks do
  45.                 inputCallbacks[index]()
  46.             end
  47.         end
  48.  
  49.         local inputBinaryCallbacks = boundBinaryActions[input]
  50.         if inputBinaryCallbacks then
  51.             for index = 1, #inputBinaryCallbacks do
  52.                 inputBinaryCallbacks[index](true)
  53.             end
  54.         end
  55.     end
  56.  
  57.     callbackEnded = function(inputObject)
  58.         local input = inputObject.UserInputType
  59.         if (CONFIG.DetectTouchAsButton1 and input == UIT_TOUCH) then
  60.             input = UIT_BUTTON1
  61.         end
  62.  
  63.         local inputBinaryCallbacks = boundBinaryActions[input]
  64.         if inputBinaryCallbacks then
  65.             for index = 1, #inputBinaryCallbacks do
  66.                 inputBinaryCallbacks[index](false)
  67.             end
  68.         end
  69.     end
  70.  
  71.     callbackChanged = function(inputObject)
  72.         local input = inputObject.UserInputType
  73.         local inputCallbacks = boundChangeActions[input]
  74.  
  75.         if inputCallbacks then
  76.             for index = 1, #inputCallbacks do
  77.                 inputCallbacks[index](inputObject)
  78.             end
  79.         end
  80.     end
  81.  
  82.     callbackFrame = function()
  83.         for index = 1, #boundFrames do
  84.             boundFrames[index](UserInputService)
  85.         end
  86.     end
  87. end
  88.  
  89. local Input = {} do
  90.     Input.bindAction = function(action, callback)
  91.         if not boundActions[action] then boundActions[action] = {} end
  92.         table.insert(boundActions[action], callback)
  93.     end
  94.  
  95.     Input.bindActionBinary = function(action, callback)
  96.         if not boundBinaryActions[action] then boundBinaryActions[action] = {} end
  97.         table.insert(boundBinaryActions[action], callback)
  98.     end
  99.  
  100.     Input.bindActionChange = function(action, callback)
  101.         if not boundChangeActions[action] then boundChangeActions[action] = {} end
  102.         table.insert(boundChangeActions[action], callback)
  103.     end
  104.  
  105.     Input.bindToFrame = function(callback)
  106.         table.insert(boundFrames, callback)
  107.     end
  108.  
  109.     Input.disable = function()
  110.         connectionBegan:Disconnect()
  111.         connectionEnded:Disconnect()
  112.         connectionChanged:Disconnect()
  113.         connectionFrame:Disconnect()
  114.     end
  115.  
  116.     Input.enable = function()
  117.         connectionBegan = UserInputService.InputBegan:Connect(callbackBegan)
  118.         connectionEnded = UserInputService.InputEnded:Connect(callbackEnded)
  119.         connectionChanged = UserInputService.InputChanged:Connect(callbackChanged)
  120.         connectionFrame = RenderStepped:Connect(callbackFrame)
  121.     end
  122.  
  123.     Input.enable()
  124. end
  125.  
  126. return Input
  127. end
  128.  
  129. function aMouseRay()
  130.     local CONFIG = aConfiguration()
  131.  
  132. local MouseRay = {} do
  133.     local Ray = Ray.new
  134.     local CFrame = CFrame.new
  135.     local Camera = workspace.CurrentCamera
  136.  
  137.     local cache = {nil, CFrame()}
  138.  
  139.     MouseRay.new = function(position, targetFilter)
  140.         local newRay = Camera:ScreenPointToRay(position.X, position.Y) do
  141.             newRay = Ray(newRay.Origin, newRay.Direction * CONFIG.RaycastDistance)
  142.         end
  143.  
  144.         cache = {workspace:FindPartOnRayWithIgnoreList(newRay, targetFilter)}
  145.         cache[3] = newRay.Unit.Direction
  146.     end
  147.  
  148.     MouseRay.getCFrame = function()
  149.         return CFrame(cache[2], cache[3])
  150.     end
  151.  
  152.     MouseRay.getTarget = function()
  153.         return cache[1]
  154.     end
  155. end
  156.  
  157. return MouseRay
  158. end
  159.  
  160. function aRbxMouseButton()
  161.     local CONFIG = aConfiguration()
  162.  
  163. local Input = aInput()
  164.  
  165. local buttons = {}
  166.  
  167. local makeNewButton = function(buttonId)
  168.     local buttonInputType = Enum.UserInputType["MouseButton" ..buttonId]
  169.  
  170.     local properties = {} do
  171.         properties.ButtonId = buttonId
  172.         properties.ButtonName =
  173.             (buttonId == 1 and "Left") or
  174.             (buttonId == 2 and "Right") or
  175.             (buttonId == 3 and "Middle")
  176.  
  177.         properties.IsDown = false
  178.     end
  179.  
  180.     local signals = {} do
  181.         signals.Down = Instance.new("BindableEvent")
  182.         signals.Up = Instance.new("BindableEvent")
  183.  
  184.         Input.bindActionBinary(buttonInputType, function(isBegin)
  185.             if isBegin and not properties.IsDown then
  186.                 properties.IsDown = true
  187.                 signals.Down:Fire()
  188.             elseif not isBegin and properties.IsDown then
  189.                 properties.IsDown = false
  190.                 signals.Up:Fire()
  191.             end
  192.         end)
  193.  
  194.         signals.Click = Instance.new("BindableEvent") do
  195.             local wentDownAt
  196.  
  197.             signals.Down.Event:Connect(function()
  198.                 wentDownAt = tick()
  199.             end)
  200.             signals.Up.Event:Connect(function()
  201.                 local timeSpentDown = tick() - wentDownAt
  202.                 if timeSpentDown > CONFIG.ClickThreshold then return end
  203.                 signals.Click:Fire(timeSpentDown)
  204.             end)
  205.         end
  206.     end
  207.  
  208.     local methods = {} do
  209.         methods.ForceDown = function()
  210.             if properties.IsDown then return end
  211.             properties.IsDown = true
  212.             signals.Down:Fire()
  213.         end
  214.         methods.ForceUp = function()
  215.             if not properties.IsDown then return end
  216.             properties.IsDown = false
  217.             signals.Up:Fire()
  218.         end
  219.     end
  220.  
  221.     local newButton = {} do
  222.         setmetatable(newButton, {
  223.             __index = function(self, index)
  224.                 local property = properties[index]
  225.                 if property then return property end
  226.  
  227.                 local signal = signals[index]
  228.                 if signal then return signal.Event end
  229.  
  230.                 local method = methods[index]
  231.                 if method then return method end
  232.  
  233.                 error(tostring(index).. " is not a valid member of RbxMouseButton")
  234.             end,
  235.             __newindex = function() end
  236.         })
  237.     end
  238.  
  239.     return newButton
  240. end
  241.  
  242. local RbxMouseButtonContainer = {} do
  243.     setmetatable(RbxMouseButtonContainer, {
  244.         __index = function(self, index)
  245.             local buttonId =
  246.                 ((index == 1 or index == "Left") and 1) or
  247.                 ((index == 2 or index == "Right") and 2) or
  248.                 ((index == 3 or index == "Middle") and 3)
  249.  
  250.             if not buttonId then error(tostring(index).. " is not a valid mouse button") end
  251.             if not buttons[buttonId] then
  252.                 buttons[buttonId] = makeNewButton(buttonId)
  253.             end
  254.             return buttons[buttonId]
  255.         end,
  256.         __newindex = function() end
  257.     })
  258. end
  259.  
  260. return RbxMouseButtonContainer
  261.  
  262. end
  263.  
  264. function aRbxMouseIcon()
  265.     local methods = {} do
  266.     local UserInputService = game:GetService("UserInputService")
  267.     local RenderStepped = game:GetService("RunService").RenderStepped
  268.     local Mouse = game:GetService("Players").LocalPlayer:GetMouse()
  269.  
  270.     local currentMouseIcon = Mouse.Icon
  271.  
  272.     methods.Hide = function()
  273.         UserInputService.MouseIconEnabled = false
  274.     end
  275.  
  276.     methods.Show = function()
  277.         UserInputService.MouseIconEnabled = true
  278.     end
  279.  
  280.     methods.Set = function(id)
  281.         local assetId =
  282.             (typeof(id) == "number" and "rbxassetid://" ..id) or
  283.             (typeof(id) == "string" and id) or
  284.             (not id and "") or
  285.             Mouse.Icon
  286.  
  287.         Mouse.Icon = assetId
  288.     end
  289.  
  290.     methods.Get = function()
  291.         return Mouse.Icon
  292.     end
  293. end
  294.  
  295. local RbxMouseIcon = {} do
  296.     setmetatable(RbxMouseIcon, {
  297.         __index = function(self, index)
  298.             local method = methods[index]
  299.             if method then return method end
  300.  
  301.             error(tostring(index).. " is not a valid member of RbxMouseIcon")
  302.         end,
  303.         __newindex = function() end
  304.     })
  305. end
  306.  
  307. return RbxMouseIcon
  308.  
  309. end
  310.  
  311. function aRbxTargetFilter()
  312.     local methods = {} do
  313.     local filterTable = {}
  314.  
  315.     methods.Set = function(self, object)
  316.         if typeof(object) == "table" then
  317.             filterTable = object
  318.         else
  319.             filterTable = {object}
  320.         end
  321.     end
  322.  
  323.     methods.Get = function()
  324.         return filterTable
  325.     end
  326.  
  327.     methods.Add = function(self, object)
  328.         for index = 1, #filterTable do
  329.             if object == filterTable[index] then
  330.                 return
  331.             end
  332.         end
  333.         table.insert(filterTable, object)
  334.     end
  335.  
  336.     methods.Remove = function(self, object)
  337.         for index = 1, #filterTable do
  338.             if object == filterTable[index] then
  339.                 table.remove(filterTable, index)
  340.                 break
  341.             end
  342.         end
  343.     end
  344. end
  345.  
  346. local RbxTargetFilter = {} do
  347.     setmetatable(RbxTargetFilter, {
  348.         __index = function(self, index)
  349.             local method = methods[index]
  350.             if method then return method end
  351.  
  352.             error(tostring(index).. " is not a valid member of RbxTargetFilter")
  353.         end,
  354.         __newindex = function() end
  355.     })
  356. end
  357.  
  358. return RbxTargetFilter
  359. end
  360.  
  361. local CONFIG = aConfiguration()
  362. local UIT_MOUSE_MOVEMENT = Enum.UserInputType.MouseMovement
  363.  
  364. local Input = aInput()
  365.  
  366. local children = {} do
  367.     children.Button = aRbxMouseButton()
  368.     children.Icon = aRbxMouseIcon()
  369.  
  370.     if CONFIG.TargetEnabled then
  371.         children.TargetFilter = aRbxTargetFilter()
  372.     end
  373. end
  374.  
  375. local properties = {} do
  376.     local MouseRay = aMouseRay()
  377.  
  378.     properties.Position = Vector2.new()
  379.     properties.CFrame = CFrame.new()
  380.  
  381.     if not CONFIG.ConstantlyUpdatingProperties then
  382.         Input.bindActionChange(UIT_MOUSE_MOVEMENT, function(inputObject)
  383.             properties.Position = Vector2.new(inputObject.Position.X, inputObject.Position.Y)
  384.             MouseRay.new(properties.Position, children.TargetFilter:Get())
  385.             properties.CFrame = MouseRay.getCFrame()
  386.         end)
  387.     else
  388.         Input.bindToFrame(function(UserInputService)
  389.             local mousePosition = UserInputService:GetMouseLocation()
  390.             properties.Position = mousePosition
  391.             MouseRay.new(mousePosition, children.TargetFilter:Get())
  392.             properties.CFrame = MouseRay.getCFrame()
  393.         end)
  394.     end
  395.  
  396.     if CONFIG.TargetEnabled then
  397.         properties.Target = nil
  398.         local updateTarget = function()
  399.             properties.Target = MouseRay.getTarget()
  400.         end
  401.  
  402.         if not CONFIG.ConstantlyUpdatingProperties then
  403.             Input.bindActionChange(UIT_MOUSE_MOVEMENT, updateTarget)
  404.         else
  405.             Input.bindToFrame(updateTarget)
  406.         end
  407.     end
  408. end
  409.  
  410. local signals = {} do
  411.     signals.Move = Instance.new("BindableEvent")
  412.  
  413.     Input.bindActionChange(UIT_MOUSE_MOVEMENT, function()
  414.         signals.Move:Fire(properties.Position)
  415.     end)
  416. end
  417.  
  418. local methods = {} do
  419.     methods.Enable = function(self)
  420.         Input.enable()
  421.     end
  422.     methods.Disable = function(self)
  423.         Input.disable()
  424.     end
  425. end
  426.  
  427. local RbxMouse = {} do
  428.     local getMember = function(self, index)
  429.         local child = children[index]
  430.         if child then return child end
  431.  
  432.         local property = properties[index]
  433.         if property then return property end
  434.  
  435.         local signal = signals[index]
  436.         if signal then return signal.Event end
  437.  
  438.         local method = methods[index]
  439.         if method then return method end
  440.     end
  441.  
  442.     setmetatable(RbxMouse, {
  443.         __index = function(self, index)
  444.             local member = getMember(self, index)
  445.             if member then return member end
  446.             if CONFIG.TargetEnabled and index == "Target" then return nil end
  447.  
  448.             error(tostring(index).. " is not a valid member of RbxMouse")
  449.         end,
  450.         __newindex = function() end
  451.     })
  452. end
  453.  
  454. return RbxMouse
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement