/**
 * @name Distributron
 * @author IVG Design
 * @version 1.1.3
 * @date 2026-07-28
 * @license MIT
 * @ui HEADLESS
 * @description Distributes layers along a shape path with advanced control options
 * 
 * @functionality
 * - Distributes multiple layers evenly along a selected shape path
 * - Creates control null with pseudo effects for animation control
 * - Randomization options for rotation variations
 * - Start and end distribution offset controls
 * - First and last layer index selection for partial distribution
 * - Automatic path-following expressions with position and rotation
 * - Includes bundled ApplyFFX module for pseudo effect application
 * - Creates mask linked to shape path for reference
 * - Parents control layer to shape for coordinated movement
 * 
 * @usage
 * 1. Select a shape layer with a path in your composition
 * 2. Run the script via File > Scripts > PathDistributor.jsx
 * 3. Script creates "CTRL" null with distribution controls:
 *    - Randomize Rotation: Adds variation to each layer's rotation
 *    - Rotation Offset: Global rotation adjustment
 *    - Start/End Distribution Offset: Path segment control
 *    - First/Last Layer Index: Range of layers to distribute
 * 4. Layers between specified indices are distributed along path
 * 5. Adjust controls in Effects panel for animation
 * 
 * @requirements
 * - Adobe After Effects CS6 or later
 * - Shape layer with at least one path selected
 * - Multiple layers in composition for distribution
 * - Shape layer must be at top of layer stack or will be moved
 * 
 * @notes
 * - Bundled version includes ApplyFFX module inline
 * - Creates complex expressions for path-following behavior
 * - All distributed layers parent to CTRL null for group control
 * - Shape layer moves to top if not already there
 * - Pseudo effect binary data embedded for compatibility
 * - All operations wrapped in undo group "Distributron"
 *
 * @changelog
 * - 1.1.3 (2026-07-28): Gave the pseudo effect a unique, namespaced matchname
 *   ("Pseudo/PEM Matchname" -> "Pseudo/IVGD Distributron"). After Effects registers exactly
 *   one pseudo-effect definition per matchname per session, and five catalog scripts
 *   all shipped Pseudo Effect Maker's default "Pseudo/PEM Matchname", so running any
 *   two of them in the same session made each redefine the other's controls — the
 *   already-applied rigs reset with "effect control conversion required" and lost their
 *   parameters. Existing projects saved with the OLD matchname keep working (the effect
 *   definition is embedded in the project file); only newly-applied rigs use the new identity.
 * - 1.1.2 (2026-07-04): Fixed the path-following expression to reference the actual name of the newly-created mask instead of the hardcoded "Mask 1". Shape layers that already carry a mask no longer produce a wrong or broken distribution.
 * - 1.1.1 (2026-06-02): Removed an ECMA 3-incompatible trailing comma from the ApplyFFX config object.
 * - 1.1.0 (2025-08-13): Added controls for start/end offsets.
 * - 1.0.0: Initial release with core distribution functionality.
 */

//========== INCLUDED FUNCTIONS ============//
/**
 * @fileoverview
 * The applyFFX module provides methods to apply pseudo effects to layers in After Effects.
 * 
 * @module applyFFX
 * 
 * @example
 * // Import the applyFFX module
 * //@include "path/to/applyFFX.js"
 * 
 * // Get the active layer in the active composition
 * var layer = app.project.activeItem.layer(1);
 * 
 * // Configuration data
 * var binaryData = "...";
 * var matchName = "Multiparent";
 * var version = "1.0.0";
 * var name = "MultiParent";
 * 
 * // Apply the pseudo effect to the layer
 * applyFFX.config(layer, binaryData, matchName, version, name);
 * 
 * @usageNotes
 * 1. Place the applyFFX.js file in a location accessible to your After Effects scripts.
 * 2. Use the @include directive to include applyFFX.js in your script.
 * 3. Use applyFFX.config() to apply a pseudo effect to a layer based on your configuration.
 */

