/**
 * Elast-o-matic - Keyframe Bounce & Elastic Overshoot Applier
 *
 * @name Elast-o-matic
 * @author IVG Design
 * @version 1.1.3
 * @date 2026-07-28
 * @license MIT
 * @ui HEADLESS
 *
 * @description
 * Adds physical follow-through to any keyframed property in one click. Select one or
 * more properties and run it: each property gets its own pseudo-effect controller and
 * an expression that reacts to the property's keyframes. The default variant is an
 * elastic "Inertial Bounce" (springy overshoot after every keyframe); hold Cmd (macOS)
 * or Ctrl (Windows) while launching to apply the "Bounce" variant instead (gravity
 * bounces that settle, like a ball dropping). Everything stays live and editable from
 * the Effect Controls panel after the fact - no baked keyframes.
 *
 * @functionality
 * • Adds ONE pseudo-effect controller ("Inertial Bounce" or "Bounce") to each layer that has
 *   selected properties, and drives every selected property on that layer from it
 * • Rigs multiple properties across multiple layers in one run — each layer gets its own controller
 * • Inertial variant controls: Amplitude, Frequency, Decay, Duration, Delay (in frames), External Driver (+ Layer / Animated Property)
 * • Bounce variant controls: Elasticity, Gravity, Number of bounces
 * • Inertial variant can follow ANOTHER layer's motion via the External Driver checkbox + layer picker
 * • Select a SUBSET of a property's keyframes (>= 2) to overshoot only off those keys — unselected
 *   keyframes (and the motion after them) stay native; select all (or the property) for the whole timeline
 * • Hold Cmd/Ctrl at launch to switch from Inertial Bounce to Bounce
 *
 * @usage
 * 1. Select a layer and the keyframed property/properties you want to rig
 * 2. Run Elast-o-matic (from the IVGD Command Bar, hold Cmd/Ctrl for the Bounce variant)
 * 3. Tune the motion from the generated effect(s) in the Effect Controls panel
 *
 * @requirements
 * • Adobe After Effects CC or later
 * • Active composition, a selected layer, and at least one selected property
 * • "Allow Scripts to Write Files and Access Network" enabled (first run per project
 *   may need to register the pseudo effect from a temporary .ffx file)
 *
 * @notes
 * • The FFX-registration snippet inside ensurePseudoRegistered() (writing the
 *   controller binary to a temp .ffx and applying it on a throwaway comp) is based
 *   on "Apply Pseudo Effect as Animation Preset" (c) 2017 Tomas Šinkūnas,
 *   www.rendertom.com. The script itself is IVG Design's.
 * • The Inertial expression reads the last keyframe before the current time, so it
 *   activates after every keyframe, not just the final one.
 * • The overshoot is velocity-continuous (1.1.2): amplitude is scaled by the angular
 *   frequency so the oscillation starts moving at the keyframe's own velocity instead
 *   of jumping — no kink at the handoff between the native motion and the overshoot.
 * • Deleting the generated effect disables the expression (it will error politely);
 *   remove the expression from the property to fully undo by hand.
 *
 * @changelog
 * - 1.1.3 (2026-07-28): Gave both pseudo effects unique, namespaced matchnames
 *   ("Pseudo/595056" -> "Pseudo/IVGD ElastOMaticIB" for Inertial Bounce, "Pseudo/477756"
 *   -> "Pseudo/IVGD ElastOMaticB" for Bounce). After Effects registers exactly one
 *   pseudo-effect definition per matchname per session, and the catalog's pseudo effects
 *   shipped with Pseudo Effect Maker's generic default identifiers, so running two of them
 *   in the same session could make 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 matchnames keep working (the effect definition is embedded
 *   in the project file); only newly-applied rigs use the new identity.
 * - 1.1.2 (2026-07-12): Velocity-continuous overshoot — amplitude normalised by the angular
 *   frequency so the spring launches at the keyframe's own arrival velocity.
 */

