Skip to main content
T.shusaku
Participant
August 5, 2024
Answered

レイヤーの上下左右の端に、ヌルを親として作成するスクリプト

  • August 5, 2024
  • 2 replies
  • 416 views

以下のスクリプトは、選択した複数レイヤーの矩形の上下左右の端に、ヌルを親として作成するスクリプトです。

このスクリプトは、アンカーポイントが[0,0]にあるシェイプレイヤーには効果がありますが、アンカーポイントが0でなかったり、通常のレイヤーには効果がありません。

この問題をどなたか解決できませんか。 よろしくお願いします。

 

    var proj = app.project;

    // Ensure a composition is open
    var comp = proj.activeItem;

    // Ensure layers are selected
    var selectedLayers = comp.selectedLayers;

    // Prompt the user to select the position of the null object
    var positionOptions = ["center", "top", "bottom", "left", "right"];
    var position = prompt("select position (center, top, bottom, left, right):", "right");


    // Start undo group
    app.beginUndoGroup("Create Null at Selected Position");

    // Calculate the bounding box of the selected layers
    var minX = Infinity, maxX = -Infinity;
    var minY = Infinity, maxY = -Infinity;

    for (var i = 0; i < selectedLayers.length; i++) {
        var layer = selectedLayers[i];
        var layerBounds = layer.sourceRectAtTime(comp.time, false);

        var layerMinX = layer.position.value[0] + layerBounds.left;
        var layerMaxX = layerMinX + layerBounds.width;
        var layerMinY = layer.position.value[1] + layerBounds.top;
        var layerMaxY = layerMinY + layerBounds.height;

        minX = Math.min(minX, layerMinX);
        maxX = Math.max(maxX, layerMaxX);
        minY = Math.min(minY, layerMinY);
        maxY = Math.max(maxY, layerMaxY);
    }

    var centerX = (minX + maxX) / 2;
    var centerY = (minY + maxY) / 2;
    var centerZ = 0;

    var nullPosition = [centerX, centerY, centerZ];

    switch (position) {
        case "top":
            nullPosition = [centerX, minY, centerZ];
            break;
        case "bottom":
            nullPosition = [centerX, maxY, centerZ];
            break;
        case "left":
            nullPosition = [minX, centerY, centerZ];
            break;
        case "right":
            nullPosition = [maxX, centerY, centerZ];
            break;
    }

    // Create a null object at the calculated position
    var nullLayer = comp.layers.addNull();
    nullLayer.name = "Positioned Null (" + position + ")";
    nullLayer.position.setValue(nullPosition);

    // Parent the selected layers to the null object
    for (var i = 0; i < selectedLayers.length; i++) {
        var layer = selectedLayers[i];
        layer.parent = nullLayer;
    }

    // End undo group
    app.endUndoGroup();

 

This topic has been closed for replies.
Correct answer stunning_Sunflower16B7

minX,maxX,minY,maxYを作る箇所で、アンカーポイントの値で補正すれば大丈夫かなと思います。

    for (var i = 0; i < selectedLayers.length; i++) {
        var layer = selectedLayers[i];
        var layerBounds = layer.sourceRectAtTime(comp.time, false);

        if (layer instanceof ShapeLayer) {
            var layerMinX = layer.position.value[0] + layerBounds.left + layer.anchorPoint.value[0];
            var layerMaxX = layerMinX + layerBounds.width;
            var layerMinY = layer.position.value[1] + layerBounds.top + layer.anchorPoint.value[1];
            var layerMaxY = layerMinY + layerBounds.height;
        }

        if (layer instanceof AVLayer) {
            var layerMinX = layer.position.value[0] - layer.anchorPoint.value[0];
            var layerMaxX = layerMinX + layerBounds.width;
            var layerMinY = layer.position.value[1] - layer.anchorPoint.value[1];
            var layerMaxY = layerMinY + layerBounds.height;
        }

        minX = Math.min(minX, layerMinX);
        maxX = Math.max(maxX, layerMaxX);
        minY = Math.min(minY, layerMinY);
        maxY = Math.max(maxY, layerMaxY);
    }

 

回転やスケールも対応させる場合はもっと複雑になると思いますが、三角関数などで愚直に計算していけば大丈夫かと。

2 replies

Participating Frequently
August 6, 2024

minX,maxX,minY,maxYを作る箇所で、アンカーポイントの値で補正すれば大丈夫かなと思います。

    for (var i = 0; i < selectedLayers.length; i++) {
        var layer = selectedLayers[i];
        var layerBounds = layer.sourceRectAtTime(comp.time, false);

        if (layer instanceof ShapeLayer) {
            var layerMinX = layer.position.value[0] + layerBounds.left + layer.anchorPoint.value[0];
            var layerMaxX = layerMinX + layerBounds.width;
            var layerMinY = layer.position.value[1] + layerBounds.top + layer.anchorPoint.value[1];
            var layerMaxY = layerMinY + layerBounds.height;
        }

        if (layer instanceof AVLayer) {
            var layerMinX = layer.position.value[0] - layer.anchorPoint.value[0];
            var layerMaxX = layerMinX + layerBounds.width;
            var layerMinY = layer.position.value[1] - layer.anchorPoint.value[1];
            var layerMaxY = layerMinY + layerBounds.height;
        }

        minX = Math.min(minX, layerMinX);
        maxX = Math.max(maxX, layerMaxX);
        minY = Math.min(minY, layerMinY);
        maxY = Math.max(maxY, layerMaxY);
    }

 

回転やスケールも対応させる場合はもっと複雑になると思いますが、三角関数などで愚直に計算していけば大丈夫かと。

T.shusaku
T.shusakuAuthor
Participant
August 6, 2024

お二人ともありがとうございます!

 

tetsuohさんのスクリプトにて動作確認ができました!

シェイプの場合とレイヤーの場合で分けたら良かったのですね。

 

ちなみに、シェイプの場合はアンカーポイントは減算する書き方が正しいようでした!

if (layer instanceof ShapeLayer) {
var layerMinX = layer.position.value[0] + layerBounds.left - layer.anchorPoint.value[0];
var layerMaxX = layerMinX + layerBounds.width;
var layerMinY = layer.position.value[1] + layerBounds.top - layer.anchorPoint.value[1];
var layerMaxY = layerMinY + layerBounds.height;
}

 

また、すみません。三角関数の実装についてですが学生以来につき皆目見当がつかず・・。

もし宜しければ、何かヒントを頂けると助かります。

Participating Frequently
August 6, 2024

アンカーポイントの位置を原点とする各頂点の位置の移動を求めればよいので

回転行列が一番よさそうな感じかもです。

https://mathwords.net/heimenkaiten

の「原点以外を中心とした回転の公式」というので求められそうな気がします。

角度と弧度の変換が必要だったはずなのと、AEの角度が一般的なグラフとは90度向きが違っていたはずなのでいろいろやってみるとよいと思いますが、こういった数学の公式的なものはchatGPTがうまく答えを出してくれそうな気がします

Community Expert
August 5, 2024

解決方法ではありませんが、
このスクリプトは、標準で搭載されているスクリプト「Create Nulls From Paths.jsx」と同じ機能ではないでしょうか?
試してみてはどうでしょう。

 

スクリプトの機能は、シェイプのパスの頂点をヌルで制御するもので、平面レイヤーには効果はありません。
平面の四隅を自由に動かす場合は、「コーナーピン」など変形エフェクトが複数あるので、それを利用するようになります。