Is there a property or method for knowing if a GuiBase2d is being rendered or not?

I’m wondering if there’s a way to tell if a GuiBase2d Instance is being rendered or not. I don’t mean this in the context of it being in the bounds of the viewport. What I’m asking is if there’s a way to tell if the instance has a valid ancestry such that can be rendered?

For example, here are some cases where the highlighted frame would render:
RobloxStudioBeta_ww1WezvlRf

RobloxStudioBeta_21Uh3Zz3qJ

And here are some cases where it would not:
UqU59GLbgc

RobloxStudioBeta_qK7zUwflWJ

RobloxStudioBeta_F55wEwPK1x

I am aware that it’s possible to check for this in code, but it’s not future proof b/c Roblox could change the “rules” on what is considered a valid ancestry. There’s also added complexity if you want to track if this has changed b/c you would also need to watch every instance in the ancestry path for if their Enabled or Visible properties have changed etc.

For reference GuiBase2d contains the following classes:

tldr; is there something along the lines of a AbsoluteVisible property for GuiBase2d?

1 Like

i haven’t heard of a property or method like that but it’s an interesting idea

what if a frame is underneath another one?
would that be considered AbsoluteVisible = false and Visible = true

1 Like

I’m not sure if I’m fully understanding your question, but I think you’re basically asking:

local screen = Instance.new("ScreenGui")
screen.Parent = Players.LocalPlayer.PlayerGui

local frame1 = Instance.new("Frame")
frame1.Visible = false
frame1.Parent = screen

local frame2 = Instance.new("Frame")
frame2.Parent = frame1

print(frame2.AbsoluteVisible) -- false
print(frame2.Visible) -- true

In which case, yes. Maybe the naming of the property could be changed to be more clear, but this falls in line with other absolute properties having a mismatch.

I.e. frame.AbsoluteRotation may not equal frame.Rotation

Regardless, that’s besides the point and something more relevant to a features request. Right now I’m curious if a property or methods exists for this already.

1 Like

I’m fairly sure GetGuiObjectsAtPosition returns only visible guis. Using this assumption, you can check whether a gui object is actively being rendered by running this method at the guis position and checking if that object is in the returned array.

I haven’t tested this myself so I’m not sure if this works for objects in world space and objects outside of the visible viewport.

2 Likes

What are you trying to achieve?

I had the same question but I think I solved it in a different way

I might be able to help you if you are willing to share more details

I want to know if a gui is truly visible at any given time b/c I have a “twin” frame that I’d like to match the visibility to.

I.e.

local function match(instance: GuiObject)
	local frame = Instance.new("Frame")

	frame.Visible = instance.AbsoluteVisible
	instance:GetPropertyChangedSignal("AbsoluteVisible"):Connect(function()
		frame.Visible = instance.AbsoluteVisible
	end)
end

that’s too bad, I don’t see any work arounds besides making a custom property for it and listing to changes in the hierarchy

@VegetationBush, can’t use that method based on this reply from staff


I think what you can do is listening to Visible and Enabled properties up the hierarchy

since it has a cascading effect where if the parent is not visible the child also wouldn’t be you can make an algorithm that only checks the parent’s visibility instead of the entire tree, Attributes should be helpful in this regard, shouldn’t be too expensive based on given information

2 Likes

I’m not sure if this will help, but TextLabel.TextBounds are 0, 0 (or not the correct TextBounds size) when not rendered. When they are rendered, they update to the correct TextBounds size.

In my game, I use this to check if the TextLabel is updated and update the frame it’s inside to fit the text length.

Its quite hacky but it works :man_shrugging:

Screen Recording 2024-07-21 at 7.43.27 PM

2 Likes

I wish something like that existed but sadly no. I had the same issue and came up with this workaround:

local function isRendered(instance: GuiObject)
	local ap = instance.AbsolutePosition
	local as = instance.AbsoluteSize
	local lt = ap + Vector2.one
	local lb = ap + Vector2.new(0, as.Y) + Vector2.new(1, -1)
	local rt = ap + Vector2.new(as.X, 0) + Vector2.new(-1, 1)
	local rb = ap + as - Vector2.one
	local m = ap + as/2 -- for extra accurracy
	
	for _, pos: Vector2 in {lt, lb, rt, rb, m} do
		if table.find(localPlayer.PlayerGui:GetGuiObjectsAtPosition(pos.X, pos.Y), instance) then
			return true
		end
	end
	
	return false
end

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

1 Like