Give this a try:
- 1. Make a new toolbar button.
2. SHIFT+right-click the new button to edit its commands.
3. Paste the following script into the command for one of the mouse buttons:
Code: Select all_NoEcho
-_RunPythonScript (
import Rhino
import rhinoscriptsyntax as rs
import System.Windows.Forms
import re
def LayersAndMaterials():
by_layer = rs.GetString('List Style', 'ByLayer', ['ByLayer', 'ByMaterial'])
if by_layer is None or by_layer == '': return 0
by_layer = by_layer == 'ByLayer'
filter = rs.GetString('Filter', 'none')
if filter is None or filter == '': return 0
if filter == 'none': filter = ''
replace = 'Yes'
if filter != '':
replace = rs.GetString('Remove filter?', 'Yes', ['Yes', 'No'])
if replace == None: return 0
replace = replace == 'Yes'
map = {}
doc = Rhino.RhinoDoc.ActiveDoc
for layer in doc.Layers:
idx = layer.RenderMaterialIndex
mat = doc.Materials[idx]
matName = 'default'
layerName = layer.Name
if mat != None: matName = mat.Name
if matName == '': matName = '<unnamed>'
if by_layer:
if filter == '':
map[layerName] = matName
elif re.search(filter, layerName):
if replace:
replaced = re.sub(filter, '', layerName)
if replaced != '':
layerName = replaced
map[layerName] = matName
else:
if filter == '':
if map.get(matName) is None:
map[matName] = []
map[matName].append(layerName)
elif re.search(filter, matName):
if replace:
replaced = re.sub(filter, '', matName)
if replaced != '':
matName = replaced
if map.get(matName) is None:
map[matName] = []
map[matName].append(layerName)
out = ''
if by_layer:
for pair in sorted(map.items()):
out += pair[0] + ': ' + pair[1] + '\n'
else:
for pair in sorted(map.items()):
out += pair[0] + ': \n'
for value in pair[1]:
out += ' ' + value + '\n'
if out == '':
if by_layer:
print 'No matching layers were found.'
else:
print 'No matching materials were found.'
else:
out = out.rstrip()
System.Windows.Forms.Clipboard.SetText(out)
print '------------------------------------------------------'
print 'The following list has been copied to the clipboard:'
print '------------------------------------------------------'
print out
print '------------------------------------------------------'
return 0
LayersAndMaterials()
)
Take care to copy it exactly, since it is written in python, in which the indentation of the code is significant.
When you run it, it will first prompt for whether you'd like to categorize materials by layer, or layers by material. It will then prompt for a filter, which will be used to match characters in the material or layer names. Leaving the filter set to 'none' (meaning, just hitting Enter to get past it) will cause all names to be included. Once built, the final list will be printed to the console, and copied to the clipboard.
[edit: updated to add an option for removing the filter string from names in the output list.]
The filter is searched using regular expressions, so it's not limited to matching just the ends of names, and you could get pretty fancy with it if you wanted to. Just for example, if you had five layers named
Layer 01,
Layer 02,
Layer 03,
Layer 04, and
Layer 05, you could select the second and the fourth using the filter:
0[24], which matches occurrences of a zero, followed by either a 2 or a 4. The filter
\s0[0-9], which matches a space followed by a digit, would match all five. Were the second one named
Layer x02, and the third
Layer X03, you could pick them from the list using
\s[a-zA-Z], which matches a space followed by a letter, either lower or upper case. A simple
Layer or
aye filter would match all of these examples.
So that's the general idea; if necessary, you can find more information by searching for regex (regular expression); you can find lots of tutorials and free programs available for playing around with patterns.