【AEスクリプト】コンポの外にあるキーを尺内の最後に持ってくる 『MoveHidingKeysToEnd』

修正時、尺調整してるときに、たま~に「コンポ尺より後ろにキーがあるけど、レイヤーをスライドさせて尺内に持ってくるのが大変」ということがあります。そんなときにお使いください。UIはありません。

以下のコードをテキストにコピーして、拡張子を.jsxにすれば完成です。
右上のマークをクリックすれば全文をコピーできます。

(function (aGbl) {
    //----------------------------------------------------------------------------------------------------------------------
    try{
        mMoveHidingKeysToEnd();
    }catch(e){
        app.endUndoGroup();
        alert(e.message + e.line);
    }
    //--------------------------------------------------------   
    function mMoveHidingKeysToEnd(  ){
        app.beginUndoGroup("MoveHidingKeysToEnd");
    
        var mAi = app.project.activeItem;
        var mSls = mAi.selectedLayers;
    
        var mTimeAllF = mAi.time;
        for( var k =0; k<mSls.length ; k++ ){
            var mSl = mSls[k];
            
            var mProps = mGetAllKeyProps(mSl);
            if( mProps.length === 0 ){ continue;}
            
            //コンポのアウト時間を得ておく。
            var mCmpOutTime = mAi.duration - mAi.frameDuration;
            
            //コンポのアウト時間より後にキーがあるプロップのみにする。
            var mOutProps = [];
            labelI:
            for( var i =0; i<mProps.length ; i++ ){
                var mProp = mProps[i];
                for( var j = 1; j<=mProp.numKeys ; j++ ){
                    var mKeyTime = mProp.keyTime(j);
                    if( mCmpOutTime < mKeyTime ){
                        mOutProps.push( mProp );
                        continue labelI;
                    }
                }
            }
            mProps = mOutProps;
            if( mProps.length === 0 ){ continue;}
  
            //ペーストするときの先頭時間を出す。
            //コンポのアウト時間を基準位置として、そこから対象キー群の先頭~最後尺ぶんもどった時間位置。
            //ついでに各キー時間が入った配列も作っておく。
            var mKeyTimes = [];
            var mKeyTimess = [];
            for( var i =0; i<mProps.length ; i++ ){
                var mProp = mProps[i];
                var mKeyTimesTp = [];
                for( var j = 1; j<=mProp.numKeys ; j++ ){
                    var mKeyTime = mProp.keyTime(j);
                    if( mCmpOutTime < mKeyTime ){
                        mKeyTimesTp.push( mKeyTime );
                        mKeyTimes.push( mKeyTime );
                    }
                }
                mKeyTimess.push( mKeyTimesTp );
            }
            mKeyTimes.sort( function( a , b ){ return a - b; } );
            var mKeyTimeF = mKeyTimes[0];
            var mKeyTimeL = mKeyTimes[mKeyTimes.length-1];
            var mIndcTime = mCmpOutTime - ( mKeyTimeL - mKeyTimeF );
            
    
            //プロップごとに処理する。
            for( var i =0; i<mProps.length ; i++ ){
                var mProp = mProps[i];

                //コンポのアウト時間以降のキーの最初の番号と数を得る。
                var mCntr = 0;
                var mFstNum = null;
                for( var j =1; j <= mProp.numKeys; j++ ){
                    if( mCmpOutTime < mProp.keyTime(j) ){
                        if( mCntr === 0 ){ mFstNum = j;}
                        mCntr++;
                    } 
                }
                if(mFstNum === null ){ continue;}
            
                //ペースト時間位置を割り出す。
                //インジケータ基準時間+ (  対象プロップ先頭キー時間 -  全先頭キーの時間)。 
                var mTgtTime = mIndcTime + ( mKeyTimess[i][0] - mKeyTimeF );
                //移動させる。
                mMoveKeys(mProp, mFstNum, mCntr, mTgtTime);
            }
            if(k === 0){
                mTimeAllF = mIndcTime;
            }else{ 
                if( mTimeAllF > mIndcTime ){ mTimeAllF = mIndcTime;}
            }
        }
    
        //インジケータを全最前キー時間に移動させる。
        mAi.time = mTimeAllF;
        app.endUndoGroup();
    }
    //----------------------------------------------------------------------------------------------------------------------
    //----------------------------------------------------------------------------------------------------------------------    
    //キーがあるプロパティを集める関数。
    function mGetAllKeyProps(aSl){
        var mSl = aSl;
        var mProps = [];
        for( var i = 1; i<=mSl.numProperties ; i++ ){ mFunc(mSl.property(i));}
          
        function mFunc(aProp){
             if( aProp.propertyType === PropertyType.PROPERTY ){
                 if(aProp.canVaryOverTime && aProp.numKeys !== 0 && !mIsHidden(aProp)){
                    mProps.push( aProp );
                }
            }else{  
                for( var i = 1; i<=aProp.numProperties ; i++ ){
                    mFunc(aProp.property(i));
                }
            }
       }
        return mProps;
    }
    //---------------------------------------------------------------
    //hiddenかどうかを返す関数。キーを全て選択状態にしてしまうが、このスクリプトに関しては問題ない。
    function mIsHidden(aProp){
        try{
            aProp.selected = aProp.selected;
            return false;
        }catch(e){
            return(/hidden/.test(e.message));
        }
    }
    //---------------------------------------------------------------------------------------------------------------------- 
    function mMoveKeys(aProp, aKeyIdxF, aNum, aInsrtTime){
        var mProp = aProp;
        var mInsrtTimeF = aInsrtTime;
        var mNumF = aKeyIdxF;
        var mNumL = mNumF + aNum-1;
        
        //動かす各キーのインサート時間を得る。
        var mInsrtTimes = [];
        var mStdTime = mProp.keyTime(mNumF);
        for( var i = mNumF; i<=mNumL ; i++ ){
            mInsrtTimes.push( (mProp.keyTime(i) - mStdTime) + mInsrtTimeF );
        }
    
        //消す前に情報を得ておく。
        var mInfos = [];
        for( var i = mNumF; i<=mNumL ; i++ ){
            var mInfo = mCreateKeyInfoObj( i, mProp );
            mInfos.push( mInfo );
        }
    
        //対象キーを消す。
        for( var i = mNumL; i >=mNumF ; i-- ){
            mProp.removeKey(i);
        }
    
        //キーを追加していく。//番号がズレる前に都度情報を入れる。
        for( var i = 0; i<mInsrtTimes.length ; i++ ){
            var mAddKeyIdx = mProp.addKey(mInsrtTimes[i]);
            //上記のキー追加で取得した番号のキー情報を変える。
            mApplyKeyInfoObj( mAddKeyIdx, mProp, mInfos[i] );
        }
    }
    //---------------------------------------------------------------------------------------------------------------------- 
    //キー番号から各種情報objを作る関数。
    function mCreateKeyInfoObj( aIdx, aSp ){
        var mSp = aSp;
        var i = aIdx;
        var mObj = {};
        
        mObj.mVal = mSp.keyValue(i);
        //時間補完法関連。
        mObj.mTenEaseIO = [ mSp.keyInTemporalEase(i) , mSp.keyOutTemporalEase(i) ];
        mObj.mTenCont = mSp.keyTemporalContinuous(i);
        mObj.mTenAuto = mSp.keyTemporalAutoBezier(i);
        //空間補完法関連&ロービング。
        var mPropType = mSp.propertyValueType;
        if( mPropType.propertyValueType === PropertyValueType.TwoD_SPATIAL
        || mPropType.propertyValueType === PropertyValueType.ThreeD_SPATIAL){
            mObj.mSpaTngtIO = [ mSp.keyInSpatialTangent(i) , mSp.keyOutSpatialTangent(i) ] ;
            mObj.mSpaCont = mSp.keySpatialContinuous(i);
            mObj.mSpaAuto = mSp.keySpatialAutoBezier(i);
            mObj.mRoving = mSp.keyRoving(i);
        }
        //キー補完種類。
        mObj.mItpTypeIO = [ mSp.keyInInterpolationType(i) , mSp.keyOutInterpolationType(i) ];
        return mObj;
    }
    //-------------------------------------------------------------
    //キー番号のキーに各種情報objを適用する関数。
    function mApplyKeyInfoObj( aIdx, aSp, aObj ){
        var mSp = aSp;
        var j = aIdx;
        var mObj = aObj;
        
        mSp.setValueAtKey( j, mObj.mVal );
        
        //時間補完法関連。
        mSp.setTemporalEaseAtKey(j, mObj.mTenEaseIO[0], mObj.mTenEaseIO[1]);
        mSp.setTemporalContinuousAtKey(j, mObj.mTenCont);
        mSp.setTemporalAutoBezierAtKey(j, mObj.mTenAuto);
        
        //空間補完法関連&ロービング。
        var mPropType = mSp.propertyValueType;
        if( mPropType.propertyValueType === PropertyValueType.TwoD_SPATIAL
        || mPropType.propertyValueType === PropertyValueType.ThreeD_SPATIAL){
            mSp.setSpatialTangentsAtKey(j, mObj.mSpaTngtIO[0], mObj.mSpaTngtIO[1]);
            mSp.setSpatialContinuousAtKey(j, mObj.mSpaCont);
            mSp.setSpatialAutoBezierAtKey(j, mObj.mSpaAuto);
            mSp.setRovingAtKey(j, mObj.mRoving);
        }
        //キー補完種類は最後に適用する。
        mSp.setInterpolationTypeAtKey(j, mObj.mItpTypeIO[0], mObj.mItpTypeIO[1]);
    }   
        
    //---------------------------------------------------------------------------------------------------------------------- 
    //キーフレーム関連プロパティ集。
    /*
    numKeys
    selectedKeys
        
    setValueAtKey()
    nearestKeyIndex()
    keyTime()
    keyValue()
    addKey()
    removeKey()

    ease関連一式

    isInterpolationTypeValid()

    setSelectedAtKey()
    keySelected()

    ease関連一式  
    setInterpolationTypeAtKey(keyIndex, inType, outType)	 //キーフレームの補間の種類を設定。
    keyInInterpolationType(keyIndex)	 //キーフレームの「イン」側の補間方法を取得。
    keyOutInterpolationType(keyIndex)	 //キーフレームの「アウト」側の補間方法を取得。

    //プロパティが_SPATIALでないとエラーとなる。
    setSpatialTangentsAtKey(keyIndex, inTangent, outTangent)	// キーフレームの空間補間法のイン/アウトの接線のベクトルを設定。
    keyInSpatialTangent(keyIndex) 	 //キーフレームの空間補間法のイン/アウトの接線のベクトルを取得。
    keyOutSpatialTangent(keyIndex) 	 //キーフレームの空間補間法のアウト側の接線を取得。

    //イーズは配列。
    setTemporalEaseAtKey(keyIndex, inTemporalEase, outTemporalEase)	 //キーフレームの時間補間法のイージーイーズを設定。
    keyInTemporalEase(keyIndex)	 //キーフレームの時間補間法のイン側のイージーイーズを取得。
    keyOutTemporalEase(keyIndex)	 //キーフレームの時間補間法のアウト側のイージーイーズを取得。

    setTemporalContinuousAtKey(keyIndex, newVal)	 //キーフレームの時間補間法の連続ベジェモードを設定。
    keyTemporalContinuous(keyIndex)	 //キーフレームの時間補間法が連続ベジェモードになっているか。インアウトのInterpolationTypeがBEZIER でないと影響が無い。
    setTemporalAutoBezierAtKey(keyIndex, newVal)	 //キーフレームの時間補間法の自動ベジェモードを設定。
    keyTemporalAutoBezier(keyIndex)	 //キーフレームの時間補間法が自動ベジェモードになっているか。インアウトのInterpolationTypeがBEZIER でないと影響が無い。

    //プロパティが_SPATIALでないとエラーとなる。
    setSpatialContinuousAtKey(keyIndex, newVal)	 //キーフレームの空間補間法の連続ベジェモードを設定。
    keySpatialContinuous(keyIndex)	 //キーフレームの空間補間法が連続ベジェモードになっているか。
    setSpatialAutoBezierAtKey(keyIndex, newVal)	// キーフレームの空間補間法の自動ベジェモードを設定。
    keySpatialAutoBezier(keyIndex)	// キーフレームの空間補間法が自動ベジェモードになっているか。keySpatialContinuousがtrueでないと影響が無い。

    setRovingAtKey(keyIndex, newVal)	 //キーフレームの時間ロービングモードの設定。
    keyRoving(keyIndex) //キーフレームが時間ロービングモードになっているか。
    */
    //----------------------------------------------------------------------------------------------------------------------  
})(this);

使い方

対象のレイヤー(複数可)を選び、スクリプトを起動させると、コンポ尺より後ろにある全てのキーがコンポの最後に移動します。

*もしもすでにコンポ内のラスト付近にキーがあると、そのキーを上書きする可能性があります。なので、コンポ外にあるキーぶんのスペースを確保しておいて実行してください。

解説

各レイヤーの対象キー中の、一番先頭キー時間をゼロとし、他のキー時間はそれとの差分(1次元ベクトル)として保存するのがポイントです。こうしておけば、他の時間位置にペーストする際に、その時間+ベクトルで処理できて便利です。今回はコンポの最後のとこにペーストしましたが、他にもインジケータ時間にペーストするスクリプトを作るときなども、このやり方だと直観的でわかりやすいかなと思います。

コードの最後にまとめてあるコメントは、プロパティオブジェクトのキーフレーム関連プロパティとメソッドをまとめたものです。

参考サイト:
After Effects スクリプトリファレンス

よかったらシェアしてね!
  • URLをコピーしました!