So Roblox mouse events suck. By those I mean like MouseLeave/MouseEnter specifically, they do not work reliably at all. So with that said, I went and made my own module to handle it more reliably.
It works well, however I just noticed a logical issue I’m pretty confused on how to fix.
Basically you can see it here:
Since the spacing between the two buttons is quite small, there’s an issue with the event callbacks not running in the correct order. (not quite sure, it’s like the callbacks for MouseEnter fire before the MouseLeave ones, so that screws everything up and therefor hides the mouse tooltip)
Here’s my code, if anyone wants to take a peek.
local mouseEvents = {}
mouseEvents.__index = mouseEvents
local player = game.Players.LocalPlayer
local playerMouse = player:GetMouse()
--//Dependencies
local UIController;
function mouseEvents.new(button)
local self = setmetatable({}, mouseEvents)
--//Field declarations
self.button = button
self.eventCallbacks = {onMouseEnter = {}, onMouseLeave = {}, onMouseMoved = {}}
self.mouseOnButton = false
--//Initiate update event for this button
self:Init()
return self
end
function mouseEvents:loadDependencies() --//Loads dependencies to use
UIController = require(script.Parent:WaitForChild("UIController"))
end
function mouseEvents:Init() --//Sets up events to handle updating the state of the button
local parentFrameName = self.button:GetAttribute("ParentFrame")
local parentFrame = UIController.elements.named[parentFrameName]
--//Handle disabling/enabling event callbacks when ever the button's parent frame changes (visible/invisible)
parentFrame:GetPropertyChangedSignal("Visible"):Connect(function()
if not parentFrame.Visible then
--//When ever the frame is hidden, the mouse can no longer be hovered on the button, so fire those event callbacks
self:fireCallbacks(self.eventCallbacks.onMouseLeave)
end
end)
playerMouse.Move:Connect(function()
if not parentFrame.Visible then return end --//We don't want to do anything if the button's parent frame is not visible
local isMouseOnButton = self:isMouseOnButton()
if isMouseOnButton and not self.mouseOnButton then
self.mouseOnButton = true
self:fireCallbacks(self.eventCallbacks.onMouseEnter)
elseif not isMouseOnButton and self.mouseOnButton then
self.mouseOnButton = false
self:fireCallbacks(self.eventCallbacks.onMouseLeave)
elseif isMouseOnButton then
--//Mouse moved on the button
self:fireCallbacks(self.eventCallbacks.onMouseMoved)
end
end)
end
function mouseEvents:fireCallbacks(callbacks) --//Executes all of the specified callbacks
for _, callback in ipairs(callbacks) do
callback()
end
end
function mouseEvents:isMouseOnButton() --//Determines if the mouse is currently hovering over the button
local buttonPos, buttonSize = self.button.AbsolutePosition, self.button.AbsoluteSize
local mouseX, mouseY = playerMouse.X, playerMouse.Y
return (mouseX > buttonPos.X and mouseX < buttonPos.X + buttonSize.X) and (mouseY > buttonPos.Y and mouseY < buttonPos.Y + buttonSize.Y)
end
function mouseEvents:onMouseEnter(callback) --//Attaches callback to be fired when the mouse hovers over the button
table.insert(self.eventCallbacks.onMouseEnter, callback)
end
function mouseEvents:onMouseLeave(callback) --//Attaches callback to be fired when the mouse leaves the button
table.insert(self.eventCallbacks.onMouseLeave, callback)
end
function mouseEvents:onMouseMoved(callback) --//Attaches callback to be fired when ever the mouse moves on the button
table.insert(self.eventCallbacks.onMouseMoved, callback)
end
return mouseEvents
Any help appreciated, thanks.