Quick Links: Download Gideros Studio | Gideros Documentation | Gideros community chat | DONATE
Recursively check if Sprite is (literally) visible — Gideros Forum

Recursively check if Sprite is (literally) visible

totebototebo Member
edited September 2016 in General questions
Is there a way of checking if a Sprite is visible, taking all of its parents into account? Without being able check if the final Sprite has been added to "stage", I can't seem to figure it out.

I want to use this in my Button class to avoid it triggering if it has been added to a Sprite with setVisible(false), or if it hasn't been added to the stage at all.
My Gideros games: www.totebo.com

Comments

  • totebototebo Member
    edited September 2016
    This seems to work, but feels "dirty". Is there a better/simpler/more efficient way?
    function isVisibleRecursive( sprite )
     
    	stage.__is_stage = true
     
    	local visible = false
     
    	repeat
     
    		visible = sprite:isVisible() and sprite:getParent() ~= nil
    		sprite = sprite:getParent()
     
    	until sprite == nil or sprite.__is_stage
     
    	return visible
     
    end
     
    local sprite1 = Sprite.new()
    local sprite2 = Sprite.new()
    sprite2:addChild( sprite1 )
    stage:addChild( sprite2 )
     
    print( isVisibleRecursive(sprite1) )
    My Gideros games: www.totebo.com
  • totebototebo Member
    edited September 2016
    .
    My Gideros games: www.totebo.com
  • @totebo try this from GiderosCodingEasy by ar2rsawseen
    function Sprite:isVisibleDeeply()
    	-- Answer true only if the sprite and all it's a parents are visible. Normally, isVisible() will
    	-- return true even if a sprite is actually not visible on screen by wont of one of it's parents
    	-- being made invisible.
    	--
    	local try=self
    	while (try) do
    		if  not(try:isVisible() and try:getAlpha()>0) then
    			return false
    		end
    		try = try:getParent()
    	end
    	return true
    end
    https://github.com/ar2rsawseen/GiderosCodingEasy/blob/master/GiderosCodingEasy.lua#L687
  • totebototebo Member
    edited September 2016
    Thanks @pie!

    I think that solition only checks for isVisible, and would return true even if the Sprite is not added to the stage (and thus not actually visible)?
    My Gideros games: www.totebo.com
  • Fantastic, thanks! Had missed that one.
    My Gideros games: www.totebo.com
  • totebototebo Member
    edited September 2016
    This is the final method, for reference:
    function isVisibleRecursive( sprite )
     
    	local visible = false
     
    	repeat
     
    		visible = sprite:isVisible() and stage:contains(sprite)
    		sprite = sprite:getParent()
     
    	until sprite == nil or visible == false
     
    	return visible
     
    end
     
    local sprite1 = Sprite.new()
    local sprite2 = Sprite.new()
    sprite2:addChild( sprite1 )
    stage:addChild( sprite2 )
     
    print( isVisibleRecursive(sprite1) )
    My Gideros games: www.totebo.com
  • i don't know if it would be faster to check at the beginning
    local visible=false
    if not stage:contains(sprite) then return visible end

    as this is maybe native and so perhaps faster then checking one by one all levels of the hierarchy for containment.
  • totebototebo Member
    edited September 2016
    Yeah, edited the post, check it out. It should break as soon as sprite is not visible, or stage does not contain it. If the first sprite isVisible() == false or not contained by stage, it's game over.
    My Gideros games: www.totebo.com
  • n1cken1cke Maintainer
    Accepted Answer
    function Sprite:isVisibleRecursive()
    	if self.__parent then return self:isVisible() and self.__parent:isVisibleRecursive()
    	else return self:isVisible() and stage:contains(self) end
    end

    Likes: talis, keszegh

    +1 -1 (+2 / -0 )Share on Facebook
  • keszeghkeszegh Member
    edited September 2016
    yes, but contains needs to be called only for the initial sprite, like:
    function isVisibleRecursive( sprite )
     
    	local visible = false
     if not stage:contains(sprite) then return visible end
    	repeat
     
    		visible = sprite:isVisible()
    		sprite = sprite:getParent()
     
    	until sprite == nil or visible == false
     
    	return visible
     
    end
     
    local sprite1 = Sprite.new()
    local sprite2 = Sprite.new()
    sprite2:addChild( sprite1 )
    stage:addChild( sprite2 )
     
    print( isVisibleRecursive(sprite1) )
  • Wow, that is neat. And beyond my level of efficient coding. Nice one @n1cke!
    My Gideros games: www.totebo.com
  • keszeghkeszegh Member
    edited September 2016
    @n1cke, that's neat, although my version still contains less calls to contains.
  • n1cken1cke Maintainer
    edited September 2016
    @keszegh: only one "contains" call is performed here because it is last condition to check.
  • @n1cke, you are right, my mistake. your code is most efficient.

    at the end it depends also on if one tends to set sprites to not visible. if this is less likely (like in my case), then it still may be more efficient to start with a stage:contains and then proceed with the visibility checks.
  • hgy29hgy29 Maintainer
    edited September 2016 Accepted Answer
    @totebo,
    I don't know if it will work for you but you may want to try:
     function isReallyVisible(sprite)
     local gx,gy=sprite:localToGlobal(0,0) --Assuming 0,0 is actually within the sprite
     return sprite:hitTestPoint(gx,gy,true) -- Check inside taking clip/visibility into account
     end
    +1 -1 (+2 / -0 )Share on Facebook
  • That's a cool and different solution!
    My Gideros games: www.totebo.com
Sign In or Register to comment.