bumping bc i ran into this problem, and from what i was able to gather:
from GetGuiObjectsAtPosition doesn’t ignore disabled GUI
from We need a way to check if a GUIObject is visible (GUIObject.IsVisible)
in my case, i have a “descriptor” object that describes a button behavior when hovered over by a mouse, gamepad, or touch input. the guibutton.enter, .leave, and .move-adjacent events are inconsistent and unreliable (especially with gamepads) so i chose the most sensible option and wrote in-house functionalities for enter/leave/move.
BasePlayerGui:GetGuiObjectsAtPosition() does not have a whitelist, so it appears that this function queries the entire baseplayergui which i’m sure is very costly especially for games with interfaces that house several guiobjects.
this is what i was able to come up with, it’s basically the equivalent of BasePlayerGui:GetWhitelistedGuiObjectsAtPosition(whitelist: {GuiObject}, mouselocation: Vector2), if such a function existed. it does not respect clipsdescendants or rotation.
i hope that this will help anyone coming across this thread:
--- returns true if guiobject is actually visible on screen
local function isvisibleonscreen(guiobject: GuiObject)
if guiobject.Visible == false then
return false
else
local screengui = guiobject:FindFirstAncestorOfClass("ScreenGui")
if screengui then
if screengui.Enabled == false then
return false
end
end
local ancestor = guiobject:FindFirstAncestorWhichIsA("GuiObject")
if ancestor then
return isvisibleonscreen(ancestor)
else
return guiobject.Visible
end
end
end
--- returns the equivalent of `BasePlayerGui:GetWhitelistedGuiObjectsAtPosition()`
local function findhovertarget(list: {GuiObject}, insetmouselocation: Vector2): GuiObject?
local mousex, mousey = insetmouselocation.X, insetmouselocation.Y
local inbounds = table.create(#list)
for _, guiobject in list do
local topleft = guiobject.AbsolutePosition
local bottomright = topleft + guiobject.AbsoluteSize
if mousex >= topleft.X
and mousex <= bottomright.X
and mousey >= topleft.Y
and mousey <= bottomright.Y
and isvisibleonscreen(guiobject)
then
table.insert(inbounds, guiobject)
end
end
if #inbounds > 1 then
--- sort by distance from center of guiobject
table.sort(inbounds, function(a, b)
--- local dista = vector.magnitude(a.AbsolutePosition::any + (a.AbsoluteSize*0.5) - insetmouselocation)
--- local distb = vector.magnitude(b.AbsolutePosition::any + (b.AbsoluteSize*0.5) - insetmouselocation)
local dista = (a.AbsolutePosition + (a.AbsoluteSize*0.5) - insetmouselocation).Magnitude
local distb = (b.AbsolutePosition + (b.AbsoluteSize*0.5) - insetmouselocation).Magnitude
return dista < distb
end)
end
return inbounds[1]
end