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

Accessing the essentialProperty() function for a Comp

Contributor ,
Sep 16, 2021 Sep 16, 2021

I'm having fun with the Essential Graphics panel, and the ability to create reusable components. Coupled with power in expressions, this stuff is amazing.

 

I've run into an issue, though. With the Essential Graphics panel you create "Essential Properties" for a comp. You can reference these with the powerful .essentialProperty() function. Great!

 

The problem becomes that you can only use .essentialProperty() on a layer, not on a comp. But the Essential Properties are a feature of a comp, not a layer. So now I have to somehow reference the parent where the comp is used, then the layer that is the comp I'm in, then the properties. So you end up with:

 

    comp("parentComp").layer(thisComp.name).essentialProperty("whatever");

 

But... there is no parentComp() function. So at run time who knows what the containing Comp is called? And any attempt to reference the .essentialProperty() function on a Comp fails, such as thisComp.essentialProperty() or comp("whatever").essentialProperty(). It has to be a layer, for some reason. Even though essential properties are an element of the comp.

 

Does anyone know a workaround for this? This seems like a huge oversight in the creation of Essential Properties.

TOPICS
Expressions , How to
1.7K
Translate
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
LEGEND ,
Sep 16, 2021 Sep 16, 2021

You have a misunderstanding. Why should/ could there even be such a thing as parentComp(), given that any comp can be used a million times as a sub-comp across different comps and different nesting levels?! See the problem? This would simply cause a logic paradox and that pretty much is a clear reason why there can never be such a function unless they completely change that stuff and e.g. expose the internal IDs/ magic numbers AE uses to check dependencies. So no, there is no way to do any of that, at least at the moment.

 

Mylenium

Translate
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 ,
Sep 17, 2021 Sep 17, 2021

Wow, missed the point entirely. I completely understand that there can't be a parentComp() function. That WAS the point.

 

Because you can't do that, there is no generic way to access the .essentialProperties() for the current comp. Those Essential Properties are an element of the comp, you create them on the comp. But because you can only do .essentialProperty() on an instantiated layer, there is no generic way to access them.

 

The point is that .essentialProperty() should not be a function of a layer, but rather of a comp. You should be able to say thisComp.essentialProperty() or comp("fred").essentialProperty().

 

As it now stands, the inability to do what you just said is impossible, is precisely the reason why having .essentialProperty() be a function of a layer IS the problem. There is NO way to say parentComp.thisLayer.essentialProperty() exactly because of the issue you point out.

Translate
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 ,
Sep 17, 2021 Sep 17, 2021

Also, I note you've made this very comment a number of times, going back several years.

 

Virtually every object oriented piece of software faces this same issue: class vs an instance of a class. They all have functional capability to resolve this, class code that has the capability to refer to either all instances, or this specific instance of the class. This is not a new problem, either for software or for AE.

Translate
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 ,
Sep 18, 2021 Sep 18, 2021

Using a Null Object, you could "store" the properties of a comp for use with Essential Graphics, but all that would do is report them to the essential properties.  You wouldn't be able to alter them.  However, if you were to take your Comp and place it into another comp and use that second comp with Essential Graphics, then all the first comp's properties might be open to you.  I say might as I'm not sure what you'd hoping to adapt.  And with the method I describe, you'll be doing a lot of pickwhiping of properties so that the second comp can update the layers but that would get you the end result (I think), even if it feels convoluted.

Translate
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 ,
Sep 18, 2021 Sep 18, 2021

Well, there's already a lot of "pick whipping" going on, becuase I'm doing this in expressions 🙂

 

The issue I'm facing is that I have an object with a "state" control (hidden, painting, normal, highlighted, and so on). That control is a drop down menu in a "controls" layer.. It also is an Essnetial Property. When the state changes, I do a short animation (paint it, highlight it, whatever). When you keyframe this state changes, I look back at the "last key" get it's time, and do the animation from that. Works locally. Sweet!

 

Yet doesn't work if you keyframe the essential property, because it's another context. OK, so I look at the comp above, find myself as a layer with .layer(thisLayer.name) and do .essentialProperty() on that. Works great. Again, sweet!

 

The problem comes when you want to make this whole thing a reusable object. The top level essential properties are the issue. I don't know (or don't want to have to know) the name of the comp it's used in. And so, it's all broken. This could be solved with thisComp.essentialProperties(). But alas, that doesn't work.

 

All this noise said, you have given me a great idea. I'm going to use a null (actually my control layer) to "store" the last state, and the time of the last state change. I should be able to do the animation off of that.

 

Unless you or someone knows how to have some animation kick off whenever some value changes, that seems to be my best choice.

 

Thanks for the idea. Really appreciate your response.

Translate
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 ,
Sep 18, 2021 Sep 18, 2021

Might not be an exact solution, but this expression from Dan Ebberts fades a layer based on a keyframe:

fadeTime = framesToTime(20);
s = effect("Slider Control")("Slider");
if (s.numKeys > 0){
n = s.nearestKey(time).index;
if (time < s.key(n).time) n--;
if (n > 0)
linear(time - s.key(n).time,0,fadeTime,100,0)
else
0;
}else
0

 

 

 

 

Translate
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 ,
Sep 18, 2021 Sep 18, 2021

Yep, that's exactly the code I found and copied. Works great. 🙂

 

The problem agian, is if, in his example, the Slider Control is used in an Essential Property, it breaks. There are no keys on the local effect, only on the Essential Property's copy of the effect. But as I noted, you can get at use .essentialProperty("Slider Control") and it works. I thought I was golden. Then... alas, if you don't know the comp you're in, you're hosed.

 

That said, I think I have a workaround. I'm going to store the last value of the control, and the time the last value changed, both in slidesrs in the control layer, and animate from that. Or at least that's what I'm going to try. That way I don't need the keyframe data. Wish me luck 🙂

Translate
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 ,
Sep 19, 2021 Sep 19, 2021
LATEST

And... I've solved it. It's not pretty, but I solved it with one additional slider. That slider that I call "Delta" has this code in it:

    s = effect("State")("Menu");
    t = time;
    while ((t > 0) && (s.value == s.valueAtTime(t))) {
        t = t - thisComp.frameDuration;
    }
    t;

That Delta slider now contains the last time the state menu changed. From that I can do things in other layers, for example, in their opacity, that look like this:

    m = thisComp.layer("Controls").effect("State")("Menu");
    if (m.value == 5) {
        d = thisComp.layer("Controls").effect("Anim Duration")("Slider");
        t = thisComp.layer("Controls").effect("Delta")("Slider"); 
        easeOut(time, t, t+d, 0, 100);
    } else {
        0
    }
 
And this works perfectly. Regardless of how many layers deep the comp is in essential properties. I don't have to reference the enclosing comp, ever. And it even works regardless of the start point of the sub comp's layer in the master comp. Yee, haa!
Translate
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