How do I check if a UI is truly visible?

If a button has the Visible property set to true, but the frame (parent) has the Visible property set to false, the button won’t actually be “Visible”. So my question is, how can I check if a GuiObject is truly visible?

1 Like

You could just simply check if the Gui is set to true or false, so that you can do your stuff here

local Gui = script.Parent

if Gui.Enabled == true then
    --Do stuff if the Gui is visible
else
    --Do stuff if the Gui is invisible
end

Whenever the Visible property of a GuiObject is set to false, that Object (And it’s descendants that are inside with it) all become invisible, I believe that goes for ScreenGui's as well with their Enabled property

Not sure which one you’re referring to exactly though

2 Likes

you could check if all of its Parented GUI instances are visible or not.

for example, if you have a TextButton in a Frame, which is in a ScreenGui, then you can check if either of those are visible (or enabled for the ScreenGUI) and if either of them are false, then the textbutton isnt “Truly” visible

1 Like

This would work for the specified example stated in the OP, but not as a function where there can be limitless amounts of parents, all with their Visible properties set to different values.

2 Likes

If you’re trying to check whether you want everything to be visible/invisible, I believe you can just loop through the entire Gui & its descendants to check the Object you’re searching for is a GuiObject or not

local Gui = script.Parent
local CurrentState = "Visible"

local function ToggleVisibility()
    for _, Object in pairs(Gui:GetDescendants()) do 
        if Object:IsA("GuiObject") then

            if CurrentState == "Visible" then
                Object.Visible = true

            elseif CurrentState == "Invisible" then
                Object.Visible = false
            end

        end
    end

end

ToggleVisibility()

Unless if I misunderstood your question, you’ll have to look more into this

https://developer.roblox.com/en-us/api-reference/property/GuiObject/Visible

you just have to loop through its parents

What’s your use case here? Why is your script depending on an element’s “true visibility”?

1 Like

I’ve been intermittently checking on this post for a while now, but I haven’t seen anyone submit substantial code yet…

Here’s how I would approach it. Following the concepts touched on by @letris and @John_15051, this function below loops through a given guiObject’s parents (starting from itself) until it either reaches a guiObject with a false visibility or it reaches game, implying that there were no GUI objects that triggered a stop in the loop and that all parenting GUI objects (including the passed in one), are Visible.

function checkIfTrulyVisible(guiObject)
	if not guiObject or not guiObject:IsA("GuiObject") then return false end
	local trulyVisible = true
	local currentGui = guiObject
	while currentGui ~= game and currentGui ~= nil do
		if currentGui:IsA("GuiObject") then
			if currentGui.Visible == false then
				return false
			end
		end
		currentGui = currentGui.Parent
	end
	return true
end

print(checkIfTrulyVisible(script.Parent)) -- Pass in script.Parent (which in my case is a TextButton under a set of many other GUI objects)

As @colbert2677 sort of implied, this type of function isn’t really practical. I have never run into an instance where I needed to check if any GUI object was “truly” visible- your code should be structured in a way so that this is not an issue.

Hope this helps. Let me know if you have any issues.

2 Likes

Loop through the buttons, check the parent of each button. If the parent has the Visible property, then see if it is true or false. Check if the parent of that is also a UI element. But this would take too long. I don’t think you are able to do this is in a fast way.

I’m creating a dynamic console support module that binds actions based on a prespecified gamepad KeyCode. One of the bind function parameters is the button that will be “pressed”. Let’s say that button is within a frame, for example, a “Purchase” button inside of a shop frame. That frame may be closed or opened. I only want to perform the purchase action if the button is “truly visible”.

I think I can use the logic behind @xendatro’s reply; I attempted to make something similar before posting but couldn’t get it to work that well. I’ll make an update tomorrow and reply if I have any luck.

Can you tell me why do you need this feature in the first place?

local guiObject = script.Parent
local screenGui = guiObject:FindFirstAncestorWhichIsA("ScreenGui")

if guiObject.Visible then
	if screenGui.Enabled then
		for i, guiChild in ipairs(screenGui:GetDescendants()) do
			if guiObject:IsDescendantOf(guiChild) and guiChild:IsA("GuiObject") then
				if not guiChild.Visible then
					print("The Gui object is currently not visible as the containing "..guiChild.ClassName.." instance is invisible.")
					break
				end
			end
			if i == #screenGui:GetDescendants() then
				print("The Gui object is currently visible!")
			end
		end
	else
		print("The Gui object is currently not visible as the containing ScreenGui instance is disabled.")
	end
else
	print("The Gui object is currently invisible!")
end

I believe this should do the trick. Most of the provided solutions thus far have been sub-optimal to say the least.

1 Like

Update:

Thanks to the logic behind @xendatro’s reply, I came up with a revised version. It works in my scenario so I’ll post it here and mark it as solved in case others are looking for a similar solution.

function TrulyVisible(Frame: Instance): boolean
	local screenGui = Frame:FindFirstAncestorWhichIsA("ScreenGui")

	if screenGui and screenGui.Enabled == false then
		return false
	end

	while Frame ~= screenGui or Frame ~= nil do
		if Frame:IsA("GuiObject") and Frame.Visible == false then
			return false
		end

		Frame = Frame.Parent
	end

	return true
end

For the sake of simplicity, I didn’t include any checking to see if the frame is within the screen size.

8 Likes

hello, i was thinking how does that line one work? like the colon sign is it like you can say

gui:TrulyVisible() 

?

The colons in the first line are for type checking. You can find more info about it here.

Oh wow it’s conplicated. By the way, is there a way to make functions that uses the colon sign? Kind of like part:Destroy() or instance:FindFirstChild(“randomstring”)?

yes,

local customPart = {}
function customPart:Destroy()
  some code
end
customPart:Destroy()