Ok, here’s a thing you normally don’t notice when using a cloner with random clones, because random is random, right?.. Under certain circumstances the clones displayed in the viewport don’t correspond with the indices they are supposed to be.
This is noticeable if you manually turn off & on a/the effector, hence giving only the correct display after the toggle.
Well, this is not about manual things. For a lot of reasons it’s very important to me to know exactly which clone is which. So, I made a “hack” to get the right results…
See preview below for a simple example with index 2 selected in the moSelectionTag which is used in the plainEffector to hide the clone. Notice the nrs in the console - which I think are correct & don’t correspond with the viewport in the last 2 images..
_Left_image: all goes well because the cloners offset is smaller than the “hidden index 2”.
_Middle_image: here is where it goes wrong. The cloners offset passes index 2 (offset >= 3) and incorrect clones are shown.
_Right_image: going back to offset 2 also shows the incorrect children.
Once going to offset 1 everything is fine again - or after dis-/enabling the effector...
So, none of this happens if I apply my “hack” in the script below which turns every effector off/on to get the right result.
Isn’t there a more elegant solution for this?
Is it a bug, or is it me?..
import c4d, math
from c4d.modules import mograph
from c4d import utils
def main():
moObj = op.GetObject() # cloner > with a pyTag
##### ----- #####
useHack = True # use a "hack", turning effector(s) on/off to get the correct random results..
if useHack == True:
doc = op.GetDocument()
inex = moObj[c4d.ID_MG_MOTIONGENERATOR_EFFECTORLIST]
for i in range(inex.GetObjectCount()):
effector = inex.ObjectFromIndex(doc, i)
effector[c4d.ID_BASEOBJECT_GENERATOR_FLAG] = False
effector[c4d.ID_BASEOBJECT_GENERATOR_FLAG] = True
effector.Message(c4d.MSG_UPDATE)
##### ----- #####
moData = mograph.GeGetMoData(moObj)
moCount = moData.GetCount()
moFlags = moData.GetArray(c4d.MODATA_FLAGS)
moChil = moData.GetArray(c4d.MODATA_CLONE)
dirChil = len(moObj.GetChildren())
dirMod = 1/float(dirChil)
for i in range(moCount):
if moFlags[i] != 1: print ("-fl->", moFlags[i])
elif moFlags[i] == 1:
# method 1
dirInst = int(math.floor(moChil[i]/dirMod))
if dirInst == dirChil: dirInst -= 1
# method 2
childIdx = int(math.floor(utils.ClampValue(moChil[i] * dirChil, 0, dirChil-1)))
print ("-fl->", moFlags[i], "-m1->", dirInst, "-m2->", childIdx)
print ("-----")
Note: there are 2 methods in the script to get the right index for the clone. The 2nd method I found on this page: https://plugincafe.maxon.net/topic/10032/13500_identify-name-of-clone-source-at-index/2 which I used as a sanity check. Both methods display the same indices, so effectively there’s no difference.
Also, a simple c4d file attached for testing purposes (R23). By the way, the above happens exactly the same in S22.