Trying to create an extension 'Tag Folder Visibility' to hide and show specific tag folders

Oh - I see now. The scenario I would usually not want is to switch the layer and then begin adding tagged geometry. But bringing a component in from the Component Panel with an alternate Tag/Layer set as current tags the component. I did not know that.

Do you know what the difference is between toggling the visibility of Tags and toggling the visibility of Groups/Components in the Outliner vs. Fade rest of model → Hide? Everything else is not hidden in the Outliner and their visibility toggle status appears active.

I also tested by selecting a component and then selecting View Hidden Objects. That doesn’t make the hidden groups/components appear.

I did another test by creating Dummy Tag, a tag that is not in any folder. I set it as current. When I toggle the visibility of Untagged, all of the groups/components in the model space have their visibility toggled. But they are also dimmed in the Outliner - which is not their behavior when Untagged is current and any other tag or tag layer is current (normally their display is dimmed when visibility toggling is performed in the Outliner).

1 Like

This does not display objects assigned to tags that are switched off.
But does not change their individual visibility property.
It is just a display override.

This does change their individual visibility property for what is changed in Outliner.

This does not display objects outside the current edit context.
But does not change their individual visibility property.
It is just a display override.

I think TIG has a plugin that uses observer(s) to watch things and if it is active and the user tries to add primitive geometry it either pops up a warning or automatically switches back to the “Untagged” layer.

It is likely hosted over at SketchUcation.

If you are within an edit context of a group / component, and Fade Rest → Hide is checked, then anything outside the context is not displayed whether View > Show Hidden Objects is on or not.

But anything within the edit context or nested below it that is hidden, will show as dashed edges and faces when View > Show Hidden Objects is on.

I think that there was another recent questioning of this being strange or perhaps a bug.

We would think that, if all the primitive geometry was assigned to “Untagged” and if it’s parent instance was assigned to a visible tag, … that if we switched off “Untagged” then all the primitive edges and faces would not be displayed.

But, this is not the case and it has worked like this since at least 2017.

1 Like

I have some reading to do…

I don’t know. My brain is still looping on why I’d want to move the pencil from Untagged to make anything else the active layer.

Drafsmen today, maybe in the past also, have to be very disciplined. Mistakes are unavoidable, though. Even though we teach people -always- to draw raw geometry untagged, my experience is that Sketchup is fairly forgiving.

What I’m trying to express is that it seems very natural to move from a general state to a specific state and then to be able to return to this former general state. Which TIG’s method does very well.

Our simple human minds seem to be able to follow this quite easily.

I can’t replicate this. What I see is when ever a tag is hidden the groups with that tag are dimmed in the outliner, regardless of the current tag.

afaik Sketchups default behaviour has always been that untagged geometry (on ‘Layer 0’) gets hidden when untagged gets hidden, unless it’s in a tagged group (on another ‘layer’). This is what makes untagged different from tagged. The qualities of untagged elements ‘are attributed’ to those of it’s parent group tag (I hope I’m frasing this correctly).

Okay, I see what you mean. I did not state that correctly. They are not dimmed if inside of untagged groups. What I did was to have tagged groups/components inside of untagged top-level groups (because I was using color by tag - a separate issue). The other way is to have the tags for groups/components inside of tag folders.

Not dimmed via folder visibility: untagged top level, tags in folders:

Dimmed via untagged: untagged top level, tags in folders, Dummy Tag current layer:

I guess I hadn’t changed the current layer from Untagged enough to realize that Untagged is like a tag itself.

Please avoid using the term “on layer” as layers (tags) are not geometric collections. They are simply display property sets used by the display engine that can be shared by multiple objects. So geometric objects have a tag (layer) property that are assigned to point at a layer object or nil.

Yes, you phrased it correctly. It is similar to how nested faces that are unpainted with materials (i.e., equal to nil,) are displayed using their parent instance’s material (if assigned.)

1 Like

