• Global community
    • Language:
      • Deutsch
      • English
      • Español
      • Français
      • Português
  • 日本語コミュニティ
    Dedicated community for Japanese speakers
  • 한국 커뮤니티
    Dedicated community for Korean speakers
Exit
0

Expressions that have worked for years, are now plagued with vague error messages.

Contributor ,
Jun 27, 2019 Jun 27, 2019

Copy link to clipboard

Copied

since the latest AE update 16.1.2 I have a fairly bulletproof expressions system that just doesn't work.

the error message is non-descriptive, and its in the wrong place. I can't even find where AE is having the issue.

What has been changed in AE's expression language? I can't find ANYTHING on it.

the error I am getting is:

Error: Object of type (there's a double space here, like it expected to be able to put a word in the error at this point, and it didn't come up with anything)  found where a Number, Array, or Property is needed

it happens on Line 01 of a fairly complicated expression... which is a comment.

looks like it means the first line of actual code, which looks like this:

var correctRailID = 29.0562;

the NEXT line invokes a function I wrote... which has worked for 5 years without a single hiccup.

function idLayers(ralId){

// get all layers in comp.

var count = thisComp.numLayers;

var i = 1;

var anArray = [];

for(i = 1; i <= count; i ++){

  try{

  //var constantVal = ralId;

  var iValue = thisComp.layer(i).effect("railID")("Slider").value;

  if(iValue == ralId){

  // then we have a match. put it on the list.

  anArray.push(thisComp.layer(i));

  }

  } catch(err){

  // ignore errors

  }

}

  return anArray.reverse();

}

I'm not seeing anything that shouldn't just work.

TOPICS
Expressions

Views

1.1K

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines

correct answers 1 Correct answer

Community Expert , Jun 27, 2019 Jun 27, 2019

Votes

Translate

Translate
Community Expert ,
Jun 27, 2019 Jun 27, 2019

Copy link to clipboard

Copied

It would help to see the whole expression.

Dan

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Contributor ,
Jun 27, 2019 Jun 27, 2019

Copy link to clipboard

Copied

I got to ask : does it REALLY help to see the full expression? because this thing is not only fairly big as expressions go, it's part of a system. I suspect you'd need the whole darned thing, and then we're talking about an entire project.

I'm working through it. it looks like (and I cannot 'know' because the debugger is buggered to heck)

a function called : layersRelevantToTime is returning gibberish.

so I've duplicated it's behavior in the main Logic (at the bottom) and I'm trying to see what's what.

I had trouble getting AE to return arrays of layers in the past. You might even see a comment to that effect somewhere in that mish mash. I'm wondering if that's what's going on here. commenting out anything that tries to get layersRelevantToTime seems to evaluate.

// ----------------------------------------------------------------------------- //

//           functions:

// ----------------------------------------------------------------------------- //

// ----------------------------------------------------------------------------- //

function orderedLayers(theArray){

  // the one with the earliest inPoint.

var earliest = theArray[0]

var second = theArray[1]

var andex = 0;

for(andex = 0; andex < theArray.length; andex ++){

  if(theArray[andex].inPoint < earliest.inPoint){

  second = earliest;

  earliest = theArray[andex];

  }

}

  return [earliest,second]

}

// ----------------------------------------------------------------------------- //

// does the bulk of the work to transition from 1 layer to the next.

// assumes the layers have certain features: handles for instance.

function doTransition(startLayer, stopLayer){

// now get the points. in WorldCoords.

var startPT = startLayer.toWorld(startLayer.anchorPoint);

var stopPT = stopLayer.toWorld(stopLayer.anchorPoint);

var startHPt = startLayer.effect("outgoingHandle")("3D Point");

var stopHPt = stopLayer.effect("incomingHandle")("3D Point");

// thats the 4 spline points.

// now get our position along the spline.

var duration =  stopLayer.inPoint - startLayer.outPoint ;

// now we used to just average accorss the ease. looked like this: renderVal = ease((time - M.inPoint) / dur, outVal, inVal);  but now we want to get the progress 0 - 1 eased.

var uneasedProg = (time - startLayer.outPoint)/duration; 

var progress = easeInOutQuad((time - startLayer.outPoint)/duration); // eased.

//had to reverse the order of points, bc that makes it go forward.

return (pointOnSpline(stopPT, stopHPt, startHPt, startPT, progress))

}

