Copying Take Overrides from an object to another via Python not working properly
-
Hi there, I'm working on a script to transfer (or copy) the overrides from a source object to a target one and it seems to be working if there is no overrides in sub-Takes.
Basically what the script does is a scan through all Takes starting from the first after the Main (takeData.GetMainTake().GetDown()
) and retrieves each override ID and value and it adds to the target object viaFindOrAddOverrideParam()
.
But for any odd reason the result is not consistent if there are sub-Takes involved as it changes depending on which one is active before running the script, and in all cases, I would expect a perfect copy but that's not what's happening. I must be missing something here
My gut feeling says that the problem is related to the backup so I just tried forcing it viaFindOverrideCounterPart()
but without success.
I'm sending a dummy file attached with a set of Takes just to show the problem I'm trying to describe here:
copy_overrides_to_another_object.c4d
This is the script that works with the file above:
import c4d def GetNextTake(op): if op == None: return None if op.GetDown(): return op.GetDown() while not op.GetNext() and op.GetUp(): op = op.GetUp() return op.GetNext() def getDescIdName(op, descID): description = op.GetDescription(c4d.DESCFLAGS_DESC_0) for bc, paramid, groupid in description: if paramid == descID: return bc[c4d.DESC_NAME] def TransferTakeOverrides(srcObj, trgObj, takeData, currentTake): while currentTake: srcOverride = currentTake.FindOverride(takeData, srcObj) if srcOverride is not None: for descID in srcOverride.GetAllOverrideDescID(): # Get the backup node for the source override backup, result = takeData.FindOverrideCounterPart(srcOverride, descID) # backup: The counterpart node // result: the Take if backup is None: raise RuntimeError("Failed to find the default override.") # Get the backup value of the given Description ID backupValue = backup.GetParameter(descID, c4d.DESCFLAGS_GET_0) print(currentTake.GetName(), " DescID:", getDescIdName(srcObj,descID)) print(" --->",srcOverride.GetSceneNode().GetName()) print(" overr. value:", srcOverride.GetParameter(descID, c4d.DESCFLAGS_GET_0)) print(" backup value:", backupValue,"from", result.GetName()) # Get the override value srcOverValue = srcOverride.GetParameter(descID, c4d.DESCFLAGS_GET_0) # add override to the target object trgOverride = currentTake.FindOrAddOverrideParam(takeData, trgObj, descID, srcOverValue) # Get the backup node for the target override trg_backup, trg_result = takeData.FindOverrideCounterPart(trgOverride, descID) trg_backupValue = trg_backup.GetParameter(descID, c4d.DESCFLAGS_GET_0) # force adding source backup value to the target backup take (just trying to fix the problem!) trgBackup = trg_result.FindOrAddOverrideParam(takeData, trgObj, descID, backupValue) trgBackup.UpdateSceneNode(takeData, descID) trgOverride.UpdateSceneNode(takeData, descID) print(" --->",trgOverride.GetSceneNode().GetName()) print(" overr. value:", trgOverride.GetParameter(descID, c4d.DESCFLAGS_GET_0)) print(" backup value:", trg_backupValue,"from", trg_result.GetName()) print(" ----------------") currentTake = GetNextTake(currentTake) print("======================================") def main(): op = c4d.BaseObject(c4d.Ocube) op[c4d.ID_BASELIST_NAME] = "trg_Cube" doc.InsertObject(op) objs = doc.GetObjects() objs.reverse() if len(objs) != 2: return takeData = doc.GetTakeData() currentTake = takeData.GetMainTake().GetDown() TransferTakeOverrides(srcObj=objs[0], trgObj=objs[1], takeData=takeData, currentTake=currentTake) c4d.EventAdd() if __name__=='__main__': main()
-
Hi,
Finally found why by adding the backupvalue in the function FindOrAddOverrideParam.
I yet, need to understand why because it should be optional even if this parameter is there for something.
Maybe for one of those case but I am not sure.import c4d def GetNextTake(op): if op == None: return None if op.GetDown(): return op.GetDown() while not op.GetNext() and op.GetUp(): op = op.GetUp() return op.GetNext() def getDescIdName(op, descID): description = op.GetDescription(c4d.DESCFLAGS_DESC_0) for bc, paramid, groupid in description: if paramid == descID: return bc[c4d.DESC_NAME] def TransferTakeOverrides(srcObj, trgObj, takeData, currentTake): while currentTake: srcOverride = currentTake.FindOverride(takeData, srcObj) if srcOverride is not None: for descID in srcOverride.GetAllOverrideDescID(): # Get the backup node for the source override backup, ownerTake = takeData.FindOverrideCounterPart(srcOverride, descID) # backup: The counterpart node // result: the Take if backup is None: raise RuntimeError("Failed to find the default override.") # Get the backup value of the given Description ID backupValue = backup.GetParameter(descID, c4d.DESCFLAGS_GET_0) srcOverValue = srcOverride.GetParameter(descID, c4d.DESCFLAGS_GET_0) print(currentTake.GetName(), " DescID:", getDescIdName(srcObj,descID)) print(" --->",srcOverride.GetSceneNode().GetName()) print(" overr. value:", srcOverValue) print(" backup value:", backupValue,"from", ownerTake.GetName()) # Get the override value # add override to the target object trgOverride = currentTake.FindOrAddOverrideParam(takeData, trgObj, descID, srcOverValue, backupValue) trgOverride.UpdateSceneNode(takeData, descID) # Get the backup node for the target override trg_backup, trg_ownerTake = takeData.FindOverrideCounterPart(trgOverride, descID) trgOverValue = trgOverride.GetParameter(descID, c4d.DESCFLAGS_GET_0) trg_backupValue = trg_backup.GetParameter(descID, c4d.DESCFLAGS_GET_0) print(" --->",trgOverride.GetSceneNode().GetName()) print(" overr. value:", trgOverValue) print(" backup value:", trg_backupValue,"from", trg_ownerTake.GetName()) print(" ----------------") currentTake = GetNextTake(currentTake) print("======================================") def main(): op = c4d.BaseObject(c4d.Ocube) op[c4d.ID_BASELIST_NAME] = "trg_Cube" doc.InsertObject(op) objs = doc.GetObjects() objs.reverse() if len(objs) != 2: return takeData = doc.GetTakeData() currentTake = takeData.GetMainTake().GetDown() TransferTakeOverrides(srcObj=objs[0], trgObj=objs[1], takeData=takeData, currentTake=currentTake) c4d.EventAdd() if __name__=='__main__': main()
Cheers,
Manuel -
@m_magalhaes said in Copying Take Overrides from an object to another via Python not working properly:
adding the backupvalue
You are master!
thanks my friend, it's working!