(function elastOMatic() {

    /****************** VARIANT DATA ******************/

    var INERTIAL = {
        label: "Inertial Bounce",
        effectSuffix: " Inertial Bounce",
        fileName: "Elast-o-matic Inertial",
        matchName: "Pseudo/IVGD ElastOMaticIB",
        binary: "RIFX\x00\x00\x18ÆFaFXhead\x00\x00\x00\x10\x00\x00\x00\x03\x00\x00\x00]\x00\x00\x00+\x00\x00\x00\x00LIST\x00\x00\x18¢bescbeso\x00\x00\x008\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x005\x00!UU\x00\x00\x00\x04\x00\x01\x00\x01\x07Ð\x03è?ð\x00\x00\x00\x00\x00\x00?ð\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00ÿÿÿÿLIST\x00\x00\x00¬tdsptdot\x00\x00\x00\x04ÿÿÿÿtdpl\x00\x00\x00\x04\x00\x00\x00\x02LIST\x00\x00\x00@tdsitdix\x00\x00\x00\x04ÿÿÿÿtdmn\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 ElastOMaticIB\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00tdsn\x00\x00\x00\x18Utf8\x00\x00\x00\x0FInertial Bounce\x00LIST\x00\x00\x00dtdsptdot\x00\x00\x00\x04ÿÿÿÿtdpl\x00\x00\x00\x04\x00\x00\x00\x01LIST\x00\x00\x00@tdsitdix\x00\x00\x00\x04ÿÿÿÿtdmn\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\x17\x16sspcfnam\x00\x00\x00\bUtf8\x00\x00\x00\x00LIST\x00\x00\b\\parTparn\x00\x00\x00\x04\x00\x00\x00\ntdmn\x00\x00\x00(Pseudo/IVGD ElastOMaticIB-0000\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00pard\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\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\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00À\böÿÿd\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00ÿÿÿÿ\x00\x00\x00\x00\x00 \x19\x00\x01\x00\x00\x00\x00Ð\x00Vtdmn\x00\x00\x00(Pseudo/IVGD ElastOMaticIB-0001\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00pard\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\nAmplitude\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00@4\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00ÂÈ\x00\x00BÈ\x00\x00Á \x00\x00A \x00\x00A \x00\x00\x00\x02\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00Ð\x00Vtdmn\x00\x00\x00(Pseudo/IVGD ElastOMaticIB-0002\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00pard\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\nFrequency\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00@\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00ÂÈ\x00\x00BÈ\x00\x00Á \x00\x00A \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Ð\x00Vtdmn\x00\x00\x00(Pseudo/IVGD ElastOMaticIB-0003\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00pard\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\nDecay\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00@\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00ÂÈ\x00\x00BÈ\x00\x00Á \x00\x00A \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Ð\x00Vtdmn\x00\x00\x00(Pseudo/IVGD ElastOMaticIB-0004\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00pard\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\nDuration\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00?ø\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00ÂÈ\x00\x00BÈ\x00\x00Á \x00\x00A \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Ð\x00Vtdmn\x00\x00\x00(Pseudo/IVGD ElastOMaticIB-0005\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00pard\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\nDelay (in frames)\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00Äz\x00\x00Dz\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Ð\x00Vtdmn\x00\x00\x00(Pseudo/IVGD ElastOMaticIB-0006\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00pard\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x04External Driver\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00Äz\x00\x00Dz\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Ð\x00Vpdnm\x00\x00\x00\bUtf8\x00\x00\x00\x00tdmn\x00\x00\x00(Pseudo/IVGD ElastOMaticIB-0007\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00pard\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00External Driver Layer\x00\x00\x00\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\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00Ð\x00Vtdmn\x00\x00\x00(Pseudo/IVGD ElastOMaticIB-0008\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00pard\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x07External Animated Property\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x00\x00\x00\x00\x00\x00\x01\x00\x06\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00Ð\x00Vpdnm\x00\x00\x00<Utf8\x00\x00\x003position|rotation|scale|opacity|xPosition|yPosition\x00tdmn\x00\x00\x00(ADBE Effect Built In Params\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00pard\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\t\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\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\x0E~tdgptdsb\x00\x00\x00\x04\x00\x00\x00\x01tdsn\x00\x00\x00\x18Utf8\x00\x00\x00\x0FInertial Bounce\x00tdmn\x00\x00\x00(Pseudo/IVGD ElastOMaticIB-0000\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00LIST\x00\x00\x00ìtdbstdsb\x00\x00\x00\x04\x00\x00\x00\x03tdsn\x00\x00\x00\bUtf8\x00\x00\x00\x00tdb4\x00\x00\x00|Û\x00\x01\x00\x01\x00\x00\x00\x01\x00\x00\x00\x005?\x1A6âë\x1CC-?ð\x00\x00\x00\x00\x00\x00?ð\x00\x00\x00\x00\x00\x00?ð\x00\x00\x00\x00\x00\x00?ð\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\x0BUtdps\x00\x00\x00\x04\x00\x00\x00\x00tdmn\x00\x00\x00(Pseudo/IVGD ElastOMaticIB-0001\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00LIST\x00\x00\x00þtdbstdsb\x00\x00\x00\x04\x00\x00\x00\x01tdsn\x00\x00\x00\x12Utf8\x00\x00\x00\tAmplitude\x00tdb4\x00\x00\x00|Û\x00\x01\x00\x01\x00\x00ÿÿ\x00ÿ\x00\x005\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\b\t\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\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(@4\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\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\x00tduM\x00\x00\x00\b@$\x00\x00\x00\x00\x00\x00tdmn\x00\x00\x00(Pseudo/IVGD ElastOMaticIB-0002\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00LIST\x00\x00\x00þtdbstdsb\x00\x00\x00\x04\x00\x00\x00\x01tdsn\x00\x00\x00\x12Utf8\x00\x00\x00\tFrequency\x00tdb4\x00\x00\x00|Û\x00\x01\x00\x01\x00\x00ÿÿ\x00ÿ\x00\x005\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\b\t\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\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\x00tdum\x00\x00\x00\bÀ$\x00\x00\x00\x00\x00\x00tduM\x00\x00\x00\b@$\x00\x00\x00\x00\x00\x00tdmn\x00\x00\x00(Pseudo/IVGD ElastOMaticIB-0003\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00LIST\x00\x00\x00útdbstdsb\x00\x00\x00\x04\x00\x00\x00\x01tdsn\x00\x00\x00\x0EUtf8\x00\x00\x00\x05Decay\x00tdb4\x00\x00\x00|Û\x00\x01\x00\x01\x00\x00ÿÿ\x00ÿ\x00\x005\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\b\t\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\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\x00tdum\x00\x00\x00\bÀ$\x00\x00\x00\x00\x00\x00tduM\x00\x00\x00\b@$\x00\x00\x00\x00\x00\x00tdmn\x00\x00\x00(Pseudo/IVGD ElastOMaticIB-0004\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00LIST\x00\x00\x00ütdbstdsb\x00\x00\x00\x04\x00\x00\x00\x01tdsn\x00\x00\x00\x10Utf8\x00\x00\x00\bDurationtdb4\x00\x00\x00|Û\x00\x01\x00\x01\x00\x00ÿÿ\x00ÿ\x00\x005\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\b\t\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\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\x00tdum\x00\x00\x00\bÀ$\x00\x00\x00\x00\x00\x00tduM\x00\x00\x00\b@$\x00\x00\x00\x00\x00\x00tdmn\x00\x00\x00(Pseudo/IVGD ElastOMaticIB-0005\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\x1AUtf8\x00\x00\x00\x11Delay (in frames)\x00tdb4\x00\x00\x00|Û\x00\x01\x00\x01\x00\x00ÿÿ\x00ÿ\x00\x005\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\b\t\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\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\x00tduM\x00\x00\x00\b@$\x00\x00\x00\x00\x00\x00tdmn\x00\x00\x00(Pseudo/IVGD ElastOMaticIB-0006\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00LIST\x00\x00\x00ätdbstdsb\x00\x00\x00\x04\x00\x00\x00\x01tdsn\x00\x00\x00\x18Utf8\x00\x00\x00\x0FExternal Driver\x00tdb4\x00\x00\x00|Û\x00\x01\x00\x01\x00\x00\x00\x01\x00\x04\x00\x005?\x1A6âë\x1CC-?ð\x00\x00\x00\x00\x00\x00?ð\x00\x00\x00\x00\x00\x00?ð\x00\x00\x00\x00\x00\x00?ð\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\x00tdmn\x00\x00\x00(Pseudo/IVGD ElastOMaticIB-0007\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00LIST\x00\x00\x01\x02tdbstdsb\x00\x00\x00\x04\x00\x00\x00\x01tdsn\x00\x00\x00\x1EUtf8\x00\x00\x00\x15External Driver Layer\x00tdb4\x00\x00\x00|Û\x00\x01\x00\x01\x00\x00\x00\x01\x00ÿ\x00\x005?\x1A6âë\x1CC-?ð\x00\x00\x00\x00\x00\x00?ð\x00\x00\x00\x00\x00\x00?ð\x00\x00\x00\x00\x00\x00?ð\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\x00tdps\x00\x00\x00\x04\x00\x00\x00\x00tdmn\x00\x00\x00(Pseudo/IVGD ElastOMaticIB-0008\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00LIST\x00\x00\x00îtdbstdsb\x00\x00\x00\x04\x00\x00\x00\x01tdsn\x00\x00\x00\"Utf8\x00\x00\x00\x1AExternal Animated Propertytdb4\x00\x00\x00|Û\x00\x01\x00\x01\x00\x00\x00\x01\x00ÿ\x00\x005?\x1A6âë\x1CC-?ð\x00\x00\x00\x00\x00\x00?ð\x00\x00\x00\x00\x00\x00?ð\x00\x00\x00\x00\x00\x00?ð\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\x00tdmn\x00\x00\x00(ADBE Effect Built In Params\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00LIST\x00\x00\x036tdgptdsb\x00\x00\x00\x04\x00\x00\x00\x01tdsn\x00\x00\x00\x1CUtf8\x00\x00\x00\x13Compositing Options\x00tdmn\x00\x00\x00(ADBE Effect Mask Parade\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00LIST\x00\x00\x00Vtdgptdsb\x00\x00\x00\x04\x00\x00\x00\x01tdsn\x00\x00\x00\x0EUtf8\x00\x00\x00\x06-_0_/-tdmn\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\x00tdmn\x00\x00\x00(ADBE Effect Mask Opacity\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00LIST\x00\x00\x00útdbstdsb\x00\x00\x00\x04\x00\x00\x00\x01tdsn\x00\x00\x00\x0EUtf8\x00\x00\x00\x06-_0_/-tdb4\x00\x00\x00|Û\x00\x01\x00\x01\x00\x00ÿÿÿÿ\x00\x005?\x1A6âë\x1CC-?ð\x00\x00\x00\x00\x00\x00?ð\x00\x00\x00\x00\x00\x00?ð\x00\x00\x00\x00\x00\x00?ð\x00\x00\x00\x00\x00\x00\x00\x00\x00\b\t\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\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(@Y\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\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@Y\x00\x00\x00\x00\x00\x00tdmn\x00\x00\x00(ADBE Force CPU GPU\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Útdbstdsb\x00\x00\x00\x04\x00\x00\x00\x01tdsn\x00\x00\x00\x0EUtf8\x00\x00\x00\x06-_0_/-tdb4\x00\x00\x00|Û\x00\x01\x00\x01\x00\x00\x00\x02\x00\x04\x00\x005?\x1A6âë\x1CC-?ð\x00\x00\x00\x00\x00\x00?ð\x00\x00\x00\x00\x00\x00?ð\x00\x00\x00\x00\x00\x00?ð\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\x00tdmn\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\x00tdmn\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\x00pgui\x00\x00\x00\x10\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
    };

    var BOUNCE = {
        label: "Bounce",
        effectSuffix: " Bounce",
        fileName: "Elast-o-matic Bounce",
        matchName: "Pseudo/IVGD ElastOMaticB",
        binary: "RIFX\x00\x00\x0E~FaFXhead\x00\x00\x00\x10\x00\x00\x00\x03\x00\x00\x00]\x00\x00\x00+\x00\x00\x00\x00LIST\x00\x00\x0EZbescbeso\x00\x00\x008\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00x\x00\x00<\x00\x00\x00\x00\x00\x00\x02¢\x00À\x02¢\x00À?ð\x00\x00\x00\x00\x00\x00?ð\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00ÿÿÿÿLIST\x00\x00\x00¬tdsptdot\x00\x00\x00\x04ÿÿÿÿtdpl\x00\x00\x00\x04\x00\x00\x00\x02LIST\x00\x00\x00@tdsitdix\x00\x00\x00\x04ÿÿÿÿtdmn\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 ElastOMaticB\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00tdsn\x00\x00\x00\x0EUtf8\x00\x00\x00\x06BounceLIST\x00\x00\x00dtdsptdot\x00\x00\x00\x04ÿÿÿÿtdpl\x00\x00\x00\x04\x00\x00\x00\x01LIST\x00\x00\x00@tdsitdix\x00\x00\x00\x04ÿÿÿÿtdmn\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\fØsspcfnam\x00\x00\x00\bUtf8\x00\x00\x00\x00LIST\x00\x00\x04\fparTparn\x00\x00\x00\x04\x00\x00\x00\x05tdmn\x00\x00\x00(Pseudo/IVGD ElastOMaticB-0000\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00pard\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\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\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00À\böÿÿd\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00ÿÿÿÿ\x00\x00\x00\x00\x00 \x19\x00\x01\x00\x00\x00\x00Ð\x00Vtdmn\x00\x00\x00(Pseudo/IVGD ElastOMaticB-0001\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00pard\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\nElasticity\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00?æffffff\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00ÂÈ\x00\x00BÈ\x00\x00\x00\x00\x00\x00@ \x00\x00?333\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00Ð\x00Vtdmn\x00\x00\x00(Pseudo/IVGD ElastOMaticB-0002\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00pard\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\nGravity\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00@³\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00ÇÃP\x00GÃP\x00\x00\x00\x00\x00F\x1C@\x00E@\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00Ð\x00Vtdmn\x00\x00\x00(Pseudo/IVGD ElastOMaticB-0003\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00pard\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\nNumber of bounces\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00@\x14\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00BÈ\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Ð\x00Vtdmn\x00\x00\x00(ADBE Effect Built In Params\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00pard\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\t\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\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tdgptdsb\x00\x00\x00\x04\x00\x00\x00\x01tdsn\x00\x00\x00\x0EUtf8\x00\x00\x00\x06Bouncetdmn\x00\x00\x00(Pseudo/IVGD ElastOMaticB-0000\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00LIST\x00\x00\x00ìtdbstdsb\x00\x00\x00\x04\x00\x00\x00\x03tdsn\x00\x00\x00\bUtf8\x00\x00\x00\x00tdb4\x00\x00\x00|Û\x00\x01\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00x\x00?\x1A6âë\x1CC-?ð\x00\x00\x00\x00\x00\x00?ð\x00\x00\x00\x00\x00\x00?ð\x00\x00\x00\x00\x00\x00?ð\x00\x00\x00\x00\x00\x00\x00\x00\x00\x04\x04\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x14\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\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\x07Rtdps\x00\x00\x00\x04\x00\x00\x00\x00tdmn\x00\x00\x00(Pseudo/IVGD ElastOMaticB-0001\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00LIST\x00\x00\x00þtdbstdsb\x00\x00\x00\x04\x00\x00\x00\x01tdsn\x00\x00\x00\x12Utf8\x00\x00\x00\nElasticitytdb4\x00\x00\x00|Û\x00\x01\x00\x01\x00\x00ÿÿ\x00ÿ\x00\x00x\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\b\t\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\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(?æffffff\x00\x00\x00\x00\x00\x00\x00\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@\x14\x00\x00\x00\x00\x00\x00tdmn\x00\x00\x00(Pseudo/IVGD ElastOMaticB-0002\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00LIST\x00\x00\x00ütdbstdsb\x00\x00\x00\x04\x00\x00\x00\x01tdsn\x00\x00\x00\x10Utf8\x00\x00\x00\x07Gravity\x00tdb4\x00\x00\x00|Û\x00\x01\x00\x01\x00\x00ÿÿ\x00ÿ\x00\x00x\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\b\t\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\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\x00tdum\x00\x00\x00\b\x00\x00\x00\x00\x00\x00\x00\x00tduM\x00\x00\x00\b@Ã\x00\x00\x00\x00\x00tdmn\x00\x00\x00(Pseudo/IVGD ElastOMaticB-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\x1AUtf8\x00\x00\x00\x11Number of bounces\x00tdb4\x00\x00\x00|Û\x00\x01\x00\x01\x00\x00ÿÿ\x00ÿ\x00\x00x\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\b\t\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\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(@\x14\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\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(ADBE Effect Built In Params\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00LIST\x00\x00\x036tdgptdsb\x00\x00\x00\x04\x00\x00\x00\x01tdsn\x00\x00\x00\x1CUtf8\x00\x00\x00\x13Compositing Options\x00tdmn\x00\x00\x00(ADBE Effect Mask Parade\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00LIST\x00\x00\x00Vtdgptdsb\x00\x00\x00\x04\x00\x00\x00\x01tdsn\x00\x00\x00\x0EUtf8\x00\x00\x00\x06-_0_/-tdmn\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\x00tdmn\x00\x00\x00(ADBE Effect Mask Opacity\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00LIST\x00\x00\x00útdbstdsb\x00\x00\x00\x04\x00\x00\x00\x01tdsn\x00\x00\x00\x0EUtf8\x00\x00\x00\x06-_0_/-tdb4\x00\x00\x00|Û\x00\x01\x00\x01\x00\x00ÿÿÿÿ\x00\x00x\x00?\x1A6âë\x1CC-?ð\x00\x00\x00\x00\x00\x00?ð\x00\x00\x00\x00\x00\x00?ð\x00\x00\x00\x00\x00\x00?ð\x00\x00\x00\x00\x00\x00\x00\x00\x00\b\t\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\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(@Y\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\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@Y\x00\x00\x00\x00\x00\x00tdmn\x00\x00\x00(ADBE Force CPU GPU\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Útdbstdsb\x00\x00\x00\x04\x00\x00\x00\x01tdsn\x00\x00\x00\x0EUtf8\x00\x00\x00\x06-_0_/-tdb4\x00\x00\x00|Û\x00\x01\x00\x01\x00\x00\x00\x02\x00\x04\x00\x00x\x00?\x1A6âë\x1CC-?ð\x00\x00\x00\x00\x00\x00?ð\x00\x00\x00\x00\x00\x00?ð\x00\x00\x00\x00\x00\x00?ð\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\x00tdmn\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\x00tdmn\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\x00pgui\x00\x00\x00\x10\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
    };

    /****************** GUARDS ******************/

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

    var props = composition.selectedProperties;
    if (!props || props.length === 0) {
        alert("Please select at least one property (e.g. Position) to apply the bounce to.");
        return;
    }

    /****************** VARIANT SELECTION (Cmd/Ctrl at launch) ******************/

    var useBounce = false;
    try {
        var kb = ScriptUI.environment.keyboardState;
        if (kb && (kb.metaKey || kb.ctrlKey)) useBounce = true;
    } catch (eKb) { }
    var data = useBounce ? BOUNCE : INERTIAL;

    /****************** HELPERS ******************/

    // Registers the pseudo effect with AE if this project hasn't seen it yet:
    // writes the FFX to the temp folder and applies it once on a throwaway comp.
    // (Technique (c) 2017 Tomas Šinkūnas, rendertom.com)
    function ensurePseudoRegistered(effectsProp, variant) {
        var needed = false;
        try {
            if (effectsProp.canAddProperty && !effectsProp.canAddProperty(variant.matchName)) {
                needed = true;
            }
        } catch (eCan) { }
        if (!needed) return;

        var ffxFile = new File(Folder.temp.fsName + "/" + variant.fileName + ".ffx");
        ffxFile.encoding = "BINARY";
        var opened = ffxFile.open("w");
        var wrote = (opened === false) ? false : ffxFile.write(variant.binary);
        ffxFile.close();
        if (opened === false || wrote === false) {
            throw new Error("Could not write the temporary .ffx preset (" + ffxFile.fsName + "). " +
                "Enable 'Allow Scripts to Write Files and Access Network' in Preferences > Scripting & Expressions and try again.");
        }

        var tempComp = app.project.items.addComp("tempComp", 100, 100, 1, 1, 24);
        var tempLayer = tempComp.layers.addShape();
        tempLayer.applyPreset(ffxFile);
        tempComp.remove();
    }

    // The overshoot is normalised by (freq * 2π) so it LAUNCHES at the property's
    // real arrival velocity — that makes the join at the keyframe velocity-continuous
    // (no dip/stagger where the eased approach hands off to the spring). Amplitude 20
    // (the FFX default) is the neutral point: exactly arrival velocity; higher =
    // snappier/bigger launch, lower = softer/smaller. Dividing by freq keeps that
    // true at any Frequency.
    function buildInertialExpression(ctrlName) {
        return [
            'var freq = effect("' + ctrlName + '")("Frequency");',
            'var amp = effect("' + ctrlName + '")("Amplitude");',
            'var decay = effect("' + ctrlName + '")("Decay");',
            'var decayDuration = effect("' + ctrlName + '")("Duration");',
            'var delay = effect("' + ctrlName + '")("Delay (in frames)");',
            'var extDriver = effect("' + ctrlName + '")("External Driver");',
            'var n = 0;',
            'var aPropDrop = effect("' + ctrlName + '")("External Animated Property");',
            'var aProp;',
            'if (aPropDrop == 1) {',
            '    aProp = "position";',
            '} else if (aPropDrop == 2) {',
            '    aProp = "rotation";',
            '} else if (aPropDrop == 3) {',
            '    aProp = "scale";',
            '} else if (aPropDrop == 4) {',
            '    aProp = "opacity";',
            '} else if (aPropDrop == 5) {',
            '    aProp = "xPosition";',
            '} else if (aPropDrop == 6) {',
            '    aProp = "yPosition";',
            '}',
            '',
            'if (extDriver == 1) {',
            '    var externalLayer = effect("' + ctrlName + '")("External Driver Layer").transform[aProp];',
            '    if (externalLayer.numKeys > 0) {',
            '        n = externalLayer.nearestKey(time).index;',
            '        if (externalLayer.key(n).time > time) {',
            '            n--;',
            '        }',
            '    }',
            '    if (n == 0) {',
            '        t = 0;',
            '    } else {',
            '        t = time - externalLayer.key(n).time;',
            '    }',
            '    if (n > 0 && t < decayDuration) {',
            '        var v = externalLayer.velocityAtTime(externalLayer.key(n).time - framesToTime(delay) - thisComp.frameDuration / 10);',
            '        value + v * (amp / 20) * Math.sin(freq * t * 2 * Math.PI) / Math.exp(decay * t) / (freq * 2 * Math.PI);',
            '    } else {',
            '        value;',
            '    }',
            '} else {',
            '    if (numKeys > 0) {',
            '        n = nearestKey(time).index;',
            '        if (key(n).time > time) {',
            '            n--;',
            '        }',
            '    }',
            '    if (n == 0) {',
            '        t = 0;',
            '    } else {',
            '        t = time - key(n).time;',
            '    }',
            '    if (n > 0 && t < decayDuration) {',
            '        var v = velocityAtTime(key(n).time - thisComp.frameDuration / 10);',
            '        value + v * (amp / 20) * Math.sin(freq * t * 2 * Math.PI) / Math.exp(decay * t) / (freq * 2 * Math.PI);',
            '    } else {',
            '        value;',
            '    }',
            '}'
        ].join('\n');
    }

    function buildBounceExpression(ctrlName) {
        return [
            'var e = effect("' + ctrlName + '")("Elasticity");',
            'var g = effect("' + ctrlName + '")("Gravity");',
            'var nMax = effect("' + ctrlName + '")("Number of bounces");',
            '',
            'n = 0;',
            'if (numKeys > 0){',
            ' n = nearestKey(time).index;',
            ' if (key(n).time > time) n--;',
            '}',
            'if (n > 0){',
            ' t = time - key(n).time;',
            ' v = -velocityAtTime(key(n).time - .001)*e;',
            ' vl = length(v);',
            ' if (value instanceof Array){',
            '   vu = (vl > 0) ? normalize(v) : [0,0,0];',
            '}else{',
            '   vu = (v < 0) ? -1 : 1;',
            ' }',
            ' tCur = 0;',
            ' segDur = 2*vl/g;',
            ' tNext = segDur;',
            ' nb = 1; // number of bounces',
            ' while (tNext < t && nb <= nMax){',
            '   vl *= e;',
            '   segDur *= e;',
            '   tCur = tNext;',
            '   tNext += segDur;',
            '   nb++',
            ' }',
            ' if(nb <= nMax){',
            '   delta = t - tCur;',
            '   value +  vu*delta*(vl - g*delta/2);',
            ' }else{',
            '   value',
            ' }',
            '}else',
            ' value'
        ].join('\n');
    }

    // One controller per layer: reuse an existing controller of this variant if
    // the layer already has one, otherwise register + add it once.
    function getOrAddController(effectsProp, variant, ctrlName) {
        for (var e = 1; e <= effectsProp.numProperties; e++) {
            var ex = effectsProp.property(e);
            try {
                if (ex && ex.name === ctrlName && ex.matchName === variant.matchName) return ex;
            } catch (xReuse) { }
        }
        ensurePseudoRegistered(effectsProp, variant);
        var fx = effectsProp.addProperty(variant.matchName);
        fx.name = ctrlName;
        return fx;
    }

    // The times of a property's selected keyframes when a proper SUBSET is selected
    // (>= 2, but not all); else null (whole timeline). Must be read BEFORE any effect
    // is added — addProperty() changes the timeline selection and would clobber it.
    function selectedKeyTimes(prop) {
        var n = prop.numKeys;
        if (!n || n < 2) return null;
        var sel;
        try { sel = prop.selectedKeys; } catch (eSel) { sel = null; }
        if (!sel || sel.length < 2) return null;   // 0-1 keys selected -> whole timeline
        if (sel.length >= n) return null;          // all keys selected -> whole timeline
        var times = [];
        for (var i = 0; i < sel.length; i++) times.push(prop.keyTime(sel[i]));
        return times;
    }

    // Confine the effect to the SELECTED keyframes: at any time find the key driving
    // the value (the last key at/before now); overshoot only when that key is one of
    // the selected ones, otherwise return the native value so unselected keyframes
    // (and the interpolation after them) are left untouched. null => whole timeline.
    function wrapSelected(core, times) {
        if (!times) return core;
        return [
            'var _sel = [' + times.join(',') + '];',
            'var _dk = (numKeys > 0) ? nearestKey(time).index : 0;',
            'if (_dk > 0 && key(_dk).time > time) _dk--;',
            'var _on = false;',
            'if (_dk > 0) {',
            '    var _kt = key(_dk).time;',
            '    for (var _i = 0; _i < _sel.length; _i++) {',
            '        if (Math.abs(_kt - _sel[_i]) < 0.0005) { _on = true; break; }',
            '    }',
            '}',
            'if (!_on) {',
            '    value;',
            '} else {',
            core,
            '}'
        ].join('\n');
    }

    /****************** MAIN ******************/

    app.beginUndoGroup("Elast-o-matic (" + data.label + ")");
    try {
        var ctrlName = data.label;   // one controller per layer, named after the variant
        var rigged = 0;

        // Rig each layer independently so a copy of the controller lands on every
        // layer that has selected properties — once per layer — instead of piling
        // every property's controller onto the first selected layer.
        for (var L = 1; L <= composition.numLayers; L++) {
            var lyr = composition.layer(L);
            var sel = lyr.selectedProperties;
            if (!sel || sel.length === 0) continue;

            // Only leaf properties that can hold an expression (skip groups like Transform).
            var valueProps = [];
            for (var s = 0; s < sel.length; s++) {
                if (sel[s] && sel[s].canSetExpression) valueProps.push(sel[s]);
            }
            if (valueProps.length === 0) continue;

            var effectsProp = lyr.property("ADBE Effect Parade");

            // Capture each property's selected-key times NOW, before adding the
            // controller — addProperty() reshuffles the timeline selection.
            var selTimesList = [];
            for (var c = 0; c < valueProps.length; c++) {
                selTimesList.push(selectedKeyTimes(valueProps[c]));
            }

            var controller = getOrAddController(effectsProp, data, ctrlName);

            for (var v = 0; v < valueProps.length; v++) {
                try {
                    var prop = valueProps[v];
                    var core = useBounce
                        ? buildBounceExpression(ctrlName)
                        : buildInertialExpression(ctrlName);
                    prop.expression = wrapSelected(core, selTimesList[v]);
                    rigged++;
                } catch (ePer) {
                    alert("Elast-o-matic: could not rig \"" + valueProps[v].name + "\" on \"" +
                        lyr.name + "\":\n" + ePer.toString());
                }
            }
        }

        if (rigged === 0) {
            alert("Elast-o-matic: no keyframeable properties were selected.\n" +
                "Select the property/properties (or some of their keyframes) and run again.");
        }
    } catch (err) {
        alert("Elast-o-matic error: " + err.toString() +
            (err.line ? "  (line " + err.line + ")" : ""));
    } finally {
        app.endUndoGroup();
    }

})();
