If statement in Expression that refuses to cooperate.

Moderators: Disciple, zlovatt

Post Reply
NEO_AMiGA
Posts: 20
Joined: September 4th, 2008, 5:55 am

Ooh... Guys... Pulling my hair out over here. I'm stuck at something that SHOULD work and that really is no hard thing at all.

The scenario is that I animate a null that have several other layers linked (with expression) to it. And then those individual layers reaches a certain Y-value I want to "kill" them by setting the opacity to 0. But I want to do that on the frame after they reach this value. And it seems like the valueAtTime only works in scripts and not in expressions. Sooo... I thought that I just bounce a "control value" in a slider or so to get the behavior I want. Should be an easy thing but no matter how I do it I can get it to work. So starting to think that there is something funny going on here that I don't know about.

This is the first expression I tried:

Code: Select all

//Variables
//At what yposition do we "kill" the layer?
ykill = 410; 
opacityBounce  = effect("Opacity Fix Bounce")(1).value;
//opacityBounce = Math.floor(opacityBounce);

//variable for storing the Y-position of the layer
ypos = transform.position[1];

//If we have reached the killframe or are outside the frame
if( (ypos <= ykill) || (ypos > 600) ){
	if(opacityBounce < 2){
		effect("Opacity Fix Bounce")(1).value = 2;
	}
	 else if (opacityBounce == 2){
		effect("Opacity Fix Bounce")(1).value = 3;
	}
}

//Text visible
else{
	effect("Opacity Fix Bounce")(1).value = 1;
}
But it's a no go. For some reason it keeps going back into the if(opacityBounce < 2) even though opacityBounce is 2. So it never sets the slider value (effect("Opacity Fix Bounce")(1).value) to 3.

Soo... After slamming my head to the desk a couple of hours and trying variations of that expression i tried something like:

Code: Select all

//Variables
//At what yposition do we "kill" the layer?
ykill = 410; 
opacityBounce  = effect("Opacity Fix Bounce")(1).value;

//variable for storing the Y-position of the layer
ypos = transform.position[1];

//If we have reached the killframe or are outside the frame
if( ( (ypos <= ykill) || (ypos > 600) ) && (opacityBounce = 1) ){
	effect("Opacity Fix Bounce")(1).value = 2;
}

else if( ( (ypos <= ykill) || (ypos > 600) ) && (opacityBounce = 2) ){
	effect("Opacity Fix Bounce")(1).value = 3;
}

//Text visible
else{
	effect("Opacity Fix Bounce")(1).value = 1;
}
But it still never sets the slider to 3. And I can not understand why. When writing all these I got a bit uncertain to if it should be two "=" when checking the value in opacityBounce. LIke:

Code: Select all

