{"id":20863204,"url":"https://github.com/mysterypancake/after-effects-fun","last_synced_at":"2026-02-21T05:49:32.409Z","repository":{"id":162571059,"uuid":"298263597","full_name":"MysteryPancake/After-Effects-Fun","owner":"MysteryPancake","description":"Expressions, scripts and projects for Adobe After Effects","archived":false,"fork":false,"pushed_at":"2024-05-28T12:49:39.000Z","size":11164,"stargazers_count":41,"open_issues_count":0,"forks_count":5,"subscribers_count":5,"default_branch":"master","last_synced_at":"2024-05-29T04:24:13.131Z","etag":null,"topics":["adobe","adobe-after-effects","after-effects","fun","html","javascript","js","jsx"],"latest_commit_sha":null,"homepage":"https://mysterypancake.github.io/After-Effects-Fun/","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/MysteryPancake.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2020-09-24T11:53:25.000Z","updated_at":"2024-05-28T12:49:43.000Z","dependencies_parsed_at":"2024-03-09T04:35:25.547Z","dependency_job_id":null,"html_url":"https://github.com/MysteryPancake/After-Effects-Fun","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/MysteryPancake%2FAfter-Effects-Fun","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/MysteryPancake%2FAfter-Effects-Fun/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/MysteryPancake%2FAfter-Effects-Fun/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/MysteryPancake%2FAfter-Effects-Fun/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/MysteryPancake","download_url":"https://codeload.github.com/MysteryPancake/After-Effects-Fun/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":225132839,"owners_count":17425881,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["adobe","adobe-after-effects","after-effects","fun","html","javascript","js","jsx"],"created_at":"2024-11-18T05:28:04.619Z","updated_at":"2026-02-21T05:49:27.375Z","avatar_url":"https://github.com/MysteryPancake.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# After Effects Fun\nExpressions, scripts and projects for Adobe After Effects.\n\nUsually created by myself or others on the [/r/AfterEffects Discord](http://discord.gg/aftereffects).\n\n## Projects\nThese were made using [custom exploits](#break)!\n\n[Playable Pong (JavaScript only)](projects/PONG)\n\n[\u003cimg src=\"images/PongDemo.gif?raw=true\" width=\"320\" alt=\"Pong demo\"\u003e](https://youtu.be/3HMT1M9F5yA)\n\n[Drawing (JavaScript only)](projects/DRAW)\n\n[\u003cimg src=\"images/DrawDemo.gif?raw=true\" width=\"320\" alt=\"Drawing demo\"\u003e](https://youtu.be/XxiwhegTduI)\n\n## Expressions\n\n[Limitless linear](expressions/linear.js)\n\n[\u003cimg src=\"images/LinearDemo.gif?raw=true\" width=\"320\" alt=\"Limitless linear demo\"\u003e](expressions/linear.js)\n\n[Custom easings](expressions/easing2.js)\n\n[\u003cimg src=\"images/EasingDemo.gif?raw=true\" width=\"320\" alt=\"Easings reference\"\u003e](https://youtu.be/6qnkLmMJ2AE)\n[![Easings demo](https://img.youtube.com/vi/jy5WZwaGMhY/mqdefault.jpg)](https://youtu.be/jy5WZwaGMhY)\n\n[Spring easing](expressions/easing4.js)\n\n[\u003cimg src=\"images/SpringDemo.gif?raw=true\" width=\"320\" alt=\"Spring easing demo\"\u003e](expressions/easing4.js)\n\n[Path rotation](expressions/pathRotation.js)\n\n[![Path rotation demo](https://img.youtube.com/vi/_G5AHLrX-jU/mqdefault.jpg)](https://youtu.be/_G5AHLrX-jU)\n\n[Spiral path](expressions/spiralPath.js)\n\n[\u003cimg src=\"images/SpiralDemo.gif?raw=true\" width=\"320\" alt=\"Spiral path demo\"\u003e](expressions/spiralPath.js)\n\n[Camera snapping](expressions/cameraSnap.js)\n\n[![Camera snapping demo](https://img.youtube.com/vi/VJOOgkROCwU/mqdefault.jpg)](https://youtu.be/VJOOgkROCwU)\n\n## Tools\n[Image to expression converter](https://mysterypancake.github.io/After-Effects-Fun/tools/imagetoexpression)\n\n[![Expression converter](https://img.youtube.com/vi/sEwBKQni7kU/mqdefault.jpg)](https://youtu.be/sEwBKQni7kU)\n[![Expression demo](https://img.youtube.com/vi/OfXQXMyMp-U/mqdefault.jpg)](https://youtu.be/OfXQXMyMp-U)\n\n\u003ca name=\"break\"\u003e\u003c/a\u003e\n## Global Variable Exploits\n\n**WARNING: These are all unpredictable to work with!**\n\nTo have fun in After Effects, I often need to store data in memory and share it between expressions.\n\nOften this is considered impossible, but there are several ways to do it:\n\n### 1. Variable Leaking (JavaScript only)\n\nI discovered variable names aren't properly deleted by After Effects:\n```javascript\n// Write a variable named \"leak\"\nvar leak = 5;\n\n// Read all variable names\nObject.keys(this); // [\"leak\"] (among others)\n```\n\nVariable names are shared between all expressions, and remain in memory until After Effects is restarted.\n\n[`Object.keys(this)`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/keys) reads variable names, but not values. Therefore to store values, I put them in the name itself:\n\n```javascript\n// Write a variable named \"leak_5\"\nvar leak_5;\n```\n\n[`eval()`](https://www.w3schools.com/jsref/jsref_eval.asp) allows dynamic variable names:\n\n```javascript\n// Write any variable name you want\nconst name = \"hello\";\neval(`var ${name}`);\n```\n\nTo tell whether a variable is built-in, you can add a prefix:\n\n```javascript\n// Add a \"leak_\" prefix to identify custom variables\nconst data = \"hello\";\neval(`var leak_${data}`);\n```\n\n```javascript\n// Read all variable names\nObject.keys(this); // [\"leak\", \"leak_5\", \"hello\", \"leak_hello\"] (among others)\n```\n\nUsing this concept, you can store multiple types of data in one variable name:\n\n```javascript\n// Write 2 values into a single name\nconst writeX = 5;\nconst writeY = \"hi\";\n\neval(`var leak_${writeX}_${writeY}`);\n```\n\n```javascript\n// Read values by splitting\nconst parts = Object.keys(this).pop().split(\"_\"); // [\"leak\", \"5\", \"hi\"]\n\nconst readX = parseInt(parts[1]); // 5\nconst readY = parts[2]; // \"hi\"\n```\n\nYou can delete variable names like so:\n\n```javascript\n// Delete variable named \"leak_5_hi\"\ndelete leak_5_hi;\n```\n\n[Many characters aren't allowed in variable names](https://www.dummies.com/web-design-development/javascript/naming-javascript-variables/), so [you have to be creative](projects/PONG/PONG.js#L92-L100).\n\n### 2. The Debug Object (JavaScript + ExtendScript)\n\n[@stibinator](https://github.com/stibinator) [told me](https://blob.pureandapplied.com.au/the-global-object-in-after-effects/) about the [debug object `$`](https://helpx.adobe.com/cy_en/after-effects/using/legacy-and-extend-script-engine.html#dollar-object).\n\n`$` is shared between all expressions, and remains in memory until After Effects is restarted.\n\n```javascript\n// Write number\n$.leak = 5;\n\n// Read number\n$.leak; // 5\n```\n\n[`Object.keys`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/keys) works on `$`:\n\n```javascript\n// Read all keys\nObject.keys($); // [{ leak: 5 }] (among others)\n```\n\n`$` allows any type of data to be stored:\n\n```javascript\n// Write complex data\n$.leak2 = [\n    {\n        name: \"Jeff\",\n        age: 20\n    },\n    {\n        name: \"Joe\",\n        age: 1\n    }\n];\n\n// Read complex data\n$.leak2; // [{ name: \"Jeff\", age: 20 }, { name: \"Joe\", age: 1 }]\n```\n\n`$` allows custom keys:\n\n```javascript\n// Write using a custom key\nconst key = \"leak3\";\n$[key] = 123;\n\n// Read using a custom key\n$[key]; // 123\n```\n\n`$` also works in ExtendScript, but `Object.keys` doesn't.\n\n### 3. Environment Variables (ExtendScript only)\n\nI discovered ExtendScript has a method which [sets environment variables](https://extendscript.docsforadobe.dev/extendscript-tools-features/dollar-object.html#setenv):\n```javascript\n$.setenv(key, value);\n```\n\nHowever it only writes string values:\n\n```javascript\n$.setenv(\"leak\", 5);\n$.getenv(\"leak\"); // \"5\"\n```\n\n### Summary\n\n|Exploit|Engine|Get|Set|Capable of storing|\n|:---|:---|:---|:--|:--|\n|Variable leaking|JavaScript|`Object.keys(this)`|```eval(`var ${value}`)```|Strings (excluding special characters)|\n|The debug object|Both|`$.key`|`$.key = value`|Anything|\n|Environment variables|ExtendScript|`$.getenv(key)`|`$.setenv(key, value)`|Strings|\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmysterypancake%2Fafter-effects-fun","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmysterypancake%2Fafter-effects-fun","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmysterypancake%2Fafter-effects-fun/lists"}