SOLVED Sorting cloner each n frame

Yup it's a subject that comes up every few years. I've read this post http://www.plugincafe.com/forum/forum_posts.asp?TID=13473
The last code by supergeordie seems to do what I need (change the sorting every 72 frames - I have about 100k unique combinations of the cloner I need to have which has to be done autoamtically)

The problem with that code is that it's written in Python2 so it doesn't work with the new versions of c4d. As I'm completely ignorant when it comes to Python (never touched it) but need to solve this issue, I wonder...

  1. What do I actually need to change in that code to fit Python3
  2. Are there any updated ways to approach this that are cleaner, more efficient, etc?

Thanks!

Hi sorry the code need to be adapted to support properly fields.

And I removed pip._internal.utils.misc because it's an external package (so not there by default) and is not used in the script.

import c4d, math, random
from c4d.modules import mograph as mo
from c4d import Vector as v, utils as u, Matrix as m
from math import *

TWOPI = pi*2

def my_shuffle(array):
        random.shuffle(array)
        return array

def main():
    md = mo.GeGetMoData(op)
    if md is None: return False

    cnt     = md.GetCount()
    indarr = md.GetArray(c4d.MODATA_ALT_INDEX)
    marr  = md.GetArray(c4d.MODATA_MATRIX)

    hasField = op[c4d.FIELDS].HasContent()
    
    frame = doc.GetTime().GetFrame(doc.GetFps())

    if frame == 0 or -1 in indarr : indarr = list(range(cnt))

    if frame % 30 == 0:
        my_shuffle(indarr)
        md.SetArray(c4d.MODATA_ALT_INDEX, indarr, hasField)

    positions = []

    for i in range(cnt):
        index = indarr[i]
        positions.append(marr[index].off)

    for i in range(cnt):
        marr[i].off = positions[i]

    md.SetArray(c4d.MODATA_MATRIX, marr, hasField)

    return True

Cheers,
Maxime.

Replace xrange by range, you can also follow Python 3 Migration Guideline.

Cheers,
Maxime.

@m_adam thanks !
So I changed xrange to range but there's still some issues I can't seem to figure out
Here's the code I'm using

import c4d, math, random, pip._internal.utils.misc
from c4d.modules import mograph as mo
from c4d import Vector as v, utils as u, Matrix as m
from pip._internal.utils.misc import *
from math import *

TWOPI = pi*2


def my_shuffle(array):
        random.shuffle(array)
        return array

def main():
    md = mo.GeGetMoData(op)
    if md is None: return False

    cnt     = md.GetCount()
    indarr = md.GetArray(c4d.MODATA_ALT_INDEX)
    marr  = md.GetArray(c4d.MODATA_MATRIX)
    fall     = md.GetFalloffs()


    frame = doc.GetTime().GetFrame(doc.GetFps())

    if frame == 0 or -1 in indarr : indarr = range(cnt)

    if frame % 30 == 0:
        my_shuffle(indarr)
        md.SetArray(c4d.MODATA_ALT_INDEX, indarr, True)

    positions = []

    for i in range(cnt):
        index = indarr[i]
        positions.append(marr[index].off)

    for i in range(cnt):
        marr[i].off = positions[i]

    print (indarr)
    md.SetArray(c4d.MODATA_MATRIX, marr, True)

    return True

Nothing happens when I execute and hit play, and this is what the console says:

Traceback (most recent call last):
  File "<Python>", line 29, in main
  File "<Python>", line 11, in my_shuffle
  File "C:\Program Files\Maxon Cinema 4D R24\resource\modules\python\libs\python39.win64.framework\lib\random.py", line 362, in shuffle
    x[i], x[j] = x[j], x[i]
TypeError: 'range' object does not support item assignment

it also types "range(0, 4)" a whole bunch of times

I know it might be the easiest or most obvious thing but I really feel like I'm so ignorant when it comes to anything code.
Hopefully there's an easy fix I'm missing.
Thanks!

Here the adapted code

import c4d, math, random
from c4d.modules import mograph as mo
from c4d import Vector as v, utils as u, Matrix as m
from math import *

TWOPI = pi*2


def my_shuffle(array):
        random.shuffle(array)
        return array

def main():
    md = mo.GeGetMoData(op)
    if md is None: return False

    cnt     = md.GetCount()
    indarr = md.GetArray(c4d.MODATA_ALT_INDEX)
    marr  = md.GetArray(c4d.MODATA_MATRIX)
    fall     = md.GetFalloffs()


    frame = doc.GetTime().GetFrame(doc.GetFps())

    if frame == 0 or -1 in indarr : indarr = list(range(cnt))

    if frame % 30 == 0:
        my_shuffle(indarr)
        md.SetArray(c4d.MODATA_ALT_INDEX, indarr, True)

    positions = []

    for i in range(cnt):
        index = indarr[i]
        positions.append(marr[index].off)

    for i in range(cnt):
        marr[i].off = positions[i]

    md.SetArray(c4d.MODATA_MATRIX, marr, True)

    return True

Cheers,
Maxime.

Thank you so much for going over it adam
I tried this code but it doesnt seem to work, i added the "print (indarr)" line and the console just says "[0, 1, 2, 3]" over and over so it doesnt seem to randomize the order.

Is there a reason you took down the PIP_utils line? It doesn't help with randomziing the order in anyway?

Hi sorry the code need to be adapted to support properly fields.

And I removed pip._internal.utils.misc because it's an external package (so not there by default) and is not used in the script.

import c4d, math, random
from c4d.modules import mograph as mo
from c4d import Vector as v, utils as u, Matrix as m
from math import *

TWOPI = pi*2

def my_shuffle(array):
        random.shuffle(array)
        return array

def main():
    md = mo.GeGetMoData(op)
    if md is None: return False

    cnt     = md.GetCount()
    indarr = md.GetArray(c4d.MODATA_ALT_INDEX)
    marr  = md.GetArray(c4d.MODATA_MATRIX)

    hasField = op[c4d.FIELDS].HasContent()
    
    frame = doc.GetTime().GetFrame(doc.GetFps())

    if frame == 0 or -1 in indarr : indarr = list(range(cnt))

    if frame % 30 == 0:
        my_shuffle(indarr)
        md.SetArray(c4d.MODATA_ALT_INDEX, indarr, hasField)

    positions = []

    for i in range(cnt):
        index = indarr[i]
        positions.append(marr[index].off)

    for i in range(cnt):
        marr[i].off = positions[i]

    md.SetArray(c4d.MODATA_MATRIX, marr, hasField)

    return True

Cheers,
Maxime.

Hello @Jengo,

without any further questions or replies, we will consider this thread as solved by Monday the 20th and flag it accordingly.

Thank you for your understanding,
Ferdinand