Forum Replies Created

Page 9 of 17
  • looks like the ‘less than’ symbols in that code got messed up, might need to change that when you paste the code.

    Alex Printz
    Mograph Designer

  • The expression would go on the ship’s position.

    for each frame you would need to calculate the ship’s position for all previous frames and add them together.

    1. start from frame 0
    2. grab the joystick’s position
    3. linear that to a pixel offset ratio(per frame)
    4. add that to the current value
    3. clap to your screen limits.

    Loop to next frame, until you get to current frame.

    Like this:

    //you should change these:
    buffer = [250,100]; //EDGE SCREEN BUFFER [X,Y]
    joystickRange = 200; //MAX ABSOLUTE RANGE OF JOYSTICK FROM CENTER
    joystickMaxRate = 250; //MAX PIXELS PER SECOND MOVE

    //you can change these if you want, but don't necessarly need to:
    shipPosition = [thisComp.width, thisComp.height]/2; //ship start's in center screen;
    compMin = buffer; //top-left corner;
    compMax = [thisComp.width, thisComp.height] - buffer; //bottom-right corner;

    for(f=0; f<=timeToFrames(time); f++){ //for each previous frame
    joystickMove = thisComp.layer("joystick").position.valueAtTime(framesToTime(f)); //get joystick amount;
    for(i=0;i<2;i++) joystickMove[i] = easeOut(Math.abs(joystickMove[i]),0,joystickRange,0,joystickMaxRate/(1/thisComp.frameDuration)) * (joystickMove[i]<0?-1:1); //convert joystick position to offset rate;
    shipPosition+= joystickMove; //move ship amount;
    for(i=0;i<2;i++) shipPosition[i] = clamp(shipPosition[i],compMin[i],compMax[i]); //clamp ship within screen;
    }

    shipPosition //final call

    Alex Printz
    Mograph Designer

  • Alex Printz

    August 27, 2019 at 2:33 pm in reply to: Get RGB values from from a color picker

    I built something similar to this once that worked quite well. I don’t know how or why you would use sampleImage to accomplish what you’re trying to do, but this is how I did my way:

    First, I made a single ‘pixel’ composition made up of 9×9 pixels and 3 frames long, and inside there I had three 2×8 white solids for each R,G,B with a single pixel space around them on all sides. I adjusted the solids so each was visible for only one frame.

    Then I made a ‘screen matte’ composition that was 320×240 of the ‘pixel’ compositions laid out in a grid (so 2880×2160) with a black solid beneath them. By scrubbing through the three frames, I could get a frame where only R, G, or B were white for the whole of the monitor.

    Then I made another comp called ‘screen footage’ at 960×720 pixels (320×240 X 3). I placed what I wanted on the screen inside here, scaled the footage to the size of the composition, and applied a mosaic effect to it at 320×240.

    Then I made a final comp called ‘screen assembly’, and inside there placed the ‘screen matte’ and ‘screen footage’ comps like this:

    – Red Matte layer (time remapped to red pixel times)
    – Red Footage (effect: set channel, keep only red channel visible from source, none for other color channels; luma track matte mode, blend mode set to add)
    – Green Matte layer (time remapped to green pixel times)
    – Green Footage (same as red but blue channel)
    – Blue Matte layer (time remapped to blue pixel times)
    – Blue Footage (same as red but blue channel)
    – Black Solid

    Place ‘screen assembly’ comp into a regular composition and scale it down to whatever size you need, blur, bloom, etc.)

    Alex Printz
    Mograph Designer

  • Alex Printz

    August 6, 2019 at 5:33 pm in reply to: Ease In to Linear (range mapping problem)

    This one is pretty plug and play. Just need to make your 2 sliders, and 2 keys.

    function cubicBezier(t, tMin, tMax, value1, value2, handles){

    aX = thisLayer.linear(t,tMin,tMax,0,1);
    try{
    mX1 = thisLayer.clamp(handles[0],0,1);
    mX2 = thisLayer.clamp(handles[2],0,1);
    mY1 = handles[1]; mY2 = handles[3];
    }catch(e){mX1 = .89; mY1 = -0.03; mX2 = 0; mY2 = .98;}

    function A(aA1,aA2){return 1-3*aA2+3*aA1;}
    function B(aA1,aA2){return 3*aA2-6*aA1;}
    function C(aA1){return 3*aA1;}
    function CalcBezier(aT,aA1,aA2){
    return((A(aA1,aA2)*aT+B(aA1,aA2))*aT+C(aA1))*aT;
    }
    function GetSlope(aT,aA1,aA2){
    return 3*A(aA1,aA2)*aT*aT+2*B(aA1,aA2)*aT+C(aA1);
    }
    function GetTForX(aX){
    var aGuessT=aX;
    for(var i=0;i<6;++i){
    var currentSlope=GetSlope(aGuessT,mX1,mX2);
    if(currentSlope==0)returnaGuessT;
    var currentX=CalcBezier(aGuessT,mX1,mX2)-aX;
    aGuessT-=currentX/currentSlope;
    }return aGuessT;
    }

    if (mX1 != mY1 && mX2 != mY2) aX = CalcBezier(GetTForX(aX), mY1, mY2);
    return tMin < tMax ? thisLayer.linear(aX,0,1,value1,value2) : thisLayer.linear(aX,0,1,value2,value1);
    }

    V = value.length;
    S1 = effect("S1")(1).value; //slider for '% length until reached velocity'
    S2 = effect("S2")(1).value; //slider for ' rate of accelleration increase'

    AP = key(1).value; //point A position
    AT = key(1).time; //point A time
    CP = key(numKeys).value; //point C position
    CT = key(numKeys).time; //point C time

    BP = linear(S1,0,100,AP,CP); //point B position
    BT = linear(S1,0,100,AT,CT); //point B time

    XP = linear(S2,0,100,BP,AP); //handle B1(X) position
    XT = linear(S2,0,100,AT,BT); //handle B1(X) time

    O = linear(S2,0,100,0,BP-AP); //sets the offset from accellerating;

    if(V.length > 1){
    for(i=0;i= BT){ //if we are after the accelleration
    linear(time,BT,CT,BP,CP); //linears between B and C (full accleration)
    }else{
    if(V > 1) for(i=0;i 1){
    F=[];
    for(i=0;i

    Alex Printz
    Mograph Designer

  • Alex Printz

    August 6, 2019 at 2:42 pm in reply to: Ease In to Linear (range mapping problem)

    whoops, I think L should be set to ‘thisLayer’; I had this code pasted on a text object for debugging and it was referencing the animated layer.

    Alex Printz
    Mograph Designer

  • Alex Printz

    August 6, 2019 at 2:40 pm in reply to: Ease In to Linear (range mapping problem)

    Set two keyframes, your beginning and end points. These will be A and C.

    then have to sliders, “S1” and “S2” (rename them however you want.

    S1 should be the percentage of length of time it takes to accelerate up to full velocity.
    S2 should be rate that the acceleration happens (is it really smooth? Is it really abrupt?).

    B will be calculated automatically based on S1 and S2.

    Alex Printz
    Mograph Designer

  • Alex Printz

    July 22, 2019 at 7:37 pm in reply to: Ease In to Linear (range mapping problem)

    That’s an interesting approach, there’s lots of ways to deal with stuff like this I guess is the answer. Here is my working code that I’ve taken a stab at after lunch. The biggest change was I was having problems with the matrix math, I’m sure there are more appropriate ways to deal with this either as for loops or whatnot, but here it is:

    function cubicBezier(t, tMin, tMax, value1, value2, handles){

    aX = thisLayer.linear(t,tMin,tMax,0,1);
    try{
    mX1 = thisLayer.clamp(handles[0],0,1);
    mX2 = thisLayer.clamp(handles[2],0,1);
    mY1 = handles[1]; mY2 = handles[3];
    }catch(e){mX1 = .89; mY1 = -0.03; mX2 = 0; mY2 = .98;}

    function A(aA1,aA2){return 1.0-3.0*aA2+3.0*aA1;}
    function B(aA1,aA2){return 3.0*aA2-6.0*aA1;}
    function C(aA1){return 3.0*aA1;}
    function CalcBezier(aT,aA1,aA2){
    return((A(aA1,aA2)*aT+B(aA1,aA2))*aT+C(aA1))*aT;
    }
    function GetSlope(aT,aA1,aA2){
    return 3.0*A(aA1,aA2)*aT*aT+2.0*B(aA1,aA2)*aT+C(aA1);
    }
    function GetTForX(aX){
    var aGuessT=aX;
    for(var i=0;i<6;++i){
    var currentSlope=GetSlope(aGuessT,mX1,mX2);
    if(currentSlope==0.0)returnaGuessT;
    var currentX=CalcBezier(aGuessT,mX1,mX2)-aX;
    aGuessT-=currentX/currentSlope;
    }return aGuessT;
    }

    if (mX1 != mY1 && mX2 != mY2) aX = CalcBezier(GetTForX(aX), mY1, mY2);
    return tMin < tMax ? thisLayer.linear(aX,0,1,value1,value2) : thisLayer.linear(aX,0,1,value2,value1);
    }

    L = thisComp.layer("Shape Layer 1");
    S1 = L.effect("S1")(1).value; //slider for '% length until reached velocity'
    S2 = L.effect("S2")(1).value; //slider for ' rate of accelleration increase'

    AP = L.position.key(1).value; //point A position
    AT = L.position.key(1).time; //point A time
    CP = L.position.key(numKeys).value; //point C position
    CT = L.position.key(numKeys).time; //point C time

    BP = linear(S1,0,100,AP,CP); //point B position
    BT = linear(S1,0,100,AT,CT); //point B time

    XP = linear(S2,0,100,BP,AP); //handle B1(X) position
    XT = linear(S2,0,100,AT,BT); //handle B1(X) time

    O = linear(S2,0,100,0,BP-AP); //sets the offset from accellerating;
    BP = [BP[0]-O[0],BP[1]-O[1]]; // offsets B position caused my accelleration
    CP = [CP[0]-O[0],CP[1]-O[1]]; // offsets C position caused my accelleration
    XP = [XP[0]-O[0],XP[1]-O[1]]; // offsets B1(X) position caused my accelleration

    if(time >= BT){ //if we are after the accelleration
    linear(time,BT,CT,BP,CP); //linears between B and C (full accleration)
    }else{
    XP[0] = linear(XP[0],AP[0],BP[0],0,.1); // linearizes B1(X) X-position
    XP[1] = linear(XP[1],AP[1],BP[1],0,.1); // linearizes B1(X) Y-position
    XT = linear(XT,AT,BT,0,1); // linearizes B1 time

    //creates bezier curves between point A and B with B1(X) as handle
    FX = cubicBezier(time, AT, BT, AP[0], BP[0], [ .01, 0, XT, XP[0] ]);
    FY = cubicBezier(time, AT, BT, AP[1], BP[1], [ .01, 0, XT, XP[1] ]);

    [FX,FY]
    }

    Alex Printz
    Mograph Designer

  • Alex Printz

    July 22, 2019 at 3:30 pm in reply to: Ease In to Linear (range mapping problem)

    Fun thought experiment, lets talk it through a bit.

    Well, first let’s think how we would draw this out in bezier curves.

    It would be 3 points to create the blue line; one (A) at the origin, one (C) at the destination, and one stuck in the middle at the inflection point (B). I would want no out-tangent on the origin, and an in-tangent on the inflection point (B1) , and no point at the out point.

    The in-tangent location (B1) would be on a straight line extended between (B-C), at an yet-undetermined distance.

    For clarification, if we were going to decelerate, it would be another inflection point at the beginning of the deceleration, but it would have an out-tangent parallel to the slope of the (B-C).

    to parse data like this, I would probably cannibalize a cubic Bezier function, https://cubic-bezier.com/#.17,.67,.83,.67.

    Luckily for you, I’ve already rewritten this as a function for my own needs:

    "cubicBezier":function(t, tMin, tMax, value1, value2, handles){

    aX = thisLayer.linear(t,tMin,tMax,0,1);
    try{
    mX1 = thisLayer.clamp(handles[0],0,1);
    mX2 = thisLayer.clamp(handles[2],0,1);
    mY1 = handles[1]; mY2 = handles[3];
    }catch(e){mX1 = .89; mY1 = -0.03; mX2 = 0; mY2 = .98;}

    function A(aA1,aA2){return 1.0-3.0*aA2+3.0*aA1;}
    function B(aA1,aA2){return 3.0*aA2-6.0*aA1;}
    function C(aA1){return 3.0*aA1;}
    function CalcBezier(aT,aA1,aA2){return((A(aA1,aA2)*aT+B(aA1,aA2))*aT+C(aA1))*aT;}
    function GetSlope(aT,aA1,aA2){return 3.0*A(aA1,aA2)*aT*aT+2.0*B(aA1,aA2)*aT+C(aA1);}
    function GetTForX(aX){
    var aGuessT=aX;
    for(var i=0;i<6;++i){
    var currentSlope=GetSlope(aGuessT,mX1,mX2);
    if(currentSlope==0.0)returnaGuessT;
    var currentX=CalcBezier(aGuessT,mX1,mX2)-aX;
    aGuessT-=currentX/currentSlope;
    }return aGuessT;}

    if (mX1 != mY1 && mX2 != mY2) aX = CalcBezier(GetTForX(aX), mY1, mY2);
    return tMin < tMax ? thisLayer.linear(aX,0,1,value1,value2) : thisLayer.linear(aX,0,1,value2,value1);
    },

    This works just like linear, where you parse (t,tMin,tMax,value1,value2), but then at the end we add an additional cubic-bezier handle [outTangent-X, outTangent-Y, inTangent-X, inTangent-Y].

    So, what you really need to do now is make two sliders: one (Slider 1 or S1) that chooses the time (X-value) of the inflection point (B) relative to the position between A and C. This will be equivalent to your image’s “range mapper” limit.

    And then another slider that adjusts the acceleration intensity (which will adjust the inflection point’s value (Y-value), C’s value (Y-value), and also the distance between B1 and B on B-C. This will be a ‘percentage’ indicator.

    So, where do we put B?

    first, lets create our points:

    A = [key[1].time, key[1].value];
    C = [key[numKeys].time,key[numKeys].value];

    B will be at:


    B = linear(S1, 0,100,A,C);

    Now, where do we put B1? Well, if we wanted maximum accelleration, B1 would be found at A. If we wanted minimum acceleration, B1 would be found at B. Neither of this are what you really want; you want something in-between.

    So what we can do is this:


    B1 = linear(S2,0,100,A,B);
    o = linear(S2,0,100,0,B[1]-A[1]); //sets the offset from accellerating
    B[1]-= o;
    B1[1]-=o;
    C[1]-= o;

    Now, to parse our handle through the cubic bezier function we need to normalize it from a factor of 0-1. So let’s do this:

    xs = 1/(B[0]-A[0]);
    ys = 1/(B[1]-A[1]);
    B1[0] = (B1[0]-A[0]) * xs;
    B1[1] = (B1[1]-A[1])*sy;

    finally, we just need to determine what part gets parsed through the bezier-curve equation and what doesn’t.


    if(time >= B[0]){
    linear(time,B[0],C[0],B[1],C[1]);
    }

    or parse that through the cubic bezier function:

    else cubicBezier(time, A[0], B[0], A[1], B[1], [ 0, 0, B1[0], B1[1] ])

    I think that should do it. There are likely a ton of typos and maybe even a wrong thing or two, but this ought to be 80% of it. No idea how to do multiple keys off the top of my head, but it will likely be else/if functions and checking if things are linear. This is where I would start though. There’s a chance you’ll need to get B1 closer to B, I would just linearize it again prior to offsetting it if need be: B1 = linear(z,0,1,B1,B);

    Note: none of this code was tested.

    Alex Printz
    Mograph Designer

  • Alex Printz

    March 22, 2019 at 2:45 pm in reply to: Expression to Create Arcs in After Effects

    You know what, I just re-read your question and I first response is entirely backwards to what you were asking, pushing data into paths.

    No, there is no way to force paths to specific coordinates prior to AE Oct.2017 update. Sorry for getting your hopes up.

    Alex Printz
    Mograph Designer

  • Alex Printz

    March 22, 2019 at 2:43 pm in reply to: Expression to Create Arcs in After Effects

    There is no way to do this ‘correctly’ natively prior to AE2017 october update, but there is a cheat.

    My friend Paul Conigliaro did develop a technique and wrote a plugin to do this: what it does is duplicate the shapelayer and path onto a guide layer, add a micro trim path (e.g, Start: 99.9, End:100), and then add a round-end stroke of 1 pixel to essentially draw a dot at the end of the path.

    On a null layer, it then averages the SourceRecAtTime of the layer and does a world conversion, something like this (not tested, code might be formatted incorrectly):

    target = thisComp.layer("target guide layer");
    target.toComp([target.sourceRecAtTime(time).left+(target.sourceRecAtTime(time).width/2),target.sourceRecAtTime(time).top+(target.sourceRecAtTime(time).height/2)].

    This should be pretty much the position of the center of the end of the trimmed path.

    Alex Printz
    Mograph Designer

Page 9 of 17

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