Layers with the same name?
-
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.
-
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, aGeMarker
object contains an unique ID used to identifyBaseList2D
based objects. Since aLayerObject
inherits fromBaseList2D
in C++ you could use BaseList2D::GetMarker() to retrieve the corresponding unique GeMarker and use it to distinguish multiple layers.Best, Riccardo
-
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 theC4DAtom::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
-
Thank you. I will try your solution.
-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() '''
-
@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. -
Thank you, that explains a lot.
One question, how to print a ByteSeq or store it as a integer or ascii value? -
@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.
-
Thanks, it is clear to me now.
I am using str(opUuid).encode("hex") now. -
Since R21 sp1 issue regarding ByteSeq not being able to be printed in the Python Console is resolved.
Cheers,
Maxime.