I notice that when using the RenameLayer method in Python, any renamed sub-layers inherit the name of the parent layer. Is there a way to avoid this? In the following illustration, I used the RenameLayer method to change “Ringo” to “Richard”. The results are shown below.
Yes, that works here too. The problem must be related to how I am selecting the layers. What I am attempting to do is to create a find/replace tool for layer names. Here is what I have that is producing the results shown above:
import rhinoscriptsyntax as rs
def LayerFindReplace():
findText = rs.StringBox(“Enter the text to find”, None, “Layer Find/Replace”)
if findText is None:
return
else:
replaceText = rs.StringBox(“Enter the replacement text”, findText, “Layer Find/Replace”)
if replaceText is None:
return
else:
layers = rs.LayerNames()
if layers:
for layer in layers:
name = rs.LayerName(layer, False)
if findText in name:
newtext = layer.replace(findText,replaceText)
rs.RenameLayer(layer,newtext)
I did not try to run your code (might be useful next time to enclose your code with back ticks) but from what it looks like, you need to change the line:
Thank you for that link about enclosing the code. I knew there was a way to do that, but I couldn’t recall what it was. I recall Mitch mentioning it within the last couple of weeks.
Your suggestion works for me. It’s obvious now that you mentioned it. Good old hindsight!!
You may find that this errors out if you have sublayers and you change the name of a sublayer - depending on the order in which it was in the layer table… Also, if the same substring is contained in more than one level of a nested sublayer, it may not change all of the instances of that substring in the full layer name.
Layer name find/replace is complicated with sublayers because of the nesting involved.
Yeah, I wouldn’t be surprised one bit. At the time we had a department that requested this script. I don’t believe they ever use sub-layers. That’s probably why no one ever flagged this as being unreliable.
Merde, yes, I see that - OK, back to the drawing board. The recursion must be sinking into an infinite loop or something. Every time I mess with layer functions I always regret it.
I think the problem is that you have to start by renaming the top layer and then work your way down taking account of the renamed top layer. Sorting the layers by level and then getting the new name at each step solves it.
import rhinoscriptsyntax as rs
__version__ = 0.
__author__ = "Graham Knapp"
__homepage__ = "https://discourse.mcneel.com/t/renaming-a-sub-layer-with-python/14779"
def main():
old = rs.StringBox("Text to replace", None, 'Rename Layers')
if not old:
return
new = rs.StringBox("Replacement text", old, 'Rename Layers')
if not new:
return
for i_layer in sorted(rs.LayerIds(), key = lambda x: rs.LayerName(x).count("::")):
name = rs.LayerName(i_layer)
if old in name:
rs.RenameLayer(name, name.split("::")[-1].replace(old,new))
if __name__ == '__main__':
main()
I’ll take a look at your script. I have a version that works, but it doesn’t iterate indefinitely. So if there were say, 20 sub-layers deep, it wouldn’t change them all. I’d be good for 12 with my current version. For us, we would never even get close to that. But now this has become a personal challenge. I don’t like to give up!
BTW… Tobias has a very nice tool that handle finding and replacing layer names, among other things. He was generous enough to share it, and it’s probably what we will use, but like I said, I don’t give up easily.
I’m always wary of working with sublayers, for if you change a layer name that has children, it automatically changes the childrens’ full names as well. Then you might end up with “Layer does not exist in the layer table…” error message if you are iterating through a layer name list made beforehand. That’s why in most of my scripts concerning layers I start at the bottom most level and work up via recursion.
Working with layer ID’s is also a good idea as they do not change if the layer name changes. What’s not obvious from the rhinoscriptsyntax Help doc is that most all rs methods that concern layers can accept either layer names or layer ids. However, they do not generally return layer ids, only full names.
Yes, this version works well. I think you’re right about using layer ID’s instead of names. In my experiments I saw that warning “Layer does not exist in the layer table" many times. Graham’s solution also uses layer ID’s.
A non-recursive approach (that might be relevant here) is to get all the layer names, sort these by depth, and then iterate over this list of names (and rename/delete layers etc).
Edit: I think this is what @Dancergraham already suggested above. As you were