Renaming issues in selecting of child items

Hi all, I am doing a simple renaming application but I am encountering a few problems, hopefully someone may point it out to me so that I can revise my code.

Okay, the code below shows a part of my renaming process in which in the searchReplace, it is working fine if the user are selecting a single/ multiple items manually.

However, I have also implemented a selectHierarchy button (as shown in the code) which selects the children. For example:
Group 1
-> pCube1
–> pCone1

So if user selects pCube1 and hit the button, it will selects its child item, pCone1 in this case.

But when I tried to run the searchReplace function, say I am going to replace ‘p’ with ‘test’, it only renames the first item - pCube1 to testCube1 while not doing the same for the child item as it still remains as pCone1 and I also got the following error: # RuntimeError: No object matches name #

I think I may have missed out something in the selectHierarchy function or something… Any ideas?

By the way, I have a side question too. Is it wise to have all my defining function, def() to have cmds.ls(sl=True) in each and every one of them?
Other than the tedios task of typing them the same over and over again, but will it cause any adverse effects? Or will it be okay to leave it as it is since the whole code is able to run without any problems?


def searchReplace(self):
        wordSearch = str(self.searchTxt.text())
        wordReplace = str(self.replaceTxt.text())

        objCnt = cmds.ls(sl=True, sn=True)

        if len(objCnt) == 0:
            self.searchTxt.clear()
            self.replaceTxt.clear()
            cmds.warning('Nothing is selected')
        else:
            for wordString in objCnt:
                if wordSearch in wordString:
                    newWordString = wordString.replace(wordSearch, wordReplace)
                    cmds.rename(wordString, newWordString)
                    self.searchTxt.clear()
                    self.replaceTxt.clear()
                    print '%s' %wordString + " has changed to : " + "%s" %newWordString

def selectHierarchy(self):
        sel = cmds.ls(selection = True)
        selCnt = len(sel)
        
        if int(selCnt) != 0:
            objHierarchy = cmds.select(hi=True)
        else:
            cmds.warning('Nothing is selected')

You’re getting the error because you are trying to rename something that Maya can’t find anymore because when you change a parent’s name, you also change the DAGPath for any subsequent children.

For instance, let’s take your example of pCube1 and pCone1

group1

  • pCube1
    – pCone1

The full DAGPaths for the cube and the cone would be
ex. 1

group1|pCube1
group1|pCube1|pCone1

Now here’s the thing, when you do a rename using cmds.rename, you modifiy the DAGPath of the affected nodes. So if you were to rename pCube1 to testCube1 the full DAGPath for both the cube and the cone become
ex. 2

group1|testCube1
group1|testCube1|pCone1

In your code, you get a list of the nodes you want to rename before you rename them (ex. 1).
When you rename the first item (pCube1 -> testCube1), the DAGPath of it’s child (pCone1) is changed (ex. 2), but when you try to rename pCone1 using the path you stored earlier Maya can’t find it anymore since that node’s DAGPath changed when you renamed it’s parent.
ie. You’re trying to rename group1|pCube1|pCone1 when it’s correct path at that point is group1|testCube1|pCone1

So you can try looping backwards or reversing the list so you rename the children first and work your way up, or use a dynamic iteration where you keep looping through a current object and it’s children until no more children can be found.

[QUOTE=Maph;24145]You’re getting the error because you are trying to rename something that Maya can’t find anymore because when you change a parent’s name, you also change the DAGPath for any subsequent children.

For instance, let’s take your example of pCube1 and pCone1

The full DAGPaths for the cube and the cone would be
ex. 1

Now here’s the thing, when you do a rename using cmds.rename, you modifiy the DAGPath of the affected nodes. So if you were to rename pCube1 to testCube1 the full DAGPath for both the cube and the cone become
ex. 2

In your code, you get a list of the nodes you want to rename before you rename them (ex. 1).
When you rename the first item (pCube1 -> testCube1), the DAGPath of it’s child (pCone1) is changed (ex. 2), but when you try to rename pCone1 using the path you stored earlier Maya can’t find it anymore since that node’s DAGPath changed when you renamed it’s parent.
ie. You’re trying to rename group1|pCube1|pCone1 when it’s correct path at that point is group1|testCube1|pCone1

So you can try looping backwards or reversing the list so you rename the children first and work your way up, or use a dynamic iteration where you keep looping through a current object and it’s children until no more children can be found.[/QUOTE]

Hi Maph, thanks for getting back to me. I love your explaination and I can understand why my code ain’t working when it comes to renaming to the last children/ object…

While I am trying out other ways, I found out that if I simply changed and edit some codes in my selectHierarchy, surprisingly it works. It rectifies the problem that I have as I have posted. But even so, is this pratical? Additonally, are there any documentations that shows what elements are having the type =transform?

sel = cmds.ls(sl=True)
cmds.listRelatives(ad=True, type='transform', fullPath=True)
cmds.select(sel, objHierarchy)

By the way, regarding your suggestion on renaming the children first and working it up, this is a rather interesting, for me at least…
Can you show me a simple example of how it works? I totally have no idea that it could be coded in this manner.

Many thanks in advance!

Well, if you’re using listRelatives with the ad (allDescendents) flag you actually get a list which is in reverse order. :wink:
So when you iterate through that list, the first item will be last child in the entire hierarchy chain, and the last item will be the top most parent node.

If you want to use cmds.select, try doing the following


rootNode = cmds.ls(sl=True)[0]
cmds.select(rootNode, hi=True, replace = True)
transforms = cmds.ls(selection=True, type="transform")
transforms.reverse()

for t in transform:
         cmds.rename(t, "newName")

reverse is a method you can call on every python list out there. It modifies the original list, so keep that in mind.

For the transform type. Any type of Maya object that you can move is a transform. :slight_smile:

[QUOTE=Maph;24149]Well, if you’re using listRelatives with the ad (allDescendents) flag you actually get a list which is in reverse order. :wink:
So when you iterate through that list, the first item will be last child in the entire hierarchy chain, and the last item will be the top most parent node.

If you want to use cmds.select, try doing the following




rootNode = cmds.ls(sl=True)[0]
cmds.select(rootNode, hi=True, replace = True)
transforms = cmds.ls(selection=True, type="transform")
transforms.reverse()

for t in transform:
         cmds.rename(t, "newName")

reverse is a method you can call on every python list out there. It modifies the original list, so keep that in mind.

For the transform type. Any type of Maya object that you can move is a transform. :)[/QUOTE]

Hi Maph, thanks for getting back to me as well as the coding as an alternative solution :slight_smile:
By the way, just to let you know that there is a small typo error in the ‘for’ function, where it should be transforms and not transform, in any event if anyone is coming across this thread :slight_smile:

Nonetheless, initially I have assume that for listRelatives.addDescendents is almost the same as the select function(hi=True), not to mention it is already getting the selection in reverse order… Must have misread the documentation for it… By the way, a quick question.

Regarding your first line of code rootNode = cmds.ls(sl=True)[0], is it really necessary to put [0]? I understand the codes means it is getting the first selected item, but even as I tried to select the child then the parent, the code seems to be working without problems. So is there a reason behind it?

You can do this really easily with PyMel :

nodes = pm.selected()
nodes.extend(nodes[0].getChildren(ad=True, type='transform))

for node in nodes :
node.rename(“foo”)