Here’s a version that toggle’s folders ‘below’, although at first site it might work contrary to what one would expect. It’s not completely foolproof yet either, because it can’t hide all folders as was demonstrated in version 0.0.8.

It is, I think, a way to swifty be able to approach nested geometry without using the outliner (haven’t tested it yet, though).

Edit: this now works regardless whether the active tag is in a folder or not.

module SUForum
  module FolderVisibility
    extend self
    VERSION ||= "0.3.1"
    MENU ||= "View"

    def all_folders(folders = [], root_folder = Sketchup.active_model.active_layer.parent)
      root_folder.each_folder do |folder|
        folders << folder
        all_folders(folders, folder)
      end
      folders
    end
    
    def toggle_tags(state)
      model = Sketchup.active_model
      active_tag = model.active_layer

      model.layers.each { |tag| tag.visible = state unless tag == active_tag }
    end
    
    #based on: https://community.sketchucation.com/post/1323194
    def toggle_folders()
        model = Sketchup.active_model
        
        model.start_operation("Toggle Floders", true)
        unless @visible and @visible[0] ### hide and remember
          @visible=[]
          all_folders.each{|e| @visible << e if e.visible?}
          @visible.each{ |e| e.visible=false } if @visible[0]
          state = @visible[0] ? 'invisible' : 'no previous selection'
        else ### show and forget
          @visible.each{ |e| e.visible=true if e.valid? }
          @visible = []
          state = 'visible'
        end
        model.commit_operation
        puts state
  end
  
  unless defined?(@ui_loaded)
      add_separator_to_menu(MENU)
      menu = UI.menu(MENU).add_item("Toggle Folders") { toggle_folders() }
      
      @ui_loaded = true
    end
  end
end

1 Like

For who ever might be interested. Some more tweaking in this version 0.4.0. This is -sort of- starting to work the way I was hoping, I think.

Toggling all folders below isn’t working yet (?) in this update.

Hide and Show Tags are separate menu items and Toggle Folders now works regardless whether the parent is a folder or the layer manager.

I might turn it into a real extension one of these days.

module SUForum
  module FolderVisibility
    extend self
    VERSION ||= "0.4.0"
    MENU ||= "View"

    def folders_below ( folders = [], active_layer = Sketchup.active_model.active_layer )
        active_folder = active_layer.folder
        active_parent = active_layer.parent
        root = []
        
        unless active_parent and active_folder
        active_parent.each_folder { |folder| folders << folder }
        root << folders
        
        else
        active_folder.each_folder { |folder| folders << folder }
        root << folders
        end
        folders
    end
    
    def toggle_tags(state)
      model = Sketchup.active_model
      active_tag = model.active_layer

      model.layers.each { |tag| tag.visible = state unless tag == active_tag }
    end
    
    #based on: https://community.sketchucation.com/post/1323194
    def toggle_folders()
        model = Sketchup.active_model
        
        model.start_operation("Toggle Folders", true)
        unless @visible and @visible[0] ### hide and remember
          @visible=[]
          folders_below.each{|e| @visible << e if e.visible?}
          @visible.each{ |e| e.visible=false } if @visible[0]
          state = @visible[0] ? 'invisible' : 'no previous selection'
        else ### show and forget
          @visible.each{ |e| e.visible=true if e.valid? }
          @visible = []
          state = 'visible'
        end
        model.commit_operation
        puts state
  end
  
  unless defined?(@ui_loaded)
      add_separator_to_menu(MENU)
      menu = UI.menu(MENU).add_item("Toggle Folders") { toggle_folders() }
      menu = UI.menu(MENU).add_submenu("Tag Visibility")
      menu.add_item("Hide Tags") { toggle_tags(false) }
      menu.add_item("Show Tags") { toggle_tags(true) }
      
      @ui_loaded = true
    end
  end
end

1 Like

Here is a new version. Hiding folders below now hides all folders below. There are a bunch of options in this script, which is a reason not to turn this into an extension right now (without creating a proper UI). It would only complicate things.

