Keyboard Shortcuts to Conditionally Collapse/Expand Layers

Is it possible to create a keyboard shortcut that will Expand All Layers in the Layers Menu? Also one for Collapse All Layers?

Regards,
Terry.

Hi Terry- not directly that I know of but a macro using this python will do it, if that helps:

import scriptcontext as sc

for layer in sc.doc.Layers:
    layer.IsExpanded=True

for example

_-RunPythonScript (
import scriptcontext as sc

for layer in sc.doc.Layers:
    layer.IsExpanded=False
)

Does that help?

-Pascal

On a similar note, I kind of use the layers panel like a feature tree and sometimes it gets a bit bloated and long. Is there a way to collapse all layers except the currently active or currently selected layer(s)?

Pascal :man_lifting_weights:,

This works fine.

ExpandAllLayers is stored in my Scripts directory and contains:

from scriptcontext import doc
doc.Views.RedrawEnabled = False
for layer in doc.Layers:
    layer.IsExpanded = True
doc.Views.RedrawEnabled = True

while CollapseAllLayers contains:

from scriptcontext import doc
doc.Views.RedrawEnabled = False
for layer in doc.Layers:
    layer.IsExpanded = False
doc.Views.RedrawEnabled = True

ExpandAllLayers.py (148 Bytes)
CollapseAllLayers.py (149 Bytes)

My keyboard shortcuts now look like:

Thanks for the quick response. :rocket:

Regards,
Terry.
:grinning:

How does Rhino determine if the layer you want to keep open is the Currently Active or Selected Layer? Do you want to collapse all layers with no Visible layers selected? The following script will do that. I stored it in my Scripts folder as CollapseNotVisibleLayers.

from scriptcontext import doc
doc.Views.RedrawEnabled = False
for layer in doc.Layers:
	if not layer.IsVisible:
		layer.IsExpanded = False
doc.Views.RedrawEnabled = True

Here is a file for this:
CollapseNotVisibleLayers.py (176 Bytes)

And my keyboard shortcuts now look like this:

Here is one example of my Layers menu before pushing F8:


and here it is after:

Regards,
Terry.

1 Like

Hi Terry,

Thanks for sharing! Actually that’s even better than what I was imagining.

Your implementation made me realize that I only select layers that I would want to work on, which are usually the only layers visible with all others hidden.

The reason I made the distinction between currently active or selected layers was just to provide two separate options, so I wouldn’t want a script that would have to make that distinction.

And in retrospect, collapsing all but the active layer would actually be counterproductive since I’m often working on multiple interdependent layers, so I wouldn’t want those collapsed anyway.

But a script that could collapse all but the selected layers (and I guess their parent layers for it to work?) would be nice.

If the selected layer is the one highlighted in Blue, what is an active layer? How can it be detected? Is an active layer one with objects or one which is expanded?

I see that Rhino recognizes a Current layer which is the one with the check mark in the Current column.

So far I have not found a way to detect a layer highlighted in Blue.

Oh a simple misunderstanding then: by active layer, I meant what you refer to as the current layer, which is probably the more suitable way to refer to it as.

As for the selected layer highlighted in blue, that’s unfortunate, maybe Rhino devs could expose it in RhinoCommon?

Vince,

Here is a script that collapses all layers except the current layer.

from scriptcontext import doc
doc.Views.RedrawEnabled = False
# Get full name of current layer.
current_name = doc.Layers.CurrentLayer.FullPath
# Collapse layers that do not share part of current layer full name.
for layer in doc.Layers:
	full_path = layer.FullPath
	if full_path:
		# Collapse layer if its name is not in the beginning of current's.
		if current_name.find(full_path) != 0:
			layer.IsExpanded = False
		# If layer name is in the beggining of current's, do more checks.
		else:
			lc = len(current_name)
			lf = len(full_path)
			# If layer name is the same length as current's or
			# it fills a hierarchy of current, then do not collapse it.
			if not (lf == lc or (lc > lf and current_name[lf] == ":")):
				layer.IsExpanded = False
doc.Views.RedrawEnabled = True

Here is a file for this:
CollapseNotCurrentLayers.py (801 Bytes)

Regards,
Terry.

You can get a list of selected layers, here is a sample code:

import Rhino
import rhinoscriptsyntax as rs
selectedLayers = Rhino.RhinoDoc.ActiveDoc.Layers.GetSelected() # get the currently selected layers
for l in selectedLayers[1]: # array of indices of selected layers
    lname = Rhino.RhinoDoc.ActiveDoc.Layers.FindIndex(l) # use index to find layername
    print lname.Name #layername property

Maybe it can be implemented to help with not collapsing the selected layers as well in your case.

Hi Terry - the LayerTable can help-
https://developer.rhino3d.com/api/rhinocommon/rhino.docobjects.tables.layertable/getselected
Ooops, too late.
-Pascal

@Jarek and @pascal,

Thanks for the help.

Here is a script that will collapse all but the selected layers (layers highlighted in Blue):

from scriptcontext import doc
doc.Views.RedrawEnabled = False
# Get the currently selected layers
selectedLayers = doc.Layers.GetSelected()
# Get full name for all layers.
names = [layer.FullPath for layer in doc.Layers]
# Get full name of selected layers.
selected_names = [names[l] for l in selectedLayers[1]]
# Collect index of layers that share part of selected layer name.
i = 0; ok = set()
for full_path in names:
	if full_path:
		for selected_name in selected_names:
			if selected_name.find(full_path) == 0:
				ls = len(selected_name); lf = len(full_path)
				if lf == ls or (ls > lf and selected_name[lf] == ":"):
					ok.add(i)
	i += 1
# Collapse layers that do not share part of selected layer name.
for j in range(i):
	if j not in ok: doc.Layers[j].IsExpanded = False
doc.Views.RedrawEnabled = True

Here is a file for this:
CollapseNotSelectedLayers.py (834 Bytes)

Here is a sample .3dm file you can use to exercise the script:
SeveralLayers.3dm (4.1 MB)

Here is an example using the sample file.

Regards,
Terry.

1 Like