// ----------------------------------------------------------------------------- //

// returns position data for 3d Position along a spline, given 4 points and a position.

// getting seriously anomolous results from the Z channel. looking for bad coding, and hoping it's not math.

function pointOnSpline(cpZero, cpOne, cpTwo, cpThree, t){

  var retArray = [];

var cx = 3.0* (cpOne[0] - cpZero[0]);

var bx = 3.0 * (cpTwo[0] - cpOne[0]) - cx;

var ax = cpThree[0] - cpZero[0]- cx - bx;

// ok to here.

var cy = 3.0* (cpOne[1] - cpZero[1]);

var by = 3.0 * (cpTwo[1] - cpOne[1]) - cy;

var ay = cpThree[1] - cpZero[1]- cy - by;

// ok to here.

var cz = 3.0* (cpOne[2] - cpZero[2]);

var bz = 3.0 * (cpTwo[2] - cpOne[2]) - cz;

var az = cpThree[2] - cpZero[2]- cz - bz;

var tSquare = t * t;

var tCube = tSquare * t;

// now create the result.

var theX = (ax * tCube) + (bx * tSquare) + (cx * t) + cpZero[0];

var theY = (ay * tCube) + (by * tSquare) + (cy * t) + cpZero[1];

var theZ = (az * tCube) + (bz * tSquare) + (cz *t) + cpZero[2];

retArray = [theX, theY, theZ];

return retArray;

}

// ----------------------------------------------------------------------------- //

// homebrew ease function.

function  easeInOutQuad(t) { return t<.5 ? 2*t*t : -1+(4-2*t)*t }

// ----------------------------------------------------------------------------- //

// compares layers in the list to time. returns in timed order, relevant layers (layers with inpoints/outpoints that overlap current time.

function layersRelevantToTime(theLayers){

  var retArray = []

  var dex = 1;

  for (dex = 0; dex < theLayers.length; dex ++){

  if(theLayers[dex].inPoint <= time && theLayers[dex].outPoint >= time){

  retArray.push(theLayers[dex]);

  }

  }

  return retArray.reverse();

  //return retArray;

}

// ----------------------------------------------------------------------------- //

function idLayers(ralId){

// get all layers in comp.

var count = thisComp.numLayers;

var i = 1;

var anArray = [];

for(i = 1; i <= count; i ++){

  try{

  //var constantVal = ralId;

  var iValue = thisComp.layer(i).effect("railID")("Slider").value;

  if(iValue == ralId){

  // then we have a match. put it on the list.

  anArray.push(thisComp.layer(i));

  }

  } catch(err){

  // ignore errors

  }

}

  return anArray.reverse();

}

// ----------------------------------------------------------------------------- //

//           main logic

// ----------------------------------------------------------------------------- //

var someIdLayers = idLayers(effect("theRailID")("Slider").value);  // get all the layers with the correct rail id

// now we must test if we got anything.

var theCount = someIdLayers.length;

//var theCount = 1;

