Hi, I use a template for all my models which has +150 layers, but frequently I only need say 10 in each actual model. Once the model is built, I can filter the layers that are visible in the Layers Panel by >Layers with Objects. Before the model is built I can use Filter > Selected Layers or any of the other objects. However, none of these options are satisfactory as scrolling through the list to shift click and filter at the start is annoying.
So, I started prepping an Eto,Forms / python script that is populated with all the layers in the file, each with a check box. I would like to be able to check the layers that I want visible, and press a button to act as a proxy or replicate the process of shift clicking a bunch of layers and filter the layers panel by selected layers. Is this possible? I’ve seen reference that this part of Rhino is not accessible via the API. Is this correct? Can you think of a workaround?
Many thanks Dale, I really appreciate the response. I looked at the code you signposted to but couldn’t figure how to integrate it into my existing code. Full disclosure here - I’m a novice in the scripting department and get ChatGPT to do all the heavy lifting, but in this instance I couldn’t get it to integrate your functionality into this context.
I have an Eto.forms dialog with a checkboxlist. Each of the list items is the name of a layer in the file. Layers that are checked are kept on when the Apply button is pressed. Unchecked layers are turned off when apply is pressed. I then have to manually filter the layers visible in the UI by by showing On layers only. This isn’t a big hassle, but it would be awesome to integrate this into the script. I’ve copied the code below in it’s entirety.
If anyone has any pointers, I’d really appreciate it.
#! python 2
import Rhino
import Eto.Forms as forms
import Eto.Drawing as drawing
import scriptcontext as sc
#This turns on / off layers according to the checkbox status. The next stage is to explore if this
information can be used to automatically run the layer filter in the UI?>
## also needs adjusted to sort the layers maybe?
# Create a class for the dialog
class LayerListDialog(forms.Dialog[bool]):
def __init__(self):
# Initialize the dialog
self.Title = "Layer List"
self.ClientSize = drawing.Size(400, 1000)
self.Padding = drawing.Padding(10)
self.Resizable = True
# Dictionary to store checkboxes for each layer
self.layer_checkboxes = {}
# Create a scrollable container
self.scrollable = forms.Scrollable()
self.scrollable.Content = self.create_layer_table()
# Add the scrollable container to the dialog layout
layout = forms.DynamicLayout()
layout.AddRow(self.scrollable)
layout.Add(None) # Add a spacer
# Create a grid layout for the buttons
button_layout = forms.TableLayout(Spacing=drawing.Size(10, 10), Padding=drawing.Padding(10))
button_layout.Rows.Add(forms.TableRow()) # Add an empty row at the top
# Create the Apply button
self.ApplyButton = forms.Button(Text="Apply")
self.ApplyButton.Click += self.on_apply_button_click
self.ApplyButton.Size = drawing.Size(80, 30)
# Create the Close button
self.CloseButton = forms.Button(Text="Close")
self.CloseButton.Click += self.on_ok_button_click
self.CloseButton.Size = drawing.Size(80, 30)
# Create the Check All button
self.CheckAllButton = forms.Button(Text="Check All")
self.CheckAllButton.Click += self.on_check_all_button_click
self.CheckAllButton.Size = drawing.Size(80, 30)
# Create the Uncheck All button
self.UncheckAllButton = forms.Button(Text="Clear All")
self.UncheckAllButton.Click += self.on_uncheck_all_button_click
self.UncheckAllButton.Size = drawing.Size(80, 30)
# Add buttons in the new layout
button_layout.Rows.Add(forms.TableRow(self.CheckAllButton, self.ApplyButton))
button_layout.Rows.Add(forms.TableRow(self.UncheckAllButton, self.CloseButton))
# Add buttons to the layout underneath the scrollable container
layout.AddRow(button_layout)
# Set the dialog content
self.Content = layout
# Adjust the scrollable container dynamically when resized
self.SizeChanged += self.on_size_changed
def create_layer_table(self):
# Create a table layout to hold the checkboxes and layer names
layer_table = forms.TableLayout()
layer_table.Spacing = drawing.Size(5, 5)
layer_table.Padding = drawing.Padding(5)
layer_table.Rows.Add(forms.TableRow()) # Add an empty row at the top
# Add each layer with a checkbox
for layer in sc.doc.Layers:
if not layer.IsDeleted:
checkbox = forms.CheckBox()
checkbox.Checked = layer.IsVisible
self.layer_checkboxes[layer.Id] = checkbox
label = forms.Label(Text=layer.FullPath)
row = forms.TableRow(checkbox, label)
layer_table.Rows.Add(row)
layer_table.Rows.Add(forms.TableRow()) # Add an empty row at the bottom
return layer_table
def on_size_changed(self, sender, e):
# Update the scrollable container size when the dialog size changes
self.scrollable.Width = self.ClientSize.Width - 20
self.scrollable.Height = self.ClientSize.Height - 150 # Adjust height to make space for buttons
def on_ok_button_click(self, sender, e):
# Close the dialog when Close is clicked
self.Close(True)
def on_apply_button_click(self, sender, e):
# Set the visibility of layers based on checkbox states
for layer_id, checkbox in self.layer_checkboxes.items():
layer = sc.doc.Layers.FindId(layer_id)
if layer is not None:
layer.IsVisible = checkbox.Checked
layer.CommitChanges() # Apply the change to the document
# Redraw the document to reflect changes
sc.doc.Views.Redraw()
def on_uncheck_all_button_click(self, sender, e):
# Uncheck all checkboxes
for checkbox in self.layer_checkboxes.values():
checkbox.Checked = False
def on_check_all_button_click(self, sender, e):
# Check all checkboxes
for checkbox in self.layer_checkboxes.values():
checkbox.Checked = True
# Show the dialog
def show_layer_list_dialog():
dialog = LayerListDialog()
dialog.ShowModal(Rhino.UI.RhinoEtoApp.MainWindow)
# Run the function to show the dialog
if __name__ == "__main__":
show_layer_list_dialog()
#! python 2
import Rhino
import rhinoscriptsyntax as rs
import scriptcontext as sc
def main():
if sc.doc.Layers.Count <= 1:
print("More than 1 layer required.")
return
items = []
for layer in sc.doc.Layers:
if layer.IsDeleted:
continue
if layer.Index == sc.doc.Layers.CurrentLayerIndex:
continue
items.append([layer.Name, layer.IsVisibleInUserInterface])
title = 'Show/Hide Layers'
message = 'Check to show, uncheck to hide:'
rc = rs.CheckListBox(items, message, title)
if not rc:
return
for item in rc:
name = item[0]
layer = sc.doc.Layers.FindName(name)
if layer:
state = item[1]
if layer.IsVisibleInUserInterface != state:
layer.IsVisibleInUserInterface = state
layer.CommitChanges()
# Redraw the layers panel
sc.doc.Views.EnableRedraw(True, True, True)
if __name__ == "__main__":
main()