Creative Communities of the World Forums

The peer to peer support community for media production professionals.

Activity Forums Adobe After Effects Expressions Conditional Expression

  • Conditional Expression

    Posted by Mark Allen on September 29, 2006 at 1:41 am

    Hello, I’m new to these forums and new to expression scripting. I wrote a script which got half my problem solved, but I can’t take it to the next level and was hoping someone here might offer the right tip.

    The Problem: Arrange a bunch of layers (like 400) along the x axis with a consistent space between the edges of the layers (which have different widths) WITH the condition to do it for different widths if certain conditions apply. I figured out the first part, but the conditional part elludes me.

    english script:

    IF the previous layer’s name contains (or starts with) “door” OR the current layer’s name contains (or starts with) “door” THEN set the x position to (half the width of the previous layer + half the width of the current layer+200+ x position of previous layer)
    // this would put 200 pixels between the sides of each layer… the or could be a separate if else i suppose.

    ELSE IF the current layer’s name contains (or starts with) “WallThing” THEN set the x position to (half the width of the previous layer + half the width of the current layer+100+ x position of previous layer)
    // this would put 100 pixels between the sides of the previous layer and the current layer if the current contains “WallThing”

    ELSE IF the previous layer’s name contains (or starts with) “WallThing” THEN set the x position to (half the width of the index-2 layer + half the width of the current layer+200+ x position of previous layer)
    // this would basically irgnore the WallThing layer and put 200 pixels between the sides of the index-2 layer and the current layer if the index-1 contains “WallThing”

    OTHERWISE set the x position to (half the width of the index-1 layer + half the width of the current layer+400+ x position of previous layer)
    // this would put 400 pixels between the sides of the index-1 layer and the current layer

    That’s it. If you can’t read a portion of the name, can it be done by way the full name? if not that, can it be done with the layer type? (comp vs. footage) Will the width read the width of a comp if a precomp is on the layer above?

    Is it possible to make the pixel amounts global type of variables or controlled by a singular unit is some manner?

    And is there a better than the manual reference for this stuff? Not like a full course, but a basic reference?

    Thank you!

    Mark Allen replied 19 years, 7 months ago 2 Members · 7 Replies
  • 7 Replies
  • Colin Braley

    September 29, 2006 at 4:49 am

    This should do it:

    //begin code

    x = 0;
    y = 0;//I dont know what you want Y to be
    z = 0;//I dont know what you want Z to be
    //–
    if( index == 1 )
    {
    //I dont know what you want to do for the first layer
    [0,0,0]
    }else{

    //—

    prevName = thisComp.layer( index – 1 ).name;
    currName = thisComp.layer( index ).name;
    //–
    if( prevName.indexOf (“door”) != -1|| currName.indexOf( ” door ” ) != -1 )
    x = thisComp.layer(index -1).position[0] / 2 + thisLayer.width / 2 + 200 + thisComp.layer( index -1 ).position[0];
    else if( currName.indexOf ( “wallThing” ) != -1)
    x = thisComp.layer(index -1).width /2 + thisLayer.width / 2 + 100 + thisComp.layer (index – 1 ).position[0];
    else if ( prevName.indexOf( “wallThing” ) != -1 )
    x = thisComp.layer( index -2 ).width /2 + thisLayer.width /2 + 200 + thisComp.layer (index -1 ).position[0];
    else
    x = thisComp.layer( index – 1).width + thisLayer.width /2 + 400 + thisComp.layer( index -1).position[0];

    [x, y, z]
    }

    //end code

    A few questions/comments:

    -I left a blank after if( index ==1 ) because I don’t know what you want to happen if its the first layer.
    -I didn;t have much time to test this
    -The code formatting will look horrible and there will be no indentatin because its hard to read.
    -Also, when the code looks at the other layers’ names note that it is case sensitive
    -Lastly Im curious as to what this code is doing….it sounds like you are trying to build a house 🙂

    ~Colin

  • Mark Allen

    September 29, 2006 at 8:40 am

    Colin!!! You’re my hero!

    Yes, there were a couple bugs which were easy enough to fix and yes I made a slight error in my desciption – but that was also easy to fix and now I have some fantastic code. Seriously… You made my night thank you!

    I will share the final code and then answer your questions….

    //begin code

    x = 0;
    y = 270;
    z = 0;
    normalDistance = 200;
    doorDistance = 100;

    prevName = thisComp.layer( index – 1 ).name;
    currName = thisComp.layer( index ).name;
    //–

    if (currName.indexOf( “wallThing” ) != -1)
    x = thisComp.layer(index -1).width /2 + normalDistance/2 + thisComp.layer( index -1 ).position[0];
    // make wall things ignore their own presence

    else if ( prevName.indexOf( “wallThing” ) != -1 )
    x = thisComp.layer( index -2 ).width /2 + thisLayer.width /2 + normalDistance + thisComp.layer (index -2 ).position[0];
    // make layer after a wallthing ignore the wall thing’s presence

    else if( prevName.indexOf (“door”) != -1|| currName.indexOf( “door” ) != -1 )
    x = thisComp.layer(index -1).width / 2 + thisLayer.width / 2 + doorDistance + thisComp.layer( index -1 ).position[0];
    // make door layers and layers after door layers have their own distance

    else
    x = thisComp.layer( index – 1).width/2 + thisLayer.width / 2 + normalDistance + thisComp.layer( index -1).position[0];
    // everything else gets set to the normal distance

    [x, y, z]

    //end code

    To answer your question – I’m building a hallway. A hallway that has over 500 photographs and we are tracking down this hallway for about 30 minutes. The photographs have the same height and different widths but the distance between them is meant to be the same. However – to make the hallway more interesting and seem like we made a hallway which is unique for about a mile long, we are adding certain touches… like fire alarms, conduits… we’re also adding doors – but the doors are special, the conduits and such are meant to be ignored, but the doors are mean to have a little space for them. And now… you’ve made it possible.

    I will email you a link to it if you like when it’s done next week. (I would post it but it would be removed eventually and due to rights issues can’t be stored on the common video servers.)

    Just curious – how long did it take you to write this?

    ALSO – I realize that AE can’t use globals… so I made a cheat… hack… i made a null called “globalnull” and then set the x and y positions to numbers I wanted access to and then did…

    normDistance = thisComp.layer(“globalnull”).position[0]

    etc.

    Is there a more elegant solution to this because while amazingly convenient, it feels like a hack…

    Thanks again.

  • Colin Braley

    September 29, 2006 at 4:22 pm

    Glad I could help…sounds like an interesting project…when the video is done send me a link sometime if you are able to. My email is cbraley AT vt.edu.
    And to answer your questions:
    – The code didn’t take me too long to write…just under 10 minutes…all I really had to do was translate your psuedo-code into javascript…you did all the thinking for me.
    – Also, you are right in saying that AE has no global variables, and that was a clever solution to use the x position of a null as a global variable. However, there is a more elegant solution called an “Expression control.” Go to effects > expression controls and add a “Slider” to a layer sometime. You can rename this effect something like “GAP” and then pick whip to it whenever you need to reference that value in an expression. For more info about expression controls check out

    https://www.digitaltutors.com/digital_tutors/video.php?v=528

    that tutorial.
    There are also other ways (like using loops) to get around AE’s lack of global variables but usually that kind of thing isn’t necessary.
    I hope I helped you out.
    ~Colin

  • Mark Allen

    September 29, 2006 at 9:56 pm

    Great tip on that tutorial. I’ve heard of these sliders and just been too lazy to figure out how to use them… which now seems silly.

    I will be emailing you a link to a finished sample (and my thanks again) next week when this thing is finished!

    Is there a great resource online for javascript “words” that can be used with AE? The indexOf was key here and I would have had no idea that this existed or how to find it unless you’d put it out there. I don’t know what I may come across in the future, but seems like I would have wanted to find “indexOf” listed under “things to do with .name” in a manual that actually made sense. 🙂

  • Colin Braley

    September 30, 2006 at 1:42 am

    Mynameisinuse,
    I’m not sure if there is an online resource of every javascript keyword/function. Many realy programming languages like C++ or Java have somehting called an “API” which is an online document that tells you about all the commands in the language and their proper syntax. It’s probably out there somewhere, but I don’t know where. However, if you find it most of it would be useless to you because javascript is a scripting language meant for developing websites. After Effect’s expressions just use a subset of the javascript comands with some of their own things mixed in. If you want to learn more “things to do with .name” check out this resource:
    https://www.quirksmode.org/js/strings.html
    it might be a little but confusing however because it assumes you know some programming terminology. If you have any questions about anything in there post ’em on here and Im sure myself or someone will help you out.
    ~Colin

  • Mark Allen

    October 4, 2006 at 1:46 am

    Well… almost done with this project. I have about 524 layers in the project. There are about 450 of them which all use the same expression (posted above with the alteration of using a controls null slider).

    HOWEVER…. after pasting this lovely expression, I’m getting the error on random layers: “stack overrun – expression disabled” and then a bunch of them after that “time out expression disabled.”

    Seems from my fussing with it that I have to set a real keyframe every 40 layers or so. Is there a limit to how many times one can refer back to a previous layer?

    What exactly does “stack overrun” mean in this case?

    Thanks in advance.

  • Mark Allen

    October 4, 2006 at 5:39 am

    Okay – so, I turned to my brother who is a programmer (CTO of a tech company as well) but who has never even seen After Effects open and he said that the stack overrun was a bug in AE that he could fix (hehehe sounds like a programmer doesn’t he?) , but for now it was running out of memory from the references. Meaning 453 layers referencing the previous layer. (index-1)

    so – I mentioned the idea of running it as a script and after a couple of hours with he and I and the scripting book we managed (though he really did it all) to come up with a script hack which solved the problem using Colin’s basic program inside a script form.

    Now, I had to remove all the neat slider expression controls because they were erring which was a bummer – but by now I’d figured out what I wanted for those numbers anyway so it was okay…

    …and for the edification of anyone reading or referencing this – I post the script below… if anyone wants to tell me how we could have referenced a slider instead of assigning a number (in for example z = 0) then that would be interesting for me to know.

    one side benefit without the 453 scripts, the project seems to run faster.

    thanks to everyone whose scripts I stole lines from for things like the undogroup and sorry for the crazy spacing which came because of gmail to mail.app to textedit.

    //begin code

    app.beginUndoGroup(“DistanceScript”);
    var

    curItem = app.project.activeItem;
    if

    (curItem == null || !(curItem instanceof CompItem)){
    alert(“Please establish a comp as the active item and run the script again”);

    }

    var

    thisComp = app.project.activeItem;
    if

    (thisComp == null || !(thisComp instanceof CompItem)){
    alert(“Please establish a comp as the active item and run the script again”);

    }

    var

    startLayer = 10
    var

    stopLayer = 463
    for

    (var index = startLayer; index <= stopLayer; ++index) { var curLayer = curItem.layer(index) var prevLayer = curItem.layer(index-1) var prevName = prevLayer.name var currName = curLayer.name var x = 0.0 var y = 0.0 var z = 0.0 var normalDistance = 200 var doorDistance = 100 if (currName.indexOf( "wallThing" ) != -1) x = prevLayer.width /2 + normalDistance/2 + prevLayer.position.value[0]; else if (prevName.indexOf( "wallThing" ) != -1) x = thisComp.layer(index -2).width /2 + curLayer.width /2 + normalDistance + thisComp.layer(index -2).position.value[0]; else if( prevName.indexOf ("door") != -1|| currName.indexOf( "door" ) != -1 ) x = prevLayer.width / 2 + curLayer.width / 2 + doorDistance + prevLayer.position.value[0]; else x = prevLayer.width/2 + curLayer.width / 2 + normalDistance + prevLayer.position.value[0]; curLayer.position.setValue([ x, y, z] ); } app.endUndoGroup();

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