if(theCount > 0){

  // then we know we have layers out there. at least 1.

  //var myArray = layersRelevantToTime(someIdLayers); // now just get the layers that are alive at this time.

/////var retArray = []

  var myArray = [];

  var dex = 1;

  for (dex = 0; dex < someIdLayers.length; dex ++){

  if(someIdLayers[dex].inPoint <= time && someIdLayers[dex].outPoint >= time){

  myArray.push(someIdLayers[dex]);

  }

  }

  // now test my array.

  var aNewCount = myArray.length;

  //var aNewCount = 1;

  if(aNewCount > 1){

  // if we get at least 2 layers <- good thing.

  var someLayers = orderedLayers(myArray); //  we might get more than 2 active layers so filter out all but the first 2.

  var theVal  = doTransition(someLayers[0], someLayers[1]);   // run the main function.

  theVal;  // set the value.

  }else{

  // with just 1 or less layers.

  if(aNewCount == 1){

  myArray[0].toWorld(myArray[0].anchorPoint);

  }

  if(aNewCount == 0){

  // unlikely but we COULD get no relevant layers.

  transform.position

  }

  }

}else{

  // with no layers, we can't do anything.

  transform.position

}

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Contributor ,
Jun 27, 2019 Jun 27, 2019

Copy link to clipboard

Copied

oh crap... AE is releasing the memory to the layers Array before I can evaluate it.

it has to be.

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Expert ,
Jun 27, 2019 Jun 27, 2019

Copy link to clipboard

Copied

I applied to a layer's position and it didn't have any errors in the Legacy ExtendScript and Javascript engine. Can you explain the setup some more so we can have more context? What does the expression do? Looks like you need a slider named theRailID on your layer, what else needs to be set up?

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Contributor ,
Jun 27, 2019 Jun 27, 2019

Copy link to clipboard

Copied

Justin,

it is an entire replacement animation system for the 3d camera, that I built. It uses a LOT of layers to generate a spline, and does it's own tweening to defeat the terrible built in animation system. the layers for each "station" (I use a railway metaphor to describe the behavior) are intended to overlap in the timeline, and the system automatically transitions the camera (and it's aim target) to constrain to the incoming layer. The whole thing was designed to make those Info-graphic 2.5D 3 minute long camera animations tolerable. You know... the ones where if you even look at the camera's keys sideways, you have to re-edit the entire thing from scratch, because Adobe's tweening engine is FUBAR?

I've even got a scriptUI panel that builds it. the scriptUI panel is necessarily legacy, but the expressions should just be working. they worked just fine in the last version of AE.