var ApplyFFX = (function () {
	var module = {};

	/**
 * Deselects all layers in a given composition.
 * 
 * @function deselectAll
 * @memberof applyFFX
 * 
 * @param {object} theComp - The composition whose layers should be deselected.
 * 
 * @example 
 * var comp = app.project.activeItem;
 * applyFFX.deselectAll(comp);
 */
	module.deselectAll = function (theComp) {
		for (var i = 1, il = theComp.numLayers; i <= il; i++) {
			theComp.layer(i).selected = false;
		}
	};

	/**
	 * Applies a pseudo effect to a given layer based on the configuration provided.
	 * 
	 * @function config
	 * @memberof applyFFX
	 * 
	 * @param {object} layer - The layer to which the pseudo effect should be applied.
	 * @param {string} binaryData - The binary data for the effect.
	 * @param {string} matchName - The match name for the pseudo effect.
	 * @param {string} version - The version of the pseudo effect.
	 * @param {string} name - The name of the pseudo effect.
	 * 
	 * @example 
	 * var layer = someLayerObject;
	 * var binaryData = "...";
	 * var matchName = "Multiparent";
	 * var version = "1.0.0";
	 * var name = "MultiParent";
	 * applyFFX.config(layer, binaryData, matchName, version, name);
	 */
	module.config = function (layer, binaryData, matchName, version, name) {
		var config = {
			binary: binaryData,
			matchName: 'Pseudo/' + matchName,
			name: name,
			version: version
		};

		var tempFolder = Folder.temp;
		var ffxFile = File(tempFolder.fsName + '/' + config.name + '_v' + config.version + '.ffx');
		ffxFile.encoding = 'BINARY';
		ffxFile.open('w');
		ffxFile.write(config.binary);
		ffxFile.close();

		var myComp = app.project.activeItem;
		module.deselectAll(myComp);
		layer.selected = true;
		layer.applyPreset(ffxFile);
	};
	return module;
})();

//========== END OF INCLUDED FUNCTIONS ============//

/**
 * Distribute Layers Along a Path in Adobe After Effects
 *
 * Automates the process of distributing selected layers along a specified path within an active composition.
 *
 * FUNCTIONALITY:
 * - Checks for a single selected shape layer with a path.
 * - Works with both open and closed paths.
 * - Can animate the path and the distribution will adjust dynamically.
 * - If selected layer isn't at the top, it moves it there.
 * - Creates a mask on the selected shape layer and parents it to the shape path.
 * - Adds a CTRL null layer with various controls for randomizing rotation, offsetting rotation, and specifying start/end indices.
 * - CTRL null is created at the center anchor point of the Path layer and parented to it.
 * - Adds "Start Distribution Offset" and "End Distribution Offset" controls to the CTRL layer for fine-tuning distribution.
 * - Distributes other layers along the path by applying expressions to their Position and Rotation properties.
 * - Allows for real-time manipulation and animation through the CTRL layer.
 *
 * USAGE:
 * 1. Select a shape layer with a path in an active composition.
 * 2. Run the script.
 * 3. Adjust the controls in the generated CTRL layer for desired distribution and animation.
 *
 * @author IVG Design
 * @version 1.1.0
 * @date 2023 10 9
 * @changelog 
 * 	1.0.0	- initial release with core functionalities.
 *  1.1.0   - added controls for start/end offsets.
 * @license Provided as is
 */



