Creative Communities of the World Forums

The peer to peer support community for media production professionals.

Activity Forums Adobe After Effects Expressions Get path to property of a layer

  • Get path to property of a layer

    Posted by Jakob Wagner on August 12, 2016 at 1:29 pm

    Hi

    I’m trying to get and store, in a variable, the path to the selected property in a layer. Later I will be using this path to set the same property.
    I’m a bit confused about how it works. This is my layer:

    My script so far:
    var comp = app.project.activeItem;
    var selectedProperties = comp.selectedProperties;
    var property = selectedProperties[0];
    alert(“Index: “+property.propertyIndex+”, Depth: “+property.propertyDepth+”, Parent: “+property.parentProperty.name);

    If I select Stroke Width I get:
    Index: 5, Depth: 5, Parent: Stroke 1

    If I select Stroke 1 I get:
    Index: 2, Depth: 4, Parent: Contents

    If I select Contents I get:
    Index: 2, Depth: 1, Parent: circle

    Why is parent of Stroke 1 Contents, and not Ellipse 1? If stroke 1 is Depth 4 and Contents is Depth 1, there must be an invisible propertyGroup?

    Any clues of this behaviour? Any good tips on how to get the full path to a selected property?

    Thanks,
    Jakob

    PS. I know of gimme prop path plugin which pretty much do this, however, I need to do it with code.

    Jakob Wagner replied 9 years, 8 months ago 2 Members · 7 Replies
  • 7 Replies
  • Xavier Gomez

    August 13, 2016 at 2:19 pm

    Shape layers and shape groups within them have a “Contents” property.
    The shape layer’s content is not elided (see propertyGroup.elided attribute in the scripting guide) and has matchName “ADBE Roots Vector Group”.
    A shape group’s content is elided (does not appear in GUI) and has matchName “ADBE Vectors Group”.

    The parent of Ellipse 1 is not the “contents” of the shape but the contents of the group.
    It might look a bit convoluted at start, but once you have understood these two differences it’s fine.

    Xavier

  • Xavier Gomez

    August 13, 2016 at 2:22 pm

    Sorry , in the before last line, i meant Ellipse Path 1 (which is in the content of the group), not Ellipse 1 (which is the group itself)

  • Jakob Wagner

    August 15, 2016 at 9:24 am

    I knew it, it was a trap!
    Thank you Xavier. Now it makes better sense.

    For other interested I ended up with this code, which works. (for now)

    function testButtonClick()
    {
    var comp = app.project.activeItem;
    var layers = comp.selectedLayers;
    var layer = layers[0];
    var selectedProperties = comp.selectedProperties;
    var property = selectedProperties[0];

    var propPath = getPropPath(property);
    var prop = eval("layer.property"+getPropPath(property));
    alert(prop.value)
    }

    function getPropPath(prop)
    {
    var layerRoot = false;
    var propPath = "";

    while(prop.parentProperty)
    {
    propPath = "('"+prop.name+"')"+propPath;
    prop = prop.parentProperty;
    }
    return propPath;
    }

  • Xavier Gomez

    August 15, 2016 at 9:54 am

    Be careful with “prop.name” as it is often not a reliable enough identifier.
    Some properties in the same group can share the same name, as in indexed groups, or in effects (in later versions, some properties names of Adobe’s effects have been changed so that they don’t have the same name, but in earlier versions you could have several time the same property name in a given effect).

    Xavier

  • Jakob Wagner

    August 15, 2016 at 12:06 pm

    Alright. Thank you for the warning. I have changed this line:
    propPath = “(‘”+prop.name+”‘)”+propPath;
    to this line:
    propPath = “(“+prop.propertyIndex+”)”+propPath;

    And it works too. Is that better?

    Can I ask you one last question? I’m using “prop.parentProperty” to detect if the property is a layer. A layer does not have a parent. Is there a better way of doing that? I tried instanceof, but I couldn’t get it to work.

  • Xavier Gomez

    August 15, 2016 at 6:32 pm

    instanceof won’t work because not all layers have the same constructor (can’t remember the exact names, but i think text layers are instanceof TextLayer, shape layers of ShapeLayer, layers with source of AVLayer, etc, something like that, and they also have distinct matchNames).
    while (prop.parentProperty) is completely fine.
    You could also replace by : while (prop.propertyDepth>0) (that’s what i use, but it’s not better).

    For the path itself, i think that for children of a named group, using propertyIndex or matchName makes no difference.
    For children of an indexed group, it really depends on the usage of your script, because matchName can’t work (most of the time all children have the same matchName, so it can’t be a reliable identifier), and between the time you identify the property and the time you use the path, the user may have changed its position in the property stack, hence propertyIndex can also be unreliable.

    Last tip: you should use try{}catch(){} around the eval, because the property may be gone/invalid.
    You could also avoid the use of eval by saving the path as an array of identifiers, not a string, and looping over the array entries to recover the property. Then no need of try/catch.

    Hope that helps.

    Xavier.

  • Jakob Wagner

    August 16, 2016 at 8:06 am

    Hi Xavier

    Thank you very much for taking the time. This is great info!

    Have an awesome day,
    Jakob

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