I would have to send you a project file, or the scriptUI panel (which wouldn't work, and has multiple errors of the exact same kind, ie: non descriptive, in the wrong place, and largely useless. I don't see any place to attach a binary in this forum.

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Contributor ,
Jun 27, 2019 Jun 27, 2019

Copy link to clipboard

Copied

yeah I just opened up AE v 15.1.2 railCam works without complaint.

Adobe did something to expressions I have not yet found documented.

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Expert ,
Jun 27, 2019 Jun 27, 2019

Copy link to clipboard

Copied

Your best bet is going to be narrowing down your code to identifying the issue, so you have a small snippet that others can test and verify that it's not performing correctly or is behaving differently in a newer release of AE. Sounds like it has something to do with counting layers, but since we're not as familiar with your project as you are, it's hard to help otherwise.

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Contributor ,
Jun 27, 2019 Jun 27, 2019

Copy link to clipboard

Copied

that's what I think too. of course this is all happening on a break neck deadline, and AE 16 has been a royal pain about a few things, so instead of wasting my time trying to make nice with AE 16.1.2... out the airlock it goes. 15.1.2 has no issues doing things the right way.

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Expert ,
Jun 27, 2019 Jun 27, 2019

Copy link to clipboard

Copied

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Contributor ,
Jun 27, 2019 Jun 27, 2019

Copy link to clipboard

Copied

thanks dan, I'll take a good look at that when... deadlines aren't impending.

thanks both of you for taking an interest.

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Expert ,
Jun 27, 2019 Jun 27, 2019

Copy link to clipboard

Copied

You can always try switching to the Legacy ExtendScript engine in Project Settings to see if that fixes it.

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Contributor ,
Jun 27, 2019 Jun 27, 2019

Copy link to clipboard

Copied

aNewCount is evaluating incorrectly for sure.

And that would definitely cause the misplaced error.

in the instance where there should ONLY be a value of 1 in aNewCount, it evaluates to > 1. And of course... asking for index [1] from an array with length == 1 you get an error.

but it gets weirder. in situations where aNewCount should == 2... that is: there are 2 layers at this time, which have a railID equal to the one we are looking for... aNewCount evaluates to == 1.

and then in this line:

myArray[0].toWorld(myArray[0].anchorPoint) causes an error.

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Contributor ,
Jul 12, 2019 Jul 12, 2019

Copy link to clipboard

Copied

in the end... the issue was twofold breaks in expression syntax. and really deserved more flag waving form adobe.

the new Javascript engine:

1. does not allow you to declare functions BELOW your code. gotta do it at the top.

2. requires an else statement for EVERY IF statement.

so if you have :

if {
// do stuff

}

you need:

if {
// do stuff

}else{

}

or it won't work.

dan's link (above) illuminated these issues.

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Expert ,
Jul 12, 2019 Jul 12, 2019

Copy link to clipboard

Copied

1. What you're describing is JavaScript hoisting, read more on that here:

JavaScript Hoisting

Regardless, it's good practice to always declare your variables before using them.

2. Actually, this is not the case. Both the Legacy ExtendScript and the JavaScript Expression engine allow you to exclude else from an if/else statement.

For example, this is a valid expression in both engines:

var res = 100;

if(thisLayer.name == 'test'){

    res = 50;

}

res;

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Contributor ,
Jul 12, 2019 Jul 12, 2019

Copy link to clipboard

Copied

Justin, I tested it. It was so baffling that this is a thing that I played chicken with the expression editor.

My code does not work at all if I do not put an else{ } on every single if{ }

are there qualifications? who knows. Adobe's docs Literally say this:

"Ending an expression in an if statement without an else is not allowed"

while my code is old, it is based on best practices as documented when it was written. I referenced many code examples, thought it was odd that they'd define code after using it, But when in Rome... 

but that's ok. I put Huge commented sections that delineate the section where functions are declared. It's not difficult to do these fixes.

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Expert ,
Jul 12, 2019 Jul 12, 2019

Copy link to clipboard

Copied

> "Ending an expression in an if statement without an else is not allowed"

This makes sense because an expression has to return your result. An if statement doesn't return anything, however expression field seems to override this by looking for the last returned variable:

So basically this throws an error:

var condition = thisLayer.name == 'test';

if(condition === true){

     50;

}

Because firstly, it returns nothing, and secondly, there is no override case in the scenario that the condition is not met.

This does work, however through the overriding nature of AE expressions:

var condition = thisLayer.name == 'test';

if(condition === true){

     50;

}else{

     100;

}

Firstly, it returns nothing, but secondly, through the overriding nature of expressions, it looks for the last returned variable which is either 50 or 100. All scenarios are covered in this example and this is valid.

For clarity's sake, I personally always return the result:

var res;

var condition = thisLayer.name == 'test';

if(condition === true){

     res = 50;

}else{

     res = 100;

}

res;

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Contributor ,
Jul 12, 2019 Jul 12, 2019

Copy link to clipboard

Copied

but I do not return a value INSIDE an if statement.

I define my values at the top of the function, and return them at the bottom.

if statements are seen as potential transforms to the base values in the function.

this helps with readability, and makes the function less maze like overall.

for ex:

func doSomething(){

     var aVal = 0;

     if (test something){
          aVal += 56;
     }
     return aVal

}

that's how all of the code in question is structured. The variable is always returned... unless you're saying that the if statement cannot exit without either a return or an else statement... which is a strange choice for a language to make.

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Expert ,
Jul 12, 2019 Jul 12, 2019

Copy link to clipboard

Copied

LATEST

I'm literally saying what the rule describes, you cannot end an expression with an if statement that doesn't have an else. In your case, you're ending with a function which should be fine.

Converting your example into working code, this works fine in both expression engines, are you experiencing something different?

function doSomething(){

     var aVal = 0;

     var condition = true;

     if (condition){

          aVal += 56;

     }

     return aVal;

}

doSomething();

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines