Maxon Developers Maxon Developers
    • Documentation
      • Cinema 4D Python API
      • Cinema 4D C++ API
      • Cineware API
      • ZBrush Python API
      • ZBrush GoZ API
      • Code Examples on Github
    • Forum
    • Downloads
    • Support
      • Support Procedures
      • Registered Developer Program
      • Plugin IDs
      • Contact Us
    • Categories
      • Overview
      • News & Information
      • Cinema 4D SDK Support
      • Cineware SDK Support
      • ZBrush 4D SDK Support
      • Bugs
      • General Talk
    • Unread
    • Recent
    • Tags
    • Users
    • Login

    Layers with the same name?

    Cinema 4D SDK
    r20 python
    3
    10
    1.2k
    Loading More Posts
    • Oldest to Newest
    • Newest to Oldest
    • Most Votes
    Reply
    • Reply as topic
    Log in to reply
    This topic has been deleted. Only users with topic management privileges can see it.
    • P
      pim
      last edited by

      I store the layer of objects using the layer name in an external file.
      However, if layers do not have unique names, restoring the info (due to layers with the same name) will go wrong.

      Is there another way, besides layerdata, to get the correct layer?
      I do not want to use the layerdata, because then I have to store the layerdata link.

      So, basically, is there another way to distinguish layers, not using layerdata or the layer name?

      I hope I make myself clear.

      1 Reply Last reply Reply Quote 0
      • r_giganteR
        r_gigante
        last edited by

        Hi pim, thanks for reaching out us.

        With regard to your request I confirm that being GeMarker class not available in Python you are out of real chances to distinguish two layers sharing the same name.
        As written in the GeMarker Manual, a GeMarker object contains an unique ID used to identify BaseList2D based objects. Since a LayerObject inherits from BaseList2D in C++ you could use BaseList2D::GetMarker() to retrieve the corresponding unique GeMarker and use it to distinguish multiple layers.

        Best, Riccardo

        1 Reply Last reply Reply Quote 0
        • r_giganteR
          r_gigante
          last edited by r_gigante

          Hi pim,

          I need to rectify my answer - kudos to @m_adam - since although you can't directly access GeMarker you can make use of the C4DAtom::FindUniqueID().

          At the same time, due to a known bug, it's likely that the FindUniqueID returned value might be properly represented in the Python Console.

          In R21 SP1 you can make use of hash(uniqueID) - see What's New in R21.1 - whilst in previous releases you might consider to use the sequence of ASCII value of the unique ID to generate a meaningful string.

              layers = doc.GetLayerObjectRoot()
              layer = layers.GetDown()
              
              while layer is not None:
                  # get the unique ID
                  uniqueID = layer.FindUniqueID(c4d.MAXON_CREATOR_ID)
          
                  # create a string containing the uniqueID characters ASCII value
                  asciiValuesUniqueID = ''
                  for i in uniqueID:
                      asciiValuesUniqueID += str(ord(i))
          
                  # show results
                  print 'name: ', layer.GetName(), '\n / asciiValuesUniqueID: ', asciiValuesUniqueID, '\n / hash(UniqueID): =', hash(uniqueID) 
                  layer = layer.GetNext()
          

          Cheers, Riccardo

          M 1 Reply Last reply Reply Quote 0
          • P
            pim
            last edited by

            Thank you. I will try your solution.
            -Pim

            1 Reply Last reply Reply Quote 0
            • P
              pim
              last edited by pim

              I tried the solution and it "hangs" cinema.
              To me it seems that "uniqueID = layer.FindUniqueID(c4d.MAXON_CREATOR_ID)" returns strange values that cannot be interpreted correctly by hash(uniqueID);

              Here the output and the script.
              I used R21 to test.

               200
               217
               210
               152
               191
               170
               19
              12
              p 112
               237
              s 115
              R 82
               191
               23
               0
               0
              
              import c4d
              from c4d import gui
              
              def main():
                  layers = doc.GetLayerObjectRoot()
                  layer = layers.GetDown()
                  
                  while layer is not None:
                      # get the unique ID
                      uniqueID = layer.FindUniqueID(c4d.MAXON_CREATOR_ID)
              
                      # create a string containing the uniqueID characters ASCII value
                      asciiValuesUniqueID = ''
                      for i in uniqueID:
                          print i, ord(i)                    # added for debug
                          asciiValuesUniqueID += str(ord(i))
              
                      # show results
                      # line below, is commented out. Otherwise cinema 4d 'Hangs''
                      print 'name: ', layer.GetName(), '\n / asciiValuesUniqueID: ', asciiValuesUniqueID, '\n / hash(UniqueID): =', hash(uniqueID) 
                      layer = layer.GetNext()
              
              # Execute main()
              if __name__=='__main__':
                  main()
              '''
              1 Reply Last reply Reply Quote 0
              • M
                m_adam @r_gigante
                last edited by

                @pim said in Layers with the same name?:

                I tried the solution and it "hangs" cinema.
                I used R21 to test.

                @r_gigante said in Layers with the same name?:

                In R21 SP1 you can make use of hash(uniqueID) - see What's New in R21.1
                Especially Fixed a crash when hashing a c4d.storage.ByteSeq.

                FindUniqueID return a c4d.storage.ByteSeq so it's possible to dirrectly compare them.

                Like bellow:

                import c4d
                import random
                
                def CreateLayer(x):
                    # Creates a new Layer in memory
                    layer = c4d.documents.LayerObject()
                    if layer is None:
                        raise RuntimeError("Failed to create a Layer.")
                
                    # Defines the Layer Name
                    layer.SetName("My Super Layer")
                    print "Created layer ID: {0}, color: {1}".format(x, layer[c4d.ID_LAYER_COLOR])
                        
                    return layer
                
                def GetUniqueID(layer):
                    if not isinstance(layer, c4d.documents.LayerObject):
                        raise TypeError("The passed layer object was not a LayerObject")
                    
                    return layer.FindUniqueID(c4d.MAXON_CREATOR_ID)
                
                def HierarchyIterator(obj):
                    while obj:
                        yield obj
                        for opChild in HierarchyIterator(obj.GetDown()):
                            yield opChild
                        obj = obj.GetNext()
                
                # Main function
                def main():    
                    # Creates 5 layers with the same name
                    layer1 = CreateLayer(1)
                    layer2 = CreateLayer(2)
                    layer3 = CreateLayer(3)
                    layer4 = CreateLayer(4)
                    layer5 = CreateLayer(5)
                    
                    # Store their uuid
                    layerIdList = []
                    layerIdList.append(GetUniqueID(layer1))
                    layerIdList.append(GetUniqueID(layer2))
                    layerIdList.append(GetUniqueID(layer3))
                    layerIdList.append(GetUniqueID(layer4))
                    layerIdList.append(GetUniqueID(layer5))
                    
                    # Insert them randomly
                    layerList = []
                    layerList.append(layer1)
                    layerList.append(layer2)
                    layerList.append(layer3)
                    layerList.append(layer4)
                    layerList.append(layer5)
                
                    # Shuffle the list and insert them in the doc
                    rootLayers = doc.GetLayerObjectRoot()
                    if rootLayers is None:
                        raise RuntimeError("Failed to retrieve the Root Layer.")
                    
                    random.shuffle(layerList)
                    for layer in layerList:
                        # Inserts the layer into the LayerRoot, in the document
                        layer.InsertUnder(rootLayers)
                        
                    
                    print "--------"
                    
                    # Now iterates over each layer in the doc and print their their color.
                    for layer in HierarchyIterator(rootLayers.GetDown()):
                        layerUuid = GetUniqueID(layer)
                        try:
                            # Find the index that match our byteseq
                            layerCreatedId = layerIdList.index(layerUuid) + 1
                            print "Created layer ID: {0}, color: {1}".format(layerCreatedId, layer[c4d.ID_LAYER_COLOR])
                            
                        # If the uuid is not found maybe the layer was already present previously
                        except ValueError:
                            continue
                    
                    c4d.EventAdd()
                    
                # Execute main()
                if __name__=='__main__':
                    main()
                

                Cheers,
                Maxime.

                MAXON SDK Specialist

                Development Blog, MAXON Registered Developer

                1 Reply Last reply Reply Quote 0
                • P
                  pim
                  last edited by

                  Thank you, that explains a lot.
                  One question, how to print a ByteSeq or store it as a integer or ascii value?

                  M 1 Reply Last reply Reply Quote 0
                  • M
                    m_adam @pim
                    last edited by

                    @pim said in Layers with the same name?:

                    Thank you, that explains a lot.
                    One question, how to print a ByteSeq or store it as a integer or ascii value?

                    Riccardo already demonstrated you how to convert a ByteSeq in ascii value (of course since ByteSeq is a ByteSeq.... some Byte can't be converted to a string).

                        opUuid = op.FindUniqueID(c4d.MAXON_CREATOR_ID)
                    
                        print str(opUuid).encode("hex") # Display in hex
                    
                        # display each int value for character
                        for x in range(0, len(opUuid)):
                            print ord(opUuid[x])
                    ```
                    
                    Cheers,
                    Maxime.

                    MAXON SDK Specialist

                    Development Blog, MAXON Registered Developer

                    1 Reply Last reply Reply Quote 0
                    • P
                      pim
                      last edited by

                      Thanks, it is clear to me now.
                      I am using str(opUuid).encode("hex") now.

                      1 Reply Last reply Reply Quote 0
                      • M
                        m_adam
                        last edited by

                        Since R21 sp1 issue regarding ByteSeq not being able to be printed in the Python Console is resolved.

                        Cheers,
                        Maxime.

                        MAXON SDK Specialist

                        Development Blog, MAXON Registered Developer

                        1 Reply Last reply Reply Quote 1
                        • First post
                          Last post