hello,
The BaseContainer of an object is saved automatically with the document. As long as you are storing your data in the object's BaseContainer, you don't have to worry to save them with the document.
Read/Write/Copy need to be override when you are storing data somewhere else. In most of the case, If one of those function is implemented, you have to implement all of them.
GVO (GetVirtualObjects) isn't the right place to change the scene. See information about threading
To know if you are on the main thread or not you can use GeIsMainThread
The right place to do something like this is the Message function.
You can react to the message MSG_DESCRIPTION_POSTSETPARAMETER to apply some modifications when a parameter have been changed.
You can also react to the message MSG_MENUPREPARE that is sent before the object is inserted in the scene.
Be careful that this selection tag shouldn't be moved from the generator (or it will be reset)
To avoid that, you can change its bit using ChangeNBit
Here are an example of what you want to do.
def CreateSelectionTag(self, node):
#Creates a selection tag. Remove the tag first if it already exist
bc = node.GetDataInstance()
if bc is None:
return False
tag = bc.GetLink(ID_TAGLINK)
if tag:
tag.Remove()
bc.RemoveIndex(ID_TAGLINK)
tag = c4d.SelectionTag(c4d.Tpolygonselection)
if tag is None:
return False
tag.ChangeNBit(c4d.NBIT_NO_DELETE, c4d.NBITCONTROL_SET);
tag.ChangeNBit(c4d.NBIT_NO_DD, c4d.NBITCONTROL_SET);
node.InsertTag(tag)
bc.SetLink(ID_TAGLINK, tag)
return True
def RemoveSeletionTag(self, node):
# Remove the tag
bc = node.GetDataInstance()
if bc is None:
return False
tag = bc.GetLink(ID_TAGLINK)
if tag is None:
return False
tag.Remove()
bc.RemoveIndex(ID_TAGLINK)
return True
def Init(self, op):
op[ID_CHECKBOX] = True
return True
def Message(self, node, type, data):
# MSG_MENUPREPARE is sent before the object (generator here) is inserted in the scene. This is a nice moment to add any tag to the node
if type == c4d.MSG_MENUPREPARE:
print ("Message mainthread ? ", c4d.threading.GeIsMainThread())
self.CreateSelectionTag(node)
# MSG_DESCRIPTION_POSTSETPARAMETER is sent if a parameter have changed. Check here if we should add or remove a tag.
elif type == c4d.MSG_DESCRIPTION_POSTSETPARAMETER:
print ("Message mainthread ? ", c4d.threading.GeIsMainThread())
if data['descid'][0].id == ID_CHECKBOX:
if node[ID_CHECKBOX]:
return self.CreateSelectionTag(node)
else:
return self.RemoveSeletionTag(node)
return True
# Override method, should generate and return the object.
def GetVirtualObjects(self, op, hierarchyhelp):
print ("GVO mainthread ? ", c4d.threading.GeIsMainThread())
if op[ID_CHECKBOX]:
bc = op.GetDataInstance()
tag = bc.GetLink(ID_TAGLINK)
if tag:
print ("the tag is", tag)
else:
print ("this should never happen")
else:
bc = op.GetDataInstance()
tag = bc.GetLink(ID_TAGLINK)
if tag:
print ("this should never happen")
else:
print ("there's no tag and box isn't checked")
Cheers,
Manuel