Creative Communities of the World Forums

The peer to peer support community for media production professionals.

Activity Forums Adobe After Effects Expressions Problem with layer position

  • Problem with layer position

    Posted by Sébastien Périer on March 7, 2008 at 10:31 pm

    Hi everyone, it’s my first post here (i’ve been reading for a while) and i hope that my problem doesn’t sound stupid.

    Ok, so let’s go; I got a Composition with 2 layers.

    The first one is a Null object (called controller) with an expression control “Point” applied to it.

    The second is a Solid layer. I got an expression on it linking it’s position to the expression control on my Controller layer.

    I also got an expression on my Controller layer Point Effect that says something about this:

    CurrentPosX = effect(“Contoller”)(“point”)[0];
    NextPosX = (some simple math operations);

    [NextPosX, CurrentPosX]

    The idea behind that is that the “y” coordinate shall be the previous “x” coordinate.

    But the first line, where i set my CurrentPosX always give me the same result. Instead of getting the current [0] value of my expression control, it gives me the default value when i added the expression control. I fact it doesn’t take into account the expression applied to the “x” value.

    I don’t know if i’m clear as english is not my native language, but i’m stuck on this. I tried to use the valueAtTime attribute, but i always get the same result.

    So my question is: is there any way to get the current value of an effect inside the expression that is modifying it.

    Thanks for your help.

    Sébastien Périer replied 18 years, 2 months ago 2 Members · 7 Replies
  • 7 Replies
  • Dan Ebberts

    March 7, 2008 at 11:16 pm

    Unfortunately, all you have access to inside the expression is the pre-expession (i.e. static or keyframed) values. Sometimes you can get around this by making your expression a function of time. What are you trying to do exactly?

    Dan

  • Sébastien Périer

    March 8, 2008 at 12:08 am

    It’s a bit difficult to explain.

    in fact i have 8 solids, and i do control their opacity with my controller layer. Until here it sounds easy.

    Thoses 8 layers opacity value is an expression linking to my Point[0] value. This value looks like this: 10010110. Each 1 or 0 stands for one of the layer, 1 saying it should be visible, 0 it should not be visible.

    This number is generated by an expression. I have a slider control in which i keyframe the value from 0 to 8, depending on how many of theses solids i want to be visible. Lets say i want 4 solids visible, I will put a 4 in my slider control, and it will update the point[0] value with four 1, and the chosen solids will show up. I used a Point controller as the slider control does not allow such large numbers.

    My problem is that i don’t want my 4 visible to change every frame, but right now it’s what it does., because i’m not able to get that value back at the begining of my expression to compare the number of layers actually showing, with the number requested by my slider control. And, if i wanted to add 1 more layer visible, it would also choose 5 new random solids.

    That is my problem.

  • Dan Ebberts

    March 8, 2008 at 1:47 am

    We can fix this. What does the part of the expression that determins which layers are visibil look like?

    Dan

  • Sébastien Périer

    March 8, 2008 at 9:31 am

    Nice to hear something like that Dan.

    So let’s get deeper into my code.

    First of all, my 8 solid layers are named “L01”, “L02”, … , “L08”

    The expression linking their opacity to my Expresion control looks like that:

    For “L01”:

    ———————————————–
    Switch =thisComp.layer(“Ctrl_Lxx”).effect(“Lxx Global Switch”)(“Point”)[0];

    // “Ctrl_Lxx” is the name of my null layer with expresion control
    // “Lxx Global Switch” is the name of my Point expression control

    if (Switch >= 10000000) Switch = Switch-10000000;
    if (Switch >= 1000000) Switch = Switch-1000000;
    if (Switch >= 100000) Switch = Switch-100000;
    if (Switch >= 10000) Switch = Switch-10000;
    if (Switch >= 1000) Switch = Switch-1000;
    if (Switch >= 100) Switch = Switch-100;
    if (Switch >= 10) Switch = Switch-10;

    if (Switch < 1) transform.opacity = 10; else transform.opacity = 100; ----------------------------------------------- For "L02": ----------------------------------------------- Switch =thisComp.layer("Ctrl_Lxx").effect("Lxx Global Switch")("Point")[0]; if (Switch >= 10000000) Switch = Switch-10000000;
    if (Switch >= 1000000) Switch = Switch-1000000;
    if (Switch >= 100000) Switch = Switch-100000;
    if (Switch >= 10000) Switch = Switch-10000;
    if (Switch >= 1000) Switch = Switch-1000;
    if (Switch >= 100) Switch = Switch-100;

    if (Switch < 10) transform.opacity = 10; if (Switch >= 10) transform.opacity = 100;
    ———————————————–

    and so on, for the 6 other layers.

    The main expression if of course on the effect(“Lxx Global Switch”)(“Point”).

    It Looks like:

    ———————————————–
    Target = effect(“Lxx Switch Target”)(“Curseur”);
    //(“Curseur”) is the french name of “Slider”; This is the slider control where i choose how many layers shall be seen.

    Actual = effect(“Lxx Global Switch”)(“Point”)[0];
    //This is where i was supposed to get the actual information of shown layers.

    ActualTable = [0,0,0,0,0,0,0,0];
    // This is the Array where i was supposed to store the shown information in a more conviniant way than in a large number for programation purposes, based on the “Actual” value.

    FinalTable = [0,0,0,0,0,0,0,0];
    //This is the array where i’ll store the new shown/hidden layers.

    ActualNum = 0;
    // This is where I was supposed to put the calculated information on how many layers are actually lit based on the “Actual” value.

    Final = Actual;
    //Final is where i’ll store the final result.

    //Below is the part where i transformed the “Actual” value into the “ActualTable” Array, and where i counted how many layers where lit in order to update the “ActualNum” value.
    //It is in comment because right now it was useless as i tried to figure out how to get that “Actual” value right first.

    /*
    if (Actual >= 10000000)
    {
    ActualTable[0] = 1;
    ActualNum++;
    Actual = Actual – 10000000;
    }
    else ActualTable[0] = 0;

    if (Actual >= 1000000)
    {
    ActualTable[1] = 1;
    ActualNum++;
    Actual = Actual – 1000000;
    }
    else ActualTable[1] = 0;

    if (Actual >= 100000)
    {
    ActualTable[2] = 1;
    ActualNum++;
    Actual = Actual – 100000;
    }
    else ActualTable[2] = 0;

    if (Actual >= 10000)
    {
    ActualTable[3] = 1;
    ActualNum++;
    Actual = Actual – 10000;
    }
    else ActualTable[3] = 0;

    if (Actual >= 1000)
    {
    ActualTable[4] = 1;
    ActualNum++;
    Actual = Actual – 1000;
    }
    else ActualTable[4] = 0;

    if (Actual >= 100)
    {
    ActualTable[5] = 1;
    ActualNum++;
    Actual = Actual – 100;
    }
    else ActualTable[5] = 0;

    if (Actual >= 10)
    {
    ActualTable[6] = 1;
    ActualNum++;
    Actual = Actual – 10;
    }
    else ActualTable[6] = 0;

    if (Actual >= 1)
    {
    ActualTable[7] = 1;
    ActualNum++;
    Actual = Actual – 1;
    }
    else ActualTable[7] = 0;
    */

    // This is where I’m supposed to update and calculate my “ActualTable” taking into account the new “target” value of shown layers.
    // Right now, as my ActualNum is always at “0”, it always goes only thru the first “if”.

    if (Target > ActualNum)
    {
    while (Target > ActualNum)
    {
    temp = Math.round(random(7));
    if (ActualTable[temp] == 0)
    {
    ActualTable[temp] = 1;
    ActualNum++;
    }
    }
    }
    if (ActualNum > Target)
    {
    while (ActualNum > Target)
    {
    temp = Math.round(random(7));
    if (ActualTable[temp] == 1)
    {
    ActualTable[temp] = 0;
    ActualNum–;
    }
    }
    }
    FinalTable = ActualTable;

    //Finally, i convert back my array into a simple large value to update my (“point”)[0] value.

    Final = (FinalTable[0]*10000000) + (FinalTable[1]*1000000) + (FinalTable[2]*100000) + (FinalTable[3]*10000) + (FinalTable[4]*1000) + (FinalTable[5]*100) + (FinalTable[6]*10) + FinalTable[7];

    //In here, only the [0] value matters, i used the [1] value to show my intermediate values to help me debbugging the script.
    [Final, ActualNum]
    ———————————————–

    And that’s about it. it may not be the smartest way to achieve such an effect, but i haven’t used my programming skills for mre tha 3 years now, and it’s kinda difficult to get back in touch with Javascript and such.

    Thank you Dan.

  • Dan Ebberts

    March 8, 2008 at 5:53 pm

    Wow, that’s a lot of code. 🙂

    I took what I think you’re trying to do and simplified it a little. Hopefully this will be useful to you. I set up a null named “control” with a slider named “target” that controls how many layers are to be visible and another named “global switch” that calculates which layers should be visible. The expression for “global switch” encodes the results in binary, so 0 would be no layers on, 3 would be layers 1 and 2 on, 255 would be all layers on, etc.

    Here’s that expression (it’s basically just a card shuffling algorithm, thus the array named “deck”):

    slider = effect(“target”)(“Slider”);

    deck = [1,2,4,8,16,32,64,128];
    howMany = Math.min(Math.round(slider),deck.length);
    seedRandom(index,true); // same results every time
    for (i = 0; i < deck.length; i++){ // shuffle the deck idx = i + Math.floor(random(deck.length - i)); temp = deck[i]; deck[i] = deck[idx]; deck[idx] = temp; } result = 0; for(i = 0; i < howMany; i++) result += deck[i] Then each opacity expression just has to check its bit in the "global switch" output. There are lots of ways to do it. I converted the last character of the layer's name to an index (L01 >> 0, L08 >> 7, etc.) into the deck array and then just use a bit-wise AND to see if the corresponding bit is set in the “target” slider.

    slider = thisComp.layer(“control”).effect(“global switch”)(“Slider”);
    deck = [1,2,4,8,16,32,64,128];
    myIndex = parseInt(name.substr(-1))-1;
    if ((deck[myIndex] & slider) > 0) 100 else 0

    One key point is that the actual layers selected can be changed by modifying the first parameter to seedRandom() in the first expression (I don’t know if you need to do that or not).

    Play around with it – see if it helps.

    Dan

  • Sébastien Périer

    March 9, 2008 at 1:00 pm

    Hum, this is looking really nice. i’ll give it a try on monday when i get back to work and i’ll tell you if it works nicely.

    Thanks again Dan,

    Seb

  • Sébastien Périer

    March 10, 2008 at 12:08 pm

    That’s wonderfull Dan,

    it’s working great. Best of all, i’ve understood most of the code, so bad my math skills are not really high.

    Anyway, thats perfect, and for even more control, i’ve added a “Manual” switch so the animators can choose whatever layer they want visible.

    Thanks again,

    Seb

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