UserInputService Mouse

Tired of having to use the player mouse or the plugin mouse? Well here’s a solution! This module returns a custom mouse class that uses the UserInputService instead. Yay! No more having to worry if plugin:Activate(true) was called and still active etc.

I also added/adjusted a few properties to this custom mouse. They are described here:

--[[
	mouse.TargetFilter [Instance] or [Array of Instances]
		> Determines an object (and its descendants) to be included when determining Mouse.Hit and Mouse.Target
		> Note for added functionality this can be set to either a single instance or a table of instances.
		> Defaulted to the workspace.
	mouse.TargetSurfaceNormal [readonly][Vector3]
		> Describes the SurfaceNormal of the BasePart surface at which the mouse is pointing	
	mouse.ViewSize [readonly][Vector2]
		> Describes the width and height of the screen in pixels
	mouse.Position [readonly][Vector2]
		> Describes the X and Y components of the mouse’s screen position
	mouse.TargetBlackList [Instance] or [Array of Instances]
		> Determines an object (and its descendants) to be ignored when determining Mouse.Hit and Mouse.Target
		> This can be set to either a single instance or a table of instances.
	mouse.IgnoreCharacter [boolean]
		> Only applies when a local player's character exists and is automatically set to true. This is a very odd property I admit, 
		> but for whatever reason the player mouse ignores the character so I figured I'd include this to perfectly emulate.
--]]

The rest of the properties/events pertaining to the mouse function as normal. It is worth noting though that properties such as mouse.Parent or mouse.DataCost do not exist with this custom mouse.

You can find the module here:

As part of this module I ended up writing some functions that extend raycasting a abilities a bit. Mainly I tried to emulate the concept from this thread.

You can find that module by itself here:

Both modules have further explanation of their API inside.

Hope this is helpful! Enjoy!

26 Likes

Cool module, there’s also this one by @EmeraldSlash if you’d like an alternative.

4 Likes

Sorry if this is the wrong place to ask, but is there any way this might crash the client? Specifically when reading mouse.Hit? Sometimes players crash in my game when they activate a certain tool that uses this module and the only culprit I can think of is this module.

Only thing I could think of would be the raycast callback module. It’s likely a problem with the floating point math. I’ve updated both to add some extra checks against this, but if you still find this problem let me explain it in full.

The way the raycast callback module works is that like a normal ray it has an origin and a direction. the ray shoots from the origin and if it hits something it checks whether or not the thing it hit should be returned or if the ray should continue forward or just straight up stop. For example you might use this to continue raycasting through objects that are above a certain transparency and return information about objects that are not.

Here’s where we get into the floating point math. When you hit an object you want to continue through you might think we just use the previous ray’s hit position and the remaining length of the original ray to continue forward. However, because of floating point inaccuracy this may cause our result to hit the exact same target. Imagine an infinitely thin piece of paper (a plane). If you find the intersection point and want to continue through it you better bet that numerically you’re exactly precise. Otherwise even that 1E-8 decimal loss of information may put you on the same side of the paper as you were before, and then boom you’re trapped in an infinite loop.

“Alright, easy fix” you might say. “Just nudge the intersection forward by an unnoticeable amount”. This is exactly what I did, BUT it comes at a cost. If you have two very thin parts edge to edge, there’s a possibility this little shift will move right past the second part. Good news is, that it’s very unlikely to happen so not a huge worry, but something to take note of.

Okay, but there’s still another potential problem. The raycast length also poses a potential problem, but is solved by the same solution. The jist of the matter is that due to floating point error we may never reach the full length of the original ray and thus also get trapped in an infinite loop. The solution is to have a cutoff minimum length which again should be unnoticeable.

Hopefully that helped. Let me know!

2 Likes

Thanks for taking the time to look into that. I will test it out later :slight_smile:

1 Like

Alright, so I made a new version of this module which I think works a bit better.

Aside from (hopefully) fixing the raycasting issue from before by slightly changing my approach, there’s now a new user settable method. This method can be used to define certain types of parts that should be ignored. For example, if I wanted to ignore BaseParts that were CanCollide = false I’d write:

local mouse = require(game.Workspace.Mouse).new()

function mouse:IgnoreCheck(hit, pos, normal, material)
	return not hit.CanCollide
end

mouse.Button1Down:Connect(function()
	print(mouse.Target)
end)

Here’s the new module. Let me know if I missed anything! :grin:

3 Likes