It can hide all tags :slightly_smiling_face: And a bunch of other options were added.

Any questions, remarks, suggestions for improvement or constuctive commentary I’d appreciate. Is it worthwhile to turn this into a Sketchup extension??

module SUForum
  module FolderVisibility
    extend self
    VERSION ||= "0.5.0"
    MENU ||= "View"
    
    #This software is offered to you for free, as is.
    #NO LIABILITY WHAT SO EVER is taken for the consequences of the use of this software.
    #It's largely based on methods that have been made public on the Sketchup Forum and
    #Sketchucation. These resources are mentioned above each method.
    #Special thanks go to those providing them and those who gave me some expert advise
    #on writing my first lines of Ruby code.

    def folders_below(folders = [], a_f = Sketchup.active_model.active_layer.folder )
        a_p = Sketchup.active_model.layers
        
        if a_f # collects folders below the parent folder of the active tag
        a_f.each_folder { |folder|
                folders << folder
                folders_below(folders, folder)
                }
        elsif # collects folders below when the active tag is at the top level
        a_p.each_folder { |folder|
                folders << folder
                folders_below(folders, folder)
                }
        end
        folders
    end

    # puts folders_below
    
    # method by Dezmo
    def all_folders(folders = [], root_folder = Sketchup.active_model.layers)
      root_folder.each_folder do |folder|
        folders << folder
        all_folders(folders, folder)
      end
      folders
    end
    
    # puts all_folders
    
    def toggle_folders(state) # shows or hides all folders below ## optionally you can replace folders_below by all_folders
        model = Sketchup.active_model
      
          model.start_operation(" Toggle Folders Below ", true) # enter menu name
          folders_below.each { |f| f.visible = state }
          model.commit_operation
    end
    
    # method by 3DxJFD
    def toggle_tags(state) # collects all tags except the active tag
      model = Sketchup.active_model
      active_tag = model.active_layer
      
      model.start_operation("Tag Visibility")
      model.layers.each { |tag| tag.visible = state unless tag == active_tag }
      model.commit_operation
    end
    
    # based on TIG's method here: https://community.sketchucation.com/post/1323194
    def hide_below()
        model = Sketchup.active_model
        
        model.start_operation("Toggle Visible Below", true)
        unless @visible and @visible[0] ### hide and remember
          @visible=[]
          folders_below.each{|e| @visible << e if e.visible?} ## optionally folders_below can be replaced by all_folders
          @visible.each{ |e| e.visible=false } if @visible[0]
          state = @visible[0] ? 'invisible' : 'no previous selection'
        else ### show and forget
          @visible.each{ |e| e.visible=true if e.valid? }
          @visible = []
          state = 'visible'
        end
        model.commit_operation
        puts state
  end
  
  def forget_hidden()
      model = Sketchup.active_model
      
      model.start_operation("Toggle Visible Below", true)
      if @visible and @visible[0] ### hide and remember
        @visible=[]
        folders_below.each{|e| @visible << e if e.visible?} ## optionally folders_below can be replaced by all_folders
        @visible.each{ |e| e.visible=false } if @visible[0]
        state = @visible[0] ? 'invisible' : 'no previous selection'

      end
      model.commit_operation
      puts state
end
  
  unless defined?(@ui_loaded)
      add_separator_to_menu(MENU)
      #menu = UI.menu(MENU).add_item("Toggle Folders") { toggles_folders() }
      menu = UI.menu(MENU).add_submenu("Folder Visibility")
      menu.add_item("Toggle to Hide Below") { hide_below() }
      menu.add_item("Forget Latest Visible") { forget_hidden() }
      #menu = UI.menu(MENU).add_submenu("Toggle Folders Below") ## optional, toggle hide / show collected
      menu.add_item("Hide Below") { toggle_folders(false) }
      menu.add_item("Show Below") { toggle_folders(true) }
      menu = UI.menu(MENU).add_submenu("Tag Visibility")
      menu.add_item("Hide Tags") { toggle_tags(false) }
      menu.add_item("Show Tags") { toggle_tags(true) }
      
      @ui_loaded = true
    end
  end