function main() {
	
	app.beginUndoGroup("Distributron");
	
	// Step 1: Get the active composition and the selected layers
	var comp = app.project.activeItem;
	var selectedLayers = comp.selectedLayers;

	if (selectedLayers.length !== 1) {
		alert("Please select exactly one shape layer with a path.");
		app.endUndoGroup();
		return;
	}

	// Move shapeLayer to the top if it's not
	var shapeLayer = selectedLayers[0];
	if (shapeLayer.index !== 1) {
		shapeLayer.moveToBeginning();
	}

	// Step 2: Create a mask on the selected layer and parent it to the shape path
	var mask = shapeLayer.Masks.addProperty("Mask");
	mask.property("Mask Path").expression = "thisLayer.content(1).content(1).path";

	// Step 3: Create the CTRL layer and add necessary controls
	var ctrlLayer = comp.layers.addNull();
	ctrlLayer.name = "CTRL";
	ctrlLayer.parent = shapeLayer;


	// Center CTRL null to shapeLayer's anchor point
	var shapeLayerAnchor = shapeLayer.property("Anchor Point").value;
	ctrlLayer.property("Position").setValue(shapeLayerAnchor);
	var controlBinary = "RIFX\x00\x00\x16\x18FaFXhead\x00\x00\x00\x10\x00\x00\x00\x03\x00\x00\x00D\x00\x00\x00\x01\x01\x00\x00\x00LIST\x00\x00\x15\u00F4bescbeso\x00\x00\x008\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00]\u00A8\x00\x1D\u00F8R\x00\x00\x00\x00\x00d\x00d\x00d\x00d?\u00F0\x00\x00\x00\x00\x00\x00?\u00F0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\u00FF\u00FF\u00FF\u00FFLIST\x00\x00\x00\u00ACtdsptdot\x00\x00\x00\x04\u00FF\u00FF\u00FF\u00FFtdpl\x00\x00\x00\x04\x00\x00\x00\x02LIST\x00\x00\x00@tdsitdix\x00\x00\x00\x04\u00FF\u00FF\u00FF\u00FFtdmn\x00\x00\x00(ADBE Effect Parade\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00LIST\x00\x00\x00@tdsitdix\x00\x00\x00\x04\x00\x00\x00\x00tdmn\x00\x00\x00(Pseudo/IVGD Distributron\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00tdsn\x00\x00\x00\x1ADistribute Along the Path\x00LIST\x00\x00\x00dtdsptdot\x00\x00\x00\x04\u00FF\u00FF\u00FF\u00FFtdpl\x00\x00\x00\x04\x00\x00\x00\x01LIST\x00\x00\x00@tdsitdix\x00\x00\x00\x04\u00FF\u00FF\u00FF\u00FFtdmn\x00\x00\x00(ADBE End of path sentinel\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00LIST\x00\x00\x14fsspcfnam\x00\x00\x000\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00LIST\x00\x00\b\bparTparn\x00\x00\x00\x04\x00\x00\x00\ntdmn\x00\x00\x00(Pseudo/IVGD Distributron-0000\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00pard\x00\x00\x00\u0094\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x00\x00\x00\x00\x00\x00\x0E\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\u00FF\u00FF\u00FF\u00FF\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00tdmn\x00\x00\x00(Pseudo/IVGD Distributron-0001\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00pard\x00\x00\x00\u0094\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\nRandomize Rotation\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\u00C4z\x00\x00Dz\x00\x00\u00C1 \x00\x00A \x00\x00\x00\x00\x00\x00\x00\x02\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00tdmn\x00\x00\x00(Pseudo/IVGD Distributron-0002\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00pard\x00\x00\x00\u0094\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x03Rotation Offset\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00tdmn\x00\x00\x00(Pseudo/IVGD Distributron-0003\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00pard\x00\x00\x00\u0094\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\nStart Distribution Offset\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00G\u00C3P\x00\x00\x00\x00\x00A \x00\x00\x00\x00\x00\x00\x00\x02\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00tdmn\x00\x00\x00(Pseudo/IVGD Distributron-0004\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00pard\x00\x00\x00\u0094\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\nEnd Distribution Offset\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00G\u00C3P\x00\x00\x00\x00\x00A \x00\x00\x00\x00\x00\x00\x00\x02\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00tdmn\x00\x00\x00(Pseudo/IVGD Distributron-0005\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00pard\x00\x00\x00\u0094\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\rDistribution setup\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00tdmn\x00\x00\x00(Pseudo/IVGD Distributron-0006\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00pard\x00\x00\x00\u0094\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\nFirst Layer Index\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00Dz\x00\x00\x00\x00\x00\x00A \x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00tdmn\x00\x00\x00(Pseudo/IVGD Distributron-0007\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00pard\x00\x00\x00\u0094\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\nLast Layer Index\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00Dz\x00\x00\x00\x00\x00\x00A \x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00tdmn\x00\x00\x00(Pseudo/IVGD Distributron-0008\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00pard\x00\x00\x00\u0094\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00Distribution Path Layer \x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\u00FF\u00FF\u00FF\u00FF\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00tdmn\x00\x00\x00(Pseudo/IVGD Distributron-0009\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00pard\x00\x00\x00\u0094\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x0E\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00LIST\x00\x00\f\x12tdgptdsb\x00\x00\x00\x04\x00\x00\x00\x01tdsn\x00\x00\x00\x1ADistribute Along the Path\x00tdmn\x00\x00\x00(Pseudo/IVGD Distributron-0000\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00LIST\x00\x00\x00\u00DAtdbstdsb\x00\x00\x00\x04\x00\x00\x00\x03tdsn\x00\x00\x00\x01\x00\x00tdb4\x00\x00\x00|\u00DB\u0099\x00\x01\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x02X?\x1A6\u00E2\u00EB\x1CC-?\u00F0\x00\x00\x00\x00\x00\x00?\u00F0\x00\x00\x00\x00\x00\x00?\u00F0\x00\x00\x00\x00\x00\x00?\u00F0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x04\x04\u00C0\u00C0\u00C0\u00FF\u00C0\u00C0\u00C0\x00\x00\x00\x00\u0080\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00cdat\x00\x00\x00(\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00tdpi\x00\x00\x00\x04\x00\x00\x00\x0Etdmn\x00\x00\x00(Pseudo/IVGD Distributron-0001\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00LIST\x00\x00\x01\x00tdbstdsb\x00\x00\x00\x04\x00\x00\x00\x01tdsn\x00\x00\x00\x13Randomize Rotation\x00\x00tdb4\x00\x00\x00|\u00BD\u0099\x00\x01\x00\x01\x00\x00\x00\x01\x00\u00FF\x00\x00]\u00A8\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00cdat\x00\x00\x00(\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00tdum\x00\x00\x00\b\u00C0$\x00\x00\x00\x00\x00\x00tduM\x00\x00\x00\b@$\x00\x00\x00\x00\x00\x00tdmn\x00\x00\x00(Pseudo/IVGD Distributron-0002\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00LIST\x00\x00\x00\u00DCtdbstdsb\x00\x00\x00\x04\x00\x00\x00\x01tdsn\x00\x00\x00\x10Rotation Offset\x00tdb4\x00\x00\x00|\u00BD\u0099\x00\x01\x00\x01\x00\x00\x00\x01\x00\u00FF\x00\x00]\u00A8\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00cdat\x00\x00\x00(\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00tdmn\x00\x00\x00(Pseudo/IVGD Distributron-0003\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00LIST\x00\x00\x01\x06tdbstdsb\x00\x00\x00\x04\x00\x00\x00\x01tdsn\x00\x00\x00\x1AStart Distribution Offset\x00tdb4\x00\x00\x00|\u00BD\u0099\x00\x01\x00\x01\x00\x00\x00\x01\x00\u00FF\x00\x00]\u00A8\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00cdat\x00\x00\x00(\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00tdum\x00\x00\x00\b\x00\x00\x00\x00\x00\x00\x00\x00tduM\x00\x00\x00\b@$\x00\x00\x00\x00\x00\x00tdmn\x00\x00\x00(Pseudo/IVGD Distributron-0004\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00LIST\x00\x00\x01\x04tdbstdsb\x00\x00\x00\x04\x00\x00\x00\x01tdsn\x00\x00\x00\x18End Distribution Offset\x00tdb4\x00\x00\x00|\u00BD\u0099\x00\x01\x00\x01\x00\x00\x00\x01\x00\u00FF\x00\x00]\u00A8\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00cdat\x00\x00\x00(\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00tdum\x00\x00\x00\b\x00\x00\x00\x00\x00\x00\x00\x00tduM\x00\x00\x00\b@$\x00\x00\x00\x00\x00\x00tdmn\x00\x00\x00(Pseudo/IVGD Distributron-0005\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00LIST\x00\x00\x00\u00E0tdbstdsb\x00\x00\x00\x04\x00\x00\x00\x01tdsn\x00\x00\x00\x13Distribution setup\x00\x00tdb4\x00\x00\x00|\u00BD\u0099\x00\x01\x00\x01\x00\x00\x00\x01\x00\x04\x00\x00]\u00A8\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00cdat\x00\x00\x00(\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00tdmn\x00\x00\x00(Pseudo/IVGD Distributron-0006\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00LIST\x00\x00\x00\u00FEtdbstdsb\x00\x00\x00\x04\x00\x00\x00\x01tdsn\x00\x00\x00\x12First Layer Index\x00tdb4\x00\x00\x00|\u00BD\u0099\x00\x01\x00\x01\x00\x00\x00\x01\x00\u00FF\x00\x00]\u00A8\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00cdat\x00\x00\x00(\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00tdum\x00\x00\x00\b\x00\x00\x00\x00\x00\x00\x00\x00tduM\x00\x00\x00\b@$\x00\x00\x00\x00\x00\x00tdmn\x00\x00\x00(Pseudo/IVGD Distributron-0007\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00LIST\x00\x00\x00\u00FEtdbstdsb\x00\x00\x00\x04\x00\x00\x00\x01tdsn\x00\x00\x00\x11Last Layer Index\x00\x00tdb4\x00\x00\x00|\u00BD\u0099\x00\x01\x00\x01\x00\x00\x00\x01\x00\u00FF\x00\x00]\u00A8\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00cdat\x00\x00\x00(\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00tdum\x00\x00\x00\b\x00\x00\x00\x00\x00\x00\x00\x00tduM\x00\x00\x00\b@$\x00\x00\x00\x00\x00\x00tdmn\x00\x00\x00(Pseudo/IVGD Distributron-0008\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00LIST\x00\x00\x00\u00F2tdbstdsb\x00\x00\x00\x04\x00\x00\x00\x01tdsn\x00\x00\x00\x19Distribution Path Layer \x00\x00tdb4\x00\x00\x00|\u00DB\u0099\x00\x01\x00\x01\x00\x00\x00\x01\x00\u00FF\x00\x00]\u00A8?\x1A6\u00E2\u00EB\x1CC-?\u00F0\x00\x00\x00\x00\x00\x00?\u00F0\x00\x00\x00\x00\x00\x00?\u00F0\x00\x00\x00\x00\x00\x00?\u00F0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x04\x04\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00cdat\x00\x00\x00(\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00tdpi\x00\x00\x00\x04\x00\x00\x00\x0Etdmn\x00\x00\x00(Pseudo/IVGD Distributron-0009\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00LIST\x00\x00\x00\u00F2tdbstdsb\x00\x00\x00\x04\x00\x00\x00\x01tdsn\x00\x00\x00\x1ADistribute Along the Path\x00tdb4\x00\x00\x00|\u00BD\u0099\x00\x01\x00\x01\x00\x00\x00\x01\x00\x04\x00\x00]\u00A8\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00cdat\x00\x00\x00(\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00tdpi\x00\x00\x00\x04\x00\x00\x00\x0Etdmn\x00\x00\x00(ADBE Group End\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00{\"controlName\":\"Distribute Along the Path\",\"matchname\":\"Pseudo/IVGD Distributron\",\"controlArray\":[{\"name\":\"Randomize Rotation\",\"type\":\"slider\",\"canHaveKeyframes\":true,\"canBeInvisible\":true,\"invisible\":false,\"keyframes\":true,\"id\":3880628942,\"hold\":false,\"default\":0,\"sliderMax\":10,\"sliderMin\":-10,\"validMax\":1000,\"validMin\":-1000,\"precision\":2,\"percent\":false,\"pixel\":false,\"open\":false,\"errors\":[\n\n],\"error\":[\n\n]},{\"name\":\"Rotation Offset\",\"type\":\"angle\",\"canHaveKeyframes\":true,\"canBeInvisible\":false,\"default\":0,\"keyframes\":true,\"id\":8431351131,\"hold\":false,\"open\":false,\"error\":[\n\n]},{\"name\":\"Start Distribution Offset\",\"type\":\"slider\",\"canHaveKeyframes\":true,\"canBeInvisible\":true,\"invisible\":false,\"keyframes\":true,\"id\":7486280573,\"hold\":false,\"default\":0,\"sliderMax\":10,\"sliderMin\":0,\"validMax\":100000,\"validMin\":0,\"precision\":2,\"percent\":false,\"pixel\":false,\"open\":false,\"errors\":[\n\n],\"error\":[\n\n]},{\"name\":\"End Distribution Offset\",\"type\":\"slider\",\"canHaveKeyframes\":true,\"canBeInvisible\":true,\"invisible\":false,\"keyframes\":true,\"id\":3000218553,\"hold\":false,\"default\":0,\"sliderMax\":10,\"sliderMin\":0,\"validMax\":100000,\"validMin\":0,\"precision\":2,\"percent\":false,\"pixel\":false,\"open\":false,\"errors\":[\n\n],\"error\":[\n\n]},{\"name\":\"Distribution setup\",\"type\":\"group\",\"canHaveKeyframes\":false,\"canBeInvisible\":true,\"invisible\":false,\"keyframes\":false,\"id\":4489051058,\"hold\":false,\"children\":[\n\n],\"open\":false,\"error\":[\n\n]},{\"name\":\"First Layer Index\",\"type\":\"slider\",\"canHaveKeyframes\":true,\"canBeInvisible\":true,\"invisible\":false,\"keyframes\":true,\"id\":6317602853,\"hold\":false,\"default\":0,\"sliderMax\":10,\"sliderMin\":0,\"validMax\":1000,\"validMin\":0,\"precision\":0,\"percent\":false,\"pixel\":false,\"open\":false,\"errors\":[\n\n],\"error\":[\n\n]},{\"name\":\"Last Layer Index\",\"type\":\"slider\",\"canHaveKeyframes\":true,\"canBeInvisible\":true,\"invisible\":false,\"keyframes\":true,\"id\":9321827334,\"hold\":false,\"default\":0,\"sliderMax\":10,\"sliderMin\":0,\"validMax\":1000,\"validMin\":0,\"precision\":0,\"percent\":false,\"pixel\":false,\"open\":false,\"errors\":[\n\n],\"error\":[\n\n]},{\"name\":\"Distribution Path Layer \",\"type\":\"layer\",\"canHaveKeyframes\":false,\"canBeInvisible\":true,\"invisible\":false,\"keyframes\":false,\"id\":7930276358,\"hold\":false,\"default\":true,\"error\":[\n\n]},{\"name\":\"EndGroup\",\"type\":\"endgroup\",\"canBeInvisible\":false,\"canHaveKeyframes\":false,\"keyframes\":false,\"hold\":false,\"id\":2110947075,\"groupId\":0,\"error\":[\n\n]}],\"version\":3}";
	var name = "Distribute Along Path";
	var matchName = "IVGD Distributron";
	var version = "1.1.0";
	
	ApplyFFX.config(ctrlLayer, controlBinary, matchName, version, name); 

	ctrlLayer("ADBE Effect Parade")("Distribute Along the Path")("Distribution Path Layer ").setValue(shapeLayer.index);

	
	// Step 4: Set highest and lowest index, parent layers to CTRL and add expression to Position and Rotation of other layers
	var layers = comp.layers;
	var minIndex = shapeLayer.index + 1;
	var maxIndex = layers.length;

	ctrlLayer("ADBE Effect Parade")("Distribute Along the Path")("First Layer Index").setValue(minIndex);
	ctrlLayer("ADBE Effect Parade")("Distribute Along the Path")("Last Layer Index").setValue(maxIndex);

	// Your expression (including the update for the last item offset)
	var expression = 'function calcPathLength(path) {\n' +
		'  var length = 0;\n' +
		'  var numPoints = path.length;\n' +
		'  for (var i = 1; i < numPoints; i++) {\n' +
		'    length += lengthTo(path[i - 1], path[i]);\n' +
		'  }\n' +
		'  return length;\n' +
		'}\n' +
		'function lengthTo(point1, point2) {\n' +
		'  return Math.sqrt(Math.pow(point2[0] - point1[0], 2) + Math.pow(point2[1] - point1[1], 2));\n' +
		'}\n' +
		'var controlLayer = thisComp.layer("CTRL");\n' +
		'var selectedPathLayer = controlLayer.effect("Distribute Along the Path")("Distribution Path Layer ");\n' +
		'var pathProperty = selectedPathLayer.mask("' + mask.name + '").maskPath;\n' +
		'var time = time;\n' +
		'var path = pathProperty.points(time);\n' +
		'var pathLength = calcPathLength(path);\n' +
		'var randomRotation = controlLayer.effect("Distribute Along the Path")("Randomize Rotation");\n' +
		'var offsetRotation = controlLayer.effect("Distribute Along the Path")("Rotation Offset");\n' +
		'var startIndex = controlLayer.effect("Distribute Along the Path")("First Layer Index");\n' +
		'var endIndex = controlLayer.effect("Distribute Along the Path")("Last Layer Index");\n' +
		'var endOffset = controlLayer.effect("Distribute Along the Path")("End Distribution Offset");\n' +
		'var startOffset = controlLayer.effect("Distribute Along the Path")("Start Distribution Offset");\n' +
		'var effectivePathLength = pathLength - endOffset - startOffset;\n' +
		'var myIndex = index - startIndex;\n' +
		'var t = startOffset + myIndex / (endIndex - startIndex) * effectivePathLength;\n' +
		'var pos = pathProperty.pointOnPath(t / pathLength, time);\n' +
		'var tangent = pathProperty.normalOnPath(t / pathLength, time);\n' +
		'var angle = Math.atan2(tangent[1], tangent[0]) * 180 / Math.PI;\n' +
		'var rotation = angle + 90 + offsetRotation + randomRotation * (Math.random() - 0.5) * 2;\n' +
		'if (thisProperty.name === "Position") {\n' +
		'  pos;\n' +
		'} else if (thisProperty.name === "Rotation") {\n' +
		'  rotation;\n' +
		'}\n';

	for (var i = 1; i <= layers.length; i++) {
		var layer = layers[i];
		if (layer.index >= minIndex && layer.index <= maxIndex) {
			layer.parent = ctrlLayer;
			layer.property("Position").expression = expression;
			layer.property("Rotation").expression = expression;
		}
	}

	app.endUndoGroup();

}

main();
