Creative Communities of the World Forums

The peer to peer support community for media production professionals.

Activity Forums Adobe After Effects Expressions Mutually Excusive Positioning with Expressions

  • Mutually Excusive Positioning with Expressions

    Posted by Aris Blevins on April 25, 2006 at 5:02 pm

    Hello all,

    I am wondering if there is a basic string in expressions to look at every layer but one. Essentially I want 25 objects to never be in the same place at once. I have their motion worked and, I think, a rather inelegant (160 repetitive lines of code) solution to not overlapping. I am convinced that there is some easy call that I can set so that the script which check every other layers position against it’s own and proceed to the else variable.

    Does that make sense? I am just entering the more advanced world of expressions and this may be a pipe dream.

    Aris

    Dan Ebberts replied 20 years ago 4 Members · 10 Replies
  • 10 Replies
  • Dan Ebberts

    April 25, 2006 at 5:29 pm

    It might look something like this:

    for (var i = 1; i <= thisComp.numLayers; i++){ match = false; //assume no layer's position matches if (i == index) continue; //skip self if (position == thisComp.layer(i).position){ match = true; // oops - found a layer with same position break; } } if (match) { // your "else" stuff goes here } I haven't tested it so there may be errors, but it should be close. It assumes that you want to check every other layer in the comp. If you have cameras, lights, or other layers you want to exclude - you'll have to modify the code. Dan

  • Aris Blevins

    April 25, 2006 at 7:26 pm

    Dan,

    This certainly simplifies my code, but I am still getting layers sitting on top of each other. Am I mistaken in that the seedRandom function calls a different seed for every layer? I’ll post what I have for conversations sake, but if I’m totally wrong in every sense of the word, just let me know and I’ll head back to the drawing board.

    posX= [130, 284, 438, 591, 745];
    posY = [132, 294, 455, 617, 778];
    holdTime = .75;
    seed = Math.floor(time/holdTime)
    seed1 = i
    for (var i = 1; i <= thisComp.numLayers; i++){ match = false; //assume no layer's position matches if (i == index) continue; //skip self if (position == thisComp.layer(i).position){ match = true; // oops - found a layer with same position break; } } if (match) { seedRandom(seed1, true); [posX[Math.floor(random(5))],posY[Math.floor(random(5))]] }else{ seedRandom(seed, true); [posX[Math.floor(random(5))],posY[Math.floor(random(5))]] }

  • Colin Braley

    April 25, 2006 at 8:36 pm

    I read this thread and am a little confused. Are you trying to use a random motion expression on all your layers while making sure that none of them have the same position, or are you trying to make sure none of the layers overlap visually? If you are trying to make sure none of the layers have the same position this wouldn’t be very hard, but if you are trying to make sure the layers don’t overlap visually this would be more difficult.
    ~Colin

  • Dan Ebberts

    April 25, 2006 at 8:42 pm

    OK – you’ve stumbled on to one of the more obscure limitations of expressions. As far as I know, there’s no way to generate the same random sequence in different layers. This becomes an issue in applications like yours that need the random action of different layers to be coordinated. So, the work-around is to do all the random calculations in one layer, which will serve the results to the others. Here’s one way:

    First, create a text layer (name it “master”) and apply this expression for the source text:

    holdTime = .75;
    seed = Math.floor(time/holdTime);
    seedRandom(seed,true);
    posArray = [];
    for (var i = 0; i < 25; i++){ posArray[i] = i; } for (var i = 0; i <25; i++){ idx = Math.floor(random(i)); temp = posArray[idx]; posArray[idx] = posArray[i]; posArray[i] = temp; } outStr = ""; for (var i = 0; i < 25; i++){ outStr += posArray[i]; if(i != 24) outStr += ","; } outStr You'll notice that you get a comma-separated random sequence of the numbers from 0 to 24 that changes every 3/4 seconds (holdTime). You can turn off visibility for this layer. You need to keep this layer below (in the layer stack) the layers that you will be randomly positioning. Those layers need to be layers 1 through 25 in the layer stack. Apply this expression to each of those layer's position property: posX= [130, 284, 438, 591, 745]; posY = [132, 294, 455, 617, 778]; arrayText = thisComp.layer("master").text.sourceText; myArray = arrayText.split(","); myIdx = parseInt(myArray[index-1]); myXIdx = Math.floor(myIdx/5); myYIdx = myIdx%5; [posX[myXIdx],posY[myYIdx]] This expression reads the random number from the text layer that is appropriate for its layer index and converts that to indexes into the posX and posY tables. This renders fairly slowly, because there is a lot of calculating going on. Have fun! Dan

  • Aris Blevins

    April 25, 2006 at 8:53 pm

    Good lord!!! That is so much more complicated then I would have possibly thought. Fantastic though. I’m going to spend a little while deciphering what exacly you did here.

    Thank you so much for your help.

    Aris

  • Rich Rubasch

    April 26, 2006 at 2:54 am

    I’m going to spend a little time putting my eyeballs and most of my brain back into my skull.

    After looking at these expressions it is clear I don’t speak that language!

    Rich Rubasch
    Tilt Media

  • Dan Ebberts

    April 26, 2006 at 3:56 pm

    Sorry, I should have posted a warning that it could be damaging to your eyeballs and brain. 🙂

    Actually, if you think that one is tough, there’s an even more mind-numbing (but better, I think) solution involving time multiplexing. Not for the faint of heart though.

    Dan

  • Aris Blevins

    April 26, 2006 at 4:42 pm

    That I would like to see just as a learning tool. I think I have started to parse out the functionality of your last bit of code (no way I could have implemented it from scratch still, but it’s a start) and it would be good to re-blow my mind so that I don’t get too confident.

    Aris

  • Dan Ebberts

    April 26, 2006 at 5:11 pm

    OK then. Let’s make it a little training exercise. First the code.

    Instead of a text layer, you would create a null, name it “master”, add a slider to it, and add this expression to the slider:

    setSize = 25;

    t = Math.round(time);
    setNo = Math.floor(t/setSize);
    setIdx = t%setSize;

    seed = Math.floor(setNo);
    seedRandom(seed,true);
    posArray = [];
    for (var i = 0; i < 25; i++){ posArray[i] = i; } for (var i = 0; i <25; i++){ idx = Math.floor(random(i)); temp = posArray[idx]; posArray[idx] = posArray[i]; posArray[i] = temp; } posArray[setIdx] As before, this layer needs to be at the bottom of your layer stack. Then add this position expression to your grid layers: holdTime = .75 setSize = 25; setNumber = Math.floor(time/holdTime); myTime = setNumber*setSize + index - 1; posX= [130, 284, 438, 591, 745]; posY = [132, 294, 455, 617, 778]; myIdx = thisComp.layer("master").effect("Slider Control")("Slider").valueAtTime(myTime); myXIdx = Math.floor(myIdx/5); myYIdx = myIdx%5; [posX[myXIdx],posY[myYIdx]] If you can figure out how it works, I'd have to say that you've learned quite a bit about expressions. Bonus points if you can answer these questions: 1. Why will this method fail if your comp is longer than 7 minutes and 12 seconds? 2. If your comp is longer than that, what could you do to make this method work? 🙂 Dan

  • Dan Ebberts

    April 26, 2006 at 5:28 pm

    Got a little careless with my math. Question 1 should be:

    1) Why will this method fail if your comp is longer than 5 minutes and 24 seconds?

    Dan

We use anonymous cookies to give you the best experience we can.
Our Privacy policy | GDPR Policy