Selecting objects via partial name



  • On 15/07/2013 at 08:14, xxxxxxxx wrote:

    Hey guys,

    I was just wondering if there was a way to select objects in a scene with the same beginning of the name.
    eg.
    Layer panel
    Layer panel
    Layer window
    Layer window
    Streetlamp
    Streetlamp_02

    so if I ran the plugin it would then select everything with 'Layer' in or 'Street'

    My master plan is to create a script that selects all objects with the same 12 characters at the beginning of their name, groups them into a null, then names the null with those 12 characters.

    When importing fbx files to work on, its bringing in 10000 objects, This will help speed up work greatly.

    Cheers in advance

    Tom



  • On 15/07/2013 at 09:48, xxxxxxxx wrote:

    1. c4d has that functionality built in (the magnifying glass icon in the om).
    2. yes it is possible, although c4d has not a special method for that exact case. there are the 
    search methods in BaseDocument. but they will always only return the first match. a custom 
    method could look like that( where nodelist is a list of GeListNodes ) :

    def FilterNodeByName( nodelist, filterstring ) :
        result = []
        if isinstance(nodelist, list) :
            for node in nodelist:
                if isinstance(node, c4d.BaseList2D) and filterstring in node.GetName() :
                    result.append(node)
        else: return None
        return result
    

    edit : fyi you might have to modify the filter string and the name string. i always forget if __contains__ () is case sensitive for strings, but i think it is, so for an insensitive search you would have to force both strings into lower or upper case.



  • On 19/08/2013 at 03:45, xxxxxxxx wrote:

    Hey littledevil,

    cheers for the reply, sorry its been a while, just coming back to this now.
    Here is a script I've found:

      
    import c4d  
      
    def main() :  
      mapping = {}  
      context = doc.GetActiveObject() or doc.GetFirstObject()  
      
      if not context:  
          return  
      
      root = context.GetUp()  
      
      # Go to the first object in the context.  
      while context.GetPred() :  
          context = context.GetPred()  
      
      # Fill the mapping.  
      while context:  
          mapping.setdefault(context.GetName(), []).append(context)  
          context = context.GetNext()  
      
      # Create Null-Objects.  
      items = sorted(mapping.iteritems(), key=lambda x: x[0])  
      prev = None  
      for name, objects in items:  
          null = c4d.BaseObject(c4d.Onull)  
          null.SetName(name)  
          for obj in objects:  
              doc.AddUndo(c4d.UNDOTYPE_CHANGE, obj)  
              obj.Remove()  
              obj.InsertUnderLast(null)  
          doc.AddUndo(c4d.UNDOTYPE_NEW, null)  
          doc.InsertObject(null, root, prev)  
          prev = null  
      
      c4d.EventAdd()  
      
    main()  
    

    I'm trying to tweak it, maybe by adding a range(13) in there to select the characters?

    In the section of #Fill The Mapping. I was trying to get in a range, so it only gets the first 12 characters of a name, but the .GetName() takes no arguments.



  • On 19/08/2013 at 04:06, xxxxxxxx wrote:

    strings are arrays of chars (or more pythonic lists).

    string = '01234567'
    print len(string)
    \>> 8
    print string[4]
    \>> 4
    print string[1:4]
    \>> 1234
    print string[:-1]
    \>> 0123456
    

    I did use sort of this quality of strings in my first snippet, when i did call __contains__ on a string
    which is an enumerator object method.

    > if filterstring in node.GetName() :



  • On 19/08/2013 at 05:18, xxxxxxxx wrote:

    I'm trying to go about removing the last few characters from the end of each string in the list

      
    for x in mapping:  
      mapping[:-13]  
    

    Or do you think it would be more to do with the first line of the #Create Null-Objects.?



  • On 19/08/2013 at 07:54, xxxxxxxx wrote:

    a negative index does indicate an inverted index order.

    > mapping[:-13]

    is the short (implicit) form for

    > mapping[0:-13]
    >
    >
    >
    which means take the list mapping and copy its content form the first index to the last index - 13.
    so for a list with 15 indices list[:-13] and list[:2] are the same result list. also not assigning the 
    copied list to a variable does not really make any sense. if you do want to copy a list from its first 
    to its nth component it is simply mylist[:nth].

    mylist = mylist[:11]
      
    or a bit more extensive including checking for oor exceptions :
      
    def cliplist(data, n) :
        if isinstance(data, list) and isinstance(n, int) :
            if len(data) > n-1:
                return data[:n]
            else:
                return data
        return None
      
    ...
      
    mylist = cliplist(mylist, 11)
    

Log in to reply