if(opacityBounce = 2){
or

Code: Select all

if(opacityBounce == 2){
I was almost 100% certain that it should be "==". But that's a no go in all cases. Which I find odd? Have I missed something fundamental in AE? Or what's going on here. I'm going so nuts that I don't know what to do or where to go or what to break. =(

Or is there an easier way to from Expressions set a "valueAtTime"...?
NEO_AMiGA
Posts: 20
Joined: September 4th, 2008, 5:55 am

I have tried some more, since I'm a stubborn old bastard.

At frame 151 the layer in question get's to the Y position 410. Then it stays there for 20 frames.

Test 4563:

Code: Select all

//Variables
//At what yposition do we "kill" the layer?
ykill = 410; 
opacityBounce  = effect("Opacity Fix Bounce")(1).value;
//opacityBounce = Math.floor(opacityBounce);

//variable for storing the Y-position of the layer
ypos = transform.position[1];

//If we have reached the killframe or are outside the frame
if( (ypos <= ykill) || (ypos > 600) ){
	if(opacityBounce == 1) effect("Opacity Fix Bounce")(1).value = 2 else effect("Opacity Fix Bounce")(1).value = 3
}

//Text visible
else effect("Opacity Fix Bounce")(1).value = 1;
Result: It set's the slider to 3 at frame 151 and leaves it there

Test 4564:

Code: Select all

//Variables
//At what yposition do we "kill" the layer?
ykill = 410; 
opacityBounce  = effect("Opacity Fix Bounce")(1).value;
//opacityBounce = Math.floor(opacityBounce);

//variable for storing the Y-position of the layer
ypos = transform.position[1];

//If we have reached the killframe or are outside the frame
if( (ypos <= ykill) || (ypos > 600) ){
	if(opacityBounce < 2) effect("Opacity Fix Bounce")(1).value = 2 else effect("Opacity Fix Bounce")(1).value = 3
}

//Text visible
else effect("Opacity Fix Bounce")(1).value = 1;
if(opacityBounce == 1) have been changed to if(opacityBounce < 2)... With this it changes the slider to 2 at frame 151 and leaves it there. But why doesn't it change it to three when it runs the expression on frame 152...!? I just don't get it. =(
NEO_AMiGA
Posts: 20
Joined: September 4th, 2008, 5:55 am

...oh btw. Forgot some essentioal information. These expressions are added to a Expression Control Slider on the animated text later. That Expression Control Slider is the "Opacity Fix Bounce" slider.
Dan Ebberts
Posts: 320
Joined: June 26th, 2004, 10:01 am
Location: Folsom, CA
Contact:

I think the problem you're having is the result of the fact that when an expression accesses the value of the property to which the expression is applied (slider in your case), what it gets is the pre-expression value. So an expression has no way of passing information to itself from one frame to the next. So the expression can change the value, but when it runs again at the next frame, it will retrieve the original, pre-expression value.

Dan
Mylenium
Posts: 139
Joined: July 20th, 2005, 12:07 am

NEO_AMiGA wrote:And it seems like the valueAtTime only works in scripts and not in expressions.
It does. It's however merely a read-only method, which is only logical for a system, that evaluates at every frame anyways. As for the rest - well, consider for a moment, that you are permanently changing the start value of the slider with your expression which then in turn serves as the base for the next comparison. Your syntax simply cannot work. You'd need a loop for that, but that's not necessary, if you follow the next point. You also fail to do a layer space conversion for the parented layers, which is the second reason why this will never work - technically, the siblings do not move at all in AE's way of thinking. Once you get that cleared up, you will not need any sliders at all and can compare the threshold distance directly.

Mylenium
[Pour Mylène, ange sur terre]
Dan Ebberts
Posts: 320
Joined: June 26th, 2004, 10:01 am
Location: Folsom, CA
Contact:

I would think something like this would get you closer:

ykill = 410;

ypos = toWorld(transform.anchorPoint)[1];
oldypos = toWorld(transform.anchorPoint, time - thisComp.frameDuration)[1];

if ((ypos >= yKill) && (oldypos >= ykill) && (ypos < 600){

*** do stuff

}else{

*** do other stuff

}


Dan
NEO_AMiGA
Posts: 20
Joined: September 4th, 2008, 5:55 am

I'm not all clear to what this will do. But I wil play with it tomorrow. Thanks!
Dan Ebberts wrote:I would think something like this would get you closer:

ykill = 410;

ypos = toWorld(transform.anchorPoint)[1];
oldypos = toWorld(transform.anchorPoint, time - thisComp.frameDuration)[1];

if ((ypos >= yKill) && (oldypos >= ykill) && (ypos < 600){

*** do stuff

}else{

*** do other stuff

}


Dan
NEO_AMiGA
Posts: 20
Joined: September 4th, 2008, 5:55 am

Hey Dan

I could not sit still so started to look at this. But could you just maybe tell me a bit about this:
ypos = toWorld(transform.anchorPoint)[1];
oldypos = toWorld(transform.anchorPoint, time - thisComp.frameDuration)[1];

Can't really wrap my head around what it'll do.
Dan Ebberts wrote:I would think something like this would get you closer:

ykill = 410;

ypos = toWorld(transform.anchorPoint)[1];
oldypos = toWorld(transform.anchorPoint, time - thisComp.frameDuration)[1];

if ((ypos >= yKill) && (oldypos >= ykill) && (ypos < 600){

*** do stuff

}else{

*** do other stuff

}


Dan
Dan Ebberts
Posts: 320
Joined: June 26th, 2004, 10:01 am
Location: Folsom, CA
Contact:

toWorld(transform.anchorPoint) gives you the world position of a layer. You'd only need to do it this way if the layer is a child of another layer. If not, you could just use transform.position and transform.position.valueAtTime(time - thisComp.frameDuration) (which gives you the position at the previous frame).

Hope that helps.

Dan
NEO_AMiGA
Posts: 20
Joined: September 4th, 2008, 5:55 am

Weeo! Thanks man! Now it works, couldn't have made it without you!

Code: Select all

//Variables
//At what yposition do we "kill" the layer?
ykill = 410;

ypos = transform.position[1];
oldypos = transform.position.valueAtTime(time - thisComp.frameDuration)[1] ;

//If we have reached the killframe or are outside the frame
if((ypos <= ykill) && (oldypos <= ykill) && (ypos < 600)){
	transform.opacity.value = 0;
}

else{
	transform.opacity.value = 100;
}
Guess it could be tighten up a bit more depending on how one write the expression, but guess thats a matter of taste and so. Thanks once again Dan!
Dan Ebberts wrote:toWorld(transform.anchorPoint) gives you the world position of a layer. You'd only need to do it this way if the layer is a child of another layer. If not, you could just use transform.position and transform.position.valueAtTime(time - thisComp.frameDuration) (which gives you the position at the previous frame).

Hope that helps.

Dan
Post Reply