Forum Replies Created

Page 4 of 1081
  • Dan Ebberts

    July 22, 2025 at 3:54 pm in reply to: Path interpolation limitation?

    I’m confused by your mention of the values of keyframes 2 and 3, but this example might be helpful. It will interpolate directly between the path values at keyfames 1 and 4 over the time defined by tStart and tEnd. It assumes that the path has the same number of points at keyframes 1 and 4:

    function interp(a1,a2,pct){
    a = [];
    for (var i = 0; i < a1.length; i++){
    a.push(linear(pct,0,1,a1[i],a2[i]));
    }
    return a;
    }
    tStart = 0;
    tEnd = 1;
    t1 = key(1).time;
    t2 = key(4).time;
    t = linear(time,tStart,tEnd,0,1);
    p1 = points(t1);
    p2 = points(t2);
    p = interp(p1,p2,t);
    i1 = inTangents(t1);
    i2 = inTangents(t2);
    i = interp(i1,i2,t);
    o1 = outTangents(t1);
    o2 = outTangents(t2);
    o = interp(o1,o2,t);
    createPath(p,i,o,isClosed())
  • Dan Ebberts

    July 13, 2025 at 9:50 pm in reply to: Bounce out expression needed

    That one is difficult to run backwards (if that’s what you meant) because there’s no definite end point, but maybe something like this would be useful:

    val = value;
    if (numKeys > 1){
    n = nearestKey(time).index;
    if (key(n).time > time) n--;
    if ((n > 0) && (n < numKeys)){
    d = key(n+1).time-key(n).time;
    dv = key(n+1).value-key(n).value;
    t = (time-key(n).time)/d;
    val = key(n).value + dv*t*t*(2.70158*t - 1.70158);
    }
    }
    val
  • Sorry, I didn’t test it before. This seems to work:

    font01 = "ProximaNova-Black";
    font02 = "ProximaNovaCond-Black";
    font03 = "ProximaNovaExCn-Black";
    font04 = "ProximaNovaExWd-Black";
    font05 = "ProximaNovaWide-Black";
    font06 = "ProximaSera-Black";
    font07 = "ProximaSoft-Black";
    font08 = "ProximaSoftCond-Black";
    font09 = "ProximaSoftExCn-Black";
    dropMenu = comp("Master").layer("Control").effect("Dropdown Menu Control")("Menu").value-1;
    const fontArray = [font01, font02, font03, font04, font05, font06, font07, font08, font09];
    const iterator = fontArray[dropMenu];
    txt = text.sourceText;
    n = comp("Master").layer("Control").effect("Text Width")("Slider");
    outStr = "";
    newLine = "";
    splt = txt.split(" ");
    function txtp() {
    for (i = 0; i < splt.length; i++) {
    if ((newLine + " " + splt[i]).length > n) {
    if (outStr != "") outStr += "\r";
    outStr += newLine;
    newLine = splt[i];
    }else{
    if (newLine != "") newLine += " ";
    newLine += splt[i];
    }
    }
    if (newLine != "") {
    if (outStr != "") outStr += "\r";
    outStr += newLine;
    }
    return outStr;
    }
    text.sourceText.style
    .setFont(iterator)
    .setText(txtp())
  • Try changing the last line to:

    .setText(txtp())
  • Dan Ebberts

    June 26, 2025 at 11:09 pm in reply to: Autoscale Text Box for two lines of text

    Assuming your text layers (“Text 1” and “Text 2”) have checkboxes to indicate their inclusion in the shape calculation, something like this should work:

    m = 15; // margin
    L1 = thisComp.layer("Text 1");
    L2 = thisComp.layer("Text 2");
    cb1 = L1.effect("Checkbox Control")("Checkbox").value;
    cb2 = L2.effect("Checkbox Control")("Checkbox").value;
    r1 = L1.sourceRectAtTime(time,false);
    r2 = L2.sourceRectAtTime(time,false);
    ul1 = L1.toComp([r1.left,r1.top]);
    lr1 = L1.toComp([r1.left+r1.width,r1.top+r1.height]);
    ul2 = L2.toComp([r2.left,r2.top]);
    lr2 = L2.toComp([r2.left+r2.width,r2.top+r2.height]);
    if (cb1 && cb2){
    l = Math.min(ul1[0],ul2[0]); // left
    r = Math.max(lr1[0],lr2[0]); // right
    t = Math.min(ul1[1],ul2[1]); // top
    b = Math.max(lr1[1],lr2[1]); // bottom
    }else if (cb1){
    l = ul1[0];
    r = lr1[0];
    t = ul1[1];
    b = lr1[1];
    }else if (cb2){
    l = ul2[0];
    r = lr2[0];
    t = ul2[1];
    b = lr2[1];
    }else{
    l = r = t = b = -100;
    }
    p = [fromComp([l-m,t-m]),fromComp([r+m,t-m]),fromComp([r+m,b+m]),fromComp([l-m,b+m])];
    createPath(p,[],[],true)
  • Try it this way:

    var yRot = thisComp.layer("MASTER").transform.yRotation;
    if (yRot< -63 || yRot > 63)
    0
    else if (yRot >= 50 && yRot <= 63)
    linear(yRot,50,63,100,0)
    else if (yRot <= -50 && yRot >= -63)
    linear(yRot,-63,-50,0,100)
    else
    100
  • Ah, yes. I didn’t consider that. I’d try it like this:

    L = thisComp.layer("Shape Layer 1");
    ellipse = L.content("Ellipse 1");
    p = ellipse.content("Path 1").path;
    start1 = ellipse.content("Trim Paths 1").start;
    end1 = ellipse.content("Trim Paths 1").end;
    end2 = ellipse.content("Trim Paths 2").end;
    offset1 = L.transform.anchorPoint;
    offset2 = [-20,20];
    L.toComp(p.pointOnPath(start1/100 + ((end1-start1)/100)*(end2/100))+ offset1 + offset2)
  • First you need to convert the ellipse to bezier (right click on Ellipse Path 1 > Convert to Bezier Path). Then this expression for the the text layer’s position should work:

    L = thisComp.layer("Shape Layer 1");
    ellipse = L.content("Ellipse 1");
    p = ellipse.content("Path 1").path;
    end1 = ellipse.content("Trim Paths 1").end;
    end2 = ellipse.content("Trim Paths 2").end;
    offset1 = L.transform.anchorPoint;
    offset2 = [-20,20];
    L.toComp(p.pointOnPath((end1/100)*(end2/100))+ offset1 + offset2)

    Adjust offset2 to move the text slightly off the path (or set it to [0,0] if you want the text right on the trim path end point)

  • Dan Ebberts

    June 15, 2025 at 7:06 am in reply to: Get Max value from graphic.

    Not directly from the graph editor, but you can analyze whatever property is driving the graph, with something like this:

    prop = thisComp.layer("White Solid 1").effect("Slider Control")("Slider");
    for (i = 0; i <= thisComp.duration; i += thisComp.frameDuration){
    max = (i == 0) ? prop.valueAtTime(i) : Math.max (max, prop.valueAtTime(i));
    }
    max

    but there will be a tradeoff between resolution and processing time. The example above checks the value every frame, but you could change it to check more often if you need finer resolution.

  • Ah, I missed the template literal. So once you change the curly quotes to straight quotes and get rid of the http:// stuff, this should work:

    let layerNames = "";
    for (let i = 1; i <= thisComp.numLayers; i++) {
    if (i === index) continue;
    let targetLayer = thisComp.layer(i);
    if (targetLayer.active) {
    layerNames += 'Layer Index:${targetLayer.index} - ${targetLayer.name}\r';
    }
    }
    layerNames.trim();
Page 4 of 1081

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