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

Seeking Help with AE Script: Merging Step 2 & Step 2.5 for Keyframe & Separated Dimensions Handling

New Here ,
Mar 27, 2024 Mar 27, 2024

Copy link to clipboard

Copied

Hey!

I'm working on an After Effects script that involves two main functions, Step 2 and Step 2.5, which I'm trying to merge. Individually, they work as intended, but integration has hit a snag, especially concerning properties with separated dimensions.

  • Step 2 (Universal Keyframe Detection & Expression Application): This part duplicates a layer and aims to apply a placeholder expression to any property with keyframes. However, it struggles specifically with properties that have separated dimensions (like "Position" into "X Position" and "Y Position"), not applying expressions as needed.

  • Step 2.5 (Handling Separated Dimensions and Orientation): Focused on properties with separated dimensions, this script part effectively duplicates a layer, clears keyframes, and applies expressions for separated dimensions and the "Orientation" property on 3D layers.

Challenge: The main issue arises when trying to integrate Step 2's broad keyframe handling with Step 2.5's specialized approach for separated dimensions and "Orientation." The expected seamless application of placeholder expressions to properties with separated dimensions (XYZ properties) in Step 2 does not occur, leading to errors like "property or a parent property is hidden."

Request for Advice: I need to create a unified script that can:

  • Duplicate a layer,
  • Identify and remove keyframes from all properties, focusing on ensuring that properties with separated dimensions and "Orientation" are included,
  • Apply a universal placeholder expression to these properties without encountering errors.

I'd greatly appreciate any insights on how to address the issue with separated dimensions in Step 2 or any tips for successfully integrating these functionalities.

Thanks for your support and guidance! 
The below is script Step 2.0

#target aftereffects

(function createComprehensiveDelaySetupUI(thisObj) {
    var scriptName = "Complete Delay Setup with Keyframe Removal";

    function createUI(thisObj) {
        var panel = (thisObj instanceof Panel) ? thisObj : new Window("palette", scriptName, undefined, {resizeable:true});
        if (!panel) return null;

        panel.add("button", undefined, "Apply Keyframe Removal", {name: "applyBtn"}).onClick = function() {
            applyKeyframeRemoval();
        };

        panel.onResizing = panel.onResize = function() { this.layout.resize(); };
        panel.layout.layout(true);
        return panel;
    }

    function applyKeyframeRemoval() {
        var comp = app.project.activeItem;
        if (!comp || !(comp instanceof CompItem)) {
            alert("Please select a composition.");
            return;
        }

        var selectedLayers = comp.selectedLayers;
        if (selectedLayers.length !== 1) {
            alert("Please select exactly one layer.");
            return;
        }

        app.beginUndoGroup(scriptName);

        var baseLayer = selectedLayers[0];
        var delayLayer = baseLayer.duplicate();
        delayLayer.name = baseLayer.name + " Delay 01";

        removeAllKeyframesAndApplyExpression(delayLayer);

        app.endUndoGroup();
    }

    function removeAllKeyframesAndApplyExpression(layer) {
        traverseProperties(layer, function(prop) {
            if (prop.numKeys > 0) {
                for (var k = prop.numKeys; k >= 1; k--) {
                    prop.removeKey(k);
                }
                prop.expression = "\"Placeholder expression for removed keyframes\"";
            }
        });
    }

    function traverseProperties(group, callback) {
        for (var i = 1; i <= group.numProperties; i++) {
            var prop = group.property(i);
            if (!prop) continue;

            if (prop.propertyType === PropertyType.PROPERTY) {
                callback(prop);
            } else if (prop.propertyType === PropertyType.INDEXED_GROUP || prop.propertyType === PropertyType.NAMED_GROUP) {
                traverseProperties(prop, callback); // Recurse into groups
            }
        }
    }

    var myScriptPal = createUI(thisObj);
    if (myScriptPal instanceof Window) {
        myScriptPal.center();
        myScriptPal.show();
    } else {
        myScriptPal.layout.layout(true);
    }
})();



 The script below is Step 2.5

#target aftereffects

(function createDelaySetupUI(thisObj) {
    var scriptName = "Comprehensive Delay Setup for Separated Dimensions and Orientation";

    function createUI(thisObj) {
        var panel = (thisObj instanceof Panel) ? thisObj : new Window("palette", scriptName, undefined, {resizeable: true});
        if (!panel) return null;

        panel.add("button", undefined, "Apply Delay Setup", {name: "applyBtn"}).onClick = function() {
            applyExpressionsToSeparatedPropertiesAndOrientation();
        };

        panel.onResizing = panel.onResize = function() { this.layout.resize(); };
        panel.layout.layout(true);
        return panel;
    }

    function applyExpressionsToSeparatedPropertiesAndOrientation() {
        var comp = app.project.activeItem;
        if (!comp || !(comp instanceof CompItem)) {
            alert("Please select a composition.");
            return;
        }

        var selectedLayers = comp.selectedLayers;
        if (selectedLayers.length !== 1) {
            alert("Please select exactly one layer.");
            return;
        }

        app.beginUndoGroup(scriptName);

        var baseLayer = selectedLayers[0];
        var delayLayer = baseLayer.duplicate();
        delayLayer.name = baseLayer.name + " Delay 01";

        clearAndApplyExpressionIfKeyframed(delayLayer, "position");
        if (delayLayer.threeDLayer) {
            clearAndApplyExpressionIfKeyframed(delayLayer, "rotation");
            handleOrientationIfKeyframed(delayLayer); // Handle Orientation for 3D layers
        }

        app.endUndoGroup();
    }

    function clearAndApplyExpressionIfKeyframed(layer, propName) {
        // This checks for separated dimensions in position and rotation and applies expressions if they had keyframes
        var dimensions = propName === "position" ? ['X Position', 'Y Position', (layer.threeDLayer ? 'Z Position' : null)] : 
                                                     ['X Rotation', 'Y Rotation', 'Z Rotation'];
        dimensions.forEach(function(dimName) {
            if (dimName && layer.transform[dimName] && layer.transform[dimName].numKeys > 0) {
                var dimProp = layer.transform[dimName];
                while (dimProp.numKeys > 0) {
                    dimProp.removeKey(1);
                }
                dimProp.expression = "\"Delayed expression for " + dimName + "\"";
            }
        });
    }

    function handleOrientationIfKeyframed(layer) {
        // This function specifically handles the Orientation property for 3D layers
        var orientationProp = layer.transform.orientation;
        if (orientationProp.numKeys > 0) {
            while (orientationProp.numKeys > 0) {
                orientationProp.removeKey(1);
            }
            orientationProp.expression = "\"Delayed expression for Orientation\"";
        }
    }

    var myScriptPal = createUI(thisObj);
    if (myScriptPal instanceof Window) {
        myScriptPal.center();
        myScriptPal.show();
    } else {
        myScriptPal.layout.layout(true);
    }
})();

 

TOPICS
Scripting

Views

89

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 ,
Mar 28, 2024 Mar 28, 2024

Copy link to clipboard

Copied

LATEST

I don't have the time to understand your issue in full detail, but if you run into issues, where you try to change expresssions or keyframes on hidden properties, maybe before doing this you can

- add a check if the property is a separation leader and also dimensions are separated and if this is the case, you process not the property itself, but the separation followers instead.
- analogously also check if the prop is a separation follower and dimensions are not separated (and in that case process the leader instead).

Mathias Möhl - Developer of tools like BeatEdit and Automation Blocks for Premiere Pro and After Effects

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