python effector shift clones array

On 14/03/2017 at 13:16, xxxxxxxx wrote:

Yannick thank you so much for explaining in such depth.

I had not noticed there was a different control mode available! Now everything works perfectly.

Here is my refined code for offsetting a cloner array:

import c4d
from c4d.modules import mograph as mo
  
def main() :
    md = mo.GeGetMoData(op) #get cloner data from user data link field
    
    if md==None: return 
    
    frame = doc.GetTime().GetFrame(doc.GetFps())
    
    offset = op[c4d.ID_USERDATA,3]
  
    moArray = md.GetArray(c4d.MODATA_MATRIX) #get array of clones
     
    newArray = shiftArray(op[c4d.ID_USERDATA,3], moArray)
        
    md.SetArray(c4d.MODATA_MATRIX, newArray, True)
    
    return True
    
    
def shiftArray(offset, array) :
    offset = offset % len(array)
    return array[offset:] + array[:offset]

On 15/03/2017 at 01:01, xxxxxxxx wrote:

Glad you wrote an offsetting effector.

About Douwe's effector example, it's useless and wrong to store the MODATA_MATRIX in a global array.
This causes the range error when changing the cloner size. Because the previously stored array (with an invalid size for the MoData) was set again.

In your effector you don't use a global variable and that's right as the latest MoData array can always be retrieved with MoData.GetArray().

On 15/03/2017 at 08:11, xxxxxxxx wrote:

🙂

At last.

This issue dates back to november 2012 for me ( http://www.plugincafe.com/\forum/forum_posts.asp?TID=7394 )

So, I want to shuffle clones every 30 frames.
This is where I got stuck ( as in,  I keep on getting the same order ),
which made me "invent" the global overwrite.

  
import c4d  
import random  
from c4d.modules import mograph as mo  
  
def my_shuffle(array) :  
  random.shuffle(array)  
  return array  
  
def main() :  
  md = mo.GeGetMoData(op)   
  if md==None: return   
  frame = doc.GetTime().GetFrame(doc.GetFps())  
  marr = md.GetArray(c4d.MODATA_MATRIX)  
        
  if frame%30==0:  
      newmarr = my_shuffle(marr)  
      md.SetArray(c4d.MODATA_MATRIX, newmarr, True)  
      return True  

Anybody ?

On 17/03/2017 at 10:48, xxxxxxxx wrote:

Hi Douwe,

Thanks for joining the discussion and pointing the issue that made you use a global array.
You're right, for each frame the same matrix array is retrieved. So the shuffled array is set each 30 frame and reset the next frame.

This would need further investigation to check if this is a limitation of effectors/python effectors.

On 19/03/2017 at 14:21, xxxxxxxx wrote:

Hey guys, I'm really new to python, I know my approach doesn't utilise history/memory, just a simple offset translation on the source.

I don't know how you could do it without using a global value?

On 20/03/2017 at 17:28, xxxxxxxx wrote:

Originally posted by xxxxxxxx

Hi Douwe,

Thanks for joining the discussion and pointing the issue that made you use a global array.
You're right, for each frame the same matrix array is retrieved. So the shuffled array is set each 30 frame and reset the next frame.

This would need further investigation to check if this is a limitation of effectors/python effectors.

Thanks for listening, Yannick.
Would love to come across a clean way to do this / get this fixed !

d

On 21/03/2017 at 07:42, xxxxxxxx wrote:

Hey, just having a look at another way of doing this without global variables. I smashed this together really quickly so needs error handling, tightening up, optimising, minimising etc:

import c4d, random
from c4d.modules import mograph as mo
from c4d import Vector as v, utils as u, Matrix as m
  
  
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 xrange(cnt) :
        index = indarr[i]
        positions.append(marr[index].off)
    
    for i in xrange(cnt) :
        marr[i].off = positions[i]
  
    md.SetArray(c4d.MODATA_MATRIX, marr, True)
  
    return True
  

So it looks like the MODATA_ALT_INDEX array does not get reset each frame so you can use it for all kinds of stuff 🙂

Hope this helps,

Adam

On 23/03/2017 at 12:24, xxxxxxxx wrote:

Hi Supergeordie,

I just tried your code and it doesn't seem to be working for me, it resets to original array on the next frame like the original problem we had. 
Does it work for you?

On 23/03/2017 at 12:50, xxxxxxxx wrote:

It works for me. 😕

Saying that, I never actually expected it to work considering the behavior of the other mograph arrays When I threw it together the other day, I happily had clones switching position randomly every Nth frame and I was printing to the console the ALT_INDEX array and it looked like it was doing what it should. Maybe there's something funny going on? (Or maybe I'm being stupid and missed something) Either way I'm out of town until Sunday so I'll have a look then. 🙂

Cheers,

Adam

On 23/03/2017 at 13:11, xxxxxxxx wrote:

Perhaps there's something different about my scene rather than the code, I made a fresh new scene, one cloner, one python effector set to "full control" with your code. would be interesting to see your scenefile, could it be a c4d version difference? I'm using r18.041

On 27/03/2017 at 01:43, xxxxxxxx wrote:

OK, I think I know why. For me it seems to work on the matrix object but not the cloner. I imagine this is because the matrix object does not use this ALT_INDEX array or something.

In my setup I was already using the matrix object with a cloner mapped onto it.
Here's how it works for me:

https://vimeo.com/210222042
password: altind3x

Thanks,

Adam

On 28/03/2017 at 03:01, xxxxxxxx wrote:

Interesting.. I don't know what to say..
Is this just to avoid using global variables?

On 28/03/2017 at 03:14, xxxxxxxx wrote:

Just saw it as a bit of a challenge really, I use global values mainly for this type of thing 🙂