end

Maybe Show/Hide isn’t needed and just Toggle for folders?

Basic Html Dialog works in SU '22 but Show/Hide Tags does not in '24. Maybe same deal for tags: just toggle?

Previous deleted comment!

I’m pretty familiar with behaviorism but I’m more of an ethologist.

1 Like

Thanks 3DxJFD. This needs more study.

1 Like

The second method to find the hierarchy path to the active folder reveals its parent folder. That’s interesting.

 def parents_path( a_l = Sketchup.active_model.active_layer)
      current = a_l.folder
      path = []
      
      while current
        path.unshift(current)
        current = current.folder if current.respond_to?(:folder)
      end
      path
    end

def parent_folder(parent = [])
    parent = parents_path.first()
end

puts parent_folder

I (being also a genealogist) would not have called the first folder the “parent”.
I would call it the progenitor folder or root folder.

1 Like

I believe I’m revering to this:

I’m not sure what to make of the above so I’ll just give another version:


def ancestors_path(layer = Sketchup.active_model.active_layer)
  current = layer.folder
  ancestors = []

  while current
    ancestors.unshift(current) # Add to the beginning to create a root-to-parent order
    current = current.folder if current.respond_to?(:folder)
  end
  ancestors
end

# Retrieves the direct parent of the given layer.
def parent_folder(layer = Sketchup.active_model.active_layer)
  layer.folder || "No parent found"
end

# Retrieves the root ancestor of the given layer.
def root_ancestor(layer = Sketchup.active_model.active_layer)
  ancestors = ancestors_path(layer)
  ancestors.first || "No root ancestor found"
end

puts "Parent Folder: #{parent_folder}"
puts "Root Ancestor: #{root_ancestor}"

Even more family-friendly (but maybe not ‘technically’ correct):


def ancestors_path(layer = Sketchup.active_model.active_layer)
  current = layer.folder
  ancestors = []

  while current
    ancestors.unshift(current) 
    current = current.folder if current.respond_to?(:folder)
  end
  ancestors
end

# Retrieves the immediate parent of the layer.
def parent_folder(layer = Sketchup.active_model.active_layer)
  layer.folder || "No parent found"
end

# Retrieves the grandparents (parent of the parent folder).
def grandparents_folder(layer = Sketchup.active_model.active_layer)
  parent = layer.folder
  parent.respond_to?(:folder) ? parent.folder : "No grandparents found"
end

# Retrieves the aunts and uncles (siblings of the parent folder).
def aunts_and_uncles(layer = Sketchup.active_model.active_layer)
  parent = layer.folder
  if parent && parent.respond_to?(:folder)
    grandparent = parent.folder
    if grandparent.respond_to?(:folders)
      grandparent.folders - [parent] 
    else
      "No aunts and uncles found"
    end
  else
    "No aunts and uncles found"
  end
end

# Retrieves the cousins (siblings of the layer).
def cousins(layer = Sketchup.active_model.active_layer)
  parent = layer.folder
  if parent && parent.respond_to?(:layers)
    parent.layers - [layer] 
  else
    "No cousins found"
  end
end

puts "Parent Folder: #{parent_folder}"
puts "Grandparents Folder: #{grandparents_folder}"
puts "Aunts and Uncles: #{aunts_and_uncles}"
puts "Cousins: #{cousins}"


The above may not have been particularly useful… but Happy New Year to you! Thanks for the interest, discussions, and advice.

2 Likes

I didn’t really mean any base criticism of what you had produced previously.
Just made an observation of the naming of the “basemost” ancestral folder.

The definition of “parent” is the first direct ancestor (the previous generation) from which the “offspring” was produced.
The sire (father) or the dam (mother).

parent_folder = current.folder
3 Likes